Compare commits

..

39 Commits

Author SHA1 Message Date
leilei
4fadded872 feat:更新代码
All checks were successful
Deploy Lighttpd Admin / deploy (push) Successful in 4m53s
2026-01-14 17:12:04 +08:00
leilei
f684fd49fb feat:更新代码
Some checks failed
Deploy To Dev / deploy (push) Has been cancelled
2026-01-14 17:08:07 +08:00
leilei
15da7d589f feat:更新代码 2026-01-14 15:26:10 +08:00
leilei
1a6b15ea79 Merge branch 'master' of https://git.gxtech.ltd/GxTech/xSynergy-Web into dev 2025-11-24 14:09:30 +08:00
leilei
c522e5f7f1 feat:更新代码 2025-11-24 14:08:29 +08:00
leilei
042e72925d faet:更新代码 2025-11-24 10:29:13 +08:00
leilei
a1faf63eb8 feat:更新代码 2025-11-24 10:17:34 +08:00
leilei
6600c7c282 feat:统一订阅 2025-11-24 10:10:26 +08:00
b9c3488915 测试webhook
11
2025-11-23 23:36:47 +08:00
ee706b2540 测试webhook
完成测试
2025-11-23 10:31:25 +08:00
6cf53f897b 测试webhook
test
2025-11-23 10:30:39 +08:00
fdd8dfbf98 测试webhook 2025-11-23 02:45:31 +08:00
6a4334797b 测试webhook 2025-11-23 02:42:36 +08:00
b4ba201631 Update .gitea/workflows/deploy.yaml 2025-11-22 00:48:12 +08:00
9faf75265d Update dist/index.html 2025-11-22 00:46:16 +08:00
39b11d0c10 Update dist/index.html 2025-11-22 00:42:34 +08:00
0101bc8ad1 Update .gitea/workflows/deploy.yaml 2025-11-22 00:40:55 +08:00
982a61ddc8 Update .gitea/workflows/deploy.yaml 2025-11-22 00:39:37 +08:00
82d4a0865b Update .gitea/workflows/deploy.yaml 2025-11-22 00:21:22 +08:00
5d853d565c Update .gitea/workflows/deploy.yaml 2025-11-22 00:18:43 +08:00
f10d2dc642 Update .gitea/workflows/deploy.yaml 2025-11-21 18:01:54 +08:00
cdddde25d1 Update .gitea/workflows/deploy.yaml 2025-11-21 18:00:49 +08:00
e213dcf656 Update .gitea/workflows/deploy.yaml 2025-11-21 17:54:05 +08:00
c8361daa8e Update .gitea/workflows/deploy.yaml 2025-11-21 17:49:01 +08:00
fec0b747ea Update .gitea/workflows/deploy.yaml 2025-11-21 17:45:42 +08:00
edc8945735 Update .gitea/workflows/deploy.yaml 2025-11-21 17:43:31 +08:00
ffb141383d Update .gitea/workflows/deploy.yaml 2025-11-21 17:33:33 +08:00
3365c09b73 Update .gitea/workflows/deploy.yaml 2025-11-21 17:28:03 +08:00
bb83625fbf Update .gitea/workflows/deploy.yaml 2025-11-21 17:23:00 +08:00
2e525d5ea1 Update .gitea/workflows/deploy.yaml 2025-11-21 17:17:49 +08:00
6e471815cc Update .gitea/workflows/deploy.yaml 2025-11-21 16:39:33 +08:00
0eb56d5732 Update .gitea/workflows/deploy.yaml 2025-11-21 16:32:35 +08:00
f8c1171656 Update .gitea/workflows/deploy.yaml 2025-11-21 16:25:38 +08:00
0b77dca9da Update .gitea/workflows/deploy.yaml 2025-11-21 16:24:35 +08:00
leilei
c9e5ae8da4 feat:更新代码 2025-11-21 16:18:53 +08:00
leilei
32e0ec0a2c feat:更新进入房间方式 2025-11-21 16:15:05 +08:00
leilei
1457a44f0b feat:更新dev代码 2025-11-21 16:10:35 +08:00
leilei
77b499ffb0 feat:更新dev代码 2025-11-21 16:06:21 +08:00
leilei
5bf4998cbd feat:更新dev代码 2025-11-21 16:04:30 +08:00
148 changed files with 4649 additions and 10844 deletions

View File

@@ -0,0 +1,48 @@
name: Deploy Lighttpd Admin
on:
push:
branches:
- 'dev'
jobs:
deploy:
runs-on: ubuntu-22.04
container:
volumes:
- /app/lighttpd-admin:/app/xsy-admin
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Copy specific directory to runner's host machine
run: |
TARGET_DIR="./dist"
# 检查 dist 目录是否存在
if [ ! -d "$TARGET_DIR" ]; then
echo "Error: The source directory '$TARGET_DIR' does not exist in the repository."
# 如果目录不存在,报错并退出当前步骤
exit 1
fi
ls -lha /app/xsy-admin/
rm -rf /app/xsy-admin/*
cp -r ./dist/* /app/xsy-admin/
- name: Find and restart the app container
run: |
# 1. 使用 docker ps 过滤包含 'xsy-admin' 服务的容器
# 2. 提取容器 ID 或名称
CONTAINER_ID=$(docker ps -a --filter "name=xsy-admin" --format "{{.ID}}")
if [ -z "$CONTAINER_ID" ]; then
echo "Error: Could not find any container matching name 'app1'."
exit 1
else
echo "Found container ID: $CONTAINER_ID. Restarting..."
# 使用标准的 docker restart 命令
docker restart "$CONTAINER_ID"
echo "Container restarted successfully."
fi

3
.gitignore vendored
View File

@@ -8,8 +8,7 @@ pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
.DS_Store
dist-ssr
coverage
*.local

BIN
dist.zip

Binary file not shown.

1
dist/assets/401-BSBdQqy4.css vendored Normal file
View File

@@ -0,0 +1 @@
.errPage-container[data-v-2c8b7582]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-2c8b7582]{background:#008489;color:#fff;border:none!important}.errPage-container .pan-gif[data-v-2c8b7582]{margin:0 auto;display:block}.errPage-container .pan-img[data-v-2c8b7582]{display:block;margin:0 auto;width:100%}.errPage-container .text-jumbo[data-v-2c8b7582]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-2c8b7582]{font-size:14px}.errPage-container .list-unstyled li[data-v-2c8b7582]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-2c8b7582]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-2c8b7582]:hover{text-decoration:underline}

1
dist/assets/401-DO7f-liB.js vendored Normal file
View File

@@ -0,0 +1 @@
import{_ as d,g as f,r as m,c as k,f as o,w as n,h as s,o as g,p as a,k as e}from"./index-DRNenl-T.js";const h=""+new URL("401-HGF6Q5qM.gif",import.meta.url).href,w={class:"errPage-container"},x={class:"list-unstyled"},b={class:"link-type"},v=["src"],y={__name:"401",setup(B){let{proxy:r}=f();const u=m(h+"?"+ +new Date);function c(){r.$route.query.noGoBack?r.$router.push({path:"/"}):r.$router.go(-1)}return(C,t)=>{const _=s("el-button"),i=s("router-link"),l=s("el-col"),p=s("el-row");return g(),k("div",w,[o(_,{icon:"arrow-left",class:"pan-back-btn",onClick:c},{default:n(()=>[...t[0]||(t[0]=[a(" 返回 ",-1)])]),_:1}),o(p,null,{default:n(()=>[o(l,{span:12},{default:n(()=>[t[2]||(t[2]=e("h1",{class:"text-jumbo text-ginormous"}," 401错误! ",-1)),t[3]||(t[3]=e("h2",null,"您没有访问权限!",-1)),t[4]||(t[4]=e("h6",null,"对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面",-1)),e("ul",x,[e("li",b,[o(i,{to:"/"},{default:n(()=>[...t[1]||(t[1]=[a(" 回首页 ",-1)])]),_:1})])])]),_:1}),o(l,{span:12},{default:n(()=>[e("img",{src:u.value,width:"313",height:"428",alt:"Girl has dropped her ice cream."},null,8,v)]),_:1})]),_:1})])}}},I=d(y,[["__scopeId","data-v-2c8b7582"]]);export{I as default};

BIN
dist/assets/401-DO7f-liB.js.gz vendored Normal file

Binary file not shown.

BIN
dist/assets/401-HGF6Q5qM.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

1
dist/assets/404-C8Inh8VK.js vendored Normal file
View File

@@ -0,0 +1 @@
import{_ as o,B as l,c as r,k as t,C as _,f as c,q as n,i as d,w as p,h as m,o as u,p as v}from"./index-DRNenl-T.js";const h=""+new URL("404-N4aRkdWY.png",import.meta.url).href,a=""+new URL("404_cloud-CPexjtDj.png",import.meta.url).href,f={class:"wscn-http404-container"},g={class:"wscn-http404"},x={class:"bullshit"},k={class:"bullshit__headline"},w={__name:"404",setup(b){let e=l(()=>"找不到网页!");return(N,s)=>{const i=m("router-link");return u(),r("div",f,[t("div",g,[s[3]||(s[3]=_('<div class="pic-404" data-v-328ae272><img class="pic-404__parent" src="'+h+'" alt="404" data-v-328ae272><img class="pic-404__child left" src="'+a+'" alt="404" data-v-328ae272><img class="pic-404__child mid" src="'+a+'" alt="404" data-v-328ae272><img class="pic-404__child right" src="'+a+'" alt="404" data-v-328ae272></div>',1)),t("div",x,[s[1]||(s[1]=t("div",{class:"bullshit__oops"}," 404错误! ",-1)),t("div",k,n(d(e)),1),s[2]||(s[2]=t("div",{class:"bullshit__info"}," 对不起您正在寻找的页面不存在。尝试检查URL的错误然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。 ",-1)),c(i,{to:"/index",class:"bullshit__return-home"},{default:p(()=>[...s[0]||(s[0]=[v(" 返回首页 ",-1)])]),_:1})])])])}}},C=o(w,[["__scopeId","data-v-328ae272"]]);export{C as default};

BIN
dist/assets/404-C8Inh8VK.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/404-Cb2yUGol.css vendored Normal file
View File

@@ -0,0 +1 @@
.wscn-http404-container[data-v-328ae272]{transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-328ae272]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-328ae272]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-328ae272]{width:100%}.wscn-http404 .pic-404__child[data-v-328ae272]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-328ae272]{width:80px;top:17px;left:220px;opacity:0;animation-name:cloudLeft-328ae272;animation-duration:2s;animation-timing-function:linear;animation-fill-mode:forwards;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-328ae272]{width:46px;top:10px;left:420px;opacity:0;animation-name:cloudMid-328ae272;animation-duration:2s;animation-timing-function:linear;animation-fill-mode:forwards;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-328ae272]{width:62px;top:100px;left:500px;opacity:0;animation-name:cloudRight-328ae272;animation-duration:2s;animation-timing-function:linear;animation-fill-mode:forwards;animation-delay:1s}@keyframes cloudLeft-328ae272{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudMid-328ae272{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudRight-328ae272{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-328ae272]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-328ae272]{font-size:32px;font-weight:700;line-height:40px;color:#1482f0;opacity:0;margin-bottom:20px;animation-name:slideUp-328ae272;animation-duration:.5s;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-328ae272]{font-size:20px;line-height:24px;color:#222;font-weight:700;opacity:0;margin-bottom:10px;animation-name:slideUp-328ae272;animation-duration:.5s;animation-delay:.1s;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-328ae272]{font-size:13px;line-height:21px;color:gray;opacity:0;margin-bottom:30px;animation-name:slideUp-328ae272;animation-duration:.5s;animation-delay:.2s;animation-fill-mode:forwards}.wscn-http404 .bullshit__return-home[data-v-328ae272]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;opacity:0;font-size:14px;line-height:36px;cursor:pointer;animation-name:slideUp-328ae272;animation-duration:.5s;animation-delay:.3s;animation-fill-mode:forwards}@keyframes slideUp-328ae272{0%{transform:translateY(60px);opacity:0}to{transform:translateY(0);opacity:1}}

BIN
dist/assets/404-Cb2yUGol.css.gz vendored Normal file

Binary file not shown.

BIN
dist/assets/404-N4aRkdWY.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
dist/assets/404_cloud-CPexjtDj.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

1
dist/assets/authRole-BGeC_BV4.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/authRole-BGeC_BV4.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/authRoom-ScM_P5Lw.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/authRoom-ScM_P5Lw.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-27WP78gO.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-27WP78gO.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-B6TwTdR5.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-B6TwTdR5.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-B9qSM1WT.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-B9qSM1WT.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-BFgkfykF.js vendored Normal file
View File

@@ -0,0 +1 @@
import{u as s,a as c,c as n,o as u}from"./index-DRNenl-T.js";const i={__name:"index",setup(p){const e=s(),t=c(),{params:o,query:a}=e,{path:r}=o;return t.replace({path:"/"+r,query:a}),(_,m)=>(u(),n("div"))}};export{i as default};

1
dist/assets/index-CkP6b1E2.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-CkP6b1E2.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-DPF0UxJm.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-DPF0UxJm.js.gz vendored Normal file

Binary file not shown.

80
dist/assets/index-DRNenl-T.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-DRNenl-T.js.gz vendored Normal file

Binary file not shown.

1
dist/assets/index-Dz1wU-dg.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/index-Dz1wU-dg.css.gz vendored Normal file

Binary file not shown.

1
dist/assets/login-C2MWIt8z.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/login-C2MWIt8z.css.gz vendored Normal file

Binary file not shown.

14
dist/assets/login-dH8WbfOy.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
dist/assets/login-dH8WbfOy.js.gz vendored Normal file

Binary file not shown.

BIN
dist/assets/loginBg-BZpWbmau.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

1
dist/assets/menu-Ca_cGcaO.js vendored Normal file
View File

@@ -0,0 +1 @@
import{A as e}from"./index-DRNenl-T.js";const i=s=>e({url:"/api/v1/permission/permissions/tree",method:"get",params:s}),o=s=>e({url:"/api/v1/permission/permissions",method:"post",data:s}),t=s=>e({url:"/api/v1/permission/permissions/"+s.uid,method:"put",data:s}),n=s=>e({url:"/api/v1/permission/permissions/"+s,method:"delete"}),p=s=>e({url:"/api/v1/permission/roles/"+s.roleId+"/permissions/add",method:"post",data:s}),a=s=>e({url:"/api/v1/permission/roles/"+s+"/all-permissions",method:"get"});export{o as a,p as b,n as d,a as g,i as l,t as u};

BIN
dist/assets/profile-BkLdKdgI.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
dist/assets/role-zDKXfY8i.js vendored Normal file
View File

@@ -0,0 +1 @@
import{A as s}from"./index-DRNenl-T.js";const t=e=>s({url:"/api/v1/permission/roles",method:"get",params:e}),a=e=>s({url:"/api/v1/permission/roles/"+e,method:"get"}),l=e=>s({url:"/api/v1/permission/roles",method:"post",data:e}),i=e=>s({url:"/api/v1/permission/roles/"+e.uid,method:"put",data:e}),u=e=>s({url:"/api/v1/permission/roles/"+e,method:"delete"}),n=e=>s({url:"/api/v1/permission/users/"+e.userId+"/roles",method:"get",params:e}),p=(e,r)=>s({url:"/api/v1/permission/users/"+r+"/roles",method:"get",params:e}),d=e=>s({url:"/api/v1/permission/users/"+e.userId+"/roles/remove",method:"post",data:e}),m=e=>s({url:"/api/v1/permission/users/"+e.userId+"/roles/add",method:"post",data:e});export{l as a,p as b,m as c,u as d,n as e,d as f,a as g,t as l,i as u};

1
dist/assets/room-DnQmkEzy.js vendored Normal file
View File

@@ -0,0 +1 @@
import{A as r}from"./index-DRNenl-T.js";const o=t=>r({url:"/api/v1/rooms/list",method:"get",params:t}),s=(t,a)=>r({url:"/api/v1/rooms/"+t,method:"delete",params:a}),i=t=>r({url:"/api/v1/rooms/participants/list",method:"get",params:t}),p=(t,a)=>r({url:"/api/v1/rooms/"+t+"/participants",method:"delete",params:a}),m=(t,a)=>r({url:"/api/v1/meeting/"+t+"/participant/remove",method:"post",data:a}),n=(t,a)=>r({url:"/api/v1/meeting/"+t+"/participant/mute",method:"post",data:a});export{p as a,s as d,o as l,n as m,i as p,m as r};

BIN
dist/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

14
dist/index.html vendored Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="./favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>xSynergy远程协作系统</title>
<script type="module" crossorigin src="./assets/index-DRNenl-T.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-Dz1wU-dg.css">
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@@ -1,140 +0,0 @@
// import request from '@/views/conferencingRoom/utils/request.js'
// import { tansParams } from "@/utils/ruoyi";
import request from '@/utils/request'
// 创建房间获取token
export function getRoomToken(data) {
return request({
url: `/api/v1/rooms/create`,
method: 'post',
data: data,
})
}
//邀请用户参与房间
export function getInvite(room_uid,data) {
return request({
url: `/api/v1/meeting/${room_uid}/invite`,
method: 'post',
data: data,
})
}
// 创建房间
export function createRoom(data) {
return request({
url: `/room/`,
method: 'post',
data: tansParams(data),
})
}
//获取所有房间列表
export function getRoomList() {
return request({
url: `/room/ `,
method: 'get',
})
}
//修改状态 加入 退出
export function getStatusApi(room_uid,data) {
return request({
url: `/api/v1/meeting/${room_uid}/status`,
method: 'post',
data: data,
})
}
//参与者获取token
export function getTokenApi(room_uid) {
return request({
url: `/api/v1/meeting/${room_uid}/token`,
method: 'get',
})
}
//用户退出房间
export function exitRoomApi(room_uid) {
return request({
url: `/api/v1/meeting/${room_uid}/leave`,
method: 'post',
})
}
//获取当前房间信息
export function getRoomInfoApi(room_uid) {
return request({
url: `/api/v1/meeting/${room_uid}/info`,
method: 'get',
})
}
//获取文件列表
export function getFileListApi(room_uid) {
return request({
url: `/api/v1/conversion/${room_uid}/files`,
method: 'get',
// params:{
// service: room_uid
// }
})
}
//上传文件获取token
export function getUploadTokenApi(data) {
return request({
url: `/api/file/token`,
method: 'post',
data: data,
})
}
//上传文件
export function uploadFileApi(token,data) {
return request({
url: `/api/file/${token}/upload`,
method: 'post',
data: data,
headers: {
'Content-Type': 'multipart/form-data',
},
})
}
//提交一个文档转换任务,将指定的 Office 文档转换为 PDF 格式
export function convertFileApi(data,roomId) {
return request({
url: `/api/v1/conversion/${ roomId }/convert`,
method: 'post',
data: data,
})
}
//获取文档转换任务状态结构
export function getConvertStatusApi(taskId,roomId) {
return request({
url: `/api/v1/conversion/${ roomId }/status/${taskId}`,
method: 'get',
})
}
//获取当前会议中所有参与者信息
export function getParticipantsApi(roomId) {
return request({
url: `/api/v1/meeting/${ roomId }/participants`,
method: 'get',
})
}
// 获取当前房间中视频
export function getvideoUrlApi(room_uid) {
return request({
url: `/api/v1/room/${ room_uid }/recordings`,
method: 'get',
})
}

View File

@@ -1,38 +0,0 @@
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
})
}
//获取参与者历史参会记录
export function getParticipantsHistoryApi(userId,data) {
return request({
url: `/api/v1/rooms/${ userId }/participants/history`,
method: 'get',
params:data
})
}
// 获取用户详细信息
export function getInfo(userUid,type) {
return request({
url: `/api/v1/auth/users/${userUid}`,
method: 'get',
params:type
})
}

10
src/api/interface.js Normal file
View File

@@ -0,0 +1,10 @@
import request from '@/utils/request'
// 查询菜单列表
export const listMenu = (data) => {
return request({
url: '/api/v1/permission/permissions/tree',
method: 'get',
params: data,
});
};

View File

@@ -58,4 +58,13 @@ export function checkPwdStrength(password) {
method: 'post',
data: params
})
}
// 获取用户头像
export function getAvatarsApi(name) {
return request({
url: `/api/v1/avatars/username/${name}/200`,
method: 'get',
responseType: 'blob'
});
}

View File

@@ -1,9 +1,70 @@
import request from '@/utils/request'
// 获取路由
export const getRouters = () => {
// 查询菜单列表
export const listMenu = (data) => {
return request({
url: '/system/menu/getRouters',
url: '/api/v1/permission/permissions/tree',
method: 'get',
params: data
});
};
// 查询菜单下拉树结构
export const treeselect = () => {
return request({
url: '/system/menu/treeselect',
method: 'get'
})
}
});
};
// 根据角色ID查询菜单下拉树结构
export const roleMenuTreeselect = (roleId) => {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get'
});
};
// 新增菜单
export const addMenu = (data) => {
return request({
url: '/api/v1/permission/permissions',
method: 'post',
data: data
});
};
// 修改菜单
export const updateMenu = (data) => {
return request({
url: '/api/v1/permission/permissions/' + data.uid,
method: 'put',
data: data
});
};
// 删除菜单
export const delMenu = (menuId) => {
return request({
url: '/api/v1/permission/permissions/' + menuId,
method: 'delete'
});
};
//分配权限增量
export const dataScope = (data) => {
return request({
url: '/api/v1/permission/roles/' + data.roleId + '/permissions/add',
method: 'post',
data: data
});
};
//获取当前角色存在的权限菜单
export const getRolePermissions = (roleId) => {
return request({
url: '/api/v1/permission/roles/' + roleId + '/all-permissions',
method: 'get'
});
};

133
src/api/role.js Normal file
View File

@@ -0,0 +1,133 @@
import request from '@/utils/request';
export const listRole = (query) => {
return request({
url: '/api/v1/permission/roles',
method: 'get',
params: query
});
};
/**
* 查询角色详细
*/
export const getRole = (roleId) => {
return request({
url: '/api/v1/permission/roles/' + roleId,
method: 'get'
});
};
/**
* 新增角色
*/
export const addRole = (data) => {
return request({
url: '/api/v1/permission/roles',
method: 'post',
data: data
});
};
/**
* 修改角色
* @param data
*/
export const updateRole = (data) => {
return request({
url: '/api/v1/permission/roles/' + data.uid,
method: 'put',
data: data
});
};
/**
* 角色数据权限
*/
export const dataScope = (data) => {
return request({
url: '/system/role/dataScope',
method: 'put',
data: data
});
};
/**
* 角色状态修改
*/
export const changeRoleStatus = (roleId, status) => {
const data = {
roleId,
status
};
return request({
url: '/system/role/changeStatus',
method: 'put',
data: data
});
};
/**
* 删除角色
*/
export const delRole = (roleId) => {
return request({
url: '/api/v1/permission/roles/' + roleId,
method: 'delete'
});
};
/**
* 查询用户已授权角色列表
*/
export const allocatedUserList = (query)=> {
return request({
url: '/api/v1/permission/users/' + query.userId + '/roles',
method: 'get',
params: query
});
};
/**
* 查询未分配角色列表
*/
export const unallocatedUserList = (query,userId) => {
return request({
url: '/api/v1/permission/users/' + userId + '/roles',
method: 'get',
params: query
});
};
/**
* 取消用户授权角色
*/
export const authUserCancel = (data) => {
return request({
url: '/api/v1/permission/users/' + data.userId + '/roles/remove',
method: 'post',
data: data
});
};
/**
* 授权用户选择的角色
*/
export const authUserSelectAll = (data) => {
return request({
url: '/api/v1/permission/users/' + data.userId + '/roles/add',
method: 'post',
data: data
});
};
/**
* 查询未分配用户角色列表
*/
// export const unallocatedUserList = (query) => {
// return request({
// url: '/api/v1/permission/roles',
// method: 'get',
// params: query
// });
// };

69
src/api/room.js Normal file
View File

@@ -0,0 +1,69 @@
import request from '@/utils/request';
export const listRoom = (query) => {
return request({
url: '/api/v1/rooms/list',
method: 'get',
params: query
});
};
/**
* 删除房间
*/
export const delRoom = (roomId,data) => {
return request({
url: '/api/v1/rooms/' + roomId,
method: 'delete',
params: data
});
};
/**
* 查询房间参与者列表
*/
export const participantUserList = (query)=> {
return request({
url: '/api/v1/rooms/participants/list',
method: 'get',
params: query
});
};
/**
* 删除参与者信息
*/
export const delParticipant = (roomId,data) => {
return request({
url: '/api/v1/rooms/' + roomId +'/participants',
method: 'delete',
params: data
});
};
/**
* 提出房间参与者
*/
export const removeParticipant = (roomId,data) => {
return request({
url: '/api/v1/meeting/' + roomId + '/participant/remove' ,
method: 'post',
data: data
});
};
//静音 解除静音
export const muteParticipant = (roomId,data) => {
return request({
url: '/api/v1/meeting/' + roomId + '/participant/mute' ,
method: 'post',
data: data
});
};

32
src/api/user.js Normal file
View File

@@ -0,0 +1,32 @@
import request from '@/utils/request'
/**
* 查询用户列表
* @param query
*/
export function listUser(data) {
return request({
url: `/api/v1/auth/userList`,
method: 'get',
params:data
})
}
/**
* 修改用户
*/
export const updateUser = (data) => {
console.log(data,'data')
return request({
url: `/api/v1/auth/userInfo/${data.uid}/update`,
method: 'put',
data: data
});
};
export default {
listUser,
updateUser
};

View File

@@ -1,5 +1,5 @@
// $menu-bg-color: #8290f0;
$menu-bg-color: #434343;
$menu-bg-color: #409EFF;
// $menu-bg-color: #434343;
#app {
.main-container {
@@ -140,7 +140,7 @@ $menu-bg-color: #434343;
.sidebar-container {
// width: 54px !important;
height: calc(100vh - 50px);
background-color: red;
// background-color: red;
}

View File

@@ -50,8 +50,7 @@ function handleLink(item) {
router.push(path)
}
watchEffect(() => {
// if you go to the redirect page, do not update the breadcrumbs
watchEffect(() => {
if (route.path.startsWith('/redirect/')) {
return
}

View File

@@ -0,0 +1,119 @@
<template>
<div :class="{ 'hidden': hidden }" class="pagination-container">
<el-pagination
:background="background"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:pager-count="pagerCount"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
export default {
name: 'Pagination'
}
</script>
<script setup>
import { scrollTo } from '@/utils/scroll-to.js'
import { computed } from 'vue'
const props = defineProps({
total: {
type: Number,
required: true
},
page: {
type: Number,
default: 1
},
limit: {
type: Number,
default: 20
},
pageSizes: {
type: Array,
default: () => [10, 20, 30, 50]
},
// 移动端页码按钮的数量端默认值5
pagerCount: {
type: Number,
default: document.body.clientWidth < 992 ? 5 : 7
},
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper'
},
background: {
type: Boolean,
default: true
},
autoScroll: {
type: Boolean,
default: true
},
hidden: {
type: Boolean,
default: false
},
float: {
type: String,
default: 'right'
}
})
const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
const currentPage = computed({
get() {
return props.page
},
set(val) {
emit('update:page', val)
}
})
const pageSize = computed({
get() {
return props.limit
},
set(val){
emit('update:limit', val)
}
})
function handleSizeChange(val) {
if (currentPage.value * val > props.total) {
currentPage.value = 1
}
emit('pagination', { page: currentPage.value, limit: val })
if (props.autoScroll) {
scrollTo(0, 800)
}
}
function handleCurrentChange(val) {
emit('pagination', { page: val, limit: pageSize.value })
if (props.autoScroll) {
scrollTo(0, 800)
}
}
</script>
<style lang="scss" scoped>
.pagination-container {
padding: 32px 16px;
.el-pagination{
float: v-bind(float);
}
}
.pagination-container.hidden {
display: none;
}
</style>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 24</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-48.000000, -152.000000)">
<g id="编组-4备份" transform="translate(48.000000, 152.000000)">
<line x1="6" y1="18" x2="16.4593589" y2="7.54064109" id="路径-20" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<polygon id="矩形" fill="#3381FF" points="12 6 18 6 18 12"></polygon>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 746 B

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 24</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-8.000000, -152.000000)">
<g id="编组-4备份" transform="translate(8.000000, 152.000000)">
<line x1="6" y1="18" x2="16.4593589" y2="7.54064109" id="路径-20" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<polygon id="矩形" fill="#444E60" points="12 6 18 6 18 12"></polygon>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 744 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.7 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -476.000000)" stroke="#3381FF">
<g id="编组-9备份" transform="translate(48.000000, 476.000000)">
<path d="M10.6666667,9.66666667 L10.6666667,6.16666667 C10.6666667,5.52233446 11.1890011,5 11.8333333,5 C12.4776655,5 13,5.52233446 13,6.16666667 L13,9.66666667 L13,9.66666667 C14.2886644,9.66666667 15.3333333,10.7113356 15.3333333,12 L15.3333333,12 L15.3333333,12 L8.33333333,12 C8.33333333,10.7113356 9.37800225,9.66666667 10.6666667,9.66666667 L10.6666667,9.66666667 L10.6666667,9.66666667 Z" id="路径-47"></path>
<path d="M15.3333333,12 L17.6666667,17.8333333 C13.8159078,18.6034851 9.85075886,18.6034851 6,17.8333333 L8.33333333,12" id="路径"></path>
<line x1="11.8333333" y1="17.8333333" x2="11.8333333" y2="15.5" id="路径-49"></line>
<line x1="9.5" y1="17.8333333" x2="9.5" y2="15.5" id="路径-51"></line>
<line x1="14.1666667" y1="17.8333333" x2="14.1666667" y2="15.5" id="路径-52"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="小班课" transform="translate(-16.000000, -549.000000)" stroke="#444E60">
<g id="编组-35" transform="translate(8.000000, 285.000000)">
<g id="编组-9" transform="translate(8.000000, 264.000000)">
<path d="M10.6666667,9.66666667 L10.6666667,6.16666667 C10.6666667,5.52233446 11.1890011,5 11.8333333,5 C12.4776655,5 13,5.52233446 13,6.16666667 L13,9.66666667 L13,9.66666667 C14.2886644,9.66666667 15.3333333,10.7113356 15.3333333,12 L15.3333333,12 L15.3333333,12 L8.33333333,12 C8.33333333,10.7113356 9.37800225,9.66666667 10.6666667,9.66666667 L10.6666667,9.66666667 L10.6666667,9.66666667 Z" id="路径-47"></path>
<path d="M15.3333333,12 L17.6666667,17.8333333 C13.8159078,18.6034851 9.85075886,18.6034851 6,17.8333333 L8.33333333,12" id="路径"></path>
<line x1="11.8333333" y1="17.8333333" x2="11.8333333" y2="15.5" id="路径-49"></line>
<line x1="9.5" y1="17.8333333" x2="9.5" y2="15.5" id="路径-51"></line>
<line x1="14.1666667" y1="17.8333333" x2="14.1666667" y2="15.5" id="路径-52"></line>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>click_p@1x</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="编组-4备份-2">
<polygon id="路径-5" stroke="#444E60" points="7 5.07179677 8.66987298 17.9641016 11.9090909 13.5745916 17.330127 12.9641016"></polygon>
<line x1="12" y1="13.7320508" x2="15" y2="18.9282032" id="路径-7" stroke="#444E60"></line>
<polygon id="路径-5" stroke="#3381FF" points="7 5.07179677 8.66987298 17.9641016 11.9090909 13.5745916 17.330127 12.9641016"></polygon>
<line x1="12" y1="13.7320508" x2="15" y2="18.9282032" id="路径-7" stroke="#3381FF"></line>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 918 B

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>click@1x</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="编组-4" stroke="#444E60">
<polygon id="路径-5" points="7 5.07179677 8.66987298 17.9641016 11.9090909 13.5745916 17.330127 12.9641016"></polygon>
<line x1="12" y1="13.7320508" x2="15" y2="18.9282032" id="路径-7"></line>
<polygon id="路径-5" points="7 5.07179677 8.66987298 17.9641016 11.9090909 13.5745916 17.330127 12.9641016"></polygon>
<line x1="12" y1="13.7320508" x2="15" y2="18.9282032" id="路径-7"></line>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 857 B

View File

@@ -1 +0,0 @@
<svg t="1757644652588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8843" width="18" height="18"><path d="M512 85.3248c235.5968 0 426.6752 169.728 426.6752 379.264a237.1328 237.1328 0 0 1-237.056 237.0304H617.728a71.0656 71.0656 0 0 0-71.1168 71.1168c0 17.9968 7.1168 34.6112 17.9968 46.9248a71.68 71.68 0 0 1 18.5088 47.872c0 39.3984-32.7168 71.1424-71.1168 71.1424-235.5968 0-426.6752-191.0784-426.6752-426.6752 0-235.5968 191.0784-426.6752 426.6752-426.6752z m-50.7392 687.4112a156.3136 156.3136 0 0 1 156.4672-156.4672h83.8912a151.808 151.808 0 0 0 151.7056-151.6288c0-160.0512-150.6816-293.9648-341.3248-293.9648a341.3504 341.3504 0 0 0-28.8512 681.472 155.648 155.648 0 0 1-21.888-79.36v-0.0512zM320 512a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m384 0a64 64 0 1 1 0-128 64 64 0 0 1 0 128zM512 384a64 64 0 1 1 0-128 64 64 0 0 1 0 128z" p-id="8844" fill="#3381ff"></path></svg>

Before

Width:  |  Height:  |  Size: 924 B

View File

@@ -1 +0,0 @@
<svg t="1757644652588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8843" width="18" height="18"><path d="M512 85.3248c235.5968 0 426.6752 169.728 426.6752 379.264a237.1328 237.1328 0 0 1-237.056 237.0304H617.728a71.0656 71.0656 0 0 0-71.1168 71.1168c0 17.9968 7.1168 34.6112 17.9968 46.9248a71.68 71.68 0 0 1 18.5088 47.872c0 39.3984-32.7168 71.1424-71.1168 71.1424-235.5968 0-426.6752-191.0784-426.6752-426.6752 0-235.5968 191.0784-426.6752 426.6752-426.6752z m-50.7392 687.4112a156.3136 156.3136 0 0 1 156.4672-156.4672h83.8912a151.808 151.808 0 0 0 151.7056-151.6288c0-160.0512-150.6816-293.9648-341.3248-293.9648a341.3504 341.3504 0 0 0-28.8512 681.472 155.648 155.648 0 0 1-21.888-79.36v-0.0512zM320 512a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m384 0a64 64 0 1 1 0-128 64 64 0 0 1 0 128zM512 384a64 64 0 1 1 0-128 64 64 0 0 1 0 128z" p-id="8844" fill="#444e60"></path></svg>

Before

Width:  |  Height:  |  Size: 924 B

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>folder备份</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -368.000000)" stroke="#3381FF">
<g id="folder备份" transform="translate(48.000000, 368.000000)">
<rect id="矩形" x="6" y="6" width="12" height="12" rx="6"></rect>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 621 B

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>folder备份</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -368.000000)" stroke="#444E60">
<g id="folder备份" transform="translate(8.000000, 368.000000)">
<rect id="矩形" x="6" y="6" width="12" height="12" rx="6"></rect>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 619 B

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-48.000000, -116.000000)" stroke="#3381FF">
<g id="编组-3" transform="translate(48.000000, 116.000000)">
<line x1="11" y1="8" x2="16" y2="13" id="路径-26"></line>
<path d="M15.5,6.16666667 L17.8333333,8.5 C18.4776655,9.14433221 18.4776655,10.1890011 17.8333333,10.8333333 L12,16.6666667 C10.7113356,17.9553311 8.62199775,17.9553311 7.33333333,16.6666667 L6.16666667,15.5 C5.52233446,14.8556678 5.52233446,13.8109989 6.16666667,13.1666667 L13.1666667,6.16666667 C13.8109989,5.52233446 14.8556678,5.52233446 15.5,6.16666667 Z" id="矩形" stroke-linecap="round" stroke-linejoin="round"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-8.000000, -116.000000)" stroke="#444E60">
<g id="编组-3" transform="translate(8.000000, 116.000000)">
<line x1="11" y1="8" x2="16" y2="13" id="路径-26"></line>
<path d="M15.5,6.16666667 L17.8333333,8.5 C18.4776655,9.14433221 18.4776655,10.1890011 17.8333333,10.8333333 L12,16.6666667 C10.7113356,17.9553311 8.62199775,17.9553311 7.33333333,16.6666667 L6.16666667,15.5 C5.52233446,14.8556678 5.52233446,13.8109989 6.16666667,13.1666667 L13.1666667,6.16666667 C13.8109989,5.52233446 14.8556678,5.52233446 15.5,6.16666667 Z" id="矩形" stroke-linecap="round" stroke-linejoin="round"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 24</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -224.000000)" stroke="#3381FF">
<g id="编组备份" transform="translate(48.000000, 224.000000)">
<path d="M12.5,5 C13.0522847,5 13.5,5.44771525 13.5,6 L13.5,7 C13.5,6.44771525 13.9477153,6 14.5,6 C15.0522847,6 15.5,6.44771525 15.5,7 L15.5,7 L15.5,9 C15.5,8.44771525 15.9477153,8 16.5,8 C17.0522847,8 17.5,8.44771525 17.5,9 L17.5,9 L17.5,15 C17.5,17.209139 15.709139,19 13.5,19 L12.1375846,19 C10.5374722,19 9.09131968,18.0464126 8.46100451,16.5756772 L6.77854301,12.6499337 C6.61031263,12.2573961 6.69801722,11.8019828 7,11.5 C7.27614237,11.2238576 7.72385763,11.2238576 8,11.5 L9.5,13 L9.5,7 L9.50672773,6.88337887 C9.56449284,6.38604019 9.98716416,6 10.5,6 C11.0522847,6 11.5,6.44771525 11.5,7 L11.5,7 L11.5,6 C11.5,5.44771525 11.9477153,5 12.5,5 Z M11.5,6 L11.5,10 M13.5,6 L13.5,10 M15.5,8 L15.5,10" id="形状结合备份" transform="translate(12.000000, 12.000000) rotate(45.000000) translate(-12.000000, -12.000000) "></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 24</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -224.000000)" stroke="#444E60">
<g id="编组备份" transform="translate(8.000000, 224.000000)">
<path d="M12.5,5 C13.0522847,5 13.5,5.44771525 13.5,6 L13.5,7 C13.5,6.44771525 13.9477153,6 14.5,6 C15.0522847,6 15.5,6.44771525 15.5,7 L15.5,7 L15.5,9 C15.5,8.44771525 15.9477153,8 16.5,8 C17.0522847,8 17.5,8.44771525 17.5,9 L17.5,9 L17.5,15 C17.5,17.209139 15.709139,19 13.5,19 L12.1375846,19 C10.5374722,19 9.09131968,18.0464126 8.46100451,16.5756772 L6.77854301,12.6499337 C6.61031263,12.2573961 6.69801722,11.8019828 7,11.5 C7.27614237,11.2238576 7.72385763,11.2238576 8,11.5 L9.5,13 L9.5,7 L9.50672773,6.88337887 C9.56449284,6.38604019 9.98716416,6 10.5,6 C11.0522847,6 11.5,6.44771525 11.5,7 L11.5,7 L11.5,6 C11.5,5.44771525 11.9477153,5 12.5,5 Z M11.5,6 L11.5,10 M13.5,6 L13.5,10 M15.5,8 L15.5,10" id="形状结合备份" transform="translate(12.000000, 12.000000) rotate(45.000000) translate(-12.000000, -12.000000) "></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-48.000000, -188.000000)">
<g id="编组-3备份" transform="translate(48.000000, 188.000000)">
<circle id="椭圆形" fill="#3381FF" cx="12" cy="12" r="2"></circle>
<line x1="12" y1="4" x2="12" y2="6" id="路径-4" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="12" y1="18" x2="12" y2="20" id="路径-4备份" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="20" y1="12" x2="18" y2="12" id="路径-4" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="6" y1="12" x2="4" y2="12" id="路径-4备份" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="17.6568542" y1="17.6568542" x2="16.2426407" y2="16.2426407" id="路径-4" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="7.75735931" y1="7.75735931" x2="6.34314575" y2="6.34314575" id="路径-4备份" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="6.34314575" y1="17.6568542" x2="7.75735931" y2="16.2426407" id="路径-4" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="16.2426407" y1="7.75735931" x2="17.6568542" y2="6.34314575" id="路径-4备份" stroke="#3381FF" stroke-linecap="square" stroke-linejoin="round"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="切图" transform="translate(-8.000000, -188.000000)">
<g id="编组-3备份" transform="translate(8.000000, 188.000000)">
<circle id="椭圆形" fill="#444E60" cx="12" cy="12" r="2"></circle>
<line x1="12" y1="4" x2="12" y2="6" id="路径-4" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="12" y1="18" x2="12" y2="20" id="路径-4备份" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="20" y1="12" x2="18" y2="12" id="路径-4" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="6" y1="12" x2="4" y2="12" id="路径-4备份" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="17.6568542" y1="17.6568542" x2="16.2426407" y2="16.2426407" id="路径-4" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="7.75735931" y1="7.75735931" x2="6.34314575" y2="6.34314575" id="路径-4备份" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="6.34314575" y1="17.6568542" x2="7.75735931" y2="16.2426407" id="路径-4" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
<line x1="16.2426407" y1="7.75735931" x2="17.6568542" y2="6.34314575" id="路径-4备份" stroke="#444E60" stroke-linecap="square" stroke-linejoin="round"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="170px" height="29px" viewBox="0 0 170 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
<title>mask (1)</title>
<desc>Created with Sketch.</desc>
<g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="mask-(1)" transform="translate(0.000000, -0.177515)" fill="#FFFFFF" fill-rule="nonzero">
<path d="M170,0.177514793 L170,29.1775148 L0,29.1775148 L0,0.177514793 L170,0.177514793 Z M155.702875,7.70508717 L155.434123,7.71050163 L8.49907471,13.4220166 C7.82142679,13.4483583 7.28571429,14.0026739 7.28571429,14.6775148 C7.28571429,15.3523557 7.82142679,15.9066713 8.49907471,15.933013 L8.49907471,15.933013 L155.434123,21.644528 C155.525243,21.6480696 155.616424,21.649841 155.707613,21.649841 C159.577292,21.649841 162.714286,18.5282242 162.714286,14.6775148 C162.714286,14.5867726 162.712506,14.4960388 162.708947,14.4053655 C162.557902,10.5575911 159.300853,7.56019825 155.434123,7.71050163 L155.702875,7.70508717 Z" id="mask"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>follow备份 3</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -44.000000)" stroke="#3381FF">
<g id="folder备份" transform="translate(48.000000, 44.000000)">
<path d="M15.2700286,11.5822879 L9.44305056,17.4092659 C9.06480988,17.7875066 8.55180543,18 8.01689232,18 L6,18 L6,18 L6,15.9831077 C6,15.4481946 6.2124934,14.9351901 6.59073408,14.5569494 L14.5569494,6.59073408 C15.3445949,5.80308864 16.6216205,5.80308864 17.4092659,6.59073408 C18.1969114,7.37837953 18.1969114,8.65540512 17.4092659,9.44305056 L17.4092659,9.44305056 L17.4092659,9.44305056 C18.1969114,10.230696 18.1969114,11.5077216 17.4092659,12.295367 L14.5569494,15.1476835 L14.5569494,15.1476835" id="路径"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>follow备份 3</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -44.000000)" stroke="#444E60">
<g id="folder备份" transform="translate(8.000000, 44.000000)">
<path d="M15.2700286,11.5822879 L9.44305056,17.4092659 C9.06480988,17.7875066 8.55180543,18 8.01689232,18 L6,18 L6,18 L6,15.9831077 C6,15.4481946 6.2124934,14.9351901 6.59073408,14.5569494 L14.5569494,6.59073408 C15.3445949,5.80308864 16.6216205,5.80308864 17.4092659,6.59073408 C18.1969114,7.37837953 18.1969114,8.65540512 17.4092659,9.44305056 L17.4092659,9.44305056 L17.4092659,9.44305056 C18.1969114,10.230696 18.1969114,11.5077216 17.4092659,12.295367 L14.5569494,15.1476835 L14.5569494,15.1476835" id="路径"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-128.000000, -128.000000)" stroke="#3381FF">
<g id="编组-34备份" transform="translate(56.000000, 88.000000)">
<g id="follow备份-23" transform="translate(72.000000, 40.000000)">
<path d="M11.8220813,5.53069562 C12.3696773,5.62507662 12.4625734,5.72554557 12.5206245,5.84774318 L12.5206245,5.84774318 L14.2189736,9.42277042 L17.9920285,9.99234378 C18.1520889,10.0165062 18.2857395,10.1091286 18.3751462,10.2348609 C18.4719375,10.3709779 18.5180744,10.5461839 18.4934299,10.727512 C18.4738012,10.8719348 18.4101452,11.0060802 18.3101095,11.107382 L18.3101095,11.107382 L15.6017319,13.8500424 L16.2437398,17.738772 C16.273578,17.9195063 16.2322362,18.0963001 16.1392467,18.2355891 C16.0531778,18.3645118 15.9218276,18.4616905 15.7619923,18.4909999 C15.6401188,18.5133481 15.5148269,18.4923492 15.4051219,18.4324315 L15.4051219,18.4324315 L11.9999312,16.5726127 L8.59474046,18.4324315 C8.45624603,18.5080732 8.30173213,18.5180361 8.16377893,18.4719016 C8.01822109,18.4232239 7.89275102,18.3137981 7.81733557,18.160431 C7.75356476,18.0307448 7.73238084,17.8825791 7.75612261,17.738772 L7.75612261,17.738772 L8.39813049,13.8500424 L5.68975282,11.107382 C5.56536722,10.981422 5.50330824,10.813681 5.50012823,10.6457587 C5.49693852,10.4773242 5.55293545,10.306672 5.67278368,10.1752191 C5.76224575,10.0770947 5.87963871,10.0116959 6.00783388,9.99234378 L6.00783388,9.99234378 L9.78088874,9.42277042 L11.4792378,5.84774318 C11.5527358,5.69302981 11.6769476,5.58159072 11.8220813,5.53069562 Z" id="星形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-128.000000, -48.000000)" stroke="#444E60">
<g id="编组-34" transform="translate(56.000000, 8.000000)">
<g id="follow备份-23" transform="translate(72.000000, 40.000000)">
<path d="M11.8220813,5.53069562 C12.3696773,5.62507662 12.4625734,5.72554557 12.5206245,5.84774318 L12.5206245,5.84774318 L14.2189736,9.42277042 L17.9920285,9.99234378 C18.1520889,10.0165062 18.2857395,10.1091286 18.3751462,10.2348609 C18.4719375,10.3709779 18.5180744,10.5461839 18.4934299,10.727512 C18.4738012,10.8719348 18.4101452,11.0060802 18.3101095,11.107382 L18.3101095,11.107382 L15.6017319,13.8500424 L16.2437398,17.738772 C16.273578,17.9195063 16.2322362,18.0963001 16.1392467,18.2355891 C16.0531778,18.3645118 15.9218276,18.4616905 15.7619923,18.4909999 C15.6401188,18.5133481 15.5148269,18.4923492 15.4051219,18.4324315 L15.4051219,18.4324315 L11.9999312,16.5726127 L8.59474046,18.4324315 C8.45624603,18.5080732 8.30173213,18.5180361 8.16377893,18.4719016 C8.01822109,18.4232239 7.89275102,18.3137981 7.81733557,18.160431 C7.75356476,18.0307448 7.73238084,17.8825791 7.75612261,17.738772 L7.75612261,17.738772 L8.39813049,13.8500424 L5.68975282,11.107382 C5.56536722,10.981422 5.50330824,10.813681 5.50012823,10.6457587 C5.49693852,10.4773242 5.55293545,10.306672 5.67278368,10.1752191 C5.76224575,10.0770947 5.87963871,10.0116959 6.00783388,9.99234378 L6.00783388,9.99234378 L9.78088874,9.42277042 L11.4792378,5.84774318 C11.5527358,5.69302981 11.6769476,5.58159072 11.8220813,5.53069562 Z" id="星形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>folder备份</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -332.000000)" stroke="#3381FF">
<g id="folder备份" transform="translate(48.000000, 332.000000)">
<rect id="矩形" x="6" y="6" width="12" height="12" rx="2"></rect>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 621 B

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>folder备份</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -332.000000)" stroke="#444E60">
<g id="folder备份" transform="translate(8.000000, 332.000000)">
<rect id="矩形" x="6" y="6" width="12" height="12" rx="2"></rect>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 619 B

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-64.000000, -128.000000)" stroke="#3381FF">
<g id="编组-34备份" transform="translate(56.000000, 88.000000)">
<g id="follow备份-21" transform="translate(8.000000, 40.000000)">
<path d="M12,5.5 C12.3399741,5.5 12.6799483,5.62969577 12.9393398,5.8890873 L12.9393398,5.8890873 L18.1109127,11.0606602 C18.3703042,11.3200517 18.5,11.6600259 18.5,12 C18.5,12.3399741 18.3703042,12.6799483 18.1109127,12.9393398 L18.1109127,12.9393398 L12.9393398,18.1109127 C12.6799483,18.3703042 12.3399741,18.5 12,18.5 C11.6600259,18.5 11.3200517,18.3703042 11.0606602,18.1109127 L11.0606602,18.1109127 L5.8890873,12.9393398 C5.62969577,12.6799483 5.5,12.3399741 5.5,12 C5.5,11.6600259 5.62969577,11.3200517 5.8890873,11.0606602 L5.8890873,11.0606602 L11.0606602,5.8890873 C11.3200517,5.62969577 11.6600259,5.5 12,5.5 Z" id="矩形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-64.000000, -48.000000)" stroke="#444E60">
<g id="编组-34" transform="translate(56.000000, 8.000000)">
<g id="follow备份-21" transform="translate(8.000000, 40.000000)">
<path d="M12,5.5 C12.3399741,5.5 12.6799483,5.62969577 12.9393398,5.8890873 L12.9393398,5.8890873 L18.1109127,11.0606602 C18.3703042,11.3200517 18.5,11.6600259 18.5,12 C18.5,12.3399741 18.3703042,12.6799483 18.1109127,12.9393398 L18.1109127,12.9393398 L12.9393398,18.1109127 C12.6799483,18.3703042 12.3399741,18.5 12,18.5 C11.6600259,18.5 11.3200517,18.3703042 11.0606602,18.1109127 L11.0606602,18.1109127 L5.8890873,12.9393398 C5.62969577,12.6799483 5.5,12.3399741 5.5,12 C5.5,11.6600259 5.62969577,11.3200517 5.8890873,11.0606602 L5.8890873,11.0606602 L11.0606602,5.8890873 C11.3200517,5.62969577 11.6600259,5.5 12,5.5 Z" id="矩形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
<title>selector</title>
<desc>Created with Sketch.</desc>
<g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="selector" transform="translate(1.000000, 1.000000)">
<path d="M7,14 L2,14 C0.8954305,14 0,13.1045695 0,12 L0,2 C0,0.8954305 0.8954305,0 2,0 L12,0 C13.1045695,0 14,0.8954305 14,2 L14,7 L14,7" id="路径" stroke="#3381FF" stroke-linecap="round" stroke-linejoin="round"></path>
<polygon id="路径-10" fill="#3381FF" fill-rule="nonzero" points="8 8 14 10 11.3333333 11.3333333 10 14"></polygon>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 861 B

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>follow备份 14</title>
<g id="Flat" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="白板-关闭摄像头-大班课" transform="translate(-16.000000, -247.000000)">
<g id="编组-35" transform="translate(8.000000, 207.000000)">
<g id="folder备份" transform="translate(8.000000, 40.000000)">
<path d="M12,19 L7,19 C5.8954305,19 5,18.1045695 5,17 L5,7 C5,5.8954305 5.8954305,5 7,5 L17,5 C18.1045695,5 19,5.8954305 19,7 L19,12 L19,12" id="路径" stroke="#444E60" stroke-linecap="round" stroke-linejoin="round"></path>
<polygon id="路径-10" fill="#444E60" points="13 13 19 15 16.3333333 16.3333333 15 19"></polygon>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 983 B

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-160.000000, -128.000000)" stroke="#3381FF">
<g id="编组-34备份" transform="translate(56.000000, 88.000000)">
<g id="follow备份-24" transform="translate(104.000000, 40.000000)">
<path d="M16.5,6 C16.9142136,6 17.2892136,6.16789322 17.5606602,6.43933983 C17.8321068,6.71078644 18,7.08578644 18,7.5 L18,7.5 L18,13.7142857 C18,14.1284993 17.8321068,14.5034993 17.5606602,14.7749459 C17.2892136,15.0463925 16.9142136,15.2142857 16.5000418,15.2142857 L16.5000418,15.2142857 L12.862101,15.2139816 L10.4309693,17.8655011 L9.7122759,15.2139169 L7.5,15.2142857 C7.08578644,15.2142857 6.71078644,15.0463925 6.43933983,14.7749459 C6.16789322,14.5034993 6,14.1284993 6,13.7142857 L6,13.7142857 L6,7.5 C6,7.08578644 6.16789322,6.71078644 6.43933983,6.43933983 C6.71078644,6.16789322 7.08578644,6 7.5,6 L7.5,6 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-160.000000, -48.000000)" stroke="#444E60">
<g id="编组-34" transform="translate(56.000000, 8.000000)">
<g id="follow备份-24" transform="translate(104.000000, 40.000000)">
<path d="M16.5,6 C16.9142136,6 17.2892136,6.16789322 17.5606602,6.43933983 C17.8321068,6.71078644 18,7.08578644 18,7.5 L18,7.5 L18,13.7142857 C18,14.1284993 17.8321068,14.5034993 17.5606602,14.7749459 C17.2892136,15.0463925 16.9142136,15.2142857 16.5000418,15.2142857 L16.5000418,15.2142857 L12.862101,15.2139816 L10.4309693,17.8655011 L9.7122759,15.2139169 L7.5,15.2142857 C7.08578644,15.2142857 6.71078644,15.0463925 6.43933983,14.7749459 C6.16789322,14.5034993 6,14.1284993 6,13.7142857 L6,13.7142857 L6,7.5 C6,7.08578644 6.16789322,6.71078644 6.43933983,6.43933983 C6.71078644,6.16789322 7.08578644,6 7.5,6 L7.5,6 Z" id="形状结合"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>follow备份 7</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -404.000000)" stroke="#3381FF">
<g id="folder备份-2" transform="translate(48.000000, 404.000000)">
<line x1="6" y1="18" x2="18" y2="6" id="路径-2"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 638 B

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>follow备份 5</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -404.000000)" stroke="#444E60">
<g id="folder备份-2" transform="translate(8.000000, 404.000000)">
<line x1="6" y1="18" x2="18" y2="6" id="路径-2"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 636 B

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="4px" height="4px" viewBox="0 0 4 4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
<title>矩形</title>
<desc>Created with Sketch.</desc>
<g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="矩形" fill="#3381FF" fill-rule="nonzero" points="4 0 4 4 0 4"></polygon>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 507 B

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="4px" height="4px" viewBox="0 0 4 4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 55.1 (78136) - https://sketchapp.com -->
<title>矩形</title>
<desc>Created with Sketch.</desc>
<g id="页面1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<polygon id="矩形" fill="#444E60" fill-rule="nonzero" points="4 0 4 4 0 4"></polygon>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 507 B

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-48.000000, -80.000000)" stroke="#3381FF">
<g id="编组-2" transform="translate(48.000000, 80.000000)">
<polyline id="路径-16" points="6 6 18 6 18 8"></polyline>
<line x1="12" y1="6" x2="12" y2="16" id="路径-17"></line>
<line x1="6" y1="6" x2="6" y2="8" id="路径-18"></line>
<line x1="10" y1="18" x2="14" y2="18" id="路径-19"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 859 B

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="切图" transform="translate(-8.000000, -80.000000)" stroke="#444E60">
<g id="编组-2" transform="translate(8.000000, 80.000000)">
<polyline id="路径-16" points="6 6 18 6 18 8"></polyline>
<line x1="12" y1="6" x2="12" y2="16" id="路径-17"></line>
<line x1="6" y1="6" x2="6" y2="8" id="路径-18"></line>
<line x1="10" y1="18" x2="14" y2="18" id="路径-19"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 857 B

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-96.000000, -128.000000)" stroke="#3381FF">
<g id="编组-34备份" transform="translate(56.000000, 88.000000)">
<g id="follow备份-22" transform="translate(40.000000, 40.000000)">
<path d="M11.8735432,6.51639519 L18.4433604,16.8729099 C18.5014646,16.9705991 18.513552,17.0816789 18.4849451,17.1824518 C18.4637477,17.2571235 18.4207741,17.3254323 18.3599622,17.3797162 L18.3599622,17.3797162 L5.9619473,17.5 C5.83202254,17.5 5.71357665,17.4508256 5.62815063,17.3687543 C5.5756394,17.3183052 5.53576798,17.2551406 5.51530514,17.1841993 L5.51530514,17.1841993 L11.5944453,6.72141053 C11.6575042,6.61539105 11.7604689,6.5460226 11.8735432,6.51639519 L11.8735432,6.51639519 Z" id="多边形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>矩形备份 25</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="工具栏" transform="translate(-96.000000, -48.000000)" stroke="#444E60">
<g id="编组-34" transform="translate(56.000000, 8.000000)">
<g id="follow备份-22" transform="translate(40.000000, 40.000000)">
<path d="M11.8735432,6.51639519 L18.4433604,16.8729099 C18.5014646,16.9705991 18.513552,17.0816789 18.4849451,17.1824518 C18.4637477,17.2571235 18.4207741,17.3254323 18.3599622,17.3797162 L18.3599622,17.3797162 L5.9619473,17.5 C5.83202254,17.5 5.71357665,17.4508256 5.62815063,17.3687543 C5.5756394,17.3183052 5.53576798,17.2551406 5.51530514,17.1841993 L5.51530514,17.1841993 L11.5944453,6.72141053 C11.6575042,6.61539105 11.7604689,6.5460226 11.8735432,6.51639519 L11.8735432,6.51639519 Z" id="多边形"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
<title>upload-pressed</title>
<desc>Created with Sketch.</desc>
<g id="页面-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Whiteboard-Guidelines" transform="translate(-736.000000, -295.000000)">
<g id="upload-pressed" transform="translate(736.000000, 295.000000)">
<rect id="矩形备份-18" fill="#FFFFFF" opacity="0.01" x="0" y="0" width="40" height="40" rx="2"></rect>
<polyline id="路径-11备份-5" stroke="#3381FF" stroke-linecap="round" stroke-linejoin="round" transform="translate(20.000000, 14.000000) rotate(-270.000000) translate(-20.000000, -14.000000) " points="22 18 20 16 18 14 20 12 22 10"></polyline>
<polyline id="Stroke-11备份-3" stroke="#3381FF" stroke-linecap="round" stroke-linejoin="round" points="28 24 28 28 12 28 12 24"></polyline>
<line x1="20" y1="24" x2="20" y2="12" id="Stroke-3备份-3" stroke="#3381FF" stroke-linecap="round" stroke-linejoin="round"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="40px" height="40px" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
<title>upload</title>
<desc>Created with Sketch.</desc>
<g id="页面-4" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Whiteboard-Guidelines" transform="translate(-696.000000, -295.000000)">
<g id="upload" transform="translate(696.000000, 295.000000)">
<rect id="矩形备份-18" fill="#FFFFFF" opacity="0.01" x="0" y="0" width="40" height="40" rx="2"></rect>
<polyline id="路径-11备份-5" stroke="#212324" stroke-linecap="round" stroke-linejoin="round" transform="translate(20.000000, 14.000000) rotate(-270.000000) translate(-20.000000, -14.000000) " points="22 18 20 16 18 14 20 12 22 10"></polyline>
<polyline id="Stroke-11备份-3" stroke="#212324" stroke-linecap="round" stroke-linejoin="round" points="28 24 28 28 12 28 12 24"></polyline>
<line x1="20" y1="24" x2="20" y2="12" id="Stroke-3备份-3" stroke="#212324" stroke-linecap="round" stroke-linejoin="round"></line>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,228 +0,0 @@
<template>
<div class="tool-mid-box-left">
<!-- 工具循环 -->
<div class="tool-box-cell-box-left" v-for="item in tools" :key="item.shapeType">
<!-- <el-tooltip :content="item.name" placement="top-end">
<div class="tool-box-cell" @click="clickAppliance(item.shapeType)">
<img :src="item.shapeType === currentShapType ? item.iconActive : item.icon" :alt="item.name" />
</div>
</el-tooltip> -->
<el-tooltip :content="item.name" placement="top-end">
<div class="tool-box-cell" @click="clickAppliance(item.shapeType)">
<img
:src="(
// 当前是该工具
item.shapeType === currentShapType
// 当前在选颜色 / 粗细时保持上一个绘图工具高亮
|| (['colorSelector','brushSize'].includes(currentShapType) && item.shapeType === lastDrawingTool)
)
? item.iconActive
: item.icon"
:alt="item.name"
/>
</div>
</el-tooltip>
<!-- 颜色选择器 -->
<div v-if="item.shapeType === 'colorSelector' && currentShapType === 'colorSelector' && colorSelectorControl"
class="tool-popup">
<el-color-picker ref="colorPickerRef" v-model="selectedColor" v-model:visible="colorVisible" show-alpha
@change="handleColorChange" />
</div>
<!-- 画笔大小选择器 -->
<div v-if="item.shapeType === 'brushSize' && currentShapType === 'brushSize' && brushSizeControl"
class="tool-popup">
<el-select ref="brushSizeRef" v-model="selectedThickness" placeholder="画笔粗细" size="small"
@change="handleThicknessChange" v-model:visible="brushSizeVisible" style="width: 60px">
<el-option v-for="size in thicknessOptions" :key="size" :label="size + 'px'" :value="size" />
</el-select>
</div>
</div>
</div>
</template>
<script setup>
import { ref, nextTick, onMounted, onBeforeUnmount } from "vue";
const props = defineProps({
canvas: {
type: Object,
required: true,
validator: (value) => value && typeof value.setDrawingTool === "function",
},
});
// 工具图标导入
import pen from "./image/pencil.svg";
import penActive from "./image/pencil-active.svg";
import eraser from "./image/eraser.svg";
import eraserActive from "./image/eraser-active.svg";
import ellipse from "./image/ellipse.svg";
import ellipseActive from "./image/ellipse-active.svg";
import rectangle from "./image/rectangle.svg";
import rectangleActive from "./image/rectangle-active.svg";
import straight from "./image/straight.svg";
import straightActive from "./image/straight-active.svg";
import brushSize from "./image/brushSize.svg";
import brushSizeActive from "./image/brushSize-active.svg";
import colorSelector from "./image/colorSelector.svg";
import colorSelectorActive from "./image/colorSelector-active.svg";
const tools = ref([
{ name: "笔", icon: pen, iconActive: penActive, shapeType: "pencil" },
{ name: "圆形", icon: ellipse, iconActive: ellipseActive, shapeType: "circle" },
{ name: "矩形", icon: rectangle, iconActive: rectangleActive, shapeType: "rectangle" },
{ name: "直线", icon: straight, iconActive: straightActive, shapeType: "line" },
{ name: "选色器", icon: colorSelector, iconActive: colorSelectorActive, shapeType: "colorSelector" },
{ name: "画笔大小", icon: brushSize, iconActive: brushSizeActive, shapeType: "brushSize" },
{ name: "橡皮擦", icon: eraser, iconActive: eraserActive, shapeType: "eraser" },
]);
// 状态
const selectedColor = ref("#ffcc00");
const selectedThickness = ref(2);
const thicknessOptions = [1, 2, 4, 8, 16];
const colorSelectorControl = ref(false);
const brushSizeControl = ref(false);
const colorVisible = ref(false);
const brushSizeVisible = ref(false);
const currentShapType = ref("pencil"); // 当前点击的工具
const lastDrawingTool = ref("pencil"); // 记录最后一个绘图工具
// refs
const colorPickerRef = ref();
const brushSizeRef = ref();
// 颜色选择逻辑
const handleColorChange = (color) => {
props.canvas?.setColor(color);
colorSelectorControl.value = false;
colorVisible.value = false;
};
// 粗细选择逻辑
const handleThicknessChange = (size) => {
props.canvas?.setThickness(size);
brushSizeControl.value = false;
brushSizeVisible.value = false;
};
// 点击工具逻辑
function clickAppliance(type) {
// 点击同一个工具时切换关闭
if (currentShapType.value === type) {
if (type === "colorSelector") {
colorSelectorControl.value = !colorSelectorControl.value;
colorVisible.value = colorSelectorControl.value;
} else if (type === "brushSize") {
brushSizeControl.value = !brushSizeControl.value;
brushSizeVisible.value = brushSizeControl.value;
}
return;
}
// 切换到新工具
currentShapType.value = type;
lastDrawingTool.value = type; // 记录最新绘图工具
if (type === "colorSelector") {
colorSelectorControl.value = true;
brushSizeControl.value = false;
nextTick(() => {
colorVisible.value = true;
});
} else if (type === "brushSize") {
brushSizeControl.value = true;
colorSelectorControl.value = false;
nextTick(() => {
brushSizeVisible.value = true;
});
} else {
colorSelectorControl.value = false;
brushSizeControl.value = false;
colorVisible.value = false;
brushSizeVisible.value = false;
props.canvas?.setDrawingTool(type);
}
}
// 点击工具栏外部关闭弹窗
function handleClickOutside(event) {
const toolBox = document.querySelector(".tool-mid-box-left");
if (!toolBox.contains(event.target)) {
// colorSelectorControl.value = false;
brushSizeControl.value = false;
// colorVisible.value = false;
brushSizeVisible.value = false;
}
}
onMounted(() => {
if (!props.canvas || typeof props.canvas.setDrawingTool !== "function") {
console.error("Invalid canvas prop passed to ToolBox");
}
document.addEventListener("click", handleClickOutside);
});
onBeforeUnmount(() => {
document.removeEventListener("click", handleClickOutside);
});
</script>
<style lang="scss" scoped>
.tool-mid-box-left {
width: 40px;
display: flex;
border-radius: 4px;
background-color: white;
justify-content: flex-start;
align-items: center;
flex-direction: column;
padding: 4px 0;
box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.1);
}
.tool-box-cell {
width: 24px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: relative;
}
.tool-box-cell-box-left {
width: 32px;
height: 32px;
user-select: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
border-radius: 2px;
position: relative;
&:hover {
background: rgba(33, 35, 36, 0.1);
}
}
/* 弹出层样式:显示在图标右侧 */
.tool-popup {
position: absolute;
left: 40px;
/* 距离工具栏宽度 */
top: 50%;
transform: translateY(-50%);
background: white;
padding: 6px;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
}
</style>

View File

@@ -3,7 +3,7 @@
:default-active="activeMenu"
mode="horizontal"
@select="handleSelect"
:ellipsis="false"
:ellipsis="false"
>
<template v-for="(item, index) in topMenus">
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber"

View File

@@ -1,287 +0,0 @@
import EventEmitter from "@/utils/emitter";
/**
* Canvas绘图类支持多种图形绘制和多人同步
* 使用百分比坐标系统确保跨设备一致性
*/
class Canvas extends EventEmitter {
constructor(canvasId) {
super();
this.canvas = document.getElementById(canvasId);
if (!this.canvas) {
throw new Error(`Canvas element with id ${canvasId} not found`);
}
this.ctx = this.canvas.getContext('2d');
this.shapes = []; // 所有已绘制形状
this.currentShape = null; // 当前正在绘制的形状
this.isDrawing = false;
this.drawingTool = 'pencil';
this.pathOptimizationEnabled = true;
this.optimizationThreshold = 0.005;
this.currentColor = '#ffcc00';
this.currentThickness = 2;
this.resize();
// 绑定事件
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.canvas.addEventListener('mousedown', this.handleMouseDown);
this.canvas.addEventListener('mousemove', this.handleMouseMove);
this.canvas.addEventListener('mouseup', this.handleMouseUp);
this.canvas.addEventListener('mouseleave', this.handleMouseLeave);
window.addEventListener('resize', () => this.resize());
}
resize() {
const parent = this.canvas.parentElement;
if (!parent) return;
const containerWidth = parent.offsetWidth - 150;
const containerHeight = parent.offsetHeight;
let width = containerWidth;
let height = Math.floor((width * 9) / 16);
if (height > containerHeight) {
height = containerHeight;
width = Math.floor((height * 16) / 9);
}
if (this.canvas.width === width && this.canvas.height === height) return;
this.canvas.width = width;
this.canvas.height = height;
this.canvas.style.width = width + "px";
this.canvas.style.height = height + "px";
this.render();
}
setDrawingTool(tool) { this.drawingTool = tool; }
setColor(color) { this.currentColor = color; }
setThickness(size) { this.currentThickness = size; }
setPathOptimization(enabled) { this.pathOptimizationEnabled = enabled; }
setOptimizationThreshold(threshold) { this.optimizationThreshold = threshold; }
getShapes() { return this.shapes; }
setShapes(shapes) { this.shapes = shapes; this.render(); }
// 获取鼠标坐标,转换为百分比坐标
getMouseCoordinates(e) {
const rect = this.canvas.getBoundingClientRect();
return {
x:((e.clientX - rect.left) / this.canvas.width).toFixed(4),
y:((e.clientY - rect.top) / this.canvas.height).toFixed(4)
};
}
handleMouseDown(e) {
this.isDrawing = true;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil') {
this.currentShape = { type: 'pencil', data: { color: this.currentColor, path: [coords], thickness: this.currentThickness } };
} else if (this.drawingTool === 'line') {
this.currentShape = { type: 'line', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness } };
} else if (this.drawingTool === 'rectangle') {
this.currentShape = { type: 'rectangle', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness, fill: false } };
} else if (this.drawingTool === 'circle') {
this.currentShape = { type: 'circle', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness, fill: false } };
} else if (this.drawingTool === 'eraser') {
this.currentShape = { type: 'eraser', data: { color: '#ffffff', start: coords, end: coords, thickness: 3 } };
}
this.emit('drawingStart', this.currentShape);
}
handleMouseMove(e) {
if (!this.isDrawing || !this.currentShape) return;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil') {
this.currentShape.data.path.push(coords);
} else {
this.currentShape.data.end = coords;
}
this.render();
this.emit('drawingUpdate', this.currentShape);
}
handleMouseUp(e) {
if (!this.isDrawing || !this.currentShape) return;
this.isDrawing = false;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil' && this.pathOptimizationEnabled && this.currentShape.data.path.length > 10) {
this.currentShape.data.path = this.optimizePath(this.currentShape.data.path);
} else {
this.currentShape.data.end = coords;
}
this.shapes.push({ ...this.currentShape });
this.emit('drawingEnd', this.currentShape);
this.currentShape = null;
this.render();
}
handleMouseLeave(e) {
if (this.isDrawing) this.handleMouseUp(e);
}
optimizePath(path) {
if (path.length < 3) return path;
const optimizedPath = [path[0]];
for (let i = 1; i < path.length - 1;) {
let a = 1;
while (i + a < path.length && this.calculateDistance(path[i], path[i + a]) < this.optimizationThreshold) a++;
optimizedPath.push(path[i]);
i += a;
}
optimizedPath.push(path[path.length - 1]);
return optimizedPath;
}
calculateDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
addShape(shapeData) {
if (Array.isArray(shapeData)) this.shapes.push(...shapeData);
else this.shapes.push(shapeData);
this.render();
}
clearCanvas() {
this.shapes = [];
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.emit('clear');
}
exportToDataURL(type = 'image/png', quality = 1) {
return this.canvas.toDataURL(type, quality);
}
render() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// 绘制历史形状
this.shapes.forEach(shape => this.drawShape(shape));
// 绘制当前正在绘制的形状
if (this.currentShape) this.drawShape(this.currentShape);
// 画画布边框
this.ctx.save();
this.ctx.strokeStyle = "#000";
this.ctx.lineWidth = 2;
this.ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.restore();
}
drawShape(shape) {
switch (shape.type) {
case 'pencil': this.drawPencil(shape.data); break;
case 'line': this.drawLine(shape.data); break;
case 'rectangle': this.drawRectangle(shape.data); break;
case 'circle': this.drawCircle(shape.data); break;
case 'eraser': this.drawEraser(shape.data, shape); break;
}
}
drawPencil(p) {
if (p.path.length < 2) return;
const path = p.path.map(pt => ({ x: pt.x * this.canvas.width, y: pt.y * this.canvas.height }));
this.ctx.beginPath();
this.ctx.strokeStyle = p.color;
this.ctx.lineWidth = p.thickness;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
this.drawSmoothCurve(this.ctx, path);
this.ctx.stroke();
}
drawSmoothCurve(ctx, path) {
if (path.length < 3) { ctx.moveTo(path[0].x, path[0].y); for (let i = 1; i < path.length; i++) ctx.lineTo(path[i].x, path[i].y); return; }
ctx.moveTo(path[0].x, path[0].y);
const threshold = 5;
for (let i = 1; i < path.length - 2;) {
let a = 1;
while (i + a < path.length - 2 &&
Math.sqrt(Math.pow(path[i].x - path[i + a].x, 2) + Math.pow(path[i].y - path[i + a].y, 2)) < threshold) a++;
const xc = (path[i].x + path[i + a].x) / 2;
const yc = (path[i].y + path[i + a].y) / 2;
ctx.quadraticCurveTo(path[i].x, path[i].y, xc, yc);
i += a;
}
ctx.lineTo(path[path.length - 1].x, path[path.length - 1].y);
}
drawLine(l) {
const sx = l.start.x * this.canvas.width, sy = l.start.y * this.canvas.height;
const ex = l.end.x * this.canvas.width, ey = l.end.y * this.canvas.height;
this.ctx.beginPath();
this.ctx.moveTo(sx, sy);
this.ctx.lineTo(ex, ey);
this.ctx.strokeStyle = l.color;
this.ctx.lineWidth = l.thickness;
this.ctx.stroke();
}
drawRectangle(r) {
const sx = r.start.x * this.canvas.width, sy = r.start.y * this.canvas.height;
const ex = r.end.x * this.canvas.width, ey = r.end.y * this.canvas.height;
const w = ex - sx, h = ey - sy;
this.ctx.beginPath();
this.ctx.rect(sx, sy, w, h);
if (r.fill) { this.ctx.fillStyle = r.color; this.ctx.fill(); }
else { this.ctx.strokeStyle = r.color; this.ctx.lineWidth = r.thickness; this.ctx.stroke(); }
}
drawCircle(c) {
const sx = c.start.x * this.canvas.width, sy = c.start.y * this.canvas.height;
const ex = c.end.x * this.canvas.width, ey = c.end.y * this.canvas.height;
const cx = (sx + ex) / 2, cy = (sy + ey) / 2;
const rx = Math.abs(ex - sx) / 2, ry = Math.abs(ey - sy) / 2;
this.ctx.beginPath();
this.ctx.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI);
if (c.fill) { this.ctx.fillStyle = c.color; this.ctx.fill(); }
else { this.ctx.strokeStyle = c.color; this.ctx.lineWidth = c.thickness; this.ctx.stroke(); }
}
drawEraser(e, shapeObj) {
const sx = e.start.x * this.canvas.width, sy = e.start.y * this.canvas.height;
const ex = e.end.x * this.canvas.width, ey = e.end.y * this.canvas.height;
const w = Math.abs(ex - sx), h = Math.abs(ey - sy);
const x = Math.min(sx, ex), y = Math.min(sy, ey);
this.ctx.beginPath();
this.ctx.rect(x, y, w, h);
this.ctx.fillStyle = 'rgba(255,255,255)';
this.ctx.fill();
// 仅当前正在绘制的橡皮擦显示边框
if (this.currentShape && shapeObj === this.currentShape) {
this.ctx.save();
this.ctx.strokeStyle = '#000';
this.ctx.lineWidth = 1;
this.ctx.strokeRect(x, y, w, h);
this.ctx.restore();
}
}
destroy() {
this.canvas.removeEventListener('mousedown', this.handleMouseDown);
this.canvas.removeEventListener('mousemove', this.handleMouseMove);
this.canvas.removeEventListener('mouseup', this.handleMouseUp);
this.canvas.removeEventListener('mouseleave', this.handleMouseLeave);
window.removeEventListener('resize', this.resize);
}
}
export default Canvas;

View File

@@ -1,285 +0,0 @@
import EventEmitter from "@/utils/emitter";
/**
* Canvas绘图类支持多种图形绘制和多人同步
* 使用百分比坐标系统确保跨设备一致性
*/
class Canvas extends EventEmitter {
constructor(canvasId) {
super();
this.canvas = document.getElementById(canvasId);
if (!this.canvas) {
throw new Error(`Canvas element with id ${canvasId} not found`);
}
this.ctx = this.canvas.getContext('2d');
this.shapes = []; // 所有已绘制形状
this.currentShape = null; // 当前正在绘制的形状
this.isDrawing = false;
this.drawingTool = 'pencil';
this.pathOptimizationEnabled = true;
this.optimizationThreshold = 0.005;
this.currentColor = '#ffcc00';
this.currentThickness = 2;
this.resize();
// 绑定事件
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.canvas.addEventListener('mousedown', this.handleMouseDown);
this.canvas.addEventListener('mousemove', this.handleMouseMove);
this.canvas.addEventListener('mouseup', this.handleMouseUp);
this.canvas.addEventListener('mouseleave', this.handleMouseLeave);
window.addEventListener('resize', () => this.resize());
}
resize() {
const parent = this.canvas.parentElement;
if (!parent) return;
const containerWidth = parent.offsetWidth;
const containerHeight = parent.offsetHeight;
let width = containerWidth;
let height = Math.floor((width * 9) / 16);
if (height > containerHeight) {
height = containerHeight;
width = Math.floor((height * 16) / 9);
}
if (this.canvas.width === width && this.canvas.height === height) return;
this.canvas.width = width;
this.canvas.height = height;
this.canvas.style.width = width + "px";
this.canvas.style.height = height + "px";
this.render();
}
setDrawingTool(tool) { this.drawingTool = tool; }
setColor(color) { this.currentColor = color; }
setThickness(size) { this.currentThickness = size; }
setPathOptimization(enabled) { this.pathOptimizationEnabled = enabled; }
setOptimizationThreshold(threshold) { this.optimizationThreshold = threshold; }
getShapes() { return this.shapes; }
setShapes(shapes) { this.shapes = shapes; this.render(); }
getMouseCoordinates(e) {
const rect = this.canvas.getBoundingClientRect();
return {
x: (e.clientX - rect.left) / this.canvas.width,
y: (e.clientY - rect.top) / this.canvas.height
};
}
handleMouseDown(e) {
this.isDrawing = true;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil') {
this.currentShape = { type: 'pencil', data: { color: this.currentColor, path: [coords], thickness: this.currentThickness } };
} else if (this.drawingTool === 'line') {
this.currentShape = { type: 'line', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness } };
} else if (this.drawingTool === 'rectangle') {
this.currentShape = { type: 'rectangle', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness, fill: false } };
} else if (this.drawingTool === 'circle') {
this.currentShape = { type: 'circle', data: { color: this.currentColor, start: coords, end: coords, thickness: this.currentThickness, fill: false } };
} else if (this.drawingTool === 'eraser') {
this.currentShape = { type: 'eraser', data: { color: '#ffffff', start: coords, end: coords, thickness: 3 } };
}
this.emit('drawingStart', this.currentShape);
}
handleMouseMove(e) {
if (!this.isDrawing || !this.currentShape) return;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil') {
this.currentShape.data.path.push(coords);
} else {
this.currentShape.data.end = coords;
}
this.render();
this.emit('drawingUpdate', this.currentShape);
}
handleMouseUp(e) {
if (!this.isDrawing || !this.currentShape) return;
this.isDrawing = false;
const coords = this.getMouseCoordinates(e);
if (this.drawingTool === 'pencil' && this.pathOptimizationEnabled && this.currentShape.data.path.length > 10) {
this.currentShape.data.path = this.optimizePath(this.currentShape.data.path);
} else {
this.currentShape.data.end = coords;
}
this.shapes.push({ ...this.currentShape });
this.emit('drawingEnd', this.currentShape);
this.currentShape = null;
this.render();
}
handleMouseLeave(e) {
if (this.isDrawing) this.handleMouseUp(e);
}
optimizePath(path) {
if (path.length < 3) return path;
const optimizedPath = [path[0]];
for (let i = 1; i < path.length - 1;) {
let a = 1;
while (i + a < path.length && this.calculateDistance(path[i], path[i + a]) < this.optimizationThreshold) a++;
optimizedPath.push(path[i]);
i += a;
}
optimizedPath.push(path[path.length - 1]);
return optimizedPath;
}
calculateDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
addShape(shapeData) {
if (Array.isArray(shapeData)) this.shapes.push(...shapeData);
else this.shapes.push(shapeData);
this.render();
}
clearCanvas() {
this.shapes = [];
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.emit('clear');
}
exportToDataURL(type = 'image/png', quality = 1) {
return this.canvas.toDataURL(type, quality);
}
render() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// 绘制历史形状
this.shapes.forEach(shape => this.drawShape(shape));
// 绘制当前正在绘制的形状
if (this.currentShape) this.drawShape(this.currentShape);
// 画画布边框
this.ctx.save();
this.ctx.strokeStyle = "#000";
this.ctx.lineWidth = 2;
this.ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.restore();
}
drawShape(shape) {
switch (shape.type) {
case 'pencil': this.drawPencil(shape.data); break;
case 'line': this.drawLine(shape.data); break;
case 'rectangle': this.drawRectangle(shape.data); break;
case 'circle': this.drawCircle(shape.data); break;
case 'eraser': this.drawEraser(shape.data, shape); break;
}
}
drawPencil(p) {
if (p.path.length < 2) return;
const path = p.path.map(pt => ({ x: pt.x * this.canvas.width, y: pt.y * this.canvas.height }));
this.ctx.beginPath();
this.ctx.strokeStyle = p.color;
this.ctx.lineWidth = p.thickness;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
this.drawSmoothCurve(this.ctx, path);
this.ctx.stroke();
}
drawSmoothCurve(ctx, path) {
if (path.length < 3) { ctx.moveTo(path[0].x, path[0].y); for (let i = 1; i < path.length; i++) ctx.lineTo(path[i].x, path[i].y); return; }
ctx.moveTo(path[0].x, path[0].y);
const threshold = 5;
for (let i = 1; i < path.length - 2;) {
let a = 1;
while (i + a < path.length - 2 &&
Math.sqrt(Math.pow(path[i].x - path[i + a].x, 2) + Math.pow(path[i].y - path[i + a].y, 2)) < threshold) a++;
const xc = (path[i].x + path[i + a].x) / 2;
const yc = (path[i].y + path[i + a].y) / 2;
ctx.quadraticCurveTo(path[i].x, path[i].y, xc, yc);
i += a;
}
ctx.lineTo(path[path.length - 1].x, path[path.length - 1].y);
}
drawLine(l) {
const sx = l.start.x * this.canvas.width, sy = l.start.y * this.canvas.height;
const ex = l.end.x * this.canvas.width, ey = l.end.y * this.canvas.height;
this.ctx.beginPath();
this.ctx.moveTo(sx, sy);
this.ctx.lineTo(ex, ey);
this.ctx.strokeStyle = l.color;
this.ctx.lineWidth = l.thickness;
this.ctx.stroke();
}
drawRectangle(r) {
const sx = r.start.x * this.canvas.width, sy = r.start.y * this.canvas.height;
const ex = r.end.x * this.canvas.width, ey = r.end.y * this.canvas.height;
const w = ex - sx, h = ey - sy;
this.ctx.beginPath();
this.ctx.rect(sx, sy, w, h);
if (r.fill) { this.ctx.fillStyle = r.color; this.ctx.fill(); }
else { this.ctx.strokeStyle = r.color; this.ctx.lineWidth = r.thickness; this.ctx.stroke(); }
}
drawCircle(c) {
const sx = c.start.x * this.canvas.width, sy = c.start.y * this.canvas.height;
const ex = c.end.x * this.canvas.width, ey = c.end.y * this.canvas.height;
const cx = (sx + ex) / 2, cy = (sy + ey) / 2;
const rx = Math.abs(ex - sx) / 2, ry = Math.abs(ey - sy) / 2;
this.ctx.beginPath();
this.ctx.ellipse(cx, cy, rx, ry, 0, 0, 2 * Math.PI);
if (c.fill) { this.ctx.fillStyle = c.color; this.ctx.fill(); }
else { this.ctx.strokeStyle = c.color; this.ctx.lineWidth = c.thickness; this.ctx.stroke(); }
}
drawEraser(e, shapeObj) {
const sx = e.start.x * this.canvas.width, sy = e.start.y * this.canvas.height;
const ex = e.end.x * this.canvas.width, ey = e.end.y * this.canvas.height;
const w = Math.abs(ex - sx), h = Math.abs(ey - sy);
const x = Math.min(sx, ex), y = Math.min(sy, ey);
this.ctx.beginPath();
this.ctx.rect(x, y, w, h);
this.ctx.fillStyle = 'rgba(255,255,255)';
this.ctx.fill();
// 仅当前正在绘制的橡皮擦显示边框
if (this.currentShape && shapeObj === this.currentShape) {
this.ctx.save();
this.ctx.strokeStyle = '#000';
this.ctx.lineWidth = 1;
this.ctx.strokeRect(x, y, w, h);
this.ctx.restore();
}
}
destroy() {
this.canvas.removeEventListener('mousedown', this.handleMouseDown);
this.canvas.removeEventListener('mousemove', this.handleMouseMove);
this.canvas.removeEventListener('mouseup', this.handleMouseUp);
this.canvas.removeEventListener('mouseleave', this.handleMouseLeave);
window.removeEventListener('resize', this.resize);
}
}
export default Canvas;

View File

@@ -83,8 +83,7 @@ const clickJoin = async () => {
inviteDialog.value = false
router.push({
path: '/conferencingRoom',
query:{
type:2,//创建房间,加入房间 2
query:{
room_uid:socketInformation.value.room_uid
}
})
@@ -132,7 +131,7 @@ defineExpose({
// onMounted(async () => {
// await mqttClient.connect(`room${Math.random().toString(16).substr(2, 8)}`);
// const res = await userStore.getInfo()
// const topic = `xSynergy/ROOM/+/rooms/${res.uid}`;
// const topic = `xsynergy/room/+/rooms/${res.uid}`;
// mqttClient.subscribe(topic, async (shapeData) => {
// // console.log(shapeData.toString(),'shapeData发送邀请')
// processingSocket(shapeData.toString())

Some files were not shown because too many files have changed in this diff Show More