提交 1aac5272 authored 作者: pengxiaohui's avatar pengxiaohui

后台接口调试

上级 9ccfdaee
module.exports = { module.exports = {
domain: 'dev.ezijing.com', domain: 'dev.ezijing.com',
url: 'https://live-broadcast2.ezijing.com/api', url: 'https://live-broadcast2.ezijing.com/api',
// url: 'https://test-microservices-live-api.ezijing.com',
// url: 'https://microservices-live-api.ezijing.com',
webpack: { webpack: {
externals: { externals: {
CKEDITOR: 'window.CKEDITOR', CKEDITOR: 'window.CKEDITOR',
...@@ -34,5 +36,6 @@ module.exports = { ...@@ -34,5 +36,6 @@ module.exports = {
ProvidePlugin: {}, ProvidePlugin: {},
others: { others: {
loginUrl: 'https://login2.ezijing.com/auth/login/index' loginUrl: 'https://login2.ezijing.com/auth/login/index'
// loginUrl: 'https://login.ezijing.com/auth/login/index'
} }
} }
...@@ -53,6 +53,21 @@ if ($GLOBAL.isDev === 'development') { ...@@ -53,6 +53,21 @@ if ($GLOBAL.isDev === 'development') {
pathRewrite: { pathRewrite: {
'^/api': '/' '^/api': '/'
} }
},
'/loginApi': {
target: 'https://learn-api2.ezijing.com/api/',
// target: 'https://learn-api.ezijing.com/api/',
selfHandleResponse: false,
secure: false,
changeOrigin: true,
followRedirects: true,
logLevel: 'info',
headers: {
'Referer': $GLOBAL.webConf.url
},
pathRewrite: {
'^/loginApi': '/'
}
} }
}, },
open: true, open: true,
......
import httpRequest from '@/utils/axios'
/**
* 操作日志
*/
export function operateLog(params) {
const logMsg = `操作人:${params.user.nickname},操作人id:${params.user.id},操作:${params.type}`
const data = {
detail: logMsg
}
httpRequest.post('/api/admin/live/v2/system/log/write', data).then(res => {
console.log(res)
}).catch(() => {})
}
/**
* 模糊搜索
*/
export function searchUserList(params) {
return httpRequest.get('/api/common/v1/sso-user/search', { params })
}
/**
* 创建腾讯用户
*/
export function createAccount(data) {
return httpRequest.post('/api/live/admin/v2/tencent/user', data)
}
/**
* 获取腾讯用户列表(分页)
*/
export function getAccountList(params) {
return httpRequest.get('/api/live/admin/v2/tencent/users', { params })
}
/**
* 获取腾讯用户列表(不分页)
*/
export function getAllAccountList() {
return httpRequest.get('/api/live/admin/v2/tencent/user/list')
}
/**
* 更新腾讯用户
*/
export function updateAccount(data) {
return httpRequest.put(`/api/live/admin/v2/tencent/user/${data.userid}/update`, data)
}
/**
* 删除腾讯用户
*/
export function deleteAccount(params) {
return httpRequest.delete(`/api/live/admin/v2/tencent/user/${params.userid}/delete`, params)
}
/**
* 创建会议
*/
export function createMeeting(data) {
return httpRequest.post('/api/live/admin/v2/tencent/meeting', data)
}
/**
* 创建会议
*/
export function updateMeeting(data) {
return httpRequest.put(`/api/live/admin/v2/tencent/meeting/${data.meeting_id}/update`, data)
}
/**
* 获取腾讯会议列表
*/
export function getMeetingList(params) {
return httpRequest.get('/api/live/admin/v2/tencent/meetings', { params })
}
/**
* 获取腾讯会议列表(不分页)
*/
export function getNonpagedMeetingList(params) {
return httpRequest.get('/api/live/admin/v2/tencent/meeting/list-by-day', { params })
}
/**
* 获取腾讯会议详情
*/
export function getMeetingDetails(params) {
return httpRequest.get(`/api/live/admin/v2/tencent/meeting/${params.meeting_id}/detail`, { params })
}
/**
* 通过会议code获取腾讯会议详情
*/
export function getMeetingDetailsByCode(params) {
return httpRequest.get(`/api/live/admin/v2/tencent/meeting/${params.meeting_code}/detail-code`, { params })
}
/**
* 取消(删除)会议
*/
export function cancelMeeting(params) {
return httpRequest.post(`/api/live/admin/v2/tencent/meeting/${params.meeting_id}/cancel`, params)
}
/**
* 终止会议
*/
export function stopMeeting(params) {
return httpRequest.post(`/api/live/admin/v2/tencent/meeting/${params.meeting_id}/dimiss`, params)
}
/**
* 获取回放地址
*/
export function getMeetingRecordAddr(params) {
return httpRequest.post(`/api/live/admin/v2/tencent/meeting/${params.meeting_id}/records/address`, params)
}
/**
* 导出参会人员
*/
export function exportParticipants(params) {
return httpRequest({
url: `/api/admin/live/v2/tencent/meeting/${params.meeting_id}/participants/export`,
method: 'get',
params,
responseType: 'blob'
})
}
import httpRequest from '@/utils/axios'
/**
* 操作日志
*/
export function operateLog(params) {
const logMsg = `操作人:${params.user.nickname},操作人id:${params.user.id},操作:${params.type}`
const data = {
detail: logMsg
}
httpRequest.post('/api/live/admin/v2/system/log/write', data).then(res => {
console.log(res)
}).catch(() => {})
}
/**
* 模糊搜索
*/
export function searchUserList(params) {
return httpRequest.get('/api/live/common/v1/sso-user/search', { params })
}
/**
* 获取当前用户的角色
*/
export function getUserRoles() {
return httpRequest.get('/api/live/admin/v2/user/roles')
}
/**
* 创建角色
*/
export function createRole(data) {
return httpRequest.post('/api/live/admin/v2/role', data)
}
/**
* 更新角色
*/
export function updateRole(params) {
return httpRequest.get(`/api/live/admin/v2/role/${params.role_id}/update`, { params })
}
/**
* 获取角色详情
*/
export function getRoleDetails(params) {
return httpRequest.get(`/api/live/admin/v2/role/${params.role_id}/detail`, { params })
}
/**
* 删除
*/
export function deleteRole(params) {
return httpRequest.get(`/api/live/admin/v2/role/${params.role_id}/delete`, { params })
}
/**
* 获取角色列表
*/
export function getRoles(params) {
return httpRequest.get('/api/live/admin/v2/roles', { params })
}
/**
* 分配角色给用户
*/
export function roleToUser(data) {
return httpRequest.post('/api/live/admin/v2/assign/roles-to-user', data)
}
/**
* 获取角色下的用户列表
*/
export function getUserListUnderRole(params) {
return httpRequest.get(`/api/live/admin/v2/role/${params.role_id}/users`, { params })
}
/**
* 从角色中移除用户
*/
export function romoveUserUnderRole(data) {
return httpRequest.post('/api/live/admin/v2/assign/remove-user-form-role', data)
}
/**
* 获取权限列表
*/
export function getPermissions(params) {
return httpRequest.get('/api/live/admin/v2/permissions', { params })
}
/**
* 分配权限给角色
*/
export function permissionToRole(data) {
return httpRequest.post('/api/live/admin/v2/assign/permission-to-role', data)
}
...@@ -25,9 +25,6 @@ import getDays from './getDays' ...@@ -25,9 +25,6 @@ import getDays from './getDays'
export default { export default {
props: { props: {
defaultDate: { defaultDate: {
validator: (value) => {
return typeof value === 'object' && (value === null || value instanceof Date)
}
}, },
type: { type: {
type: String, type: String,
...@@ -38,8 +35,8 @@ export default { ...@@ -38,8 +35,8 @@ export default {
return { return {
weekList: ['周', '一', '二', '三', '四', '五', '六'], weekList: ['周', '一', '二', '三', '四', '五', '六'],
dayList: [], dayList: [],
activeDate: [],
monthFirstDate: '', monthFirstDate: '',
activeDate: [],
rangeState: { rangeState: {
endDate: null, endDate: null,
selecting: false selecting: false
...@@ -68,6 +65,23 @@ export default { ...@@ -68,6 +65,23 @@ export default {
} }
}, },
watch: { watch: {
type: {
handler: function(nv) {
if (nv) {
this.activeDate = ''
this.rangeState = {
endDate: null,
selecting: false
}
this.rangeStartDate = null
this.rangeEndDate = null
this.rangeDates = []
this.selectFirstDate = null
this.selectLastDate = null
}
},
immediate: true
},
defaultDate: { defaultDate: {
handler: function(nv, ov) { handler: function(nv, ov) {
if (!nv) { if (!nv) {
...@@ -76,8 +90,9 @@ export default { ...@@ -76,8 +90,9 @@ export default {
this.setMonthFirstDate(_date) this.setMonthFirstDate(_date)
} else { } else {
if (Array.isArray(nv)) { if (Array.isArray(nv)) {
const d = nv[0] this.rangeStartDate = nv[0]
this.setMonthFirstDate(d) this.rangeEndDate = nv[1]
this.setMonthFirstDate(nv[0])
} else if (typeof nv === 'object' && this.type === 'date') { } else if (typeof nv === 'object' && this.type === 'date') {
this.setMonthFirstDate(nv) this.setMonthFirstDate(nv)
this.activeDate = nv this.activeDate = nv
......
<template>
<el-dialog :title="`会议号${details.meeting_code ? ':' + details.meeting_code : ''}`" :visible="dialogVisible" width="520" :close-on-click-modal="false" append-to-body center @close="dialogClose">
<el-form class="dialog-meeting-details" label-width="90px" ref="details">
<el-form-item label="会议主题:">
{{details.subject}}
</el-form-item>
<el-form-item label="会议时间:">
{{details.start_time | timeFormat('{y}-{m}-{d} {h}:{i}')}} - {{details.end_time | timeFormat('{h}:{i}')}}GMT+08:00)
</el-form-item>
<el-form-item label="会议链接:">
{{details.join_url}}
</el-form-item>
<el-form-item label="会议号:">
{{details.meeting_code}}
</el-form-item>
<el-form-item label="会议直播:" v-if="details.enable_live === 1">
{{details.live_config.live_addr}}
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="mini" @click="copyText">复制文字</el-button>
<el-button size="mini" @click="copyMeetingLink">复制参会地址</el-button>
<el-button size="mini" v-if="details.enable_live === 1" @click="copyLiveLink">复制直播地址</el-button>
<el-button type="primary" size="mini" @click="joinMeeting">进入会议</el-button>
</span>
</el-dialog>
</template>
<script>
import { dateFormat } from '@/utils/dateAlgs'
export default {
props: {
details: {
type: Object,
default: {}
},
dialogVisible: {
type: Boolean,
default: false
}
},
filters: {
timeFormat(val, fmt) {
fmt = fmt || '{y}年{m}月{d}日'
return dateFormat(val, fmt)
}
},
methods: {
dialogClose() {
this.$emit('update:dialogVisible', false)
},
copyText() {
const text = this.$refs.details.$el.innerText
this.copyFn(text)
},
copyMeetingLink() {
this.copyFn(this.details.join_url)
},
copyLiveLink() {
this.copyFn(this.details.live_config.live_addr)
},
copyFn(val) {
if (!val) return
const dom = document.createElement('textarea')
document.body.appendChild(dom)
dom.value = val
dom.select(); // 选择对象
document.execCommand('Copy');
this.$message({
message: '复制成功!',
type: 'success'
})
document.body.removeChild(dom)
},
joinMeeting() {
window.open(this.details.join_url, '_blank');
}
}
}
</script>
<style scoped>
::v-deep.el-dialog__header{
padding-top:14px;
}
::v-deep.el-dialog__headerbtn{
top:12px;
right:12px;
}
::v-deep.el-dialog__body{
padding:10px 0;
margin:0 20px;
border: 1px solid #DBDBDB;
}
::v-deep.el-dialog__footer{
padding-bottom:16px;
}
::v-deep.el-dialog .el-form-item{
margin:0;
}
</style>
\ No newline at end of file
<template> <template>
<div class="schedule-item" :style="{'min-width': minWidth}"> <div class="schedule-item" :style="{'min-width': minWidth}">
<template v-for="ev in schedule.events" > <template v-for="ev in schedule.events" >
<div :key="ev.startTime.getTime()" class="schedule-event" :style="{ height: getHeight(ev) + 'px', top: getTop(ev) + 'px' }"> <div :key="ev.start_time" class="schedule-event" :style="{ height: getHeight(ev) + 'px', top: getTop(ev) + 'px' }">
<slot name="content" :data="ev"> <slot name="content" :data="ev">
<div class="schedule-ev-inner"> <div class="schedule-ev-inner">
<h5>{{ev.title}}</h5> <h5>{{ev.title}}</h5>
<p>{{ev.startTime | timeFormat}}-{{ev.endTime | timeFormat}}</p> <p>{{ev.start_time | timeFormat}}-{{ev.end_time | timeFormat}}</p>
</div> </div>
</slot> </slot>
<div class="shadow" @click.stop="detailsClick(ev, $event)"></div> <div class="shadow" @click.stop="detailsClick(ev, $event)"></div>
...@@ -81,14 +81,14 @@ export default { ...@@ -81,14 +81,14 @@ export default {
}, },
methods: { methods: {
getTop(ev) { getTop(ev) {
const timeRange = timeTrans(ev.startTime).getTime() - this.startDotTimestamp const timeRange = timeTrans(ev.start_time).getTime() - this.startDotTimestamp
const top = timeRange / ((60 * 1000 * this.options.step) / this.timeLineHeight) const top = timeRange / ((60 * 1000 * this.options.step) / this.timeLineHeight)
ev.top = top + 1 ev.top = top + 1
return top + 1 return top + 1
}, },
getHeight(ev) { getHeight(ev) {
const start = timeTrans(ev.startTime) const start = timeTrans(ev.start_time)
let end = timeTrans(ev.endTime) let end = timeTrans(ev.end_time)
if (!isSameDate(start, end)) { if (!isSameDate(start, end)) {
end = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 24, 0, 0) end = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 24, 0, 0)
} }
...@@ -102,25 +102,28 @@ export default { ...@@ -102,25 +102,28 @@ export default {
return { return {
'schedule-event': true, 'schedule-event': true,
'status-start': ev.status === 1, 'status-start': ev.status === 1,
'status-notstarted': ev.status === 3, 'status-notstarted': ev.status === 0,
small: h < 120 && h >= 40, small: h < 120 && h >= 40,
medium: h >= 120 && h < 200, medium: h >= 120 && h < 200,
large: h >= 200 large: h >= 200
} }
}, },
detailsClick(ev, e) { detailsClick(ev, e) {
const o = { if (!this.options.readonly) {
ev, const o = {
id: this.schedule.id, ev,
x: e.clientX - e.offsetX + 'px', id: this.schedule.id,
y: e.clientY - e.offsetY + 'px', x: e.clientX - e.offsetX + 'px',
width: e.target.clientWidth + 'px', y: e.clientY - e.offsetY + 'px',
height: e.target.clientHeight + 'px' width: e.target.clientWidth + 'px',
height: e.target.clientHeight + 'px'
}
this.$emit('details', o)
} }
this.$emit('details', o)
}, },
newSchedule(dot, e) { newSchedule(dot, e) {
if (!this.options.disabledNew) { if (!this.options.readonly) {
dot.accountId = this.schedule.userid || ''
dot.x = e.clientX - e.offsetX + 'px' dot.x = e.clientX - e.offsetX + 'px'
dot.y = e.clientY - e.offsetY + 'px' dot.y = e.clientY - e.offsetY + 'px'
dot.width = e.target.clientWidth + 'px' dot.width = e.target.clientWidth + 'px'
......
<template> <template>
<div class="schedule"> <div class="schedule">
<div class="multi-schedule-header" ref="scheduleHeader"> <div class="multi-schedule-header" ref="scheduleHeader">
<div v-for="(schedule, idx) in scheduleList" :key="idx" :style="{'min-width': minWidth}">{{schedule.title}}</div> <div v-for="(schedule, idx) in scheduleList" :key="idx" :style="{'min-width': minWidth}">{{schedule.name}}</div>
</div> </div>
<el-scrollbar ref="scheduleScroll" style="height: calc(100% - 50px)"> <el-scrollbar ref="scheduleScroll" style="height: calc(100% - 50px)">
<div class="schedule-container"> <div class="schedule-container">
......
<template>
<el-form label-width="140px">
<el-form-item label="会议主题:">
{{details.subject}}
</el-form-item>
<el-form-item label="会议时间:">
{{details.start_time | dateFormat}} - {{details.end_time | dateFormat('{h}:{i}')}}GMT+08:00)
</el-form-item>
<el-form-item label="会议链接:">
{{details.join_url}}
</el-form-item>
<el-form-item label="会议号:">
{{details.meeting_code}}
</el-form-item>
<el-form-item label="会议直播:" v-if="details.enable_live === 1">
{{details.live_config.live_addr}}
</el-form-item>
<el-form-item label="手机拨号入会:" v-if="false">
<p>+8675536550000,,526430840#(中国大陆)</p>
<p>+85230018898,,526430840#(中国香港)</p>
</el-form-item>
<el-form-item label="根据您的位置拨号:" v-if="false">
<p>+8675536550000(中国大陆)</p>
<p>++85230018898(中国香港)</p>
</el-form-item>
</el-form>
</template>
<script>
import { dateFormat } from '@/utils/dateAlgs'
export default {
props: {
rowData: {},
details: {}
},
computed: {
hasLive() {
return this.rowData.hasLive || false
}
},
filters: {
dateFormat(value, fmt) {
return dateFormat(value, fmt || '{y}年{m}月{d}日 {h}:{i}')
}
}
}
</script>
<style scoped>
::v-deep.el-form-item{
margin:0;
}
</style>
\ No newline at end of file
<template>
<el-form label-width="140px">
<el-form-item label="会议主题:">
{{details.subject}}
</el-form-item>
<el-form-item label="会议时间:">
{{details.start_time | dateFormat}} - {{details.end_time | dateFormat('{h}:{i}')}}GMT+08:00)
</el-form-item>
<el-form-item label="会议号:">
{{details.meeting_code}}
</el-form-item>
<el-form-item label="会议创建者:">
{{rowData.sso_user.nickname}}
</el-form-item>
<el-form-item label="会议主持人:">
<span v-for="(it, index) in details.hosts" :key="it.userid">{{it.username}}{{index > 0 ? '、' : ''}}</span>
</el-form-item>
<el-form-item label="会议管理员:">
<span v-for="(it, index) in details.managers" :key="it.userid">{{it.nickname}}{{index > 0 ? '、' : ''}}</span>
</el-form-item>
<el-form-item label="会议直播主题:" v-if="details.enable_live === 1">
{{details.live_config.live_subject}}
</el-form-item>
<el-form-item label="会议直播简介:" v-if="details.enable_live === 1">
<p style="line-height:26px;padding:7px 10px 7px 0">{{details.live_config.live_summary}}</p>
</el-form-item>
<el-form-item label="参会成员:" v-if="rowData.status === 2">
<el-button type="text" @click="handleExport">导出excel</el-button>
</el-form-item>
<el-form-item label="回放:" v-if="rowData.status === 2">
<el-button type="text" v-if="hasRecord" @click="handleDownload">下载</el-button>
<el-button type="text" v-else disabled>暂无回放</el-button>
</el-form-item>
</el-form>
</template>
<script>
import { dateFormat } from '@/utils/dateAlgs'
import { exportParticipants, getMeetingRecordAddr } from '@api/common'
export default {
props: {
details: {},
rowData: {},
dialogType: {}
},
computed: {
hasRecord() {
if (this.rowData.record_file_ids && Array.isArray(this.rowData.record_file_ids) && this.rowData.record_file_ids.length > 0) {
return true
} else {
return false
}
},
nowFormat() {
const now = Date.now()
const _format = dateFormat(now, '{y}{m}{d}{h}{i}{s}')
const nowStr = now.toString()
return _format + nowStr.substr(10, 12)
}
},
filters: {
dateFormat(value, fmt) {
return dateFormat(value, fmt || '{y}年{m}月{d}日 {h}:{i}')
}
},
methods: {
handleExport() {
const row = this.rowData
const params = {
meeting_id: row.meeting_id
}
if (row.meeting_type === 1) {
params.sub_meeting_id = row.sub_meeting_id
}
exportParticipants(params).then((res) => {
if (res && res.type === 'text/xlsx') {
const url = URL.createObjectURL(res)
// const elink = document.createElement('a')// 创建一个a标签
// elink.download = `参会人员表_${this.nowFormat}.xlsx`;// 设置a标签的下载属性
// elink.style.display = 'none';// 将a标签设置为隐藏
// elink.href = URL.createObjectURL(blob);// 把之前处理好的地址赋给a标签的href
// document.body.appendChild(elink);// 将a标签添加到body中
// elink.click();// 执行a标签的点击方法
// URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
// document.body.removeChild(elink)// 移除a标签
this.funDownload(url, `参会人员表_${this.nowFormat}.xlsx`)
}
})
},
async handleDownload() {
const list = await this.fetchMeetingRecordAddr()
if (list && Array.isArray(list)) {
list.forEach(it => {
if (it.download_address) {
// window.open(it.download_address, '_blank')
this.funDownload(it.download_address, it.download_address)
}
})
}
},
funDownload(fileUrl, fileName) {
const elink = document.createElement('a')// 创建一个a标签
elink.download = fileName;// 设置a标签的下载属性
elink.style.display = 'none';// 将a标签设置为隐藏
elink.href = fileUrl;// 把之前处理好的地址赋给a标签的href
document.body.appendChild(elink);// 将a标签添加到body中
elink.click();// 执行a标签的点击方法
URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
document.body.removeChild(elink)// 移除a标签
},
fetchMeetingRecordAddr() {
const params = {
meeting_id: this.rowData.meeting_id,
record_file_ids: this.rowData.record_file_ids
}
return new Promise((resolve, reject) => {
getMeetingRecordAddr(params).then(res => {
if (res.code === 0 && res.data.files) {
resolve(res.data.files)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
}
}
}
</script>
<style scoped>
::v-deep.el-form-item{
margin:0;
}
</style>
\ No newline at end of file
<template>
<div class="btns">
<template v-if="status === 1">
<el-button type="text" size="small" v-if="operatable" @click="handleJoin">进入会议</el-button>
<el-button type="text" size="small" v-if="operatable && hasLive" @click="handleLive">观看直播</el-button>
<el-button type="text" size="small" v-if="operatable" @click="handleCopy">复制邀请</el-button>
<el-button type="text" size="small" v-if="operatable" @click="handleStop">终止</el-button>
<el-button type="text" size="small" v-if="!operatable" @click="handleDetails">查看</el-button>
</template>
<template v-if="status === 0">
<el-button type="text" size="small" v-if="operatable" @click="handleJoin">进入会议</el-button>
<el-button type="text" size="small" v-if="operatable" @click="handleCopy">复制邀请</el-button>
<el-button type="text" size="small" v-if="operatable" @click="handleUpdate">修改</el-button>
<!-- <el-dropdown v-if="operatable && isCycle">
<span class="dropdown-link">
修改<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click="handleUpdate">修改本次会议</el-dropdown-item>
<el-dropdown-item @click="handleUpdate">修改周期会议</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown> -->
<el-button type="text" size="small" v-if="operatable" @click="handleCancel">取消</el-button>
<el-button type="text" size="small" v-if="!operatable" @click="handleDetails">查看</el-button>
</template>
<template v-if="status === 2">
<el-button type="text" size="small" v-if="operatable" @click="handleRecord">看回放</el-button>
<el-button type="text" size="small" @click="handleDetails">查看</el-button>
<el-button type="text" size="small" v-if="operatable" @click="handleDelete">删除</el-button>
</template>
<el-dialog :title="domicTitle" :visible.sync="dialogVisible" width="520px" center>
<div slot="title" class="dialog-header">
<p class="meeting-status" v-show="dialogType === 'details'">会议{{rowData.status | statusFilter}}</p>
<p class="title">{{domicTitle}}</p>
</div>
<dialog-details :rowData="rowData" :details="details" v-show="dialogType === 'details'" />
<dialog-copy-invite :rowData="rowData" :details="details" v-show="dialogType === 'copy'"/>
<div slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" v-show="dialogType === 'copy'" @click="copyLink">复制</el-button>
<el-button @click="dialogVisible = false" size="mini">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import DialogDetails from './DialogDetails.vue'
import DialogCopyInvite from './DialogCopyInvite'
import { mapGetters } from 'vuex'
import { getMeetingDetails, stopMeeting, cancelMeeting, getMeetingRecordAddr } from '@api/common'
export default {
props: {
rowData: {}
},
data() {
return {
userId: '1234',
roleName: '', // general_admin
dialogVisible: false,
dialogType: 'copy',
details: ''
}
},
computed: {
...mapGetters(['isSuperAdmin', 'user']),
domicTitle() {
let title = ''
switch (this.dialogType) {
case 'copy':
title = '复制邀请'
break
case 'details':
title = '会议详情'
break
}
return title
},
status() {
return this.rowData.status
},
isCycle() {
return this.rowData.meeting_type === 1
},
isMyself() {
return this.rowData.sso_id === this.user.id
},
isGeneralAdmin() {
const admins = this.rowData.manage_ids
let flag = false
for (let i = 0; i < admins.length; i++) {
if (admins[i] === this.user.id) {
flag = true
break
}
}
return flag
},
hasLive() {
return this.rowData.enable_live || false
},
operatable() {
return this.isMyself || this.isSuperAdmin || this.isGeneralAdmin
}
},
filters: {
statusFilter(val) {
let result = ''
switch (val) {
case 0:
result = '未开始'
break
case 1:
result = '进行中'
break
case 2:
result = '已结束'
break
}
return result
}
},
components: { DialogDetails, DialogCopyInvite },
created() {
},
methods: {
handleCopy() {
this.fetchMeetingDetails()
this.dialogVisible = true
this.dialogType = 'copy'
},
handleDetails() {
this.dialogVisible = true
this.dialogType = 'details'
this.fetchMeetingDetails()
},
handleLive() {
window.open(this.live_config.live_addr, '_blank');
},
handleUpdate() {
this.$router.push({ path: '/meeting', query: { type: '2', meeting_id: this.rowData.meeting_id, sub_meeting_id: this.rowData.sub_meeting_id } })
},
handleCancel() {
this.$confirm('此操作将取消这场会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchCancelMeeting('cancel')
}).catch(() => {})
},
handleStop() {
this.$confirm('此操作将终止正在进行中的会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchStopMeeting()
}).catch(() => {})
},
handleDelete() {
this.$confirm('此操作将删除这场会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchCancelMeeting('delete')
}).catch(() => {})
},
handleJoin() {
window.open(this.rowData.join_url, '_blank');
},
copyLink() {
const dom = document.createElement('input')
document.body.appendChild(dom)
dom.value = this.rowData.join_url
dom.select(); // 选择对象
document.execCommand('Copy');
this.$message({
message: '复制成功!',
type: 'success'
})
document.body.removeChild(dom)
},
async handleRecord() {
if (this.rowData.record_file_ids.length === 0) {
this.$message.error('该会议没有回放')
} else {
const list = await this.fetchMeetingRecordAddr()
if (list && Array.isArray(list)) {
if (list.length === 1) {
window.open(list[0].view_address, '_blank')
}
}
}
},
fetchStopMeeting() {
const params = {
meeting_id: this.rowData.meeting_id
}
stopMeeting(params).then(res => {
if (res.code === 0 && res.data.status) {
this.$message.success('会议终止成功')
this.$emit('refresh')
} else {
this.$message.error(res.msg || '会议终止失败')
}
})
},
fetchCancelMeeting(type) {
const params = {
meeting_id: this.rowData.meeting_id
}
const msg = type === 'cancel' ? '会议取消' : '会议删除'
cancelMeeting(params).then(res => {
if (res.code === 0 && res.data.status) {
this.$message.success(msg + '成功')
this.$emit('refresh')
} else {
this.$message.error(res.msg || msg + '失败')
}
})
},
fetchMeetingDetails() {
const row = this.rowData
const params = {
meeting_id: row.meeting_id
}
if (row.meeting_type === 1) {
params.sub_meeting_id = row.sub_meeting_id
}
getMeetingDetails(params).then(res => {
if (res.code === 0 && res.data.id) {
this.details = res.data
}
})
},
fetchMeetingRecordAddr() {
const params = {
meeting_id: this.rowData.meeting_id,
record_file_ids: this.rowData.record_file_ids
}
return new Promise((resolve, reject) => {
getMeetingRecordAddr(params).then(res => {
if (res.code === 0 && res.data.files) {
resolve(res.data.files)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
}
}
}
</script>
<style scoped>
.dropdown-link{
cursor: pointer;
color: #409EFF;
font-size:12px;
}
::v-deep.el-icon-arrow-down {
font-size: 12px;
}
.btns ::v-deep.el-dialog__header{
padding-top:14px;
}
.btns ::v-deep.el-dialog__headerbtn{
top:12px;
right:12px;
}
.btns ::v-deep.el-dialog__body{
padding:10px 0;
margin:0 20px;
border: 1px solid #DBDBDB;
}
.btns ::v-deep.el-dialog__footer{
padding-bottom:16px;
}
.dialog-header .meeting-status{
text-align:left;
}
.dialog-header .title{
font-size:16px;
}
</style>
\ No newline at end of file
...@@ -13,8 +13,11 @@ ...@@ -13,8 +13,11 @@
<i class="el-icon-caret-bottom" /> <i class="el-icon-caret-bottom" />
</div> </div>
<el-dropdown-menu slot="dropdown" class="user-dropdown"> <el-dropdown-menu slot="dropdown" class="user-dropdown">
<el-dropdown-item>
<span>{{user.nickname || ''}}, 你好</span>
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout"> <el-dropdown-item divided @click.native="logout">
<span style="display: block">Log Out</span> <span style="display: block">退出登录</span>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
...@@ -34,10 +37,7 @@ export default { ...@@ -34,10 +37,7 @@ export default {
} }
}, },
computed: { computed: {
...mapGetters(['sidebar']), ...mapGetters(['sidebar', 'user']),
user() {
return this.$store.state.user
},
avatar() { avatar() {
return this.user.avatar || defaultAvatar return this.user.avatar || defaultAvatar
} }
...@@ -51,8 +51,8 @@ export default { ...@@ -51,8 +51,8 @@ export default {
this.$router.push('/meeting') this.$router.push('/meeting')
}, },
async logout() { async logout() {
await this.$store.dispatch('user/logout') await this.$store.dispatch('logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`) this.$router.push(`/${this.$route.fullPath}`)
} }
} }
} }
......
...@@ -19,7 +19,7 @@ export default { ...@@ -19,7 +19,7 @@ export default {
<style scoped> <style scoped>
.app-main { .app-main {
height: calc(100vh - 62px); height: calc(100vh - 52px);
width: 100%; width: 100%;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
......
...@@ -3,16 +3,16 @@ ...@@ -3,16 +3,16 @@
<h5>会议详情</h5> <h5>会议详情</h5>
<p> <p>
<i class="el-icon-tickets"></i> <i class="el-icon-tickets"></i>
<span>{{ev.title}}</span> <span>{{ev.subject}}</span>
</p> </p>
<p> <p>
<i class="el-icon-time"></i> <i class="el-icon-time"></i>
<span v-if="ev.startTime.getDate() === ev.endTime.getDate()">{{ev.startTime | timeFormat('{m}月{d}日')}} {{ev.startTime | timeFormat('周{a}')}} {{ev.startTime | timeFormat}}-{{ev.endTime | timeFormat}}</span> <span v-if="isSameDate">{{ev.start_time | timeFormat('{m}月{d}日')}} {{ev.end_time | timeFormat('周{a}')}} {{ev.start_time | timeFormat}}-{{ev.end_time | timeFormat}}</span>
<span v-else>{{ev.title}}</span> <span v-else>{{ev.start_time | timeFormat('{m}月{d}日 {h}:{i}')}} - {{ev.start_time | timeFormat('{m}月{d}日 {h}:{i}')}}</span>
</p> </p>
<p> <p>
<i class="el-icon-s-custom"></i> <i class="el-icon-s-custom"></i>
<span>{{ev.creator}}</span> <span>{{ev.sso_user.nickname}}</span>
</p> </p>
</div> </div>
</template> </template>
...@@ -35,6 +35,9 @@ export default { ...@@ -35,6 +35,9 @@ export default {
computed: { computed: {
ev() { ev() {
return this.data.ev return this.data.ev
},
isSameDate() {
return dateFormat(this.ev.start_time, '{m}-{d}') === dateFormat(this.ev.end_time, '{m}-{d}')
} }
}, },
created() { created() {
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
<div class="new"> <div class="new">
<h5>新建会议</h5> <h5>新建会议</h5>
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="84px"> <el-form ref="ruleForm" :model="form" :rules="rules" label-width="84px">
<el-form-item label="会议主题" prop="theme"> <el-form-item label="会议主题" prop="subject">
<el-input v-model="form.theme" size="small" /> <el-input v-model="form.subject" size="small" />
</el-form-item> </el-form-item>
<el-form-item label="开始时间" required> <el-form-item label="开始时间" required>
<el-col :span="11"> <el-col :span="11">
...@@ -32,12 +32,12 @@ ...@@ -32,12 +32,12 @@
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="会议直播" style="margin-bottom:12px;"> <el-form-item label="会议直播" style="margin-bottom:12px;">
<el-checkbox v-model="form.isLive" @change="updatePopper">开启会议直播(用于分享给观看直播的用户)</el-checkbox> <el-checkbox v-model="form.enable_live" @change="updatePopper">开启会议直播(用于分享给观看直播的用户)</el-checkbox>
</el-form-item> </el-form-item>
<el-form-item v-if="form.isLive" label="直播主题" :required="form.isLive" prop="liveTheme"> <el-form-item v-if="form.enable_live" label="直播主题" :required="form.enable_live" prop="liveTheme">
<el-input v-model="form.liveTheme" size="small" /> <el-input v-model="form.liveTheme" size="small" />
</el-form-item> </el-form-item>
<el-form-item v-if="form.isLive" label="直播简介" :required="form.isLive" prop="liveDesc"> <el-form-item v-if="form.enable_live" label="直播简介" :required="form.enable_live" prop="liveDesc">
<el-input type="textarea" v-model="form.liveDesc"></el-input> <el-input type="textarea" v-model="form.liveDesc"></el-input>
</el-form-item> </el-form-item>
<el-form-item style="text-align:center;"> <el-form-item style="text-align:center;">
...@@ -45,10 +45,14 @@ ...@@ -45,10 +45,14 @@
<el-button type="primary" @click="submitForm('ruleForm')" size="mini">立即创建</el-button> <el-button type="primary" @click="submitForm('ruleForm')" size="mini">立即创建</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<meeting-success-dialog :dialogVisible.sync="dialogVisible" :details="details"/>
</div> </div>
</template> </template>
<script> <script>
import MeetingSuccessDialog from '@/components/MeetingSuccessDialog/index'
import { timeTrans, dateFormat, getTimestampYMD, getCurHalfHour } from '@/utils/dateAlgs' import { timeTrans, dateFormat, getTimestampYMD, getCurHalfHour } from '@/utils/dateAlgs'
import { createMeeting, operateLog, getMeetingDetails } from '@api/common'
import { mapGetters } from 'vuex'
const DAY_TIMESTAMP = 8.64e7 const DAY_TIMESTAMP = 8.64e7
export default { export default {
props: { props: {
...@@ -67,6 +71,8 @@ export default { ...@@ -67,6 +71,8 @@ export default {
const timestamp = Date.parse(value); const timestamp = Date.parse(value);
if (timestamp < Date.now() - DAY_TIMESTAMP) { if (timestamp < Date.now() - DAY_TIMESTAMP) {
callback(new Error('开始时间必须大于当前时间')); callback(new Error('开始时间必须大于当前时间'));
} else {
callback();
} }
} }
} }
...@@ -76,6 +82,8 @@ export default { ...@@ -76,6 +82,8 @@ export default {
callback(new Error('结束时间必须大于开始时间')); callback(new Error('结束时间必须大于开始时间'));
} else if (this.endTimestamp > this.startTimestamp + DAY_TIMESTAMP) { } else if (this.endTimestamp > this.startTimestamp + DAY_TIMESTAMP) {
callback(new Error('会议时间不能超过24小时')); callback(new Error('会议时间不能超过24小时'));
} else {
callback();
} }
} }
} }
...@@ -91,31 +99,17 @@ export default { ...@@ -91,31 +99,17 @@ export default {
return { return {
timerClear: true, timerClear: true,
form: { form: {
theme: '', subject: '',
startDate: this.date, startDate: this.date,
startTime: getCurHalfHour('start'), startTime: getCurHalfHour('start'),
endDate: this.date, endDate: this.date,
endTime: getCurHalfHour('end'), endTime: getCurHalfHour('end'),
timezone: 'beijing', enable_live: false,
periodic: false, live_subject: '',
repeatRate: 'everyday', live_summary: ''
endType: 'endOneday',
periodicEndDate: '',
periodicTimes: 7,
isSecret: false,
secret: '',
openWaitingRoom: false,
joinAdvance: false,
mute: false,
recordVideo: false,
isLive: false,
liveTheme: '',
liveDesc: '',
isLiveSecret: false,
permitComment: false
}, },
rules: { rules: {
theme: [{ required: true, message: '请填写会议主题', trigger: 'blur' }], subject: [{ required: true, message: '请填写会议主题', trigger: 'blur' }],
startDate: [ startDate: [
{ type: 'date', required: true, message: '请选择开始日期', trigger: 'change' }, { type: 'date', required: true, message: '请选择开始日期', trigger: 'change' },
{ type: 'date', validator: startDateChecked, trigger: 'change' } { type: 'date', validator: startDateChecked, trigger: 'change' }
...@@ -126,8 +120,8 @@ export default { ...@@ -126,8 +120,8 @@ export default {
{ required: true, message: '请选择结束时间', trigger: 'change' }, { required: true, message: '请选择结束时间', trigger: 'change' },
{ validator: endDateChecked, trigger: 'change' } { validator: endDateChecked, trigger: 'change' }
], ],
liveTheme: [{ validator: validateErrMsg }], live_subject: [{ validator: validateErrMsg }],
liveDesc: [{ validator: validateErrMsg }] live_summary: [{ validator: validateErrMsg }]
}, },
startDateOptions: { startDateOptions: {
disabledDate(time) { disabledDate(time) {
...@@ -143,10 +137,13 @@ export default { ...@@ -143,10 +137,13 @@ export default {
start: getCurHalfHour('end'), start: getCurHalfHour('end'),
step: '00:30', step: '00:30',
end: '23:30' end: '23:30'
} },
details: {},
dialogVisible: false
} }
}, },
computed: { computed: {
...mapGetters(['user']),
startTimestamp() { startTimestamp() {
return this.getFullDateTime(this.form.startDate, this.form.startTime).getTime() return this.getFullDateTime(this.form.startDate, this.form.startTime).getTime()
}, },
...@@ -166,6 +163,8 @@ export default { ...@@ -166,6 +163,8 @@ export default {
data: { data: {
handler: function(nv) { handler: function(nv) {
if (nv) { if (nv) {
// console.log(nv)
this.form.subject = ''
this.form.startDate = nv.date this.form.startDate = nv.date
this.startDateChange(nv.date) this.startDateChange(nv.date)
this.form.startTime = nv.time this.form.startTime = nv.time
...@@ -176,6 +175,7 @@ export default { ...@@ -176,6 +175,7 @@ export default {
deep: true deep: true
} }
}, },
components: { MeetingSuccessDialog },
methods: { methods: {
updatePopper() { updatePopper() {
this.$emit('refreshPopover', Date.now()) this.$emit('refreshPopover', Date.now())
...@@ -219,7 +219,6 @@ export default { ...@@ -219,7 +219,6 @@ export default {
} }
}, },
endDateChange() { endDateChange() {
console.log(12344)
this.startTimeChange(this.form.startTime) this.startTimeChange(this.form.startTime)
}, },
getFullDateTime(date, timeStr) { getFullDateTime(date, timeStr) {
...@@ -252,12 +251,66 @@ export default { ...@@ -252,12 +251,66 @@ export default {
submitForm(formName) { submitForm(formName) {
this.$refs[formName].validate((valid) => { this.$refs[formName].validate((valid) => {
if (valid) { if (valid) {
console.log(valid); this.fetchCreateMeeting()
} }
}); });
}, },
more() { more() {
this.$router.push({ path: '/meeting', query: { type: '1' } }) this.$router.push({ path: '/meeting', query: { type: '1', account: this.data.accountId, start: this.startTimestamp, end: this.endTimestamp } })
},
fetchCreateMeeting() {
const form = this.form
const params = {
instanceid: 1,
userid: this.data.accountId,
subject: form.subject,
start_time: dateFormat(this.startTimestamp),
end_time: dateFormat(this.endTimestamp),
meeting_type: 0,
enable_live: form.enable_live,
live_config: {
live_subject: form.live_subject,
live_summary: form.live_summary
},
managers: [this.user.id]
}
const loading = this.$loading({
lock: true,
text: '创建腾讯会议中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
createMeeting(params).then(res => {
loading.close()
if (res.code === 0 && res.data.id) {
operateLog({ type: `创建会议,被创建会议meeting_code:${res.data.meeting_code}`, user: this.user })
this.$message.success('创建腾讯会议成功')
this.fetchMeetingDetails({ meeting_type: form.meeting_type, meeting_id: res.data.meeting_id })
this.$emit('refreshData')
}
})
},
fetchMeetingDetails(obj) {
if (obj.type === 1) {
console.log(111)
} else {
const params = {
meeting_id: obj.meeting_id
}
const loading = this.$loading({
lock: true,
text: '获取腾讯会议详情,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
getMeetingDetails(params).then(res => {
loading.close()
if (res.code === 0 && res.data.id) {
this.details = res.data
this.dialogVisible = true
}
})
}
} }
} }
} }
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
<div :class="getClass(ev)"> <div :class="getClass(ev)">
<div class="status"> <div class="status">
{{ev.status | statusFilter}} {{ev.status | statusFilter}}
<span class="time-range">{{ev.startTime | timeFormat}}-{{ev.endTime | timeFormat}}</span> <span class="time-range">{{ev.start_time | timeFormat}}-{{ev.end_time | timeFormat}}</span>
</div> </div>
<div class="event-cont"> <div class="event-cont">
<div class="title"> <div class="title">
<span>{{ev.title}}</span> <span>{{ev.subject}}</span>
</div> </div>
<div class="creator"> <div class="creator">
<span><i class="el-icon-s-custom"></i>:{{ev.creator}}</span> <span><i class="el-icon-s-custom"></i>:{{ev.sso_user.nickname}}</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -35,7 +35,7 @@ export default { ...@@ -35,7 +35,7 @@ export default {
case 2: case 2:
result = '已完成' result = '已完成'
break break
case 3: case 0:
result = '未开始' result = '未开始'
break break
} }
...@@ -54,7 +54,7 @@ export default { ...@@ -54,7 +54,7 @@ export default {
return { return {
'schedule-ev-inner test': true, 'schedule-ev-inner test': true,
'status-start': ev.status === 1, 'status-start': ev.status === 1,
'status-notstarted': ev.status === 3, 'status-notstarted': ev.status === 0,
small: h < 120 && h >= 40, small: h < 120 && h >= 40,
medium: h >= 120 && h < 200, medium: h >= 120 && h < 200,
large: h >= 200 large: h >= 200
......
<template> <template>
<div class="day"> <div class="day">
<schedule :options="options" :data="scheduleList" :date="defaultDate" @eventClick="edit" @addEvent="add"> <schedule :options="options" :data="scheduleData" :date="defaultDate">
<template slot="content" slot-scope="scope"> <template slot="content" slot-scope="scope">
<schedule-content :ev="scope.data"></schedule-content> <schedule-content :ev="scope.data"></schedule-content>
</template> </template>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<details-popover :data="scope.data"/> <details-popover :data="scope.data"/>
</template> </template>
<template slot="new-schedule" slot-scope="scope"> <template slot="new-schedule" slot-scope="scope">
<new-popover :data="scope.data" :date="defaultDate" @refreshPopover="refreshPop"/> <new-popover :data="scope.data" :date="defaultDate" @refreshPopover="refreshPop" @refreshData="getScheduleData"/>
</template> </template>
</schedule> </schedule>
</div> </div>
...@@ -18,6 +18,9 @@ import Schedule from '@/components/Schedule' ...@@ -18,6 +18,9 @@ import Schedule from '@/components/Schedule'
import ScheduleContent from './components/ScheduleContent' import ScheduleContent from './components/ScheduleContent'
import DetailsPopover from './components/DetailsPopover' import DetailsPopover from './components/DetailsPopover'
import NewPopover from './components/NewPopover' import NewPopover from './components/NewPopover'
import { getAllAccountList, getNonpagedMeetingList } from '@api/common'
import { dateFormat } from '@/utils/dateAlgs'
import { mapGetters } from 'vuex'
export default { export default {
props: { props: {
defaultDate: { defaultDate: {
...@@ -25,6 +28,9 @@ export default { ...@@ -25,6 +28,9 @@ export default {
validator: (value) => { validator: (value) => {
return typeof value === 'object' && (value === null || value instanceof Date) return typeof value === 'object' && (value === null || value instanceof Date)
} }
},
filter: {
type: Object
} }
}, },
data() { data() {
...@@ -45,142 +51,112 @@ export default { ...@@ -45,142 +51,112 @@ export default {
events: [ events: [
{ {
status: 2, status: 2,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会', title: '开个周会',
startTime: new Date(2021, 3, 13, 8, 30, 0), startTime: new Date(2021, 3, 13, 8, 30, 0),
endTime: new Date(2021, 3, 13, 9, 0, 0), endTime: new Date(2021, 3, 13, 9, 0, 0),
creator: '张三丰' creator: '张三丰'
},
{
status: 1,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 11, 0, 0),
endTime: new Date(2021, 3, 13, 13, 0, 0),
creator: '张三丰'
},
{
status: 3,
title: '开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 14, 30, 0),
endTime: new Date(2021, 3, 13, 15, 30, 0),
creator: '张三丰'
} }
] ]
}, },
scheduleList: [ scheduleData: []
{
id: 'live-1',
title: '会议室1',
events: [
{
status: 2,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 8, 30, 0),
endTime: new Date(2021, 3, 13, 9, 0, 0),
creator: '张三丰'
},
{
status: 1,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 11, 0, 0),
endTime: new Date(2021, 3, 13, 13, 0, 0),
creator: '张三丰'
},
{
status: 3,
title: '开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 20, 30, 0),
endTime: new Date(2021, 3, 14, 1, 30, 0),
creator: '张三丰'
}
]
},
{
id: 'live-2',
title: '会议室2',
events: [
{
status: 2,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 9, 30, 0),
endTime: new Date(2021, 3, 13, 10, 0, 0),
creator: '张三丰'
}
]
},
{
id: 'live-3',
title: '会议室3',
events: [
{
status: 3,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 16, 30, 0),
endTime: new Date(2021, 3, 13, 18, 0, 0),
creator: '张三丰'
}
]
},
{
id: 'live-4',
title: '会议室4',
events: [
{
status: 3,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 13, 19, 30, 0),
endTime: new Date(2021, 3, 13, 20, 30, 0),
creator: '张三丰'
}
]
},
{
id: 'live-5',
title: '会议室5',
events: [
{
status: 3,
title: '开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会开个周会',
startTime: new Date(2021, 3, 8, 21, 0, 0),
endTime: new Date(2021, 3, 8, 22, 0, 0),
creator: '张三丰'
}
]
}
],
list: [
{
id: 'live-1',
title: '会议室1',
events: []
},
{
id: 'live-2',
title: '会议室2',
events: []
}
]
} }
}, },
computed: {
...mapGetters(['user'])
},
components: { Schedule, ScheduleContent, DetailsPopover, NewPopover }, components: { Schedule, ScheduleContent, DetailsPopover, NewPopover },
watch: { watch: {
defaultDate: { defaultDate: {
handler: function(nv, ov) { handler: function(nv, ov) {
if (nv) { if (nv) {
// console.log(nv) console.log(nv)
this.getScheduleData()
} }
}, },
immediate: true immediate: true
},
'filter.status': {
handler: function(nv, ov) {
if (nv !== ov) {
this.getScheduleData()
}
},
deep: true
},
'filter.isMine': {
handler: function(nv, ov) {
if (nv !== ov) {
this.getScheduleData()
}
},
deep: true
} }
}, },
methods: { methods: {
refreshPop(val) { refreshPop(val) {
this.options.refreshPopoverState = val this.options.refreshPopoverState = val
}, },
edit(val) { pickMeeingData(aList, mList) {
console.log(val) const data = []
for (let i = 0; i < aList.length; i++) {
const _accont = aList[i]
if (_accont.userid) {
const account = {
userid: _accont.userid,
name: _accont.username,
events: []
}
for (let j = 0; j < mList.length; j++) {
const meeting = mList[j]
if (meeting.userid === _accont.userid) {
account.events.push(meeting)
}
}
data.push(account)
}
}
return data
}, },
add(val) { getScheduleData() {
console.log(val) //
Promise.all([this.fetchAccountList(), this.fetchMeetingList()]).then(res => {
// 组装数据
const scheduleData = this.pickMeeingData(res[0], res[1])
this.scheduleData = scheduleData
}).catch(err => {
console.log(err)
})
},
fetchMeetingList() {
const date = this.defaultDate
const start = dateFormat(date)
const end = dateFormat(new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1))
const params = {
sso_id: this.filter.isMine ? this.user.id : undefined,
status: this.filter.status > 2 ? undefined : this.filter.status,
start_time: start,
end_time: end
}
return new Promise((resolve, reject) => {
getNonpagedMeetingList(params).then((res) => {
if (res.code === 0 && res.data && res.data.list) {
resolve(res.data.list)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
},
fetchAccountList() {
return new Promise((resolve, reject) => {
getAllAccountList().then((res) => {
if (res.code === 0 && res.data.list) {
resolve(res.data.list)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
} }
} }
} }
......
...@@ -9,20 +9,22 @@ ...@@ -9,20 +9,22 @@
<calendar :type="dateType" style="margin-left:-10px;" :defaultDate="defaultDate" @change="calendarChange" /> <calendar :type="dateType" style="margin-left:-10px;" :defaultDate="defaultDate" @change="calendarChange" />
<div class="bottom"> <div class="bottom">
<div class="title"> <div class="title">
直播日历 <el-checkbox style="margin-left:20px;" v-model="mineFilter">我的</el-checkbox> 直播日历 <el-checkbox style="margin-left:20px;" v-model="filter.isMine">我的</el-checkbox>
</div> </div>
<div class="status-filter"> <div class="status-filter">
<el-radio-group v-model="statusFilter"> <el-radio-group v-model="filter.status">
<el-radio :label="3">进行中</el-radio> <el-radio :label="9999">全部</el-radio>
<el-radio :label="6">未开始</el-radio> <el-radio :label="1">进行中</el-radio>
<el-radio :label="9">已完成</el-radio> <el-radio :label="0">未开始</el-radio>
<el-radio :label="2">已完成</el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
</div> </div>
</div> </div>
<div class="right-container"> <div class="right-container">
<div class="top"> <div class="top">
<div class="title">2021年04月</div> <div class="title" v-if="tabActive === 'list'">{{defaultDate[0] | dateFormat}} - {{defaultDate[1] | dateFormat}}</div>
<div class="title" v-if="tabActive === 'day'">{{defaultDate | dateFormat}} {{defaultDate | dateFormat('星期{a}')}} </div>
<el-radio-group v-model="tabActive" size="mini"> <el-radio-group v-model="tabActive" size="mini">
<el-radio-button label="list">列表</el-radio-button> <el-radio-button label="list">列表</el-radio-button>
<el-radio-button label="day"></el-radio-button> <el-radio-button label="day"></el-radio-button>
...@@ -30,8 +32,8 @@ ...@@ -30,8 +32,8 @@
<el-radio-button label="month"></el-radio-button> --> <el-radio-button label="month"></el-radio-button> -->
</el-radio-group> </el-radio-group>
</div> </div>
<list v-if="tabActive === 'list'" /> <list v-if="tabActive === 'list'" :defaultDate="defaultDate" :filter="filter"/>
<day v-if="tabActive === 'day'" :defaultDate="defaultDate"/> <day v-if="tabActive === 'day'" :defaultDate="defaultDate" :filter="filter"/>
</div> </div>
</div> </div>
</div> </div>
...@@ -44,8 +46,10 @@ import { dateFormat } from '@/utils/dateAlgs' ...@@ -44,8 +46,10 @@ import { dateFormat } from '@/utils/dateAlgs'
export default { export default {
data () { data () {
return { return {
mineFilter: false, filter: {
statusFilter: '', isMine: false,
status: 9999
},
tabActive: 'list', tabActive: 'list',
defaultDate: null, defaultDate: null,
dateType: 'date' dateType: 'date'
...@@ -60,22 +64,7 @@ export default { ...@@ -60,22 +64,7 @@ export default {
}, },
filters: { filters: {
dateFormat (value, fmt) { dateFormat (value, fmt) {
return dateFormat(value, fmt) return dateFormat(value, fmt || '{y}年{m}月{d}日')
},
statusFilter(val) {
let result = ''
switch (val) {
case 1:
result = '进行中'
break
case 2:
result = '已完成'
break
case 3:
result = '未开始'
break
}
return result
} }
}, },
watch: { watch: {
...@@ -85,7 +74,7 @@ export default { ...@@ -85,7 +74,7 @@ export default {
this.defaultDate = this.now this.defaultDate = this.now
this.dateType = 'date' this.dateType = 'date'
} else { } else {
this.defaultDate = null this.defaultDate = [this.now, this.now]
this.dateType = 'daterange' this.dateType = 'daterange'
} }
}, },
...@@ -97,17 +86,7 @@ export default { ...@@ -97,17 +86,7 @@ export default {
this.$router.push('/search') this.$router.push('/search')
}, },
calendarChange(val) { calendarChange(val) {
if (this.dateType === 'date') { this.defaultDate = val
this.defaultDate = val
} else {
console.log(val)
}
},
joinMeeting(data) {
console.log(data)
},
pageChange(val) {
console.log(val)
} }
} }
} }
...@@ -144,23 +123,30 @@ h5{ ...@@ -144,23 +123,30 @@ h5{
margin-bottom:10px; margin-bottom:10px;
} }
.status-filter ::v-deep.el-radio:first-child .el-radio__input.is-checked .el-radio__inner{ .status-filter ::v-deep.el-radio:first-child .el-radio__input.is-checked .el-radio__inner{
border-color:#636363;
background:#636363;
}
.status-filter ::v-deep.el-radio:nth-child(2) .el-radio__input.is-checked .el-radio__inner{
border-color:#409eff; border-color:#409eff;
background:#409eff; background:#409eff;
} }
.status-filter ::v-deep.el-radio:last-child .el-radio__input.is-checked .el-radio__inner{ .status-filter ::v-deep.el-radio:nth-child(3) .el-radio__input.is-checked .el-radio__inner{
border-color:#BFBFBF;
background:#BFBFBF;
}
.status-filter ::v-deep.el-radio__input.is-checked .el-radio__inner{
border-color:#52B837; border-color:#52B837;
background:#52B837; background:#52B837;
} }
.status-filter ::v-deep.el-radio__input + .el-radio__label{ .status-filter ::v-deep.el-radio:last-child .el-radio__input.is-checked .el-radio__inner{
color:#52B837; border-color:#BFBFBF;
background:#BFBFBF;
} }
.status-filter ::v-deep.el-radio:first-child .el-radio__input + .el-radio__label{ .status-filter ::v-deep.el-radio:first-child .el-radio__input + .el-radio__label{
color:#636363;
}
.status-filter ::v-deep.el-radio:nth-child(2) .el-radio__input + .el-radio__label{
color:#409eff; color:#409eff;
} }
.status-filter ::v-deep.el-radio:nth-child(3) .el-radio__input + .el-radio__label{
color:#52B837;
}
.status-filter ::v-deep.el-radio:last-child .el-radio__input + .el-radio__label{ .status-filter ::v-deep.el-radio:last-child .el-radio__input + .el-radio__label{
color:#BFBFBF; color:#BFBFBF;
} }
......
<template> <template>
<el-form label-width="140px"> <el-form label-width="140px">
<el-form-item label="会议主题:"> <el-form-item label="会议主题:">
某某某会议主题 {{details.subject}}
</el-form-item> </el-form-item>
<el-form-item label="会议时间:"> <el-form-item label="会议时间:">
2021年11月06日 10:00-11:00(GMT+08:00) {{details.start_time | dateFormat}} - {{details.end_time | dateFormat('{h}:{i}')}}GMT+08:00)
</el-form-item> </el-form-item>
<el-form-item label="会议链接:"> <el-form-item label="会议链接:">
http://meeting.tencent.com/sS42KPDILN {{details.join_url}}
</el-form-item> </el-form-item>
<el-form-item label="会议号:"> <el-form-item label="会议号:">
526 430 840 {{details.meeting_code}}
</el-form-item> </el-form-item>
<el-form-item label="会议直播:" v-if="hasLive"> <el-form-item label="会议直播:" v-if="details.enable_live === 1">
http://meeting.tencent.com/sS42KPDILN {{details.live_config.live_addr}}
</el-form-item> </el-form-item>
<el-form-item label="手机拨号入会:"> <el-form-item label="手机拨号入会:" v-if="false">
<p>+8675536550000,,526430840#(中国大陆)</p> <p>+8675536550000,,526430840#(中国大陆)</p>
<p>+85230018898,,526430840#(中国香港)</p> <p>+85230018898,,526430840#(中国香港)</p>
</el-form-item> </el-form-item>
<el-form-item label="根据您的位置拨号:"> <el-form-item label="根据您的位置拨号:" v-if="false">
<p>+8675536550000(中国大陆)</p> <p>+8675536550000(中国大陆)</p>
<p>++85230018898(中国香港)</p> <p>++85230018898(中国香港)</p>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<script> <script>
import { dateFormat } from '@/utils/dateAlgs'
export default { export default {
props: { props: {
rowData: {} rowData: {},
details: {}
}, },
computed: { computed: {
hasLive() { hasLive() {
return this.rowData.hasLive || false return this.rowData.hasLive || false
} }
},
filters: {
dateFormat(value, fmt) {
return dateFormat(value, fmt || '{y}年{m}月{d}日 {h}:{i}')
}
} }
} }
</script> </script>
......
<template> <template>
<el-form label-width="140px"> <el-form label-width="140px">
<el-form-item label="会议主题:"> <el-form-item label="会议主题:">
某某某会议主题 {{details.subject}}
</el-form-item> </el-form-item>
<el-form-item label="会议时间:"> <el-form-item label="会议时间:">
2021年11月06日 10:00-11:00(GMT+08:00) {{details.start_time | dateFormat}} - {{details.end_time | dateFormat('{h}:{i}')}}GMT+08:00)
</el-form-item> </el-form-item>
<el-form-item label="会议号:"> <el-form-item label="会议号:">
526 430 840 {{details.meeting_code}}
</el-form-item> </el-form-item>
<el-form-item label="会议创建者:"> <el-form-item label="会议创建者:">
张三 {{rowData.sso_user.nickname}}
</el-form-item> </el-form-item>
<el-form-item label="会议主持人:"> <el-form-item label="会议主持人:">
李四 <span v-for="(it, index) in details.hosts" :key="it.userid">{{it.username}}{{index > 0 ? '、' : ''}}</span>
</el-form-item> </el-form-item>
<el-form-item label="会议主持人:"> <el-form-item label="会议管理员:">
王五、赵⑥ <span v-for="(it, index) in details.managers" :key="it.userid">{{it.nickname}}{{index > 0 ? '、' : ''}}</span>
</el-form-item> </el-form-item>
<el-form-item label="会议直播主题:"> <el-form-item label="会议直播主题:" v-if="details.enable_live === 1">
随便写点啥 {{details.live_config.live_subject}}
</el-form-item> </el-form-item>
<el-form-item label="会议直播简介:"> <el-form-item label="会议直播简介:" v-if="details.enable_live === 1">
<p style="line-height:26px;padding:7px 10px 7px 0">随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥随便写点啥</p> <p style="line-height:26px;padding:7px 10px 7px 0">{{details.live_config.live_summary}}</p>
</el-form-item> </el-form-item>
<el-form-item label="参会成员:"> <el-form-item label="参会成员:" v-if="rowData.status === 2">
<el-button type="text">导出excel</el-button> <el-button type="text" @click="handleExport">导出excel</el-button>
</el-form-item> </el-form-item>
<el-form-item label="回放:"> <el-form-item label="回放:" v-if="rowData.status === 2">
<el-button type="text">下载</el-button> <el-button type="text" v-if="hasRecord" @click="handleDownload">下载</el-button>
<el-button type="text" v-else disabled>暂无回放</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<script> <script>
import { dateFormat } from '@/utils/dateAlgs'
import { exportParticipants, getMeetingRecordAddr } from '@api/common'
export default { export default {
props: { props: {
details: {},
rowData: {}, rowData: {},
dialogType: {} dialogType: {}
}, },
computed: { computed: {
hasLive() { hasRecord() {
return this.rowData.hasLive || false if (this.rowData.record_file_ids && Array.isArray(this.rowData.record_file_ids) && this.rowData.record_file_ids.length > 0) {
return true
} else {
return false
}
},
nowFormat() {
const now = Date.now()
const _format = dateFormat(now, '{y}{m}{d}{h}{i}{s}')
const nowStr = now.toString()
return _format + nowStr.substr(10, 12)
}
},
filters: {
dateFormat(value, fmt) {
return dateFormat(value, fmt || '{y}年{m}月{d}日 {h}:{i}')
}
},
methods: {
handleExport() {
const row = this.rowData
const params = {
meeting_id: row.meeting_id
}
if (row.meeting_type === 1) {
params.sub_meeting_id = row.sub_meeting_id
}
exportParticipants(params).then((res) => {
if (res && res.type === 'text/xlsx') {
const url = URL.createObjectURL(res)
// const elink = document.createElement('a')// 创建一个a标签
// elink.download = `参会人员表_${this.nowFormat}.xlsx`;// 设置a标签的下载属性
// elink.style.display = 'none';// 将a标签设置为隐藏
// elink.href = URL.createObjectURL(blob);// 把之前处理好的地址赋给a标签的href
// document.body.appendChild(elink);// 将a标签添加到body中
// elink.click();// 执行a标签的点击方法
// URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
// document.body.removeChild(elink)// 移除a标签
this.funDownload(url, `参会人员表_${this.nowFormat}.xlsx`)
}
})
},
async handleDownload() {
const list = await this.fetchMeetingRecordAddr()
if (list && Array.isArray(list)) {
list.forEach(it => {
if (it.download_address) {
// window.open(it.download_address, '_blank')
this.funDownload(it.download_address, it.download_address)
}
})
}
},
funDownload(fileUrl, fileName) {
const elink = document.createElement('a')// 创建一个a标签
elink.download = fileName;// 设置a标签的下载属性
elink.style.display = 'none';// 将a标签设置为隐藏
elink.href = fileUrl;// 把之前处理好的地址赋给a标签的href
document.body.appendChild(elink);// 将a标签添加到body中
elink.click();// 执行a标签的点击方法
URL.revokeObjectURL(elink.href) // 下载完成释放URL 对象
document.body.removeChild(elink)// 移除a标签
},
fetchMeetingRecordAddr() {
const params = {
meeting_id: this.rowData.meeting_id,
record_file_ids: this.rowData.record_file_ids
}
return new Promise((resolve, reject) => {
getMeetingRecordAddr(params).then(res => {
if (res.code === 0 && res.data.files) {
resolve(res.data.files)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
} }
} }
} }
......
<template> <template>
<div class="btns"> <div class="btns">
<template v-if="status === 1"> <template v-if="status === 1">
<el-button type="text" size="small" v-if="operatable">进入会议</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleJoin">进入会议</el-button>
<el-button type="text" size="small" v-if="operatable && hasLive">观看直播</el-button> <el-button type="text" size="small" v-if="operatable && hasLive" @click="handleLive">观看直播</el-button>
<el-button type="text" size="small" v-if="operatable" @click="dialogVisible = 'copy'">复制邀请</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleCopy">复制邀请</el-button>
<el-button type="text" size="small" v-if="operatable">终止</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleStop">终止</el-button>
<el-button type="text" size="small" v-if="!operatable" @click="dialogVisible = 'details'">查看</el-button> <el-button type="text" size="small" v-if="!operatable" @click="handleDetails">查看</el-button>
</template> </template>
<template v-if="status === 2"> <template v-if="status === 0">
<el-button type="text" size="small" v-if="operatable">进入会议</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleJoin">进入会议</el-button>
<el-button type="text" size="small" v-if="operatable">复制邀请</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleCopy">复制邀请</el-button>
<el-button type="text" size="small" v-if="operatable && !isCycle">修改</el-button> <el-button type="text" size="small" v-if="operatable && !isCycle">修改</el-button>
<el-dropdown v-if="operatable && isCycle"> <el-dropdown v-if="operatable && isCycle">
<span class="dropdown-link"> <span class="dropdown-link">
...@@ -20,23 +20,23 @@ ...@@ -20,23 +20,23 @@
<el-dropdown-item>修改周期会议</el-dropdown-item> <el-dropdown-item>修改周期会议</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<el-button type="text" size="small" v-if="operatable">取消</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleCancel">取消</el-button>
<el-button type="text" size="small" v-if="!operatable" @click="dialogVisible = 'details'">查看</el-button> <el-button type="text" size="small" v-if="!operatable" @click="handleDetails">查看</el-button>
</template> </template>
<template v-if="status === 3"> <template v-if="status === 2">
<el-button type="text" size="small" v-if="operatable">看回放</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleRecord">看回放</el-button>
<el-button type="text" size="small" @click="dialogVisible = 'details'">查看</el-button> <el-button type="text" size="small" @click="handleDetails">查看</el-button>
<el-button type="text" size="small" v-if="operatable">删除</el-button> <el-button type="text" size="small" v-if="operatable" @click="handleDelete">删除</el-button>
</template> </template>
<el-dialog :title="domicTitle" :visible.sync="dialogVisible" width="520px" center> <el-dialog :title="domicTitle" :visible.sync="dialogVisible" width="520px" center>
<div slot="title" class="dialog-header"> <div slot="title" class="dialog-header">
<p class="meeting-status" v-show="dialogVisible === 'details'">会议进行中</p> <p class="meeting-status" v-show="dialogType === 'details'">会议{{rowData.status | statusFilter}}</p>
<p class="title">{{domicTitle}}</p> <p class="title">{{domicTitle}}</p>
</div> </div>
<dialog-details :rowData="rowData" :dialogType="dialogVisible" v-show="dialogVisible === 'details'" /> <dialog-details :rowData="rowData" :details="details" v-show="dialogType === 'details'" />
<dialog-copy-invite :rowData="rowData" v-show="dialogVisible === 'copy'"/> <dialog-copy-invite :rowData="rowData" :details="details" v-show="dialogType === 'copy'"/>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" v-show="dialogVisible === 'copy'">复制</el-button> <el-button type="primary" size="mini" v-show="dialogType === 'copy'" @click="copyLink">复制</el-button>
<el-button @click="dialogVisible = false" size="mini">取 消</el-button> <el-button @click="dialogVisible = false" size="mini">取 消</el-button>
</div> </div>
</el-dialog> </el-dialog>
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
<script> <script>
import DialogDetails from './DialogDetails.vue' import DialogDetails from './DialogDetails.vue'
import DialogCopyInvite from './DialogCopyInvite' import DialogCopyInvite from './DialogCopyInvite'
import { mapGetters } from 'vuex'
import { getMeetingDetails, stopMeeting, cancelMeeting, getMeetingRecordAddr } from '@api/common'
export default { export default {
props: { props: {
rowData: {} rowData: {}
...@@ -53,13 +55,16 @@ export default { ...@@ -53,13 +55,16 @@ export default {
return { return {
userId: '1234', userId: '1234',
roleName: '', // general_admin roleName: '', // general_admin
dialogVisible: false dialogVisible: false,
dialogType: 'copy',
details: ''
} }
}, },
computed: { computed: {
...mapGetters(['isSuperAdmin', 'user']),
domicTitle() { domicTitle() {
let title = '' let title = ''
switch (this.dialogVisible) { switch (this.dialogType) {
case 'copy': case 'copy':
title = '复制邀请' title = '复制邀请'
break break
...@@ -73,19 +78,16 @@ export default { ...@@ -73,19 +78,16 @@ export default {
return this.rowData.status return this.rowData.status
}, },
isCycle() { isCycle() {
return this.rowData.isCycle return this.rowData.meeting_type === 1
}, },
isMyself() { isMyself() {
return this.rowData.creatorId === this.userId return this.rowData.sso_id === this.user.id
},
isSuperAdmin() {
return this.roleName === 'administrator'
}, },
isGeneralAdmin() { isGeneralAdmin() {
const admins = this.rowData.general_admin const admins = this.rowData.manage_ids
let flag = false let flag = false
for (let i = 0; i < admins.length; i++) { for (let i = 0; i < admins.length; i++) {
if (admins[i].userId === this.userId) { if (admins[i] === this.user.id) {
flag = true flag = true
break break
} }
...@@ -93,14 +95,153 @@ export default { ...@@ -93,14 +95,153 @@ export default {
return flag return flag
}, },
hasLive() { hasLive() {
return this.rowData.hasLive || false return this.rowData.enable_live || false
}, },
operatable() { operatable() {
return this.isMyself || this.isSuperAdmin || this.isGeneralAdmin return this.isMyself || this.isSuperAdmin || this.isGeneralAdmin
} }
}, },
filters: {
statusFilter(val) {
let result = ''
switch (val) {
case 0:
result = '未开始'
break
case 1:
result = '进行中'
break
case 2:
result = '已结束'
break
}
return result
}
},
components: { DialogDetails, DialogCopyInvite }, components: { DialogDetails, DialogCopyInvite },
created() { created() {
},
methods: {
handleCopy() {
this.fetchMeetingDetails()
this.dialogVisible = true
this.dialogType = 'copy'
},
handleDetails() {
this.dialogVisible = true
this.dialogType = 'details'
this.fetchMeetingDetails()
},
handleLive() {
window.open(this.live_config.live_addr, '_blank');
},
handleCancel() {
this.$confirm('此操作将取消这场会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchCancelMeeting('cancel')
}).catch(() => {})
},
handleStop() {
this.$confirm('此操作将终止正在进行中的会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchStopMeeting()
}).catch(() => {})
},
handleDelete() {
this.$confirm('此操作将删除这场会议, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {
this.fetchCancelMeeting('delete')
}).catch(() => {})
},
handleJoin() {
window.open(this.rowData.join_url, '_blank');
},
copyLink() {
const dom = document.createElement('input')
document.body.appendChild(dom)
dom.value = this.rowData.join_url
dom.select(); // 选择对象
document.execCommand('Copy');
this.$message({
message: '复制成功!',
type: 'success'
})
document.body.removeChild(dom)
},
async handleRecord() {
if (this.rowData.record_file_ids.length === 0) {
this.$message.error('该会议没有回放')
} else {
const list = await this.fetchMeetingRecordAddr()
if (list && Array.isArray(list)) {
if (list.length === 1) {
window.open(list[0].view_address, '_blank')
}
}
}
},
fetchStopMeeting() {
const params = {
meeting_id: this.rowData.meeting_id
}
stopMeeting(params).then(res => {
if (res.code === 0 && res.data.status) {
this.$message.success('会议终止成功')
this.$emit('refresh')
} else {
this.$message.error(res.msg || '会议终止失败')
}
})
},
fetchCancelMeeting(type) {
const params = {
meeting_id: this.rowData.meeting_id
}
const msg = type === 'cancel' ? '会议取消' : '会议删除'
cancelMeeting(params).then(res => {
if (res.code === 0 && res.data.status) {
this.$message.success(msg + '成功')
this.$emit('refresh')
} else {
this.$message.error(res.msg || msg + '失败')
}
})
},
fetchMeetingDetails() {
const row = this.rowData
const params = {
meeting_id: row.meeting_id
}
if (row.meeting_type === 1) {
params.sub_meeting_id = row.sub_meeting_id
}
getMeetingDetails(params).then(res => {
if (res.code === 0 && res.data.id) {
this.details = res.data
}
})
},
fetchMeetingRecordAddr() {
const params = {
meeting_id: this.rowData.meeting_id,
record_file_ids: this.rowData.record_file_ids
}
return new Promise((resolve, reject) => {
getMeetingRecordAddr(params).then(res => {
if (res.code === 0 && res.data.files) {
resolve(res.data.files)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
}
} }
} }
</script> </script>
......
...@@ -3,26 +3,35 @@ ...@@ -3,26 +3,35 @@
<el-table :data="listData" style="width: 100%" height="calc(100% - 32px)"> <el-table :data="listData" style="width: 100%" height="calc(100% - 32px)">
<el-table-column label="会议时间" min-width="160"> <el-table-column label="会议时间" min-width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<p style="color:#AEAEAE;"> <p style="color: #aeaeae">
<span style="font-size:18px;color:#606266;">{{ scope.row.date | dateFormat('{d}')}}</span> <span style="font-size: 18px; color: #606266">{{ scope.row.start_time | dateFormat('{d}') }}</span>
{{ scope.row.date | dateFormat('{m}月')}} {{ scope.row.date | dateFormat('周{a}')}} {{ scope.row.start_time | dateFormat('{m}月') }} {{ scope.row.start_time | dateFormat('周{a}') }}
<span style="font-size:16px;color:#606266;">{{ scope.row.date | dateFormat('{h}:{i}')}}</span> <span style="font-size: 16px; color: #606266">{{ scope.row.start_time | dateFormat('{h}:{i}') }}</span>
</p> </p>
<p style="color:#AEAEAE;"> <p style="color: #aeaeae">
<span style="font-size:18px;color:#606266;">{{ scope.row.endDate | dateFormat('{d}')}}</span> <span style="font-size: 18px; color: #606266">{{ scope.row.end_time | dateFormat('{d}') }}</span>
{{ scope.row.endDate | dateFormat('{m}月')}} {{ scope.row.endDate | dateFormat('周{a}')}} {{ scope.row.end_time | dateFormat('{m}月') }} {{ scope.row.end_time | dateFormat('周{a}') }}
<span style="font-size:16px;color:#606266;">{{ scope.row.endDate | dateFormat('{h}:{i}')}}</span> <span style="font-size: 16px; color: #606266">{{ scope.row.end_time | dateFormat('{h}:{i}') }}</span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="会议主题" min-width="180"> <el-table-column label="会议主题" min-width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-popover trigger="hover" placement="top" width="240"> <el-popover trigger="hover" placement="top" width="240">
<p>{{ scope.row.title }}</p> <p>{{ scope.row.subject }}</p>
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<p style="display:flex;"> <p style="display: flex">
<span style="flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;">{{ scope.row.title }}</span> <span
<span v-if="scope.row.isCycle" style="color:#409DFF;width:40px;">(周期)</span> style="
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
"
>{{ scope.row.subject }}</span
>
<span v-if="scope.row.meeting_type === 1" style="color: #409dff; width: 40px">(周期)</span>
</p> </p>
</div> </div>
</el-popover> </el-popover>
...@@ -31,204 +40,152 @@ ...@@ -31,204 +40,152 @@
<!-- <el-table-column prop="resource" label="会议来源" width="80"></el-table-column> --> <!-- <el-table-column prop="resource" label="会议来源" width="80"></el-table-column> -->
<el-table-column prop="resource" label="会议状态" width="80"> <el-table-column prop="resource" label="会议状态" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<p :class="{'status-start': scope.row.status === 1, 'status-notstarted': scope.row.status === 2, 'status-end': scope.row.status === 3}"> <p
:class="{
'status-start': scope.row.status === 1,
'status-notstarted': scope.row.status === 0,
'status-end': scope.row.status === 2
}"
>
<i></i> <i></i>
<span style="margin-left: 10px">{{ scope.row.status | statusFilter}}</span> <span style="margin-left: 10px">{{ scope.row.status | statusFilter }}</span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="creator" label="创建人" width="80"></el-table-column> <el-table-column prop="sso_user.nickname" label="创建人" min-width="100"></el-table-column>
<el-table-column label="操作" min-width="240"> <el-table-column label="操作" width="220">
<template slot-scope="scope"> <template slot-scope="scope">
<table-handles :rowData="scope.row"/> <table-handles :rowData="scope.row" @refresh="fetchMeetingList"/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-pagination :current-page.sync="curPage" :page-size="pageSize" layout="total, prev, pager, next" :total="total" @current-change="pageChange" style="float:right;"></el-pagination> <el-pagination
:current-page.sync="curPage"
:page-size="pageSize"
layout="total, prev, pager, next"
:total="total"
@current-change="pageChange"
style="float: right"
></el-pagination>
</div> </div>
</template> </template>
<script> <script>
import { dateFormat } from '@/utils/dateAlgs' import { dateFormat } from '@/utils/dateAlgs'
import TableHandles from './components/TableHandles.vue' import TableHandles from '@/components/TableHandles/index.vue'
import { getMeetingList } from '@api/common'
import { mapGetters } from 'vuex'
export default { export default {
props: {
defaultDate: {
type: [Array, Object]
},
filter: {
type: Object
}
},
data() { data() {
return { return {
listData: [ listData: [],
{ dateRange: [],
date: new Date(2021, 3, 7, 10, 30, 0).getTime(),
endDate: new Date(2021, 3, 8, 8, 0, 0).getTime(),
title: 'CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课',
isCycle: false,
resource: '腾讯',
status: 1,
creator: '张三丰',
creatorId: '3211',
hasLive: true,
general_admin: [
{
userId: '1234'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 3, 7, 10, 30, 0).getTime(),
endDate: new Date(2021, 3, 8, 8, 0, 0).getTime(),
title: 'CIIS直播课CII课',
isCycle: false,
resource: '腾讯',
status: 1,
creator: '张三三',
creatorId: '3211',
hasLive: true,
general_admin: [
{
userId: '2222'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 3, 7, 10, 30, 0).getTime(),
endDate: new Date(2021, 3, 8, 8, 0, 0).getTime(),
title: 'CIIS直播课CII课',
isCycle: false,
resource: '腾讯',
status: 1,
creator: '张三多',
creatorId: '1234',
hasLive: false,
general_admin: [
{
userId: '2222'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播',
isCycle: true,
resource: '腾讯',
status: 2,
creator: '黄飞鸿',
hasLive: false,
general_admin: [
{
userId: '1111'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播',
isCycle: true,
resource: '腾讯',
status: 2,
creator: '黄飞鸿',
general_admin: [
{
userId: '1234'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播',
isCycle: false,
resource: '腾讯',
status: 3,
creator: '楚留香',
general_admin: [
{
userId: '1234'
},
{
userId: '1342'
}
]
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播',
isCycle: false,
resource: '腾讯',
status: 3,
creator: '楚留香',
general_admin: [
{
userId: '3421'
},
{
userId: '1342'
}
]
}
],
curPage: 1, curPage: 1,
pageSize: 20, pageSize: 20,
total: 200 total: 0
} }
}, },
computed: {
...mapGetters(['user'])
},
filters: { filters: {
dateFormat (value, fmt) { dateFormat(value, fmt) {
return dateFormat(value, fmt) return dateFormat(value, fmt)
}, },
statusFilter(val) { statusFilter(val) {
let result = '' let result = ''
switch (val) { switch (val) {
case 0:
result = '未开始'
break
case 1: case 1:
result = '进行中' result = '进行中'
break break
case 2: case 2:
result = '未开始' result = '已结束'
break
case 3:
result = '已完成'
break break
} }
return result return result
} }
}, },
components: { TableHandles }, components: { TableHandles },
watch: {
defaultDate: {
handler: function(nv, ov) {
if (nv) {
this.dateRange = nv
this.fetchMeetingList()
}
},
immediate: true,
deep: true
},
'filter.status': {
handler: function(nv, ov) {
if (nv !== ov) {
this.fetchMeetingList()
}
},
deep: true
},
'filter.isMine': {
handler: function(nv, ov) {
console.log(nv)
if (nv !== ov) {
this.fetchMeetingList()
}
},
deep: true
}
},
created() {
// this.fetchMeetingList()
},
methods: { methods: {
joinMeeting(data) { pageChange() {
console.log(data) this.fetchMeetingList()
}, },
pageChange(val) { fetchMeetingList() {
console.log(val) const start = dateFormat(this.dateRange[0])
const end = this.dateRange[1]
const endPlus1 = dateFormat(new Date(end.getFullYear(), end.getMonth(), end.getDate() + 1))
const params = {
page: this.curPage,
limit: this.pageSize,
sso_id: this.filter.isMine ? this.user.id : undefined,
status: this.filter.status > 2 ? undefined : this.filter.status,
start_time: start,
end_time: endPlus1
}
getMeetingList(params).then((res) => {
if (res.code === 0 && res.data.data) {
this.listData = res.data.data
this.total = res.data.total
}
})
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.list{ .list {
padding: 5px 5px 0 10px; padding: 5px 5px 0 10px;
height:calc(100% - 40px); height: calc(100% - 40px);
} }
.status-start{ .status-start {
color:#409eff; color: #409eff;
} }
.status-notstarted{ .status-notstarted {
color:#52B837; color: #52b837;
} }
.status-end{ .status-end {
color:#BFBFBF; color: #bfbfbf;
} }
</style> </style>
\ No newline at end of file
<template>
<div class="create-meeting">
<el-radio-group v-model="tabActive" size="mini" style="margin:14px 0 10px 40px;">
<el-radio-button label="tx">腾讯</el-radio-button>
<el-radio-button label="cc">cc</el-radio-button>
<!-- <el-radio-button label="week"></el-radio-button>
<el-radio-button label="month"></el-radio-button> -->
</el-radio-group>
<tencent-meeting-test />
</div>
</template>
<script>
import TencentMeetingTest from './tencent-meeting-test/index.vue'
export default {
data() {
return {
tabActive: 'tx'
}
},
components: { TencentMeetingTest }
}
</script>
<style scope>
.create-meeting{
height:100%;
}
</style>
\ No newline at end of file
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
</div> </div>
</template> </template>
<script> <script>
import TencentMeeting from './components/tencentMeeting.vue' import TencentMeeting from './tencent-meeting/index.vue'
export default { export default {
data() { data() {
return { return {
......
<template>
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="120px">
<!-- <el-form-item label="会议选择" prop="meetingType">
<el-radio-group v-model="form.meetingType">
<el-radio label="tencent">腾讯</el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item label="会议主题" prop="subject">
<el-input v-model="form.subject" size="small" />
</el-form-item>
<el-form-item label="开始时间" required>
<el-col :span="11">
<el-form-item prop="startDate">
<el-date-picker
v-model="form.startDate"
type="date"
placeholder="选择日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="startDateOptions"
@change="startDateChange"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="line">-</el-col>
<el-col :span="11">
<el-form-item prop="startTime">
<el-time-select
v-model="form.startTime"
style="width: 100%"
:picker-options="startTimeOptions"
placeholder="选择时间"
size="small"
:clearable="timerClear"
:editable="timerClear"
@change="startTimeChange"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="结束时间" required>
<el-col :span="11">
<el-form-item prop="endDate">
<el-date-picker
v-model="form.endDate"
type="date"
placeholder="选择日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="endDateOptions"
@change="endDateChange"
/>
</el-form-item>
</el-col>
<el-col :span="2" class="line">-</el-col>
<el-col :span="11">
<el-form-item prop="endTime">
<el-time-select
v-model="form.endTime"
style="width: 100%"
:picker-options="endTimeOptions"
placeholder="选择时间"
size="small"
:clearable="timerClear"
:editable="timerClear"
/>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="时区" required>
<el-col :span="11">
<el-select style="width: 100%" v-model="form.timezone" placeholder="选择时区" size="small">
<el-option label="(GMT+8:00)中国标准时间-北京" value="beijing" />
</el-select>
</el-col>
</el-form-item>
<el-form-item label="周期会议">
<el-switch v-model="form.meeting_type" :active-value="1" :inactive-value="0" />
</el-form-item>
<el-form-item label="重复频率" v-if="form.meeting_type" required>
<el-col :span="11">
<el-select
style="width: 100%"
v-model="form.recurring_type"
placeholder="选择重复频率"
size="small"
@change="repaeatRateChange"
>
<el-option label="每天" :value="0" />
<el-option label="每个工作日" :value="1" />
<el-option label="每周" :value="2" />
<el-option label="每两周" :value="3" />
<el-option label="每月" :value="4" />
</el-select>
</el-col>
</el-form-item>
<el-form-item label="结束重复" v-if="form.meeting_type" required>
<el-col :span="11">
<el-select style="width: 100%" v-model="form.until_type" placeholder="选择时区" size="small">
<el-option label="结束于某天" :value="0" />
<el-option label="限制会议次数" :value="1" />
</el-select>
</el-col>
<el-col :span="2" class="line">-</el-col>
<el-col :span="11">
<el-date-picker
v-if="form.until_type === 0"
v-model="getCycleMeetingEndDate"
type="date"
placeholder="选择结束日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="untilDateOptions"
/>
<el-input-number v-else v-model="form.until_count" :min="1" :max="50" size="small"></el-input-number>
</el-col>
</el-form-item>
<!-- <el-form-item label="指定主持人">
<el-col :span="11">
<el-select style="width:100%" v-model="form.moderator" placeholder="选择主持人" size="small">
<el-option :label="user.username" :value="user.id" v-for="user in userList" :key="user.id" />
</el-select>
</el-col>
</el-form-item> -->
<el-form-item label="指定会议管理员">
<el-col :span="11">
<el-select
style="width: 100%"
v-model="form.managers"
placeholder="选择管理员"
size="small"
multiple
filterable
remote
:remote-method="fetchUserList"
:loading="searchUsersloading"
>
<el-option :label="user.nickname" :value="user.id" v-for="user in userList" :key="user.id" />
</el-select>
</el-col>
<el-col :span="13" style="color: #999; height: 40px; position: relative; font-size: 12px; line-height: 18px">
<span style="position: absolute; left: 5px; top: 50%; transform: translateY(-50%)"
>(会议管理员有修改会议,复制、取消会议等所有管理本次会议的权限)</span
>
</el-col>
</el-form-item>
<el-form-item label="会议设置">
<el-checkbox style="width: 120px" v-model="form.hasPwd">开启会议密码</el-checkbox>
<el-input
style="width: 170px"
v-model="form.password"
v-if="form.hasPwd"
placeholder="请输入4-6位数字密码"
type="password"
suffix-icon="el-icon-lock"
size="small"
>
</el-input>
<el-checkbox style="display: block" v-model="form.auto_in_waiting_room">开启等候室</el-checkbox>
<el-checkbox style="display: block" v-model="form.allow_in_before_host"
>准许成员在主持人开始前进入会议</el-checkbox
>
<el-checkbox style="display: block" v-model="form.mute_enable_join">入会自动静音</el-checkbox>
<el-checkbox v-model="form.auto_record" @change="autoRecordChange">自动录制会议</el-checkbox>
<el-radio-group v-model="form.auto_record_type" v-if="form.auto_record">
<el-radio label="local">本地录制</el-radio>
<el-radio label="cloud">云录制</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="会议直播">
<el-checkbox v-model="form.enable_live">开启会议直播(用于分享给观看直播的用户)</el-checkbox>
</el-form-item>
<el-form-item label="直播主题" v-if="form.enable_live" :required="form.enable_live" prop="live_subject">
<el-input v-model="form.live_subject" size="small" />
</el-form-item>
<el-form-item label="直播简介" v-if="form.enable_live" :required="form.enable_live" prop="live_summary">
<el-input type="textarea" v-model="form.live_summary"></el-input>
</el-form-item>
<el-form-item label="直播设置" v-if="form.enable_live" style="margin-bottom: 0">
<el-checkbox style="width: 150px" v-model="form.enable_live_password">开启观看直播密码</el-checkbox>
<el-input
style="width: 170px"
v-model="form.live_password"
v-if="form.enable_live_password"
placeholder="请输入4-6位数字密码"
type="password"
suffix-icon="el-icon-lock"
size="small"
/>
</el-form-item>
<el-form-item label="" v-if="form.enable_live">
<el-checkbox v-model="form.enable_live_im">准许观众讨论</el-checkbox>
</el-form-item>
<el-form-item style="padding-left: 100px">
<el-button type="primary" @click="submitForm('ruleForm')" size="mini">立即创建</el-button>
<el-button @click="resetForm('ruleForm')" size="mini">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
import { timeTrans, dateFormat, getYMDByDate, getTimestampYMD, getCurHalfHour } from '@/utils/dateAlgs'
import { searchUserList } from '@api/common'
const DAY_TIMESTAMP = 8.64e7
export default {
data() {
const now = new Date()
const nowDate = getYMDByDate(now)
const startDateChecked = (rule, value, callback) => {
if (value) {
console.log(value)
const timestamp = Date.parse(value)
if (timestamp < Date.now() - DAY_TIMESTAMP) {
callback(new Error('开始时间必须大于当前时间'))
} else {
callback()
}
}
}
const endDateChecked = (rule, value, callback) => {
if (value) {
if (this.endTimestamp < this.startTimestamp) {
callback(new Error('结束时间必须大于开始时间'))
} else if (this.endTimestamp > this.startTimestamp + DAY_TIMESTAMP) {
callback(new Error('会议时间不能超过24小时'))
} else {
callback()
}
}
}
const validateErrMsg = (rule, value, callback) => {
// 当开启会议直播时,启用验证,处理callback
if (this.form.isLive) {
const errMsg = rule.field === 'liveTheme' ? '请输入直播主题' : '请输入直播简介'
callback(new Error(errMsg))
} else {
callback()
}
}
return {
timerClear: false,
time: '',
form: {
meetingType: 'tencent',
subject: '',
startDate: nowDate,
startTime: getCurHalfHour('start'),
endDate: nowDate,
endTime: getCurHalfHour('end'),
timezone: 'beijing',
meeting_type: 0,
recurring_rule: {
recurring_type: 0,
until_type: 0,
until_date: '',
until_count: 7
},
recurring_type: 0,
until_type: 0,
until_date: '',
until_count: 7,
hasPwd: false,
password: '',
settings: {
auto_in_waiting_room: false,
allow_in_before_host: true,
auto_record_type: 'cloud',
mute_enable_join: false
},
auto_in_waiting_room: false,
allow_in_before_host: false,
auto_record_type: 'cloud',
mute_enable_join: false,
auto_record: false,
enable_live: false,
live_config: {
live_subject: '',
live_summary: '',
enable_live_password: false,
live_password: '',
enable_live_im: false
},
live_subject: '',
live_summary: '',
enable_live_password: false,
live_password: '',
enable_live_im: false
},
userList: [],
searchUsersloading: false,
rules: {
meetingType: [{ required: true, message: '请选择会议类型', trigger: 'blur' }],
subject: [{ required: true, message: '请填写会议主题', trigger: 'blur' }],
startDate: [
{ type: 'date', required: true, message: '请选择开始日期', trigger: 'change' },
{ type: 'date', validator: startDateChecked, trigger: 'change' }
],
startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
endDate: [{ type: 'date', required: true, message: '请选择结束日期', trigger: 'change' }],
endTime: [
{ required: true, message: '请选择结束时间', trigger: 'change' },
{ validator: endDateChecked, trigger: 'change' }
],
moderator: [{ required: true, message: '请选择主持人', trigger: 'change' }],
liveTheme: [{ validator: validateErrMsg }],
liveDesc: [{ validator: validateErrMsg }]
},
startDateOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - DAY_TIMESTAMP
}
},
startTimeOptions: {
start: getCurHalfHour('start'),
step: '00:30',
end: '23:30'
},
endTimeOptions: {
start: getCurHalfHour('end'),
step: '00:30',
end: '23:30'
},
monthMaxDay: 28,
_untilDateOptions: {
disabledDate: time => {
let flag = false
switch (this.form.recurring_type) {
case 0: {
break
}
case 1: {
if (time.getDay() === 5 || time.getDay() === 6) flag = true
break
}
case 2: {
const startDate = timeTrans(this.form.startDate)
if (startDate.getDay() !== time.getDay() || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true
break
}
case 3: {
const startDate = timeTrans(this.form.startDate)
const disabledDay = ((getTimestampYMD(time) - getTimestampYMD(startDate)) / (DAY_TIMESTAMP * 7)) % 2 !== 0
if (disabledDay || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true
break
}
case 4: {
const startDate = timeTrans(this.form.startDate)
const day = startDate.getDate()
const targetDay = time.getDate()
let disabledDay = false
if (day > 28) {
const year = time.getFullYear()
const month = time.getMonth() + 1
const targetMDays = new Date(year, month, 0).getDate()
if (targetDay !== targetMDays) disabledDay = true
} else if (startDate.getDate() !== targetDay) {
disabledDay = true
}
if (disabledDay || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true
break
}
}
return flag
}
}
}
},
computed: {
endDateOptions() {
const sDate = this.form.startDate
return {
disabledDate(time) {
return (
getTimestampYMD(time) < getTimestampYMD(sDate) ||
getTimestampYMD(time) > getTimestampYMD(sDate) + DAY_TIMESTAMP
)
}
}
},
untilDateOptions() {
const form = this.form
const type = form.recurring_type
const sDate = timeTrans(form.startDate)
// const eDate = timeTrans(form.endDate)
return {
disabledDate: time => {
let flag = false
if (getTimestampYMD(time) < getTimestampYMD(sDate)) {
flag = true
} else {
switch (type) {
case 0: {
break
}
case 1: {
if (time.getDay() === 5 || time.getDay() === 6) flag = true
break
}
case 2: {
if (sDate.getDay() !== time.getDay()) flag = true
break
}
case 3: {
const disabledDay = ((getTimestampYMD(time) - getTimestampYMD(sDate)) / (DAY_TIMESTAMP * 7)) % 2 !== 0
if (disabledDay) flag = true
break
}
case 4: {
const day = sDate.getDate()
const targetDay = time.getDate()
let disabledDay = false
if (day > 28) {
const year = time.getFullYear()
const month = time.getMonth() + 1
const targetMDays = new Date(year, month, 0).getDate()
if (targetDay !== targetMDays) disabledDay = true
} else if (sDate.getDate() !== targetDay) {
disabledDay = true
}
if (disabledDay) flag = true
break
}
}
}
return flag
}
}
}
},
watch: {
getCycleMeetingEndDate: {
handler: function (nv, ov) {
this.form.until_date = Date.parse(nv)
},
immediate: true
}
},
methods: {
startDateChange(val) {
this.form.endDate = val
const _startDate = timeTrans(this.form.startDate)
if (Date.parse(_startDate) > Date.now()) {
this.startTimeOptions = {
start: '00:00',
step: '00:30',
end: '23:30'
}
} else {
this.startTimeOptions = {
start: getCurHalfHour('start'),
step: '00:30',
end: '23:30'
}
}
if (this.showSchedule) {
this.fetchMeetingList()
}
},
startTimeChange(val) {
const { startDate, endDate } = this.form
const fullDate = this.getFullDateTime(startDate, val)
if (this.isSameDate(startDate, endDate)) {
const startTime = getCurHalfHour('end', fullDate)
this.form.endTime = startTime
this.endTimeOptions = {
start: startTime,
step: '00:30',
end: '23:30'
}
} else {
const endTime = getCurHalfHour('start', fullDate)
this.form.endTime = endTime
this.endTimeOptions = {
start: '00:00',
step: '00:30',
end: endTime
}
}
},
endDateChange() {
this.startTimeChange(this.form.startTime)
},
repaeatRateChange(val) {
if (val === 'everyworkday' && this.form.endType === 'endOneday') {
this.form.periodicTimes = 7
}
},
getFullDateTime(date, timeStr) {
const hmArr = timeStr.split(':')
const h = parseInt(hmArr[0])
const s = parseInt(hmArr[1])
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), h, s, 0)
},
isSameDate(start, end) {
return dateFormat(start, '{y}-{m}-{d}') === dateFormat(end, '{y}-{m}-{d}')
},
autoRecordChange(val) {
this.auto_record_type = val ? 'cloud' : 'none'
},
copyText() {
const text = this.$refs.details.$el.innerText
this.copyFn(text)
},
copyMeetingLink() {
this.copyFn(this.details.join_url)
},
copyLiveLink() {
this.copyFn(this.details.live_config.live_addr)
},
copyFn(val) {
if (!val) return
const dom = document.createElement('textarea')
document.body.appendChild(dom)
dom.value = val
dom.select(); // 选择对象
document.execCommand('Copy');
this.$message({
message: '复制成功!',
type: 'success'
})
document.body.removeChild(dom)
},
joinMeeting() {
window.open(this.details.join_url, '_blank');
},
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
this.$message.success('验证通过')
} else {
return false
}
})
},
resetForm(formName) {
this.$refs[formName].resetFields()
},
fetchUserList(val) {
if (val) {
const params = {
nickname: val
}
this.searchUsersloading = true
searchUserList(params)
.then(res => {
this.searchUsersloading = false
if (res.data && Array.isArray(res.data.items)) {
this.userList = res.data.items
}
})
.catch(() => {})
}
}
}
}
</script>
<style scoped>
.el-form {
flex: 1;
max-width: 600px;
padding:20px 0 10px;
}
.line {
text-align: center;
}
</style>
\ No newline at end of file
<template>
<component v-bind:is="currentPage"></component>
</template>
<script>
import PageCreate from './page-create'
import PageAccountCreate from './page-account-create'
import PageUpdate from './page-update'
export default {
data () {
return {
currentPage: 'PageCreate'
}
},
components: { PageCreate, PageAccountCreate, PageUpdate },
watch: {
$route: {
handler: function (nv, ov) {
const query = this.$route.query
console.log(query)
if (query.type === '1') {
this.currentPage = 'PageAccountCreate'
} else if (query.type === '2') {
console.log('edit')
this.currentPage = 'PageUpdate'
} else {
this.currentPage = 'PageCreate'
}
},
immediate: true
}
}
}
</script>
\ No newline at end of file
<template>
<div>同一账号下创建</div>
</template>
<script>
export default ({
data () {
return {}
}
})
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="create">
<div class="inner">
<meeting-form></meeting-form>
</div>
</div>
</template>
<script>
import MeetingForm from './components/MeetingForm'
export default ({
data () {
return {}
},
components: { MeetingForm }
})
</script>
<style scoped>
.create{
overflow-y: auto;
height: calc(100% - 52px);
}
.inner {
background: #fff;
margin: 0 15px;
border-radius: 4px;
padding-bottom:10px;
}
</style>
<template>
<div>修改</div>
</template>
<script>
export default {
data() {
return {
obj: {
timestamp: 1618998029,
nonce: 'rgHMrr7Bg',
signature: 'UG7wBenexQhiuD2wpCwuxkU0jqcj006d',
instanceid: 1,
userid: '6653195831513972736',
subject: 'sewe',
start_time: '2021-04-21 17:30:00',
end_time: '2021-04-21 18:00:00',
password: '',
meeting_type: 1,
recurring_rule: {
recurring_type: 0,
until_type: 1,
until_count: 2
},
settings: {
mute_enable_join: false,
auto_in_waiting_room: false,
allow_in_before_host: true,
auto_record_type: 'none'
},
enable_live: 0,
live_config: {
live_subject: '',
live_summary: '',
enable_live_password: false,
enable_live_im: false
},
managers: ['6775725014348988416'],
meeting_id: '8343776720283269132'
}
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -2,150 +2,250 @@ ...@@ -2,150 +2,250 @@
<div class="tx-meeting-container"> <div class="tx-meeting-container">
<div class="inner"> <div class="inner">
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="120px"> <el-form ref="ruleForm" :model="form" :rules="rules" label-width="120px">
<!-- <el-form-item label="会议选择" prop="meetingType"> <el-form-item label="会议主题" prop="subject">
<el-radio-group v-model="form.meetingType"> <el-input v-model="form.subject" size="small" />
<el-radio label="tencent">腾讯</el-radio>
</el-radio-group>
</el-form-item> -->
<el-form-item label="会议主题" prop="theme">
<el-input v-model="form.theme" size="small" />
</el-form-item> </el-form-item>
<el-form-item label="开始时间" required> <el-form-item label="开始时间" required>
<el-col :span="11"> <el-col :span="11">
<el-form-item prop="startDate"> <el-form-item prop="startDate">
<el-date-picker v-model="form.startDate" type="date" placeholder="选择日期" style="width: 100%;" size="small" :clearable="timerClear" :editable="timerClear" :picker-options="startDateOptions" @change="startDateChange" /> <el-date-picker
v-model="form.startDate"
type="date"
placeholder="选择日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="startDateOptions"
@change="startDateChange"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2" class="line">-</el-col> <el-col :span="2" class="line">-</el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item prop="startTime"> <el-form-item prop="startTime">
<el-time-select v-model="form.startTime" style="width:100%;" :picker-options="startTimeOptions" placeholder="选择时间" size="small" :clearable="timerClear" :editable="timerClear" @change="startTimeChange" /> <el-time-select
v-model="form.startTime"
style="width: 100%"
:picker-options="startTimeOptions"
placeholder="选择时间"
size="small"
:clearable="timerClear"
:editable="timerClear"
@change="startTimeChange"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="结束时间" required> <el-form-item label="结束时间" required>
<el-col :span="11"> <el-col :span="11">
<el-form-item prop="endDate"> <el-form-item prop="endDate">
<el-date-picker v-model="form.endDate" type="date" placeholder="选择日期" style="width: 100%;" size="small" :clearable="timerClear" :editable="timerClear" :picker-options="endDateOptions" @change="endDateChange" /> <el-date-picker
v-model="form.endDate"
type="date"
placeholder="选择日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="endDateOptions"
@change="endDateChange"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="2" class="line">-</el-col> <el-col :span="2" class="line">-</el-col>
<el-col :span="11"> <el-col :span="11">
<el-form-item prop="endTime"> <el-form-item prop="endTime">
<el-time-select v-model="form.endTime" style="width:100%;" :picker-options="endTimeOptions" placeholder="选择时间" size="small" :clearable="timerClear" :editable="timerClear"/> <el-time-select
v-model="form.endTime"
style="width: 100%"
:picker-options="endTimeOptions"
placeholder="选择时间"
size="small"
:clearable="timerClear"
:editable="timerClear"
/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="时区" required> <el-form-item label="时区" required>
<el-col :span="11"> <el-col :span="11">
<el-select style="width:100%" v-model="form.timezone" placeholder="选择时区" size="small"> <el-select style="width: 100%" v-model="form.timezone" placeholder="选择时区" size="small">
<el-option label="(GMT+8:00)中国标准时间-北京" value="beijing" /> <el-option label="(GMT+8:00)中国标准时间-北京" value="beijing" />
</el-select> </el-select>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="周期会议"> <el-form-item label="周期会议">
<el-switch v-model="form.periodic" /> <el-switch v-model="form.meeting_type" :active-value="1" :inactive-value="0" />
</el-form-item> </el-form-item>
<el-form-item label="重复频率" v-if="form.periodic" required> <el-form-item label="重复频率" v-if="form.meeting_type" required>
<el-col :span="11"> <el-col :span="11">
<el-select style="width:100%" v-model="form.repeatRate" placeholder="选择重复频率" size="small" @change="repaeatRateChange"> <el-select
<el-option label="每天" value="everyday" /> style="width: 100%"
<el-option label="每个工作日" value="everyworkday" /> v-model="form.recurring_type"
<el-option label="每周" value="everyweek" /> placeholder="选择重复频率"
<el-option label="每两周" value="every2weeks" /> size="small"
<el-option label="每月" value="everymonth" /> @change="repaeatRateChange"
</el-select> >
<el-option label="每天" :value="0" />
<el-option label="每个工作日" :value="1" />
<el-option label="每周" :value="2" />
<el-option label="每两周" :value="3" />
<el-option label="每月" :value="4" />
</el-select>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="结束重复" v-if="form.periodic" required> <el-form-item label="结束重复" v-if="form.meeting_type" required>
<el-col :span="11"> <el-col :span="11">
<el-select style="width:100%" v-model="form.endType" placeholder="选择时区" size="small"> <el-select style="width: 100%" v-model="form.until_type" placeholder="选择时区" size="small">
<el-option label="结束于某天" value="endOneday" /> <el-option label="结束于某天" :value="0" />
<el-option label="限制会议次数" value="limitTimes" /> <el-option label="限制会议次数" :value="1" />
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="2" class="line">-</el-col> <el-col :span="2" class="line">-</el-col>
<el-col :span="11"> <el-col :span="11">
<el-date-picker v-if="form.endType === 'endOneday'" v-model="getCycleMeetingEndDate" type="date" placeholder="选择结束日期" style="width: 100%;" size="small" :clearable="timerClear" :editable="timerClear" :picker-options="cycleMeetingEndDateOptions" /> <el-date-picker
<el-input-number v-else v-model="form.periodicTimes" :min="1" :max="50" size="small" @change="handleChange"></el-input-number> v-if="form.until_type === 0"
v-model="getCycleMeetingEndDate"
type="date"
placeholder="选择结束日期"
style="width: 100%"
size="small"
:clearable="timerClear"
:editable="timerClear"
:picker-options="cycleMeetingEndDateOptions"
/>
<el-input-number v-else v-model="form.until_count" :min="1" :max="50" size="small"></el-input-number>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="指定主持人"> <!-- <el-form-item label="指定主持人">
<el-col :span="11"> <el-col :span="11">
<el-select style="width:100%" v-model="form.moderator" placeholder="选择主持人" size="small"> <el-select style="width:100%" v-model="form.moderator" placeholder="选择主持人" size="small">
<el-option label="张三" value="zhangsan" /> <el-option :label="user.username" :value="user.id" v-for="user in userList" :key="user.id" />
<el-option label="李四" value="lisi" />
</el-select> </el-select>
</el-col> </el-col>
</el-form-item> </el-form-item> -->
<el-form-item label="指定会议管理员"> <el-form-item label="指定会议管理员">
<el-col :span="11"> <el-col :span="11">
<el-select style="width:100%" v-model="form.administrators" placeholder="选择管理员" size="small" multiple> <el-select
<el-option label="张三" value="zhangsan" /> style="width: 100%"
<el-option label="李四" value="lisi" /> v-model="form.managers"
placeholder="选择管理员"
size="small"
multiple
filterable
remote
:remote-method="fetchUserList"
:loading="searchUsersloading"
>
<el-option :label="user.nickname" :value="user.id" v-for="user in userList" :key="user.id" />
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="13" style="color:#999;height:40px;position:relative;font-size:12px;line-height:18px;"> <el-col :span="13" style="color: #999; height: 40px; position: relative; font-size: 12px; line-height: 18px">
<span style="position:absolute;left:5px;top:50%;transform:translateY(-50%)">(会议管理员有修改会议,复制、取消会议等所有管理本次会议的权限)</span> <span style="position: absolute; left: 5px; top: 50%; transform: translateY(-50%)"
>(会议管理员有修改会议,复制、取消会议等所有管理本次会议的权限)</span
>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item label="会议设置"> <el-form-item label="会议设置">
<el-checkbox style="width:120px;" v-model="form.isSecret">开启会议密码</el-checkbox> <el-checkbox style="width: 120px" v-model="form.hasPwd">开启会议密码</el-checkbox>
<el-input style="width:170px;" v-model="form.secret" v-if="form.isSecret" placeholder="请输入4-6位数字密码" type="password" suffix-icon="el-icon-lock" size="small"> <el-input
style="width: 170px"
v-model="form.password"
v-if="form.hasPwd"
placeholder="请输入4-6位数字密码"
type="password"
suffix-icon="el-icon-lock"
size="small"
>
</el-input> </el-input>
<el-checkbox style="display:block;" v-model="form.openWaitingRoom">开启等候室</el-checkbox> <el-checkbox style="display: block" v-model="form.auto_in_waiting_room">开启等候室</el-checkbox>
<el-checkbox style="display:block;" v-model="form.joinAdvance">准许成员在主持人开始前进入会议</el-checkbox> <el-checkbox style="display: block" v-model="form.allow_in_before_host"
<el-checkbox style="display:block;" v-model="form.mute">入会自动静音</el-checkbox> >准许成员在主持人开始前进入会议</el-checkbox
<el-checkbox style="display:block;" v-model="form.recordVideo">自动录制会议</el-checkbox> >
<el-checkbox style="display: block" v-model="form.mute_enable_join">入会自动静音</el-checkbox>
<el-checkbox v-model="form.auto_record" @change="autoRecordChange">自动录制会议</el-checkbox>
<el-radio-group v-model="form.auto_record_type" v-if="form.auto_record">
<el-radio label="local">本地录制</el-radio>
<el-radio label="cloud">云录制</el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="会议直播"> <el-form-item label="会议直播">
<el-checkbox v-model="form.isLive">开启会议直播(用于分享给观看直播的用户)</el-checkbox> <el-checkbox v-model="form.enable_live">开启会议直播(用于分享给观看直播的用户)</el-checkbox>
</el-form-item> </el-form-item>
<el-form-item label="直播主题" v-if="form.isLive" :required="form.isLive" prop="liveTheme"> <el-form-item label="直播主题" v-if="form.enable_live" :required="form.enable_live" prop="live_subject">
<el-input v-model="form.liveTheme" size="small" /> <el-input v-model="form.live_subject" size="small" />
</el-form-item> </el-form-item>
<el-form-item label="直播简介" v-if="form.isLive" :required="form.isLive" prop="liveDesc"> <el-form-item label="直播简介" v-if="form.enable_live" :required="form.enable_live" prop="live_summary">
<el-input type="textarea" v-model="form.liveDesc"></el-input> <el-input type="textarea" v-model="form.live_summary"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="直播设置" v-if="form.isLive" > <el-form-item label="直播设置" v-if="form.enable_live" style="margin-bottom: 0">
<el-checkbox style="display:block;" v-model="form.isLiveSecret">开启观看直播密码</el-checkbox> <el-checkbox style="width: 150px" v-model="form.enable_live_password">开启观看直播密码</el-checkbox>
<el-checkbox v-model="form.permitComment">准许观众讨论</el-checkbox> <el-input
style="width: 170px"
v-model="form.live_password"
v-if="form.enable_live_password"
placeholder="请输入4-6位数字密码"
type="password"
suffix-icon="el-icon-lock"
size="small"
/>
</el-form-item> </el-form-item>
<el-form-item style="padding-left:100px;"> <el-form-item label="" v-if="form.enable_live">
<el-button type="primary" @click="submitForm('ruleForm')" size="mini">立即创建</el-button> <el-checkbox v-model="form.enable_live_im">准许观众讨论</el-checkbox>
</el-form-item>
<el-form-item style="padding-left: 100px">
<el-button type="primary" @click="submitForm('ruleForm')" size="mini">{{isUpdate ? '修改会议' : '立即创建'}}</el-button>
<el-button @click="resetForm('ruleForm')" size="mini">重置</el-button> <el-button @click="resetForm('ruleForm')" size="mini">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="right-container" v-if="showSchedule"> <div class="right-container" v-if="showSchedule">
<div class="title">{{form.startDate | timeFormat}} {{form.startDate | timeFormat('星期{a}')}}</div> <div class="title">{{ form.startDate | timeFormat }} {{ form.startDate | timeFormat('星期{a}') }}</div>
<schedule :options="options" :data="schedule" :date="form.startDate" /> <schedule :options="options" :data="schedule" :date="form.startDate" />
<div class="pre-time-range" :style="{top: getTop, height: getHeight}"></div> <div class="pre-time-range" :style="{ top: getTop, height: getHeight }"></div>
</div> </div>
</div> </div>
<meeting-success-dialog :dialogVisible.sync="dialogVisible" :details="details"/>
</div> </div>
</template> </template>
<script> <script>
import Schedule from '@/components/Schedule' import Schedule from '@/components/Schedule'
import { timeTrans, dateFormat, getTimestampYMD, computedDateByRateTimes, computedTimesByRateDate, getCurHalfHour, isSameDate } from '@/utils/dateAlgs' import MeetingSuccessDialog from '@/components/MeetingSuccessDialog/index'
import {
timeTrans,
dateFormat,
getYMDByDate,
getTimestampYMD,
computedDateByRateTimes,
computedTimesByRateDate,
getCurHalfHour,
isSameDate
} from '@/utils/dateAlgs'
import { searchUserList, createMeeting, operateLog, getMeetingDetails, getNonpagedMeetingList, updateMeeting } from '@api/common'
const DAY_TIMESTAMP = 8.64e7 const DAY_TIMESTAMP = 8.64e7
export default { export default {
data () { data() {
const now = new Date() const now = new Date()
const nowDate = new Date(now.getFullYear(), now.getMonth(), now.getDate()) const nowDate = getYMDByDate(now)
const startDateChecked = (rule, value, callback) => { const startDateChecked = (rule, value, callback) => {
if (value) { if (value) {
const timestamp = Date.parse(value); console.log(value)
const timestamp = Date.parse(value)
if (timestamp < Date.now() - DAY_TIMESTAMP) { if (timestamp < Date.now() - DAY_TIMESTAMP) {
callback(new Error('开始时间必须大于当前时间')); callback(new Error('开始时间必须大于当前时间'))
} else {
callback()
} }
} }
} }
const endDateChecked = (rule, value, callback) => { const endDateChecked = (rule, value, callback) => {
if (value) { if (value) {
if (this.endTimestamp < this.startTimestamp) { if (this.endTimestamp < this.startTimestamp) {
callback(new Error('结束时间必须大于开始时间')); callback(new Error('结束时间必须大于开始时间'))
} else if (this.endTimestamp > this.startTimestamp + DAY_TIMESTAMP) { } else if (this.endTimestamp > this.startTimestamp + DAY_TIMESTAMP) {
callback(new Error('会议时间不能超过24小时')); callback(new Error('会议时间不能超过24小时'))
} else {
callback()
} }
} }
} }
...@@ -153,50 +253,47 @@ export default { ...@@ -153,50 +253,47 @@ export default {
// 当开启会议直播时,启用验证,处理callback // 当开启会议直播时,启用验证,处理callback
if (this.form.isLive) { if (this.form.isLive) {
const errMsg = rule.field === 'liveTheme' ? '请输入直播主题' : '请输入直播简介' const errMsg = rule.field === 'liveTheme' ? '请输入直播主题' : '请输入直播简介'
callback(new Error(errMsg)); callback(new Error(errMsg))
} else { } else {
callback(); callback()
} }
}; }
return { return {
tabActive: 'tx',
timerClear: false, timerClear: false,
time: '', time: '',
form: { form: {
meetingType: 'tencent', subject: '',
theme: '',
startDate: nowDate, startDate: nowDate,
startTime: getCurHalfHour('start'), startTime: getCurHalfHour('start'),
endDate: nowDate, endDate: nowDate,
endTime: getCurHalfHour('end'), endTime: getCurHalfHour('end'),
timezone: 'beijing', timezone: 'beijing',
periodic: true, meeting_type: 0,
repeatRate: 'everyday', recurring_type: 0,
endType: 'endOneday', until_type: 0,
periodicEndDate: '', until_date: '',
periodicTimes: 7, until_count: 7,
isSecret: false, hasPwd: false,
secret: '', password: '',
openWaitingRoom: false, auto_in_waiting_room: false,
joinAdvance: false, allow_in_before_host: true,
mute: false, auto_record_type: 'none',
recordVideo: false, mute_enable_join: false,
isLive: false, auto_record: false,
liveTheme: '', enable_live: false,
liveDesc: '', live_subject: '',
isLiveSecret: false, live_summary: '',
permitComment: false enable_live_password: false,
live_password: '',
enable_live_im: false
}, },
rules: { rules: {
meetingType: [{ required: true, message: '请选择会议类型', trigger: 'blur' }], subject: [{ required: true, message: '请填写会议主题', trigger: 'blur' }],
theme: [{ required: true, message: '请填写会议主题', trigger: 'blur' }],
startDate: [ startDate: [
{ type: 'date', required: true, message: '请选择开始日期', trigger: 'change' }, { type: 'date', required: true, message: '请选择开始日期', trigger: 'change' },
{ type: 'date', validator: startDateChecked, trigger: 'change' } { type: 'date', validator: startDateChecked, trigger: 'change' }
], ],
startTime: [ startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
{ required: true, message: '请选择开始时间', trigger: 'change' }
],
endDate: [{ type: 'date', required: true, message: '请选择结束日期', trigger: 'change' }], endDate: [{ type: 'date', required: true, message: '请选择结束日期', trigger: 'change' }],
endTime: [ endTime: [
{ required: true, message: '请选择结束时间', trigger: 'change' }, { required: true, message: '请选择结束时间', trigger: 'change' },
...@@ -208,7 +305,7 @@ export default { ...@@ -208,7 +305,7 @@ export default {
}, },
startDateOptions: { startDateOptions: {
disabledDate(time) { disabledDate(time) {
return time.getTime() < Date.now() - DAY_TIMESTAMP; return time.getTime() < Date.now() - DAY_TIMESTAMP
} }
}, },
startTimeOptions: { startTimeOptions: {
...@@ -223,36 +320,36 @@ export default { ...@@ -223,36 +320,36 @@ export default {
}, },
monthMaxDay: 28, monthMaxDay: 28,
cycleMeetingEndDateOptions: { cycleMeetingEndDateOptions: {
disabledDate: (time) => { disabledDate: time => {
let flag = false let flag = false
switch (this.form.repeatRate) { switch (this.form.recurring_type) {
case 'everyday': { case 0: {
break break
} }
case 'everyworkday': { case 1: {
if (time.getDay() === 5 || time.getDay() === 6) flag = true if (time.getDay() === 5 || time.getDay() === 6) flag = true
break break
} }
case 'everyweek': { case 2: {
const startDate = timeTrans(this.form.startDate) const startDate = timeTrans(this.form.startDate)
if (startDate.getDay() !== time.getDay() || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true if (startDate.getDay() !== time.getDay() || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true
break break
} }
case 'every2weeks': { case 3: {
const startDate = timeTrans(this.form.startDate) const startDate = timeTrans(this.form.startDate)
const disabledDay = ((getTimestampYMD(time) - getTimestampYMD(startDate)) / (DAY_TIMESTAMP * 7)) % 2 !== 0 const disabledDay = ((getTimestampYMD(time) - getTimestampYMD(startDate)) / (DAY_TIMESTAMP * 7)) % 2 !== 0
if (disabledDay || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true if (disabledDay || getTimestampYMD(time) < getTimestampYMD(startDate)) flag = true
break break
} }
case 'everymonth': { case 4: {
const startDate = timeTrans(this.form.startDate) const startDate = timeTrans(this.form.startDate)
const day = startDate.getDate() const day = startDate.getDate()
const targetDay = time.getDate() const targetDay = time.getDate()
let disabledDay = false let disabledDay = false
if (day > 28) { if (day > 28) {
const year = time.getFullYear(); const year = time.getFullYear()
const month = time.getMonth() + 1; const month = time.getMonth() + 1
const targetMDays = new Date(year, month, 0).getDate(); const targetMDays = new Date(year, month, 0).getDate()
if (targetDay !== targetMDays) disabledDay = true if (targetDay !== targetMDays) disabledDay = true
} else if (startDate.getDate() !== targetDay) { } else if (startDate.getDate() !== targetDay) {
disabledDay = true disabledDay = true
...@@ -264,6 +361,8 @@ export default { ...@@ -264,6 +361,8 @@ export default {
return flag return flag
} }
}, },
userList: [],
searchUsersloading: false,
showSchedule: false, showSchedule: false,
options: { options: {
multi: false, // 是否为多日程 multi: false, // 是否为多日程
...@@ -272,21 +371,27 @@ export default { ...@@ -272,21 +371,27 @@ export default {
step: 60, // 只接收15, 30, 60三种步伐 step: 60, // 只接收15, 30, 60三种步伐
lineHeight: 40, // init number 时间线间的高度 lineHeight: 40, // init number 时间线间的高度
nowBeforeDisabled: true, nowBeforeDisabled: true,
disabledNew: true, readonly: true,
popoverPos: 'bottom' popoverPos: 'bottom'
}, },
schedule: { schedule: {
id: 'live-1', userid: '',
events: [ events: []
] },
} dialogVisible: false,
details: {},
isUpdate: false,
userid: ''
} }
}, },
computed: { computed: {
user() {
return this.$store.getters.user
},
getTop() { getTop() {
const timeRange = this.startTimestamp - this.startDotTimestamp const timeRange = this.startTimestamp - this.startDotTimestamp
const top = timeRange / ((60 * 1000 * this.options.step) / this.options.lineHeight) const top = timeRange / ((60 * 1000 * this.options.step) / this.options.lineHeight)
return (top + 56) + 'px' return top + 56 + 'px'
}, },
getHeight() { getHeight() {
const start = timeTrans(this.startTimestamp) const start = timeTrans(this.startTimestamp)
...@@ -296,7 +401,7 @@ export default { ...@@ -296,7 +401,7 @@ export default {
} }
const timeRange = end.getTime() - start.getTime() const timeRange = end.getTime() - start.getTime()
const h = timeRange / ((60 * 1000 * this.options.step) / this.options.lineHeight) const h = timeRange / ((60 * 1000 * this.options.step) / this.options.lineHeight)
return (h - 2) + 'px' return h - 2 + 'px'
}, },
startDotTimestamp() { startDotTimestamp() {
const date = this.form.startDate const date = this.form.startDate
...@@ -310,20 +415,23 @@ export default { ...@@ -310,20 +415,23 @@ export default {
return this.getFullDateTime(this.form.endDate, this.form.endTime).getTime() return this.getFullDateTime(this.form.endDate, this.form.endTime).getTime()
}, },
getCycleMeetingEndDate: { getCycleMeetingEndDate: {
get: function() { get: function () {
const startDate = this.form.startDate ? this.form.startDate : Date.now() const startDate = this.form.startDate ? this.form.startDate : Date.now()
return computedDateByRateTimes(startDate, this.form.periodicTimes, this.form.repeatRate) return computedDateByRateTimes(startDate, this.form.until_count, this.form.recurring_type)
}, },
set: function (newValue) { set: function (newValue) {
const times = computedTimesByRateDate(this.form.startDate, newValue, this.form.repeatRate) const times = computedTimesByRateDate(this.form.startDate, newValue, this.form.recurring_type)
this.form.periodicTimes = times this.form.until_count = times
} }
}, },
endDateOptions() { endDateOptions() {
const _startDate = this.form.startDate; const _startDate = this.form.startDate
return { return {
disabledDate(time) { disabledDate(time) {
return getTimestampYMD(time) < getTimestampYMD(_startDate) || getTimestampYMD(time) > getTimestampYMD(_startDate) + DAY_TIMESTAMP; return (
getTimestampYMD(time) < getTimestampYMD(_startDate) ||
getTimestampYMD(time) > getTimestampYMD(_startDate) + DAY_TIMESTAMP
)
} }
} }
} }
...@@ -334,27 +442,47 @@ export default { ...@@ -334,27 +442,47 @@ export default {
return dateFormat(val, fmt) return dateFormat(val, fmt)
} }
}, },
components: { Schedule }, components: { Schedule, MeetingSuccessDialog },
created() { created() {
const type = this.$route.query.type // this.getUserList()
switch (type) {
case '1':
this.showSchedule = true
}
console.log(this.$route.query)
}, },
watch: { watch: {
getCycleMeetingEndDate: { getCycleMeetingEndDate: {
handler: function(nv, ov) { handler: function (nv, ov) {
this.form.periodicEndDate = Date.parse(nv) this.form.until_date = Date.parse(nv)
},
immediate: true
},
$route: {
handler: function (nv, ov) {
const query = this.$route.query
console.log(query)
if (query.type === '1') {
this.showSchedule = true
this.form.startDate = getYMDByDate(query.start)
this.form.startTime = dateFormat(query.start, '{h}:{i}')
this.form.endDate = getYMDByDate(query.end)
this.form.endTime = dateFormat(query.end, '{h}:{i}')
this.schedule.userid = query.account
this.fetchMeetingList()
} else if (query.type === '2') {
const params = {
meeting_id: query.meeting_id,
sub_meeting_id: query.sub_meeting_id
}
this.isUpdate = true
this.getDetailsData(params)
} else {
this.showSchedule = false
}
}, },
immediate: true immediate: true
} }
}, },
methods: { methods: {
startDateChange(val) { startDateChange(val) {
this.form.endDate = val; this.form.endDate = val
const _startDate = timeTrans(this.form.startDate); const _startDate = timeTrans(this.form.startDate)
if (Date.parse(_startDate) > Date.now()) { if (Date.parse(_startDate) > Date.now()) {
this.startTimeOptions = { this.startTimeOptions = {
start: '00:00', start: '00:00',
...@@ -368,6 +496,9 @@ export default { ...@@ -368,6 +496,9 @@ export default {
end: '23:30' end: '23:30'
} }
} }
if (this.showSchedule) {
this.fetchMeetingList()
}
}, },
startTimeChange(val) { startTimeChange(val) {
const { startDate, endDate } = this.form const { startDate, endDate } = this.form
...@@ -382,7 +513,7 @@ export default { ...@@ -382,7 +513,7 @@ export default {
} }
} else { } else {
const endTime = getCurHalfHour('start', fullDate) const endTime = getCurHalfHour('start', fullDate)
this.form.endTime = endTime; this.form.endTime = endTime
this.endTimeOptions = { this.endTimeOptions = {
start: '00:00', start: '00:00',
step: '00:30', step: '00:30',
...@@ -395,78 +526,305 @@ export default { ...@@ -395,78 +526,305 @@ export default {
}, },
repaeatRateChange(val) { repaeatRateChange(val) {
if (val === 'everyworkday' && this.form.endType === 'endOneday') { if (val === 'everyworkday' && this.form.endType === 'endOneday') {
this.form.periodicTimes = 7; this.form.periodicTimes = 7
} }
}, },
getFullDateTime(date, timeStr) { getFullDateTime(date, timeStr) {
const hmArr = timeStr.split(':'); const hmArr = timeStr.split(':')
const h = parseInt(hmArr[0]); const h = parseInt(hmArr[0])
const s = parseInt(hmArr[1]); const s = parseInt(hmArr[1])
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), h, s, 0) return new Date(date.getFullYear(), date.getMonth(), date.getDate(), h, s, 0)
}, },
isSameDate(start, end) { isSameDate(start, end) {
return dateFormat(start, '{y}-{m}-{d}') === dateFormat(end, '{y}-{m}-{d}') return dateFormat(start, '{y}-{m}-{d}') === dateFormat(end, '{y}-{m}-{d}')
}, },
autoRecordChange(val) {
this.auto_record_type = val ? 'cloud' : 'none'
},
copyText() {
const text = this.$refs.details.$el.innerText
this.copyFn(text)
},
copyMeetingLink() {
this.copyFn(this.details.join_url)
},
copyLiveLink() {
this.copyFn(this.details.live_config.live_addr)
},
copyFn(val) {
if (!val) return
const dom = document.createElement('textarea')
document.body.appendChild(dom)
dom.value = val
dom.select(); // 选择对象
document.execCommand('Copy');
this.$message({
message: '复制成功!',
type: 'success'
})
document.body.removeChild(dom)
},
joinMeeting() {
window.open(this.details.join_url, '_blank');
},
submitForm(formName) { submitForm(formName) {
this.$refs[formName].validate((valid) => { this.$refs[formName].validate(valid => {
if (valid) { if (valid) {
console.log(valid); if (this.isUpdate) {
this.fetchUpdateMeeting()
} else {
this.fetchCreateMeeting()
}
} else { } else {
console.log('error submit!!'); return false
return false;
} }
}); })
}, },
resetForm(formName) { resetForm(formName) {
this.$refs[formName].resetFields(); this.$refs[formName].resetFields()
}, },
handleChange(val) { async getDetailsData(params) {
console.log(val) const details = await this.fetchMeetingDetails(params)
this.details = details
const start = timeTrans(details.start_time)
const end = timeTrans(details.end_time)
this.userid = details.userid
this.form.subject = details.subject
this.form.startDate = getYMDByDate(start)
this.form.startTime = dateFormat(start, '{h}:{i}')
this.form.endDate = getYMDByDate(end)
this.form.endTime = dateFormat(end, '{h}:{i}')
this.form.meeting_type = details.meeting_type
if (details.meeting_type === 1) {
const recurringRule = details.recurring_rule
this.form.recurring_type = recurringRule.recurring_type
this.form.until_type = recurringRule.until_type
if (recurringRule.until_type === 0) {
this.form.until_date = timeTrans(recurringRule.until_date)
} else {
this.form.until_count = recurringRule.until_count
}
}
if (details.password) {
this.form.password = details.password
this.hasPwd = true
}
const setting = details.settings
this.form.auto_in_waiting_room = setting.auto_in_waiting_room
this.form.allow_in_before_host = setting.allow_in_before_host
this.form.auto_record_type = setting.auto_record_type
if (setting.auto_record_type !== 'none') {
this.form.auto_record = true
}
this.form.mute_enable_join = setting.mute_enable_join
this.form.enable_live = details.enable_live
if (details.enable_live === 1) {
const liveConfig = details.live_config
this.form.live_subject = liveConfig.live_subject
this.form.live_summary = liveConfig.live_summary
this.form.enable_live_password = liveConfig.enable_live_password
this.form.live_password = liveConfig.live_password
this.form.enable_live_im = liveConfig.enable_live_im
}
},
async showMeetingDetails(obj) {
const loading = this.$loading({
lock: true,
text: '获取腾讯会议详情,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const params = {
meeting_id: obj.meeting_id,
sub_meeting_id: obj.sub_meetings[0].sub_meeting_id
}
const details = await this.fetchMeetingDetails(params)
loading.close()
this.details = details
this.dialogVisible = true
},
fetchMeetingList() {
const date = this.form.startDate
const start = dateFormat(date)
const end = dateFormat(new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1))
const params = {
userid: this.schedule.userid,
start_time: start,
end_time: end
}
getNonpagedMeetingList(params).then((res) => {
if (res.code === 0 && res.data && res.data.list) {
console.log(res.data.list)
this.schedule.events = res.data.list
} else {
}
}).catch()
},
fetchUserList(val) {
if (val) {
const params = {
nickname: val
}
this.searchUsersloading = true
searchUserList(params)
.then(res => {
this.searchUsersloading = false
if (res.data && Array.isArray(res.data.items)) {
this.userList = res.data.items
}
})
.catch(() => {})
}
},
getSubmitParams() {
const form = this.form
const params = {
instanceid: 1,
userid: this.showSchedule ? this.schedule.userid : undefined,
subject: form.subject,
start_time: dateFormat(this.startTimestamp),
end_time: dateFormat(this.endTimestamp),
password: form.password,
meeting_type: form.meeting_type,
recurring_rule: {
recurring_type: form.recurring_type,
until_type: form.until_type,
until_date: form.until_type ? undefined : parseInt(form.until_date / 1000),
until_count: form.until_type ? form.until_count : undefined
},
settings: {
mute_enable_join: form.mute_enable_join,
auto_in_waiting_room: form.auto_in_waiting_room,
allow_in_before_host: form.allow_in_before_host,
auto_record_type: form.auto_record ? form.auto_record_type : 'none'
},
enable_live: form.enable_live,
live_config: {
live_subject: form.live_subject,
live_summary: form.live_summary,
enable_live_password: form.enable_live_password,
live_password: form.enable_live_password ? form.live_password : undefined,
enable_live_im: form.enable_live_im
},
managers: form.managers.length > 0 ? form.managers : [this.user.id]
}
return params
},
fetchUpdateMeeting() {
const params = this.getSubmitParams()
params.meeting_id = this.$route.query.meeting_id
params.userid = this.userid
const loading = this.$loading({
lock: true,
text: '修改腾讯会议中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
console.log(params)
updateMeeting(params).then(res => {
loading.close()
if (res.code === 0 && res.data.status) {
operateLog({ type: `修改会议,被修改会议meeting_code:${res.data.meeting_code}`, user: this.user })
this.$message.success('修改腾讯会议成功')
this.dialogVisible = true
} else {
this.$message.error(res.message || res.msg || '创建腾讯会议失败')
}
})
},
fetchCreateMeeting() {
const params = this.getSubmitParams()
const loading = this.$loading({
lock: true,
text: '创建腾讯会议中,请稍后...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
createMeeting(params).then(res => {
loading.close()
if (res.code === 0 && res.data.id) {
operateLog({ type: `创建会议,被创建会议meeting_code:${res.data.meeting_code}`, user: this.user })
this.$message.success('创建腾讯会议成功')
this.showMeetingDetails(res.data)
} else {
this.$message.error(res.message || res.msg || '创建腾讯会议失败')
}
})
},
fetchMeetingDetails(params) {
return new Promise((resolve, reject) => {
getMeetingDetails(params).then(res => {
if (res.code === 0 && res.data.id) {
resolve(res.data)
} else {
reject(res)
}
}).catch((err) => reject(err))
})
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.tx-meeting-container{ .tx-meeting-container {
overflow-y:auto; overflow-y: auto;
height:calc(100% - 52px); height: calc(100% - 52px);
} }
.inner{ .inner {
display:flex; display: flex;
background:#fff; background: #fff;
margin:0 15px; margin: 0 15px;
border-radius:4px; border-radius: 4px;
padding-bottom:10px;
} }
.el-form{ .el-form {
flex: 1; flex: 1;
max-width:600px; max-width: 600px;
padding-bottom:30px; padding:20px 0 10px;
} }
.line{ .line {
text-align:center; text-align: center;
} }
.right-container{ .right-container {
position:relative; position: relative;
width:45%; width: 45%;
box-sizing:border-box; box-sizing: border-box;
padding-left: 20px; padding-left: 20px;
} }
.right-container .title{ .right-container .title {
position:absolute; position: absolute;
left:0; left: 0;
top:0; top: 0;
width:100%; width: 100%;
line-height:50px; line-height: 50px;
font-size:16px; font-size: 16px;
text-align:center; text-align: center;
} }
.pre-time-range{ .pre-time-range {
position:absolute; position: absolute;
left:70px; left: 70px;
width:calc(100% - 70px); width: calc(100% - 70px);
background:#52b837; background: #52b837;
} }
.right-container .el-scrollbar ::v-deep.el-scrollbar__wrap{ .right-container .el-scrollbar ::v-deep.el-scrollbar__wrap {
/* overflow:hidden; */ /* overflow:hidden; */
} }
.tx-meeting-container ::v-deep.el-dialog__header{
padding-top:14px;
}
.tx-meeting-container ::v-deep.el-dialog__headerbtn{
top:12px;
right:12px;
}
.tx-meeting-container ::v-deep.el-dialog__body{
padding:10px 0;
margin:0 20px;
border: 1px solid #DBDBDB;
}
.tx-meeting-container ::v-deep.el-dialog__footer{
padding-bottom:16px;
}
.tx-meeting-container ::v-deep.el-dialog .el-form-item{
margin:0;
}
</style> </style>
...@@ -10,23 +10,22 @@ ...@@ -10,23 +10,22 @@
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<label>会议主题</label> <label>会议主题</label>
<el-input placeholder="请输入会议主题" v-model="filter.meetingTitle" size="mini" clearable></el-input> <el-input placeholder="请输入会议主题" v-model="filter.subject" size="mini" clearable></el-input>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<label>会议状态</label> <label>会议状态</label>
<el-select v-model="filter.status" placeholder="请选择" size="mini" clearable> <el-select v-model="filter.status" placeholder="请选择" size="mini" clearable>
<el-option label="进行中" value="1" /> <el-option label="进行中" :value="1" />
<el-option label="未开始" value="2" /> <el-option label="未开始" :value="0" />
<el-option label="已完成" value="3" /> <el-option label="已完成" :value="2" />
</el-select> </el-select>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<label>会议类型</label> <label>会议创建人</label>
<el-select v-model="filter.meetingType" placeholder="请选择" size="mini" clearable> <el-select v-model="filter.userid" placeholder="搜索用户" size="mini" filterable remote :remote-method="fetchUserList" :loading="searchUsersloading">
<el-option label="腾讯" value="1" /> <el-option :label="user.nickname" :value="user.id" v-for="user in userList" :key="user.id" />
<el-option label="cc" value="2" />
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="11"> <el-col :span="11">
...@@ -34,61 +33,67 @@ ...@@ -34,61 +33,67 @@
<el-date-picker v-model="filter.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" size="mini" clearable></el-date-picker> <el-date-picker v-model="filter.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" size="mini" clearable></el-date-picker>
</el-col> </el-col>
<el-col :span="5"> <el-col :span="5">
<el-button type="primary" icon="el-icon-search" size="mini">查询</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="fetchMeetingList">查询</el-button>
<el-button icon="el-icon-refresh-left" size="mini" @click="reset">重置</el-button> <el-button icon="el-icon-refresh-left" size="mini" @click="reset">重置</el-button>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
<el-table :data="listData" style="width: 100%" height="calc(100% - 116px)"> <el-table :data="listData" style="width: 100%" height="calc(100% - 116px)">
<el-table-column label="会议时间" min-width="180"> <el-table-column label="会议时间" min-width="160">
<template slot-scope="scope"> <template slot-scope="scope">
<p style="color:#AEAEAE;"> <p style="color: #aeaeae">
<span style="font-size:18px;color:#606266;">{{ scope.row.date | dateFormat('{d}')}}</span> <span style="font-size: 18px; color: #606266">{{ scope.row.start_time | dateFormat('{d}') }}</span>
{{ scope.row.date | dateFormat('{m}月')}} {{ scope.row.date | dateFormat('周{a}')}} {{ scope.row.start_time | dateFormat('{m}月') }} {{ scope.row.start_time | dateFormat('周{a}') }}
<span style="font-size:16px;color:#606266;">{{ scope.row.date | dateFormat('{h}:{i}')}}</span> <span style="font-size: 16px; color: #606266">{{ scope.row.start_time | dateFormat('{h}:{i}') }}</span>
</p> </p>
<p style="color:#AEAEAE;"> <p style="color: #aeaeae">
<span style="font-size:18px;color:#606266;">{{ scope.row.endDate | dateFormat('{d}')}}</span> <span style="font-size: 18px; color: #606266">{{ scope.row.end_time | dateFormat('{d}') }}</span>
{{ scope.row.endDate | dateFormat('{m}月')}} {{ scope.row.endDate | dateFormat('周{a}')}} {{ scope.row.end_time | dateFormat('{m}月') }} {{ scope.row.end_time | dateFormat('周{a}') }}
<span style="font-size:16px;color:#606266;">{{ scope.row.endDate | dateFormat('{h}:{i}')}}</span> <span style="font-size: 16px; color: #606266">{{ scope.row.end_time | dateFormat('{h}:{i}') }}</span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="会议主题" min-width="170"> <el-table-column label="会议主题" min-width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-popover trigger="hover" placement="top" width="240"> <el-popover trigger="hover" placement="top" width="240">
<p>{{ scope.row.title }}</p> <p>{{ scope.row.subject }}</p>
<div slot="reference" class="name-wrapper"> <div slot="reference" class="name-wrapper">
<p style="display:flex;"> <p style="display: flex">
<span style="flex:1;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;">{{ scope.row.title }}</span> <span
<span v-if="scope.row.isCycle" style="color:#409DFF;width:40px;">(周期)</span> style="
flex: 1;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
"
>{{ scope.row.subject }}</span
>
<span v-if="scope.row.meeting_type === 1" style="color: #409dff; width: 40px">(周期)</span>
</p> </p>
</div> </div>
</el-popover> </el-popover>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="resource" label="会议来源" min-width="80"></el-table-column> <!-- <el-table-column prop="resource" label="会议来源" width="80"></el-table-column> -->
<el-table-column prop="resource" label="会议状态" min-width="80"> <el-table-column prop="resource" label="会议状态" min-width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<p :class="{'status-start': scope.row.status === 1, 'status-notstarted': scope.row.status === 2, 'status-end': scope.row.status === 3}"> <p
:class="{
'status-start': scope.row.status === 1,
'status-notstarted': scope.row.status === 0,
'status-end': scope.row.status === 2
}"
>
<i></i> <i></i>
<span style="margin-left: 10px">{{ scope.row.status | statusFilter}}</span> <span style="margin-left: 10px">{{ scope.row.status | statusFilter }}</span>
</p> </p>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="creator" label="创建人" min-width="80"></el-table-column> <el-table-column prop="sso_user.nickname" label="创建人" min-width="100"></el-table-column>
<el-table-column label="操作" min-width="240"> <el-table-column label="操作" width="240">
<template slot-scope="scope"> <template slot-scope="scope">
<p> <table-handles :rowData="scope.row" @refresh="fetchMeetingList"/>
<el-button @click="joinMeeting(scope.row)" type="text" size="small">进入会议</el-button>
<el-button type="text" size="small">观看会议直播</el-button>
<el-button type="text" size="small">复制邀请</el-button>
</p>
<el-button type="text" size="small">查看</el-button>
<el-button type="text" size="small">修改</el-button>
<el-button type="text" size="small">取消</el-button>
<el-button type="text" size="small">终止</el-button>
<el-button type="text" size="small">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -97,51 +102,31 @@ ...@@ -97,51 +102,31 @@
</div> </div>
</template> </template>
<script> <script>
import TableHandles from '@/components/TableHandles/index.vue'
import { dateFormat } from '@/utils/dateAlgs' import { dateFormat } from '@/utils/dateAlgs'
import { searchUserList, getMeetingList } from '@api/common'
import { mapGetters } from 'vuex'
export default { export default {
data() { data() {
return { return {
filter: { filter: {
meetingId: '', meetingId: '',
meetingTitle: '', subject: '',
status: '', status: '',
meetingType: '', userid: '',
timeRange: '' timeRange: ''
}, },
listData: [ searchUsersloading: false,
{ userList: [],
date: new Date(2021, 3, 7, 10, 30, 0).getTime(), listData: [],
endDate: new Date(2021, 3, 8, 8, 0, 0).getTime(),
title: 'CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课CIIS直播课',
isCycle: false,
resource: '腾讯',
status: 1,
creator: '张三丰'
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播索菲亚直播',
isCycle: true,
resource: '腾讯',
status: 2,
creator: '黄飞鸿'
},
{
date: new Date(2021, 10, 7).getTime(),
endDate: new Date(2021, 10, 8).getTime(),
title: '索菲亚直播索菲亚直播',
isCycle: false,
resource: '腾讯',
status: 3,
creator: '楚留香'
}
],
curPage: 1, curPage: 1,
pageSize: 20, pageSize: 20,
total: 200 total: 200
} }
}, },
computed: {
...mapGetters(['user'])
},
filters: { filters: {
dateFormat (value, fmt) { dateFormat (value, fmt) {
return dateFormat(value, fmt) return dateFormat(value, fmt)
...@@ -155,23 +140,63 @@ export default { ...@@ -155,23 +140,63 @@ export default {
case 2: case 2:
result = '已完成' result = '已完成'
break break
case 3: case 0:
result = '未开始' result = '未开始'
break break
} }
return result return result
} }
}, },
components: { TableHandles },
created() {
this.fetchMeetingList()
},
methods: { methods: {
reset() { reset() {
// this.filter
Object.keys(this.filter).map(key => { this.filter[key] = '' }) Object.keys(this.filter).map(key => { this.filter[key] = '' })
this.fetchMeetingList()
},
pageChange() {
this.fetchMeetingList()
}, },
joinMeeting(data) { fetchMeetingList() {
console.log(data) const filter = this.filter
let start, endPlus1
if (filter.length > 0) {
start = dateFormat(filter.timeRange[0])
const end = filter.timeRange[1]
endPlus1 = dateFormat(new Date(end.getFullYear(), end.getMonth(), end.getDate() + 1))
}
const params = {
page: this.curPage,
limit: this.pageSize,
sso_id: filter.userid ? filter.userid : undefined,
status: filter.status ? filter.status : undefined,
meeting_id: filter.meetingId ? filter.meetingId : undefined,
subject: filter.subject ? filter.subject : undefined,
start_time: start,
end_time: endPlus1
}
getMeetingList(params).then((res) => {
if (res.code === 0 && res.data.data) {
this.listData = res.data.data
this.total = res.data.total
}
})
}, },
pageChange(val) { fetchUserList(val) {
console.log(val) if (val) {
const params = {
nickname: val
}
this.searchUsersloading = true;
searchUserList(params).then((res) => {
this.searchUsersloading = false;
if (res.data && Array.isArray(res.data.items)) {
this.userList = res.data.items
}
}).catch(() => {})
}
} }
} }
} }
......
<template> <template>
<div class="account"> <div class="account">
<h5>账号管理 <el-button style="float:right;margin:12px 30px 0 0" size="mini" type="primary" plain @click="dialogVisible = 'add'">添加账号</el-button></h5> <h5>账号管理 <el-button style="float:right;margin:12px 30px 0 0" size="mini" type="primary" plain @click="handleAdd" v-if="isSuperAdmin">添加账号</el-button></h5>
<div class="inner"> <div class="inner">
<el-table :data="listData" style="width: 100%" height="calc(100% - 32px)"> <el-table :data="listData" style="width: 100%" height="calc(100% - 32px)">
<el-table-column prop="id" label="ID" min-width="120"></el-table-column> <el-table-column prop="userid" label="ID" min-width="120"></el-table-column>
<el-table-column prop="name" label="名称" min-width="120"></el-table-column> <el-table-column prop="username" label="名称" min-width="120"></el-table-column>
<el-table-column prop="mobile" label="手机号码" min-width="120"></el-table-column> <el-table-column prop="phone" label="手机号码" min-width="120"></el-table-column>
<el-table-column prop="email" label="邮箱" min-width="120"></el-table-column> <el-table-column prop="email" label="邮箱" min-width="140"></el-table-column>
<el-table-column label="操作" min-width="140"> <el-table-column label="操作" min-width="60">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" size="small" @click="edit(scope.row)">编辑</el-button> <el-button type="text" size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" size="small" @click="dialogVisible = 'delete'">删除</el-button> <el-button type="text" size="small" @click="handleDelete(scope.row.userid)" v-if="isSuperAdmin">删除</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-pagination :current-page.sync="curPage" :page-size="pageSize" layout="total, prev, pager, next" :total="total" @current-change="pageChange" style="float:right;"></el-pagination> <el-pagination :current-page.sync="curPage" :page-size="pageSize" layout="total, prev, pager, next" :total="total" @current-change="pageChange" style="float:right;"></el-pagination>
<el-dialog :title="domicTitle" :visible.sync="dialogVisible" width="30%" center> <el-dialog :title="domicTitle" :visible.sync="dialogVisible" width="30%" center>
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" v-show="dialogVisible === 'add' || dialogVisible === 'edit'"> <el-form :model="form" :rules="rules" ref="ruleForm" label-width="70px" class="demo-ruleForm" v-show="dialogVisible === 'add' || dialogVisible === 'edit'">
<el-form-item label="ID" prop="id"> <el-form-item label="ID" prop="userid" v-if="dialogVisible === 'edit'">
<el-input v-model="form.id"></el-input> <el-input v-model="form.userid" size="small" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="名称" prop="name"> <el-form-item label="ID" prop="userid" v-else>
<el-input v-model="form.name"></el-input> <el-select style="width:100%" v-model="form.userid" placeholder="搜索用户" size="small" filterable remote :remote-method="fetchUserList" :loading="searchUsersloading">
<el-option :label="user.nickname" :value="user.id" v-for="user in userList" :key="user.id" />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="手机号" prop="mobile"> <el-form-item label="名称" prop="username">
<el-input v-model="form.mobile"></el-input> <el-input v-model="form.username" size="small"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="form.phone" size="small"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="邮箱" prop="email"> <el-form-item label="邮箱" prop="email">
<el-input v-model="form.email"></el-input> <el-input v-model="form.email" size="small"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<p v-show="dialogVisible === 'delete'">确认删除此账号吗?</p> <p v-show="dialogVisible === 'delete'">删除此账号,与其相关的会议将被同时删除,确认删除此账号吗?</p>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button type="primary" @click="addAccount" size="mini">确 定</el-button> <el-button type="primary" @click="handleBtn" size="mini">确 定</el-button>
<el-button @click="dialogVisible = null" size="mini">取 消</el-button> <el-button @click="dialogVisible = null" size="mini">取 消</el-button>
</span> </span>
</el-dialog> </el-dialog>
...@@ -40,6 +45,9 @@ ...@@ -40,6 +45,9 @@
</div> </div>
</template> </template>
<script> <script>
import { getAccountList, searchUserList, createAccount, updateAccount, deleteAccount, operateLog } from '@api/common'
import { mapGetters } from 'vuex'
import _ from 'lodash'
export default { export default {
data () { data () {
const MOBILE_REG = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/ const MOBILE_REG = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
...@@ -48,6 +56,8 @@ export default { ...@@ -48,6 +56,8 @@ export default {
if (value) { if (value) {
if (!MOBILE_REG.test(value)) { if (!MOBILE_REG.test(value)) {
callback(new Error('手机号格式错误')); callback(new Error('手机号格式错误'));
} else {
callback()
} }
} }
} }
...@@ -55,44 +65,27 @@ export default { ...@@ -55,44 +65,27 @@ export default {
if (value) { if (value) {
if (!EMAIL_REG.test(value)) { if (!EMAIL_REG.test(value)) {
callback(new Error('邮箱格式错误')); callback(new Error('邮箱格式错误'));
} else {
callback()
} }
} }
} }
return { return {
listData: [ listData: [],
{
id: '1234567890',
name: '张三',
mobile: '13111112222',
email: '1243@qq.com'
},
{
id: '1234567891',
name: '张三',
mobile: '13111112222',
email: '1243@qq.com'
},
{
id: '1234567892',
name: '张三',
mobile: '13111112222',
email: '1243@qq.com'
}
],
curPage: 1, curPage: 1,
pageSize: 20, pageSize: 20,
total: 200, total: 0,
dialogVisible: null, dialogVisible: null,
form: { form: {
id: '', userid: '',
name: '', username: '',
mobile: '', phone: '',
email: '' email: ''
}, },
rules: { rules: {
id: [{ required: true, message: '请输入ID', trigger: 'blur' }], userid: [{ required: true, message: '请输入ID', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }], username: [{ required: true, message: '请输入名称', trigger: 'blur' }],
mobile: [ phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' }, { required: true, message: '请输入手机号', trigger: 'blur' },
{ validator: checkMobile, trigger: 'blur' } { validator: checkMobile, trigger: 'blur' }
], ],
...@@ -100,10 +93,14 @@ export default { ...@@ -100,10 +93,14 @@ export default {
{ required: true, message: '请输入邮箱', trigger: 'blur' }, { required: true, message: '请输入邮箱', trigger: 'blur' },
{ validator: checkEmail, trigger: 'blur' } { validator: checkEmail, trigger: 'blur' }
] ]
} },
searchUsersloading: false,
userList: [],
deleteId: ''
} }
}, },
computed: { computed: {
...mapGetters(['isSuperAdmin']),
domicTitle() { domicTitle() {
let title = '新增' let title = '新增'
switch (this.dialogVisible) { switch (this.dialogVisible) {
...@@ -117,20 +114,117 @@ export default { ...@@ -117,20 +114,117 @@ export default {
return title + '账号' return title + '账号'
} }
}, },
created() {
this.fetchAccountList()
console.log(this.isSuperAdmin)
},
methods: { methods: {
pageChange(val) { handleEdit(data) {
console.log(val) this.form = _.cloneDeep(data)
},
edit(data) {
this.form = data
this.dialogVisible = 'edit' this.dialogVisible = 'edit'
}, },
addAccount() { handleAdd() {
this.$refs.ruleForm.validate((valid) => { for (const key in this.form) {
if (valid) { this.form[key] = ''
console.log('submit!'); }
this.dialogVisible = 'add'
},
handleDelete(id) {
this.dialogVisible = 'delete'
this.deleteId = id
},
pageChange() {
this.fetchRoleList()
},
handleBtn() {
if (this.dialogVisible === 'delete') {
this.fetchDeleteAccount()
} else {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.dialogVisible === 'add' ? this.fetchCreateAccount() : this.fetchUpdateAccount()
}
});
}
this.dialogVisible = false
},
fetchUserList(val) {
if (val) {
const params = {
nickname: val
}
this.searchUsersloading = true;
searchUserList(params).then((res) => {
this.searchUsersloading = false;
if (res.data && Array.isArray(res.data.items)) {
this.userList = res.data.items
}
}).catch(() => {})
}
},
fetchAccountList() {
const params = {
page: this.curPage,
limit: this.pageSize
}
getAccountList(params).then((res) => {
if (res.code === 0 && res.data.data) {
this.listData = res.data.data
this.total = res.data.total
}
})
},
fetchCreateAccount() {
const form = this.form
const params = {
userid: form.userid,
username: form.username,
phone: form.phone,
email: form.email,
type: 1
}
createAccount(params).then((res) => {
if (res.code === 0 && res.data.id) {
this.$message.success('创建账户成功')
this.fetchAccountList()
operateLog({ type: `创建腾讯账号,被创建账户userid:${form.userid}`, user: this.user })
} else {
this.$message.error(res.message || '创建账户失败')
}
})
},
fetchUpdateAccount() {
const form = this.form
const params = {
userid: form.userid,
username: form.username,
phone: form.phone,
email: form.email
}
updateAccount(params).then((res) => {
if (res.code === 0 && res.data.status === true) {
this.$message.success('更新账户成功')
this.fetchAccountList()
operateLog({ type: `更新腾讯账号,被更新账户userid:${form.userid}`, user: this.user })
} else {
this.$message.error(res.message || '更新账户失败')
}
})
},
fetchDeleteAccount() {
const params = {
userid: this.deleteId
}
deleteAccount(params).then((res) => {
if (res.code === 0 && res.data.status === true) {
this.$message.success('删除账户成功')
this.fetchAccountList()
operateLog({ type: `删除腾讯账号,被删除账户userid:${this.deleteId}`, user: this.user })
this.deleteId = ''
} else {
this.$message.error(res.message || '删除账户失败')
} }
}); })
} }
} }
} }
......
<template> <template>
<div class="account"> <div class="account">
<h5>角色管理</h5> <h5>
角色管理
<el-button style="float: right; margin: 12px 30px 0 0" size="mini" type="primary" plain @click="handleAdd"
>添加角色</el-button
>
</h5>
<div class="inner"> <div class="inner">
<el-table :data="listData" style="width: 100%" height="calc(100% - 32px)">
<el-table-column prop="name" label="角色" min-width="140" v-if="!isSuperAdmin"></el-table-column>
<el-table-column prop="display_name" label="角色名称" min-width="120"></el-table-column>
<el-table-column prop="description" label="角色描述" min-width="120"></el-table-column>
<el-table-column prop="updated_at" label="创建时间" min-width="120"></el-table-column>
<el-table-column label="操作" min-width="140">
<template slot-scope="scope">
<el-button type="text" size="small" @click="handleUsers(scope.row)">分配用户</el-button>
<el-button type="text" size="small" @click="handlePermission(scope.row)">设置权限</el-button>
<el-button type="text" size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="text" size="small" @click="handleDelete(scope.row.userid)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page.sync="curPage" :page-size="pageSize" layout="total, prev, pager, next" :total="total" @current-change="pageChange" style="float:right;"></el-pagination>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { getRoles } from '@api/system'
import { mapGetters } from 'vuex'
export default { export default {
data () { data() {
return {} return {
listData: [
{
id: 2,
name: 'general_admin',
display_name: '普通管理员',
description: '拥有超级管理员下的最高权限',
created_at: '2021-04-01 09:38:25',
updated_at: '2021-04-01 09:38:25'
},
{
id: 1,
name: 'administrator',
display_name: '超级管理员',
description: '拥有所有的权限',
created_at: '2021-04-01 09:29:41',
updated_at: '2021-04-01 09:29:41'
}
],
curPage: 1,
pageSize: 20,
total: 0
}
},
computed: {
...mapGetters(['isSuperAdmin'])
},
created() {
this.fetchRoleList()
},
methods: {
handleUsers(val) {
this.$router.push({ path: '/system/roleToUser', query: { id: val.id } })
},
handlePermission(val) {
console.log(val)
},
handleEdit(val) {
console.log(val)
},
handleDelete(val) {
console.log(val)
},
pageChange() {
this.fetchRoleList()
},
fetchRoleList() {
const params = {
page: this.curPage,
limit: this.pageSize
}
getRoles(params).then((res) => {
if (res.code === 0 && res.data.data) {
this.listData = res.data.data
this.total = res.data.total
}
})
}
} }
} }
</script> </script>
<style scoped> <style scoped>
.account{ .account {
height:100%; height: 100%;
} }
h5{ h5 {
font-size: 16px; font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
color:#333; color: #333;
font-weight: 400; font-weight: 400;
line-height:50px; line-height: 50px;
text-indent:40px; text-indent: 40px;
} }
.inner{ .inner {
height: calc(100% - 50px - 10px); height: calc(100% - 50px - 10px);
display:flex; background: #ffffff;
background: #FFFFFF;
border-radius: 10px; border-radius: 10px;
margin:0 16px; margin: 0 16px;
box-sizing:border-box; box-sizing: border-box;
padding:14px 14px 6px; padding: 14px 14px 6px;
} }
</style> </style>
\ No newline at end of file
<template>
<div class="account">
<h5>
角色管理 / 分配用户
<el-button style="float: right; margin: 12px 30px 0 0" size="mini" type="primary" plain @click="handleAdd"
>角色下增加用户</el-button
>
</h5>
<div class="inner">
<el-table :data="listData" style="width: 100%" height="calc(100% - 32px)">
<!-- <el-table-column prop="name" label="角色" min-width="140"></el-table-column> -->
<el-table-column prop="user_info.nickname" label="用户昵称" min-width="120"></el-table-column>
<el-table-column prop="user_info.id" label="用户ID" min-width="120"></el-table-column>
<el-table-column prop="user_info.mobile" label="手机号" min-width="120"></el-table-column>
<el-table-column prop="user_info.email" label="邮箱" min-width="120"></el-table-column>
<el-table-column label="操作" min-width="140">
<template slot-scope="scope">
<el-button type="text" size="small" @click="handleDelete(scope.row.userid)">从角色下删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
listData: [
{
created_at: '2021-04-01 10:45:38',
updated_at: '2021-04-01 10:45:38',
user_info: {
id: '6653195831513972736',
username: 'ZJ6653195831513972736',
email: 'wangyizheng@ezijing.com',
mobile: '18435134258',
wechat_unionid: 'oJ6hPszybKN83GkWbvaY33q4oeIo',
nickname: 'sdagads',
country_code: '86',
id_number: null,
user_id: '6653195831513972736',
gender: '0',
province: null,
city: null,
county: null,
company_name: null,
position: null,
personal_signature: null,
phone: null,
qq: null,
wechat: null,
weibo: null,
tencent_weibo: null,
org: null,
real_name: 'sdagads',
highest_degree: null,
major: null,
birthday: null,
channel_code: null,
created_time: '2020-04-07 15:44:57',
updated_time: '2020-08-26 17:12:10',
status: '0',
avatar: null,
realname: 'sdagads'
}
}
]
}
},
methods: {
handleAdd() {},
handleUsers(val) {
console.log(val)
},
handlePermission(val) {
console.log(val)
},
handleEdit(val) {
console.log(val)
},
handleDelete(val) {
console.log(val)
}
}
}
</script>
<style scoped>
.account {
height: 100%;
}
h5 {
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
color: #333;
font-weight: 400;
line-height: 50px;
text-indent: 40px;
}
.inner {
height: calc(100% - 50px - 10px);
display: flex;
background: #ffffff;
border-radius: 10px;
margin: 0 16px;
box-sizing: border-box;
padding: 14px 14px 6px;
}
</style>
\ No newline at end of file
...@@ -18,6 +18,18 @@ export default [ ...@@ -18,6 +18,18 @@ export default [
} }
] ]
}, },
{
path: '/meeting-test',
component: Layout,
children: [
{
path: '',
component: () => import('@/pages/meeting/index-test.vue'),
name: 'MeetingCreate',
meta: { title: '创建直播', affix: true }
}
]
},
{ {
path: '/calendar', path: '/calendar',
component: Layout, component: Layout,
...@@ -43,6 +55,12 @@ export default [ ...@@ -43,6 +55,12 @@ export default [
component: () => import('@/pages/system/role/index'), component: () => import('@/pages/system/role/index'),
meta: { title: '角色管理', icon: 'el-icon-s-check' } meta: { title: '角色管理', icon: 'el-icon-s-check' }
}, },
{
path: 'roleToUser',
name: 'RoleToUser',
component: () => import('@/pages/system/role/roleToUser/index'),
meta: { title: '管理角色用户', icon: '' }
},
{ {
path: 'account', path: 'account',
name: 'Account', name: 'Account',
......
const getters = { const getters = {
token: state => state.user.token, user: state => state.user.user,
roles: state => state.user.roles,
isSuperAdmin: state => state.user.isSuperAdmin,
sidebar: state => state.app.sidebar sidebar: state => state.app.sidebar
} }
export default getters export default getters
...@@ -4,7 +4,6 @@ import app from './modules/app' ...@@ -4,7 +4,6 @@ import app from './modules/app'
import user from './modules/user' import user from './modules/user'
import getters from './getters' import getters from './getters'
// import { getUser, logout } from '@/api/account'
Vue.use(Vuex) Vue.use(Vuex)
const store = new Vuex.Store({ const store = new Vuex.Store({
...@@ -17,58 +16,3 @@ const store = new Vuex.Store({ ...@@ -17,58 +16,3 @@ const store = new Vuex.Store({
}) })
export default store export default store
/* const store = new Vuex.Store({
state: {
user: {},
isLogin: false
},
mutations: {
setUser(state, user) {
state.user = user
},
setIsLogin(state, isLogin) {
state.isLogin = isLogin
},
TOGGLE_SIDEBAR: state => {
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
}
},
actions: {
getUser({ commit }) {
getUser().then(response => {
commit('setUser', response)
})
},
// 退出登录
logout({ commit }) {
return logout().then(response => {
commit('setUser', {})
commit('setIsLogin', false)
return response
})
},
// 检测登录状态
async checkLogin({ commit }) {
const isLogin = await getUser()
.then(response => {
commit('setUser', response)
return true
})
.catch(() => {
commit('setUser', {})
return false
})
commit('setIsLogin', isLogin)
return isLogin
}
}
})
export default store
*/
import { getUser, logout } from '@/api/account' import { getUser, logout } from '@/api/account'
import { getUserRoles } from '@/api/system'
const user = { const user = {
state: { state: {
user: {}, user: {},
isLogin: false roles: [],
isLogin: false,
isSuperAdmin: false
}, },
mutations: { mutations: {
...@@ -11,6 +14,12 @@ const user = { ...@@ -11,6 +14,12 @@ const user = {
}, },
setIsLogin(state, isLogin) { setIsLogin(state, isLogin) {
state.isLogin = isLogin state.isLogin = isLogin
},
setRoles(state, roles) {
state.roles = roles
},
setSuperAdmin(state, isSuperAdmin) {
state.isSuperAdmin = isSuperAdmin
} }
}, },
...@@ -20,6 +29,19 @@ const user = { ...@@ -20,6 +29,19 @@ const user = {
commit('setUser', response) commit('setUser', response)
}) })
}, },
setUserRoles({ commit }) {
getUserRoles().then(res => {
const roles = res.data.roles
let isSuperAdmin = false
if (roles && Array.isArray(roles)) {
roles.forEach(it => {
if (it.name === 'administrator') isSuperAdmin = true
})
commit('setRoles', roles)
commit('setSuperAdmin', isSuperAdmin)
}
})
},
// 退出登录 // 退出登录
logout({ commit }) { logout({ commit }) {
return logout().then(response => { return logout().then(response => {
......
import axios from 'axios' import axios from 'axios'
import qs from 'qs' import qs from 'qs'
import { Message } from 'element-ui' import { Message } from 'element-ui'
import { getNonce } from '@/utils/utils'
import router from '@/router' import router from '@/router'
const httpRequest = axios.create({ const httpRequest = axios.create({
timeout: 60000, timeout: 60000,
withCredentials: true, withCredentials: true,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' } headers: { 'Content-Type': 'application/json' }
}) })
// 请求拦截 // 请求拦截
httpRequest.interceptors.request.use( httpRequest.interceptors.request.use(
function(config) { function(config) {
const defaultParams = {
timestamp: parseInt(Date.now() / 1000),
nonce: getNonce(9),
signature: 'UG7wBenexQhiuD2wpCwuxkU0jqcj006d'
}
let params = config.params || config.data
params = Object.assign({}, defaultParams, params)
if (['post', 'put', 'delete'].includes(config.method)) {
config.data = params
} else {
config.params = params
}
if (config.headers['Content-Type'] === 'application/x-www-form-urlencoded') { if (config.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
config.data = qs.stringify(config.data) config.data = qs.stringify(config.data)
} }
...@@ -25,8 +38,9 @@ httpRequest.interceptors.request.use( ...@@ -25,8 +38,9 @@ httpRequest.interceptors.request.use(
httpRequest.interceptors.response.use( httpRequest.interceptors.response.use(
function(response) { function(response) {
const { data } = response const { data } = response
if (data.code) { if (data.code === 1 && data.msg === '请先登录') {
Message.error(data.msg || data.message) // Message.error(data.msg || data.message)
window.location.href = `${webConf.others.loginUrl}?rd=${encodeURIComponent(window.location.href)}`
return Promise.reject(data) return Promise.reject(data)
} }
return data return data
......
...@@ -11,6 +11,7 @@ export default class BeforeEnter { ...@@ -11,6 +11,7 @@ export default class BeforeEnter {
next(`/login?redirect_uri=${encodeURIComponent(window.location.href)}`) next(`/login?redirect_uri=${encodeURIComponent(window.location.href)}`)
return return
} }
store.dispatch('setUserRoles')
next() next()
} }
} }
...@@ -28,19 +28,7 @@ export function timeTrans(time) { ...@@ -28,19 +28,7 @@ export function timeTrans(time) {
} }
return date return date
} }
/**
* 获取随机字符串
* @returns {String}
*/
export function nounceStr() {
const chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
let str = ''
for (let i = 0; i < 16; i++) {
const idx = parseInt(36 * Math.random())
str += chars[idx]
}
return str
}
/** /**
* 获取一天内从某小时至某小时结束的时间点 * 获取一天内从某小时至某小时结束的时间点
* @param {number} start * @param {number} start
...@@ -117,9 +105,17 @@ export function getCurHalfHourDate(type, date) { ...@@ -117,9 +105,17 @@ export function getCurHalfHourDate(type, date) {
* @param {(Object|string|number)} date * @param {(Object|string|number)} date
* @returns {Date Object} * @returns {Date Object}
*/ */
export function getTimestampYMD(date) { export function getYMDByDate(date) {
date = timeTrans(date) date = timeTrans(date)
return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() return new Date(date.getFullYear(), date.getMonth(), date.getDate())
}
/**
* 将日期转换为年月日整时
* @param {(Object|string|number)} date
* @returns {Date Object}
*/
export function getTimestampYMD(date) {
return getYMDByDate(date).getTime()
} }
/** /**
* 获取从起始日之后的N个月范围的日期 * 获取从起始日之后的N个月范围的日期
...@@ -218,27 +214,27 @@ export function computedDateByRateTimes(startDate, times, repeatRate) { ...@@ -218,27 +214,27 @@ export function computedDateByRateTimes(startDate, times, repeatRate) {
let endTime let endTime
startDate = timeTrans(startDate) startDate = timeTrans(startDate)
switch (repeatRate) { switch (repeatRate) {
case 'everyday': { case 0: {
rangeTimeStamp = (times - 1) * dayTimeStamp rangeTimeStamp = (times - 1) * dayTimeStamp
endTime = Date.parse(startDate) + rangeTimeStamp endTime = Date.parse(startDate) + rangeTimeStamp
break break
} }
case 'everyworkday': { case 1: {
const dateArr = recentWeekdays(times, startDate) const dateArr = recentWeekdays(times, startDate)
endTime = dateArr[dateArr.length - 1] endTime = dateArr[dateArr.length - 1]
break break
} }
case 'everyweek': { case 2: {
rangeTimeStamp = (times - 1) * 7 * dayTimeStamp rangeTimeStamp = (times - 1) * 7 * dayTimeStamp
endTime = Date.parse(startDate) + rangeTimeStamp endTime = Date.parse(startDate) + rangeTimeStamp
break break
} }
case 'every2weeks': { case 3: {
rangeTimeStamp = (times - 1) * 14 * dayTimeStamp rangeTimeStamp = (times - 1) * 14 * dayTimeStamp
endTime = Date.parse(startDate) + rangeTimeStamp endTime = Date.parse(startDate) + rangeTimeStamp
break break
} }
case 'everymonth': { case 4: {
endTime = getDateByMouths(startDate, times) endTime = getDateByMouths(startDate, times)
break break
} }
...@@ -268,23 +264,23 @@ export function computedTimesByRateDate(startDate, endDate, repeatRate) { ...@@ -268,23 +264,23 @@ export function computedTimesByRateDate(startDate, endDate, repeatRate) {
const rangeTimeStamp = getTimestampYMD(endDate) - getTimestampYMD(startDate) const rangeTimeStamp = getTimestampYMD(endDate) - getTimestampYMD(startDate)
let times = 0 let times = 0
switch (repeatRate) { switch (repeatRate) {
case 'everyday': { case 0: {
times = rangeTimeStamp / dayTimeStamp + 1 times = rangeTimeStamp / dayTimeStamp + 1
break break
} }
case 'everyworkday': { case 1: {
times = rangeCount(timeTrans(startDate), timeTrans(endDate)) times = rangeCount(timeTrans(startDate), timeTrans(endDate))
break break
} }
case 'everyweek': { case 2: {
times = rangeTimeStamp / (dayTimeStamp * 7) + 1 times = rangeTimeStamp / (dayTimeStamp * 7) + 1
break break
} }
case 'every2weeks': { case 3: {
times = rangeTimeStamp / (dayTimeStamp * 14) + 1 times = rangeTimeStamp / (dayTimeStamp * 14) + 1
break break
} }
case 'everymonth': { case 4: {
times = getMonthsByDate(startDate, endDate) times = getMonthsByDate(startDate, endDate)
break break
} }
......
/**
* 获取随机字符串
* @param {number} length
* @returns {String}
*/
export function getNonce(length) {
typeof length !== 'number' && (length = 16)
const chars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'k', 'm', 'n', 'p', 'r', 's', 't', 'w', 'x', 'y', 'z', 2, 3, 4, 5, 6, 7, 8]
const charsLen = chars.length;
let str = ''
for (let i = 0; i < length; i++) {
const idx = parseInt(charsLen * Math.random())
let _char = chars[idx];
if (typeof _char === 'string' && idx % 2) {
_char = _char.toUpperCase()
}
str += _char
}
return str
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论