diff --git a/pages.json b/pages.json index 0f693bd..57bec78 100644 --- a/pages.json +++ b/pages.json @@ -87,7 +87,19 @@ { "path" : "pages/text/text2", "style" : {} - } + }, + { + "path": "pages/CloudDatabase/CloudDatabase", + "style": { + "navigationBarTitleText": "云端数据", + "navigationStyle": "custom", + "app-plus": { + "titleNView": false, + "bounce": "none", + "softinputMode": "adjustResize" + } + } + } ], "uniIdRouter" : {}, "condition" : { diff --git a/pages/Chat/Chat.vue b/pages/Chat/Chat.vue index 12c5313..6212087 100644 --- a/pages/Chat/Chat.vue +++ b/pages/Chat/Chat.vue @@ -70,6 +70,9 @@ + + + @@ -80,24 +83,46 @@ - - - + + + - - - - - + + + + + + + + + + + + 📄 + {{ file.name }} + {{ formatFileSize(file.fileSize) }} + + + @@ -417,6 +442,22 @@ return size.toFixed(2) + 'MB' } + // 从消息 content 中提取文件信息 + // 格式: [文件信息:[{...}]] + const parseFileInfo = (content) => { + if (!content || typeof content !== 'string') return { textContent: content || '', files: [] } + const match = content.match(/\[文件信息:(\[.*?\])\]/) + if (!match) return { textContent: content, files: [] } + try { + const files = JSON.parse(match[1]) + const textContent = content.replace(match[0], '').trim() + return { textContent, files } + } catch (e) { + console.error('解析文件信息失败:', e) + return { textContent: content, files: [] } + } + } + @@ -483,6 +524,17 @@ url: '/pages/WorkSpace/WorkSpace' }) } + + // 跳转到云端数据库 + const goCloudDatabase = () => { + // 保存当前会话id,确保从工作区返回时能恢复 + if (currentSessionId.value) { + uni.setStorageSync('currentSessionId', currentSessionId.value) + } + uni.navigateTo({ + url: '/pages/CloudDatabase/CloudDatabase' + }) + } const logOut = () => { uni.reLaunch({ @@ -821,7 +873,7 @@ userToken.value = getToken(); console.log("token:", userToken.value); UserConversations.value = await getUserConversations(userToken.value) || []; - console.log("UserConversations:", UserConversations.value); + // console.log("UserConversations:", JSON.stringify(UserConversations.value) ); // 优先恢复已保存的会话id,避免刷新到列表第一个 const savedSessionId = getCurrentSessionId(); if (savedSessionId && UserConversations.value.some(c => c._id === savedSessionId)) { @@ -964,7 +1016,7 @@ const takeConversationMessages = async () => { try { allmessages.value = await getConversationMessages(userToken.value, currentSessionId.value) || []; - // console.log("AI消息:", allmessages.value); + // console.log("AI消息:", JSON.stringify(allmessages.value) ); // currentMessages.value = allmessages.value.slice(-pageInfoNumber); // 数据获取后执行滚动 scrollToBottom(); diff --git a/pages/CloudDatabase/CloudDatabase.css b/pages/CloudDatabase/CloudDatabase.css new file mode 100644 index 0000000..d1595f5 --- /dev/null +++ b/pages/CloudDatabase/CloudDatabase.css @@ -0,0 +1,669 @@ + +.cloud-db-container { + display: flex; + flex-direction: column; + width: 100%; + height: 100vh; + background-color: #f5f6fa; +} + +.cloud-db-header { + flex-shrink: 0; + background-color: #ffffff; + padding-bottom: 0; +} + +.custom-navbar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20rpx 30rpx; + box-sizing: border-box; + position: relative; +} + +.navbar-left { + display: flex; + align-items: center; + min-width: 160rpx; +} + +.custom-navbar-icon { + font-size: 44rpx; + color: #333; +} + +.navbar-title { + font-size: 36rpx; + font-weight: 600; + color: #1a1a2e; +} + +.navbar-right { + width: auto; + min-width: 80rpx; + display: flex; + align-items: center; + justify-content: flex-end; +} + +.navbar-before-title { + font-size: 26rpx; + color: #3b86ff; + margin-left: 8rpx; +} + +.navbar-right-text { + font-size: 28rpx; + color: #3b86ff; + font-weight: 500; +} + +/* 菜单 */ +.menu-open { + color: #3b86ff; +} + +.menu-card { + position: absolute; + top: 80rpx; + right: 20rpx; + background: #fff; + border-radius: 16rpx; + box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); + padding: 12rpx 0; + z-index: 100; + min-width: 200rpx; +} + +.menu-card-item { + padding: 20rpx 32rpx; + font-size: 28rpx; + color: #333; +} + +.menu-card-item:active { + background: #f5f6fa; +} + +.solid-line { + height: 1rpx; + background: #eee; + margin: 4rpx 20rpx; +} + +.file-count { + font-size: 24rpx; + color: #999; + font-weight: 400; +} + +/* 分类切换 Tab */ +.category-tabs { + display: flex; + padding: 10rpx 30rpx 0; + gap: 40rpx; + border-bottom: 2rpx solid #eee; +} + +.category-tab { + font-size: 30rpx; + color: #999; + padding-bottom: 20rpx; + position: relative; + font-weight: 500; + transition: color 0.3s; +} + +.category-tab.active { + color: #3b86ff; + font-weight: 600; +} + +.category-tab.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 48rpx; + height: 6rpx; + background: #3b86ff; + border-radius: 3rpx; +} + +/* 内容区域 */ +.cloud-db-content { + flex: 1; + min-height: 0; + padding: 20rpx 30rpx; + box-sizing: border-box; +} + +/* 区块 */ +.section-block { + background: #ffffff; + border-radius: 20rpx; + padding: 24rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04); +} + +.section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16rpx; +} + +.section-title { + display: flex; + align-items: center; + gap: 12rpx; + font-size: 32rpx; + font-weight: 600; + color: #1a1a2e; +} + +.section-title .iconfont { + font-size: 36rpx; + color: #3b86ff; +} + +.section-actions { + display: flex; + align-items: center; + gap: 10rpx; +} + +.action-btn { + display: flex; + align-items: center; + gap: 6rpx; + padding: 10rpx 20rpx; + background: rgba(59, 134, 255, 0.08); + color: #3b86ff; + border-radius: 30rpx; + font-size: 24rpx; + font-weight: 500; +} + +.section-divider { + height: 2rpx; + margin: 4rpx 0 20rpx; +} + +/* 空状态 */ +.empty-tip { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60rpx 0; + color: #bbb; + font-size: 26rpx; + gap: 16rpx; +} + +.empty-tip .iconfont { + font-size: 80rpx; + color: #ddd; +} + +/* 文件网格 */ +.file-grid { + display: flex; + flex-wrap: wrap; + gap: 16rpx; +} + +.file-item { + width: calc(33.33% - 12rpx); + display: flex; + flex-direction: column; + align-items: center; + padding: 20rpx 10rpx; + border-radius: 16rpx; + background: #f8f9fc; + border: 2rpx solid transparent; + transition: all 0.2s; + box-sizing: border-box; +} + +.file-item:active { + border-color: #3b86ff; + background: rgba(59, 134, 255, 0.04); +} + +.file-icon { + width: 80rpx; + height: 80rpx; + display: flex; + align-items: center; + justify-content: center; + border-radius: 16rpx; + margin-bottom: 10rpx; +} + +.file-icon.is-directory { + background: rgba(255, 170, 0, 0.12); +} + +.file-icon.is-directory .iconfont { + font-size: 48rpx; + color: #ffa500; +} + +.file-icon.is-file { + background: rgba(59, 134, 255, 0.1); +} + +.file-icon.is-file .iconfont { + font-size: 44rpx; + color: #3b86ff; +} + +.file-name { + font-size: 24rpx; + color: #333; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + margin-bottom: 6rpx; +} + +.file-meta { + display: flex; + gap: 8rpx; + align-items: center; +} + +.file-type-tag { + font-size: 20rpx; + color: #999; + background: #f0f0f0; + padding: 2rpx 10rpx; + border-radius: 8rpx; +} + +.file-size { + font-size: 20rpx; + color: #bbb; +} + +/* 数据表列表 */ +.table-list { + display: flex; + flex-direction: column; + gap: 12rpx; +} + +.table-item { + display: flex; + align-items: center; + padding: 20rpx; + border-radius: 14rpx; + background: #f8f9fc; + border: 2rpx solid transparent; + transition: all 0.2s; +} + +.table-item:active { + border-color: #3b86ff; + background: rgba(59, 134, 255, 0.03); +} + +.table-icon { + width: 64rpx; + height: 64rpx; + display: flex; + align-items: center; + justify-content: center; + background: rgba(59, 134, 255, 0.08); + border-radius: 14rpx; + margin-right: 20rpx; + flex-shrink: 0; +} + +.table-info { + flex: 1; + min-width: 0; +} + +.table-name { + font-size: 28rpx; + font-weight: 600; + color: #1a1a2e; + margin-bottom: 4rpx; +} + +.table-desc { + font-size: 22rpx; + color: #999; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.table-meta { + display: flex; + align-items: center; + gap: 6rpx; + flex-shrink: 0; +} + +.table-rows { + font-size: 22rpx; + color: #bbb; +} + +/* 团队管理 */ +.team-manage-block { + cursor: pointer; +} + +.team-count { + font-size: 24rpx; + color: #999; +} + +.team-selector { + padding: 0 0 20rpx; +} + +.team-scroll { + white-space: nowrap; +} + +.team-chip { + display: inline-block; + padding: 12rpx 28rpx; + margin-right: 16rpx; + border-radius: 30rpx; + font-size: 26rpx; + color: #666; + background: #f0f2f5; + transition: all 0.2s; +} + +.team-chip.active { + color: #fff; + background: #3b86ff; + font-weight: 500; +} + +.select-team-tip { + padding: 80rpx 0; +} + +/* ===== 弹窗样式 ===== */ +.popup-overlay { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.4); + z-index: 999; + display: flex; + align-items: center; + justify-content: center; +} + +.popup-card { + width: 600rpx; + background: #fff; + border-radius: 30rpx; + padding: 40rpx 30rpx; + box-sizing: border-box; + position: relative; + max-height: 80vh; + display: flex; + flex-direction: column; +} + +.close-popup-card { + position: absolute; + top: 20rpx; + right: 20rpx; + width: 50rpx; + height: 50rpx; + display: flex; + align-items: center; + justify-content: center; +} + +.close-popup-card .iconfont { + font-size: 40rpx; + color: #999; +} + +.popup-title { + font-size: 34rpx; + font-weight: 600; + color: #1a1a2e; + margin-bottom: 30rpx; + text-align: center; +} + +.new-folder-name { + font-size: 26rpx; + color: #666; + margin-bottom: 10rpx; +} + +.create-folder-name { + margin-bottom: 20rpx; +} + +.create-folder-name input { + width: 100%; + height: auto; + padding: 20rpx; + box-sizing: border-box; + border: 1rpx solid #e0e0e0; + border-radius: 16rpx; + font-size: 28rpx; + background: #f9fafb; +} + +.create-folder-name input:focus { + border-color: #3b86ff; + background: #fff; +} + +.nf-path-label { + font-size: 24rpx; + color: #999; + margin-bottom: 8rpx; +} + +.nf-path-display { + font-size: 24rpx; + color: #3b86ff; + background: rgba(59, 134, 255, 0.06); + padding: 12rpx 16rpx; + border-radius: 10rpx; + margin-bottom: 20rpx; +} + +.option-wrapper { + display: flex; + gap: 20rpx; + justify-content: flex-end; + margin-top: 10rpx; +} + +.opt-btn { + padding: 16rpx 40rpx; + border-radius: 30rpx; + font-size: 28rpx; + font-weight: 500; +} + +.opt-cancel { + color: #999; + background: #f0f2f5; +} + +.opt-confirm { + color: #fff; + background: #3b86ff; +} + +/* 团队管理弹窗 */ +.team-manage-body { + flex: 1; + min-height: 0; + max-height: 500rpx; + margin-bottom: 20rpx; +} + +.member-list { + display: flex; + flex-direction: column; + gap: 10rpx; +} + +.member-item { + display: flex; + align-items: center; + padding: 16rpx; + border-radius: 14rpx; + background: #f8f9fc; +} + +.member-avatar { + width: 70rpx; + height: 70rpx; + border-radius: 50%; + overflow: hidden; + margin-right: 16rpx; + flex-shrink: 0; +} + +.member-avatar image { + width: 100%; + height: 100%; +} + +.default-avatar { + width: 100%; + height: 100%; + background: #ccc; + display: flex; + align-items: center; + justify-content: center; +} + +.member-info { + flex: 1; + min-width: 0; +} + +.member-name { + font-size: 28rpx; + font-weight: 500; + color: #333; +} + +.member-label { + font-size: 22rpx; + color: #999; + margin-top: 4rpx; +} + +.member-actions { + flex-shrink: 0; +} + +.member-role { + font-size: 22rpx; + padding: 6rpx 16rpx; + border-radius: 20rpx; +} + +.member-role.owner { + color: #e6a23c; + background: rgba(230, 162, 60, 0.1); +} + +.member-role.admin { + color: #3b86ff; + background: rgba(59, 134, 255, 0.1); +} + +.member-actions-right { + display: flex; + gap: 8rpx; +} + +.member-action-btn { + font-size: 20rpx; + padding: 8rpx 14rpx; + border-radius: 16rpx; +} + +.set-admin { + color: #3b86ff; + border: 1rpx solid #3b86ff; +} + +.remove-member { + color: #f56c6c; + border: 1rpx solid #f56c6c; +} + +.invite-section { + border-top: 1rpx solid #eee; + padding-top: 20rpx; +} + +.invite-input-wrapper { + display: flex; + align-items: center; + gap: 16rpx; +} + +.invite-input { + flex: 1; + height: auto; + padding: 18rpx 20rpx; + box-sizing: border-box; + border: 1rpx solid #e0e0e0; + border-radius: 30rpx; + font-size: 26rpx; + background: #f9fafb; +} + +.invite-btn { + background: #3b86ff; + color: #fff; + font-size: 24rpx; + padding: 14rpx 32rpx; +} + +.folder-null { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60rpx 0; + color: #bbb; + font-size: 26rpx; + gap: 12rpx; +} + +.folder-null .iconfont { + font-size: 64rpx; + color: #ddd; +} + +.text-btn { + padding: 8rpx 20rpx; + border-radius: 30rpx; + font-size: 14px; + font-weight: 500; +} \ No newline at end of file diff --git a/pages/CloudDatabase/CloudDatabase.vue b/pages/CloudDatabase/CloudDatabase.vue new file mode 100644 index 0000000..bdbbb8d --- /dev/null +++ b/pages/CloudDatabase/CloudDatabase.vue @@ -0,0 +1,982 @@ + + + + + diff --git a/pages/ContactPages/ContactPages.css b/pages/ContactPages/ContactPages.css index 4cfafed..39f3c5e 100644 --- a/pages/ContactPages/ContactPages.css +++ b/pages/ContactPages/ContactPages.css @@ -350,15 +350,27 @@ align-items: center; } -.agree-btn, -.refuse-btn { +.agree-btn { font-size: 14px; font-weight: 500; - border: 1px solid #666; - margin-left: 10rpx; + border: 1px solid #3b86ff; + color: #3b86ff; box-sizing: border-box; } +/* 好友申请状态 */ +.friend-status { + font-size: 14px; + font-weight: 500; + padding: 8rpx 20rpx; + border-radius: 30rpx; +} + +.friend-status.agreed { + color: #059669; + background-color: rgba(16, 185, 129, 0.1); +} + /* 通讯录 */ .contact-list { diff --git a/pages/ContactPages/ContactPages.vue b/pages/ContactPages/ContactPages.vue index b121852..1c7e7e5 100644 --- a/pages/ContactPages/ContactPages.vue +++ b/pages/ContactPages/ContactPages.vue @@ -9,7 +9,13 @@ {{isAgreeBeFriend ? '通过好友申请' : '申请添加朋友'}} - {{currentAddFriend.avatar}} + + + + + + {{currentAddFriend.username}} @@ -18,9 +24,9 @@ 好友备注 - + - {{isAgreeBeFriend ? '确认通过' : '发送申请'}} + {{isAgreeBeFriend ? '确认通过' : '发送申请'}} @@ -158,7 +164,7 @@ + v-model="searchFriendName" confirm-type="search" @confirm="searchFriend"/> 请输入用户名或邮箱进行搜索 @@ -167,13 +173,16 @@ - {{friend.avatar}} + + + + {{friend.nickname}} {{friend.email}} - + 添加 @@ -218,7 +227,7 @@ friend.nickname friend.email - + 添加 @@ -258,24 +267,28 @@ 好友申请 - + 暂无好友申请 + - + - {{friend.avatar}} - - - {{friend.nickname}} - {{friend.email}} - - - - 拒绝 - 同意 + + + + + {{request.friendNickName || request.sendId}} + {{request.message || '请求添加你为好友'}} + + + + 同意 + + 已同意 + - @@ -306,7 +319,10 @@ } from '@/utils/user-info.js' import { getChatFriend, - getGroup + getGroup, + sendFriendRequest, + getFriendRequestList, + saveFriend } from '@/utils/friend-api.js' import { getUserInfo, @@ -466,6 +482,7 @@ onMounted(async () => { await takeFriendList() await takeGroupList() + await takeFriendRequestList() handleFriendConnect() }) // 群聊相关 @@ -656,7 +673,7 @@ // 模糊查询:遍历 mockFriendDB,匹配 nickname、username 或 email const keyword = searchFriendName.value.toLowerCase().trim(); searchResultList.value = await searchUsers(userToken.value,keyword) - console.log("searchResultList.value:",searchResultList.value); + console.log("searchResultList.value:",JSON.stringify(searchResultList.value)); // const results = mockFriendDB.value.filter(friend => { // const isMatch = friend.nickname.toLowerCase().includes(keyword) || friend.username.toLowerCase() // .includes(keyword) || friend.email.toLowerCase().includes(keyword); @@ -670,7 +687,7 @@ const currentAddFriend = ref(null) const addNewFriend = (id) => { - const friend = mockFriendDB.value.find(friend => friend.id === id) + const friend = searchResultList.value.find(friend => friend._id === id) if (friend) { // 创建副本避免引用问题 currentAddFriend.value = { @@ -685,6 +702,8 @@ currentAddFriend.value = null isAgreeBeFriend.value = false } + + const inputFriendNickname = ref('') // 视频会议相关 const isVoice = ref(false); @@ -698,77 +717,97 @@ // 好友申请相关 const isAgreeBeFriend = ref(false) - const refuseBeFriend = (friend) => { - + const friendRequestList = ref([]) + // 获取好友申请列表 + const takeFriendRequestList = async () => { + try { + if (!UserId.value) return + const list = await getFriendRequestList(UserId.value) + if (list && list.length) { + friendRequestList.value = await takeRequestAvatar(list) + } else { + friendRequestList.value = [] + } + } catch (error) { + console.error('获取好友申请列表失败:', error) + friendRequestList.value = [] + } } - const agreeBeFriend = (friend) => { + // 获取好友申请人的头像 + const takeRequestAvatar = async (requestList) => { + if (!requestList?.length) return [] + try { + const requestIds = requestList.map(item => item.sendId) + const avatarList = await getUserAvatar(userToken.value, requestIds) + const userMap = new Map(avatarList.map(user => [user.user_id, user]) || []) + return requestList.map(request => { + const userInfo = userMap.get(request.sendId) + return { + ...request, + avatar: userInfo?.avatar || null + } + }) + } catch (err) { + console.error('获取申请人头像失败', err) + return requestList + } + } + + const agreeBeFriend = (request) => { isAgreeBeFriend.value = true currentAddFriend.value = { - ...friend + ...request, + username: request.friendNickName || request.sendId } } - - - // 模拟好友数据库 - const mockFriendDB = ref([{ - id: 1, - nickname: '张三', - username: 'zhangsan', - email: 'zhangsan@example.com', - avatar: '👤' - }, - { - id: 2, - nickname: '李四', - username: 'lisi', - email: 'lisi@example.com', - avatar: '👥' - }, - { - id: 3, - nickname: '王小明', - username: 'wangxm', - email: 'wang@example.com', - avatar: '👪' - }, - { - id: 4, - nickname: '赵磊', - username: 'zhaolei', - email: 'zhao@example.com', - avatar: '🗣️' - }, - { - id: 5, - nickname: '张三2', - username: 'zhangsan', - email: 'zhangsan@example.com', - avatar: '👤' - }, - { - id: 6, - nickname: '李四2', - username: 'lisi', - email: 'lisi@example.com', - avatar: '👥' - }, - { - id: 7, - nickname: '王小明2', - username: 'wangxm', - email: 'wang@example.com', - avatar: '👪' - }, - { - id: 8, - nickname: '赵磊2', - username: 'zhaolei', - email: 'zhao@example.com', - avatar: '🗣️' + // 同意好友申请的确认操作 + const handleFriendOperate = async () => { + if (isAgreeBeFriend.value) { + // 通过好友申请(保存好友即同意) + try { + const friendId = currentAddFriend.value.sendId + const friendNickName = inputFriendNickname.value || currentAddFriend.value.friendNickName || '' + const sessionId = currentAddFriend.value.sessionId || Date.now() + const friendRelationshipId = currentAddFriend.value.id + await saveFriend([ + { + friendNickName: friendNickName, + sender: UserId.value, + receiver: friendId, + sessionId: sessionId, + friendRelationshipId: friendRelationshipId + }, + { + friendNickName: '', + sender: friendId, + receiver: UserId.value, + sessionId: sessionId, + friendRelationshipId: friendRelationshipId + } + ]) + uni.showToast({ title: '已同意好友申请', icon: 'none' }) + const target = friendRequestList.value.find(item => item.sendId === friendId) + if (target) target.status = 1 + closeAddFriendCard() + await takeFriendList() + } catch (error) { + console.error('同意好友申请失败:', error) + uni.showToast({ title: '操作失败', icon: 'none' }) + } + } else { + // 申请好友(添加好友页面的发送申请) + try { + const friendId = currentAddFriend.value._id + const msg = await sendFriendRequest(UserId.value, inputFriendNickname.value, friendId) + uni.showToast({ title: msg, icon: 'none' }) + closeAddFriendCard() + } catch (error) { + console.error('发送好友申请失败:', error) + uni.showToast({ title: '发送申请失败', icon: 'none' }) + } } - - ]) + } // 通讯录相关 diff --git a/pages/UserProfileModal/UserProfileModal.vue b/pages/UserProfileModal/UserProfileModal.vue index 962b225..3b90456 100644 --- a/pages/UserProfileModal/UserProfileModal.vue +++ b/pages/UserProfileModal/UserProfileModal.vue @@ -48,8 +48,8 @@ onMounted, ref } from 'vue'; - import { getUserInfo } from '@/utils/cloud-api.js' - import {getToken} from '@/utils/user-info.js' + import { getUserInfo, updateUserInfo } from '@/utils/cloud-api.js' + import { getToken } from '@/utils/user-info.js' const closeUserCard = () => { console.log("点击了返回") @@ -63,13 +63,39 @@ }) } - const saveUpdate = () => { - uni.navigateBack({ - url: '/pages/Chat/Chat' - }) + const saveUpdate = async() => { + // 表单校验 + if (!editUsername.value.trim()) { + uni.showToast({ title: '用户名不能为空', icon: 'none' }) + return + } + + uni.showLoading({ title: '保存中...', mask: true }) + + try { + await updateUserInfo( + UserToken.value, + UserId.value, + editUsername.value.trim(), + editEmail.value.trim(), + editUserAvatar.value + ) + uni.hideLoading() + uni.showToast({ title: '保存成功', icon: 'success' }) + // 保存成功后延迟返回上一页 + setTimeout(() => { + closeUserCard() + }, 800) + } catch (err) { + uni.hideLoading() + const msg = typeof err === 'string' ? err : '保存失败,请稍后重试' + uni.showToast({ title: msg, icon: 'none' }) + console.error('保存用户信息失败:', err) + } } - + const UserToken = ref('') + const UserId = ref('') const editUserAvatar = ref('') const editUsername = ref('') const editEmail = ref('') @@ -84,7 +110,7 @@ sourceType: ['album', 'camera'], success: (res) => { const tempFilePath = res.tempFilePaths[0] - handlrImageSelected(tempFilePath) + handleImageSelected(tempFilePath) }, fail: (err) => { console.log('选择图片失败', err); @@ -93,17 +119,22 @@ } // 处理选择的图片 - const handlrImageSelected = (filePath) => { + const handleImageSelected = (filePath) => { editUserAvatar.value = filePath } onMounted(async()=>{ - const token = getToken() - const UserInfo = await getUserInfo(token) - - editUserAvatar.value = UserInfo.avatar || '' - editUsername.value = UserInfo.username || '' - editEmail.value = UserInfo.email || '' + UserToken.value = getToken() + try { + const UserInfo = await getUserInfo(UserToken.value) + UserId.value = UserInfo._id || '' + editUserAvatar.value = UserInfo.avatar || '' + editUsername.value = UserInfo.username || '' + editEmail.value = UserInfo.email || '' + } catch (err) { + console.error('获取用户信息失败:', err) + uni.showToast({ title: '加载用户信息失败', icon: 'none' }) + } }) diff --git a/static/iconfont/demo_index.html b/static/iconfont/demo_index.html index b6c8508..3bfb318 100644 --- a/static/iconfont/demo_index.html +++ b/static/iconfont/demo_index.html @@ -54,6 +54,12 @@
    +
  • + +
    云端,云,云服务
    +
    
    +
  • +
  • 其他文件
    @@ -420,9 +426,9 @@
    @font-face {
       font-family: 'iconfont';
    -  src: url('iconfont.woff2?t=1780384681439') format('woff2'),
    -       url('iconfont.woff?t=1780384681439') format('woff'),
    -       url('iconfont.ttf?t=1780384681439') format('truetype');
    +  src: url('iconfont.woff2?t=1782200893170') format('woff2'),
    +       url('iconfont.woff?t=1782200893170') format('woff'),
    +       url('iconfont.ttf?t=1782200893170') format('truetype');
     }
     

    第二步:定义使用 iconfont 的样式

    @@ -448,6 +454,15 @@
      +
    • + +
      + 云端,云,云服务 +
      +
      .icon-cloud +
      +
    • +
    • @@ -997,6 +1012,14 @@
        +
      • + +
        云端,云,云服务
        +
        #icon-cloud
        +
      • +
      • ", ""], _: ["", ""], "*": ["", ""], "~": ["", ""], "\n": ["
        "], " ": ["
        "], "-": ["
        "] }; function n(e2) { return e2.replace(RegExp("^" + (e2.match(/^(\t| )+/) || "")[0], "gm"), ""); @@ -3342,7 +3441,7 @@ This will fail in production.`); useStore.$id = id; return useStore; } - const WS_APP_URL = "ws://cloud_test.yuxindazhineng.com"; + const WS_APP_URL = "ws://cloud.yuxindazhineng.com"; let WebSocketManager$1 = class WebSocketManager { constructor() { this.ws = null; @@ -3381,10 +3480,10 @@ This will fail in production.`); this.ws = uni.connectSocket({ url: this.url, success: () => { - formatAppLog("log", "at utils/socket.js:43", "WebSocket 连接请求已发送"); + formatAppLog("log", "at utils/socket.js:44", "WebSocket 连接请求已发送"); }, fail: (err) => { - formatAppLog("error", "at utils/socket.js:46", "WebSocket 连接失败:", err); + formatAppLog("error", "at utils/socket.js:47", "WebSocket 连接失败:", err); this.handleError(err); } }); @@ -3401,7 +3500,7 @@ This will fail in production.`); return; this.ws.onOpen((event) => { var _a, _b, _c, _d; - formatAppLog("log", "at utils/socket.js:73", "WebSocket 已连接"); + formatAppLog("log", "at utils/socket.js:74", "WebSocket 已连接"); if (this.reconnectAttempts > 0) { (_b = (_a = this.options).onReconnect) == null ? void 0 : _b.call(_a); } @@ -3411,20 +3510,20 @@ This will fail in production.`); this.ws.onMessage((event) => { try { const data = JSON.parse(event.data); - formatAppLog("log", "at utils/socket.js:86", "收到了返回消息:", data); + formatAppLog("log", "at utils/socket.js:87", "收到了返回消息:", data); this.handleMessage(data); } catch (err) { - formatAppLog("error", "at utils/socket.js:90", "消息解析失败:", err); + formatAppLog("error", "at utils/socket.js:91", "消息解析失败:", err); uni.setStorageSync("currentSessionId", event.data.task_call_id); } }); this.ws.onError((err) => { - formatAppLog("error", "at utils/socket.js:95", "WebSocket 错误:", err); + formatAppLog("error", "at utils/socket.js:96", "WebSocket 错误:", err); this.handleError(err); }); this.ws.onClose((event) => { var _a, _b; - formatAppLog("log", "at utils/socket.js:99", "WebSocket 已关闭:", event.code, event.reason); + formatAppLog("log", "at utils/socket.js:100", "WebSocket 已关闭:", event.code, event.reason); (_b = (_a = this.options).onClose) == null ? void 0 : _b.call(_a, event); this.stopHeartbeat(); if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { @@ -3441,12 +3540,12 @@ This will fail in production.`); (_b = (_a = this.options).onMessage) == null ? void 0 : _b.call(_a, msg); const type = msg.type; if (type === "auth_ok") { - formatAppLog("log", "at utils/socket.js:161", "认证成功,socket连接成功"); + formatAppLog("log", "at utils/socket.js:162", "认证成功,socket连接成功"); return; } if (type === "auth_fail") { if ((msg == null ? void 0 : msg.reason) === "pc offline") - formatAppLog("log", "at utils/socket.js:168", "pc端不在线,不可聊天"); + formatAppLog("log", "at utils/socket.js:169", "pc端不在线,不可聊天"); this.isManualClose = true; this.close(); return; @@ -3465,12 +3564,12 @@ This will fail in production.`); return; } const msg = JSON.stringify(data); - formatAppLog("log", "at utils/socket.js:192", "发送的消息是:", msg); + formatAppLog("log", "at utils/socket.js:193", "发送的消息是:", msg); this.ws.send({ data: msg, success: () => resolve(), fail: (err) => { - formatAppLog("error", "at utils/socket.js:200", "发送消息失败:", err); + formatAppLog("error", "at utils/socket.js:201", "发送消息失败:", err); reject(err); } }); @@ -3484,7 +3583,7 @@ This will fail in production.`); if (this.reconnectTimer) return; this.reconnectAttempts++; - formatAppLog("log", "at utils/socket.js:226", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); + formatAppLog("log", "at utils/socket.js:227", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; if (!this.isManualClose) { @@ -3503,7 +3602,7 @@ This will fail in production.`); this.send({ ws_event: "ping" }).catch(() => { - formatAppLog("log", "at utils/socket.js:248", "心跳发送失败,准备重连"); + formatAppLog("log", "at utils/socket.js:249", "心跳发送失败,准备重连"); if (!this.reconnectTimer && !this.isManualClose) { this.reconnect(); } @@ -3528,7 +3627,7 @@ This will fail in production.`); */ handleError(error) { var _a, _b; - formatAppLog("error", "at utils/socket.js:276", "WebSocket 错误处理:", JSON.stringify(error)); + formatAppLog("error", "at utils/socket.js:277", "WebSocket 错误处理:", JSON.stringify(error)); (_b = (_a = this.options).onError) == null ? void 0 : _b.call(_a, error); } /** @@ -3554,7 +3653,7 @@ This will fail in production.`); * 清理所有定时器、标记手动关闭、停止重连 */ close() { - formatAppLog("log", "at utils/socket.js:312", "手动关闭 WebSocket 连接"); + formatAppLog("log", "at utils/socket.js:313", "手动关闭 WebSocket 连接"); this.isManualClose = true; this.stopHeartbeat(); if (this.reconnectTimer) { @@ -3572,11 +3671,11 @@ This will fail in production.`); this.ws.onClose(null); try { this.ws.close({ - success: () => formatAppLog("log", "at utils/socket.js:334", "连接已关闭"), - fail: (err) => formatAppLog("error", "at utils/socket.js:335", "关闭失败:", err) + success: () => formatAppLog("log", "at utils/socket.js:335", "连接已关闭"), + fail: (err) => formatAppLog("error", "at utils/socket.js:336", "关闭失败:", err) }); } catch (error) { - formatAppLog("error", "at utils/socket.js:343", "关闭连接出错:", error); + formatAppLog("error", "at utils/socket.js:344", "关闭连接出错:", error); } this.ws = null; } @@ -4002,6 +4101,98 @@ This will fail in production.`); }); }); }; + const sendFriendRequest = async (sendId, friendNickName, friendId) => { + return new Promise((resolve, reject) => { + formatAppLog("log", "at utils/friend-api.js:239", "进入sendFriendRequest"); + uni.request({ + url: `${BASE_Friend_URL}/api/friendship/saveShip`, + method: "POST", + data: { + sendId, + friendNickName, + recipientId: friendId + }, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if ((respond == null ? void 0 : respond.code) === 0 || (respond == null ? void 0 : respond.msg) === "成功") { + resolve("已成功发送好友申请"); + } else { + const msg = res.data.msg || "发送好友申请出错啦"; + reject(msg); + } + } else { + reject(`发送好友申请失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const saveFriend = async (friendList) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_Friend_URL}/api/chatList/save`, + method: "POST", + header: { + "Content-Type": "application/json" + }, + data: friendList, + success: (res) => { + if (res.statusCode === 200) { + const respond = res.data; + if ((respond == null ? void 0 : respond.code) === 0 || (respond == null ? void 0 : respond.msg) === "成功") { + resolve("保存好友成功"); + } else { + const msg = (respond == null ? void 0 : respond.msg) || "保存好友出错啦"; + reject(msg); + } + } else { + reject(`保存好友失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; + const getFriendRequestList = async (sendId) => { + return new Promise((resolve, reject) => { + uni.request({ + url: `${BASE_Friend_URL}/api/friendship/getFriendship`, + method: "POST", + data: { + "current": 1, + "size": 100, + "sendId": sendId + }, + success: (res) => { + var _a; + if (res.statusCode === 200) { + const respond = res.data; + if ((respond == null ? void 0 : respond.code) === 0 || (respond == null ? void 0 : respond.msg) === "成功") { + const records = ((_a = respond == null ? void 0 : respond.data) == null ? void 0 : _a.records) || []; + resolve(records); + } else { + const msg = res.data.msg || "获取添加我的好友出错啦"; + reject(msg); + } + } else { + reject(`获取添加我的好友失败:${res.statusCode}`); + } + }, + fail: (err) => { + const msg = err.errMsg || "网络错误"; + reject(msg); + } + }); + }); + }; const WS_Friend_URL = "wss://wss.yuxindazhineng.com"; class WebSocketManager { constructor() { @@ -4035,16 +4226,17 @@ This will fail in production.`); }; this.isManualClose = false; if (this.ws) { + formatAppLog("log", "at utils/friend-socket.js:37", "关闭现有连接"); this.close(); } try { this.ws = uni.connectSocket({ url: this.url, success: () => { - formatAppLog("log", "at utils/friend-socket.js:44", "WebSocket 连接请求已发送"); + formatAppLog("log", "at utils/friend-socket.js:45", "WebSocket 连接请求已发送"); }, fail: (err) => { - formatAppLog("error", "at utils/friend-socket.js:47", "WebSocket 连接失败:", err); + formatAppLog("error", "at utils/friend-socket.js:48", "WebSocket 连接失败:", err); this.handleError(err); } }); @@ -4061,7 +4253,7 @@ This will fail in production.`); return; this.ws.onOpen((event) => { var _a, _b, _c, _d; - formatAppLog("log", "at utils/friend-socket.js:74", "WebSocket 已连接"); + formatAppLog("log", "at utils/friend-socket.js:75", "WebSocket 已连接"); if (this.reconnectAttempts > 0) { (_b = (_a = this.options).onReconnect) == null ? void 0 : _b.call(_a); } @@ -4071,20 +4263,20 @@ This will fail in production.`); this.ws.onMessage((event) => { try { const data = JSON.parse(event.data); - formatAppLog("log", "at utils/friend-socket.js:87", "收到了返回消息:", data); + formatAppLog("log", "at utils/friend-socket.js:88", "收到了返回消息:", data); this.handleMessage(data); } catch (err) { - formatAppLog("error", "at utils/friend-socket.js:90", "消息解析失败:", err); + formatAppLog("error", "at utils/friend-socket.js:91", "消息解析失败:", err); uni.setStorageSync("currentSessionId", event.data.task_call_id); } }); this.ws.onError((err) => { - formatAppLog("error", "at utils/friend-socket.js:95", "WebSocket 错误:", err); + formatAppLog("error", "at utils/friend-socket.js:96", "WebSocket 错误:", JSON.stringify(err)); this.handleError(err); }); this.ws.onClose((event) => { var _a, _b; - formatAppLog("log", "at utils/friend-socket.js:99", "WebSocket 已关闭:", event.code, event.reason); + formatAppLog("log", "at utils/friend-socket.js:100", "WebSocket 已关闭:", event.code, event.reason); (_b = (_a = this.options).onClose) == null ? void 0 : _b.call(_a, event); if (!this.isManualClose && this.reconnectAttempts < this.maxReconnectAttempts) { this.reconnect(); @@ -4112,12 +4304,12 @@ This will fail in production.`); return; } const msg = JSON.stringify(data); - formatAppLog("log", "at utils/friend-socket.js:170", "发送的消息是:", msg); + formatAppLog("log", "at utils/friend-socket.js:171", "发送的消息是:", msg); this.ws.send({ data: msg, success: () => resolve(), fail: (err) => { - formatAppLog("error", "at utils/friend-socket.js:178", "发送消息失败:", err); + formatAppLog("error", "at utils/friend-socket.js:179", "发送消息失败:", err); reject(err); } }); @@ -4131,7 +4323,7 @@ This will fail in production.`); if (this.reconnectTimer) return; this.reconnectAttempts++; - formatAppLog("log", "at utils/friend-socket.js:204", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); + formatAppLog("log", "at utils/friend-socket.js:205", `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); this.reconnectTimer = setTimeout(() => { this.reconnectTimer = null; if (!this.isManualClose) { @@ -4150,7 +4342,7 @@ This will fail in production.`); this.send({ ws_event: "ping" }).catch(() => { - formatAppLog("log", "at utils/friend-socket.js:226", "心跳发送失败,准备重连"); + formatAppLog("log", "at utils/friend-socket.js:227", "心跳发送失败,准备重连"); if (!this.reconnectTimer && !this.isManualClose) { this.reconnect(); } @@ -4175,7 +4367,7 @@ This will fail in production.`); */ handleError(error) { var _a, _b; - formatAppLog("error", "at utils/friend-socket.js:254", "WebSocket 错误处理:", JSON.stringify(error)); + formatAppLog("error", "at utils/friend-socket.js:255", "WebSocket 错误处理:", JSON.stringify(error)); (_b = (_a = this.options).onError) == null ? void 0 : _b.call(_a, error); } /** @@ -4201,7 +4393,7 @@ This will fail in production.`); * 清理所有定时器、标记手动关闭、停止重连 */ close() { - formatAppLog("log", "at utils/friend-socket.js:290", "手动关闭 WebSocket 连接"); + formatAppLog("log", "at utils/friend-socket.js:291", "手动关闭 WebSocket 连接"); this.isManualClose = true; this.stopHeartbeat(); if (this.reconnectTimer) { @@ -4209,21 +4401,21 @@ This will fail in production.`); this.reconnectTimer = null; } if (this.ws) { - if (this.ws.onOpen) - this.ws.onOpen(null); - if (this.ws.onMessage) - this.ws.onMessage(null); - if (this.ws.onError) - this.ws.onError(null); - if (this.ws.onClose) - this.ws.onClose(null); + this.ws.onOpen(() => { + }); + this.ws.onMessage(() => { + }); + this.ws.onError(() => { + }); + this.ws.onClose(() => { + }); try { this.ws.close({ - success: () => formatAppLog("log", "at utils/friend-socket.js:312", "连接已关闭"), - fail: (err) => formatAppLog("error", "at utils/friend-socket.js:313", "关闭失败:", err) + success: () => formatAppLog("log", "at utils/friend-socket.js:314", "连接已关闭"), + fail: (err) => formatAppLog("error", "at utils/friend-socket.js:315", "关闭失败:", err) }); } catch (error) { - formatAppLog("error", "at utils/friend-socket.js:321", "关闭连接出错:", error); + formatAppLog("error", "at utils/friend-socket.js:323", "关闭连接出错:", error); } this.ws = null; } @@ -4449,7 +4641,7 @@ This will fail in production.`); uni.registerUTSPlugin("uni_modules/lime-choose-file", exports$1); const limeChooseFile_utsProxy = uni.requireUTSPlugin("uni_modules/lime-choose-file"); const pageInfoNumber = 100; - const _sfc_main$7 = { + const _sfc_main$8 = { __name: "Chat", setup(__props, { expose: __expose }) { __expose(); @@ -4458,7 +4650,7 @@ This will fail in production.`); if (friendSocketStore.isConnected) return; if (!userToken.value || !UserId.value) { - formatAppLog("warn", "at pages/Chat/Chat.vue:265", "Token或UserId未准备好"); + formatAppLog("warn", "at pages/Chat/Chat.vue:290", "Token或UserId未准备好"); return; } friendSocketStore.connect({ @@ -4529,7 +4721,7 @@ This will fail in production.`); const html = t(content); return html; } catch (e2) { - formatAppLog("error", "at pages/Chat/Chat.vue:363", "解析失败", e2); + formatAppLog("error", "at pages/Chat/Chat.vue:388", "解析失败", e2); return content; } }; @@ -4568,6 +4760,21 @@ This will fail in production.`); } return size.toFixed(2) + "MB"; }; + const parseFileInfo = (content) => { + if (!content || typeof content !== "string") + return { textContent: content || "", files: [] }; + const match = content.match(/\[文件信息:(\[.*?\])\]/); + if (!match) + return { textContent: content, files: [] }; + try { + const files = JSON.parse(match[1]); + const textContent = content.replace(match[0], "").trim(); + return { textContent, files }; + } catch (e2) { + formatAppLog("error", "at pages/Chat/Chat.vue:456", "解析文件信息失败:", e2); + return { textContent: content, files: [] }; + } + }; const selectNormalChat = async () => { try { const chars = "0123456789abcdef"; @@ -4598,7 +4805,7 @@ This will fail in production.`); } takeUserConversations(); } catch (error) { - formatAppLog("error", "at pages/Chat/Chat.vue:457", "新建普通会话失败:", error); + formatAppLog("error", "at pages/Chat/Chat.vue:498", "新建普通会话失败:", error); uni.showToast({ title: "创建会话失败,请重试", icon: "none" @@ -4621,6 +4828,14 @@ This will fail in production.`); url: "/pages/WorkSpace/WorkSpace" }); }; + const goCloudDatabase = () => { + if (currentSessionId.value) { + uni.setStorageSync("currentSessionId", currentSessionId.value); + } + uni.navigateTo({ + url: "/pages/CloudDatabase/CloudDatabase" + }); + }; const logOut = () => { uni.reLaunch({ url: "/pages/Login/Login" @@ -4628,7 +4843,7 @@ This will fail in production.`); }; const previewFileArray = vue.ref([]); const uploadPhoto = () => { - formatAppLog("log", "at pages/Chat/Chat.vue:495", "点击了拍照上传"); + formatAppLog("log", "at pages/Chat/Chat.vue:547", "点击了拍照上传"); uni.chooseImage({ count: 1, sourceType: ["camera", "album"], @@ -4651,7 +4866,7 @@ This will fail in production.`); }); }, fail: (err) => { - formatAppLog("error", "at pages/Chat/Chat.vue:513", "选择图片失败", err); + formatAppLog("error", "at pages/Chat/Chat.vue:565", "选择图片失败", err); } }); }; @@ -4672,12 +4887,12 @@ This will fail in production.`); }; const fileList = vue.ref([]); const uploadFile = () => { - formatAppLog("log", "at pages/Chat/Chat.vue:536", "点击了上传文件"); + formatAppLog("log", "at pages/Chat/Chat.vue:588", "点击了上传文件"); limeChooseFile_utsProxy.chooseFile({ count: 5, type: "all", success: (res) => { - formatAppLog("log", "at pages/Chat/Chat.vue:541", "成功了"); + formatAppLog("log", "at pages/Chat/Chat.vue:593", "成功了"); fileList.value = res.tempFiles; previewFileArray.value.push(...res.tempFiles); uni.showToast({ @@ -4686,7 +4901,7 @@ This will fail in production.`); }); }, fail: (err) => { - formatAppLog("error", "at pages/Chat/Chat.vue:552", "选择失败:", err); + formatAppLog("error", "at pages/Chat/Chat.vue:604", "选择失败:", err); uni.showToast({ title: "选择失败", icon: "error" @@ -4740,7 +4955,7 @@ This will fail in production.`); previewFileArray.value = []; } catch (err) { uni.hideLoading(); - formatAppLog("error", "at pages/Chat/Chat.vue:619", "文件上传失败:", err); + formatAppLog("error", "at pages/Chat/Chat.vue:671", "文件上传失败:", err); uni.showToast({ title: "文件上传失败,请重试", icon: "error" @@ -4869,11 +5084,11 @@ This will fail in production.`); } }; vue.watch(() => socketStore.isThinking, (newVal, oldVal) => { - formatAppLog("log", "at pages/Chat/Chat.vue:781", "isThinking 变化:", oldVal, "→", newVal); + formatAppLog("log", "at pages/Chat/Chat.vue:833", "isThinking 变化:", oldVal, "→", newVal); if (oldVal && !newVal && socketStore.messageString) { clearTimeout(aiResponseTimer); - formatAppLog("log", "at pages/Chat/Chat.vue:785", "ai返回的消息:", socketStore.messageString); - formatAppLog("log", "at pages/Chat/Chat.vue:786", "AI回复结束,刷新消息列表"); + formatAppLog("log", "at pages/Chat/Chat.vue:837", "ai返回的消息:", socketStore.messageString); + formatAppLog("log", "at pages/Chat/Chat.vue:838", "AI回复结束,刷新消息列表"); takeConversationMessages(); isThinking.value = false; textMessage.value = ""; @@ -4893,17 +5108,16 @@ This will fail in production.`); UserData.value = await getUserInfo(userToken.value); UserId.value = UserData.value._id; UserAvatar.value = UserData.value.avatar || ""; - formatAppLog("log", "at pages/Chat/Chat.vue:812", "用户信息已加载:", UserId.value, UserAvatar.value); + formatAppLog("log", "at pages/Chat/Chat.vue:864", "用户信息已加载:", UserId.value, UserAvatar.value); } catch (error) { - formatAppLog("error", "at pages/Chat/Chat.vue:814", "获取用户信息失败:", error); + formatAppLog("error", "at pages/Chat/Chat.vue:866", "获取用户信息失败:", error); } }; const takeUserConversations = async () => { try { userToken.value = getToken(); - formatAppLog("log", "at pages/Chat/Chat.vue:822", "token:", userToken.value); + formatAppLog("log", "at pages/Chat/Chat.vue:874", "token:", userToken.value); UserConversations.value = await getUserConversations(userToken.value) || []; - formatAppLog("log", "at pages/Chat/Chat.vue:824", "UserConversations:", UserConversations.value); const savedSessionId = getCurrentSessionId(); if (savedSessionId && UserConversations.value.some((c) => c._id === savedSessionId)) { currentSessionId.value = savedSessionId; @@ -4912,7 +5126,7 @@ This will fail in production.`); } else { currentSessionId.value = ""; } - formatAppLog("log", "at pages/Chat/Chat.vue:834", "保存会话id:", currentSessionId.value); + formatAppLog("log", "at pages/Chat/Chat.vue:886", "保存会话id:", currentSessionId.value); uni.setStorageSync("currentSessionId", currentSessionId.value); } catch (error) { uni.showToast({ @@ -4924,17 +5138,17 @@ This will fail in production.`); const FriendInfoList = vue.ref([]); const takeFriendList = async () => { try { - formatAppLog("log", "at pages/Chat/Chat.vue:849", "开始获取好友列表"); + formatAppLog("log", "at pages/Chat/Chat.vue:901", "开始获取好友列表"); const friendList = await getChatFriend(UserId.value); - formatAppLog("log", "at pages/Chat/Chat.vue:852", "friendList:", friendList); + formatAppLog("log", "at pages/Chat/Chat.vue:904", "friendList:", friendList); if (friendList && friendList.length) { FriendInfoList.value = await takeUserAvatar(friendList); } else { FriendInfoList.value = []; - formatAppLog("log", "at pages/Chat/Chat.vue:857", "好友列表为空"); + formatAppLog("log", "at pages/Chat/Chat.vue:909", "好友列表为空"); } } catch (error) { - formatAppLog("error", "at pages/Chat/Chat.vue:860", "获取好友列表失败:", error); + formatAppLog("error", "at pages/Chat/Chat.vue:912", "获取好友列表失败:", error); FriendInfoList.value = []; } finally { UserConversations.value = FriendInfoList.value; @@ -4961,17 +5175,17 @@ This will fail in production.`); }; }); } catch (err) { - formatAppLog("error", "at pages/Chat/Chat.vue:890", "获取好友头像失败", err); + formatAppLog("error", "at pages/Chat/Chat.vue:942", "获取好友头像失败", err); return friendList; } }; const GroupList = vue.ref([]); const takeGroupList = async () => { try { - formatAppLog("log", "at pages/Chat/Chat.vue:900", "开始获取群聊列表"); + formatAppLog("log", "at pages/Chat/Chat.vue:952", "开始获取群聊列表"); GroupList.value = await getGroup(UserId.value); } catch (error) { - formatAppLog("error", "at pages/Chat/Chat.vue:905", "获取群聊列表失败:", error); + formatAppLog("error", "at pages/Chat/Chat.vue:957", "获取群聊列表失败:", error); GroupList.value = []; } finally { UserConversations.value = GroupList.value; @@ -4983,22 +5197,22 @@ This will fail in production.`); return []; try { const memberIds = memberList.map((item) => item.groupContactId); - formatAppLog("log", "at pages/Chat/Chat.vue:919", "请求头像的ID列表:", memberIds); + formatAppLog("log", "at pages/Chat/Chat.vue:971", "请求头像的ID列表:", memberIds); const memberAvatarList = await getUserAvatar(userToken.value, memberIds); - formatAppLog("log", "at pages/Chat/Chat.vue:921", "头像接口返回数据:", memberAvatarList); + formatAppLog("log", "at pages/Chat/Chat.vue:973", "头像接口返回数据:", memberAvatarList); const userMap = new Map(memberAvatarList.map((user) => [user.user_id, user]) || []); - formatAppLog("log", "at pages/Chat/Chat.vue:924", "userMap的keys:", Array.from(userMap.keys())); + formatAppLog("log", "at pages/Chat/Chat.vue:976", "userMap的keys:", Array.from(userMap.keys())); return memberList.map((member) => { const memberId = member.groupContactId; const userInfo = userMap.get(memberId); - formatAppLog("log", "at pages/Chat/Chat.vue:929", `查找 ${memberId} 的头像:`, userInfo); + formatAppLog("log", "at pages/Chat/Chat.vue:981", `查找 ${memberId} 的头像:`, userInfo); return { ...member, avatar: (userInfo == null ? void 0 : userInfo.avatar) || null }; }); } catch (err) { - formatAppLog("error", "at pages/Chat/Chat.vue:936", "获取群成员头像失败", err); + formatAppLog("error", "at pages/Chat/Chat.vue:988", "获取群成员头像失败", err); return memberList; } }; @@ -5029,7 +5243,7 @@ This will fail in production.`); const takeFriendMessages = async () => { try { allmessages.value = await getFriendMessages(currentSessionId.value) || []; - formatAppLog("log", "at pages/Chat/Chat.vue:981", "好友消息:", JSON.stringify(allmessages.value)); + formatAppLog("log", "at pages/Chat/Chat.vue:1033", "好友消息:", JSON.stringify(allmessages.value)); scrollToBottom(); } catch (error) { uni.showToast({ @@ -5041,12 +5255,12 @@ This will fail in production.`); const takeGroupMessages = async () => { try { allmessages.value = await getGroupMessages(currentSessionId.value) || []; - formatAppLog("log", "at pages/Chat/Chat.vue:994", "群聊消息:", allmessages.value); + formatAppLog("log", "at pages/Chat/Chat.vue:1046", "群聊消息:", allmessages.value); const memberList = await getGroupMemberList(currentSessionId.value); - formatAppLog("log", "at pages/Chat/Chat.vue:997", "获取到的群成员列表:", memberList); + formatAppLog("log", "at pages/Chat/Chat.vue:1049", "获取到的群成员列表:", memberList); if (memberList && memberList.length) { groupMemberList.value = await takeGroupMemberAvatar(memberList); - formatAppLog("log", "at pages/Chat/Chat.vue:1000", "群成员列表(带头像):", groupMemberList.value); + formatAppLog("log", "at pages/Chat/Chat.vue:1052", "群成员列表(带头像):", groupMemberList.value); } else { groupMemberList.value = []; } @@ -5059,7 +5273,7 @@ This will fail in production.`); } }; const loadMoreMessages = async () => { - formatAppLog("log", "at pages/Chat/Chat.vue:1015", "加载更多信息"); + formatAppLog("log", "at pages/Chat/Chat.vue:1067", "加载更多信息"); if (allmessages.value.length > pageInfoNumber * currentPage.value) { currentPage.value += 1; const newMessages = allmessages.value.slice(-pageInfoNumber * currentPage.value); @@ -5078,9 +5292,9 @@ This will fail in production.`); } }; vue.watch(() => friendSocketStore.MessageReceived, (newId) => { - formatAppLog("log", "at pages/Chat/Chat.vue:1043", "收到了好友消息"); + formatAppLog("log", "at pages/Chat/Chat.vue:1095", "收到了好友消息"); if (newId) { - formatAppLog("log", "at pages/Chat/Chat.vue:1045", "ChatType:", ChatType.value); + formatAppLog("log", "at pages/Chat/Chat.vue:1097", "ChatType:", ChatType.value); switch (ChatType.value) { case 0: takeConversationMessages(); @@ -5095,7 +5309,7 @@ This will fail in production.`); friendSocketStore.MessageReceived = false; break; default: - formatAppLog("log", "at pages/Chat/Chat.vue:1061", "default 分支"); + formatAppLog("log", "at pages/Chat/Chat.vue:1113", "default 分支"); friendSocketStore.MessageReceived = false; break; } @@ -5149,7 +5363,7 @@ This will fail in production.`); await takeGroupMessages(); } }); - const __returned__ = { friendSocketStore, handleFriendConnect, socketStore, ChatType, convertMarkdownTable, renderTable, pareseMarkdown, sanitizeContent, previewImage, openFile, formatFileSize, selectNormalChat, showNewChatModal, closeNewChatModal, isChatSidebar, handleChatSidebar, goWorkSpace, logOut, previewFileArray, uploadPhoto, deleteImage, fileList, uploadFile, handleConnect, isThinking, isUploading, uploadedFiles, sendMessage, sendFriendMessage, sendGroupMessage, get aiResponseTimer() { + const __returned__ = { friendSocketStore, handleFriendConnect, socketStore, ChatType, convertMarkdownTable, renderTable, pareseMarkdown, sanitizeContent, previewImage, openFile, formatFileSize, parseFileInfo, selectNormalChat, showNewChatModal, closeNewChatModal, isChatSidebar, handleChatSidebar, goWorkSpace, goCloudDatabase, logOut, previewFileArray, uploadPhoto, deleteImage, fileList, uploadFile, handleConnect, isThinking, isUploading, uploadedFiles, sendMessage, sendFriendMessage, sendGroupMessage, get aiResponseTimer() { return aiResponseTimer; }, set aiResponseTimer(v) { aiResponseTimer = v; @@ -5206,7 +5420,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$7(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, @@ -5338,6 +5552,12 @@ This will fail in production.`); }, [ vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }) ]), + vue.createElementVNode("view", { + class: "head-btn", + onClick: $setup.goCloudDatabase + }, [ + vue.createElementVNode("view", { class: "iconfont icon-cloud" }) + ]), vue.createElementVNode("view", { class: "head-btn log-out", onClick: $setup.logOut @@ -5394,9 +5614,55 @@ This will fail in production.`); class: vue.normalizeClass(["chat-content", { "chat-content-user": message.role === "user" }]) }, [ - vue.createElementVNode("view", { - innerHTML: $setup.pareseMarkdown(message.content) - }, null, 8, ["innerHTML"]) + $setup.parseFileInfo(message.content).textContent ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + innerHTML: $setup.pareseMarkdown($setup.parseFileInfo(message.content).textContent) + }, null, 8, ["innerHTML"])) : vue.createCommentVNode("v-if", true), + $setup.parseFileInfo(message.content).files.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "message-file-list" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.parseFileInfo(message.content).files, (file, idx) => { + return vue.openBlock(), vue.createElementBlock("view", { + key: idx, + class: "file-item" + }, [ + ["jpg", "jpeg", "png", "gif", "webp", "bmp"].includes(file.extendName.toLowerCase()) ? (vue.openBlock(), vue.createElementBlock("image", { + key: 0, + src: file.url, + mode: "widthFix", + class: "message-image", + onClick: ($event) => $setup.previewImage(file.url) + }, null, 8, ["src", "onClick"])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "message-file", + onClick: ($event) => $setup.openFile(file.url) + }, [ + vue.createElementVNode("view", { class: "file-icon" }, "📄"), + vue.createElementVNode( + "view", + { class: "file-name" }, + vue.toDisplayString(file.name), + 1 + /* TEXT */ + ), + vue.createElementVNode( + "view", + { class: "file-size" }, + vue.toDisplayString($setup.formatFileSize(file.fileSize)), + 1 + /* TEXT */ + ) + ], 8, ["onClick"])) + ]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) : vue.createCommentVNode("v-if", true) ], 2 /* CLASS */ @@ -5684,8 +5950,8 @@ This will fail in production.`); /* STABLE_FRAGMENT */ ); } - const PagesChatChat = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$6], ["__scopeId", "data-v-5eb7b895"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/Chat/Chat.vue"]]); - const _sfc_main$6 = { + const PagesChatChat = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["render", _sfc_render$7], ["__scopeId", "data-v-5eb7b895"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/Chat/Chat.vue"]]); + const _sfc_main$7 = { __name: "WorkSpace", setup(__props, { expose: __expose }) { __expose(); @@ -6020,7 +6286,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$6(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, @@ -6271,8 +6537,8 @@ This will fail in production.`); /* STABLE_FRAGMENT */ ); } - const PagesWorkSpaceWorkSpace = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$5], ["__scopeId", "data-v-c1a60359"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/WorkSpace.vue"]]); - const _sfc_main$5 = { + const PagesWorkSpaceWorkSpace = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$6], ["__scopeId", "data-v-c1a60359"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/WorkSpace.vue"]]); + const _sfc_main$6 = { __name: "UserProfileModal", setup(__props, { expose: __expose }) { __expose(); @@ -6287,11 +6553,34 @@ This will fail in production.`); } }); }; - const saveUpdate = () => { - uni.navigateBack({ - url: "/pages/Chat/Chat" - }); + const saveUpdate = async () => { + if (!editUsername.value.trim()) { + uni.showToast({ title: "用户名不能为空", icon: "none" }); + return; + } + uni.showLoading({ title: "保存中...", mask: true }); + try { + await updateUserInfo( + UserToken.value, + UserId.value, + editUsername.value.trim(), + editEmail.value.trim(), + editUserAvatar.value + ); + uni.hideLoading(); + uni.showToast({ title: "保存成功", icon: "success" }); + setTimeout(() => { + closeUserCard(); + }, 800); + } catch (err) { + uni.hideLoading(); + const msg = typeof err === "string" ? err : "保存失败,请稍后重试"; + uni.showToast({ title: msg, icon: "none" }); + formatAppLog("error", "at pages/UserProfileModal/UserProfileModal.vue:93", "保存用户信息失败:", err); + } }; + const UserToken = vue.ref(""); + const UserId = vue.ref(""); const editUserAvatar = vue.ref(""); const editUsername = vue.ref(""); const editEmail = vue.ref(""); @@ -6304,25 +6593,33 @@ This will fail in production.`); sourceType: ["album", "camera"], success: (res) => { const tempFilePath = res.tempFilePaths[0]; - handlrImageSelected(tempFilePath); + handleImageSelected(tempFilePath); }, fail: (err) => { - formatAppLog("log", "at pages/UserProfileModal/UserProfileModal.vue:90", "选择图片失败", err); + formatAppLog("log", "at pages/UserProfileModal/UserProfileModal.vue:116", "选择图片失败", err); } }); }; - const handlrImageSelected = (filePath) => { + const handleImageSelected = (filePath) => { editUserAvatar.value = filePath; }; vue.onMounted(async () => { - const token = getToken(); - const UserInfo = await getUserInfo(token); - editUserAvatar.value = UserInfo.avatar || ""; - editUsername.value = UserInfo.username || ""; - editEmail.value = UserInfo.email || ""; + UserToken.value = getToken(); + try { + const UserInfo = await getUserInfo(UserToken.value); + UserId.value = UserInfo._id || ""; + editUserAvatar.value = UserInfo.avatar || ""; + editUsername.value = UserInfo.username || ""; + editEmail.value = UserInfo.email || ""; + } catch (err) { + formatAppLog("error", "at pages/UserProfileModal/UserProfileModal.vue:135", "获取用户信息失败:", err); + uni.showToast({ title: "加载用户信息失败", icon: "none" }); + } }); - const __returned__ = { closeUserCard, saveUpdate, editUserAvatar, editUsername, editEmail, isNameFocus, isEmailFocus, triggerAvatarUpload, handlrImageSelected, onMounted: vue.onMounted, ref: vue.ref, get getUserInfo() { + const __returned__ = { closeUserCard, saveUpdate, UserToken, UserId, editUserAvatar, editUsername, editEmail, isNameFocus, isEmailFocus, triggerAvatarUpload, handleImageSelected, onMounted: vue.onMounted, ref: vue.ref, get getUserInfo() { return getUserInfo; + }, get updateUserInfo() { + return updateUserInfo; }, get getToken() { return getToken; } }; @@ -6330,7 +6627,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$5(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, @@ -6428,8 +6725,8 @@ This will fail in production.`); /* STABLE_FRAGMENT */ ); } - const PagesUserProfileModalUserProfileModal = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4], ["__scopeId", "data-v-d2908b51"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/UserProfileModal/UserProfileModal.vue"]]); - const _sfc_main$4 = { + const PagesUserProfileModalUserProfileModal = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["render", _sfc_render$5], ["__scopeId", "data-v-d2908b51"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/UserProfileModal/UserProfileModal.vue"]]); + const _sfc_main$5 = { __name: "ContactPages", setup(__props, { expose: __expose }) { __expose(); @@ -6438,7 +6735,7 @@ This will fail in production.`); if (friendSocketStore.isConnected) return; if (!userToken.value || !UserId.value) { - formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:325", "Token或UserId未准备好"); + formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:341", "Token或UserId未准备好"); return; } friendSocketStore.connect({ @@ -6512,21 +6809,21 @@ This will fail in production.`); const FriendInfoList = vue.ref([]); const takeFriendList = async () => { try { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:426", "开始获取好友列表"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:442", "开始获取好友列表"); userToken.value = getToken(); const userInfo = await getUserInfo(userToken.value); UserId.value = userInfo._id; - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:430", "UserId.value:", UserId.value); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:446", "UserId.value:", UserId.value); const friendList = await getChatFriend(UserId.value); - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:432", "friendList:", friendList); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:448", "friendList:", friendList); if (friendList && friendList.length) { FriendInfoList.value = await takeUserAvatar(friendList); } else { FriendInfoList.value = []; - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:437", "好友列表为空"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:453", "好友列表为空"); } } catch (error) { - formatAppLog("error", "at pages/ContactPages/ContactPages.vue:440", "获取好友列表失败:", error); + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:456", "获取好友列表失败:", error); FriendInfoList.value = []; } }; @@ -6545,26 +6842,27 @@ This will fail in production.`); }; }); } catch (err) { - formatAppLog("error", "at pages/ContactPages/ContactPages.vue:461", "获取好友头像失败", err); + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:477", "获取好友头像失败", err); return friendList; } }; vue.onMounted(async () => { await takeFriendList(); await takeGroupList(); + await takeFriendRequestList(); handleFriendConnect(); }); const GroupList = vue.ref([]); const takeGroupList = async () => { try { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:477", "开始获取群聊列表"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:494", "开始获取群聊列表"); userToken.value = getToken(); const userInfo = await getUserInfo(userToken.value); UserId.value = userInfo._id; - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:481", "UserId.value:", UserId.value); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:498", "UserId.value:", UserId.value); GroupList.value = await getGroup(UserId.value); } catch (error) { - formatAppLog("error", "at pages/ContactPages/ContactPages.vue:484", "获取群聊列表失败:", error); + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:501", "获取群聊列表失败:", error); GroupList.value = []; } }; @@ -6580,7 +6878,7 @@ This will fail in production.`); reject(new Error("Token或UserId未准备好")); return; } - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:505", "friendSocket 未连接,正在建立连接..."); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:522", "friendSocket 未连接,正在建立连接..."); friendSocketStore.connect({ token: userToken.value, UserId: UserId.value @@ -6588,7 +6886,7 @@ This will fail in production.`); const checkInterval = setInterval(() => { if (friendSocketStore.isConnected) { clearInterval(checkInterval); - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:514", "friendSocket 连接已建立"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:531", "friendSocket 连接已建立"); resolve(); } }, 100); @@ -6636,10 +6934,10 @@ This will fail in production.`); if (isSend) { await sendCreateGroup(); } else { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:570", "发送新建群聊消息失败"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:587", "发送新建群聊消息失败"); } } catch (err) { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:573", err); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:590", err); uni.showToast({ title: `新建群聊失败${err}`, icon: "none" @@ -6652,21 +6950,21 @@ This will fail in production.`); reject(new Error("超时未返回群聊创建结果")); }, 18e4); const unwatch = vue.watch(() => friendSocketStore.command, async (newVal) => { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:592", "创建一个一次性监听器"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:609", "创建一个一次性监听器"); if (newVal && friendSocketStore.command === 3) { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:594", "监听到command的值是3,检查群聊是否创建成功", friendSocketStore.command); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:611", "监听到command的值是3,检查群聊是否创建成功", friendSocketStore.command); try { await takeGroupList(); const newGroup = GroupList.value.find((g) => g.id === friendSocketStore.groupId); if (newGroup) { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:601", "✅ 新建群聊成功", newGroup); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:618", "✅ 新建群聊成功", newGroup); selectGroupMember.value = []; currentTab.value = 0; } else { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:606", "❌ 新建群聊失败 / 群组不存在"); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:623", "❌ 新建群聊失败 / 群组不存在"); } } catch (error) { - formatAppLog("error", "at pages/ContactPages/ContactPages.vue:610", "保存AI回复失败:", error); + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:627", "保存AI回复失败:", error); reject(error); } finally { friendSocketStore.command = null; @@ -6680,8 +6978,8 @@ This will fail in production.`); }; const selectGroupMember = vue.ref([]); const handlCreateEmember = (id) => { - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:631", "选择的好友id:", id); - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:632", "selectGroupMember.value=", JSON.stringify(selectGroupMember.value)); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:648", "选择的好友id:", id); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:649", "selectGroupMember.value=", JSON.stringify(selectGroupMember.value)); const index = selectGroupMember.value.findIndex((item) => item.id === id); if (index === -1) { const friendItem = FriendInfoList.value.find((item) => item.receiver === id); @@ -6705,20 +7003,20 @@ This will fail in production.`); } const keyword = searchFriendName.value.toLowerCase().trim(); searchResultList.value = await searchUsers(userToken.value, keyword); - formatAppLog("log", "at pages/ContactPages/ContactPages.vue:659", "searchResultList.value:", searchResultList.value); + formatAppLog("log", "at pages/ContactPages/ContactPages.vue:676", "searchResultList.value:", JSON.stringify(searchResultList.value)); }; const handleFriendSearchFocus = () => { isSearchFriend.value = !isSearchFriend.value; }; const currentAddFriend = vue.ref(null); const addNewFriend = (id) => { - const friend = mockFriendDB.value.find((friend2) => friend2.id === id); + const friend = searchResultList.value.find((friend2) => friend2._id === id); if (friend) { currentAddFriend.value = { ...friend }; } else { - formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:680", "未找到该好友"); + formatAppLog("warn", "at pages/ContactPages/ContactPages.vue:697", "未找到该好友"); currentAddFriend.value = null; } }; @@ -6726,6 +7024,7 @@ This will fail in production.`); currentAddFriend.value = null; isAgreeBeFriend.value = false; }; + const inputFriendNickname = vue.ref(""); const isVoice = vue.ref(false); const isCamera = vue.ref(false); const togglesVoice = () => { @@ -6735,78 +7034,105 @@ This will fail in production.`); isCamera.value = !isCamera.value; }; const isAgreeBeFriend = vue.ref(false); - const refuseBeFriend = (friend) => { + const friendRequestList = vue.ref([]); + const takeFriendRequestList = async () => { + try { + if (!UserId.value) + return; + const list = await getFriendRequestList(UserId.value); + if (list && list.length) { + friendRequestList.value = await takeRequestAvatar(list); + } else { + friendRequestList.value = []; + } + } catch (error) { + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:732", "获取好友申请列表失败:", error); + friendRequestList.value = []; + } }; - const agreeBeFriend = (friend) => { + const takeRequestAvatar = async (requestList) => { + if (!(requestList == null ? void 0 : requestList.length)) + return []; + try { + const requestIds = requestList.map((item) => item.sendId); + const avatarList = await getUserAvatar(userToken.value, requestIds); + const userMap = new Map(avatarList.map((user) => [user.user_id, user]) || []); + return requestList.map((request) => { + const userInfo = userMap.get(request.sendId); + return { + ...request, + avatar: (userInfo == null ? void 0 : userInfo.avatar) || null + }; + }); + } catch (err) { + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:751", "获取申请人头像失败", err); + return requestList; + } + }; + const agreeBeFriend = (request) => { isAgreeBeFriend.value = true; currentAddFriend.value = { - ...friend + ...request, + username: request.friendNickName || request.sendId }; }; - const mockFriendDB = vue.ref([ - { - id: 1, - nickname: "张三", - username: "zhangsan", - email: "zhangsan@example.com", - avatar: "👤" - }, - { - id: 2, - nickname: "李四", - username: "lisi", - email: "lisi@example.com", - avatar: "👥" - }, - { - id: 3, - nickname: "王小明", - username: "wangxm", - email: "wang@example.com", - avatar: "👪" - }, - { - id: 4, - nickname: "赵磊", - username: "zhaolei", - email: "zhao@example.com", - avatar: "🗣️" - }, - { - id: 5, - nickname: "张三2", - username: "zhangsan", - email: "zhangsan@example.com", - avatar: "👤" - }, - { - id: 6, - nickname: "李四2", - username: "lisi", - email: "lisi@example.com", - avatar: "👥" - }, - { - id: 7, - nickname: "王小明2", - username: "wangxm", - email: "wang@example.com", - avatar: "👪" - }, - { - id: 8, - nickname: "赵磊2", - username: "zhaolei", - email: "zhao@example.com", - avatar: "🗣️" + const handleFriendOperate = async () => { + if (isAgreeBeFriend.value) { + try { + const friendId = currentAddFriend.value.sendId; + const friendNickName = inputFriendNickname.value || currentAddFriend.value.friendNickName || ""; + const sessionId = currentAddFriend.value.sessionId || Date.now(); + const friendRelationshipId = currentAddFriend.value.id; + await saveFriend([ + { + friendNickName, + sender: UserId.value, + receiver: friendId, + sessionId, + friendRelationshipId + }, + { + friendNickName: "", + sender: friendId, + receiver: UserId.value, + sessionId, + friendRelationshipId + } + ]); + uni.showToast({ title: "已同意好友申请", icon: "none" }); + const target = friendRequestList.value.find((item) => item.sendId === friendId); + if (target) + target.status = 1; + closeAddFriendCard(); + await takeFriendList(); + } catch (error) { + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:795", "同意好友申请失败:", error); + uni.showToast({ title: "操作失败", icon: "none" }); + } + } else { + try { + const friendId = currentAddFriend.value._id; + const msg = await sendFriendRequest(UserId.value, inputFriendNickname.value, friendId); + uni.showToast({ title: msg, icon: "none" }); + closeAddFriendCard(); + } catch (error) { + formatAppLog("error", "at pages/ContactPages/ContactPages.vue:806", "发送好友申请失败:", error); + uni.showToast({ title: "发送申请失败", icon: "none" }); + } } - ]); - const __returned__ = { friendSocketStore, handleFriendConnect, handleBack, changeChatType, currentTab, tabList, onSwiperChange, switchTab, userToken, UserId, FriendAI, FriendInfoList, takeFriendList, takeUserAvatar, GroupList, takeGroupList, createGroupName, createGroupData, ensureFriendSocketConnected, createGroup, sendCreateGroup, selectGroupMember, handlCreateEmember, isSearchFriend, searchFriendName, searchResultList, searchFriend, handleFriendSearchFocus, currentAddFriend, addNewFriend, closeAddFriendCard, isVoice, isCamera, togglesVoice, togglesCamera, isAgreeBeFriend, refuseBeFriend, agreeBeFriend, mockFriendDB, onMounted: vue.onMounted, reactive: vue.reactive, ref: vue.ref, watch: vue.watch, get getToken() { + }; + const __returned__ = { friendSocketStore, handleFriendConnect, handleBack, changeChatType, currentTab, tabList, onSwiperChange, switchTab, userToken, UserId, FriendAI, FriendInfoList, takeFriendList, takeUserAvatar, GroupList, takeGroupList, createGroupName, createGroupData, ensureFriendSocketConnected, createGroup, sendCreateGroup, selectGroupMember, handlCreateEmember, isSearchFriend, searchFriendName, searchResultList, searchFriend, handleFriendSearchFocus, currentAddFriend, addNewFriend, closeAddFriendCard, inputFriendNickname, isVoice, isCamera, togglesVoice, togglesCamera, isAgreeBeFriend, friendRequestList, takeFriendRequestList, takeRequestAvatar, agreeBeFriend, handleFriendOperate, onMounted: vue.onMounted, reactive: vue.reactive, ref: vue.ref, watch: vue.watch, get getToken() { return getToken; }, get getChatFriend() { return getChatFriend; }, get getGroup() { return getGroup; + }, get sendFriendRequest() { + return sendFriendRequest; + }, get getFriendRequestList() { + return getFriendRequestList; + }, get saveFriend() { + return saveFriend; }, get getUserInfo() { return getUserInfo; }, get getUserAvatar() { @@ -6820,7 +7146,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) { const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); return vue.openBlock(), vue.createElementBlock( vue.Fragment, @@ -6847,13 +7173,21 @@ This will fail in production.`); ), vue.createElementVNode("view", { class: "friend-card" }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ - vue.createElementVNode( - "view", - { class: "friend-avatar" }, - vue.toDisplayString($setup.currentAddFriend.avatar), - 1 - /* TEXT */ - ) + $setup.currentAddFriend.avatar ? (vue.openBlock(), vue.createElementBlock("image", { + key: 0, + src: $setup.currentAddFriend.avatar, + class: "friend-avatar", + mode: "aspectFill" + }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "friend-avatar" + }, [ + vue.createVNode(_component_uni_icons, { + type: "person-filled", + size: "100rpx", + color: "#ffffff" + }) + ])) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( @@ -6874,14 +7208,26 @@ This will fail in production.`); ]), vue.createElementVNode("view", { class: "nickname-wrapper" }, [ vue.createElementVNode("view", null, "好友备注"), - vue.createElementVNode("input", { - class: "input-nickname", - placeholder: "请输入好友名称" - }) + vue.withDirectives(vue.createElementVNode( + "input", + { + class: "input-nickname", + placeholder: "请输入好友名称", + "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.inputFriendNickname = $event) + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.inputFriendNickname] + ]) ]), vue.createElementVNode( "view", - { class: "text-btn confirm-btn" }, + { + class: "text-btn confirm-btn", + onClick: $setup.handleFriendOperate + }, vue.toDisplayString($setup.isAgreeBeFriend ? "确认通过" : "发送申请"), 1 /* TEXT */ @@ -6913,7 +7259,7 @@ This will fail in production.`); vue.createElementVNode("view", { class: "friend-list" }, [ vue.createElementVNode("view", { class: "friend-card", - onClick: _cache[0] || (_cache[0] = ($event) => $setup.changeChatType(0)) + onClick: _cache[1] || (_cache[1] = ($event) => $setup.changeChatType(0)) }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ vue.createElementVNode("view", { @@ -7059,7 +7405,7 @@ This will fail in production.`); { class: "input", placeholder: "请输入群名称", - "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => $setup.createGroupName = $event) + "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.createGroupName = $event) }, null, 512 @@ -7185,7 +7531,9 @@ This will fail in production.`); class: vue.normalizeClass(["search-file-input", { active: $setup.isSearchFriend }]), onFocus: $setup.handleFriendSearchFocus, onBlur: $setup.handleFriendSearchFocus, - "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.searchFriendName = $event) + "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => $setup.searchFriendName = $event), + "confirm-type": "search", + onConfirm: $setup.searchFriend }, null, 34 @@ -7220,13 +7568,13 @@ This will fail in production.`); key: friend.id }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ - vue.createElementVNode( - "view", - { class: "friend-avatar" }, - vue.toDisplayString(friend.avatar), - 1 - /* TEXT */ - ) + vue.createElementVNode("view", { class: "friend-avatar" }, [ + vue.createElementVNode("image", { + class: "friend-avatar", + src: friend.avatar, + mode: "aspectFill" + }, null, 8, ["src"]) + ]) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( @@ -7246,7 +7594,7 @@ This will fail in production.`); ]), vue.createElementVNode("view", { class: "friend-card-right", - onClick: ($event) => $setup.addNewFriend(friend.id) + onClick: ($event) => $setup.addNewFriend(friend._id) }, [ vue.createElementVNode("view", { class: "add-btn text-btn" }, "添加") ], 8, ["onClick"]) @@ -7311,7 +7659,7 @@ This will fail in production.`); ]), vue.createElementVNode("view", { class: "friend-card-right", - onClick: _cache[3] || (_cache[3] = ($event) => $setup.addNewFriend(_ctx.friend.id)) + onClick: _cache[4] || (_cache[4] = ($event) => _ctx.addMeetingMembers(_ctx.friend.id)) }, [ vue.createElementVNode("view", { class: "add-btn text-btn" }, "添加") ]) @@ -7378,7 +7726,11 @@ This will fail in production.`); vue.createElementVNode("view", { class: "tabpage-title" }, "好友申请") ]), vue.createElementVNode("view", { class: "tabpage-body" }, [ - vue.createElementVNode("scroll-view", { + !$setup.friendRequestList.length ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "no-result" + }, "暂无好友申请")) : (vue.openBlock(), vue.createElementBlock("scroll-view", { + key: 1, class: "group-member", direction: "vertical", "scroll-y": "true" @@ -7387,47 +7739,57 @@ This will fail in production.`); (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, - vue.renderList($setup.mockFriendDB, (friend) => { + vue.renderList($setup.friendRequestList, (request) => { return vue.openBlock(), vue.createElementBlock("view", { class: "friend-card", - key: friend.id + key: request.id }, [ vue.createElementVNode("view", { class: "friend-card-left" }, [ - vue.createElementVNode( - "view", - { class: "friend-avatar" }, - vue.toDisplayString(friend.avatar), - 1 - /* TEXT */ - ) + request.avatar ? (vue.openBlock(), vue.createElementBlock("image", { + key: 0, + src: request.avatar, + class: "friend-avatar", + mode: "aspectFill" + }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "friend-avatar" + }, [ + vue.createVNode(_component_uni_icons, { + type: "person-filled", + size: "100rpx", + color: "#ffffff" + }) + ])) ]), vue.createElementVNode("view", { class: "friend-card-middle" }, [ vue.createElementVNode( "view", { class: "friend-name" }, - vue.toDisplayString(friend.nickname), + vue.toDisplayString(request.friendNickName || request.sendId), 1 /* TEXT */ ), vue.createElementVNode( "view", { class: "friend-label" }, - vue.toDisplayString(friend.email), + vue.toDisplayString(request.message || "请求添加你为好友"), 1 /* TEXT */ ) ]), vue.createElementVNode("view", { class: "friend-card-right" }, [ - vue.createElementVNode("view", { class: "friend-option" }, [ - vue.createElementVNode("view", { - class: "refuse-btn text-btn", - onClick: ($event) => $setup.refuseBeFriend(friend) - }, "拒绝", 8, ["onClick"]), + request.state === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "friend-option" + }, [ vue.createElementVNode("view", { class: "agree-btn text-btn", - onClick: ($event) => $setup.agreeBeFriend(friend) + onClick: ($event) => $setup.agreeBeFriend(request) }, "同意", 8, ["onClick"]) - ]) + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "friend-status agreed" + }, "已同意")) ]) ]); }), @@ -7435,7 +7797,7 @@ This will fail in production.`); /* KEYED_FRAGMENT */ )) ]) - ]) + ])) ]) ]) ]) @@ -7476,8 +7838,8 @@ This will fail in production.`); /* STABLE_FRAGMENT */ ); } - const PagesContactPagesContactPages = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__scopeId", "data-v-976117c3"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/ContactPages/ContactPages.vue"]]); - const _sfc_main$3 = { + const PagesContactPagesContactPages = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4], ["__scopeId", "data-v-976117c3"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/ContactPages/ContactPages.vue"]]); + const _sfc_main$4 = { __name: "TemplateSpace", setup(__props, { expose: __expose }) { __expose(); @@ -7791,7 +8153,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock( vue.Fragment, null, @@ -8034,8 +8396,8 @@ This will fail in production.`); /* STABLE_FRAGMENT */ ); } - const PagesWorkSpaceTemplateSpaceTemplateSpace = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__scopeId", "data-v-769edd25"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/TemplateSpace/TemplateSpace.vue"]]); - const _sfc_main$2 = { + const PagesWorkSpaceTemplateSpaceTemplateSpace = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$3], ["__scopeId", "data-v-769edd25"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/WorkSpace/TemplateSpace/TemplateSpace.vue"]]); + const _sfc_main$3 = { __name: "text", setup(__props, { expose: __expose }) { __expose(); @@ -8190,15 +8552,15 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("view", null, [ vue.createElementVNode("view", { innerHTML: $setup.sanitizeContent($setup.formHtml) }, null, 8, ["innerHTML"]) ]); } - const PagesTextText = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text.vue"]]); - const _sfc_main$1 = { + const PagesTextText = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$2], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text.vue"]]); + const _sfc_main$2 = { __name: "text2", setup(__props, { expose: __expose }) { __expose(); @@ -8355,7 +8717,7 @@ This will fail in production.`); return __returned__; } }; - function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { + function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("view", { class: "container" }, [ vue.createElementVNode("view", { class: "status-card" }, [ vue.createElementVNode("text", { class: "status-label" }, "连接状态"), @@ -8552,7 +8914,1394 @@ This will fail in production.`); ]) ]); } - const PagesTextText2 = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-cd5869b7"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text2.vue"]]); + const PagesTextText2 = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$1], ["__scopeId", "data-v-cd5869b7"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/text/text2.vue"]]); + const _sfc_main$1 = { + __name: "CloudDatabase", + setup(__props, { expose: __expose }) { + __expose(); + const userToken = vue.ref(""); + const userId = vue.ref(""); + const workspaceId = vue.ref(""); + const currentCategory = vue.ref("user"); + const switchCategory = (category) => { + currentCategory.value = category; + currentFolderPath.value = []; + loadCurrentFiles(); + }; + const navbarTitle = vue.ref("云端数据"); + const isMenuOpen = vue.ref(false); + const isSelectFolder = vue.ref(false); + const selectFileList = vue.ref([]); + const handleMenu = () => { + isMenuOpen.value = !isMenuOpen.value; + }; + const handleSelectFolder = () => { + isSelectFolder.value = !isSelectFolder.value; + if (!isSelectFolder.value) { + selectFileList.value = []; + } + }; + const parentFolderName = vue.computed(() => { + var _a; + if (currentFolderPath.value.length === 0) + return ""; + if (currentFolderPath.value.length === 1) + return "云端数据"; + return ((_a = currentFolderPath.value[currentFolderPath.value.length - 2]) == null ? void 0 : _a.name) || "云端数据"; + }); + const handleBackOrUp = () => { + if (currentFolderPath.value.length > 0) { + currentFolderPath.value.pop(); + navbarTitle.value = currentFolderPath.value.length > 0 ? currentFolderPath.value[currentFolderPath.value.length - 1].name : "云端数据"; + loadCurrentFiles(); + } else { + uni.navigateBack({ + delta: 1, + fail() { + uni.reLaunch({ url: "/pages/Chat/Chat" }); + } + }); + } + }; + const rawPersonalFileData = vue.ref([]); + const rawTeamFileData = vue.ref([]); + const personalFiles = vue.ref([]); + const teamFiles = vue.ref([]); + const currentFolderPath = vue.ref([]); + const isFolder = (file) => { + return file.type === "folder"; + }; + const getFileExtension = (file) => { + if (isFolder(file)) + return "folder"; + const name2 = file.name || ""; + const dotIndex = name2.lastIndexOf("."); + if (dotIndex === -1) + return ""; + return name2.slice(dotIndex).toLowerCase(); + }; + const getFileIcon = (file) => { + if (isFolder(file)) + return "icon-a-wenjianjiawenjian"; + const ext = getFileExtension(file); + const mimeType = (file.type || "").toLowerCase(); + const extMap = { + ".png": "icon-wenjiantupian", + ".jpg": "icon-wenjiantupian", + ".jpeg": "icon-wenjiantupian", + ".gif": "icon-wenjiantupian", + ".svg": "icon-SVG", + ".bmp": "icon-wenjiantupian", + ".webp": "icon-wenjiantupian", + ".mp4": "icon-wenjianshipin", + ".avi": "icon-wenjianshipin", + ".mov": "icon-wenjianshipin", + ".wmv": "icon-wenjianshipin", + ".flv": "icon-wenjianshipin", + ".mkv": "icon-wenjianshipin", + ".mp3": "icon-wenjianyinpin", + ".wav": "icon-wenjianyinpin", + ".flac": "icon-wenjianyinpin", + ".aac": "icon-wenjianyinpin", + ".pdf": "icon-PDF", + ".doc": "icon-DOC", + ".docx": "icon-DOC", + ".xls": "icon-XLS", + ".xlsx": "icon-XLS", + ".ppt": "icon-PPT", + ".pptx": "icon-PPT", + ".txt": "icon-TXT", + ".md": "icon-file-markdown-fill", + ".zip": "icon-wenjianyasuo", + ".rar": "icon-wenjianyasuo", + ".7z": "icon-wenjianyasuo", + ".tar": "icon-wenjianyasuo", + ".gz": "icon-wenjianyasuo", + ".js": "icon-JS", + ".ts": "icon-daimawenjia", + ".vue": "icon-daimawenjia", + ".html": "icon-HTML", + ".css": "icon-CSS", + ".py": "icon-daimawenjian", + ".java": "icon-daimawenjian", + ".json": "icon-JSON" + }; + if (ext && extMap[ext]) + return extMap[ext]; + if (mimeType.startsWith("image/")) + return "icon-wenjiantupian"; + if (mimeType.startsWith("video/")) + return "icon-wenjianshipin"; + if (mimeType.startsWith("audio/")) + return "icon-wenjianyinpin"; + if (mimeType.includes("spreadsheet") || mimeType.includes("excel")) + return "icon-XLS"; + if (mimeType.includes("document") || mimeType.includes("word")) + return "icon-DOC"; + if (mimeType.includes("presentation") || mimeType.includes("powerpoint")) + return "icon-PPT"; + if (mimeType.includes("pdf")) + return "icon-PDF"; + if (mimeType.includes("zip") || mimeType.includes("rar") || mimeType.includes("tar") || mimeType.includes("gzip")) + return "icon-wenjianyasuo"; + return "icon-qitawenjian"; + }; + const formatFileSize = (bytes) => { + if (!bytes) + return ""; + if (bytes < 1024) + return bytes + " B"; + if (bytes < 1024 * 1024) + return (bytes / 1024).toFixed(1) + " KB"; + return (bytes / (1024 * 1024)).toFixed(1) + " MB"; + }; + const currentFolderDisplayPath = vue.computed(() => { + if (currentFolderPath.value.length === 0) + return "根目录 (/)"; + return "/" + currentFolderPath.value.map((f) => f.name).join("/"); + }); + const personalFileCount = vue.computed(() => rawPersonalFileData.value.length); + const findFolderByPath = (dataList, targetPath) => { + for (const item of dataList) { + if (isFolder(item) && item.path === targetPath) { + return item.children || []; + } + } + return null; + }; + const loadCurrentFiles = () => { + const rawData = currentCategory.value === "user" ? rawPersonalFileData.value : rawTeamFileData.value; + if (currentFolderPath.value.length === 0) { + if (currentCategory.value === "user") { + personalFiles.value = rawData; + } else { + teamFiles.value = rawData; + } + } else { + const currentFolder = currentFolderPath.value[currentFolderPath.value.length - 1]; + const result = currentFolder.children || []; + if (currentCategory.value === "user") { + personalFiles.value = result; + } else { + teamFiles.value = result; + } + } + }; + const fetchFileList = async () => { + try { + userToken.value = getToken(); + const userInfo = await getUserInfo(userToken.value); + userId.value = userInfo._id; + workspaceId.value = uni.getStorageSync("workspace_id") || ""; + const personalData = await getCloudFileList(userToken.value, "user"); + rawPersonalFileData.value = personalData || []; + if (currentCategory.value === "user") { + personalFiles.value = personalData || []; + } + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:509", "获取文件列表失败:", error); + rawPersonalFileData.value = []; + personalFiles.value = []; + } + }; + const fetchTeamFileList = async (teamId) => { + try { + const teamData = await getCloudFileList(userToken.value, "team", "/", teamId); + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:519", "团队云端文件:", JSON.stringify(teamData)); + rawTeamFileData.value = teamData || []; + teamFiles.value = teamData || []; + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:523", "获取团队文件列表失败:", error); + rawTeamFileData.value = []; + teamFiles.value = []; + } + }; + const handleFileClick = (file) => { + if (isFolder(file)) { + currentFolderPath.value.push({ + path: file.path, + name: file.name, + children: file.children || [] + }); + navbarTitle.value = file.name; + loadCurrentFiles(); + } else { + handleDownload(file); + } + }; + const handleFileLongPress = (file) => { + if (isSelectFolder.value) { + const idx = selectFileList.value.indexOf(file.id); + if (idx !== -1) { + selectFileList.value.splice(idx, 1); + } else { + selectFileList.value.push(file.id); + } + return; + } + const menuItems = isFolder(file) ? ["重命名", "删除"] : ["下载", "重命名", "删除"]; + uni.showActionSheet({ + itemList: menuItems, + success: (res) => { + if (isFolder(file)) { + switch (res.tapIndex) { + case 0: + handleRename(file); + break; + case 1: + handleDeleteFile(file); + break; + } + } else { + switch (res.tapIndex) { + case 0: + handleDownload(file); + break; + case 1: + handleRename(file); + break; + case 2: + handleDeleteFile(file); + break; + } + } + } + }); + }; + const handleDownload = async (file) => { + if (isFolder(file)) { + uni.showToast({ title: "暂不支持下载目录", icon: "none" }); + return; + } + try { + uni.showLoading({ title: "获取下载链接..." }); + const downloadUrl = await getCloudFileUrl(userToken.value, file.id); + uni.hideLoading(); + if (!downloadUrl) { + uni.showToast({ title: "获取下载链接失败", icon: "error" }); + return; + } + uni.showLoading({ title: "下载中..." }); + uni.downloadFile({ + url: downloadUrl, + success: (downloadRes) => { + uni.hideLoading(); + if (downloadRes.statusCode === 200) { + const tempPath = downloadRes.tempFilePath; + saveFileToYxd(file.name, tempPath); + } else { + uni.showToast({ title: "下载失败", icon: "error" }); + } + }, + fail: () => { + uni.hideLoading(); + uni.showToast({ title: "下载失败,请重试", icon: "error" }); + } + }); + } catch (error) { + uni.hideLoading(); + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:614", "下载失败:", 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); + }, () => { + plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => { + fs.root.getDirectory("yxd", { create: true }, (dirEntry) => { + copyFileToDir(tempPath, targetPath, fileName); + }, (err) => { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:638", "创建 yxd 目录失败:", err); + uni.showToast({ title: "创建目录失败", icon: "error" }); + }); + }); + }); + } 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); + }); + }; + 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/CloudDatabase/CloudDatabase.vue:720", "打开文件失败:", err); + openFileWithMenu(filePath); + } + }); + }; + const openFileWithMenu = (filePath) => { + plus.runtime.openFile(filePath, {}, (e2) => { + formatAppLog("log", "at pages/CloudDatabase/CloudDatabase.vue:732", "文件打开成功"); + }); + }; + const handleRename = (file) => { + uni.showModal({ + title: "重命名", + content: "请输入新名称", + editable: true, + placeholderText: file.name, + success: (res) => { + if (res.confirm && res.content) { + uni.showToast({ title: "重命名成功", icon: "success" }); + refreshCurrentFileList(); + } + } + }); + }; + const handleDeleteFile = (file) => { + uni.showModal({ + title: "提示", + content: `确定要删除"${file.name}"吗?`, + success: async (res) => { + if (res.confirm) { + 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" }); + refreshCurrentFileList(); + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:779", "删除失败:", error); + uni.showToast({ title: "删除失败,请重试", icon: "error" }); + } + } + } + }); + }; + const refreshCurrentFileList = async () => { + if (currentCategory.value === "user") { + await fetchFileList(); + } else { + await fetchTeamFileList(currentTeamId.value); + } + }; + const showNewFolder = vue.ref(false); + const newFolderName = vue.ref(""); + const openNewFolderModal = () => { + showNewFolder.value = true; + newFolderName.value = ""; + }; + const closeNewFolderModal = () => { + showNewFolder.value = false; + newFolderName.value = ""; + }; + const confirmCreateFolder = async () => { + const name2 = newFolderName.value.trim(); + if (!name2) { + uni.showToast({ title: "请输入目录名称", icon: "none" }); + return; + } + try { + if (workspaceId.value) { + const prefix = currentFolderDisplayPath.value === "根目录 (/)" ? "/" : currentFolderDisplayPath.value; + const dirPath = prefix + name2; + await createWorkspaceFolder(userToken.value, workspaceId.value, dirPath); + } + uni.showToast({ title: "创建成功", icon: "success" }); + closeNewFolderModal(); + refreshCurrentFileList(); + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:826", "创建文件夹失败:", 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 } + ]); + const teamTables = vue.ref([ + { 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(""); + const newTableDesc = vue.ref(""); + const openNewTableModal = () => { + showNewTable.value = true; + newTableName.value = ""; + newTableDesc.value = ""; + }; + const closeNewTableModal = () => { + showNewTable.value = false; + newTableName.value = ""; + newTableDesc.value = ""; + }; + const confirmCreateTable = () => { + const name2 = newTableName.value.trim(); + if (!name2) { + uni.showToast({ title: "请输入表名称", icon: "none" }); + return; + } + const newTable = { + id: Date.now().toString(), + name: name2, + desc: newTableDesc.value.trim() || "无描述", + rowCount: 0 + }; + if (currentCategory.value === "user") { + personalTables.value.push(newTable); + } else { + teamTables.value.push(newTable); + } + uni.showToast({ title: "创建成功", icon: "success" }); + closeNewTableModal(); + }; + const handleTableClick = (table) => { + 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 fetchTeamList = async () => { + try { + if (!userId.value) { + const token = getToken(); + const userInfo = await getUserInfo(token); + userId.value = userInfo._id; + } + const groups = await getGroup(userId.value); + teamGroups.value = groups || []; + } catch (error) { + formatAppLog("error", "at pages/CloudDatabase/CloudDatabase.vue:898", "获取团队列表失败:", error); + teamGroups.value = []; + } + }; + const selectTeam = async (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 { + 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 closeTeamManage = () => { + showTeamManage.value = false; + inviteKeyword.value = ""; + }; + 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" }); + return; + } + uni.showToast({ title: "邀请已发送", icon: "success" }); + inviteKeyword.value = ""; + }; + 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() { + return getToken; + }, get getUserInfo() { + return getUserInfo; + }, get getCloudFileList() { + return getCloudFileList; + }, get getCloudFileUrl() { + return getCloudFileUrl; + }, get createWorkspaceFolder() { + return createWorkspaceFolder; + }, get daleteWorkspace() { + return daleteWorkspace; + }, get getWorkspaceFileURL() { + return getWorkspaceFileURL; + }, get getGroup() { + return getGroup; + } }; + Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true }); + return __returned__; + } + }; + function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { + const _component_uni_icons = resolveEasycom(vue.resolveDynamicComponent("uni-icons"), __easycom_0); + return vue.openBlock(), vue.createElementBlock( + vue.Fragment, + null, + [ + vue.createElementVNode("view", { class: "status-bar" }), + $setup.showTeamManage ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "popup-overlay", + onClick: $setup.closeTeamManage + }, [ + vue.createElementVNode("view", { + class: "popup-card", + onClick: _cache[1] || (_cache[1] = vue.withModifiers(() => { + }, ["stop"])) + }, [ + vue.createElementVNode("view", { + class: "close-popup-card", + onClick: $setup.closeTeamManage + }, [ + vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) + ]), + vue.createElementVNode("view", { class: "popup-title" }, "团队管理"), + vue.createElementVNode("scroll-view", { + class: "team-manage-body", + "scroll-y": "" + }, [ + $setup.currentTeamMembers.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "folder-null" + }, "暂无团队成员")) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "member-list" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.currentTeamMembers, (member) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "member-item", + key: member.id || member.receiver + }, [ + vue.createElementVNode("view", { class: "member-avatar" }, [ + member.avatar ? (vue.openBlock(), vue.createElementBlock("image", { + key: 0, + src: member.avatar, + mode: "aspectFill" + }, null, 8, ["src"])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "default-avatar" + }, [ + vue.createVNode(_component_uni_icons, { + type: "person-filled", + size: "60rpx", + color: "#ffffff" + }) + ])) + ]), + vue.createElementVNode("view", { class: "member-info" }, [ + vue.createElementVNode( + "view", + { class: "member-name" }, + vue.toDisplayString(member.friendNickName || member.username || member.name), + 1 + /* TEXT */ + ), + vue.createElementVNode( + "view", + { class: "member-label" }, + vue.toDisplayString(member.email || member.sessionId || ""), + 1 + /* TEXT */ + ) + ]), + vue.createElementVNode("view", { class: "member-actions" }, [ + member.role === "owner" ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + 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 set-admin", + onClick: ($event) => $setup.setTeamAdmin(member) + }, "设为管理", 8, ["onClick"]), + vue.createElementVNode("view", { + class: "member-action-btn remove-member", + onClick: ($event) => $setup.removeTeamMember(member) + }, "移除", 8, ["onClick"]) + ])) + ]) + ]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) + ]), + vue.createElementVNode("view", { class: "invite-section" }, [ + vue.createElementVNode("view", { class: "invite-input-wrapper" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + class: "invite-input", + placeholder: "输入用户ID或名称邀请", + "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $setup.inviteKeyword = $event) + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.inviteKeyword] + ]), + vue.createElementVNode("view", { + class: "invite-btn text-btn", + onClick: $setup.inviteTeamMember + }, "邀请") + ]) + ]) + ]) + ])) : vue.createCommentVNode("v-if", true), + $setup.showNewFolder ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "popup-overlay", + onClick: $setup.closeNewFolderModal + }, [ + vue.createElementVNode("view", { + class: "popup-card", + onClick: _cache[3] || (_cache[3] = vue.withModifiers(() => { + }, ["stop"])) + }, [ + vue.createElementVNode("view", { + class: "close-popup-card", + onClick: $setup.closeNewFolderModal + }, [ + vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) + ]), + vue.createElementVNode( + "view", + { class: "popup-title" }, + "新建" + vue.toDisplayString($setup.currentCategory === "user" ? "个人" : "团队") + "目录", + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "new-folder-name" }, "目录名称"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => $setup.newFolderName = $event), + type: "text", + placeholder: "输入目录名称" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.newFolderName] + ]) + ]), + vue.createElementVNode("view", { class: "nf-path-label" }, "当前路径"), + vue.createElementVNode( + "view", + { class: "nf-path-display" }, + vue.toDisplayString($setup.currentFolderDisplayPath), + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "option-wrapper" }, [ + vue.createElementVNode("view", { + class: "opt-btn opt-cancel", + onClick: $setup.closeNewFolderModal + }, "取消"), + vue.createElementVNode("view", { + class: "opt-btn opt-confirm", + onClick: $setup.confirmCreateFolder + }, "确认") + ]) + ]) + ])) : vue.createCommentVNode("v-if", true), + $setup.showNewTable ? (vue.openBlock(), vue.createElementBlock("view", { + key: 2, + class: "popup-overlay", + onClick: $setup.closeNewTableModal + }, [ + vue.createElementVNode("view", { + class: "popup-card", + onClick: _cache[6] || (_cache[6] = vue.withModifiers(() => { + }, ["stop"])) + }, [ + vue.createElementVNode("view", { + class: "close-popup-card", + onClick: $setup.closeNewTableModal + }, [ + vue.createElementVNode("view", { class: "iconfont icon-quxiao" }) + ]), + vue.createElementVNode( + "view", + { class: "popup-title" }, + "新建" + vue.toDisplayString($setup.currentCategory === "user" ? "个人" : "团队") + "数据表", + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "new-folder-name" }, "表名称"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => $setup.newTableName = $event), + type: "text", + placeholder: "输入表名称,如:users" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.newTableName] + ]) + ]), + vue.createElementVNode("view", { class: "new-folder-name" }, "描述"), + vue.createElementVNode("view", { class: "create-folder-name" }, [ + vue.withDirectives(vue.createElementVNode( + "input", + { + "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => $setup.newTableDesc = $event), + type: "text", + placeholder: "输入表描述(可选)" + }, + null, + 512 + /* NEED_PATCH */ + ), [ + [vue.vModelText, $setup.newTableDesc] + ]) + ]), + vue.createElementVNode("view", { class: "option-wrapper" }, [ + vue.createElementVNode("view", { + class: "opt-btn opt-cancel", + onClick: $setup.closeNewTableModal + }, "取消"), + vue.createElementVNode("view", { + class: "opt-btn opt-confirm", + onClick: $setup.confirmCreateTable + }, "确认") + ]) + ]) + ])) : vue.createCommentVNode("v-if", true), + vue.createElementVNode("view", { class: "cloud-db-container page-container" }, [ + vue.createElementVNode("view", { class: "cloud-db-header" }, [ + vue.createElementVNode("view", { class: "custom-navbar" }, [ + vue.createElementVNode("view", { + class: "navbar-left", + onClick: $setup.handleBackOrUp + }, [ + vue.createElementVNode("view", { class: "iconfont icon-fanhui custom-navbar-icon" }), + $setup.currentFolderPath.length > 0 ? (vue.openBlock(), vue.createElementBlock( + "view", + { + key: 0, + class: "navbar-before-title" + }, + vue.toDisplayString($setup.parentFolderName), + 1 + /* TEXT */ + )) : vue.createCommentVNode("v-if", true) + ]), + vue.createElementVNode( + "view", + { class: "navbar-title" }, + vue.toDisplayString($setup.navbarTitle), + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "navbar-right" }, [ + $setup.isSelectFolder ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "navbar-right-text", + onClick: $setup.handleSelectFolder + }, "完成")) : (vue.openBlock(), vue.createElementBlock( + "view", + { + key: 1, + class: vue.normalizeClass(["iconfont icon-gengduo", $setup.isMenuOpen ? "menu-open" : "custom-navbar-icon"]), + onClick: $setup.handleMenu + }, + null, + 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")) + }, + " 个人 ", + 2 + /* CLASS */ + ), + vue.createElementVNode( + "view", + { + class: vue.normalizeClass(["category-tab", { active: $setup.currentCategory === "team" }]), + onClick: _cache[10] || (_cache[10] = ($event) => $setup.switchCategory("team")) + }, + " 团队 ", + 2 + /* CLASS */ + ) + ]) + ]), + vue.createElementVNode("scroll-view", { + class: "cloud-db-content", + "scroll-y": "" + }, [ + $setup.currentCategory === "user" ? (vue.openBlock(), vue.createElementBlock( + vue.Fragment, + { key: 0 }, + [ + vue.createElementVNode("view", { class: "section-block" }, [ + vue.createElementVNode("view", { class: "section-header" }, [ + vue.createElementVNode("view", { class: "section-title" }, [ + vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), + vue.createElementVNode("text", null, "云端文件"), + vue.createElementVNode( + "text", + { class: "file-count" }, + vue.toDisplayString($setup.personalFileCount > 0 ? "(" + $setup.personalFileCount + ")" : ""), + 1 + /* TEXT */ + ) + ]), + vue.createElementVNode("view", { class: "section-actions" }, [ + vue.createElementVNode("view", { + class: "action-btn", + onClick: $setup.openNewFolderModal + }, [ + vue.createVNode(_component_uni_icons, { + type: "plus", + size: "16" + }), + vue.createElementVNode("text", null, "新建目录") + ]) + ]) + ]), + vue.createElementVNode("view", { class: "section-body" }, [ + $setup.personalFiles.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "empty-tip" + }, [ + vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), + vue.createElementVNode("text", null, "暂无云端文件") + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "file-grid" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.personalFiles, (file) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "file-item", + key: file.id, + onClick: ($event) => $setup.handleFileClick(file), + onLongpress: ($event) => $setup.handleFileLongPress(file) + }, [ + vue.createElementVNode( + "view", + { + class: vue.normalizeClass(["file-icon", $setup.isFolder(file) ? "is-directory" : "is-file"]) + }, + [ + vue.createElementVNode( + "view", + { + class: vue.normalizeClass(["iconfont", $setup.getFileIcon(file)]) + }, + null, + 2 + /* CLASS */ + ) + ], + 2 + /* CLASS */ + ), + vue.createElementVNode( + "view", + { class: "file-name" }, + vue.toDisplayString(file.name), + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "file-meta" }, [ + vue.createElementVNode( + "text", + { class: "file-type-tag" }, + vue.toDisplayString($setup.isFolder(file) ? "目录" : "文件"), + 1 + /* TEXT */ + ), + file.size ? (vue.openBlock(), vue.createElementBlock( + "text", + { + key: 0, + class: "file-size" + }, + vue.toDisplayString($setup.formatFileSize(file.size)), + 1 + /* TEXT */ + )) : vue.createCommentVNode("v-if", true) + ]) + ], 40, ["onClick", "onLongpress"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) + ]) + ]), + vue.createElementVNode("view", { class: "section-divider" }), + vue.createElementVNode("view", { class: "section-block" }, [ + vue.createElementVNode("view", { class: "section-header" }, [ + vue.createElementVNode("view", { class: "section-title" }, [ + vue.createElementVNode("view", { class: "iconfont icon-shujuku" }), + vue.createElementVNode("text", null, "云端数据库") + ]), + vue.createElementVNode("view", { class: "section-actions" }, [ + vue.createElementVNode("view", { + class: "action-btn", + onClick: $setup.openNewTableModal + }, [ + vue.createVNode(_component_uni_icons, { + type: "plus", + size: "16" + }), + vue.createElementVNode("text", null, "新建表") + ]) + ]) + ]), + vue.createElementVNode("view", { class: "section-body" }, [ + $setup.personalTables.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "empty-tip" + }, [ + vue.createElementVNode("view", { class: "iconfont icon-shujuku" }), + vue.createElementVNode("text", null, "暂无数据表") + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "table-list" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.personalTables, (table) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "table-item", + key: table.id, + onClick: ($event) => $setup.handleTableClick(table) + }, [ + vue.createElementVNode("view", { class: "table-icon" }, [ + vue.createVNode(_component_uni_icons, { + type: "compose", + size: "22", + color: "#3b86ff" + }) + ]), + vue.createElementVNode("view", { class: "table-info" }, [ + vue.createElementVNode( + "view", + { class: "table-name" }, + vue.toDisplayString(table.name), + 1 + /* TEXT */ + ), + vue.createElementVNode( + "view", + { class: "table-desc" }, + vue.toDisplayString(table.desc || "无描述"), + 1 + /* TEXT */ + ) + ]), + vue.createElementVNode("view", { class: "table-meta" }, [ + vue.createElementVNode( + "text", + { class: "table-rows" }, + vue.toDisplayString(table.rowCount || 0) + " 条记录", + 1 + /* TEXT */ + ), + vue.createVNode(_component_uni_icons, { + type: "right", + size: "14", + color: "#999" + }) + ]) + ], 8, ["onClick"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) + ]) + ]) + ], + 64 + /* STABLE_FRAGMENT */ + )) : vue.createCommentVNode("v-if", true), + $setup.currentCategory === "team" ? (vue.openBlock(), vue.createElementBlock( + vue.Fragment, + { key: 1 }, + [ + vue.createElementVNode("view", { + class: "section-block team-manage-block", + onClick: $setup.openTeamManage + }, [ + vue.createElementVNode("view", { class: "section-header" }, [ + vue.createElementVNode("view", { class: "section-title" }, [ + vue.createElementVNode("view", { class: "iconfont icon-qunliao" }), + vue.createElementVNode("text", null, "团队管理") + ]), + vue.createElementVNode("view", { class: "section-actions" }, [ + vue.createElementVNode( + "text", + { class: "team-count" }, + vue.toDisplayString($setup.teamGroups.length) + " 个团队", + 1 + /* TEXT */ + ), + vue.createVNode(_component_uni_icons, { + type: "right", + size: "14", + color: "#999" + }) + ]) + ]) + ]), + vue.createElementVNode("view", { class: "section-divider" }), + $setup.teamGroups.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "team-selector" + }, [ + vue.createElementVNode("scroll-view", { + "scroll-x": "", + class: "team-scroll" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.teamGroups, (team) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: vue.normalizeClass(["team-chip", { active: $setup.currentTeamId === team.id }]), + key: team.id, + onClick: ($event) => $setup.selectTeam(team.id) + }, vue.toDisplayString(team.name), 11, ["onClick"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ]) + ])) : vue.createCommentVNode("v-if", true), + !$setup.currentTeamId && $setup.teamGroups.length > 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "empty-tip select-team-tip" + }, [ + vue.createElementVNode("view", { class: "iconfont icon-qunliao" }), + vue.createElementVNode("text", null, "请选择一个团队") + ])) : vue.createCommentVNode("v-if", true), + $setup.currentTeamId ? (vue.openBlock(), vue.createElementBlock("view", { + key: 2, + class: "section-block" + }, [ + vue.createElementVNode("view", { class: "section-header" }, [ + vue.createElementVNode("view", { class: "section-title" }, [ + vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), + vue.createElementVNode("text", null, "团队云端文件") + ]), + vue.createElementVNode("view", { class: "section-actions" }, [ + vue.createElementVNode("view", { + class: "action-btn", + onClick: $setup.openNewFolderModal + }, [ + vue.createVNode(_component_uni_icons, { + type: "plus", + size: "16" + }), + vue.createElementVNode("text", null, "新建目录") + ]) + ]) + ]), + vue.createElementVNode("view", { class: "section-body" }, [ + $setup.teamFiles.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "empty-tip" + }, [ + vue.createElementVNode("view", { class: "iconfont icon-wenjianjia" }), + vue.createElementVNode("text", null, "暂无团队云端文件") + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "file-grid" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.teamFiles, (file) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "file-item", + key: file.id, + onClick: ($event) => $setup.handleFileClick(file), + onLongpress: ($event) => $setup.handleFileLongPress(file) + }, [ + vue.createElementVNode( + "view", + { + class: vue.normalizeClass(["file-icon", $setup.isFolder(file) ? "is-directory" : "is-file"]) + }, + [ + vue.createElementVNode( + "view", + { + class: vue.normalizeClass(["iconfont", $setup.getFileIcon(file)]) + }, + null, + 2 + /* CLASS */ + ) + ], + 2 + /* CLASS */ + ), + vue.createElementVNode( + "view", + { class: "file-name" }, + vue.toDisplayString(file.name), + 1 + /* TEXT */ + ), + vue.createElementVNode("view", { class: "file-meta" }, [ + vue.createElementVNode( + "text", + { class: "file-type-tag" }, + vue.toDisplayString($setup.isFolder(file) ? "目录" : "文件"), + 1 + /* TEXT */ + ), + file.size ? (vue.openBlock(), vue.createElementBlock( + "text", + { + key: 0, + class: "file-size" + }, + vue.toDisplayString($setup.formatFileSize(file.size)), + 1 + /* TEXT */ + )) : vue.createCommentVNode("v-if", true) + ]) + ], 40, ["onClick", "onLongpress"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) + ]) + ])) : vue.createCommentVNode("v-if", true), + $setup.currentTeamId ? (vue.openBlock(), vue.createElementBlock("view", { + key: 3, + class: "section-divider" + })) : vue.createCommentVNode("v-if", true), + $setup.currentTeamId ? (vue.openBlock(), vue.createElementBlock("view", { + key: 4, + class: "section-block" + }, [ + vue.createElementVNode("view", { class: "section-header" }, [ + vue.createElementVNode("view", { class: "section-title" }, [ + vue.createElementVNode("view", { class: "iconfont icon-shujuku" }), + vue.createElementVNode("text", null, "团队云端数据库") + ]), + vue.createElementVNode("view", { class: "section-actions" }, [ + vue.createElementVNode("view", { + class: "action-btn", + onClick: $setup.openNewTableModal + }, [ + vue.createVNode(_component_uni_icons, { + type: "plus", + size: "16" + }), + vue.createElementVNode("text", null, "新建表") + ]) + ]) + ]), + vue.createElementVNode("view", { class: "section-body" }, [ + $setup.teamTables.length === 0 ? (vue.openBlock(), vue.createElementBlock("view", { + key: 0, + class: "empty-tip" + }, [ + vue.createElementVNode("view", { class: "iconfont icon-shujuku" }), + vue.createElementVNode("text", null, "暂无团队数据表") + ])) : (vue.openBlock(), vue.createElementBlock("view", { + key: 1, + class: "table-list" + }, [ + (vue.openBlock(true), vue.createElementBlock( + vue.Fragment, + null, + vue.renderList($setup.teamTables, (table) => { + return vue.openBlock(), vue.createElementBlock("view", { + class: "table-item", + key: table.id, + onClick: ($event) => $setup.handleTableClick(table) + }, [ + vue.createElementVNode("view", { class: "table-icon" }, [ + vue.createVNode(_component_uni_icons, { + type: "compose", + size: "22", + color: "#3b86ff" + }) + ]), + vue.createElementVNode("view", { class: "table-info" }, [ + vue.createElementVNode( + "view", + { class: "table-name" }, + vue.toDisplayString(table.name), + 1 + /* TEXT */ + ), + vue.createElementVNode( + "view", + { class: "table-desc" }, + vue.toDisplayString(table.desc || "无描述"), + 1 + /* TEXT */ + ) + ]), + vue.createElementVNode("view", { class: "table-meta" }, [ + vue.createElementVNode( + "text", + { class: "table-rows" }, + vue.toDisplayString(table.rowCount || 0) + " 条记录", + 1 + /* TEXT */ + ), + vue.createVNode(_component_uni_icons, { + type: "right", + size: "14", + color: "#999" + }) + ]) + ], 8, ["onClick"]); + }), + 128 + /* KEYED_FRAGMENT */ + )) + ])) + ]) + ])) : vue.createCommentVNode("v-if", true) + ], + 64 + /* STABLE_FRAGMENT */ + )) : vue.createCommentVNode("v-if", true) + ]) + ]) + ], + 64 + /* STABLE_FRAGMENT */ + ); + } + const PagesCloudDatabaseCloudDatabase = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render], ["__scopeId", "data-v-51006ffb"], ["__file", "D:/Projects/uniapp/app-test/test1/pages/CloudDatabase/CloudDatabase.vue"]]); __definePage("pages/Login/Login", PagesLoginLogin); __definePage("pages/Chat/Chat", PagesChatChat); __definePage("pages/WorkSpace/WorkSpace", PagesWorkSpaceWorkSpace); @@ -8561,6 +10310,7 @@ This will fail in production.`); __definePage("pages/WorkSpace/TemplateSpace/TemplateSpace", PagesWorkSpaceTemplateSpaceTemplateSpace); __definePage("pages/text/text", PagesTextText); __definePage("pages/text/text2", PagesTextText2); + __definePage("pages/CloudDatabase/CloudDatabase", PagesCloudDatabaseCloudDatabase); const _sfc_main = { onLaunch: function() { formatAppLog("log", "at App.vue:4", "App Launch"); diff --git a/unpackage/dist/dev/app-plus/app.css b/unpackage/dist/dev/app-plus/app.css index d6da9e5..b82ace9 100644 --- a/unpackage/dist/dev/app-plus/app.css +++ b/unpackage/dist/dev/app-plus/app.css @@ -28,9 +28,9 @@ /*每个页面公共css */ @font-face { font-family: "iconfont"; /* Project id 4890805 */ - src: url('static/iconfont/iconfont.woff2?t=1780384681439') format('woff2'), - url('static/iconfont/iconfont.woff?t=1780384681439') format('woff'), - url('static/iconfont/iconfont.ttf?t=1780384681439') format('truetype'); + src: url('static/iconfont/iconfont.woff2?t=1782200893170') format('woff2'), + url('static/iconfont/iconfont.woff?t=1782200893170') format('woff'), + url('static/iconfont/iconfont.ttf?t=1782200893170') format('truetype'); } .iconfont { font-family: "iconfont" !important; @@ -39,6 +39,9 @@ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } +.icon-cloud:before { + content: "\e988"; +} .icon-qitawenjian:before { content: "\e7b6"; } diff --git a/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css b/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css new file mode 100644 index 0000000..b6e293a --- /dev/null +++ b/unpackage/dist/dev/app-plus/pages/CloudDatabase/CloudDatabase.css @@ -0,0 +1,1116 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ +/* 颜色变量 */ +/* 行为相关颜色 */ +/* 文字基本颜色 */ +/* 背景颜色 */ +/* 边框颜色 */ +/* 尺寸变量 */ +/* 文字尺寸 */ +/* 图片尺寸 */ +/* Border Radius */ +/* 水平间距 */ +/* 垂直间距 */ +/* 透明度 */ +/* 文章场景相关 */ +.uniui-cart-filled[data-v-d31e1c47]:before { + content: "\e6d0"; +} +.uniui-gift-filled[data-v-d31e1c47]:before { + content: "\e6c4"; +} +.uniui-color[data-v-d31e1c47]:before { + content: "\e6cf"; +} +.uniui-wallet[data-v-d31e1c47]:before { + content: "\e6b1"; +} +.uniui-settings-filled[data-v-d31e1c47]:before { + content: "\e6ce"; +} +.uniui-auth-filled[data-v-d31e1c47]:before { + content: "\e6cc"; +} +.uniui-shop-filled[data-v-d31e1c47]:before { + content: "\e6cd"; +} +.uniui-staff-filled[data-v-d31e1c47]:before { + content: "\e6cb"; +} +.uniui-vip-filled[data-v-d31e1c47]:before { + content: "\e6c6"; +} +.uniui-plus-filled[data-v-d31e1c47]:before { + content: "\e6c7"; +} +.uniui-folder-add-filled[data-v-d31e1c47]:before { + content: "\e6c8"; +} +.uniui-color-filled[data-v-d31e1c47]:before { + content: "\e6c9"; +} +.uniui-tune-filled[data-v-d31e1c47]:before { + content: "\e6ca"; +} +.uniui-calendar-filled[data-v-d31e1c47]:before { + content: "\e6c0"; +} +.uniui-notification-filled[data-v-d31e1c47]:before { + content: "\e6c1"; +} +.uniui-wallet-filled[data-v-d31e1c47]:before { + content: "\e6c2"; +} +.uniui-medal-filled[data-v-d31e1c47]:before { + content: "\e6c3"; +} +.uniui-fire-filled[data-v-d31e1c47]:before { + content: "\e6c5"; +} +.uniui-refreshempty[data-v-d31e1c47]:before { + content: "\e6bf"; +} +.uniui-location-filled[data-v-d31e1c47]:before { + content: "\e6af"; +} +.uniui-person-filled[data-v-d31e1c47]:before { + content: "\e69d"; +} +.uniui-personadd-filled[data-v-d31e1c47]:before { + content: "\e698"; +} +.uniui-arrowthinleft[data-v-d31e1c47]:before { + content: "\e6d2"; +} +.uniui-arrowthinup[data-v-d31e1c47]:before { + content: "\e6d3"; +} +.uniui-arrowthindown[data-v-d31e1c47]:before { + content: "\e6d4"; +} +.uniui-back[data-v-d31e1c47]:before { + content: "\e6b9"; +} +.uniui-forward[data-v-d31e1c47]:before { + content: "\e6ba"; +} +.uniui-arrow-right[data-v-d31e1c47]:before { + content: "\e6bb"; +} +.uniui-arrow-left[data-v-d31e1c47]:before { + content: "\e6bc"; +} +.uniui-arrow-up[data-v-d31e1c47]:before { + content: "\e6bd"; +} +.uniui-arrow-down[data-v-d31e1c47]:before { + content: "\e6be"; +} +.uniui-arrowthinright[data-v-d31e1c47]:before { + content: "\e6d1"; +} +.uniui-down[data-v-d31e1c47]:before { + content: "\e6b8"; +} +.uniui-bottom[data-v-d31e1c47]:before { + content: "\e6b8"; +} +.uniui-arrowright[data-v-d31e1c47]:before { + content: "\e6d5"; +} +.uniui-right[data-v-d31e1c47]:before { + content: "\e6b5"; +} +.uniui-up[data-v-d31e1c47]:before { + content: "\e6b6"; +} +.uniui-top[data-v-d31e1c47]:before { + content: "\e6b6"; +} +.uniui-left[data-v-d31e1c47]:before { + content: "\e6b7"; +} +.uniui-arrowup[data-v-d31e1c47]:before { + content: "\e6d6"; +} +.uniui-eye[data-v-d31e1c47]:before { + content: "\e651"; +} +.uniui-eye-filled[data-v-d31e1c47]:before { + content: "\e66a"; +} +.uniui-eye-slash[data-v-d31e1c47]:before { + content: "\e6b3"; +} +.uniui-eye-slash-filled[data-v-d31e1c47]:before { + content: "\e6b4"; +} +.uniui-info-filled[data-v-d31e1c47]:before { + content: "\e649"; +} +.uniui-reload[data-v-d31e1c47]:before { + content: "\e6b2"; +} +.uniui-micoff-filled[data-v-d31e1c47]:before { + content: "\e6b0"; +} +.uniui-map-pin-ellipse[data-v-d31e1c47]:before { + content: "\e6ac"; +} +.uniui-map-pin[data-v-d31e1c47]:before { + content: "\e6ad"; +} +.uniui-location[data-v-d31e1c47]:before { + content: "\e6ae"; +} +.uniui-starhalf[data-v-d31e1c47]:before { + content: "\e683"; +} +.uniui-star[data-v-d31e1c47]:before { + content: "\e688"; +} +.uniui-star-filled[data-v-d31e1c47]:before { + content: "\e68f"; +} +.uniui-calendar[data-v-d31e1c47]:before { + content: "\e6a0"; +} +.uniui-fire[data-v-d31e1c47]:before { + content: "\e6a1"; +} +.uniui-medal[data-v-d31e1c47]:before { + content: "\e6a2"; +} +.uniui-font[data-v-d31e1c47]:before { + content: "\e6a3"; +} +.uniui-gift[data-v-d31e1c47]:before { + content: "\e6a4"; +} +.uniui-link[data-v-d31e1c47]:before { + content: "\e6a5"; +} +.uniui-notification[data-v-d31e1c47]:before { + content: "\e6a6"; +} +.uniui-staff[data-v-d31e1c47]:before { + content: "\e6a7"; +} +.uniui-vip[data-v-d31e1c47]:before { + content: "\e6a8"; +} +.uniui-folder-add[data-v-d31e1c47]:before { + content: "\e6a9"; +} +.uniui-tune[data-v-d31e1c47]:before { + content: "\e6aa"; +} +.uniui-auth[data-v-d31e1c47]:before { + content: "\e6ab"; +} +.uniui-person[data-v-d31e1c47]:before { + content: "\e699"; +} +.uniui-email-filled[data-v-d31e1c47]:before { + content: "\e69a"; +} +.uniui-phone-filled[data-v-d31e1c47]:before { + content: "\e69b"; +} +.uniui-phone[data-v-d31e1c47]:before { + content: "\e69c"; +} +.uniui-email[data-v-d31e1c47]:before { + content: "\e69e"; +} +.uniui-personadd[data-v-d31e1c47]:before { + content: "\e69f"; +} +.uniui-chatboxes-filled[data-v-d31e1c47]:before { + content: "\e692"; +} +.uniui-contact[data-v-d31e1c47]:before { + content: "\e693"; +} +.uniui-chatbubble-filled[data-v-d31e1c47]:before { + content: "\e694"; +} +.uniui-contact-filled[data-v-d31e1c47]:before { + content: "\e695"; +} +.uniui-chatboxes[data-v-d31e1c47]:before { + content: "\e696"; +} +.uniui-chatbubble[data-v-d31e1c47]:before { + content: "\e697"; +} +.uniui-upload-filled[data-v-d31e1c47]:before { + content: "\e68e"; +} +.uniui-upload[data-v-d31e1c47]:before { + content: "\e690"; +} +.uniui-weixin[data-v-d31e1c47]:before { + content: "\e691"; +} +.uniui-compose[data-v-d31e1c47]:before { + content: "\e67f"; +} +.uniui-qq[data-v-d31e1c47]:before { + content: "\e680"; +} +.uniui-download-filled[data-v-d31e1c47]:before { + content: "\e681"; +} +.uniui-pyq[data-v-d31e1c47]:before { + content: "\e682"; +} +.uniui-sound[data-v-d31e1c47]:before { + content: "\e684"; +} +.uniui-trash-filled[data-v-d31e1c47]:before { + content: "\e685"; +} +.uniui-sound-filled[data-v-d31e1c47]:before { + content: "\e686"; +} +.uniui-trash[data-v-d31e1c47]:before { + content: "\e687"; +} +.uniui-videocam-filled[data-v-d31e1c47]:before { + content: "\e689"; +} +.uniui-spinner-cycle[data-v-d31e1c47]:before { + content: "\e68a"; +} +.uniui-weibo[data-v-d31e1c47]:before { + content: "\e68b"; +} +.uniui-videocam[data-v-d31e1c47]:before { + content: "\e68c"; +} +.uniui-download[data-v-d31e1c47]:before { + content: "\e68d"; +} +.uniui-help[data-v-d31e1c47]:before { + content: "\e679"; +} +.uniui-navigate-filled[data-v-d31e1c47]:before { + content: "\e67a"; +} +.uniui-plusempty[data-v-d31e1c47]:before { + content: "\e67b"; +} +.uniui-smallcircle[data-v-d31e1c47]:before { + content: "\e67c"; +} +.uniui-minus-filled[data-v-d31e1c47]:before { + content: "\e67d"; +} +.uniui-micoff[data-v-d31e1c47]:before { + content: "\e67e"; +} +.uniui-closeempty[data-v-d31e1c47]:before { + content: "\e66c"; +} +.uniui-clear[data-v-d31e1c47]:before { + content: "\e66d"; +} +.uniui-navigate[data-v-d31e1c47]:before { + content: "\e66e"; +} +.uniui-minus[data-v-d31e1c47]:before { + content: "\e66f"; +} +.uniui-image[data-v-d31e1c47]:before { + content: "\e670"; +} +.uniui-mic[data-v-d31e1c47]:before { + content: "\e671"; +} +.uniui-paperplane[data-v-d31e1c47]:before { + content: "\e672"; +} +.uniui-close[data-v-d31e1c47]:before { + content: "\e673"; +} +.uniui-help-filled[data-v-d31e1c47]:before { + content: "\e674"; +} +.uniui-paperplane-filled[data-v-d31e1c47]:before { + content: "\e675"; +} +.uniui-plus[data-v-d31e1c47]:before { + content: "\e676"; +} +.uniui-mic-filled[data-v-d31e1c47]:before { + content: "\e677"; +} +.uniui-image-filled[data-v-d31e1c47]:before { + content: "\e678"; +} +.uniui-locked-filled[data-v-d31e1c47]:before { + content: "\e668"; +} +.uniui-info[data-v-d31e1c47]:before { + content: "\e669"; +} +.uniui-locked[data-v-d31e1c47]:before { + content: "\e66b"; +} +.uniui-camera-filled[data-v-d31e1c47]:before { + content: "\e658"; +} +.uniui-chat-filled[data-v-d31e1c47]:before { + content: "\e659"; +} +.uniui-camera[data-v-d31e1c47]:before { + content: "\e65a"; +} +.uniui-circle[data-v-d31e1c47]:before { + content: "\e65b"; +} +.uniui-checkmarkempty[data-v-d31e1c47]:before { + content: "\e65c"; +} +.uniui-chat[data-v-d31e1c47]:before { + content: "\e65d"; +} +.uniui-circle-filled[data-v-d31e1c47]:before { + content: "\e65e"; +} +.uniui-flag[data-v-d31e1c47]:before { + content: "\e65f"; +} +.uniui-flag-filled[data-v-d31e1c47]:before { + content: "\e660"; +} +.uniui-gear-filled[data-v-d31e1c47]:before { + content: "\e661"; +} +.uniui-home[data-v-d31e1c47]:before { + content: "\e662"; +} +.uniui-home-filled[data-v-d31e1c47]:before { + content: "\e663"; +} +.uniui-gear[data-v-d31e1c47]:before { + content: "\e664"; +} +.uniui-smallcircle-filled[data-v-d31e1c47]:before { + content: "\e665"; +} +.uniui-map-filled[data-v-d31e1c47]:before { + content: "\e666"; +} +.uniui-map[data-v-d31e1c47]:before { + content: "\e667"; +} +.uniui-refresh-filled[data-v-d31e1c47]:before { + content: "\e656"; +} +.uniui-refresh[data-v-d31e1c47]:before { + content: "\e657"; +} +.uniui-cloud-upload[data-v-d31e1c47]:before { + content: "\e645"; +} +.uniui-cloud-download-filled[data-v-d31e1c47]:before { + content: "\e646"; +} +.uniui-cloud-download[data-v-d31e1c47]:before { + content: "\e647"; +} +.uniui-cloud-upload-filled[data-v-d31e1c47]:before { + content: "\e648"; +} +.uniui-redo[data-v-d31e1c47]:before { + content: "\e64a"; +} +.uniui-images-filled[data-v-d31e1c47]:before { + content: "\e64b"; +} +.uniui-undo-filled[data-v-d31e1c47]:before { + content: "\e64c"; +} +.uniui-more[data-v-d31e1c47]:before { + content: "\e64d"; +} +.uniui-more-filled[data-v-d31e1c47]:before { + content: "\e64e"; +} +.uniui-undo[data-v-d31e1c47]:before { + content: "\e64f"; +} +.uniui-images[data-v-d31e1c47]:before { + content: "\e650"; +} +.uniui-paperclip[data-v-d31e1c47]:before { + content: "\e652"; +} +.uniui-settings[data-v-d31e1c47]:before { + content: "\e653"; +} +.uniui-search[data-v-d31e1c47]:before { + content: "\e654"; +} +.uniui-redo-filled[data-v-d31e1c47]:before { + content: "\e655"; +} +.uniui-list[data-v-d31e1c47]:before { + content: "\e644"; +} +.uniui-mail-open-filled[data-v-d31e1c47]:before { + content: "\e63a"; +} +.uniui-hand-down-filled[data-v-d31e1c47]:before { + content: "\e63c"; +} +.uniui-hand-down[data-v-d31e1c47]:before { + content: "\e63d"; +} +.uniui-hand-up-filled[data-v-d31e1c47]:before { + content: "\e63e"; +} +.uniui-hand-up[data-v-d31e1c47]:before { + content: "\e63f"; +} +.uniui-heart-filled[data-v-d31e1c47]:before { + content: "\e641"; +} +.uniui-mail-open[data-v-d31e1c47]:before { + content: "\e643"; +} +.uniui-heart[data-v-d31e1c47]:before { + content: "\e639"; +} +.uniui-loop[data-v-d31e1c47]:before { + content: "\e633"; +} +.uniui-pulldown[data-v-d31e1c47]:before { + content: "\e632"; +} +.uniui-scan[data-v-d31e1c47]:before { + content: "\e62a"; +} +.uniui-bars[data-v-d31e1c47]:before { + content: "\e627"; +} +.uniui-checkbox[data-v-d31e1c47]:before { + content: "\e62b"; +} +.uniui-checkbox-filled[data-v-d31e1c47]:before { + content: "\e62c"; +} +.uniui-shop[data-v-d31e1c47]:before { + content: "\e62f"; +} +.uniui-headphones[data-v-d31e1c47]:before { + content: "\e630"; +} +.uniui-cart[data-v-d31e1c47]:before { + content: "\e631"; +} +@font-face { + font-family: uniicons; + src: url("../../assets/uniicons.32e978a5.ttf"); +} +.uni-icons[data-v-d31e1c47] { + font-family: uniicons; + text-decoration: none; + text-align: center; +} + +.cloud-db-container[data-v-51006ffb] { + display: flex; + flex-direction: column; + width: 100%; + height: 100vh; + background-color: #f5f6fa; +} +.cloud-db-header[data-v-51006ffb] { + flex-shrink: 0; + background-color: #ffffff; + padding-bottom: 0; +} +.custom-navbar[data-v-51006ffb] { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.625rem 0.9375rem; + box-sizing: border-box; + position: relative; +} +.navbar-left[data-v-51006ffb] { + display: flex; + align-items: center; + min-width: 5rem; +} +.custom-navbar-icon[data-v-51006ffb] { + font-size: 1.375rem; + color: #333; +} +.navbar-title[data-v-51006ffb] { + font-size: 1.125rem; + font-weight: 600; + color: #1a1a2e; +} +.navbar-right[data-v-51006ffb] { + width: auto; + min-width: 2.5rem; + display: flex; + align-items: center; + justify-content: flex-end; +} +.navbar-before-title[data-v-51006ffb] { + font-size: 0.8125rem; + color: #3b86ff; + margin-left: 0.25rem; +} +.navbar-right-text[data-v-51006ffb] { + font-size: 0.875rem; + color: #3b86ff; + font-weight: 500; +} + +/* 菜单 */ +.menu-open[data-v-51006ffb] { + color: #3b86ff; +} +.menu-card[data-v-51006ffb] { + position: absolute; + top: 2.5rem; + right: 0.625rem; + background: #fff; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.625rem rgba(0, 0, 0, 0.1); + padding: 0.375rem 0; + z-index: 100; + min-width: 6.25rem; +} +.menu-card-item[data-v-51006ffb] { + padding: 0.625rem 1rem; + font-size: 0.875rem; + color: #333; +} +.menu-card-item[data-v-51006ffb]:active { + background: #f5f6fa; +} +.solid-line[data-v-51006ffb] { + height: 0.03125rem; + background: #eee; + margin: 0.125rem 0.625rem; +} +.file-count[data-v-51006ffb] { + font-size: 0.75rem; + color: #999; + font-weight: 400; +} + +/* 分类切换 Tab */ +.category-tabs[data-v-51006ffb] { + display: flex; + padding: 0.3125rem 0.9375rem 0; + gap: 1.25rem; + border-bottom: 0.0625rem solid #eee; +} +.category-tab[data-v-51006ffb] { + font-size: 0.9375rem; + color: #999; + padding-bottom: 0.625rem; + position: relative; + font-weight: 500; + transition: color 0.3s; +} +.category-tab.active[data-v-51006ffb] { + color: #3b86ff; + font-weight: 600; +} +.category-tab.active[data-v-51006ffb]::after { + content: ''; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 1.5rem; + height: 0.1875rem; + background: #3b86ff; + border-radius: 0.09375rem; +} + +/* 内容区域 */ +.cloud-db-content[data-v-51006ffb] { + flex: 1; + min-height: 0; + padding: 0.625rem 0.9375rem; + box-sizing: border-box; +} + +/* 区块 */ +.section-block[data-v-51006ffb] { + background: #ffffff; + border-radius: 0.625rem; + padding: 0.75rem; + margin-bottom: 0.625rem; + box-shadow: 0 0.0625rem 0.375rem rgba(0, 0, 0, 0.04); +} +.section-header[data-v-51006ffb] { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; +} +.section-title[data-v-51006ffb] { + display: flex; + align-items: center; + gap: 0.375rem; + font-size: 1rem; + font-weight: 600; + color: #1a1a2e; +} +.section-title .iconfont[data-v-51006ffb] { + font-size: 1.125rem; + color: #3b86ff; +} +.section-actions[data-v-51006ffb] { + display: flex; + align-items: center; + gap: 0.3125rem; +} +.action-btn[data-v-51006ffb] { + display: flex; + align-items: center; + gap: 0.1875rem; + padding: 0.3125rem 0.625rem; + background: rgba(59, 134, 255, 0.08); + color: #3b86ff; + border-radius: 0.9375rem; + font-size: 0.75rem; + font-weight: 500; +} +.section-divider[data-v-51006ffb] { + height: 0.0625rem; + margin: 0.125rem 0 0.625rem; +} + +/* 空状态 */ +.empty-tip[data-v-51006ffb] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1.875rem 0; + color: #bbb; + font-size: 0.8125rem; + gap: 0.5rem; +} +.empty-tip .iconfont[data-v-51006ffb] { + font-size: 2.5rem; + color: #ddd; +} + +/* 文件网格 */ +.file-grid[data-v-51006ffb] { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} +.file-item[data-v-51006ffb] { + width: calc(33.33% - 0.375rem); + display: flex; + flex-direction: column; + align-items: center; + padding: 0.625rem 0.3125rem; + border-radius: 0.5rem; + background: #f8f9fc; + border: 0.0625rem solid transparent; + transition: all 0.2s; + box-sizing: border-box; +} +.file-item[data-v-51006ffb]:active { + border-color: #3b86ff; + background: rgba(59, 134, 255, 0.04); +} +.file-icon[data-v-51006ffb] { + width: 2.5rem; + height: 2.5rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 0.5rem; + margin-bottom: 0.3125rem; +} +.file-icon.is-directory[data-v-51006ffb] { + background: rgba(255, 170, 0, 0.12); +} +.file-icon.is-directory .iconfont[data-v-51006ffb] { + font-size: 1.5rem; + color: #ffa500; +} +.file-icon.is-file[data-v-51006ffb] { + background: rgba(59, 134, 255, 0.1); +} +.file-icon.is-file .iconfont[data-v-51006ffb] { + font-size: 1.375rem; + color: #3b86ff; +} +.file-name[data-v-51006ffb] { + font-size: 0.75rem; + color: #333; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + margin-bottom: 0.1875rem; +} +.file-meta[data-v-51006ffb] { + display: flex; + gap: 0.25rem; + align-items: center; +} +.file-type-tag[data-v-51006ffb] { + font-size: 0.625rem; + color: #999; + background: #f0f0f0; + padding: 0.0625rem 0.3125rem; + border-radius: 0.25rem; +} +.file-size[data-v-51006ffb] { + font-size: 0.625rem; + color: #bbb; +} + +/* 数据表列表 */ +.table-list[data-v-51006ffb] { + display: flex; + flex-direction: column; + gap: 0.375rem; +} +.table-item[data-v-51006ffb] { + display: flex; + align-items: center; + padding: 0.625rem; + border-radius: 0.4375rem; + background: #f8f9fc; + border: 0.0625rem solid transparent; + transition: all 0.2s; +} +.table-item[data-v-51006ffb]:active { + border-color: #3b86ff; + background: rgba(59, 134, 255, 0.03); +} +.table-icon[data-v-51006ffb] { + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + background: rgba(59, 134, 255, 0.08); + border-radius: 0.4375rem; + margin-right: 0.625rem; + flex-shrink: 0; +} +.table-info[data-v-51006ffb] { + flex: 1; + min-width: 0; +} +.table-name[data-v-51006ffb] { + font-size: 0.875rem; + font-weight: 600; + color: #1a1a2e; + margin-bottom: 0.125rem; +} +.table-desc[data-v-51006ffb] { + font-size: 0.6875rem; + color: #999; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.table-meta[data-v-51006ffb] { + display: flex; + align-items: center; + gap: 0.1875rem; + flex-shrink: 0; +} +.table-rows[data-v-51006ffb] { + font-size: 0.6875rem; + color: #bbb; +} + +/* 团队管理 */ +.team-manage-block[data-v-51006ffb] { + cursor: pointer; +} +.team-count[data-v-51006ffb] { + font-size: 0.75rem; + color: #999; +} +.team-selector[data-v-51006ffb] { + padding: 0 0 0.625rem; +} +.team-scroll[data-v-51006ffb] { + white-space: nowrap; +} +.team-chip[data-v-51006ffb] { + display: inline-block; + padding: 0.375rem 0.875rem; + margin-right: 0.5rem; + border-radius: 0.9375rem; + font-size: 0.8125rem; + color: #666; + background: #f0f2f5; + transition: all 0.2s; +} +.team-chip.active[data-v-51006ffb] { + color: #fff; + background: #3b86ff; + font-weight: 500; +} +.select-team-tip[data-v-51006ffb] { + padding: 2.5rem 0; +} + +/* ===== 弹窗样式 ===== */ +.popup-overlay[data-v-51006ffb] { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.4); + z-index: 999; + display: flex; + align-items: center; + justify-content: center; +} +.popup-card[data-v-51006ffb] { + width: 18.75rem; + background: #fff; + border-radius: 0.9375rem; + padding: 1.25rem 0.9375rem; + box-sizing: border-box; + position: relative; + max-height: 80vh; + display: flex; + flex-direction: column; +} +.close-popup-card[data-v-51006ffb] { + position: absolute; + top: 0.625rem; + right: 0.625rem; + width: 1.5625rem; + height: 1.5625rem; + display: flex; + align-items: center; + justify-content: center; +} +.close-popup-card .iconfont[data-v-51006ffb] { + font-size: 1.25rem; + color: #999; +} +.popup-title[data-v-51006ffb] { + font-size: 1.0625rem; + font-weight: 600; + color: #1a1a2e; + margin-bottom: 0.9375rem; + text-align: center; +} +.new-folder-name[data-v-51006ffb] { + font-size: 0.8125rem; + color: #666; + margin-bottom: 0.3125rem; +} +.create-folder-name[data-v-51006ffb] { + margin-bottom: 0.625rem; +} +.create-folder-name uni-input[data-v-51006ffb] { + width: 100%; + height: auto; + padding: 0.625rem; + box-sizing: border-box; + border: 0.03125rem solid #e0e0e0; + border-radius: 0.5rem; + font-size: 0.875rem; + background: #f9fafb; +} +.create-folder-name uni-input[data-v-51006ffb]:focus { + border-color: #3b86ff; + background: #fff; +} +.nf-path-label[data-v-51006ffb] { + font-size: 0.75rem; + color: #999; + margin-bottom: 0.25rem; +} +.nf-path-display[data-v-51006ffb] { + font-size: 0.75rem; + color: #3b86ff; + background: rgba(59, 134, 255, 0.06); + padding: 0.375rem 0.5rem; + border-radius: 0.3125rem; + margin-bottom: 0.625rem; +} +.option-wrapper[data-v-51006ffb] { + display: flex; + gap: 0.625rem; + justify-content: flex-end; + margin-top: 0.3125rem; +} +.opt-btn[data-v-51006ffb] { + padding: 0.5rem 1.25rem; + border-radius: 0.9375rem; + font-size: 0.875rem; + font-weight: 500; +} +.opt-cancel[data-v-51006ffb] { + color: #999; + background: #f0f2f5; +} +.opt-confirm[data-v-51006ffb] { + color: #fff; + background: #3b86ff; +} + +/* 团队管理弹窗 */ +.team-manage-body[data-v-51006ffb] { + flex: 1; + min-height: 0; + max-height: 15.625rem; + margin-bottom: 0.625rem; +} +.member-list[data-v-51006ffb] { + display: flex; + flex-direction: column; + gap: 0.3125rem; +} +.member-item[data-v-51006ffb] { + display: flex; + align-items: center; + padding: 0.5rem; + border-radius: 0.4375rem; + background: #f8f9fc; +} +.member-avatar[data-v-51006ffb] { + width: 2.1875rem; + height: 2.1875rem; + border-radius: 50%; + overflow: hidden; + margin-right: 0.5rem; + flex-shrink: 0; +} +.member-avatar uni-image[data-v-51006ffb] { + width: 100%; + height: 100%; +} +.default-avatar[data-v-51006ffb] { + width: 100%; + height: 100%; + background: #ccc; + display: flex; + align-items: center; + justify-content: center; +} +.member-info[data-v-51006ffb] { + flex: 1; + min-width: 0; +} +.member-name[data-v-51006ffb] { + font-size: 0.875rem; + font-weight: 500; + color: #333; +} +.member-label[data-v-51006ffb] { + font-size: 0.6875rem; + color: #999; + margin-top: 0.125rem; +} +.member-actions[data-v-51006ffb] { + flex-shrink: 0; +} +.member-role[data-v-51006ffb] { + font-size: 0.6875rem; + padding: 0.1875rem 0.5rem; + border-radius: 0.625rem; +} +.member-role.owner[data-v-51006ffb] { + color: #e6a23c; + background: rgba(230, 162, 60, 0.1); +} +.member-role.admin[data-v-51006ffb] { + color: #3b86ff; + background: rgba(59, 134, 255, 0.1); +} +.member-actions-right[data-v-51006ffb] { + display: flex; + gap: 0.25rem; +} +.member-action-btn[data-v-51006ffb] { + font-size: 0.625rem; + padding: 0.25rem 0.4375rem; + border-radius: 0.5rem; +} +.set-admin[data-v-51006ffb] { + color: #3b86ff; + border: 0.03125rem solid #3b86ff; +} +.remove-member[data-v-51006ffb] { + color: #f56c6c; + border: 0.03125rem solid #f56c6c; +} +.invite-section[data-v-51006ffb] { + border-top: 0.03125rem solid #eee; + padding-top: 0.625rem; +} +.invite-input-wrapper[data-v-51006ffb] { + display: flex; + align-items: center; + gap: 0.5rem; +} +.invite-input[data-v-51006ffb] { + flex: 1; + height: auto; + padding: 0.5625rem 0.625rem; + box-sizing: border-box; + border: 0.03125rem solid #e0e0e0; + border-radius: 0.9375rem; + font-size: 0.8125rem; + background: #f9fafb; +} +.invite-btn[data-v-51006ffb] { + background: #3b86ff; + color: #fff; + font-size: 0.75rem; + padding: 0.4375rem 1rem; +} +.folder-null[data-v-51006ffb] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1.875rem 0; + color: #bbb; + font-size: 0.8125rem; + gap: 0.375rem; +} +.folder-null .iconfont[data-v-51006ffb] { + font-size: 2rem; + color: #ddd; +} +.text-btn[data-v-51006ffb] { + padding: 0.25rem 0.625rem; + border-radius: 0.9375rem; + font-size: 14px; + font-weight: 500; +} diff --git a/unpackage/dist/dev/app-plus/pages/ContactPages/ContactPages.css b/unpackage/dist/dev/app-plus/pages/ContactPages/ContactPages.css index 9d8f356..4417e3d 100644 --- a/unpackage/dist/dev/app-plus/pages/ContactPages/ContactPages.css +++ b/unpackage/dist/dev/app-plus/pages/ContactPages/ContactPages.css @@ -841,15 +841,26 @@ justify-content: center; align-items: center; } -.agree-btn[data-v-976117c3], -.refuse-btn[data-v-976117c3] { +.agree-btn[data-v-976117c3] { font-size: 14px; font-weight: 500; - border: 1px solid #666; - margin-left: 0.3125rem; + border: 1px solid #3b86ff; + color: #3b86ff; box-sizing: border-box; } +/* 好友申请状态 */ +.friend-status[data-v-976117c3] { + font-size: 14px; + font-weight: 500; + padding: 0.25rem 0.625rem; + border-radius: 0.9375rem; +} +.friend-status.agreed[data-v-976117c3] { + color: #059669; + background-color: rgba(16, 185, 129, 0.1); +} + /* 通讯录 */ .contact-list[data-v-976117c3] { display: flex; diff --git a/unpackage/dist/dev/app-plus/static/iconfont/demo_index.html b/unpackage/dist/dev/app-plus/static/iconfont/demo_index.html index b6c8508..3bfb318 100644 --- a/unpackage/dist/dev/app-plus/static/iconfont/demo_index.html +++ b/unpackage/dist/dev/app-plus/static/iconfont/demo_index.html @@ -54,6 +54,12 @@
          +
        • + +
          云端,云,云服务
          +
          &#xe988;
          +
        • +
        • 其他文件
          @@ -420,9 +426,9 @@
          @font-face {
             font-family: 'iconfont';
          -  src: url('iconfont.woff2?t=1780384681439') format('woff2'),
          -       url('iconfont.woff?t=1780384681439') format('woff'),
          -       url('iconfont.ttf?t=1780384681439') format('truetype');
          +  src: url('iconfont.woff2?t=1782200893170') format('woff2'),
          +       url('iconfont.woff?t=1782200893170') format('woff'),
          +       url('iconfont.ttf?t=1782200893170') format('truetype');
           }
           

          第二步:定义使用 iconfont 的样式

          @@ -448,6 +454,15 @@
            +
          • + +
            + 云端,云,云服务 +
            +
            .icon-cloud +
            +
          • +
          • @@ -997,6 +1012,14 @@
              +
            • + +
              云端,云,云服务
              +
              #icon-cloud
              +
            • +