From 6a2d383be69619e6d444698b4a3336c851abdbb5 Mon Sep 17 00:00:00 2001 From: RockYang Date: Thu, 7 Sep 2023 09:29:16 +0800 Subject: [PATCH] feat: extract css to a single file, add chat_id path variable support --- web/src/assets/css/chat-plus.css | 307 ++++++++++++++++++++++ web/src/assets/css/chat-plus.styl | 404 +++++++++++++++++++++++++++++ web/src/components/ChatPrompt.vue | 2 +- web/src/router.js | 9 +- web/src/views/ChatPlus.vue | 416 ++++-------------------------- 5 files changed, 765 insertions(+), 373 deletions(-) create mode 100644 web/src/assets/css/chat-plus.css create mode 100644 web/src/assets/css/chat-plus.styl diff --git a/web/src/assets/css/chat-plus.css b/web/src/assets/css/chat-plus.css new file mode 100644 index 00000000..c6e52bf4 --- /dev/null +++ b/web/src/assets/css/chat-plus.css @@ -0,0 +1,307 @@ +#app { + height: 100%; +} +#app .common-layout { + height: 100%; +} +#app .common-layout .el-aside { + background-color: #252526; +} +#app .common-layout .el-aside .title-box { + padding: 6px 10px; + display: flex; + color: #fff; + font-size: 20px; +} +#app .common-layout .el-aside .title-box .logo { + background-color: #fff; + border-radius: 8px; + width: 35px; + height: 35px; +} +#app .common-layout .el-aside .title-box span { + padding-top: 5px; + padding-left: 10px; +} +#app .common-layout .el-aside .chat-list { + display: flex; + flex-flow: column; + background-color: #28292a; + border-top: 1px solid #2f3032; + border-right: 1px solid #2f3032; +} +#app .common-layout .el-aside .chat-list .search-box { + flex-wrap: wrap; + padding: 10px 15px; +} +#app .common-layout .el-aside .chat-list .search-box .el-input__wrapper { + background-color: #363535; + box-shadow: none; +} +#app .common-layout .el-aside .chat-list ::-webkit-scrollbar { + width: 0; + height: 0; + background-color: transparent; +} +#app .common-layout .el-aside .chat-list .content { + width: 100%; + overflow-y: scroll; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item { + display: flex; + width: 100%; + justify-content: flex-start; + padding: 8px 12px; + cursor: pointer; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item:hover { + background-color: #343540; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item .avatar { + width: 28px; + height: 28px; + border-radius: 50%; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title-input { + font-size: 14px; + margin-top: 4px; + margin-left: 10px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 210px; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title { + color: #c1c1c1; + padding: 5px 10px; + max-width: 220px; + font-size: 14px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item .btn { + display: none; + position: absolute; + right: 2px; + top: 16px; + color: #fff; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item .btn .el-icon { + margin-right: 8px; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item.active { + background-color: #343540; +} +#app .common-layout .el-aside .chat-list .content .chat-list-item.active .btn { + display: inline; +} +#app .common-layout .el-aside .tool-box { + display: flex; + justify-content: flex-end; + align-items: center; + padding: 0 20px 10px 20px; + border-top: 1px solid #3c3c3c; +} +#app .common-layout .el-aside .tool-box .user-info { + width: 100%; + padding-top: 10px; +} +#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link { + width: 100%; + cursor: pointer; + display: flex; +} +#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-image { + width: 20px; + height: 20px; + border-radius: 5px; +} +#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .username { + display: flex; + line-height: 22px; + width: 230px; + padding-left: 10px; +} +#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-icon { + color: #ccc; + line-height: 24px; +} +#app .common-layout .el-main { + overflow: hidden; + --el-main-padding: 0; + margin: 0; +} +#app .common-layout .el-main .chat-head { + width: 100%; + height: 50px; + background-color: #28292a; +} +#app .common-layout .el-main .chat-head .chat-config { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + padding-top: 10px; +} +#app .common-layout .el-main .chat-head .chat-config .role-select-label { + color: #fff; +} +#app .common-layout .el-main .chat-head .chat-config .el-select { + margin-right: 10px; +} +#app .common-layout .el-main .chat-head .chat-config .role-select { + max-width: 130px; +} +#app .common-layout .el-main .chat-head .chat-config .el-button .el-icon { + margin-right: 5px; +} +#app .common-layout .el-main .chat-head .iconfont { + margin-right: 5px; +} +#app .common-layout .el-main .right-box { + min-width: 0; + flex: 1; + background-color: #fff; + border-left: 1px solid #4f4f4f; +} +#app .common-layout .el-main .right-box #container { + overflow: hidden; + width: 100%; +} +#app .common-layout .el-main .right-box #container ::-webkit-scrollbar { + width: 0; + height: 0; + background-color: transparent; +} +#app .common-layout .el-main .right-box #container .chat-box { + overflow-y: scroll; + --content-font-size: 16px; + --content-color: #c1c1c1; + font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; + padding: 0 0 50px 0; +} +#app .common-layout .el-main .right-box #container .chat-box .chat-line { + font-size: 14px; + display: flex; + align-items: flex-start; +} +#app .common-layout .el-main .right-box #container .re-generate { + position: relative; + display: flex; + justify-content: center; +} +#app .common-layout .el-main .right-box #container .re-generate .btn-box { + position: absolute; + bottom: 10px; +} +#app .common-layout .el-main .right-box #container .re-generate .btn-box .el-button .el-icon { + margin-right: 5px; +} +#app .common-layout .el-main .right-box #container .input-box { + background-color: #fff; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 2px 15px rgba(0,0,0,0.1); + padding: 0 15px; +} +#app .common-layout .el-main .right-box #container .input-box .input-container { + width: 100%; + margin: 0; + border: none; + padding: 10px 0; + display: flex; + justify-content: center; + position: relative; +} +#app .common-layout .el-main .right-box #container .input-box .input-container .el-textarea .el-textarea__inner::-webkit-scrollbar { + width: 0; + height: 0; +} +#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn { + position: absolute; + right: 12px; + top: 20px; +} +#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn .el-button { + padding: 8px 5px; + border-radius: 6px; + background: #19c37d; + color: #fff; + font-size: 20px; +} +#app .common-layout .el-main .right-box #container::-webkit-scrollbar { + width: 0; + height: 0; +} +#app .el-message-box { + width: 90%; + max-width: 420px; +} +#app .el-message { + min-width: 100px; + max-width: 600px; +} +.el-select-dropdown__wrap .el-select-dropdown__item .role-option { + display: flex; + flex-flow: row; + margin-top: 8px; +} +.el-select-dropdown__wrap .el-select-dropdown__item .role-option .el-image { + width: 20px; + height: 20px; + border-radius: 50%; +} +.el-select-dropdown__wrap .el-select-dropdown__item .role-option span { + margin-left: 5px; + height: 20px; + line-height: 20px; +} +.account { + display: flex; + background-color: #90ffc2; + color: #000; + width: 100%; + border-radius: 10px; + padding: 10px; +} +.account .vip-logo .el-image { + width: 40px; + height: 40px; + border-radius: 100%; + background-color: #fff; +} +.account .vip-info { + padding: 0 10px 0 10px; +} +.account .vip-info h4, +.account .vip-info p { + margin: 0; +} +.account .vip-info h4 { + font-weight: bold; + font-size: 16px; +} +.account .vip-info p { + color: #333; +} +.account .pay-btn { + width: 100%; + display: flex; + justify-content: right; + align-items: center; +} +.notice { + background-color: #f6deff; + width: 100%; + padding: 5px 10px; + border-radius: 5px; + color: #cf49ff; +} +.dialog-service { + text-align: center; +} +.dialog-service .el-image { + width: 360px; +} diff --git a/web/src/assets/css/chat-plus.styl b/web/src/assets/css/chat-plus.styl new file mode 100644 index 00000000..b097fc4e --- /dev/null +++ b/web/src/assets/css/chat-plus.styl @@ -0,0 +1,404 @@ +$sideBgColor = #252526; +$borderColor = #4676d0; +#app { + + height: 100%; + + .common-layout { + height: 100%; + + // left side + + .el-aside { + background-color: $sideBgColor; + + .title-box { + padding: 6px 10px; + display: flex; + color: #ffffff; + font-size: 20px; + + .logo { + background-color: #ffffff + border-radius: 8px; + width: 35px; + height: 35px; + } + + span { + padding-top: 5px; + padding-left: 10px; + } + } + + .chat-list { + display: flex + flex-flow: column + background-color: #28292A + border-top: 1px solid #2F3032 + border-right: 1px solid #2F3032 + + .search-box { + flex-wrap: wrap + padding: 10px 15px; + + .el-input__wrapper { + background-color: #363535; + box-shadow: none + } + } + + // 隐藏滚动条 + + ::-webkit-scrollbar { + width: 0; + height: 0; + background-color: transparent; + } + + .content { + //display flex + //flex-wrap: wrap; + //flex-direction column + width: 100% + overflow-y: scroll + + .chat-list-item { + display: flex + width: 100% + justify-content: flex-start + padding: 8px 12px + //border-bottom: 1px solid #3c3c3c + cursor: pointer + + &:hover { + background-color #343540 + } + + .avatar { + width: 28px; + height: 28px; + border-radius: 50%; + } + + .chat-title-input { + font-size: 14px; + margin-top: 4px; + margin-left: 10px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + width: 210px; + } + + .chat-title { + color: #c1c1c1 + padding: 5px 10px; + max-width 220px; + font-size 14px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .btn { + display none + position: absolute; + right: 2px; + top: 16px; + color #ffffff + + .el-icon { + margin-right 8px; + } + } + } + + .chat-list-item.active { + background-color: #343540; + + .btn { + display inline + } + } + } + } + + + .tool-box { + display: flex; + justify-content: flex-end; + align-items: center; + padding 0 20px 10px 20px; + border-top 1px solid #3c3c3c; + + .user-info { + width 100% + padding-top 10px; + + .el-dropdown-link { + width 100%; + cursor: pointer + display flex + + .el-image { + width: 20px; + height: 20px; + border-radius: 5px; + } + + .username { + display flex + line-height 22px; + width 230px; + padding-left 10px; + + } + + .el-icon { + color: #cccccc; + line-height 24px; + } + } + + } + } + } + + .el-main { + overflow: hidden; + --el-main-padding: 0; + margin: 0; + + .chat-head { + width: 100%; + height: 50px; + background-color: #28292A + + .chat-config { + display flex + flex-direction row + align-items: center; + justify-content center; + padding-top 10px; + + .role-select-label { + color #ffffff + } + + .el-select { + //max-width 150px; + margin-right 10px; + } + + .role-select { + max-width 130px; + } + + .el-button { + .el-icon { + margin-right 5px; + } + } + } + + .iconfont { + margin-right 5px; + } + } + + .right-box { + min-width: 0; + flex: 1; + background-color: #ffffff + border-left: 1px solid #4f4f4f + + #container { + overflow: hidden; + width: 100%; + + ::-webkit-scrollbar { + width: 0; + height: 0; + background-color: transparent; + } + + .chat-box { + overflow-y: scroll; + //border-bottom: 1px solid #4f4f4f + + // 变量定义 + --content-font-size: 16px; + --content-color: #c1c1c1; + + font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; + padding: 0 0 50px 0; + + .chat-line { + font-size: 14px; + display: flex; + align-items: flex-start; + + } + } + + .re-generate { + position: relative; + display: flex; + justify-content: center; + + .btn-box { + position: absolute + bottom: 10px; + + .el-button { + .el-icon { + margin-right 5px; + } + } + + } + } + + .input-box { + background-color: #ffffff + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1); + padding 0 15px; + + .input-container { + width 100% + margin: 0; + border: none; + padding: 10px 0; + display flex + justify-content center + position relative + + .el-textarea { + + .el-textarea__inner::-webkit-scrollbar { + width: 0; + height: 0; + } + } + + .send-btn { + position absolute; + right 12px; + top 20px; + + .el-button { + padding 8px 5px; + border-radius 6px; + background: rgb(25, 195, 125) + color #ffffff; + font-size 20px; + } + } + + } + } + } + + #container::-webkit-scrollbar { + width: 0; + height: 0; + } + } + } + } + + .el-message-box { + width: 90%; + max-width: 420px; + } + + .el-message { + min-width: 100px; + max-width: 600px; + } +} + +.el-select-dropdown__wrap { + .el-select-dropdown__item { + .role-option { + display flex + flex-flow row + margin-top 8px; + + .el-image { + width 20px + height 20px + border-radius 50% + } + + span { + margin-left 5px; + height 20px; + line-height 20px; + } + } + } +} + +.account { + display flex + background-color #90FFC2 + color #000000 + width 100% + border-radius 10px + padding 10px + + .vip-logo { + .el-image { + width 40px + height 40px + border-radius 100% + background-color #ffffff + } + } + + .vip-info { + padding: 0 10px 0 10px + + h4, p { + margin 0 + } + + h4 { + font-weight bold + font-size 16px; + } + + p { + color #333333 + } + } + + .pay-btn { + width 100% + display flex + justify-content right + align-items center + + } +} + +.notice { + background-color #F6DEFF + width 100% + padding 5px 10px; + border-radius 5px; + color #CF49FF +} + +.dialog-service { + text-align center + + .el-image { + width 360px; + } +} \ No newline at end of file diff --git a/web/src/components/ChatPrompt.vue b/web/src/components/ChatPrompt.vue index 5f56e675..7bf9a105 100644 --- a/web/src/components/ChatPrompt.vue +++ b/web/src/components/ChatPrompt.vue @@ -45,7 +45,7 @@ export default defineComponent({ default: 0, }, model: { - type: String, + type: Number, default: '', }, }, diff --git a/web/src/router.js b/web/src/router.js index ae42d71b..40d4f21a 100644 --- a/web/src/router.js +++ b/web/src/router.js @@ -21,11 +21,18 @@ const routes = [ component: () => import('@/views/Register.vue'), }, { - name: 'plus', + name: 'chat', path: '/chat', meta: {title: '创作中心'}, component: () => import('@/views/ChatPlus.vue'), }, + { + name: 'chat-id', + path: '/chat/:id', + meta: {title: '创作中心'}, + component: () => import('@/views/ChatPlus.vue'), + props: true // 将路由参数传递给组件的 props + }, { name: 'chat-export', path: '/chat/export', diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index 5c560697..4303aa10 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -285,8 +285,8 @@ import Welcome from "@/components/Welcome.vue"; import ChatMidJourney from "@/components/ChatMidJourney.vue"; const title = ref('ChatGPT-智能助手'); -const logo = 'images/logo.png'; -const rewardImg = ref('images/reward.png') +const logo = '/images/logo.png'; +const rewardImg = ref('/images/reward.png') const models = ref([]) const modelID = ref(0) const chatData = ref([]); @@ -320,23 +320,40 @@ onMounted(() => { checkSession().then((user) => { loginUser.value = user isLogin.value = true - // 加载角色列表 - httpGet(`/api/role/list?user_id=${user.id}`).then((res) => { - roles.value = res.data; - roleId.value = roles.value[0]['id']; - // 获取会话列表 - loadChats(); + // 获取会话列表 + httpGet("/api/chat/list?user_id=" + loginUser.value.id).then((res) => { + if (res.data) { + chatList.value = res.data; + allChats.value = res.data; + } // 加载模型 httpGet('/api/model/list?enable=1').then(res => { models.value = res.data modelID.value = models.value[0].id - // 创建新的对话 - newChat(); + + // 加载角色列表 + httpGet(`/api/role/list?user_id=${user.id}`).then((res) => { + roles.value = res.data; + roleId.value = roles.value[0]['id']; + const chatId = router.currentRoute.value.params['id'] + const chat = getChatById(chatId) + if (chat === null) { + // 创建新的对话 + newChat(); + } else { + // 加载对话 + loadChat(chat) + } + }).catch((e) => { + ElMessage.error('获取聊天角色失败: ' + e.messages) + }) }).catch(e => { ElMessage.error("加载模型失败: " + e.message) }) - }).catch((e) => { - ElMessage.error('获取聊天角色失败: ' + e.messages) + + }).catch(() => { + // TODO: 增加重试按钮 + ElMessage.error("加载会话列表失败!") }) }).catch(() => { router.push('login') @@ -354,19 +371,6 @@ onMounted(() => { window.onresize = () => resizeElement(); }); -// 加载会话 -const loadChats = function () { - httpGet("/api/chat/list?user_id=" + loginUser.value.id).then((res) => { - if (res.data) { - chatList.value = res.data; - allChats.value = res.data; - } - }).catch(() => { - // TODO: 增加重试按钮 - ElMessage.error("加载会话列表失败!") - }) -} - const getRoleById = function (rid) { for (let i = 0; i < roles.value.length; i++) { if (roles.value[i]['id'] === rid) { @@ -412,7 +416,12 @@ const newChat = function () { } // 切换会话 -const changeChat = function (chat) { +const changeChat = (chat) => { + router.push("/chat/"+chat.chat_id) + loadChat(chat) +} + +const loadChat = function (chat) { if (activeChat.value['chat_id'] === chat.chat_id) { return; } @@ -841,353 +850,18 @@ const exportChat = () => { // console.log(url) window.open(url, '_blank'); } + +const getChatById = (chatId) => { + for (let index in chatList.value) { + if (chatList.value[index].chat_id === chatId) { + return chatList.value[index] + } + } + return null +} \ No newline at end of file