feat:跟新组织架构
9
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.0.10",
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
|
"@msgpack/msgpack": "^3.1.2",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"code-inspector-plugin": "^0.20.12",
|
"code-inspector-plugin": "^0.20.12",
|
||||||
@@ -602,6 +603,14 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@msgpack/msgpack": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@msgpack/msgpack/-/msgpack-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.0.10",
|
"@element-plus/icons-vue": "^2.0.10",
|
||||||
|
"@msgpack/msgpack": "^3.1.2",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"code-inspector-plugin": "^0.20.12",
|
"code-inspector-plugin": "^0.20.12",
|
||||||
|
|||||||
19
src/api/coordinate.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 获取组织列表
|
||||||
|
export function getDirectories(data) {
|
||||||
|
return request({
|
||||||
|
url: `/api/v1/auth/directories`,
|
||||||
|
method: 'get',
|
||||||
|
params:data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取指定目录下的用户列表
|
||||||
|
export function getDirectoriesUsers(directory_uuid,data) {
|
||||||
|
return request({
|
||||||
|
url: `/api/v1/auth/directories/${directory_uuid}/users`,
|
||||||
|
method: 'get',
|
||||||
|
params:data
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ export function login(username, password) {
|
|||||||
// 获取用户详细信息
|
// 获取用户详细信息
|
||||||
export function getInfo(userUid) {
|
export function getInfo(userUid) {
|
||||||
return request({
|
return request({
|
||||||
url: `/api/v1/auth/user/${userUid}`,
|
url: `/api/v1/auth/users/${userUid}`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/assets/images/cooponents-tab1.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/images/cooponents-tab2.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/images/cooponents-tab3.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/assets/images/cooponents-tab4.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/assets/images/profile.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/images/user-information1.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/assets/images/user-information2.png
Normal file
|
After Width: | Height: | Size: 535 B |
BIN
src/assets/images/user-information3.png
Normal file
|
After Width: | Height: | Size: 939 B |
BIN
src/assets/images/user-information4.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/images/userlist-icon1.png
Normal file
|
After Width: | Height: | Size: 676 B |
BIN
src/assets/images/userlist-icon2.png
Normal file
|
After Width: | Height: | Size: 777 B |
@@ -20,6 +20,16 @@ const router = createRouter({
|
|||||||
path: "/login",
|
path: "/login",
|
||||||
component: () => import("@/views/login.vue"),
|
component: () => import("@/views/login.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/coordinate",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: "Coordinate",
|
||||||
|
component: () => import("@/views/coordinate/personnelList/index.vue")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
// 错误页面路由
|
// 错误页面路由
|
||||||
{
|
{
|
||||||
path: "/:pathMatch(.*)*",
|
path: "/:pathMatch(.*)*",
|
||||||
|
|||||||
@@ -33,13 +33,14 @@ class MQTTClient {
|
|||||||
this.client.on("error", (error) => reject(error))
|
this.client.on("error", (error) => reject(error))
|
||||||
|
|
||||||
// 消息分发
|
// 消息分发
|
||||||
this.client.on("message", (topic, payload) => {
|
this.client.on("message", (topic, payload) => {
|
||||||
try {
|
try {
|
||||||
const message = JSON.parse(payload.toString())
|
// const message = JSON.parse(payload.toString())
|
||||||
// 遍历所有订阅主题,执行通配符匹配
|
// 遍历所有订阅主题,执行通配符匹配
|
||||||
this.messageHandlers.forEach((handlers, subTopic) => {
|
this.messageHandlers.forEach((handlers, subTopic) => {
|
||||||
if (this.topicMatch(subTopic, topic)) {
|
if (this.topicMatch(subTopic, topic)) {
|
||||||
handlers.forEach((handler) => handler(message, topic))
|
// handlers.forEach((handler) => handler(message, topic))
|
||||||
|
handlers.forEach((handler) => handler(payload, topic))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -99,11 +99,13 @@ service.interceptors.request.use(
|
|||||||
|
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
|
console.log(response,'response')
|
||||||
// 1. 检查响应是否存在
|
// 1. 检查响应是否存在
|
||||||
if (!response) {
|
if (!response) {
|
||||||
ElMessage.error('无响应数据');
|
ElMessage.error('无响应数据');
|
||||||
return Promise.reject(new Error('无响应数据'));
|
return Promise.reject(new Error('无响应数据'));
|
||||||
}
|
}
|
||||||
|
console.log(response.data,'response.data')
|
||||||
// 2. 安全获取响应数据和状态码
|
// 2. 安全获取响应数据和状态码
|
||||||
const responseData = response.data || {};
|
const responseData = response.data || {};
|
||||||
const statusCode = response.status;
|
const statusCode = response.status;
|
||||||
@@ -124,6 +126,7 @@ service.interceptors.response.use(
|
|||||||
return Promise.resolve(responseData);
|
return Promise.resolve(responseData);
|
||||||
|
|
||||||
case 401:
|
case 401:
|
||||||
|
console.log('未授权', responseData)
|
||||||
return handleUnauthorized().then(() => {
|
return handleUnauthorized().then(() => {
|
||||||
return Promise.reject({ code: 401, message: '未授权' });
|
return Promise.reject({ code: 401, message: '未授权' });
|
||||||
});
|
});
|
||||||
@@ -143,6 +146,13 @@ service.interceptors.response.use(
|
|||||||
console.error('请求错误:', error);
|
console.error('请求错误:', error);
|
||||||
let { message } = error;
|
let { message } = error;
|
||||||
let code = error?.response?.status || -1;
|
let code = error?.response?.status || -1;
|
||||||
|
console.log(code,'code')
|
||||||
|
|
||||||
|
if(code == 401) {
|
||||||
|
return handleUnauthorized().then(() => {
|
||||||
|
return Promise.reject({ code: 401, message: '未授权' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (message == 'Network Error') {
|
if (message == 'Network Error') {
|
||||||
message = '后端接口连接异常';
|
message = '后端接口连接异常';
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { mqttClient } from "./mqtt";
|
import { mqttClient } from "./mqtt";
|
||||||
import { getWhiteboardShapes, getWhiteboardHistory } from "@/views/custom/api";
|
import { getWhiteboardShapes, getWhiteboardHistory } from "@/views/custom/api";
|
||||||
import { useMeterStore } from '@/stores/modules/meter';
|
import { useMeterStore } from '@/stores/modules/meter';
|
||||||
|
import { encode, decode } from '@msgpack/msgpack'
|
||||||
|
|
||||||
const meterStore = useMeterStore();
|
const meterStore = useMeterStore();
|
||||||
meterStore.initUdid();
|
meterStore.initUdid();
|
||||||
@@ -42,12 +43,15 @@ export const WhiteboardSync = {
|
|||||||
|
|
||||||
// 订阅当前房间
|
// 订阅当前房间
|
||||||
const topic = `xSynergy/ROOM/${roomUid}/whiteboard/#`;
|
const topic = `xSynergy/ROOM/${roomUid}/whiteboard/#`;
|
||||||
mqttClient.subscribe(topic, async (shapeData) => {
|
mqttClient.subscribe(topic, async (shapeData) => {
|
||||||
|
// console.log(shapeData, 'shapeData++格式装换')
|
||||||
|
const shapeDataNew = decode(shapeData);
|
||||||
|
// console.log(shapeDataNew, '格式解码')
|
||||||
try {
|
try {
|
||||||
isRemote = true;
|
isRemote = true;
|
||||||
// 如果 shape 来自本地用户,则跳过
|
// 如果 shape 来自本地用户,则跳过
|
||||||
if (shapeData.user_uid === localUid) return;
|
if (shapeDataNew.user_uid === localUid) return;
|
||||||
const res = await getWhiteboardHistory({ after_timestamp: shapeData.created_at }, roomUid);
|
const res = await getWhiteboardHistory({ after_timestamp: shapeDataNew.created_at }, roomUid);
|
||||||
if (res.meta.code === 200) {
|
if (res.meta.code === 200) {
|
||||||
canvasInstance.addShape(res.data.shapes);
|
canvasInstance.addShape(res.data.shapes);
|
||||||
} else {
|
} else {
|
||||||
@@ -62,7 +66,7 @@ export const WhiteboardSync = {
|
|||||||
|
|
||||||
console.log("✅ 已订阅:", topic);
|
console.log("✅ 已订阅:", topic);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("初始化多人同步失败:",err)
|
console.log("初始化多人同步失败:", err)
|
||||||
// console.error("❌ 连接或订阅失败:", err);
|
// console.error("❌ 连接或订阅失败:", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +76,9 @@ export const WhiteboardSync = {
|
|||||||
if (isRemote || !['pencil', 'line', 'rectangle', 'circle', 'eraser'].includes(shape.type)) return;
|
if (isRemote || !['pencil', 'line', 'rectangle', 'circle', 'eraser'].includes(shape.type)) return;
|
||||||
|
|
||||||
// 如果是本地用户自己的 shape,则不调用接口
|
// 如果是本地用户自己的 shape,则不调用接口
|
||||||
if (shape.user_uid && shape.user_uid === localUid) return;
|
if (shape.user_uid && shape.user_uid === localUid) return;
|
||||||
|
|
||||||
shape.room_uid = roomUid;
|
|
||||||
|
|
||||||
|
shape.room_uid = roomUid;
|
||||||
try {
|
try {
|
||||||
await getWhiteboardShapes(shape, roomUid);
|
await getWhiteboardShapes(shape, roomUid);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -85,7 +88,7 @@ export const WhiteboardSync = {
|
|||||||
|
|
||||||
// 监听画布事件:清空
|
// 监听画布事件:清空
|
||||||
canvas.on('clear', async () => {
|
canvas.on('clear', async () => {
|
||||||
if (!isRemote) {
|
if (!isRemote) {
|
||||||
try {
|
try {
|
||||||
// TODO: 调用接口,后端再发 MQTT
|
// TODO: 调用接口,后端再发 MQTT
|
||||||
// await clearWhiteboard(roomUid);
|
// await clearWhiteboard(roomUid);
|
||||||
|
|||||||
596
src/views/coordinate/personnelList/components/leftTab/index.vue
Normal file
@@ -0,0 +1,596 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- v-loading="leftListLoading || loading" -->
|
||||||
|
<div class="left-list" v-loading="leftListLoading || loading">
|
||||||
|
<div class="list-tab">
|
||||||
|
<div
|
||||||
|
:class="'list-tab-item ' + (leftTab == 1 ? 'pitch-on' : '')"
|
||||||
|
@click="() => (leftTab = 1)"
|
||||||
|
>
|
||||||
|
<img src="@/assets/images/cooponents-tab3.png" v-if="leftTab == 1" />
|
||||||
|
<img src="@/assets/images/cooponents-tab4.png" v-else />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="'list-tab-item ' + (leftTab == 2 ? 'pitch-on' : '')"
|
||||||
|
@click="() => (leftTab = 2)"
|
||||||
|
>
|
||||||
|
<img src="@/assets/images/cooponents-tab2.png" v-if="leftTab == 2" />
|
||||||
|
<img src="@/assets/images/cooponents-tab1.png" v-else />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list-content">
|
||||||
|
<div class="content-top-input">
|
||||||
|
<el-input
|
||||||
|
v-model="queryFrom.nickName"
|
||||||
|
placeholder="搜索成员"
|
||||||
|
type="text"
|
||||||
|
prefix-icon="Search"
|
||||||
|
@change="searchList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="content-datapicker" v-if="leftTab == 1">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryFrom.leftDatePicker"
|
||||||
|
type="datetimerange"
|
||||||
|
:shortcuts="shortcuts"
|
||||||
|
range-separator="到"
|
||||||
|
start-placeholder="开始时间"
|
||||||
|
end-placeholder="结束时间"
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm"
|
||||||
|
@change="searchList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-scrollbar class="left-list-scrollbar" v-if="isShow && leftTab == 1">
|
||||||
|
<div
|
||||||
|
class="content-list"
|
||||||
|
v-infinite-scroll="infinite"
|
||||||
|
v-if="dataList?.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in dataList"
|
||||||
|
:key="index"
|
||||||
|
class="content-list-item"
|
||||||
|
@click="updateDetail(item)"
|
||||||
|
:style="
|
||||||
|
item.assistanceId == assistanceId
|
||||||
|
? 'border-color: #409EFF; '
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="list-item-top">
|
||||||
|
<span>
|
||||||
|
{{ parseTime(item.beginTime, '{m}月{d}日') }}
|
||||||
|
{{ weekName[new Date(item.beginTime).getDay()] }}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{{ parseTime(item.beginTime, '{y}年') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="list-item-content">
|
||||||
|
<div class="list-item-content-text">
|
||||||
|
<div style="display: flex; flex-wrap: wrap">
|
||||||
|
<span
|
||||||
|
v-for="(items, indexs) in item.assistanceMemberList"
|
||||||
|
:key="indexs"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
items.nickName +
|
||||||
|
(indexs + 1 == item.assistanceMemberList.length
|
||||||
|
? ''
|
||||||
|
: '、')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
发起人:{{ item.initiatorName ? item.initiatorName : '' }}
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
时间:{{
|
||||||
|
parseTime(item.beginTime, '{h}:{i}') +
|
||||||
|
' ~ ' +
|
||||||
|
(item.endTime ? parseTime(item.endTime, '{h}:{i}') : '')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center" v-if="dataList?.length">
|
||||||
|
<p v-if="more">Loading...</p>
|
||||||
|
<p v-else>No more</p>
|
||||||
|
</div>
|
||||||
|
<div v-else class="list-empty">
|
||||||
|
<el-empty description="暂无记录" />
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
<div v-if="!isShow && leftTab == 1" class="list-empty">
|
||||||
|
<el-empty description="暂无记录" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-scrollbar
|
||||||
|
class="left-list-scrollbar1"
|
||||||
|
height="calc(100vh - 120px)"
|
||||||
|
v-if="leftTab == 2"
|
||||||
|
>
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
lazy
|
||||||
|
:load="HandleLoadNode"
|
||||||
|
:filter-node-method="filterNode"
|
||||||
|
highlight-current
|
||||||
|
:props="treeProps"
|
||||||
|
style="width: 100%"
|
||||||
|
@node-click="updateDetail"
|
||||||
|
>
|
||||||
|
<template #default="{ data }">
|
||||||
|
<div class="tree-item">
|
||||||
|
{{ data.name }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
// getAssistanceList,
|
||||||
|
getDirectories,
|
||||||
|
getDirectoriesUsers
|
||||||
|
} from '@/api/coordinate.js'
|
||||||
|
import { nextTick, reactive, toRefs, watch, onMounted } from 'vue'
|
||||||
|
|
||||||
|
// 接收 props
|
||||||
|
const props = defineProps({
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义 emit
|
||||||
|
const emit = defineEmits(['updateDetail', 'updateTab'])
|
||||||
|
|
||||||
|
// state
|
||||||
|
const state = reactive({
|
||||||
|
isFirst: true,
|
||||||
|
leftTab: 2,
|
||||||
|
queryFrom: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
nickName: '',
|
||||||
|
leftDatePicker: null,
|
||||||
|
},
|
||||||
|
leftListLoading: true,
|
||||||
|
loading: false,
|
||||||
|
dataList: [],
|
||||||
|
more: false,
|
||||||
|
isShow: false,
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: '本周',
|
||||||
|
value: () => {
|
||||||
|
const now = new Date()
|
||||||
|
const nowDaty = now.getDay()
|
||||||
|
const start = new Date(now)
|
||||||
|
start.setDate(now.getDate() - nowDaty)
|
||||||
|
const end = new Date(start)
|
||||||
|
end.setDate(start.getDate() + 6)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最近三周',
|
||||||
|
value: () => {
|
||||||
|
const now = new Date()
|
||||||
|
const nowDaty = now.getDay()
|
||||||
|
let end = new Date(now)
|
||||||
|
end.setDate(now.getDate() + (6 - nowDaty))
|
||||||
|
const start = new Date(end)
|
||||||
|
start.setDate(start.getDate() - 20)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '本月',
|
||||||
|
value: () => {
|
||||||
|
const now = new Date()
|
||||||
|
const start = new Date(now.getFullYear(), now.getMonth(), 1)
|
||||||
|
const end = new Date(now.getFullYear(), now.getMonth() + 1, 0)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
weekName: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
||||||
|
treeRef: null,
|
||||||
|
|
||||||
|
treeProps: {
|
||||||
|
children: 'users',
|
||||||
|
label: 'name',
|
||||||
|
value: 'uid',
|
||||||
|
isLeaf: (node) => {
|
||||||
|
if(node.uid) return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
assistanceId: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树状列表筛选
|
||||||
|
*/
|
||||||
|
const filterNode = (value, data) => {
|
||||||
|
if (!value) return true
|
||||||
|
return data.name.includes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索框变化
|
||||||
|
*/
|
||||||
|
const searchList = () => {
|
||||||
|
if (state.leftTab == 1) {
|
||||||
|
state.queryFrom.pageNum = 1
|
||||||
|
state.dataList = []
|
||||||
|
getList()
|
||||||
|
} else {
|
||||||
|
console.log('treeRef.filter',state.treeRef)
|
||||||
|
state.treeRef.filter(state.queryFrom.nickName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 变更详情
|
||||||
|
*/
|
||||||
|
const updateDetail = (item) => {
|
||||||
|
if (state.leftTab == 1) {
|
||||||
|
state.assistanceId = item.assistanceId
|
||||||
|
emit('updateDetail', item)
|
||||||
|
} else {
|
||||||
|
if (item.uid) {
|
||||||
|
emit('updateDetail', item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触底加载
|
||||||
|
*/
|
||||||
|
// const infinite = () => {
|
||||||
|
// if (state.more) {
|
||||||
|
// state.queryFrom.pageNum++
|
||||||
|
// getList()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协作记录
|
||||||
|
*/
|
||||||
|
const getList = async () => {
|
||||||
|
try {
|
||||||
|
state.leftListLoading = true
|
||||||
|
|
||||||
|
let query = structuredClone(state.queryFrom)
|
||||||
|
if (query.leftDatePicker?.length) {
|
||||||
|
query.beginSignTime = query.leftDatePicker[0]
|
||||||
|
query.endSignTime = query.leftDatePicker[1]
|
||||||
|
}
|
||||||
|
delete query.leftDatePicker
|
||||||
|
|
||||||
|
let infoData = await getAssistanceList({ ...query })
|
||||||
|
|
||||||
|
state.dataList = infoData.rows.length
|
||||||
|
? state.dataList.concat(infoData.rows)
|
||||||
|
: []
|
||||||
|
|
||||||
|
if (state.isFirst) {
|
||||||
|
emit('updateDetail', state.dataList.length ? state.dataList[0] : null)
|
||||||
|
state.assistanceId = state.dataList.length
|
||||||
|
? state.dataList[0].assistanceId
|
||||||
|
: ''
|
||||||
|
state.isFirst = false
|
||||||
|
}
|
||||||
|
|
||||||
|
state.more = state.dataList.length < infoData.total
|
||||||
|
state.isShow = Boolean(state.dataList.length)
|
||||||
|
state.leftListLoading = false
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
state.leftListLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通讯录 人员信息树
|
||||||
|
*/
|
||||||
|
const HandleLoadNode = async (node, resolve) => {
|
||||||
|
if(node.level === 0){
|
||||||
|
loadNode(resolve)
|
||||||
|
}else if(node.level === 1){
|
||||||
|
loadNode(resolve,node.data.directory_uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadNode = async(resolve,id)=>{
|
||||||
|
try {
|
||||||
|
state.leftListLoading = true
|
||||||
|
if(!id){
|
||||||
|
let res = await getDirectories({level:1})
|
||||||
|
resolve(res.data)
|
||||||
|
}else{
|
||||||
|
let res = await getDirectoriesUsers(id,{directory_uuid:id})
|
||||||
|
resolve(res.data)
|
||||||
|
}
|
||||||
|
state.leftListLoading = false
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
state.leftListLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// if (userList.data.sub_units?.length) {
|
||||||
|
// state.dataList = userList.data.sub_units
|
||||||
|
// let user = getUser(state.dataList)
|
||||||
|
// emit('updateDetail', user)
|
||||||
|
// } else {
|
||||||
|
// emit('updateDetail', null)
|
||||||
|
// }
|
||||||
|
// state.leftListLoading = false
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const getUser = (list) => {
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (list[i].type == 2) {
|
||||||
|
return list[i]
|
||||||
|
} else if (list[i].children?.length) {
|
||||||
|
let user = getUser(list[i].children)
|
||||||
|
if (user != null) {
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听 props.loading
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.loading,
|
||||||
|
(newValue) => {
|
||||||
|
state.loading = newValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听 tab 切换
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => state.leftTab,
|
||||||
|
(newValue) => {
|
||||||
|
emit('updateTab', newValue)
|
||||||
|
state.dataList = []
|
||||||
|
state.isFirst = true
|
||||||
|
state.queryFrom = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
nickName: '',
|
||||||
|
leftDatePicker: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue == 1) {
|
||||||
|
state.isShow = false
|
||||||
|
getList()
|
||||||
|
} else {
|
||||||
|
HandleLoadNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
state.dataList = []
|
||||||
|
state.isFirst = true
|
||||||
|
// getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暴露给模板
|
||||||
|
*/
|
||||||
|
const {
|
||||||
|
isFirst, leftTab, queryFrom, leftListLoading, loading,
|
||||||
|
dataList, more, isShow, shortcuts, weekName,
|
||||||
|
treeRef, treeProps, assistanceId
|
||||||
|
} = toRefs(state)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-list {
|
||||||
|
display: flex;
|
||||||
|
height: calc(100vh - 40px);
|
||||||
|
|
||||||
|
.list-tab {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
.list-tab-item {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-content {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
width: calc(100% - 56px);
|
||||||
|
box-shadow: 0px 5px 15px 0px rgba(153, 153, 153, 0.3);
|
||||||
|
|
||||||
|
.content-top-input {
|
||||||
|
@extend .flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 6px 20px;
|
||||||
|
background: #167bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-datapicker {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-list-scrollbar {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 170px);
|
||||||
|
padding: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-list-scrollbar1 {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 120px);
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-list-item {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border: 1.5px solid #c9d4e6;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.list-item-top {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 0 13px;
|
||||||
|
background: #c9d4e6;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #333333;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item-content {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 13px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 27px;
|
||||||
|
height: 27px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item-content-text {
|
||||||
|
@extend .flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
div {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 6px;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-empty {
|
||||||
|
@extend .flex;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 170px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-item {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
height: 45px;
|
||||||
|
|
||||||
|
.tree-item-img1 {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-item-text1 {
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.tree-item-text2 {
|
||||||
|
color: #333333;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.tree-item-text3 {
|
||||||
|
margin-left: 15px;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-tree-node__content {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .list-content .el-input__wrapper {
|
||||||
|
height: 38px;
|
||||||
|
border-radius: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .content-datapicker .el-date-editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background: #e6f1ff;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .left-list-scrollbar .el-scrollbar__wrap {
|
||||||
|
height: calc(100vh - 170px);
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .left-list-scrollbar1 .el-scrollbar__wrap {
|
||||||
|
height: calc(100vh - 120px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
755
src/views/coordinate/personnelList/index.vue
Normal file
@@ -0,0 +1,755 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container" v-loading="load" :element-loading-text="loadText">
|
||||||
|
<el-row :gutter="6" style="padding: 0 10px; background: #fefefe">
|
||||||
|
<el-col :xs="24" :sm="24" :md="8" :lg="6">
|
||||||
|
<leftTab
|
||||||
|
@updateDetail="updateDetail"
|
||||||
|
@updateTab="updateTab"
|
||||||
|
:loading="!detail?.appId && !detail?.userId && isShow"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="16" :lg="18">
|
||||||
|
<div
|
||||||
|
class="right-content"
|
||||||
|
|
||||||
|
>
|
||||||
|
<!-- v-loading="!detail?.appId && !detail?.userId && isShow" -->
|
||||||
|
<div class="right-content-title">
|
||||||
|
{{ tabValue == 1 ? '协作信息' : '员工信息' }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="agency-detail-massage-cont right-content-message"
|
||||||
|
v-if="isShow && tabValue == 1"
|
||||||
|
>
|
||||||
|
<div class="agency-detail-cont-item">
|
||||||
|
<span class="agency-detail-item-title">发起人</span>
|
||||||
|
<span class="agency-detail-item-content">
|
||||||
|
{{ detail.initiatorName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="agency-detail-cont-item">
|
||||||
|
<span class="agency-detail-item-title">协作时间</span>
|
||||||
|
<span class="agency-detail-item-content">
|
||||||
|
<!-- {{
|
||||||
|
parseTime(detail.beginTime, '{y}年{m}月{d}日') +
|
||||||
|
' ' +
|
||||||
|
weekName[new Date(detail.beginTime).getDay()] +
|
||||||
|
' ' +
|
||||||
|
parseTime(detail.beginTime, '{h}:{i}')
|
||||||
|
}} -->
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="agency-detail-cont-item">
|
||||||
|
<span class="agency-detail-item-title">成员</span>
|
||||||
|
<span
|
||||||
|
class="agency-detail-item-content"
|
||||||
|
v-if="detail?.assistanceMemberList?.length"
|
||||||
|
style="display: flex; flex-wrap: wrap"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-for="(items, indexs) in detail.assistanceMemberList"
|
||||||
|
:key="indexs"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
items.nickName +
|
||||||
|
(indexs + 1 == detail.assistanceMemberList.length
|
||||||
|
? ''
|
||||||
|
: '、')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="agency-detail-cont-item">
|
||||||
|
<span class="agency-detail-item-title">协作时长</span>
|
||||||
|
<span class="agency-detail-item-content">
|
||||||
|
<!-- {{ getTime() }} -->
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right-content-file" v-if="isShow && tabValue == 1">
|
||||||
|
<el-row :gutter="15">
|
||||||
|
<el-col :xs="24" :sm="24" :md="16" :lg="18">
|
||||||
|
<div class="content-file-video">
|
||||||
|
<div class="file-top">协作视频</div>
|
||||||
|
<div class="file-video-bottom">
|
||||||
|
<!-- autoplay="autoplay" -->
|
||||||
|
<video
|
||||||
|
v-if="
|
||||||
|
detail.remoteVideoFile?.prefix &&
|
||||||
|
detail.remoteVideoFile.path
|
||||||
|
"
|
||||||
|
:src="
|
||||||
|
detail.remoteVideoFile.prefix +
|
||||||
|
detail.remoteVideoFile.path
|
||||||
|
"
|
||||||
|
id="videoPlayer"
|
||||||
|
loop
|
||||||
|
controls
|
||||||
|
></video>
|
||||||
|
<div v-else class="video-null">暂无视频</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :sm="24" :md="8" :lg="6">
|
||||||
|
<div>
|
||||||
|
<div class="file-top">
|
||||||
|
附件({{
|
||||||
|
detail?.fileList?.length ? detail.fileList.length : 0
|
||||||
|
}})
|
||||||
|
</div>
|
||||||
|
<div class="content-file-list">
|
||||||
|
<el-scrollbar
|
||||||
|
class="file-list"
|
||||||
|
height="calc(100vh - 380px)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="file-list-content"
|
||||||
|
v-if="detail?.fileList?.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="file-list-item"
|
||||||
|
v-for="(item, index) in detail.fileList"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<div class="file-list-item-icon"></div>
|
||||||
|
<div class="file-list-item-text">
|
||||||
|
<div class="list-item-text text-out-of-hiding-1">
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <el-icon
|
||||||
|
:size="18"
|
||||||
|
color="#0d74ff"
|
||||||
|
style="cursor: pointer"
|
||||||
|
@click="clickDetail(item)"
|
||||||
|
>
|
||||||
|
<View />
|
||||||
|
</el-icon> -->
|
||||||
|
<el-link
|
||||||
|
:href="item.prefix + item.path"
|
||||||
|
type="primary"
|
||||||
|
target="_blank"
|
||||||
|
:underline="false"
|
||||||
|
>
|
||||||
|
<el-icon
|
||||||
|
:size="18"
|
||||||
|
color="#0d74ff"
|
||||||
|
style="cursor: pointer"
|
||||||
|
>
|
||||||
|
<Download />
|
||||||
|
</el-icon>
|
||||||
|
</el-link>
|
||||||
|
<el-icon
|
||||||
|
:size="18"
|
||||||
|
color="#FF4646"
|
||||||
|
style="cursor: pointer"
|
||||||
|
@click="clickDeleteFile(item)"
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="message-user"
|
||||||
|
v-else-if="isShow && tabValue == 2"
|
||||||
|
style="height: calc(100vh - 90px)"
|
||||||
|
>
|
||||||
|
<div class="message-user-card">
|
||||||
|
<div class="user-card-nickName">
|
||||||
|
<img v-if="detail.avatar" :src="detail.avatar" />
|
||||||
|
<img v-else src="@/assets/images/profile.jpg" />
|
||||||
|
<span>{{ detail.nickName || detail.name || '暂无信息' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-card-information">
|
||||||
|
<div class="user-information-item">
|
||||||
|
<div class="user-information-title">
|
||||||
|
<img src="@/assets/images/user-information1.png" alt="" />
|
||||||
|
<span>性别</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-text">
|
||||||
|
<!-- <dict-tag
|
||||||
|
v-if="detail.sex"
|
||||||
|
:options="sys_user_sex"
|
||||||
|
:value="detail.sex"
|
||||||
|
/>
|
||||||
|
<div v-else>
|
||||||
|
{{ '暂无' }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-item">
|
||||||
|
<div class="user-information-title">
|
||||||
|
<img src="@/assets/images/user-information2.png" alt="" />
|
||||||
|
<span>手机号</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-text">
|
||||||
|
{{ detail.phonenumber || '暂无' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-item">
|
||||||
|
<div class="user-information-title">
|
||||||
|
<img src="@/assets/images/user-information3.png" alt="" />
|
||||||
|
<span>邮箱</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-text">
|
||||||
|
{{ detail.email || '暂无' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-item">
|
||||||
|
<div class="user-information-title">
|
||||||
|
<img src="@/assets/images/user-information4.png" alt="" />
|
||||||
|
<span>所属部门</span>
|
||||||
|
</div>
|
||||||
|
<div class="user-information-text">
|
||||||
|
{{ detail.dept?.deptName || '暂无' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-card-btn">
|
||||||
|
<el-button type="primary" @click="clickInitiate">
|
||||||
|
发起协作
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="message-null">
|
||||||
|
<el-empty description="暂无内容" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- <el-dialog
|
||||||
|
v-model="inviteDialog"
|
||||||
|
title="远程协作"
|
||||||
|
width="400px"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div style="width: 100%; margin-bottom: 30px; font-size: 20px">
|
||||||
|
"
|
||||||
|
{{
|
||||||
|
socketInformation.data?.inviteNickName
|
||||||
|
? socketInformation.data?.inviteNickName
|
||||||
|
: ''
|
||||||
|
}}
|
||||||
|
" 邀请您参加远程协作
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<el-button
|
||||||
|
size="large"
|
||||||
|
type="danger"
|
||||||
|
style="font-size: 16px"
|
||||||
|
@click="clickRefuseJoin"
|
||||||
|
>
|
||||||
|
拒 绝
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
size="large"
|
||||||
|
type="primary"
|
||||||
|
style="font-size: 16px"
|
||||||
|
@click="clickJoin"
|
||||||
|
>
|
||||||
|
加 入
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onActivated, onMounted, reactive, toRefs, watch, getCurrentInstance } from 'vue'
|
||||||
|
// import {
|
||||||
|
// getFileList,
|
||||||
|
// getRemoveSolution,
|
||||||
|
// getUserStatus,
|
||||||
|
// refuseAssistance,
|
||||||
|
// } from '@/api/module/cooperation/v1/index'
|
||||||
|
// import { getAppId, getModuleId } from '@/utils/index'
|
||||||
|
|
||||||
|
import leftTab from './components/leftTab/index.vue'
|
||||||
|
import { getInfo } from '@/api/login.js'
|
||||||
|
|
||||||
|
// import useUserStore from '@/store/modules/user'
|
||||||
|
// import { getToken } from '@/utils/auth'
|
||||||
|
// import useWebSocketStore from '@/store/modules/WebSocket'
|
||||||
|
// import usePermissionStore from '@/store/modules/permission'
|
||||||
|
// import logo from '@/assets/logo/logo.png'
|
||||||
|
|
||||||
|
// import { getRtcSetDetail } from '@/api/conferencingRoom'
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
// const WebSocketStore = useWebSocketStore()
|
||||||
|
// const { sys_user_sex } = proxy.useDict('sys_user_sex')
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
detail: {},
|
||||||
|
weekName: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
|
||||||
|
tabValue: 2,
|
||||||
|
isShow: true,
|
||||||
|
load: false,
|
||||||
|
loadText: '数据加载中',
|
||||||
|
isLinkKnow: 'F',
|
||||||
|
socketInformation: null,
|
||||||
|
inviteDialog: false,
|
||||||
|
cooperation: import.meta.env.VITE_APP_COOPERATION_TYPE,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
/** 查看文件详情 */
|
||||||
|
const clickDetail = (item) => {
|
||||||
|
// let urls = item.prefix + item.path
|
||||||
|
// let status = proxy.judgeType(urls)
|
||||||
|
// if (status == 2 || status == 1) {
|
||||||
|
// state.imgMp4Ref.showModel('查看', urls)
|
||||||
|
// } else if (status == 3) {
|
||||||
|
// state.documentRef.showModel('查看', urls)
|
||||||
|
// } else if (status == 4) {
|
||||||
|
// state.model3dRef.showModel('查看', import.meta.env.VITE_APP_FILE_API + item.path)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 发起协作邀请 */
|
||||||
|
const clickInitiate = () => {
|
||||||
|
// state.loadText = '初始化协作房间中'
|
||||||
|
// state.load = true
|
||||||
|
// getUserStatus({ userIds: state.detail.userId })
|
||||||
|
// .then((res) => {
|
||||||
|
// res.data.forEach((i) => { i.status = 1 })
|
||||||
|
// if (res.data.every((i) => i.status == 1)) {
|
||||||
|
// proxy.$modal.msgSuccess('邀请已发送')
|
||||||
|
// if (state.cooperation == 'skip') {
|
||||||
|
// getRtcSetDetail().then((res) => {
|
||||||
|
// const queryParams = new URLSearchParams({
|
||||||
|
// type: 1,
|
||||||
|
// userList: JSON.stringify([{ nickName: state.detail.nickName, userId: state.detail.userId }]),
|
||||||
|
// appid: getAppId(),
|
||||||
|
// Modinstid: getModuleId(),
|
||||||
|
// token: getToken(),
|
||||||
|
// userId: useUserStore().userId,
|
||||||
|
// }).toString()
|
||||||
|
// let url = import.meta.env.VITE_APP_ENV == 'development'
|
||||||
|
// ? `/ar/app/conferencingRoom?${queryParams}`
|
||||||
|
// : `${res.data.webMeetingUrl}?${queryParams}`
|
||||||
|
// window.open(url, '_blank')
|
||||||
|
// })
|
||||||
|
// state.load = false
|
||||||
|
// } else {
|
||||||
|
// proxy.$router.push({
|
||||||
|
// path: '/conferencingRoom',
|
||||||
|
// query: {
|
||||||
|
// type: 1,
|
||||||
|
// userList: JSON.stringify([{ nickName: state.detail.nickName, userId: state.detail.userId }]),
|
||||||
|
// appid: getAppId(),
|
||||||
|
// Modinstid: getModuleId(),
|
||||||
|
// token: getToken(),
|
||||||
|
// userId: useUserStore().userId,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// proxy.$modal.msgError(
|
||||||
|
// res.data[0].status == 0 ? '当前用户不在线' : '当前用户正在其他协作中'
|
||||||
|
// )
|
||||||
|
// state.load = false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .catch(() => {
|
||||||
|
// state.load = false
|
||||||
|
// proxy.$modal.closeLoading()
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除文件 */
|
||||||
|
const clickDeleteFile = (row) => {
|
||||||
|
// proxy.$modal
|
||||||
|
// .confirm('是否确认删除 “ ' + row.name + ' ” 文件?')
|
||||||
|
// .then(async () => {
|
||||||
|
// await getRemoveSolution({ assistanceId: state.detail.assistanceId, fileId: row.fileId })
|
||||||
|
// proxy.$modal.msgSuccess('删除成功')
|
||||||
|
// getTheFileList(state.detail)
|
||||||
|
// })
|
||||||
|
// .catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改展示列表 */
|
||||||
|
const updateTab = (newValue) => {
|
||||||
|
state.detail = {}
|
||||||
|
state.tabValue = newValue
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改展示区内容 */
|
||||||
|
const updateDetail = async (details) => {
|
||||||
|
if (details) {
|
||||||
|
console.log(details,'details')
|
||||||
|
state.detail = {}
|
||||||
|
if (state.tabValue == 1) {
|
||||||
|
state.isShow = true
|
||||||
|
} else {
|
||||||
|
const res = await getInfo(details.uid)
|
||||||
|
console.log(res,'res---+++')
|
||||||
|
// state.detail = proxy.deepClone(res.data)
|
||||||
|
state.detail = res.data
|
||||||
|
|
||||||
|
// getInfo(details.uid)
|
||||||
|
// .then((res) => {
|
||||||
|
// console.log(res,'人员详细信息')
|
||||||
|
// // state.detail = proxy.deepClone(res.data)
|
||||||
|
// })
|
||||||
|
// .finally(() => { state.isShow = true })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.isShow = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取文件列表 */
|
||||||
|
const getTheFileList = (details) => {
|
||||||
|
// let detail = proxy.deepClone(details)
|
||||||
|
// getFileList({ assistanceId: detail.assistanceId }).then((resser) => {
|
||||||
|
// detail.fileList = resser.data
|
||||||
|
// state.detail = proxy.deepClone(detail)
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取通话时长 */
|
||||||
|
const getTime = () => {
|
||||||
|
let begin = new Date(state.detail.beginTime).getTime()
|
||||||
|
let end = new Date(state.detail.endTime).getTime()
|
||||||
|
if (begin && end) {
|
||||||
|
let diff = end - begin
|
||||||
|
const h = Math.floor(diff / (1000 * 60 * 60))
|
||||||
|
const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
|
||||||
|
const s = Math.floor((diff % (1000 * 60)) / 1000)
|
||||||
|
return h > 0 ? `${h}小时 ${m}分钟 ${s}秒`
|
||||||
|
: m > 0 ? `${m}分钟 ${s}秒`
|
||||||
|
: `${s}秒`
|
||||||
|
} else {
|
||||||
|
return '暂无'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 加入会议 */
|
||||||
|
const clickJoin = () => {
|
||||||
|
// proxy.$modal.loading('加入会议中,请稍候...')
|
||||||
|
// if (state.cooperation == 'skip') {
|
||||||
|
// getRtcSetDetail().then((res) => {
|
||||||
|
// const queryParams = new URLSearchParams({
|
||||||
|
// type: 2,
|
||||||
|
// assistanceId: state.socketInformation.data.assistanceId,
|
||||||
|
// channelName: state.socketInformation.data.channelName,
|
||||||
|
// nickName: useUserStore().nickName,
|
||||||
|
// appid: getAppId(),
|
||||||
|
// Modinstid: getModuleId(),
|
||||||
|
// token: getToken(),
|
||||||
|
// userId: useUserStore().userId,
|
||||||
|
// }).toString()
|
||||||
|
// let url = import.meta.env.VITE_APP_ENV == 'development'
|
||||||
|
// ? `/ar/app/conferencingRoom?${queryParams}`
|
||||||
|
// : `${res.data.webMeetingUrl}?${queryParams}`
|
||||||
|
// window.open(url, '_blank')
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// proxy.$router.push({
|
||||||
|
// path: '/conferencingRoom',
|
||||||
|
// query: {
|
||||||
|
// type: 2,
|
||||||
|
// assistanceId: state.socketInformation.data.assistanceId,
|
||||||
|
// channelName: state.socketInformation.data.channelName,
|
||||||
|
// nickName: useUserStore().nickName,
|
||||||
|
// appid: getAppId(),
|
||||||
|
// Modinstid: getModuleId(),
|
||||||
|
// token: getToken(),
|
||||||
|
// userId: useUserStore().userId,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// state.inviteDialog = false
|
||||||
|
// proxy.$modal.closeLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 拒绝加入 */
|
||||||
|
const clickRefuseJoin = () => {
|
||||||
|
// refuseAssistance({
|
||||||
|
// roomId: state.socketInformation.data.channelName,
|
||||||
|
// assistanceId: state.socketInformation.data.assistanceId,
|
||||||
|
// inviteUserId: state.socketInformation.data.inviteUserId,
|
||||||
|
// }).then(() => {
|
||||||
|
// proxy.$modal.msgSuccess('已拒绝加入该协作')
|
||||||
|
// state.inviteDialog = false
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理 socket 消息 */
|
||||||
|
const processingSocket = (message) => {
|
||||||
|
// if (message) {
|
||||||
|
// state.socketInformation = JSON.parse(message.data)
|
||||||
|
// if (state.socketInformation.type == 'invite_join') {
|
||||||
|
// state.inviteDialog = true
|
||||||
|
// showNotification()
|
||||||
|
// }
|
||||||
|
// if (state.socketInformation.type == 'initiator_out') {
|
||||||
|
// state.inviteDialog = false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 浏览器通知 */
|
||||||
|
const showNotification = () => {
|
||||||
|
// if ('Notification' in window) {
|
||||||
|
// Notification.requestPermission().then((permission) => {
|
||||||
|
// if (permission === 'granted') {
|
||||||
|
// const notification = new Notification('协作邀请', {
|
||||||
|
// body: state.socketInformation.data.inviteNickName + '邀请您参加远程协作',
|
||||||
|
// // icon: logo,
|
||||||
|
// })
|
||||||
|
// notification.onclick = () => { clickJoin() }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// watch(() => WebSocketStore.messages, (message) => {
|
||||||
|
// if (state.cooperation != 'web') processingSocket(message)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// onMounted(() => {
|
||||||
|
// state.isLinkKnow = proxy.getCurrentApplicationConfig('cooperation_link_know')
|
||||||
|
// state.load = false
|
||||||
|
// })
|
||||||
|
|
||||||
|
// onActivated(() => {})
|
||||||
|
// 暴露给模板
|
||||||
|
const { detail, weekName, tabValue, isShow, load, loadText, isLinkKnow, socketInformation, inviteDialog, cooperation } = toRefs(state)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
// margin: 0 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-null {
|
||||||
|
@extend .flex;
|
||||||
|
height: calc(100vh - 90px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content {
|
||||||
|
height: calc(100vh - 40px);
|
||||||
|
background: #f4f9ff;
|
||||||
|
|
||||||
|
.right-content-title {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
padding: 0 20px;
|
||||||
|
background: #167bff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content-message {
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
height: 150px;
|
||||||
|
margin: 15px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-content-file {
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
margin: 0 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-top {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
height: 50px;
|
||||||
|
padding-left: 20px;
|
||||||
|
background: #e6f1ff;
|
||||||
|
color: #333;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-file-video {
|
||||||
|
.file-video-bottom {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 350px);
|
||||||
|
padding: 15px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-file-list {
|
||||||
|
background: #fff;
|
||||||
|
padding: 15px 5px 15px 10px;
|
||||||
|
|
||||||
|
.file-list {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 10px;
|
||||||
|
|
||||||
|
.file-list-content {
|
||||||
|
@extend .flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.file-list-item {
|
||||||
|
@extend .flex;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
.file-list-item-icon {
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #89b2ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-item-text {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: calc(100% - 23px);
|
||||||
|
padding: 13px 6px 13px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f4f9ff;
|
||||||
|
|
||||||
|
.list-item-text {
|
||||||
|
display: inline-block;
|
||||||
|
width: calc(100% - 50px);
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-user {
|
||||||
|
@extend .flex;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.message-user-card {
|
||||||
|
@extend .flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 500px;
|
||||||
|
height: 95%;
|
||||||
|
max-height: 550px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.user-card-nickName {
|
||||||
|
@extend .flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: 40%;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(13, 116, 255, 0.22) 0%,
|
||||||
|
rgba(30, 173, 255, 0) 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-top: 10%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #167bff;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #051435;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card-information {
|
||||||
|
@extend .flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-around;
|
||||||
|
width: 100%;
|
||||||
|
height: 45%;
|
||||||
|
|
||||||
|
.user-information-item {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.user-information-title {
|
||||||
|
@extend .flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
width: 150px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #999;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-information-text {
|
||||||
|
width: 130px;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.user-card-btn {
|
||||||
|
@extend .flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 15%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-null {
|
||||||
|
color: #999;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .user-card-btn .el-button {
|
||||||
|
width: 70%;
|
||||||
|
height: 55%;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-size: 18px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -112,7 +112,8 @@ function requestNotificationPermission() {
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
loginView.value = true
|
loginView.value = true
|
||||||
await getInfo("self");
|
const arr = await getInfo("self");
|
||||||
|
console.log(arr,'身份信息')
|
||||||
showLogin.value = false;
|
showLogin.value = false;
|
||||||
router.push({
|
router.push({
|
||||||
path: '/whiteboard',
|
path: '/whiteboard',
|
||||||
|
|||||||