From 3544208baaf255a76bb8b8f54fbe41944fdfbf29 Mon Sep 17 00:00:00 2001 From: YiLin <482244139@qq.com> Date: Wed, 1 Jul 2026 11:35:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B7=A5=E4=BD=9C=E5=8C=BA?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E9=80=BB=E8=BE=91=EF=BC=9B=E4=BA=91=E7=AB=AF?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- manifest.json | 5 +- pages/CloudDatabase/CloudDatabase.css | 184 ++ pages/CloudDatabase/CloudDatabase.vue | 1864 +++++++++++------ pages/WorkSpace/WorkSpace.vue | 150 +- unpackage/dist/dev/app-plus/app-service.js | 1409 +++++++++++-- unpackage/dist/dev/app-plus/manifest.json | 5 +- .../pages/CloudDatabase/CloudDatabase.css | 162 ++ utils/cloud-api.js | 806 +++++++ 8 files changed, 3722 insertions(+), 863 deletions(-) diff --git a/manifest.json b/manifest.json index 05614f7..079af25 100644 --- a/manifest.json +++ b/manifest.json @@ -42,7 +42,10 @@ "", "", "", - "" + "", + "", + "", + "" ] }, /* ios打包配置 */ diff --git a/pages/CloudDatabase/CloudDatabase.css b/pages/CloudDatabase/CloudDatabase.css index d1595f5..ffa7f69 100644 --- a/pages/CloudDatabase/CloudDatabase.css +++ b/pages/CloudDatabase/CloudDatabase.css @@ -394,6 +394,31 @@ font-weight: 500; } +.team-info { + margin-top: 14rpx; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 12rpx; +} + +.team-type-tag { + font-size: 22rpx; + color: #3b86ff; + background: rgba(59, 134, 255, 0.1); + padding: 6rpx 16rpx; + border-radius: 8rpx; + font-weight: 500; +} + +.team-desc-text { + font-size: 24rpx; + color: #999; + line-height: 1.5; + flex: 1; + min-width: 0; +} + .select-team-tip { padding: 80rpx 0; } @@ -595,6 +620,11 @@ background: rgba(59, 134, 255, 0.1); } +.member-role.member { + color: #67c23a; + background: rgba(103, 194, 58, 0.1); +} + .member-actions-right { display: flex; gap: 8rpx; @@ -611,6 +641,11 @@ border: 1rpx solid #3b86ff; } +.demote-admin { + color: #e6a23c; + border: 1rpx solid #e6a23c; +} + .remove-member { color: #f56c6c; border: 1rpx solid #f56c6c; @@ -645,6 +680,88 @@ padding: 14rpx 32rpx; } +/* 搜索结果列表 */ +.search-result-list { + margin-top: 16rpx; + border-radius: 14rpx; + overflow: hidden; + background: #f8f9fc; +} + +.search-result-item { + display: flex; + align-items: center; + padding: 18rpx 20rpx; + border-bottom: 1rpx solid #eee; +} + +.search-result-item:last-child { + border-bottom: none; +} + +.search-result-item:active { + background: rgba(59, 134, 255, 0.05); +} + +.result-avatar { + width: 64rpx; + height: 64rpx; + border-radius: 50%; + flex-shrink: 0; + margin-right: 16rpx; +} + +.result-default-avatar { + width: 64rpx; + height: 64rpx; + border-radius: 50%; + background: linear-gradient(135deg, #3b86ff, #6db3ff); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + margin-right: 16rpx; +} + +.result-info { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 4rpx; +} + +.result-name { + font-size: 28rpx; + color: #333; + font-weight: 500; +} + +.result-email { + font-size: 22rpx; + color: #999; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.result-add-btn { + flex-shrink: 0; + font-size: 24rpx; + color: #3b86ff; + padding: 10rpx 24rpx; + border: 1rpx solid #3b86ff; + border-radius: 20rpx; +} + +.search-empty { + margin-top: 16rpx; + text-align: center; + font-size: 24rpx; + color: #bbb; + padding: 20rpx 0; +} + .folder-null { display: flex; flex-direction: column; @@ -661,9 +778,76 @@ color: #ddd; } +/* 删除团队 */ +.delete-team-section { + border-top: 1rpx solid #eee; + padding-top: 20rpx; + margin-top: 10rpx; +} + +.delete-team-btn { + text-align: center; + padding: 18rpx; + font-size: 26rpx; + color: #e74c3c; + background: rgba(231, 76, 60, 0.06); + border-radius: 14rpx; + border: 1rpx solid rgba(231, 76, 60, 0.2); +} + +.delete-team-btn:active { + background: rgba(231, 76, 60, 0.12); +} + +/* 修改团队信息 */ +.edit-team-section { + border-top: 1rpx solid #eee; + padding-top: 20rpx; + margin-top: 10rpx; +} + +.edit-team-btn { + text-align: center; + padding: 18rpx; + font-size: 26rpx; + color: #3b86ff; + background: rgba(59, 134, 255, 0.06); + border-radius: 14rpx; + border: 1rpx solid rgba(59, 134, 255, 0.2); +} + +.edit-team-btn:active { + background: rgba(59, 134, 255, 0.12); +} + +.edit-team-form { + margin-bottom: 10rpx; +} + +.form-label { + font-size: 26rpx; + color: #666; + margin-bottom: 8rpx; + margin-top: 18rpx; +} + .text-btn { padding: 8rpx 20rpx; border-radius: 30rpx; font-size: 14px; font-weight: 500; +} + +/* ===== 上传文件弹窗 ===== */ +.upload-path-label { + font-size: 26rpx; + color: #666; + margin-bottom: 10rpx; +} + +.upload-path-hint { + font-size: 22rpx; + color: #999; + margin-bottom: 20rpx; + text-align: center; } \ No newline at end of file diff --git a/pages/CloudDatabase/CloudDatabase.vue b/pages/CloudDatabase/CloudDatabase.vue index bdbbb8d..7bbfed0 100644 --- a/pages/CloudDatabase/CloudDatabase.vue +++ b/pages/CloudDatabase/CloudDatabase.vue @@ -12,7 +12,7 @@ 暂无团队成员 - + @@ -20,15 +20,26 @@ - {{ member.friendNickName || member.username || member.name }} + {{ member.friendNickName || member.username || member.name }} + {{ member.email || member.sessionId || '' }} - 创建者 - 管理员 + + + {{ currentUserRoleInTeam === 'owner' ? '创建者' : '管理员' }} + + + 创建者 + + + 降为成员 + 移除 + + - 设为管理 - 移除 + 设为管理 + 移除 @@ -38,9 +49,64 @@ - - 邀请 + + 搜索 + + + + + + + + + {{ user.username }} + {{ user.email }} + + 添加 + + + 未找到匹配用户 + + + + + 修改团队信息 + + + + + 删除团队 + + + + + + + + + + + 修改团队信息 + + 团队名称 + + + + 团队描述 + + + + + + + 取消 + 确认修改 @@ -65,7 +131,26 @@ - + + + + + + + 上传文件 + 上传路径 + + + + 默认为根目录 /,后端会自动创建不存在的文件夹 + + 取消 + 确认上传 + + + + + @@ -101,11 +186,11 @@ - + @@ -130,13 +215,18 @@ 云端文件 - {{ personalFileCount > 0 ? '(' + personalFileCount + ')' : '' }} + {{ personalFileCount > 0 ? '(' + personalFileCount + ')' : '' }} - + + + 上传文件 + + @@ -227,6 +317,10 @@ {{ team.name }} + + {{ currentTeamType }} + {{ currentTeamDescription }} + @@ -242,10 +336,14 @@ 团队云端文件 - + + + 上传文件 + + @@ -314,669 +412,1165 @@ + @import url("CloudDatabase.css"); + \ No newline at end of file diff --git a/pages/WorkSpace/WorkSpace.vue b/pages/WorkSpace/WorkSpace.vue index 444c1fc..b19fc3a 100644 --- a/pages/WorkSpace/WorkSpace.vue +++ b/pages/WorkSpace/WorkSpace.vue @@ -317,28 +317,13 @@ uni.downloadFile({ url: downloadUrl, - name: fileName, // 重要:指定文件名,保证打开正常 + name: fileName, success: (downloadRes) => { uni.hideLoading(); if (downloadRes.statusCode === 200) { - // 下载成功 → 直接打开文件 - uni.openDocument({ - filePath: downloadRes.tempFilePath, - showMenu: true, // 右上角显示 分享/保存 按钮 - success: () => { - uni.showToast({ - title: '打开成功', - icon: 'success' - }); - }, - fail: (err) => { - console.error('打开失败:', err); - uni.showToast({ - title: '无法打开此文件', - icon: 'error' - }); - } - }); + const tempPath = downloadRes.tempFilePath; + // 下载成功,保存到 yxd 目录 + saveFileToYxd(fileName, tempPath); } else { uni.showToast({ title: '下载失败', icon: 'error' }); } @@ -356,6 +341,133 @@ } }; + // 将下载的文件保存到外部存储 yxd 目录 + const saveFileToYxd = (fileName, tempPath) => { + // #ifdef APP-PLUS + // App 端:复制文件到 /storage/emulated/0/yxd/ + const YXD_PATH = '/storage/emulated/0/yxd/'; + + const ensureYxdDir = (callback) => { + plus.io.resolveLocalFileSystemURL(YXD_PATH, (dirEntry) => { + callback(dirEntry); + }, () => { + plus.io.resolveLocalFileSystemURL('/storage/emulated/0/', (rootEntry) => { + rootEntry.getDirectory('yxd', { create: true }, (dirEntry) => { + callback(dirEntry); + }, (err) => { + console.error('创建 yxd 目录失败:', JSON.stringify(err)); + uni.showToast({ title: '创建目录失败', icon: 'error' }); + openFileConfirm(fileName, tempPath); + }); + }, (err) => { + console.error('访问外部存储根目录失败:', JSON.stringify(err)); + uni.showToast({ title: '无法访问存储目录', icon: 'error' }); + openFileConfirm(fileName, tempPath); + }); + }); + }; + + ensureYxdDir((yxdDirEntry) => { + plus.io.resolveLocalFileSystemURL(tempPath, (fileEntry) => { + fileEntry.copyTo( + yxdDirEntry, + fileName, + () => { + const targetPath = YXD_PATH + fileName; + console.log('文件已保存到:', targetPath); + openFileConfirm(fileName, targetPath); + }, + (err) => { + console.error('复制文件失败:', JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + } + ); + }, (err) => { + console.error('读取临时文件失败:', JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + }); + }); + // #endif + // #ifndef APP-PLUS + uni.saveFile({ + tempFilePath: tempPath, + success: (saveRes) => { + openFileConfirm(fileName, saveRes.savedFilePath); + }, + fail: () => { + openFileConfirm(fileName, tempPath); + } + }); + // #endif + }; + + // 下载成功后确认是否打开文件 + const openFileConfirm = (fileName, filePath) => { + uni.showActionSheet({ + title: `${fileName} 下载完成`, + itemList: ['打开文件', '选择其他应用打开', '仅保存'], + success: (res) => { + switch (res.tapIndex) { + case 0: + openFile(filePath); + break; + case 1: + openFileWithMenu(filePath); + break; + case 2: + uni.showToast({ + title: '文件已保存到 yxd 目录', + icon: 'success' + }); + break; + } + }, + fail: () => { + uni.showToast({ + title: '文件已保存到 yxd 目录', + icon: 'success' + }); + } + }); + }; + + // 使用系统默认应用打开 + const openFile = (filePath) => { + uni.openDocument({ + filePath: filePath, + success: () => uni.showToast({ + title: '打开成功', + icon: 'success' + }), + fail: (err) => { + console.error('打开文件失败:', err); + uni.showToast({ + title: '无法打开此文件', + icon: 'error' + }); + } + }); + }; + + // 选择其他应用打开 + const openFileWithMenu = (filePath) => { + uni.openDocument({ + filePath: filePath, + showMenu: true, + success: () => uni.showToast({ + title: '打开成功', + icon: 'success' + }), + fail: (err) => { + console.error('打开文件失败:', err); + uni.showToast({ + title: '无法打开此文件', + icon: 'error' + }); + } + }); + }; + // 删除 const handleDelete = (folder) => { uni.showModal({ diff --git a/unpackage/dist/dev/app-plus/app-service.js b/unpackage/dist/dev/app-plus/app-service.js index 9f434dd..a2bec02 100644 --- a/unpackage/dist/dev/app-plus/app-service.js +++ b/unpackage/dist/dev/app-plus/app-service.js @@ -595,6 +595,319 @@ if (uni.restoreGlobal) { }); }); }; + const deleteCloudFile = (token, fileId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/file/delete`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "file_id": fileId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "删除云端文件出错啦"; + reject(msg); + } + } else { + reject(`删除云端文件失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const uploadCloudFile = (token, type, path, files, team_id) => { + return new Promise((resolve, reject) => { + const teamIdStr = team_id == null ? "" : String(team_id); + uni.uploadFile({ + url: `${BASE_URL}/cloud_api/file/upload`, + method: "POST", + // 不要手动设置 Content-Type,浏览器自动生成 multipart/form-data + header: { + // 如果后端把token放header就写这里,放表单里就写到formData + }, + // 普通文本参数(对应form-data里的文本项) + formData: { + access_token: token, + path: path || "/", + type, + team_id: teamIdStr + }, + // 多文件:每个文件name都叫files,和Postman保持一致 + files: files.map((fileItem) => ({ + uri: fileItem.tempFilePath, + // 文件本地临时路径 + name: "files" + })), + success: (res) => { + if (res.statusCode === 200) { + try { + const respond = JSON.parse(res.data); + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "获取云端文件url出错啦"; + reject(msg); + } + } catch (e2) { + reject("接口返回数据格式异常"); + } + } else { + reject(`获取云端文件url失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const getTeamList = async (token) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/list`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + access_token: token, + team_name: "" + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + const teamsList = respond.teams; + const newList = teamsList.slice(1); + resolve(newList); + } else { + const msg = res.data.error || "获取用户可访问的团队列表出错啦"; + reject(msg); + } + } else { + reject(`获取用户可访问的团队列表失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const getTeamAllMember = (token, teamId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/get_all_member`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId + }, + success: (res) => { + var _a; + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + const members = ((_a = respond.team) == null ? void 0 : _a.result) || []; + resolve(members); + } else { + const msg = (respond == null ? void 0 : respond.error) || "获取团队全部成员出错啦"; + reject(msg); + } + } else { + reject(`获取团队全部成员失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const deleteTeam = (token, teamId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/delete`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "删除团队出错啦"; + reject(msg); + } + } else { + reject(`删除团队失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const addTeamMember = (token, teamId, userIds) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/add_member`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId, + "user_ids": userIds, + "role": "admin" + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "添加团队成员出错啦"; + reject(msg); + } + } else { + reject(`添加团队成员失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const updateTeamInfo = (token, teamId, data) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/update`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId, + ...data + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "修改团队信息出错啦"; + reject(msg); + } + } else { + reject(`修改团队信息失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const removeTeamMember = (token, teamId, userIds) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/remove_member`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId, + "user_ids": userIds + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "移除团队成员出错啦"; + reject(msg); + } + } else { + reject(`移除团队成员失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const updateTeamMemberRole = (token, teamId, userId, role) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/adjust_member_role`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: { + "access_token": token, + "team_id": teamId, + "user_id": userId, + "role": role + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if (respond.success) { + resolve(respond.message); + } else { + const msg = (respond == null ? void 0 : respond.error) || "调整团员身份出错啦"; + reject(msg); + } + } else { + reject(`调整团员身份失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { @@ -6073,44 +6386,130 @@ This will fail in production.`); uni.downloadFile({ url: downloadUrl, name: fileName, - // 重要:指定文件名,保证打开正常 success: (downloadRes) => { uni.hideLoading(); if (downloadRes.statusCode === 200) { - uni.openDocument({ - filePath: downloadRes.tempFilePath, - showMenu: true, - // 右上角显示 分享/保存 按钮 - success: () => { - uni.showToast({ - title: "打开成功", - icon: "success" - }); - }, - fail: (err) => { - formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:335", "打开失败:", err); - uni.showToast({ - title: "无法打开此文件", - icon: "error" - }); - } - }); + const tempPath = downloadRes.tempFilePath; + saveFileToYxd(fileName, tempPath); } else { uni.showToast({ title: "下载失败", icon: "error" }); } }, fail: (err) => { uni.hideLoading(); - formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:348", "下载文件失败:", err); + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:333", "下载文件失败:", err); uni.showToast({ title: "下载失败,请重试", icon: "error" }); } }); } catch (error) { uni.hideLoading(); - formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:354", "获取下载链接失败:", error); + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:339", "获取下载链接失败:", error); uni.showToast({ title: "获取下载链接失败,请重试", icon: "error" }); } }; + const saveFileToYxd = (fileName, tempPath) => { + const YXD_PATH = "/storage/emulated/0/yxd/"; + const ensureYxdDir = (callback) => { + plus.io.resolveLocalFileSystemURL(YXD_PATH, (dirEntry) => { + callback(dirEntry); + }, () => { + plus.io.resolveLocalFileSystemURL("/storage/emulated/0/", (rootEntry) => { + rootEntry.getDirectory("yxd", { create: true }, (dirEntry) => { + callback(dirEntry); + }, (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:358", "创建 yxd 目录失败:", JSON.stringify(err)); + uni.showToast({ title: "创建目录失败", icon: "error" }); + openFileConfirm(fileName, tempPath); + }); + }, (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:363", "访问外部存储根目录失败:", JSON.stringify(err)); + uni.showToast({ title: "无法访问存储目录", icon: "error" }); + openFileConfirm(fileName, tempPath); + }); + }); + }; + ensureYxdDir((yxdDirEntry) => { + plus.io.resolveLocalFileSystemURL(tempPath, (fileEntry) => { + fileEntry.copyTo( + yxdDirEntry, + fileName, + () => { + const targetPath = YXD_PATH + fileName; + formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:377", "文件已保存到:", targetPath); + openFileConfirm(fileName, targetPath); + }, + (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:381", "复制文件失败:", JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + } + ); + }, (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:386", "读取临时文件失败:", JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + }); + }); + }; + const openFileConfirm = (fileName, filePath) => { + uni.showActionSheet({ + title: `${fileName} 下载完成`, + itemList: ["打开文件", "选择其他应用打开", "仅保存"], + success: (res) => { + switch (res.tapIndex) { + case 0: + openFile(filePath); + break; + case 1: + openFileWithMenu(filePath); + break; + case 2: + uni.showToast({ + title: "文件已保存到 yxd 目录", + icon: "success" + }); + break; + } + }, + fail: () => { + uni.showToast({ + title: "文件已保存到 yxd 目录", + icon: "success" + }); + } + }); + }; + const openFile = (filePath) => { + uni.openDocument({ + filePath, + success: () => uni.showToast({ + title: "打开成功", + icon: "success" + }), + fail: (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:443", "打开文件失败:", err); + uni.showToast({ + title: "无法打开此文件", + icon: "error" + }); + } + }); + }; + const openFileWithMenu = (filePath) => { + uni.openDocument({ + filePath, + showMenu: true, + success: () => uni.showToast({ + title: "打开成功", + icon: "success" + }), + fail: (err) => { + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:462", "打开文件失败:", err); + uni.showToast({ + title: "无法打开此文件", + icon: "error" + }); + } + }); + }; const handleDelete = (folder) => { uni.showModal({ title: "提示", @@ -6119,12 +6518,12 @@ This will fail in production.`); if (res.confirm) { try { const filePath = `./${folder.path}`; - formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:369", "删除的是:", filePath); + formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:481", "删除的是:", filePath); await daleteWorkspace(UserToken.value, workspaceId.value, filePath); uni.showToast({ title: "删除成功", icon: "success" }); initCurrentFolderList(); } catch (error) { - formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:374", "删除失败:", error); + formatAppLog("error", "at pages/WorkSpace/WorkSpace.vue:486", "删除失败:", error); uni.showToast({ title: "删除失败,请重试", icon: "error" }); } } @@ -6189,7 +6588,7 @@ This will fail in production.`); const currentFolderList = vue.ref([]); const getCurrentFolderList = () => { var _a, _b; - formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:452", "当前路径为:", JSON.stringify(folderStack.value)); + formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:564", "当前路径为:", JSON.stringify(folderStack.value)); const currentPath = folderStack.value.length > 0 ? folderStack.value[folderStack.value.length - 1].path : "."; if (currentPath === ".") { return ((_a = allFoldersData.value) == null ? void 0 : _a.children) || []; @@ -6213,7 +6612,7 @@ This will fail in production.`); const initCurrentFolderList = async () => { workspaceId.value = getWorkspaceId(); UserToken.value = getToken(); - formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:479", "getWorkspaceId:", workspaceId.value); + formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:591", "getWorkspaceId:", workspaceId.value); allFoldersData.value = await getWorkspaceList(UserToken.value, workspaceId.value); currentFolderList.value = getCurrentFolderList(); }; @@ -6258,7 +6657,7 @@ This will fail in production.`); uni.navigateBack({ delta: 1, fail() { - formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:536", "返回失败,进入兜底跳转"); + formatAppLog("log", "at pages/WorkSpace/WorkSpace.vue:648", "返回失败,进入兜底跳转"); uni.reLaunch({ url: "/pages/Chat/Chat" }); @@ -6269,7 +6668,7 @@ This will fail in production.`); vue.onMounted(() => { initCurrentFolderList(); }); - const __returned__ = { UserToken, workspaceId, navbarBeforeTitle, navbarTitle, isSelectFolder, selectFileList, handleSelectFolder, selectFolder, showNewFolder, isNFNFocused, newFolderName, closeNewFolderModal, newWorkspaceFolder, currentFolderPath, folderPathPreview, confirmCreateFolder, handleLongPress, handleRename, handleDownload, handleDelete, isMenuOpen, handleMenu, searchKeyword, isSearchFocus, handleSearchFocus, getFileIcon, allFoldersData, folderStack, currentFolderList, getCurrentFolderList, initCurrentFolderList, handleFolderClick, handleSelectAll, handleBackOrCheck, onMounted: vue.onMounted, ref: vue.ref, computed: vue.computed, get getWorkspaceId() { + const __returned__ = { UserToken, workspaceId, navbarBeforeTitle, navbarTitle, isSelectFolder, selectFileList, handleSelectFolder, selectFolder, showNewFolder, isNFNFocused, newFolderName, closeNewFolderModal, newWorkspaceFolder, currentFolderPath, folderPathPreview, confirmCreateFolder, handleLongPress, handleRename, handleDownload, saveFileToYxd, openFileConfirm, openFile, openFileWithMenu, handleDelete, isMenuOpen, handleMenu, searchKeyword, isSearchFocus, handleSearchFocus, getFileIcon, allFoldersData, folderStack, currentFolderList, getCurrentFolderList, initCurrentFolderList, handleFolderClick, handleSelectAll, handleBackOrCheck, onMounted: vue.onMounted, ref: vue.ref, computed: vue.computed, get getWorkspaceId() { return getWorkspaceId; }, get getToken() { return getToken; @@ -8958,7 +9357,9 @@ This will fail in production.`); uni.navigateBack({ delta: 1, fail() { - uni.reLaunch({ url: "/pages/Chat/Chat" }); + uni.reLaunch({ + url: "/pages/Chat/Chat" + }); } }); } @@ -9042,7 +9443,9 @@ This will fail in production.`); return "icon-PPT"; if (mimeType.includes("pdf")) return "icon-PDF"; - if (mimeType.includes("zip") || mimeType.includes("rar") || mimeType.includes("tar") || mimeType.includes("gzip")) + if (mimeType.includes("zip") || mimeType.includes("rar") || mimeType.includes("tar") || mimeType.includes( + "gzip" + )) return "icon-wenjianyasuo"; return "icon-qitawenjian"; }; @@ -9099,19 +9502,20 @@ This will fail in production.`); personalFiles.value = personalData || []; } } catch (error) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:509", "获取文件列表失败:", error); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:652", "获取文件列表失败:", error); rawPersonalFileData.value = []; personalFiles.value = []; } }; const fetchTeamFileList = async (teamId) => { try { + teamId = teamId == null ? "" : String(teamId); const teamData = await getCloudFileList(userToken.value, "team", "/", teamId); - formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:519", "团队云端文件:", JSON.stringify(teamData)); + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:663", "团队云端文件:", JSON.stringify(teamData)); rawTeamFileData.value = teamData || []; teamFiles.value = teamData || []; } catch (error) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:523", "获取团队文件列表失败:", error); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:667", "获取团队文件列表失败:", error); rawTeamFileData.value = []; teamFiles.value = []; } @@ -9170,18 +9574,28 @@ This will fail in production.`); }; const handleDownload = async (file) => { if (isFolder(file)) { - uni.showToast({ title: "暂不支持下载目录", icon: "none" }); + uni.showToast({ + title: "暂不支持下载目录", + icon: "none" + }); return; } try { - uni.showLoading({ title: "获取下载链接..." }); + uni.showLoading({ + title: "获取下载链接..." + }); const downloadUrl = await getCloudFileUrl(userToken.value, file.id); uni.hideLoading(); if (!downloadUrl) { - uni.showToast({ title: "获取下载链接失败", icon: "error" }); + uni.showToast({ + title: "获取下载链接失败", + icon: "error" + }); return; } - uni.showLoading({ title: "下载中..." }); + uni.showLoading({ + title: "下载中..." + }); uni.downloadFile({ url: downloadUrl, success: (downloadRes) => { @@ -9190,58 +9604,69 @@ This will fail in production.`); const tempPath = downloadRes.tempFilePath; saveFileToYxd(file.name, tempPath); } else { - uni.showToast({ title: "下载失败", icon: "error" }); + uni.showToast({ + title: "下载失败", + icon: "error" + }); } }, fail: () => { uni.hideLoading(); - uni.showToast({ title: "下载失败,请重试", icon: "error" }); + uni.showToast({ + title: "下载失败,请重试", + icon: "error" + }); } }); } catch (error) { uni.hideLoading(); - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:614", "下载失败:", error); - uni.showToast({ title: "下载失败,请重试", icon: "error" }); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:784", "下载失败:", error); + uni.showToast({ + title: "下载失败,请重试", + icon: "error" + }); } }; const saveFileToYxd = (fileName, tempPath) => { - try { - const yxdDir = `_doc/yxd/`; - const targetPath = `${yxdDir}${fileName}`; - plus.io.resolveLocalFileSystemURL(yxdDir, (dirEntry) => { - copyFileToDir(tempPath, targetPath, fileName); + const YXD_PATH = "/storage/emulated/0/yxd/"; + const ensureYxdDir = (callback) => { + plus.io.resolveLocalFileSystemURL(YXD_PATH, (dirEntry) => { + callback(dirEntry); }, () => { - plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => { - fs.root.getDirectory("yxd", { create: true }, (dirEntry) => { - copyFileToDir(tempPath, targetPath, fileName); + plus.io.resolveLocalFileSystemURL("/storage/emulated/0/", (rootEntry) => { + rootEntry.getDirectory("yxd", { create: true }, (dirEntry) => { + callback(dirEntry); }, (err) => { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:638", "创建 yxd 目录失败:", err); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:808", "创建 yxd 目录失败:", JSON.stringify(err)); uni.showToast({ title: "创建目录失败", icon: "error" }); + openFileConfirm(fileName, tempPath); }); + }, (err) => { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:813", "访问外部存储根目录失败:", JSON.stringify(err)); + uni.showToast({ title: "无法访问存储目录", icon: "error" }); + openFileConfirm(fileName, tempPath); }); }); - } catch (e2) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:644", "保存文件失败:", e2); - uni.showToast({ title: "保存失败", icon: "error" }); - } - }; - const copyFileToDir = (tempPath, targetPath, fileName) => { - plus.io.resolveLocalFileSystemURL(tempPath, (fileEntry) => { - fileEntry.copyTo( - plus.io.convertLocalFileSystemURL(targetPath).replace(fileName, ""), - fileName, - () => { - formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:670", "文件已保存到 yxd 目录:", targetPath); - openFileConfirm(fileName, targetPath); - }, - (err) => { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:675", "复制文件失败:", err); - openFileConfirm(fileName, tempPath); - } - ); - }, () => { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:681", "读取临时文件失败"); - openFileConfirm(fileName, tempPath); + }; + ensureYxdDir((yxdDirEntry) => { + plus.io.resolveLocalFileSystemURL(tempPath, (fileEntry) => { + fileEntry.copyTo( + yxdDirEntry, + fileName, + () => { + const targetPath = YXD_PATH + fileName; + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:827", "文件已保存到:", targetPath); + openFileConfirm(fileName, targetPath); + }, + (err) => { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:831", "复制文件失败:", JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + } + ); + }, (err) => { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:836", "读取临时文件失败:", JSON.stringify(err)); + openFileConfirm(fileName, tempPath); + }); }); }; const openFileConfirm = (fileName, filePath) => { @@ -9257,28 +9682,37 @@ This will fail in production.`); openFileWithMenu(filePath); break; case 2: - uni.showToast({ title: "文件已保存到 yxd 目录", icon: "success" }); + uni.showToast({ + title: "文件已保存到 yxd 目录", + icon: "success" + }); break; } }, fail: () => { - uni.showToast({ title: "文件已保存到 yxd 目录", icon: "success" }); + uni.showToast({ + title: "文件已保存到 yxd 目录", + icon: "success" + }); } }); }; const openFile = (filePath) => { uni.openDocument({ filePath, - success: () => uni.showToast({ title: "打开成功", icon: "success" }), + success: () => uni.showToast({ + title: "打开成功", + icon: "success" + }), fail: (err) => { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:720", "打开文件失败:", err); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:899", "打开文件失败:", err); openFileWithMenu(filePath); } }); }; const openFileWithMenu = (filePath) => { plus.runtime.openFile(filePath, {}, (e2) => { - formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:732", "文件打开成功"); + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:911", "文件打开成功"); }); }; const handleRename = (file) => { @@ -9289,28 +9723,55 @@ This will fail in production.`); placeholderText: file.name, success: (res) => { if (res.confirm && res.content) { - uni.showToast({ title: "重命名成功", icon: "success" }); + uni.showToast({ + title: "重命名成功", + icon: "success" + }); refreshCurrentFileList(); } } }); }; const handleDeleteFile = (file) => { + const tipText = isFolder(file) ? `确定要删除目录"${file.name}"吗?目录内所有文件将被一并删除。` : `确定要删除文件"${file.name}"吗?`; uni.showModal({ - title: "提示", - content: `确定要删除"${file.name}"吗?`, + title: "删除确认", + content: tipText, + confirmText: "删除", + confirmColor: "#e74c3c", success: async (res) => { if (res.confirm) { + uni.showLoading({ + title: "删除中..." + }); try { - const filePath = file.full_path && !file.full_path.startsWith("http") ? file.full_path : file.path + file.name; - if (workspaceId.value) { - await daleteWorkspace(userToken.value, workspaceId.value, filePath); - } - uni.showToast({ title: "删除成功", icon: "success" }); + await deleteCloudFile(userToken.value, file.id); + uni.hideLoading(); + uni.showToast({ + title: "删除成功", + icon: "success" + }); refreshCurrentFileList(); } catch (error) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:779", "删除失败:", error); - uni.showToast({ title: "删除失败,请重试", icon: "error" }); + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:977", "deleteCloudFile 失败,尝试 daleteWorkspace:", error); + try { + const filePath = file.path || "/" + file.name; + if (workspaceId.value) { + await daleteWorkspace(userToken.value, workspaceId.value, filePath); + } + uni.showToast({ + title: "删除成功", + icon: "success" + }); + refreshCurrentFileList(); + } catch (err2) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:989", "删除失败:", err2); + uni.showToast({ + title: "删除失败,请重试", + icon: "error" + }); + } } } } @@ -9336,7 +9797,10 @@ This will fail in production.`); const confirmCreateFolder = async () => { const name2 = newFolderName.value.trim(); if (!name2) { - uni.showToast({ title: "请输入目录名称", icon: "none" }); + uni.showToast({ + title: "请输入目录名称", + icon: "none" + }); return; } try { @@ -9345,22 +9809,114 @@ This will fail in production.`); const dirPath = prefix + name2; await createWorkspaceFolder(userToken.value, workspaceId.value, dirPath); } - uni.showToast({ title: "创建成功", icon: "success" }); + uni.showToast({ + title: "创建成功", + icon: "success" + }); closeNewFolderModal(); refreshCurrentFileList(); } catch (error) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:826", "创建文件夹失败:", error); - uni.showToast({ title: "创建失败,请重试", icon: "error" }); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1046", "创建文件夹失败:", error); + uni.showToast({ + title: "创建失败,请重试", + icon: "error" + }); + } + }; + const showUploadPathInput = vue.ref(false); + const uploadPath = vue.ref("/"); + const handleUploadFile = () => { + showUploadPathInput.value = true; + uploadPath.value = "/"; + }; + const closeUploadPathInput = () => { + showUploadPathInput.value = false; + }; + const confirmUploadPath = () => { + const path = uploadPath.value.trim(); + if (!path) { + uploadPath.value = "/"; + } + showUploadPathInput.value = false; + chooseAndUploadFile(); + }; + const chooseAndUploadFile = () => { + plus.io.chooseFile( + (res) => { + const files = Array.isArray(res) ? res : res.files || []; + if (files.length === 0) { + uni.showToast({ + title: "未选择文件", + icon: "none" + }); + return; + } + doUploadFiles(files); + }, + (err) => { + if (err.code !== 11) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1095", "选择文件失败:", err); + } + } + ); + }; + const doUploadFiles = async (files) => { + uni.showLoading({ + title: "上传中..." + }); + try { + const path = uploadPath.value.trim() || "/"; + const type = currentCategory.value === "user" ? "user" : "team"; + const teamId = currentCategory.value === "team" ? currentTeamId.value : ""; + await uploadCloudFile(userToken.value, type, path, files, teamId); + uni.hideLoading(); + uni.showToast({ + title: "上传成功", + icon: "success" + }); + refreshCurrentFileList(); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1147", "上传文件失败:", error); + uni.showToast({ + title: "上传失败,请重试", + icon: "error" + }); } }; const personalTables = vue.ref([ - { id: "1", name: "users", desc: "用户信息表", rowCount: 128 }, - { id: "2", name: "messages", desc: "聊天记录表", rowCount: 2048 }, - { id: "3", name: "settings", desc: "用户配置表", rowCount: 56 } + { + id: "1", + name: "users", + desc: "用户信息表", + rowCount: 128 + }, + { + id: "2", + name: "messages", + desc: "聊天记录表", + rowCount: 2048 + }, + { + id: "3", + name: "settings", + desc: "用户配置表", + rowCount: 56 + } ]); const teamTables = vue.ref([ - { id: "t1", name: "team_tasks", desc: "团队任务表", rowCount: 32 }, - { id: "t2", name: "team_docs", desc: "团队文档表", rowCount: 15 } + { + id: "t1", + name: "team_tasks", + desc: "团队任务表", + rowCount: 32 + }, + { + id: "t2", + name: "team_docs", + desc: "团队文档表", + rowCount: 15 + } ]); const showNewTable = vue.ref(false); const newTableName = vue.ref(""); @@ -9378,7 +9934,10 @@ This will fail in production.`); const confirmCreateTable = () => { const name2 = newTableName.value.trim(); if (!name2) { - uni.showToast({ title: "请输入表名称", icon: "none" }); + uni.showToast({ + title: "请输入表名称", + icon: "none" + }); return; } const newTable = { @@ -9392,101 +9951,320 @@ This will fail in production.`); } else { teamTables.value.push(newTable); } - uni.showToast({ title: "创建成功", icon: "success" }); + uni.showToast({ + title: "创建成功", + icon: "success" + }); closeNewTableModal(); }; const handleTableClick = (table) => { - uni.showToast({ title: `进入数据表:${table.name}`, icon: "none" }); + uni.showToast({ + title: `进入数据表:${table.name}`, + icon: "none" + }); }; const showTeamManage = vue.ref(false); const teamGroups = vue.ref([]); const currentTeamId = vue.ref(""); const currentTeamMembers = vue.ref([]); const inviteKeyword = vue.ref(""); + const currentTeamDescription = vue.computed(() => { + if (!currentTeamId.value) + return ""; + const team = teamGroups.value.find((g) => g.id === currentTeamId.value); + return (team == null ? void 0 : team.description) || ""; + }); + const currentTeamType = vue.computed(() => { + if (!currentTeamId.value) + return ""; + const team = teamGroups.value.find((g) => g.id === currentTeamId.value); + return (team == null ? void 0 : team.type) || ""; + }); + const currentUserRoleInTeam = vue.computed(() => { + if (!userId.value || currentTeamMembers.value.length === 0) + return "member"; + const me = currentTeamMembers.value.find((m) => m.receiver === userId.value || m.user_id === userId.value); + return (me == null ? void 0 : me.role) || "member"; + }); + const isTeamAdmin = vue.computed(() => { + const role = currentUserRoleInTeam.value; + return role === "admin" || role === "owner"; + }); const fetchTeamList = async () => { try { - if (!userId.value) { - const token = getToken(); - const userInfo = await getUserInfo(token); - userId.value = userInfo._id; - } - const groups = await getGroup(userId.value); + const token = getToken(); + const groups = await getTeamList(token); teamGroups.value = groups || []; } catch (error) { - formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:898", "获取团队列表失败:", error); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1278", "获取团队列表失败:", error); teamGroups.value = []; } }; const selectTeam = async (teamId) => { + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:1284", "团队id为", teamId); currentTeamId.value = teamId; - const team = teamGroups.value.find((g) => g.id === teamId); - if (team) { - currentTeamMembers.value = [ - { id: "owner1", receiver: "owner1", friendNickName: "创建者", username: "Owner", role: "owner" }, - { id: "m1", receiver: "m1", friendNickName: "管理员A", username: "AdminA", role: "admin" }, - { id: "m2", receiver: "m2", friendNickName: "成员B", username: "MemberB", role: "member" }, - { id: "m3", receiver: "m3", friendNickName: "成员C", username: "MemberC", role: "member" } - ]; - } else { + try { + const token = getToken(); + const members = await getTeamAllMember(token, teamId); + currentTeamMembers.value = (members || []).map((item) => { + var _a, _b, _c, _d, _e; + return { + id: item._id, + receiver: item.user_id, + user_id: item.user_id, + friendNickName: ((_a = item.user) == null ? void 0 : _a.username) || "", + username: ((_b = item.user) == null ? void 0 : _b.username) || "", + avatar: ((_c = item.user) == null ? void 0 : _c.avatar) || "", + email: ((_d = item.user) == null ? void 0 : _d.email) || "", + role: item.role || ((_e = item.user) == null ? void 0 : _e.role) || "member" + }; + }); + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1301", "获取团队成员失败:", error); currentTeamMembers.value = []; } currentFolderPath.value = []; navbarTitle.value = "云端数据"; await fetchTeamFileList(teamId); }; - const openTeamManage = () => { - showTeamManage.value = true; - if (teamGroups.value.length > 0 && !currentTeamId.value) { - selectTeam(teamGroups.value[0].id); + const openTeamManage = async () => { + if (currentTeamId.value) { + try { + const token = getToken(); + const members = await getTeamAllMember(token, currentTeamId.value); + const me = (members || []).find((m) => m.user_id === userId.value); + const myRole = (me == null ? void 0 : me.role) || "member"; + if (myRole !== "admin" && myRole !== "owner") { + uni.showToast({ title: "仅管理员可管理团队", icon: "none" }); + return; + } + currentTeamMembers.value = (members || []).map((item) => { + var _a, _b, _c, _d, _e; + return { + id: item._id, + receiver: item.user_id, + user_id: item.user_id, + friendNickName: ((_a = item.user) == null ? void 0 : _a.username) || "", + username: ((_b = item.user) == null ? void 0 : _b.username) || "", + avatar: ((_c = item.user) == null ? void 0 : _c.avatar) || "", + email: ((_d = item.user) == null ? void 0 : _d.email) || "", + role: item.role || ((_e = item.user) == null ? void 0 : _e.role) || "member" + }; + }); + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1335", "获取团队成员失败:", error); + uni.showToast({ title: "获取团队信息失败", icon: "none" }); + return; + } + } else if (teamGroups.value.length > 0) { + await selectTeam(teamGroups.value[0].id); + showTeamManage.value = true; + const me = currentTeamMembers.value.find((m) => (m.receiver || m.user_id) === userId.value); + const myRole = (me == null ? void 0 : me.role) || "member"; + if (myRole !== "admin" && myRole !== "owner") { + showTeamManage.value = false; + uni.showToast({ title: "仅管理员可管理团队", icon: "none" }); + return; + } } + showTeamManage.value = true; }; const closeTeamManage = () => { showTeamManage.value = false; inviteKeyword.value = ""; + searchResultList.value = []; + searched.value = false; }; - const setTeamAdmin = (member) => { - uni.showModal({ - title: "设置管理员", - content: `确定将"${member.friendNickName || member.username}"设为管理员吗?`, - success: (res) => { - if (res.confirm) { - member.role = "admin"; - uni.showToast({ title: "已设为管理员", icon: "success" }); - } - } - }); - }; - const removeTeamMember = (member) => { - uni.showModal({ - title: "移除成员", - content: `确定要移除"${member.friendNickName || member.username}"吗?`, - success: (res) => { - if (res.confirm) { - const index = currentTeamMembers.value.findIndex( - (m) => (m.id || m.receiver) === (member.id || member.receiver) - ); - if (index !== -1) { - currentTeamMembers.value.splice(index, 1); - } - uni.showToast({ title: "已移除", icon: "success" }); - } - } - }); - }; - const inviteTeamMember = () => { - const keyword = inviteKeyword.value.trim(); - if (!keyword) { - uni.showToast({ title: "请输入用户ID或名称", icon: "none" }); + const showEditTeam = vue.ref(false); + const editTeamName = vue.ref(""); + const editTeamDesc = vue.ref(""); + const editTeamType = vue.ref(""); + const openEditTeamModal = () => { + const team = teamGroups.value.find((g) => g.id === currentTeamId.value); + if (!team) { + uni.showToast({ title: "请先选择团队", icon: "none" }); return; } - uni.showToast({ title: "邀请已发送", icon: "success" }); - inviteKeyword.value = ""; + editTeamName.value = team.name || ""; + editTeamDesc.value = team.description || ""; + editTeamType.value = team.type || ""; + showEditTeam.value = true; + }; + const closeEditTeamModal = () => { + showEditTeam.value = false; + }; + const confirmEditTeam = async () => { + const name2 = editTeamName.value.trim(); + if (!name2) { + uni.showToast({ title: "请输入团队名称", icon: "none" }); + return; + } + uni.showLoading({ title: "修改中..." }); + try { + const token = getToken(); + await updateTeamInfo(token, currentTeamId.value, { + team_name: name2, + team_description: editTeamDesc.value.trim(), + team_type: editTeamType.value.trim() + }); + uni.hideLoading(); + uni.showToast({ title: "修改成功", icon: "success" }); + closeEditTeamModal(); + await fetchTeamList(); + currentTeamId.value = currentTeamId.value; + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1407", "修改团队信息失败:", error); + uni.showToast({ title: "修改失败,请重试", icon: "error" }); + } + }; + const toggleMemberRole = async (member, newRole) => { + const memberName = member.friendNickName || member.username || member.name; + uni.showModal({ + title: newRole === "admin" ? "设为管理员" : "降为成员", + content: `确定将"${memberName}"${newRole === "admin" ? "设为管理员" : "降为普通成员"}吗?`, + success: async (res) => { + if (res.confirm) { + uni.showLoading({ title: "操作中..." }); + try { + const token = getToken(); + const memberUserId = member.receiver || member.user_id; + await updateTeamMemberRole(token, currentTeamId.value, memberUserId, newRole); + uni.hideLoading(); + uni.showToast({ title: `已${newRole === "admin" ? "设为管理员" : "降为成员"}`, icon: "success" }); + await refreshTeamMembers(); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1432", "调整成员身份失败:", error); + uni.showToast({ title: "操作失败,请重试", icon: "error" }); + } + } + } + }); + }; + const removeTeamMemberHandler = async (member) => { + const memberName = member.friendNickName || member.username || member.name; + uni.showModal({ + title: "移除成员", + content: `确定要移除"${memberName}"吗?`, + success: async (res) => { + if (res.confirm) { + uni.showLoading({ title: "移除中..." }); + try { + const token = getToken(); + const memberUserId = member.receiver || member.user_id; + await removeTeamMember(token, currentTeamId.value, [memberUserId]); + uni.hideLoading(); + uni.showToast({ title: "已移除", icon: "success" }); + await refreshTeamMembers(); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1458", "移除团队成员失败:", error); + uni.showToast({ title: "移除失败,请重试", icon: "error" }); + } + } + } + }); + }; + const refreshTeamMembers = async () => { + const token = getToken(); + const members = await getTeamAllMember(token, currentTeamId.value); + currentTeamMembers.value = (members || []).map((item) => { + var _a, _b, _c, _d; + return { + id: item._id, + receiver: item.user_id, + user_id: item.user_id, + friendNickName: ((_a = item.user) == null ? void 0 : _a.username) || "", + username: ((_b = item.user) == null ? void 0 : _b.username) || "", + avatar: ((_c = item.user) == null ? void 0 : _c.avatar) || "", + email: ((_d = item.user) == null ? void 0 : _d.email) || "", + role: item.role || "member" + }; + }); + }; + const searchResultList = vue.ref([]); + const searched = vue.ref(false); + const searchTeamMember = async () => { + const keyword = inviteKeyword.value.trim(); + if (!keyword) { + uni.showToast({ title: "请输入用户名或邮箱", icon: "none" }); + return; + } + try { + const token = getToken(); + const users = await searchUsers(token, keyword); + searchResultList.value = users || []; + searched.value = true; + if (searchResultList.value.length === 0) { + } + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1500", "搜索用户失败:", error); + searchResultList.value = []; + searched.value = true; + } + }; + const addTeamMemberHandler = (user) => { + uni.showModal({ + title: "添加成员", + content: `确定将"${user.username}"添加到当前团队吗?`, + success: async (res) => { + if (res.confirm) { + uni.showLoading({ title: "添加中..." }); + try { + const token = getToken(); + await addTeamMember(token, currentTeamId.value, [user._id]); + uni.hideLoading(); + uni.showToast({ title: "添加成功", icon: "success" }); + inviteKeyword.value = ""; + searchResultList.value = []; + searched.value = false; + await refreshTeamMembers(); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1526", "添加团队成员失败:", error); + uni.showToast({ title: "添加失败,请重试", icon: "error" }); + } + } + } + }); + }; + const handleDeleteTeam = () => { + const team = teamGroups.value.find((g) => g.id === currentTeamId.value); + const teamName = team ? team.name : "当前团队"; + uni.showModal({ + title: "删除团队", + content: `确定要删除团队"${teamName}"吗?此操作不可撤销,团队内所有文件和数据将被永久删除。`, + confirmText: "删除", + confirmColor: "#e74c3c", + success: async (res) => { + if (res.confirm) { + uni.showLoading({ title: "删除中..." }); + try { + await deleteTeam(userToken.value, currentTeamId.value); + uni.hideLoading(); + uni.showToast({ title: "团队已删除", icon: "success" }); + currentTeamId.value = ""; + currentTeamMembers.value = []; + teamFiles.value = []; + currentFolderPath.value = []; + navbarTitle.value = "云端数据"; + await fetchTeamList(); + closeTeamManage(); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:1560", "删除团队失败:", error); + uni.showToast({ title: "删除失败,请重试", icon: "error" }); + } + } + } + }); }; vue.onMounted(async () => { await fetchFileList(); await fetchTeamList(); }); - const __returned__ = { userToken, userId, workspaceId, currentCategory, switchCategory, navbarTitle, isMenuOpen, isSelectFolder, selectFileList, handleMenu, handleSelectFolder, parentFolderName, handleBackOrUp, rawPersonalFileData, rawTeamFileData, personalFiles, teamFiles, currentFolderPath, isFolder, getFileExtension, getFileIcon, formatFileSize, currentFolderDisplayPath, personalFileCount, findFolderByPath, loadCurrentFiles, fetchFileList, fetchTeamFileList, handleFileClick, handleFileLongPress, handleDownload, saveFileToYxd, copyFileToDir, openFileConfirm, openFile, openFileWithMenu, handleRename, handleDeleteFile, refreshCurrentFileList, showNewFolder, newFolderName, openNewFolderModal, closeNewFolderModal, confirmCreateFolder, personalTables, teamTables, showNewTable, newTableName, newTableDesc, openNewTableModal, closeNewTableModal, confirmCreateTable, handleTableClick, showTeamManage, teamGroups, currentTeamId, currentTeamMembers, inviteKeyword, fetchTeamList, selectTeam, openTeamManage, closeTeamManage, setTeamAdmin, removeTeamMember, inviteTeamMember, onMounted: vue.onMounted, ref: vue.ref, computed: vue.computed, get getToken() { + const __returned__ = { userToken, userId, workspaceId, currentCategory, switchCategory, navbarTitle, isMenuOpen, isSelectFolder, selectFileList, handleMenu, handleSelectFolder, parentFolderName, handleBackOrUp, rawPersonalFileData, rawTeamFileData, personalFiles, teamFiles, currentFolderPath, isFolder, getFileExtension, getFileIcon, formatFileSize, currentFolderDisplayPath, personalFileCount, findFolderByPath, loadCurrentFiles, fetchFileList, fetchTeamFileList, handleFileClick, handleFileLongPress, handleDownload, saveFileToYxd, openFileConfirm, openFile, openFileWithMenu, handleRename, handleDeleteFile, refreshCurrentFileList, showNewFolder, newFolderName, openNewFolderModal, closeNewFolderModal, confirmCreateFolder, showUploadPathInput, uploadPath, handleUploadFile, closeUploadPathInput, confirmUploadPath, chooseAndUploadFile, doUploadFiles, personalTables, teamTables, showNewTable, newTableName, newTableDesc, openNewTableModal, closeNewTableModal, confirmCreateTable, handleTableClick, showTeamManage, teamGroups, currentTeamId, currentTeamMembers, inviteKeyword, currentTeamDescription, currentTeamType, currentUserRoleInTeam, isTeamAdmin, fetchTeamList, selectTeam, openTeamManage, closeTeamManage, showEditTeam, editTeamName, editTeamDesc, editTeamType, openEditTeamModal, closeEditTeamModal, confirmEditTeam, toggleMemberRole, removeTeamMemberHandler, refreshTeamMembers, searchResultList, searched, searchTeamMember, addTeamMemberHandler, handleDeleteTeam, onMounted: vue.onMounted, ref: vue.ref, computed: vue.computed, get getToken() { return getToken; }, get getUserInfo() { return getUserInfo; @@ -9500,8 +10278,26 @@ This will fail in production.`); return daleteWorkspace; }, get getWorkspaceFileURL() { return getWorkspaceFileURL; - }, get getGroup() { - return getGroup; + }, get getTeamList() { + return getTeamList; + }, get getTeamAllMember() { + return getTeamAllMember; + }, get searchUsers() { + return searchUsers; + }, get addTeamMember() { + return addTeamMember; + }, get updateTeamInfo() { + return updateTeamInfo; + }, get updateTeamMemberRole() { + return updateTeamMemberRole; + }, get removeTeamMember() { + return removeTeamMember; + }, get uploadCloudFile() { + return uploadCloudFile; + }, get deleteCloudFile() { + return deleteCloudFile; + }, get deleteTeam() { + return deleteTeam; } }; Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); return __returned__; @@ -9548,7 +10344,7 @@ This will fail in production.`); vue.renderList($setup.currentTeamMembers, (member) => { return vue.openBlock(), vue.createElementBlock("view", { class: "member-item", - key: member.id || member.receiver + key: member._id || member.receiver }, [ vue.createElementVNode("view", { class: "member-avatar" }, [ member.avatar ? (vue.openBlock(), vue.createElementBlock("image", { @@ -9583,23 +10379,41 @@ This will fail in production.`); ) ]), vue.createElementVNode("view", { class: "member-actions" }, [ - member.role === "owner" ? (vue.openBlock(), vue.createElementBlock("view", { - key: 0, + (member.receiver || member.user_id) === $setup.userId ? (vue.openBlock(), vue.createElementBlock( + "view", + { + key: 0, + class: vue.normalizeClass(["member-role", $setup.currentUserRoleInTeam]) + }, + vue.toDisplayString($setup.currentUserRoleInTeam === "owner" ? "创建者" : "管理员"), + 3 + /* TEXT, CLASS */ + )) : member.role === "owner" ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, class: "member-role owner" }, "创建者")) : member.role === "admin" ? (vue.openBlock(), vue.createElementBlock("view", { - key: 1, - class: "member-role admin" - }, "管理员")) : (vue.openBlock(), vue.createElementBlock("view", { key: 2, class: "member-actions-right" + }, [ + vue.createElementVNode("view", { + class: "member-action-btn demote-admin", + onClick: ($event) => $setup.toggleMemberRole(member, "member") + }, "降为成员", 8, ["onClick"]), + vue.createElementVNode("view", { + class: "member-action-btn remove-member", + onClick: ($event) => $setup.removeTeamMemberHandler(member) + }, "移除", 8, ["onClick"]) + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 3, + class: "member-actions-right" }, [ vue.createElementVNode("view", { class: "member-action-btn set-admin", - onClick: ($event) => $setup.setTeamAdmin(member) + onClick: ($event) => $setup.toggleMemberRole(member, "admin") }, "设为管理", 8, ["onClick"]), vue.createElementVNode("view", { class: "member-action-btn remove-member", - onClick: ($event) => $setup.removeTeamMember(member) + onClick: ($event) => $setup.removeTeamMemberHandler(member) }, "移除", 8, ["onClick"]) ])) ]) @@ -9616,31 +10430,161 @@ This will fail in production.`); "input", { class: "invite-input", - placeholder: "输入用户ID或名称邀请", - "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.inviteKeyword = $event) + placeholder: "输入用户名或邮箱搜索", + "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.inviteKeyword = $event), + onConfirm: $setup.searchTeamMember }, null, - 512 - /* NEED_PATCH */ + 544 + /* NEED_HYDRATION, NEED_PATCH */ ), [ [vue.vModelText, $setup.inviteKeyword] ]), vue.createElementVNode("view", { class: "invite-btn text-btn", - onClick: $setup.inviteTeamMember - }, "邀请") + onClick: $setup.searchTeamMember + }, "搜索") + ]), + $setup.searchResultList.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "search-result-list" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.searchResultList, (user) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "search-result-item", + key: user._id, + onClick: ($event) => $setup.addTeamMemberHandler(user) + }, [ + user.avatar ? (vue.openBlock(), vue.createElementBlock("image", { + key: 0, + src: user.avatar, + class: "result-avatar", + mode: "aspectFill" + }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "result-default-avatar" + }, [ + vue.createVNode(_component_uni_icons, { + type: "person-filled", + size: "40rpx", + color: "#fff" + }) + ])), + vue.createElementVNode("view", { class: "result-info" }, [ + vue.createElementVNode( + "text", + { class: "result-name" }, + vue.toDisplayString(user.username), + 1 + /* TEXT */ + ), + vue.createElementVNode( + "text", + { class: "result-email" }, + vue.toDisplayString(user.email), + 1 + /* TEXT */ + ) + ]), + vue.createElementVNode("view", { class: "result-add-btn" }, "添加") + ], 8, ["onClick"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) : $setup.inviteKeyword && $setup.searched ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "search-empty" + }, "未找到匹配用户")) : vue.createCommentVNode("v-if", true) + ]), + vue.createElementVNode("view", { class: "edit-team-section" }, [ + vue.createElementVNode("view", { + class: "edit-team-btn", + onClick: $setup.openEditTeamModal + }, "修改团队信息") + ]), + vue.createElementVNode("view", { class: "delete-team-section" }, [ + vue.createElementVNode("view", { + class: "delete-team-btn", + onClick: $setup.handleDeleteTeam + }, "删除团队") + ]) + ]) + ])) : vue.createCommentVNode("v-if", true), + $setup.showEditTeam ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "popup-overlay", + onClick: $setup.closeEditTeamModal + }, [ + vue.createElementVNode("view", { + class: "popup-card", + onClick: _cache[4] || (_cache[4] = vue.withModifiers(() => { + }, ["stop"])) + }, [ + vue.createElementVNode("view", { + class: "close-popup-card", + onClick: $setup.closeEditTeamModal + }, [ + vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) + ]), + vue.createElementVNode("view", { class: "popup-title" }, "修改团队信息"), + vue.createElementVNode("view", { class: "edit-team-form" }, [ + vue.createElementVNode("view", { class: "form-label" }, "团队名称"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.editTeamName = $event), + type: "text", + placeholder: "输入团队名称" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.editTeamName] + ]) + ]), + vue.createElementVNode("view", { class: "form-label" }, "团队描述"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $setup.editTeamDesc = $event), + type: "text", + placeholder: "输入团队描述" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.editTeamDesc] + ]) ]) + ]), + vue.createElementVNode("view", { class: "option-wrapper" }, [ + vue.createElementVNode("view", { + class: "opt-btn opt-cancel", + onClick: $setup.closeEditTeamModal + }, "取消"), + vue.createElementVNode("view", { + class: "opt-btn opt-confirm", + onClick: $setup.confirmEditTeam + }, "确认修改") ]) ]) ])) : vue.createCommentVNode("v-if", true), $setup.showNewFolder ? (vue.openBlock(), vue.createElementBlock("view", { - key: 1, + key: 2, class: "popup-overlay", onClick: $setup.closeNewFolderModal }, [ vue.createElementVNode("view", { class: "popup-card", - onClick: _cache[3] || (_cache[3] = vue.withModifiers(() => { + onClick: _cache[6] || (_cache[6] = vue.withModifiers(() => { }, ["stop"])) }, [ vue.createElementVNode("view", { @@ -9661,7 +10605,7 @@ This will fail in production.`); vue.withDirectives(vue.createElementVNode( "input", { - "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.newFolderName = $event), + "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $setup.newFolderName = $event), type: "text", placeholder: "输入目录名称" }, @@ -9692,14 +10636,60 @@ This will fail in production.`); ]) ]) ])) : vue.createCommentVNode("v-if", true), + $setup.showUploadPathInput ? (vue.openBlock(), vue.createElementBlock("view", { + key: 3, + class: "popup-overlay", + onClick: $setup.closeUploadPathInput + }, [ + vue.createElementVNode("view", { + class: "popup-card", + onClick: _cache[8] || (_cache[8] = vue.withModifiers(() => { + }, ["stop"])) + }, [ + vue.createElementVNode("view", { + class: "close-popup-card", + onClick: $setup.closeUploadPathInput + }, [ + vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) + ]), + vue.createElementVNode("view", { class: "popup-title" }, "上传文件"), + vue.createElementVNode("view", { class: "upload-path-label" }, "上传路径"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => $setup.uploadPath = $event), + type: "text", + placeholder: "输入上传路径,如:/myfolder" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.uploadPath] + ]) + ]), + vue.createElementVNode("view", { class: "upload-path-hint" }, "默认为根目录 /,后端会自动创建不存在的文件夹"), + vue.createElementVNode("view", { class: "option-wrapper" }, [ + vue.createElementVNode("view", { + class: "opt-btn opt-cancel", + onClick: $setup.closeUploadPathInput + }, "取消"), + vue.createElementVNode("view", { + class: "opt-btn opt-confirm", + onClick: $setup.confirmUploadPath + }, "确认上传") + ]) + ]) + ])) : vue.createCommentVNode("v-if", true), $setup.showNewTable ? (vue.openBlock(), vue.createElementBlock("view", { - key: 2, + key: 4, class: "popup-overlay", onClick: $setup.closeNewTableModal }, [ vue.createElementVNode("view", { class: "popup-card", - onClick: _cache[6] || (_cache[6] = vue.withModifiers(() => { + onClick: _cache[11] || (_cache[11] = vue.withModifiers(() => { }, ["stop"])) }, [ vue.createElementVNode("view", { @@ -9720,7 +10710,7 @@ This will fail in production.`); vue.withDirectives(vue.createElementVNode( "input", { - "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $setup.newTableName = $event), + "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => $setup.newTableName = $event), type: "text", placeholder: "输入表名称,如:users" }, @@ -9736,7 +10726,7 @@ This will fail in production.`); vue.withDirectives(vue.createElementVNode( "input", { - "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $setup.newTableDesc = $event), + "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => $setup.newTableDesc = $event), type: "text", placeholder: "输入表描述(可选)" }, @@ -9801,34 +10791,14 @@ This will fail in production.`); 2 /* CLASS */ )) - ]), - $setup.isMenuOpen ? (vue.openBlock(), vue.createElementBlock("view", { - key: 0, - class: "menu-card" - }, [ - vue.createElementVNode("view", { - class: "menu-card-item", - onClick: _cache[7] || (_cache[7] = ($event) => { - $setup.handleSelectFolder(); - $setup.handleMenu(); - }) - }, "选择"), - vue.createElementVNode("view", { class: "solid-line" }), - vue.createElementVNode("view", { - class: "menu-card-item", - onClick: _cache[8] || (_cache[8] = ($event) => { - $setup.openNewFolderModal(); - $setup.handleMenu(); - }) - }, "新建文件夹") - ])) : vue.createCommentVNode("v-if", true) + ]) ]), vue.createElementVNode("view", { class: "category-tabs" }, [ vue.createElementVNode( "view", { class: vue.normalizeClass(["category-tab", { active: $setup.currentCategory === "user" }]), - onClick: _cache[9] || (_cache[9] = ($event) => $setup.switchCategory("user")) + onClick: _cache[12] || (_cache[12] = ($event) => $setup.switchCategory("user")) }, " 个人 ", 2 @@ -9838,7 +10808,7 @@ This will fail in production.`); "view", { class: vue.normalizeClass(["category-tab", { active: $setup.currentCategory === "team" }]), - onClick: _cache[10] || (_cache[10] = ($event) => $setup.switchCategory("team")) + onClick: _cache[13] || (_cache[13] = ($event) => $setup.switchCategory("team")) }, " 团队 ", 2 @@ -9870,13 +10840,13 @@ This will fail in production.`); vue.createElementVNode("view", { class: "section-actions" }, [ vue.createElementVNode("view", { class: "action-btn", - onClick: $setup.openNewFolderModal + onClick: $setup.handleUploadFile }, [ vue.createVNode(_component_uni_icons, { - type: "plus", + type: "upload", size: "16" }), - vue.createElementVNode("text", null, "新建目录") + vue.createElementVNode("text", null, "上传文件") ]) ]) ]), @@ -10094,7 +11064,32 @@ This will fail in production.`); 128 /* KEYED_FRAGMENT */ )) - ]) + ]), + $setup.currentTeamType || $setup.currentTeamDescription ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "team-info" + }, [ + $setup.currentTeamType ? (vue.openBlock(), vue.createElementBlock( + "text", + { + key: 0, + class: "team-type-tag" + }, + vue.toDisplayString($setup.currentTeamType), + 1 + /* TEXT */ + )) : vue.createCommentVNode("v-if", true), + $setup.currentTeamDescription ? (vue.openBlock(), vue.createElementBlock( + "text", + { + key: 1, + class: "team-desc-text" + }, + vue.toDisplayString($setup.currentTeamDescription), + 1 + /* TEXT */ + )) : vue.createCommentVNode("v-if", true) + ])) : vue.createCommentVNode("v-if", true) ])) : vue.createCommentVNode("v-if", true), !$setup.currentTeamId && $setup.teamGroups.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { key: 1, @@ -10115,13 +11110,13 @@ This will fail in production.`); vue.createElementVNode("view", { class: "section-actions" }, [ vue.createElementVNode("view", { class: "action-btn", - onClick: $setup.openNewFolderModal + onClick: $setup.handleUploadFile }, [ vue.createVNode(_component_uni_icons, { - type: "plus", + type: "upload", size: "16" }), - vue.createElementVNode("text", null, "新建目录") + vue.createElementVNode("text", null, "上传文件") ]) ]) ]), diff --git a/unpackage/dist/dev/app-plus/manifest.json b/unpackage/dist/dev/app-plus/manifest.json index 9bb9ee2..703d9f6 100644 --- a/unpackage/dist/dev/app-plus/manifest.json +++ b/unpackage/dist/dev/app-plus/manifest.json @@ -62,7 +62,10 @@ "", "", "", - "" + "", + "", + "", + "" ] }, "apple": { diff --git a/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css b/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css index b6e293a..c177277 100644 --- a/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css +++ b/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css @@ -878,6 +878,28 @@ background: #3b86ff; font-weight: 500; } +.team-info[data-v-51006ffb] { + margin-top: 0.4375rem; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.375rem; +} +.team-type-tag[data-v-51006ffb] { + font-size: 0.6875rem; + color: #3b86ff; + background: rgba(59, 134, 255, 0.1); + padding: 0.1875rem 0.5rem; + border-radius: 0.25rem; + font-weight: 500; +} +.team-desc-text[data-v-51006ffb] { + font-size: 0.75rem; + color: #999; + line-height: 1.5; + flex: 1; + min-width: 0; +} .select-team-tip[data-v-51006ffb] { padding: 2.5rem 0; } @@ -1052,6 +1074,10 @@ color: #3b86ff; background: rgba(59, 134, 255, 0.1); } +.member-role.member[data-v-51006ffb] { + color: #67c23a; + background: rgba(103, 194, 58, 0.1); +} .member-actions-right[data-v-51006ffb] { display: flex; gap: 0.25rem; @@ -1065,6 +1091,10 @@ color: #3b86ff; border: 0.03125rem solid #3b86ff; } +.demote-admin[data-v-51006ffb] { + color: #e6a23c; + border: 0.03125rem solid #e6a23c; +} .remove-member[data-v-51006ffb] { color: #f56c6c; border: 0.03125rem solid #f56c6c; @@ -1094,6 +1124,78 @@ font-size: 0.75rem; padding: 0.4375rem 1rem; } + +/* 搜索结果列表 */ +.search-result-list[data-v-51006ffb] { + margin-top: 0.5rem; + border-radius: 0.4375rem; + overflow: hidden; + background: #f8f9fc; +} +.search-result-item[data-v-51006ffb] { + display: flex; + align-items: center; + padding: 0.5625rem 0.625rem; + border-bottom: 0.03125rem solid #eee; +} +.search-result-item[data-v-51006ffb]:last-child { + border-bottom: none; +} +.search-result-item[data-v-51006ffb]:active { + background: rgba(59, 134, 255, 0.05); +} +.result-avatar[data-v-51006ffb] { + width: 2rem; + height: 2rem; + border-radius: 50%; + flex-shrink: 0; + margin-right: 0.5rem; +} +.result-default-avatar[data-v-51006ffb] { + width: 2rem; + height: 2rem; + border-radius: 50%; + background: linear-gradient(135deg, #3b86ff, #6db3ff); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + margin-right: 0.5rem; +} +.result-info[data-v-51006ffb] { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.125rem; +} +.result-name[data-v-51006ffb] { + font-size: 0.875rem; + color: #333; + font-weight: 500; +} +.result-email[data-v-51006ffb] { + font-size: 0.6875rem; + color: #999; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.result-add-btn[data-v-51006ffb] { + flex-shrink: 0; + font-size: 0.75rem; + color: #3b86ff; + padding: 0.3125rem 0.75rem; + border: 0.03125rem solid #3b86ff; + border-radius: 0.625rem; +} +.search-empty[data-v-51006ffb] { + margin-top: 0.5rem; + text-align: center; + font-size: 0.75rem; + color: #bbb; + padding: 0.625rem 0; +} .folder-null[data-v-51006ffb] { display: flex; flex-direction: column; @@ -1108,9 +1210,69 @@ font-size: 2rem; color: #ddd; } + +/* 删除团队 */ +.delete-team-section[data-v-51006ffb] { + border-top: 0.03125rem solid #eee; + padding-top: 0.625rem; + margin-top: 0.3125rem; +} +.delete-team-btn[data-v-51006ffb] { + text-align: center; + padding: 0.5625rem; + font-size: 0.8125rem; + color: #e74c3c; + background: rgba(231, 76, 60, 0.06); + border-radius: 0.4375rem; + border: 0.03125rem solid rgba(231, 76, 60, 0.2); +} +.delete-team-btn[data-v-51006ffb]:active { + background: rgba(231, 76, 60, 0.12); +} + +/* 修改团队信息 */ +.edit-team-section[data-v-51006ffb] { + border-top: 0.03125rem solid #eee; + padding-top: 0.625rem; + margin-top: 0.3125rem; +} +.edit-team-btn[data-v-51006ffb] { + text-align: center; + padding: 0.5625rem; + font-size: 0.8125rem; + color: #3b86ff; + background: rgba(59, 134, 255, 0.06); + border-radius: 0.4375rem; + border: 0.03125rem solid rgba(59, 134, 255, 0.2); +} +.edit-team-btn[data-v-51006ffb]:active { + background: rgba(59, 134, 255, 0.12); +} +.edit-team-form[data-v-51006ffb] { + margin-bottom: 0.3125rem; +} +.form-label[data-v-51006ffb] { + font-size: 0.8125rem; + color: #666; + margin-bottom: 0.25rem; + margin-top: 0.5625rem; +} .text-btn[data-v-51006ffb] { padding: 0.25rem 0.625rem; border-radius: 0.9375rem; font-size: 14px; font-weight: 500; } + +/* ===== 上传文件弹窗 ===== */ +.upload-path-label[data-v-51006ffb] { + font-size: 0.8125rem; + color: #666; + margin-bottom: 0.3125rem; +} +.upload-path-hint[data-v-51006ffb] { + font-size: 0.6875rem; + color: #999; + margin-bottom: 0.625rem; + text-align: center; +} diff --git a/utils/cloud-api.js b/utils/cloud-api.js index b6e44d1..e0806fb 100644 --- a/utils/cloud-api.js +++ b/utils/cloud-api.js @@ -687,4 +687,810 @@ export const getCloudFileUrl = (token, fileId) => { }) } + +// 删除云端文件 +export const deleteCloudFile = (token, fileId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/file/delete`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "file_id": fileId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '删除云端文件出错啦' + reject(msg) + } + } else { + reject(`删除云端文件失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 批量上传云端文件 +export const uploadCloudFile = (token, type, path, files, team_id) => { + return new Promise((resolve, reject) => { + // 处理参数:team_id 转为字符串,空值置空 + const teamIdStr = team_id == null ? "" : String(team_id); + + uni.uploadFile({ + url: `${BASE_URL}/cloud_api/file/upload`, + method: "POST", + // 不要手动设置 Content-Type,浏览器自动生成 multipart/form-data + header: { + // 如果后端把token放header就写这里,放表单里就写到formData + }, + // 普通文本参数(对应form-data里的文本项) + formData: { + access_token: token, + path: path || "/", + type: type, + team_id: teamIdStr + }, + // 多文件:每个文件name都叫files,和Postman保持一致 + files: files.map(fileItem => ({ + uri: fileItem.tempFilePath, // 文件本地临时路径 + name: "files" + })), + + success: (res) => { + if (res.statusCode === 200) { + try { + const respond = JSON.parse(res.data); + if (respond.success) { + resolve(respond.message); + } else { + const msg = respond?.error || '获取云端文件url出错啦'; + reject(msg); + } + } catch (e) { + reject("接口返回数据格式异常"); + } + } else { + reject(`获取云端文件url失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误'; + reject(msg); + } + }); + }); +}; + + +// 获取用户可访问的团队列表 +export const getTeamList = async (token) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/list`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + access_token: token, + team_name: "" + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + const teamsList = respond.teams + // 去掉第1条数据(系统团队),从下标1开始截取剩余所有 + const newList = teamsList.slice(1) + resolve(newList) + } else { + const msg = res.data.error || '获取用户可访问的团队列表出错啦' + reject(msg) + } + + } else { + reject(`获取用户可访问的团队列表失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 获取团队全部成员 +export const getTeamAllMember = (token, teamId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/get_all_member`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + const members = respond.team?.result || [] + resolve(members) + } else { + const msg = respond?.error || '获取团队全部成员出错啦' + reject(msg) + } + } else { + reject(`获取团队全部成员失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + + +// 删除团队 +export const deleteTeam = (token, teamId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/delete`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '删除团队出错啦' + reject(msg) + } + } else { + reject(`删除团队失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 添加团队成员 +export const addTeamMember = (token, teamId, userIds) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/add_member`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId, + "user_ids": userIds, + "role": "admin" + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '添加团队成员出错啦' + reject(msg) + } + } else { + reject(`添加团队成员失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 修改团队信息 +export const updateTeamInfo = (token, teamId, data) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/update`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId, + ...data + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '修改团队信息出错啦' + reject(msg) + } + } else { + reject(`修改团队信息失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 移除团队成员 +export const removeTeamMember = (token, teamId, userIds) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/remove_member`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId, + "user_ids": userIds + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '移除团队成员出错啦' + reject(msg) + } + } else { + reject(`移除团队成员失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 调整团员身份 +export const updateTeamMemberRole = (token, teamId, userId, role) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/team/adjust_member_role`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "team_id": teamId, + "user_id": userId, + "role": role + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '调整团员身份出错啦' + reject(msg) + } + } else { + reject(`调整团员身份失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + // ============================云端数据库========================= + +// 获取用户可访问的数据库列表 +export const getCloudDbList = (token) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/list`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + // "databases": [ + // { + // "database_name": "测试3", + // "table_count": 0, + // "file_path": "/home/yxd/yxd-agent-cloud/databases/6a446df3060ba5feae589c22.db", + // "modified_time": 1782869492.6399229, + // "database_id": "6a446df3060ba5feae589c22", + // "user_id": "690c72a6b8ffa329af2d5607", + // "access_level": 2 + // }, + // { + // "database_name": "database1", + // "table_count": 0, + // "file_path": "/home/yxd/yxd-agent-cloud/databases/6a446bfa1db19f3506901d2d.db", + // "modified_time": 1782868987.3745258, + // "database_id": "6a446bfa1db19f3506901d2d", + // "team_id": "6a02f6f0d99a03faefd1f437", + // "access_level": 2 + // } + // ], + resolve(respond.databases) + } else { + const msg = respond?.error || '获取用户可访问的数据库列表出错啦' + reject(msg) + } + } else { + reject(`获取用户可访问的数据库列表失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 创建数据库(仅个人可创建) +export const createCloudDb = (token, databaseName) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/create`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "database_name": databaseName + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '创建数据库出错啦' + reject(msg) + } + } else { + reject(`创建数据库失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 上传db +export const uploadCloudDbFile = (token, file) => { + return new Promise((resolve, reject) => { + + uni.uploadFile({ + url: `${BASE_URL}/cloud_api/database/upload/db`, + method: "POST", + // 不要手动设置 Content-Type,浏览器自动生成 multipart/form-data + header: { + // 如果后端把token放header就写这里,放表单里就写到formData + }, + // 普通文本参数(对应form-data里的文本项) + formData: { + access_token: token + }, + // 多文件:每个文件name都叫files,和Postman保持一致 + file: files, + success: (res) => { + if (res.statusCode === 200) { + try { + const respond = JSON.parse(res.data); + if (respond.success) { + resolve(respond.message); + } else { + const msg = respond?.error || '上传db出错啦'; + reject(msg); + } + } catch (e) { + reject("接口返回数据格式异常"); + } + } else { + reject(`上传db失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误'; + reject(msg); + } + }); + }); +}; + + + +// 删除数据库(仅个人可创建) +export const deleteCloudDb = (token, databaseId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/delete`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "database_id": databaseName + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.message) + } else { + const msg = respond?.error || '删除数据库出错啦' + reject(msg) + } + } else { + reject(`删除数据库失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 获取数据库中的表列表 +export const getCloudDbTables = (token, databaseId, isDetail) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/list`, + method: "POST", + header: { + 'Content-Type': 'application/json' + }, + data: { + "access_token": token, + "database_id": databaseId, + "is_detail": isDetail + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond.success) { + resolve(respond.tables) + } else { + const msg = respond?.error || '获取用户可访问的数据库列表出错啦' + reject(msg) + } + } else { + reject(`获取用户可访问的数据库列表失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 删除数据库中的表 +export const deleteCloudDbTable = async (token, databaseId, tableName) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/delete_conversation`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + "table_name": table_name + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '删除数据库中的表出错啦' + reject(msg) + } + } else { + reject(`删除数据库中的表失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 更新表数据 +export const updateCloudDbTableData = async (token, databaseId, tableName, whereData, updateData) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/table/update/by/id`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + "table_name": table_name, + "where_data": { + "_row_id": 2 + }, + "update_data": { + "问题": "《水土保持监理规范2344444》制定的目的是什么" + } + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '更新表数据出错啦' + reject(msg) + } + } else { + reject(`更新表数据失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + + +// 导入文件到数据库 +export const importFileToCloudDb = (token, forceOverwrite, databaseId, file, tableName) => { + return new Promise((resolve, reject) => { + uni.uploadFile({ + url: `${BASE_URL}/cloud_api/file/upload`, + method: "POST", + // 不要手动设置 Content-Type,浏览器自动生成 multipart/form-data + header: { + // 如果后端把token放header就写这里,放表单里就写到formData + }, + // 普通文本参数(对应form-data里的文本项) + formData: { + access_token: token, + force_overwrite: forceOverwrite, + database_id: databaseId, + team_id: teamIdStr, + table_name: tableName + }, + file: file, + + success: (res) => { + if (res.statusCode === 200) { + try { + const respond = JSON.parse(res.data); + if (respond.success) { + resolve(respond.message); + } else { + const msg = respond?.error || '导入文件到数据库出错啦'; + reject(msg); + } + } catch (e) { + reject("接口返回数据格式异常"); + } + } else { + reject(`导入文件到数据库失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误'; + reject(msg); + } + }); + }); +}; + +// 查看 个人/团队 数据库权限信息 +export const getCloudDbPermission = async (token, databaseId, type, Id) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/permission/info`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + type: Id + // "team_id": "6a02f6f0d99a03faefd1f437", + // "user_id": "690c72a6b8ffa329af2d5607", + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '查看 个人/团队 数据库权限信息出错啦' + reject(msg) + } + } else { + reject(`查看 个人/团队 数据库权限信息失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 删除 团队/用户 对数据库权限 +export const deleteCloudDbPermission = async (token, databaseId, type, Id) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/permission/delete`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + type: Id + // "team_id": "6a02f6f0d99a03faefd1f437", + // "user_id": "690c72a6b8ffa329af2d5607", + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '删除 团队/用户 对数据库权限出错啦' + reject(msg) + } + } else { + reject(`删除 团队/用户 对数据库权限失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 修改/增加 团队/用户 对数据库权限 +export const updateCloudDbPermission = async (token, databaseId, type, Id, level) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/permission/update`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + "access_level": "3", + type: Id, + // "team_id": "6a02f6f0d99a03faefd1f437", + // "user_id": "690c72a6b8ffa329af2d5607", + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '修改/增加 团队/用户 对数据库权限出错啦' + reject(msg) + } + } else { + reject(`修改/增加 团队/用户 对数据库权限失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} + +// 个人数据库移交团队 +export const dbTransferToTeam = async (token, databaseId,teamId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_URL}/cloud_api/database/transfer_to_team`, + method: "POST", + data: { + "access_token": token, + "database_id": databaseId, + "team_id": teamId + }, + header: { + 'Content-Type': 'application/json' + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data + if (respond?.success) { + resolve(respond.message) + } else { + const msg = respond.failed_ids.error || '个人数据库移交团队出错啦' + reject(msg) + } + } else { + reject(`个人数据库移交团队失败:${res.statusCode}`) + } + }, + fail: (err) => { + const msg = err.errMsg || '网络错误' + reject(msg) + } + }) + }) +} \ No newline at end of file