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

This commit is contained in:
wangdan-fit2cloud 2024-05-22 14:54:37 +08:00
parent 7d2f4fe7c7
commit 49451b4c0a
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 { DeviceType } from '@/enums/common'
export interface commonTypes {
breadcrumb: any
paginationConfig: any | null
search: any
device: string
}
const useCommonStore = defineStore({
@ -12,7 +14,8 @@ const useCommonStore = defineStore({
breadcrumb: null,
// 搜索和分页缓存
paginationConfig: {},
search: {}
search: {},
device: DeviceType.Desktop
}),
actions: {
saveBreadcrumb(data: any) {
@ -23,6 +26,12 @@ const useCommonStore = defineStore({
},
saveCondition(val: string, data: any) {
this.search[val] = data
},
toggleDevice(value: DeviceType) {
this.device = value
},
isMobile() {
return this.device === DeviceType.Mobile
}
}
})

View File

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

View File

@ -1,5 +1,5 @@
<template>
<div class="chat-pc" v-loading="loading">
<div class="chat-pc" :class="classObj" v-loading="loading">
<div class="chat-pc__header">
<h4 class="ml-24">{{ applicationDetail?.name }}</h4>
</div>
@ -65,20 +65,38 @@
</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>
</template>
<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 applicationApi from '@/api/application'
import useStore from '@/stores'
import useResize from '@/layout/hooks/useResize'
useResize()
const route = useRoute()
const {
params: { accessToken }
} = 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 = {
id: 'new',
@ -149,6 +167,9 @@ function newChat() {
}
currentChatId.value = 'new'
currentChatName.value = '新建对话'
if (common.isMobile()) {
isCollapse.value = false
}
}
function getChatLog(id: string) {
@ -198,6 +219,9 @@ const clickListHandle = (item: any) => {
getChatRecord()
}
}
if (common.isMobile()) {
isCollapse.value = false
}
}
function refresh(id: string) {
@ -247,7 +271,6 @@ onMounted(() => {
}
.right-height {
height: calc(100vh - var(--app-header-height) * 2 - 24px);
overflow: scroll;
}
}
@ -278,5 +301,44 @@ onMounted(() => {
max-width: var(--app-chat-width, 860px);
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>

View File

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

View File

@ -127,7 +127,7 @@
</div>
</template>
<template #default="{ row }">
{{ hitHandlingMethod[row.hit_handling_method] }}
{{ hitHandlingMethod[row.hit_handling_method as keyof typeof hitHandlingMethod] }}
</template>
</el-table-column>
<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 { numberFormat } from '@/utils/utils'
import { datetimeFormat } from '@/utils/time'
import { hitHandlingMethod } from './utils'
import { hitHandlingMethod } from '@/enums/document'
import { MsgSuccess, MsgConfirm, MsgError } from '@/utils/message'
import useStore from '@/stores'
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 { MsgSuccess } from '@/utils/message'
import TeamApi from '@/api/team'
// import UserApi from '@/api/user'
const emit = defineEmits(['refresh'])
@ -70,11 +69,9 @@ const memberForm = ref({
users: []
})
// const SelectRemoteRef = ref()
const addMemberFormRef = ref<FormInstance>()
const loading = ref<boolean>(false)
// const userOptions = ref<Array<any>>([])
const rules = ref<FormRules>({
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 = () => {
dialogVisible.value = true
}

View File

@ -46,8 +46,8 @@
<template #default="{ row }">
<el-checkbox
:disabled="props.manage"
v-model="row.operate[MANAGE]"
@change="checkedOperateChange(MANAGE, row)"
v-model="row.operate[TeamEnum.MANAGE]"
@change="checkedOperateChange(TeamEnum.MANAGE, row)"
/>
</template>
</el-table-column>
@ -62,8 +62,8 @@
<template #default="{ row }">
<el-checkbox
:disabled="props.manage"
v-model="row.operate[USE]"
@change="checkedOperateChange(USE, row)"
v-model="row.operate[TeamEnum.USE]"
@change="checkedOperateChange(TeamEnum.USE, row)"
/>
</template>
</el-table-column>
@ -72,7 +72,7 @@
</template>
<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import { MANAGE, USE, DATASET, APPLICATION } from './../utils'
import { TeamEnum } from '@/enums/team'
const props = defineProps({
data: {
@ -85,13 +85,13 @@ const props = defineProps({
manage: Boolean
})
const isDataset = computed(() => props.type === DATASET)
const isApplication = computed(() => props.type === APPLICATION)
const isDataset = computed(() => props.type === TeamEnum.DATASET)
const isApplication = computed(() => props.type === TeamEnum.APPLICATION)
const emit = defineEmits(['update:data'])
const allChecked: any = ref({
[MANAGE]: false,
[USE]: false
[TeamEnum.MANAGE]: false,
[TeamEnum.USE]: false
})
const filterText = ref('')
@ -123,10 +123,10 @@ function handleCheckAllChange(val: string | number | boolean, Name: string | num
}
}
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) => {
if (item.id === row.id) {
item.operate[USE] = true
item.operate[TeamEnum.USE] = true
}
})
}
@ -145,4 +145,3 @@ onMounted(() => {
})
</script>
<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 PermissionSetting from './component/PermissionSetting.vue'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
import { DATASET, APPLICATION, isManage } from './utils'
import { TeamEnum } from '@/enums/team'
const CreateMemberRef = ref<InstanceType<typeof CreateMemberDialog>>()
const loading = ref(false)
@ -94,18 +94,18 @@ const currentType = ref<String>('')
const filterText = ref('')
const activeName = ref(DATASET)
const activeName = ref(TeamEnum.DATASET)
const tableHeight = ref(0)
const settingTags = reactive([
{
label: '知识库',
value: DATASET,
value: TeamEnum.DATASET,
data: [] as any
},
{
label: '应用',
value: APPLICATION,
value: TeamEnum.APPLICATION,
data: [] as any
}
])
@ -118,6 +118,10 @@ watch(filterText, (val) => {
}
})
function isManage(type: String) {
return type === 'manage'
}
function submitPermissions() {
rLoading.value = true
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'
}