feat: chat list page for mobile is ready

This commit is contained in:
RockYang 2023-06-25 06:53:22 +08:00
parent 3c8b5cb313
commit 2cadd6af44
6 changed files with 153 additions and 26 deletions

View File

@ -218,10 +218,9 @@ func (h *UserHandler) Logout(c *gin.Context) {
// Session 获取/验证会话 // Session 获取/验证会话
func (h *UserHandler) Session(c *gin.Context) { func (h *UserHandler) Session(c *gin.Context) {
sessionId := c.GetHeader(types.SessionName) user, err := utils.GetLoginUser(c, h.db)
session := h.App.ChatSession.Get(sessionId) if err == nil {
if session.ClientIP == c.ClientIP() { resp.SUCCESS(c, user)
resp.SUCCESS(c, session)
} else { } else {
resp.NotAuth(c) resp.NotAuth(c)
} }

View File

@ -3,7 +3,7 @@ import {httpGet} from "@/utils/http";
export function checkSession() { export function checkSession() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
httpGet('/api/user/session').then(res => { httpGet('/api/user/session').then(res => {
resolve(res) resolve(res.data)
}).catch(err => { }).catch(err => {
reject(err) reject(err)
}) })

View File

@ -4,11 +4,25 @@ import "element-plus/dist/index.css"
import 'vant/lib/index.css'; import 'vant/lib/index.css';
import App from './App.vue' import App from './App.vue'
import {createPinia} from "pinia"; import {createPinia} from "pinia";
import {Cell, Image, List, NavBar, Notify, Search, Tabbar, TabbarItem, TextEllipsis} from "vant"; import {
Cell,
ConfigProvider,
Image,
List,
NavBar,
Notify,
Picker,
Popup,
Search,
Tabbar,
TabbarItem,
TextEllipsis
} from "vant";
import router from "@/router"; import router from "@/router";
const app = createApp(App) const app = createApp(App)
app.use(createPinia()) app.use(createPinia())
app.use(ConfigProvider);
app.use(Tabbar); app.use(Tabbar);
app.use(TabbarItem); app.use(TabbarItem);
app.use(NavBar); app.use(NavBar);
@ -17,6 +31,8 @@ app.use(Cell)
app.use(Image) app.use(Image)
app.use(TextEllipsis) app.use(TextEllipsis)
app.use(Notify) app.use(Notify)
app.use(Picker)
app.use(Popup)
app.use(List); app.use(List);
app.use(router).use(ElementPlus).mount('#app') app.use(router).use(ElementPlus).mount('#app')

View File

@ -697,13 +697,13 @@ const searchChat = function () {
chatList.value = allChats.value chatList.value = allChats.value
return return
} }
const roles = []; const items = [];
for (let i = 0; i < allChats.value.length; i++) { for (let i = 0; i < allChats.value.length; i++) {
if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) { if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) {
roles.push(allChats.value[i]); items.push(allChats.value[i]);
} }
} }
chatList.value = roles; chatList.value = items;
} }
const updateUser = function (data) { const updateUser = function (data) {

View File

@ -1,6 +1,10 @@
<template> <template>
<div class="chat-mobile"> <div class="container chat-mobile">
<van-nav-bar :title="title"/> <van-nav-bar
:title="title"
right-text="新建会话"
@click-right="showPicker = true"
/>
<div class="content"> <div class="content">
<van-search <van-search
@ -28,9 +32,28 @@
</div> </div>
</van-cell> </van-cell>
</van-list> </van-list>
</div> </div>
<van-popup v-model:show="showPicker" position="bottom">
<van-picker
title="选择模型和角色"
:columns="columns"
@cancel="showPicker = false"
@confirm="newChat"
>
<template #option="item">
<div class="picker-option">
<van-image
fit="cover"
:src="item.icon"
round
v-if="item.icon"
/>
<span>{{ item.text }}</span>
</div>
</template>
</van-picker>
</van-popup>
</div> </div>
</template> </template>
@ -39,6 +62,8 @@ import {ref} from "vue";
import {httpGet} from "@/utils/http"; import {httpGet} from "@/utils/http";
import {getLoginUser} from "@/utils/storage"; import {getLoginUser} from "@/utils/storage";
import {showFailToast} from "vant"; import {showFailToast} from "vant";
import {checkSession} from "@/action/session";
import router from "@/router";
const title = ref("会话列表") const title = ref("会话列表")
const chatName = ref("") const chatName = ref("")
@ -49,6 +74,49 @@ const finished = ref(false)
const error = ref(false) const error = ref(false)
const user = getLoginUser() const user = getLoginUser()
const showPicker = ref(false)
const columns = ref([
[{text: 'GPT-3.5', value: 1},
{text: 'GPT-4', value: 2},
],
[{text: 'xxxx', value: 3},
{text: 'yyy', value: 4},]
])
checkSession().then(() => {
//
httpGet(`/api/role/list?user_id=${user.id}`).then((res) => {
if (res.data) {
const items = res.data
const roles = []
for (let i = 0; i < items.length; i++) {
// console.log(items[i])
roles.push({text: items[i].name, value: items[i].id, icon: items[i].icon})
}
columns.value[0] = roles
}
}).catch(() => {
showFailToast("加载聊天角色失败")
})
//
httpGet('/api/admin/config/get?key=system').then(res => {
if (res.data) {
const items = res.data.models
const models = []
for (let i = 0; i < items.length; i++) {
console.log(items[i])
models.push({text: items[i].toUpperCase(), value: items[i]})
}
columns.value[1] = models
}
}).catch(() => {
showFailToast("加载系统配置失败")
})
}).catch(() => {
router.push("/login")
})
const onLoad = () => { const onLoad = () => {
httpGet("/api/chat/list?user_id=" + user.id).then((res) => { httpGet("/api/chat/list?user_id=" + user.id).then((res) => {
if (res.data) { if (res.data) {
@ -68,13 +136,17 @@ const search = () => {
chats.value = allChats.value chats.value = allChats.value
return return
} }
const roles = []; const items = [];
for (let i = 0; i < allChats.value.length; i++) { for (let i = 0; i < allChats.value.length; i++) {
if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) { if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) {
roles.push(allChats.value[i]); items.push(allChats.value[i]);
} }
} }
chats.value = roles; chats.value = items;
}
const newChat = (value) => {
console.log(value)
} }
</script> </script>
@ -83,8 +155,6 @@ const search = () => {
.chat-mobile { .chat-mobile {
.content { .content {
padding: 0 10px;
.van-cell__value { .van-cell__value {
.chat-list-item { .chat-list-item {
display flex display flex
@ -101,5 +171,19 @@ const search = () => {
} }
} }
} }
.van-picker-column {
.picker-option {
display flex
width 100%
padding 0 10px
.van-image {
width 20px;
height 20px;
margin-right 5px
}
}
}
} }
</style> </style>

View File

@ -1,20 +1,24 @@
<template> <template>
<div> <van-config-provider :theme="theme">
<router-view/> <div class="mobile-home">
<router-view/>
<van-tabbar route v-model="active" @change="onChange"> <van-tabbar route v-model="active" @change="onChange">
<van-tabbar-item to="/mobile/chat" name="home" icon="chat-o"></van-tabbar-item> <van-tabbar-item to="/mobile/chat" name="home" icon="chat-o"></van-tabbar-item>
<van-tabbar-item to="/mobile/setting" name="setting" icon="setting-o"></van-tabbar-item> <van-tabbar-item to="/mobile/setting" name="setting" icon="setting-o"></van-tabbar-item>
<van-tabbar-item to="/mobile/profile" name="profile" icon="user-o"></van-tabbar-item> <van-tabbar-item to="/mobile/profile" name="profile" icon="user-o"></van-tabbar-item>
</van-tabbar> </van-tabbar>
</div>
</van-config-provider>
</div>
</template> </template>
<script setup> <script setup>
import {ref} from "vue"; import {ref} from "vue";
const active = ref('home'); const active = ref('home');
const theme = ref("light")
const onChange = (index) => { const onChange = (index) => {
console.log(index) console.log(index)
// showToast(` ${index}`); // showToast(` ${index}`);
@ -22,8 +26,32 @@ const onChange = (index) => {
</script> </script>
<style lang="stylus"> <style lang="stylus">
.mobile-home {
.container {
.van-nav-bar {
position fixed
width 100%
}
.content {
padding 46px 10px 0 10px;
}
}
}
//
.van-theme-dark body {
background #1c1c1e
}
.van-toast--fail { .van-toast--fail {
background #fef0f0 background #fef0f0
color #f56c6c color #f56c6c
} }
.van-nav-bar {
position fixed
width 100%
}
</style> </style>