feat: 对话演示适配移动端和部分类型优化

feat: 对话演示适配移动端和部分类型优化
This commit is contained in:
wangdan-fit2cloud 2024-05-22 14:57:42 +08:00 committed by GitHub
commit 1e5067f849
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 149 additions and 55 deletions

4
ui/src/enums/common.ts Normal file
View File

@ -0,0 +1,4 @@
export enum DeviceType {
Mobile = 'Mobile',
Desktop = 'Desktop'
}

4
ui/src/enums/document.ts Normal file
View File

@ -0,0 +1,4 @@
export enum hitHandlingMethod {
optimization = '模型优化',
directly_return = '直接回答'
}

6
ui/src/enums/team.ts Normal file
View File

@ -0,0 +1,6 @@
export enum TeamEnum {
MANAGE = 'MANAGE',
USE = 'USE',
DATASET = 'DATASET',
APPLICATION = 'APPLICATION'
}

View File

@ -0,0 +1,36 @@
import { watch, onBeforeMount, onMounted, onBeforeUnmount } from 'vue'
import { useRoute } from 'vue-router'
import useStore from '@/stores'
import { DeviceType } from '@/enums/common'
/** 参考 Bootstrap 的响应式设计 WIDTH = 600 */
const WIDTH = 600
/** 根据大小变化重新布局 */
export default () => {
const { common } = useStore()
const _isMobile = () => {
const rect = document.body.getBoundingClientRect()
return rect.width - 1 < WIDTH
}
const _resizeHandler = () => {
if (!document.hidden) {
const isMobile = _isMobile()
common.toggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop)
}
}
onBeforeMount(() => {
window.addEventListener('resize', _resizeHandler)
})
onMounted(() => {
if (_isMobile()) {
common.toggleDevice(DeviceType.Mobile)
}
})
onBeforeUnmount(() => {
window.removeEventListener('resize', _resizeHandler)
})
}

View File

@ -1,9 +1,11 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { DeviceType } from '@/enums/common'
export interface commonTypes { export interface commonTypes {
breadcrumb: any breadcrumb: any
paginationConfig: any | null paginationConfig: any | null
search: any search: any
device: string
} }
const useCommonStore = defineStore({ const useCommonStore = defineStore({
@ -12,7 +14,8 @@ const useCommonStore = defineStore({
breadcrumb: null, breadcrumb: null,
// 搜索和分页缓存 // 搜索和分页缓存
paginationConfig: {}, paginationConfig: {},
search: {} search: {},
device: DeviceType.Desktop
}), }),
actions: { actions: {
saveBreadcrumb(data: any) { saveBreadcrumb(data: any) {
@ -23,6 +26,12 @@ const useCommonStore = defineStore({
}, },
saveCondition(val: string, data: any) { saveCondition(val: string, data: any) {
this.search[val] = data this.search[val] = data
},
toggleDevice(value: DeviceType) {
this.device = value
},
isMobile() {
return this.device === DeviceType.Mobile
} }
} }
}) })

View File

@ -32,7 +32,7 @@
<span>历史记录</span> <span>历史记录</span>
</div> </div>
<el-scrollbar> <el-scrollbar max-height="300">
<div class="p-8"> <div class="p-8">
<common-list <common-list
:data="chatLogeData" :data="chatLogeData"

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="chat-pc" v-loading="loading"> <div class="chat-pc" :class="classObj" v-loading="loading">
<div class="chat-pc__header"> <div class="chat-pc__header">
<h4 class="ml-24">{{ applicationDetail?.name }}</h4> <h4 class="ml-24">{{ applicationDetail?.name }}</h4>
</div> </div>
@ -65,20 +65,38 @@
</div> </div>
</div> </div>
</div> </div>
<div class="collapse">
<el-button size="small" @click="isCollapse = !isCollapse">
<el-icon> <component :is="isCollapse ? 'Fold' : 'Expand'" /></el-icon>
</el-button>
</div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, onMounted, nextTick } from 'vue' import { reactive, ref, onMounted, nextTick, computed } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import applicationApi from '@/api/application' import applicationApi from '@/api/application'
import useStore from '@/stores' import useStore from '@/stores'
import useResize from '@/layout/hooks/useResize'
useResize()
const route = useRoute() const route = useRoute()
const { const {
params: { accessToken } params: { accessToken }
} = route as any } = route as any
const { application, user, log } = useStore() const { application, user, log, common } = useStore()
const isCollapse = ref(false)
const classObj = computed(() => {
return {
mobile: common.isMobile(),
hideLeft: !isCollapse.value,
openLeft: isCollapse.value
}
})
const newObj = { const newObj = {
id: 'new', id: 'new',
@ -149,6 +167,9 @@ function newChat() {
} }
currentChatId.value = 'new' currentChatId.value = 'new'
currentChatName.value = '新建对话' currentChatName.value = '新建对话'
if (common.isMobile()) {
isCollapse.value = false
}
} }
function getChatLog(id: string) { function getChatLog(id: string) {
@ -198,6 +219,9 @@ const clickListHandle = (item: any) => {
getChatRecord() getChatRecord()
} }
} }
if (common.isMobile()) {
isCollapse.value = false
}
} }
function refresh(id: string) { function refresh(id: string) {
@ -247,7 +271,6 @@ onMounted(() => {
} }
.right-height { .right-height {
height: calc(100vh - var(--app-header-height) * 2 - 24px); height: calc(100vh - var(--app-header-height) * 2 - 24px);
overflow: scroll;
} }
} }
@ -278,5 +301,44 @@ onMounted(() => {
max-width: var(--app-chat-width, 860px); max-width: var(--app-chat-width, 860px);
margin: 0 auto; margin: 0 auto;
} }
.collapse {
display: none;
}
}
//
.mobile {
.chat-pc {
&__right {
width: 100%;
}
&__left {
display: none;
width: 0;
}
}
.collapse {
display: block;
position: fixed;
bottom: 90px;
z-index: 99;
}
&.openLeft {
.chat-pc {
&__left {
display: block;
position: fixed;
width: 100%;
z-index: 99;
height: calc(100vh - var(--app-header-height) + 6px);
}
}
.collapse {
display: block;
position: absolute;
bottom: 90px;
right: 0;
z-index: 99;
}
}
} }
</style> </style>

View File

@ -86,7 +86,7 @@ import { useRoute } from 'vue-router'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import documentApi from '@/api/document' import documentApi from '@/api/document'
import { MsgSuccess } from '@/utils/message' import { MsgSuccess } from '@/utils/message'
import { hitHandlingMethod } from '../utils' import { hitHandlingMethod } from '@/enums/document'
const route = useRoute() const route = useRoute()
const { const {

View File

@ -127,7 +127,7 @@
</div> </div>
</template> </template>
<template #default="{ row }"> <template #default="{ row }">
{{ hitHandlingMethod[row.hit_handling_method] }} {{ hitHandlingMethod[row.hit_handling_method as keyof typeof hitHandlingMethod] }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="create_time" label="创建时间" width="175"> <el-table-column prop="create_time" label="创建时间" width="175">
@ -227,7 +227,7 @@ import SyncWebDialog from '@/views/dataset/component/SyncWebDialog.vue'
import SelectDatasetDialog from './component/SelectDatasetDialog.vue' import SelectDatasetDialog from './component/SelectDatasetDialog.vue'
import { numberFormat } from '@/utils/utils' import { numberFormat } from '@/utils/utils'
import { datetimeFormat } from '@/utils/time' import { datetimeFormat } from '@/utils/time'
import { hitHandlingMethod } from './utils' import { hitHandlingMethod } from '@/enums/document'
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message' import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
import useStore from '@/stores' import useStore from '@/stores'
const router = useRouter() const router = useRouter()

View File

@ -1,4 +0,0 @@
export const hitHandlingMethod: any = {
optimization: '模型优化',
directly_return: '直接回答'
}

View File

@ -60,7 +60,6 @@ import { ref, watch, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { MsgSuccess } from '@/utils/message' import { MsgSuccess } from '@/utils/message'
import TeamApi from '@/api/team' import TeamApi from '@/api/team'
// import UserApi from '@/api/user'
const emit = defineEmits(['refresh']) const emit = defineEmits(['refresh'])
@ -70,11 +69,9 @@ const memberForm = ref({
users: [] users: []
}) })
// const SelectRemoteRef = ref()
const addMemberFormRef = ref<FormInstance>() const addMemberFormRef = ref<FormInstance>()
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
// const userOptions = ref<Array<any>>([])
const rules = ref<FormRules>({ const rules = ref<FormRules>({
users: [ users: [
@ -96,21 +93,6 @@ watch(dialogVisible, (bool) => {
} }
}) })
// const remoteMethod = (query: string) => {
// if (query) {
// setTimeout(() => {
// getUser(query)
// }, 200)
// } else {
// userOptions.value = []
// }
// }
// const changeSelectHandle = () => {
// SelectRemoteRef.value.query = ''
// SelectRemoteRef.value.blur()
// }
const open = () => { const open = () => {
dialogVisible.value = true dialogVisible.value = true
} }

View File

@ -46,8 +46,8 @@
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox <el-checkbox
:disabled="props.manage" :disabled="props.manage"
v-model="row.operate[MANAGE]" v-model="row.operate[TeamEnum.MANAGE]"
@change="checkedOperateChange(MANAGE, row)" @change="checkedOperateChange(TeamEnum.MANAGE, row)"
/> />
</template> </template>
</el-table-column> </el-table-column>
@ -62,8 +62,8 @@
<template #default="{ row }"> <template #default="{ row }">
<el-checkbox <el-checkbox
:disabled="props.manage" :disabled="props.manage"
v-model="row.operate[USE]" v-model="row.operate[TeamEnum.USE]"
@change="checkedOperateChange(USE, row)" @change="checkedOperateChange(TeamEnum.USE, row)"
/> />
</template> </template>
</el-table-column> </el-table-column>
@ -72,7 +72,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue' import { ref, onMounted, watch, computed } from 'vue'
import { MANAGE, USE, DATASET, APPLICATION } from './../utils' import { TeamEnum } from '@/enums/team'
const props = defineProps({ const props = defineProps({
data: { data: {
@ -85,13 +85,13 @@ const props = defineProps({
manage: Boolean manage: Boolean
}) })
const isDataset = computed(() => props.type === DATASET) const isDataset = computed(() => props.type === TeamEnum.DATASET)
const isApplication = computed(() => props.type === APPLICATION) const isApplication = computed(() => props.type === TeamEnum.APPLICATION)
const emit = defineEmits(['update:data']) const emit = defineEmits(['update:data'])
const allChecked: any = ref({ const allChecked: any = ref({
[MANAGE]: false, [TeamEnum.MANAGE]: false,
[USE]: false [TeamEnum.USE]: false
}) })
const filterText = ref('') const filterText = ref('')
@ -123,10 +123,10 @@ function handleCheckAllChange(val: string | number | boolean, Name: string | num
} }
} }
function checkedOperateChange(Name: string | number, row: any) { function checkedOperateChange(Name: string | number, row: any) {
if (Name === MANAGE && row.operate[MANAGE]) { if (Name === TeamEnum.MANAGE && row.operate[TeamEnum.MANAGE]) {
props.data.map((item: any) => { props.data.map((item: any) => {
if (item.id === row.id) { if (item.id === row.id) {
item.operate[USE] = true item.operate[TeamEnum.USE] = true
} }
}) })
} }
@ -145,4 +145,3 @@ onMounted(() => {
}) })
</script> </script>
<style lang="scss" scope></style> <style lang="scss" scope></style>
../utils

View File

@ -82,7 +82,7 @@ import type { TeamMember } from '@/api/type/team'
import CreateMemberDialog from './component/CreateMemberDialog.vue' import CreateMemberDialog from './component/CreateMemberDialog.vue'
import PermissionSetting from './component/PermissionSetting.vue' import PermissionSetting from './component/PermissionSetting.vue'
import { MsgSuccess, MsgConfirm } from '@/utils/message' import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { DATASET, APPLICATION, isManage } from './utils' import { TeamEnum } from '@/enums/team'
const CreateMemberRef = ref<InstanceType<typeof CreateMemberDialog>>() const CreateMemberRef = ref<InstanceType<typeof CreateMemberDialog>>()
const loading = ref(false) const loading = ref(false)
@ -94,18 +94,18 @@ const currentType = ref<String>('')
const filterText = ref('') const filterText = ref('')
const activeName = ref(DATASET) const activeName = ref(TeamEnum.DATASET)
const tableHeight = ref(0) const tableHeight = ref(0)
const settingTags = reactive([ const settingTags = reactive([
{ {
label: '知识库', label: '知识库',
value: DATASET, value: TeamEnum.DATASET,
data: [] as any data: [] as any
}, },
{ {
label: '应用', label: '应用',
value: APPLICATION, value: TeamEnum.APPLICATION,
data: [] as any data: [] as any
} }
]) ])
@ -118,6 +118,10 @@ watch(filterText, (val) => {
} }
}) })
function isManage(type: String) {
return type === 'manage'
}
function submitPermissions() { function submitPermissions() {
rLoading.value = true rLoading.value = true
const obj: any = { const obj: any = {

View File

@ -1,8 +0,0 @@
export const MANAGE = 'MANAGE'
export const USE = 'USE'
export const DATASET = 'DATASET'
export const APPLICATION = 'APPLICATION'
export function isManage(type: String) {
return type === 'manage'
}