Merge branch 'master' of http://192.168.5.5:10010/r/web/flow_web
| | |
| | | proxy: { |
| | | '/base': { |
| | | // target: 'http://aiotlink.com:8189', |
| | | target: 'http://192.168.20.116:8089', |
| | | // target: 'http://192.168.20.158:8089', |
| | | //target: 'http://192.168.20.116:8089', |
| | | target: 'http://192.168.20.158:8089', |
| | | changeOrigin: true, |
| | | ws: true, |
| | | // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), |
| | |
| | | // secure: false |
| | | }, |
| | | '/api': { |
| | | target: 'http://192.168.20.116:8089', |
| | | // target: 'http://192.168.20.158:8089', |
| | | // target: 'http://aiotlink.com:8189', |
| | | //target: 'http://192.168.20.116:8089', |
| | | target: 'http://192.168.20.158:8089', |
| | | changeOrigin: true, |
| | | ws: true, |
| | | // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), |
| | | }, |
| | | '/api/v1': { |
| | | target: 'http://192.168.20.116:8089', |
| | | // target: 'http://192.168.20.158:8089', |
| | | // target: 'http://aiotlink.com:8189', |
| | | //target: 'http://192.168.20.116:8089', |
| | | target: 'http://192.168.20.158:8089', |
| | | changeOrigin: true, |
| | | ws: true, |
| | | // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), |
New file |
| | |
| | | import axios from 'axios'; |
| | | |
| | | export interface ISessionListResult { |
| | | code: number; |
| | | msg: string; |
| | | data: any; |
| | | } |
| | | // 会话列表 |
| | | // export function sessionListApi(dialog_id) { |
| | | // return axios.get<ISessionListResult>( |
| | | // "/api/conversation/list?modeltype=localragflow&dialogid=" + dialog_id |
| | | // ); |
| | | // } |
| | | // 删除会话 |
| | | // export function deleteSessionApi(conversation_ids: string[]) { |
| | | // return axios.post<ISessionListResult>( |
| | | // '/api/conversation/del?modeltype=localragflow', |
| | | // { conversation_ids } |
| | | // ); |
| | | // } |
| | | // 新增会话 |
| | | // export function addSessionApi(params: any) { |
| | | // return axios.get<ISessionListResult>( |
| | | // '/api/getConId/kdwithai?platform=localragflow', |
| | | // { params } |
| | | // ); |
| | | // } |
| | | // 获取智能助手列表 |
| | | // export function getDialogListApi() { |
| | | // return axios.get<ISessionListResult>('/api/dialog/list'); |
| | | // } |
| | | |
| | | // 聊天 |
| | | export function chatAgentApi(data) { |
| | | return axios.post( |
| | | '/api/v1/canvas/completion', |
| | | data |
| | | ); |
| | | } |
| | | |
| | | // 获取会话详情 |
| | | export function getAgentSessionDetailsApi(id: string) { |
| | | return axios.get( |
| | | '/api/v1/canvas/get/' + id, |
| | | {} |
| | | ); |
| | | } |
| | | // 设置 |
| | | export function agentSetApi(data) { |
| | | return axios.post( |
| | | '/api/v1/canvas/set', |
| | | data |
| | | ); |
| | | } |
| | | // 重置 |
| | | export function agentResetApi(data) { |
| | | return axios.post( |
| | | '/api/v1/canvas/reset', |
| | | data |
| | | ); |
| | | } |
| | |
| | | total: number; |
| | | } |
| | | |
| | | export interface Role { |
| | | roleId: string; |
| | | createTime: string; |
| | | updateTime: string; |
| | | roleName: string; |
| | | remark: string; |
| | | iconCls: string; |
| | | roleSort: string; |
| | | status: string; |
| | | roleKey: string; |
| | | dataScope: string; |
| | | dept: any; |
| | | resources: any; |
| | | } |
| | | |
| | | export function RoleList(params: Pagination) { |
| | | return axios.get<Result<Role[]>>('/base/system/role/list', { params }); |
| | | } |
| | | |
| | | export function RoleDelete(id) { |
| | | return axios.delete('/base/system/role/' + id); |
| | | } |
| | | |
| | | export function RoleEdit(role) { |
| | | return axios.put('/base/system/role', { role }); |
| | | } |
| | | |
| | | export function RoleAdd(role) { |
| | | return axios.post('/base/system/role', { role }); |
| | | } |
| | | |
| | | export function Rolestatus(roleId, status) { |
| | | return axios.put('/base/system/role/changeStatus', { |
| | | roleId: roleId, |
| | | status: status, |
| | | }); |
| | | } |
| | | |
| | | export function UserList(params: Pagination) { |
| | | return axios.get<Result<User[]>>('/base/system/user/list', { params }); |
| | | } |
| | |
| | | import localeUser from '@/views/authority/users/locale/en-US'; |
| | | import localeOrganization from '@/views/authority/organization/locale/en-US'; |
| | | import localeResource from '@/views/authority/resource/locale/en-US'; |
| | | import localeRole from '@/views/authority/role/locale/en-US'; |
| | | |
| | | import localeMonitor from '@/views/dashboard/monitor/locale/en-US'; |
| | | |
| | |
| | | ...localeUser, |
| | | ...localeOrganization, |
| | | ...localeResource, |
| | | ...localeRole, |
| | | |
| | | ...localeMonitor, |
| | | ...localeSearchTable, |
| | |
| | | import localeUser from '@/views/authority/users/locale/zh-CN'; |
| | | import localeOrganization from '@/views/authority/organization/locale/zh-CN'; |
| | | import localeResource from '@/views/authority/resource/locale/zh-CN'; |
| | | import localeRole from '@/views/authority/role/locale/zh-CN'; |
| | | |
| | | import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN'; |
| | | |
| | |
| | | ...localeUser, |
| | | ...localeOrganization, |
| | | ...localeResource, |
| | | ...localeRole, |
| | | |
| | | ...localeMonitor, |
| | | ...localeSearchTable, |
| | |
| | | roles: ['*'], |
| | | }, |
| | | }, |
| | | { |
| | | path: 'role', |
| | | name: 'role', |
| | | component: () => import('@/views/authority/role/index.vue'), |
| | | meta: { |
| | | locale: 'menu.role.title', |
| | | requiresAuth: true, |
| | | roles: ['*'], |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | |
New file |
| | |
| | | <template> |
| | | <div class="container"> |
| | | <authheader :items="menuTips"></authheader> |
| | | <a-card ref="account" class="general-card"> |
| | | <div class="table-page-search-wrapper"> |
| | | <div class="search-wrapper"> |
| | | <div> |
| | | <a-input |
| | | v-model="formModel.name" |
| | | :style="{ width: '320px' }" |
| | | :placeholder="$t('请输入')" |
| | | /> |
| | | </div> |
| | | <div> |
| | | <a-button |
| | | type="primary" |
| | | @click="search" |
| | | style="margin-right: 20px; margin-left: 10px" |
| | | > |
| | | <template #icon> |
| | | <icon-search /> |
| | | </template> |
| | | {{ $t('searchTable.form.search') }} |
| | | </a-button> |
| | | <a-button @click="reset"> |
| | | <template #icon> |
| | | <icon-refresh /> |
| | | </template> |
| | | {{ $t('searchTable.form.reset') }} |
| | | </a-button> |
| | | </div> |
| | | </div> |
| | | <div class="search-wrapper"> |
| | | <div> |
| | | <a-space> |
| | | <a-button type="primary" :align="'right'" @click="operation(0)" |
| | | >+ 新建角色</a-button |
| | | > |
| | | </a-space> |
| | | </div> |
| | | <div class="wrapper-icon"> |
| | | <a-tooltip :content="$t('searchTable.actions.refresh')"> |
| | | <div class="action-icon" @click="search"> |
| | | <icon-refresh size="18" /> |
| | | </div> |
| | | </a-tooltip> |
| | | <a-dropdown @select="handleSelectDensity"> |
| | | <a-tooltip :content="$t('searchTable.actions.density')"> |
| | | <div class="action-icon"> |
| | | <icon-line-height size="18" /> |
| | | </div> |
| | | </a-tooltip> |
| | | <template #content> |
| | | <a-doption |
| | | v-for="item in densityList" |
| | | :key="item.value" |
| | | :value="item.value" |
| | | :class="{ active: item.value === size }" |
| | | > |
| | | <span>{{ item.name }}</span> |
| | | </a-doption> |
| | | </template> |
| | | </a-dropdown> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <a-table |
| | | row-key="id" |
| | | :loading="loading" |
| | | :pagination="pagination" |
| | | :columns="columns" |
| | | :data="renderData" |
| | | :bordered="false" |
| | | :size="size" |
| | | @page-change="onPageChange" |
| | | > |
| | | <template #index="{ rowIndex }"> |
| | | {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} |
| | | </template> |
| | | <template #dept="{ record }">{{ |
| | | record.dept ? record.dept.deptName : '' |
| | | }}</template> |
| | | <template #status="{ record }"> |
| | | <a-switch |
| | | checked-value="1" |
| | | unchecked-value="0" |
| | | @change="statusChange(record.status, record)" |
| | | v-model="record.status" |
| | | /> |
| | | </template> |
| | | <template #operations="{ record }"> |
| | | <a-space> |
| | | <a-button type="outline" @click="operation(2, record)" |
| | | >编辑</a-button |
| | | > |
| | | <a-popconfirm |
| | | content="Are you sure you want to delete?" |
| | | type="success" |
| | | @ok="operation(3, record)" |
| | | > |
| | | <a-button type="outline" status="danger">删除</a-button> |
| | | </a-popconfirm> |
| | | <a-button |
| | | type="dashed" |
| | | status="warning" |
| | | @click="operation(4, record)" |
| | | >权限配置</a-button |
| | | > |
| | | <a-button status="success" @click="operation(5, record)" |
| | | >部门配置</a-button |
| | | > |
| | | </a-space> |
| | | </template> |
| | | </a-table> |
| | | </a-card> |
| | | <a-modal |
| | | v-model:visible="visible" |
| | | :title="save" |
| | | @cancel="handleCancel(1)" |
| | | @ok="editHandleOk" |
| | | > |
| | | <a-form :model="editform"> |
| | | <a-form-item field="roleName" label="角色名"> |
| | | <a-input v-model="editform.roleName" /> |
| | | </a-form-item> |
| | | <a-form-item field="roleKey" label="权限字符串"> |
| | | <a-input v-model="editform.roleKey" /> |
| | | </a-form-item> |
| | | <a-form-item field="remark" label="备注"> |
| | | <a-input v-model="editform.remark" /> |
| | | </a-form-item> |
| | | </a-form> |
| | | </a-modal> |
| | | <a-modal |
| | | width="50%" |
| | | v-model:visible="deptvisible" |
| | | title="部门配置" |
| | | @cancel="handleCancel(2)" |
| | | @ok="editDeptHandleOk" |
| | | > |
| | | <div :style="{ display: 'flex' }"> |
| | | <a-card |
| | | :style="{ 'width': '460px', 'height': '500px', 'overflow-y': 'auto' }" |
| | | title="机构" |
| | | hoverable |
| | | > |
| | | <a-tree |
| | | class="tree-demo" |
| | | v-model:checked-keys="checkedKeys" |
| | | v-model:expanded-keys="expandKdys" |
| | | :checkable="true" |
| | | :data="treeData" |
| | | :show-line="showLine" |
| | | @check="onCheck" |
| | | :fieldNames="{ |
| | | key: 'deptId', |
| | | title: 'deptName', |
| | | children: 'children', |
| | | }" |
| | | :check-strictly="checkStrictly" |
| | | > |
| | | </a-tree> |
| | | </a-card> |
| | | <a-card class="card-demo" title="用户所属机构" hoverable> |
| | | <a-space wrap> |
| | | <a-tag |
| | | v-for="(tag, index) of checkStrictly" |
| | | :key="tag.deptId" |
| | | @close="handleRemove(tag)" |
| | | > |
| | | {{ tag.deptName }} |
| | | </a-tag> |
| | | </a-space> |
| | | </a-card> |
| | | </div> |
| | | </a-modal> |
| | | <a-modal |
| | | width="30%" |
| | | v-model:visible="resourcevisible" |
| | | title="权限配置" |
| | | @cancel="handleCancel(3)" |
| | | @ok="editResourceHandleOk" |
| | | > |
| | | <div :style="{ 'display': 'flex', 'flex-direction': 'column' }"> |
| | | <a-tabs |
| | | :style="{ 'width': '100%', 'height': '500px', 'overflow-y': 'auto' }" |
| | | > |
| | | <a-tab-pane key="1"> |
| | | <template #title> |
| | | <icon-calendar /> |
| | | 菜单 |
| | | </template> |
| | | <a-tree |
| | | class="tree-demo" |
| | | v-model:checked-keys="checkedKeysMenu" |
| | | v-model:expanded-keys="expandKdysMenu" |
| | | :checkable="true" |
| | | :data="treeDataMenu" |
| | | :show-line="showLineMenu" |
| | | @check="onCheckMenu" |
| | | :fieldNames="{ |
| | | key: 'menuId', |
| | | title: 'menuName', |
| | | children: 'children', |
| | | }" |
| | | :check-strictly="checkStrictlyMenu" |
| | | > |
| | | </a-tree> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="2"> |
| | | <template #title> |
| | | <icon-clock-circle /> |
| | | 知识库 |
| | | </template> |
| | | <a-space direction="vertical" size="large"> |
| | | <a-checkbox-group |
| | | v-model="checkedKeysKnowledge" |
| | | direction="vertical" |
| | | @change="onCheckKnowledge" |
| | | > |
| | | <a-checkbox |
| | | v-for="(knowledg, index) of knowledgeList" |
| | | :value="knowledg.id" |
| | | :lable="knowledg.name" |
| | | @change="onCheckKnowledge" |
| | | > |
| | | {{ knowledg.name }} |
| | | </a-checkbox> |
| | | </a-checkbox-group> |
| | | </a-space> |
| | | </a-tab-pane> |
| | | <a-tab-pane key="3"> |
| | | <template #title> |
| | | <icon-user /> |
| | | 智能体 |
| | | </template> |
| | | <a-checkbox-group |
| | | v-model="checkedKeysDialog" |
| | | direction="vertical" |
| | | @change="onCheckDialog" |
| | | > |
| | | <a-checkbox |
| | | v-for="(dialog, index) of DialogsList" |
| | | :value="dialog.id" |
| | | :lable="dialog.name" |
| | | @change="onCheckDialog" |
| | | > |
| | | {{ dialog.name }} |
| | | </a-checkbox> |
| | | </a-checkbox-group> |
| | | </a-tab-pane> |
| | | </a-tabs> |
| | | <a-card |
| | | :style="{ |
| | | 'width': '100%', |
| | | 'height': '200px', |
| | | 'overflow-y': 'auto', |
| | | 'margin': '1px', |
| | | }" |
| | | class="card-demo" |
| | | title="用户所有权限" |
| | | hoverable |
| | | > |
| | | <a-space wrap> |
| | | 菜单功能: |
| | | <a-tag |
| | | v-for="(tag, index) of checkStrictlyMenu" |
| | | :key="tag.menuId" |
| | | @close="handleMenuRemove(tag)" |
| | | > |
| | | {{ tag.menuName }} |
| | | </a-tag> |
| | | </a-space> |
| | | <a-divider /> |
| | | <a-space wrap> |
| | | 知识库: |
| | | <a-tag |
| | | v-for="(tag, index) of checkStrictlyKnowledge" |
| | | :key="tag.knowledgeId" |
| | | @close="handleKnowledgeRemove(tag)" |
| | | > |
| | | {{ tag.knowledgeName }} |
| | | </a-tag> |
| | | </a-space> |
| | | <a-divider /> |
| | | <a-space wrap> |
| | | 智能体: |
| | | <a-tag |
| | | v-for="(tag, index) of checkStrictlyDialog" |
| | | :key="tag.dialogId" |
| | | @close="handleDialogRemove(tag)" |
| | | > |
| | | {{ tag.dialogName }} |
| | | </a-tag> |
| | | </a-space> |
| | | </a-card> |
| | | </div> |
| | | </a-modal> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import { computed, reactive, ref } from 'vue'; |
| | | import { useI18n } from 'vue-i18n'; |
| | | import useLoading from '@/hooks/loading'; |
| | | import { Pagination } from '@/types/global'; |
| | | import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; |
| | | import { |
| | | DialogList, |
| | | KnowledgeList, |
| | | OrganizationList, |
| | | ResourceList, Role, RoleAdd, RoleDelete, RoleEdit, RoleList, Rolestatus, |
| | | User, |
| | | UserAdd, |
| | | UserChangePwd, |
| | | UserDelete, |
| | | UserEdit, |
| | | UserList, |
| | | Userstatus |
| | | } from "@/api/authority"; |
| | | import { Modal } from '@arco-design/web-vue'; |
| | | import Authheader from '@/views/authority/components/authheader.vue'; |
| | | |
| | | let treeData = ref([]); |
| | | let checkedKeys = ref([]); |
| | | let expandKdys = ref([]); |
| | | let checkStrictly = ref([]); |
| | | |
| | | let treeDataMenu = ref([]); |
| | | let checkedKeysMenu = ref([]); |
| | | let expandKdysMenu = ref([]); |
| | | let checkStrictlyMenu = ref([]); |
| | | |
| | | let checkedKeysKnowledge = ref([]); |
| | | let checkStrictlyKnowledge = ref([]); |
| | | |
| | | let checkedKeysDialog = ref([]); |
| | | let checkStrictlyDialog = ref([]); |
| | | |
| | | let knowledgeList = ref([]); |
| | | let DialogsList = ref([]); |
| | | |
| | | let menuTips = ref(['权限管理', '角色']); |
| | | type SizeProps = 'mini' | 'small' | 'medium' | 'large'; |
| | | const account = ref(null); |
| | | const generateFormModel = () => { |
| | | return { |
| | | name: '', |
| | | }; |
| | | }; |
| | | let showLine = ref(true); |
| | | const { loading, setLoading } = useLoading(true); |
| | | const { t } = useI18n(); |
| | | let save = ref('新增'); |
| | | let renderData = ref<Role[]>([]); |
| | | let formModel = ref(generateFormModel()); |
| | | let editform = ref<Role>({ |
| | | createTime: "", |
| | | dataScope: "", |
| | | iconCls: "", |
| | | remark: "", |
| | | roleId: "", |
| | | roleKey: "", |
| | | roleName: "", |
| | | roleSort: "0", |
| | | status: "", |
| | | updateTime: "" |
| | | }); |
| | | |
| | | let size = ref<SizeProps>('medium'); |
| | | let visible = ref(false); |
| | | let deptvisible = ref(false); |
| | | let resourcevisible = ref(false); |
| | | let selectRole = ref({}); |
| | | |
| | | const onCheck = (newCheckedKeys, event) => { |
| | | let o = { deptId: event.node.deptId, deptName: event.node.deptName }; |
| | | if (event.checked) { |
| | | checkStrictly.value.push(o); |
| | | } else { |
| | | checkStrictly.value.forEach((val, idx, array) => { |
| | | // val: 当前值 |
| | | if (val.deptId == event.node.deptId) { |
| | | checkStrictly.value.splice(idx, 1); |
| | | return true; |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | const onCheckMenu = (newCheckedKeys, event) => { |
| | | let o = { menuId: event.node.menuId, menuName: event.node.menuName }; |
| | | if (event.checked) { |
| | | checkStrictlyMenu.value.push(o); |
| | | } else { |
| | | checkStrictlyMenu.value.forEach((val, idx, array) => { |
| | | // val: 当前值 |
| | | if (val.menuId == event.node.menuId) { |
| | | checkStrictlyMenu.value.splice(idx, 1); |
| | | return true; |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | const onCheckKnowledge = (newCheckedKeys, event) => { |
| | | let o = { |
| | | knowledgeId: event.target.value, |
| | | knowledgeName: event.target.labels[0].innerText, |
| | | }; |
| | | if (event.target.checked) { |
| | | checkStrictlyKnowledge.value.push(o); |
| | | } else { |
| | | checkStrictlyKnowledge.value.forEach((val, idx, array) => { |
| | | // val: 当前值 |
| | | if (val.knowledgeId == event.target.value) { |
| | | checkStrictlyKnowledge.value.splice(idx, 1); |
| | | return true; |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | const onCheckDialog = (newCheckedKeys, event) => { |
| | | let o = { |
| | | dialogId: event.target.value, |
| | | dialogName: event.target.labels[0].innerText, |
| | | }; |
| | | if (event.target.checked) { |
| | | checkStrictlyDialog.value.push(o); |
| | | } else { |
| | | checkStrictlyDialog.value.forEach((val, idx, array) => { |
| | | // val: 当前值 |
| | | if (val.dialogId == event.target.value) { |
| | | checkStrictlyDialog.value.splice(idx, 1); |
| | | return true; |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const handleRemove = (key) => { |
| | | checkStrictly.value = checkStrictly.value.filter((tag) => tag !== key); |
| | | }; |
| | | const handleMenuRemove = (key) => { |
| | | checkStrictlyMenu.value = checkStrictlyMenu.value.filter( |
| | | (tag) => tag !== key |
| | | ); |
| | | }; |
| | | const handleKnowledgeRemove = (key) => { |
| | | checkStrictlyKnowledge.value = checkStrictlyKnowledge.value.filter( |
| | | (tag) => tag !== key |
| | | ); |
| | | }; |
| | | const handleDialogRemove = (key) => { |
| | | checkStrictlyDialog.value = checkStrictlyDialog.value.filter( |
| | | (tag) => tag !== key |
| | | ); |
| | | }; |
| | | |
| | | const basePagination: Pagination = { |
| | | current: 1, |
| | | pageSize: 15, |
| | | }; |
| | | const pagination = reactive({ |
| | | ...basePagination, |
| | | }); |
| | | |
| | | const densityList = computed(() => [ |
| | | { |
| | | name: t('searchTable.size.mini'), |
| | | value: 'mini', |
| | | }, |
| | | { |
| | | name: t('searchTable.size.small'), |
| | | value: 'small', |
| | | }, |
| | | { |
| | | name: t('searchTable.size.medium'), |
| | | value: 'medium', |
| | | }, |
| | | { |
| | | name: t('searchTable.size.large'), |
| | | value: 'large', |
| | | }, |
| | | ]); |
| | | const columns = computed<TableColumnData[]>(() => [ |
| | | { |
| | | title: t('序号'), |
| | | dataIndex: 'index', |
| | | slotName: 'index', |
| | | }, |
| | | { |
| | | title: t('角色名'), |
| | | dataIndex: 'roleName', |
| | | }, |
| | | { |
| | | title: t('创建时间'), |
| | | dataIndex: 'createTime', |
| | | }, |
| | | { |
| | | title: t('权限字符串'), |
| | | dataIndex: 'roleKey', |
| | | slotName: 'roleKey', |
| | | }, |
| | | { |
| | | title: t('状态'), |
| | | dataIndex: 'status', |
| | | slotName: 'status', |
| | | }, |
| | | { |
| | | title: t('searchTable.columns.operations'), |
| | | dataIndex: 'operations', |
| | | slotName: 'operations', |
| | | }, |
| | | ]); |
| | | |
| | | const statusChange = async (value, record) => { |
| | | await Rolestatus(record.roleId, value).then((res) => {}); |
| | | }; |
| | | |
| | | const handleCancel = (type) => { |
| | | if (type == 1) { |
| | | visible.value = false; |
| | | } |
| | | if (type == 2) { |
| | | deptvisible.value = false; |
| | | } |
| | | if (type == 2) { |
| | | resourcevisible.value = false; |
| | | } |
| | | }; |
| | | |
| | | const editDeptHandleOk = async () => { |
| | | let depts: Array = [], |
| | | role: Role = { roleId: selectRole.value.roleId }; |
| | | checkStrictly.value.forEach((val) => { |
| | | depts.push(val.deptId); |
| | | }); |
| | | role.dept = depts; |
| | | await RoleEdit(role).then((res) => { |
| | | fetchData(); |
| | | }); |
| | | }; |
| | | |
| | | const editResourceHandleOk = async () => { |
| | | let resources: Array = [], |
| | | dialogs: Array = [], |
| | | Knowledges: Array = [], |
| | | role: Role = { roleId: selectRole.value.roleId }; |
| | | checkStrictlyMenu.value.forEach((val) => { |
| | | resources.push(val.menuId); |
| | | }); |
| | | role.resources = resources; |
| | | |
| | | checkStrictlyKnowledge.value.forEach((val) => { |
| | | Knowledges.push(val.knowledgeId); |
| | | }); |
| | | role.knowledges = Knowledges; |
| | | |
| | | checkStrictlyDialog.value.forEach((val) => { |
| | | dialogs.push(val.dialogId); |
| | | }); |
| | | role.dialogs = dialogs; |
| | | |
| | | await RoleEdit(role).then((res) => { |
| | | fetchData(); |
| | | }); |
| | | }; |
| | | |
| | | const editHandleOk = async () => { |
| | | if (editform.value.roleId.length > 0) { |
| | | await RoleEdit({ |
| | | ...editform.value, |
| | | } as unknown as Role).then((res) => { |
| | | fetchData(); |
| | | }); |
| | | } else { |
| | | await RoleAdd({ |
| | | ...editform.value, |
| | | } as unknown as Role).then((res) => { |
| | | fetchData(); |
| | | }); |
| | | } |
| | | }; |
| | | const operation = async (t, record) => { |
| | | if (t == 0) { |
| | | save.value = '新增'; |
| | | visible.value = true; |
| | | editform.value.roleName = ""; |
| | | editform.value.roleKey = ""; |
| | | editform.value.remark = ""; |
| | | } |
| | | //编辑 |
| | | if (t == 2) { |
| | | visible.value = true; |
| | | save.value = '编辑'; |
| | | editform.value.roleId=record.roleId |
| | | editform.value.roleName = record.roleName; |
| | | editform.value.roleKey = record.roleKey; |
| | | editform.value.remark = record.remark; |
| | | } |
| | | //删除 |
| | | if (t == 3) { |
| | | await RoleDelete(record.roleId).then((res) => { |
| | | if (res.code == 200) { |
| | | fetchData(); |
| | | } |
| | | }); |
| | | } |
| | | //权限 |
| | | if (t == 4) { |
| | | resourcevisible.value = true; |
| | | checkedKeysMenu.value = []; |
| | | expandKdysMenu.value = []; |
| | | checkStrictlyMenu.value = []; |
| | | checkStrictlyKnowledge.value = []; |
| | | checkedKeysKnowledge.value = []; |
| | | checkStrictlyDialog.value = []; |
| | | checkedKeysDialog.value = []; |
| | | selectRole.value = record; |
| | | if (record.resources) { |
| | | record.resources.forEach((val) => { |
| | | checkStrictlyMenu.value.push({ |
| | | menuId: val.menuId, |
| | | menuName: val.menuName, |
| | | }); |
| | | checkedKeysMenu.value.push(val.menuId); |
| | | expandKdysMenu.value.push(val.menuId); |
| | | }); |
| | | } |
| | | if (record.knowledges) { |
| | | record.knowledges.forEach((val) => { |
| | | checkStrictlyKnowledge.value.push({ |
| | | knowledgeId: val.id, |
| | | knowledgeName: val.name, |
| | | }); |
| | | checkedKeysKnowledge.value.push(val.id); |
| | | }); |
| | | } |
| | | if (record.dialogs) { |
| | | record.dialogs.forEach((val) => { |
| | | checkStrictlyDialog.value.push({ |
| | | dialogId: val.id, |
| | | dialogName: val.name, |
| | | }); |
| | | checkedKeysDialog.value.push(val.id); |
| | | }); |
| | | } |
| | | } |
| | | //机构 |
| | | if (t == 5) { |
| | | deptvisible.value = true; |
| | | checkedKeys.value = []; |
| | | expandKdys.value = []; |
| | | checkStrictly.value = []; |
| | | selectRole.value = record; |
| | | expandKdys.value.push('0'); |
| | | if (record.dept) { |
| | | record.dept.forEach((val) => { |
| | | checkStrictly.value.push({ |
| | | deptId: val.deptId, |
| | | deptName: val.deptName, |
| | | }); |
| | | checkedKeys.value.push(val.deptId); |
| | | expandKdys.value.push(val.deptId); |
| | | }); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const fetchData = async ( |
| | | params: Pagination = { current: 1, pageSize: 20 } |
| | | ) => { |
| | | setLoading(true); |
| | | try { |
| | | await RoleList(params).then((res) => { |
| | | renderData.value = res.rows; |
| | | console.log(renderData); |
| | | pagination.current = params.current; |
| | | pagination.total = res.total; |
| | | }); |
| | | } catch (err) { |
| | | // you can report use errorHandler or other |
| | | } finally { |
| | | setLoading(false); |
| | | } |
| | | }; |
| | | |
| | | const search = () => { |
| | | fetchData({ |
| | | ...basePagination, |
| | | ...formModel.value, |
| | | } as unknown as Pagination); |
| | | }; |
| | | |
| | | const onPageChange = (current: number) => { |
| | | fetchData({ ...basePagination, current }); |
| | | }; |
| | | |
| | | const OrganizationData = async (key) => { |
| | | await OrganizationList(key).then((res) => { |
| | | treeData.value = [...res.rows]; |
| | | }); |
| | | }; |
| | | const MenuData = async (key) => { |
| | | await ResourceList(key).then((res) => { |
| | | treeDataMenu.value = [...res.rows]; |
| | | }); |
| | | }; |
| | | |
| | | KnowledgeList().then((res) => { |
| | | knowledgeList.value = res.rows; |
| | | }); |
| | | |
| | | DialogList().then((res) => { |
| | | DialogsList.value = res.rows; |
| | | }); |
| | | fetchData(); |
| | | OrganizationData(''); |
| | | MenuData(); |
| | | |
| | | const reset = () => { |
| | | formModel.value = generateFormModel(); |
| | | }; |
| | | |
| | | const handleSelectDensity = ( |
| | | val: string | number | Record<string, any> | undefined, |
| | | e: Event |
| | | ) => { |
| | | size.value = val as SizeProps; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .card-demo { |
| | | width: 460px; |
| | | margin-left: 24px; |
| | | transition-property: all; |
| | | } |
| | | |
| | | .card-demo:hover { |
| | | transform: translateY(-4px); |
| | | } |
| | | .table-page-search-wrapper { |
| | | padding-top: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #e8e8e8; |
| | | .search-wrapper { |
| | | display: flex; |
| | | .wrapper-icon { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-left: 40px; |
| | | // margin-right: 40px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | <style lang="less"> |
| | | .ant-table-wrapper { |
| | | .ant-table-tbody { |
| | | tr { |
| | | td { |
| | | .ant-table-row-cell-break-word { |
| | | .ant-table-column-sorter { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-wrapper { |
| | | display: flex; |
| | | .wrapper-icon { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-left: 40px; |
| | | // margin-right: 40px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | <style lang="less"> |
| | | .ant-table-wrapper { |
| | | .ant-table-tbody { |
| | | tr { |
| | | td { |
| | | .ant-table-row-cell-break-word { |
| | | .ant-table-column-sorter { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | <style lang="less" scoped> |
| | | .table-page-search-wrapper { |
| | | .ant-form-inline { |
| | | :deep(.ant-form-item) { |
| | | display: flex; |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | export default { |
| | | "menu.role.title": "Role", |
| | | }; |
| | | // export default { "menu.user.title": "Account" }; |
New file |
| | |
| | | export default { |
| | | 'menu.role.title': '角色', |
| | | }; |
| | |
| | | > |
| | | <icon-calendar-clock /> |
| | | <span style="font-size: 12px;margin-left: 10px"> |
| | | {{ parseTime(item.create_date) }} |
| | | {{ moment(item.create_date).format('YYYY-MM-DD HH:mm:ss') }} |
| | | </span> |
| | | </div> |
| | | <!-- <div--> |
| | |
| | | import AgentConfig from '@/views/dmx/IntelligentAgent/components/agentConfig.vue'; |
| | | import logo from '../../../assets/images/model.png'; |
| | | import { documentHeight, parseTime } from "@/utils"; |
| | | import moment from "moment"; |
| | | // console.log(documentHeight,'高度'); |
| | | let count = 5; |
| | | const activeKey = ref(1); |
| | |
| | | > |
| | | <template #title> 新增会话 </template> |
| | | <a-form ref="formRef" :model="conversation" :rules="rules"> |
| | | <a-form-item label="助手关联:" field="dialog_id" @submit="handleSubmit"> |
| | | <a-form-item label="助手关联:" field="dialog_id" > |
| | | <a-select |
| | | style="width: 80%" |
| | | v-model="conversation.dialog_id" |
New file |
| | |
| | | <template> |
| | | <!-- 内容--> |
| | | <a-scrollbar |
| | | ref="scrollbar" |
| | | id="home" |
| | | class="chat-list" |
| | | style=" |
| | | width: 90%; |
| | | overflow: auto; |
| | | height: calc(100vh - 380px); |
| | | margin: 0px auto 20px; |
| | | " |
| | | > |
| | | <div class="chat-item" v-for="sessionDetail in sessionDetailList"> |
| | | <a-comment v-if="sessionDetail.role === 'user'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../../assets/images/icon-user.jpg" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <div :class="{ chartUserText: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </template> |
| | | </a-comment> |
| | | <a-comment v-else-if="sessionDetail.role === 'assistant'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../../assets/images/icon-chart.png" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <a-card :class="{ chatItemAnswer: theme === 'light' }"> |
| | | <div :class="{ light: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </a-card> |
| | | </template> |
| | | </a-comment> |
| | | <a-comment v-else-if="sessionDetail.role === 'last'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../../assets/images/icon-chart.png" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <a-textarea |
| | | readonly |
| | | auto-size |
| | | v-model="displayedText" |
| | | :class="{ chatItemAnswer: theme === 'light' }" |
| | | > |
| | | </a-textarea> |
| | | </template> |
| | | </a-comment> |
| | | </div> |
| | | <!-- <div class="chartStart" v-if="isStart" @click="startChat" |
| | | >停止生成</div |
| | | > |
| | | <div class="chartStart v-else" @click="stopChat">重新生成</div> --> |
| | | </a-scrollbar> |
| | | <div class="chat_bottom"> |
| | | <div class="center-bottom"> |
| | | <a-textarea |
| | | v-model="inputMsg" |
| | | @keydown.shift.enter="handleShiftEnter" |
| | | @keydown.enter="sendMessage" |
| | | placeholder="输入您想了解的内容,Shift+Enter换行,Enter发送" |
| | | allow-clear |
| | | show-word-limit |
| | | :disabled="chatDis" |
| | | :class="{ textItemAnswer: theme === 'dark' }" |
| | | :auto-size="{ |
| | | minRows: 12, |
| | | maxRows: 5, |
| | | }" |
| | | /> |
| | | <div class="btn-send"> |
| | | <!-- <icon-send size="32" /> --> |
| | | <a-button |
| | | :disabled="chatDis" |
| | | @click="sentClick" |
| | | type="primary" |
| | | style="border-radius: 24px" |
| | | :loading="loading" |
| | | size="large" |
| | | >发送</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { defineProps, ref, watch, defineEmits, onMounted, reactive, computed, nextTick } from "vue"; |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import { useAppStore } from "@/store"; |
| | | import { getAuthorization } from "@/utils/auth"; |
| | | import { EventSourceParserStream } from 'eventsource-parser/stream'; |
| | | import { agentResetApi, agentSetApi, getAgentSessionDetailsApi } from "@/api/agentSession"; |
| | | const props = defineProps({ |
| | | modalObj: Object, |
| | | }); |
| | | |
| | | // const emit = defineEmits(['addSession']); |
| | | |
| | | const sessionDetailList = ref([]); //根据会话id出来的会话详情 |
| | | const sessionList = ref([]); //会话列表 |
| | | const modalObj = reactive({ }); |
| | | const dialogId = ref(''); |
| | | const chatDis = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | | let timer: number | null = null; |
| | | const streamStr = ref(''); |
| | | const inputMsg = ref(''); |
| | | const activeSessionId = ref(''); |
| | | const fieldNames = { value: 'id', label: 'name' }; |
| | | const agentObj = reactive({}); |
| | | const agentList = ref([]); |
| | | const selectValue = ref(''); |
| | | const sectionList = ref({}); |
| | | |
| | | const appStore = useAppStore(); |
| | | const theme = computed(() => { |
| | | return appStore.theme; |
| | | }); |
| | | |
| | | |
| | | |
| | | // 初始化页面 |
| | | const initPage = async () => { |
| | | agentSet(); |
| | | agentReset(); |
| | | agentCompletion(); |
| | | queryAgentSessionDetail(agentObj.id); |
| | | }; |
| | | |
| | | // 调用set方法 |
| | | const agentSet = async () => { |
| | | const res = await agentSetApi({ |
| | | id: agentObj.id, |
| | | title: agentObj.title, |
| | | dsl: agentObj.dsl, |
| | | }); |
| | | if (res.code === 200) { |
| | | // Message.success('修改成功'); |
| | | } |
| | | } |
| | | // 调用reset方法 |
| | | const agentReset = async () => { |
| | | const res = await agentResetApi({ |
| | | id: agentObj.id, |
| | | }); |
| | | if (res.code === 200) { |
| | | // Message.success('修改成功'); |
| | | } |
| | | } |
| | | // 调用completion方法 |
| | | const agentCompletion = async () => { |
| | | const response = await fetch( |
| | | '/api/v1/canvas/completion', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | id: agentObj.id |
| | | }), |
| | | } |
| | | ); |
| | | |
| | | const reader = response?.body |
| | | ?.pipeThrough(new TextDecoderStream()) |
| | | .pipeThrough(new EventSourceParserStream()) |
| | | .getReader(); |
| | | currIndex.value = 0; |
| | | while (true) { |
| | | const x = await reader?.read(); |
| | | if (x) { |
| | | const { done, value } = x; |
| | | console.log(x, 999); |
| | | try { |
| | | const val = JSON.parse(value?.data || ''); |
| | | const d = val?.data; |
| | | if (typeof d !== 'boolean') { |
| | | console.info('data:', d); |
| | | streamStr.value = d.content; |
| | | startDisplayStr(); |
| | | } |
| | | } catch (e) { |
| | | console.warn(e); |
| | | } |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | queryAgentSessionDetail(agentObj.id); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } |
| | | // 调用get方法 |
| | | |
| | | const queryAgentSessionDetail = async (id) => { |
| | | const { code, data } = await getAgentSessionDetailsApi(id); |
| | | if (code == 0) { |
| | | console.log(data,'会话详情'); |
| | | sessionDetailList.value = data.dsl.messages; |
| | | // refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | const sentClick = () => { |
| | | sendMessage('click'); |
| | | }; |
| | | const sendMessage = async (event) => { |
| | | if (event.keyCode == 13 || event === 'click') { |
| | | if (!event.shiftKey) { |
| | | //只有enter没有shift,或进行你的其他逻辑 |
| | | if (event !== 'click') { |
| | | event.preventDefault(); // 阻止默认行为,即不换行 |
| | | } |
| | | |
| | | chatDis.value = true; |
| | | loading.value = true; |
| | | if (!activeSessionId.value) { |
| | | Message.warning('请选择会话'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // if (displayedText.value) { |
| | | // querySessionList(); |
| | | // } |
| | | |
| | | if (inputMsg.value) { |
| | | sessionDetailList.value.push({ |
| | | content: inputMsg.value, |
| | | role: 'user', |
| | | }); |
| | | sessionDetailList.value.push({ role: 'last' }); |
| | | refreshScroll(); |
| | | const response = await fetch( |
| | | '/api/v1/canvas/completion', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }), |
| | | } |
| | | ); |
| | | |
| | | const reader = response?.body |
| | | ?.pipeThrough(new TextDecoderStream()) |
| | | .pipeThrough(new EventSourceParserStream()) |
| | | .getReader(); |
| | | currIndex.value = 0; |
| | | while (true) { |
| | | const x = await reader?.read(); |
| | | if (x) { |
| | | const { done, value } = x; |
| | | console.log(x, 999); |
| | | try { |
| | | const val = JSON.parse(value?.data || ''); |
| | | const d = val?.data; |
| | | if (typeof d !== 'boolean') { |
| | | console.info('data:', d); |
| | | streamStr.value = d.content; |
| | | startDisplayStr(); |
| | | } |
| | | } catch (e) { |
| | | console.warn(e); |
| | | } |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | queryAgentSessionDetail(agentObj.id); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } else { |
| | | Message.warning('消息不能为空'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleShiftEnter = (event) => { |
| | | event.preventDefault(); |
| | | inputMsg.value += '\n'; |
| | | }; |
| | | |
| | | |
| | | |
| | | //文字动态输出 |
| | | const startDisplayStr = () => { |
| | | if (timer) { |
| | | clearTimeout(timer!); |
| | | } |
| | | const res = streamStr.value; |
| | | // 将数组中的字符串拼接起来 |
| | | if (currIndex.value < res.length) { |
| | | displayedText.value += res[currIndex.value]; |
| | | currIndex.value++; |
| | | setTimeout(startDisplayStr, 100); |
| | | refreshScroll(); |
| | | } else { |
| | | clearTimeout(timer!); |
| | | timer = null; |
| | | } |
| | | }; |
| | | |
| | | const scrollbar = ref(null); |
| | | const refreshScroll = () => { |
| | | nextTick(() => { |
| | | const container = document.getElementById('home'); |
| | | scrollbar.value.scrollTop(container.scrollHeight); |
| | | }); |
| | | }; |
| | | |
| | | |
| | | onMounted(() => { |
| | | |
| | | }); |
| | | |
| | | watch( |
| | | () => props.modalObj, |
| | | (newVal, oldVal) => { |
| | | console.log(newVal,'监听变化'); |
| | | Object.assign(agentObj, newVal); |
| | | //调用agent初始化方法 |
| | | if(JSON.stringify(newVal) != '{}'){ |
| | | initPage(); |
| | | } |
| | | },{ |
| | | immediate: true, |
| | | deep: true |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | |
| | | .dark { |
| | | color: gray !important; |
| | | } |
| | | |
| | | .container { |
| | | .chatItemAnswer { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | .light { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | } |
| | | } |
| | | .textItemAnswer { |
| | | background-color: #373739; |
| | | } |
| | | |
| | | .center { |
| | | box-sizing: border-box; |
| | | height: calc(100vh - 200px); |
| | | position: relative; |
| | | |
| | | .center-title { |
| | | line-height: 60px; |
| | | font-size: 25px; |
| | | font-family: 黑体; |
| | | color: deepskyblue; |
| | | } |
| | | |
| | | .center-content { |
| | | font-size: 14px; |
| | | color: gray; |
| | | } |
| | | |
| | | .center-question { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .center-question-left { |
| | | margin-top: 5px; |
| | | margin-left: 20px; |
| | | } |
| | | |
| | | .center-question-right { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | .center-list { |
| | | margin-top: 10px; |
| | | |
| | | .item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | .item-content { |
| | | color: #666; |
| | | } |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | .chartStart { |
| | | color: #4955f5; |
| | | cursor: pointer; |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | .chat_bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | .center-bottom { |
| | | // position: absolute; |
| | | // width: 90%; |
| | | // bottom: 20px; |
| | | // left: 5%; |
| | | background: #fff; |
| | | border: 1px solid #00000014; |
| | | border-radius: 24px; |
| | | display: flex; |
| | | flex: 1 1; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | position: relative; |
| | | // padding-top:10px; |
| | | :deep(.arco-textarea-wrapper) { |
| | | border-radius: 24px; |
| | | } |
| | | |
| | | .btn-send { |
| | | position: absolute !important; |
| | | right: 10px; |
| | | bottom: 10px; |
| | | z-index: 10; |
| | | } |
| | | :deep(.arco-btn-size-large) { |
| | | height: 28px; |
| | | width: 50px; |
| | | } |
| | | } |
| | | :deep(.arco-textarea-wrapper) { |
| | | padding-top: 5px; |
| | | } |
| | | } |
| | | } |
| | | .chat-item { |
| | | padding: 10px 0; |
| | | .chartUserText { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-top: 4px; |
| | | } |
| | | .icon-user-jpg { |
| | | border: 1px solid #d9d9d9; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | |
| | | :class="{ isLeftActive: activeSessionId === session.id }" |
| | | > |
| | | <div class="text" :class="{ time: theme === 'dark' }" |
| | | >{{ session.name }} |
| | | >{{ session.name }} |
| | | </div> |
| | | <div class="time" |
| | | >{{ |
| | | >{{ |
| | | moment(new Date(session.create_time)).format( |
| | | 'YYYY-MM-DD HH:mm:ss' |
| | | ) |
| | |
| | | </a-scrollbar> |
| | | </a-card> |
| | | </a-col> |
| | | <a-col :span="18"> |
| | | <!-- 智能体会话--> |
| | | <a-col :span="18" v-show="agentType == '1'"> |
| | | <a-card class="center"> |
| | | <!-- <div |
| | | v-if="sessionDetailList.length === 0" |
| | |
| | | </template> |
| | | <template #content> |
| | | <div :class="{ chartUserText: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </template> |
| | | </a-comment> |
| | |
| | | <template #content> |
| | | <a-card :class="{ chatItemAnswer: theme === 'light' }"> |
| | | <div :class="{ light: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </a-card> |
| | | </template> |
| | |
| | | style="border-radius: 24px" |
| | | :loading="loading" |
| | | size="large" |
| | | >发送</a-button |
| | | >发送</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </a-card> |
| | | </a-col> |
| | | <a-col :span="18" v-show="agentType == '2'"> |
| | | <a-card class="center"> |
| | | <agentSession :modalObj="agentObj"></agentSession> |
| | | </a-card> |
| | | </a-col> |
| | | |
| | | |
| | | |
| | | |
| | | <!-- <a-col :span="5"> |
| | | <a-card class="right"> |
| | | <div class="right-top"> |
| | |
| | | </div> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { |
| | | IconClose, |
| | | IconSearch, |
| | | IconTiktokColor, |
| | | } from '@arco-design/web-vue/es/icon'; |
| | | import { useAppStore, useUserStore } from '@/store'; |
| | | import { computed, nextTick, onMounted, watch, reactive, ref } from 'vue'; |
| | | import { |
| | | IconClose, |
| | | IconSearch, |
| | | IconTiktokColor, |
| | | } from '@arco-design/web-vue/es/icon'; |
| | | import { useAppStore, useUserStore } from '@/store'; |
| | | import { computed, nextTick, onMounted, watch, reactive, ref } from 'vue'; |
| | | |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import { EventSourceParserStream } from 'eventsource-parser/stream'; |
| | | import moment from 'moment'; |
| | | import AddSession from '@/views/sessionManager/components/addSession.vue'; |
| | | import { |
| | | chatApi, |
| | | getDialogListApi, |
| | | getSessionDetailsApi, |
| | | sessionListApi, |
| | | } from '@/api/session'; |
| | | import { getAuthorization } from '@/utils/auth'; |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import { EventSourceParserStream } from 'eventsource-parser/stream'; |
| | | import moment from 'moment'; |
| | | import AddSession from '@/views/sessionManager/components/addSession.vue'; |
| | | import agentSession from '@/views/sessionManager/components/agentSession.vue'; |
| | | import { |
| | | chatApi, |
| | | getDialogListApi, |
| | | getSessionDetailsApi, |
| | | sessionListApi, |
| | | } from '@/api/session'; |
| | | import { getAuthorization } from '@/utils/auth'; |
| | | import { queryCanvasList } from "@/api/Agent"; |
| | | import { getAgentSessionDetailsApi } from "@/api/agentSession"; |
| | | |
| | | const sessionDetailList = ref([]); //根据会话id出来的会话详情 |
| | | const sessionList = ref([]); //会话列表 |
| | | const modalObj = reactive({ add: false }); |
| | | const dialogId = ref(''); |
| | | const chatDis = ref(false); |
| | | const loading = ref(false); |
| | | const sessionDetailList = ref([]); //根据会话id出来的会话详情 |
| | | const sessionList = ref([]); //会话列表 |
| | | const modalObj = reactive({ add: false }); |
| | | const dialogId = ref(''); |
| | | const chatDis = ref(false); |
| | | const loading = ref(false); |
| | | const agentType = ref('1'); |
| | | |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | | let timer: number | null = null; |
| | | const streamStr = ref(''); |
| | | const inputMsg = ref(''); |
| | | const activeSessionId = ref(''); |
| | | const fieldNames = { value: 'id', label: 'name' }; |
| | | const dialogs = ref([]); |
| | | const selectValue = ref(''); |
| | | const sectionList = ref({}); |
| | | const DialogList = async () => { |
| | | const { code, data } = await getDialogListApi(); |
| | | if (code === 200) { |
| | | if (data) { |
| | | selectValue.value = data[0].id; |
| | | dialogs.value = data; |
| | | querySessionList(); |
| | | } |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | | let timer: number | null = null; |
| | | const streamStr = ref(''); |
| | | const inputMsg = ref(''); |
| | | const activeSessionId = ref(''); |
| | | const fieldNames = { value: 'id', label: 'name' }; |
| | | const dialogs = ref([]); |
| | | const dialogObj = reactive({}); |
| | | const agentObj = reactive({}); |
| | | const agentList = ref([]); |
| | | const selectValue = ref(''); |
| | | const sectionList = ref({}); |
| | | const DialogList = async () => { |
| | | const { code, data } = await getDialogListApi(); |
| | | if (code === 200) { |
| | | if (data) { |
| | | selectValue.value = data[0].id; |
| | | dialogs.value = data.map((item) => { |
| | | return { |
| | | ...item, |
| | | type: 1,//智能体 |
| | | } |
| | | }); |
| | | console.log(data, 'dialogs'); |
| | | queryCanvas(); |
| | | // querySessionList(); |
| | | } |
| | | }; |
| | | const handleShiftEnter = (event) => { |
| | | event.preventDefault(); |
| | | inputMsg.value += '\n'; |
| | | }; |
| | | const dialogChange = (val) => { |
| | | dialogId.value = val; |
| | | } |
| | | }; |
| | | |
| | | const queryCanvas = async (params = {}) => { |
| | | try { |
| | | const { data } = await queryCanvasList(params); |
| | | console.log(data, 'agent'); |
| | | agentList.value = data.map((item) => { |
| | | return { |
| | | ...item, |
| | | name: item.title, |
| | | type: 2,//agent |
| | | } |
| | | }); |
| | | // 合并数组 |
| | | dialogs.value = dialogs.value.concat(agentList.value); |
| | | |
| | | // 判断当前是智能体或agent |
| | | // console.log(val, 'val'); |
| | | if(dialogs.value.length>0){ |
| | | dialogChange(dialogs.value[0].id); |
| | | } |
| | | |
| | | } catch (err) { |
| | | // you can report use errorHandler or other |
| | | } finally { |
| | | |
| | | } |
| | | }; |
| | | |
| | | const handleShiftEnter = (event) => { |
| | | event.preventDefault(); |
| | | inputMsg.value += '\n'; |
| | | }; |
| | | const dialogChange = (val) => { |
| | | // 判断当前是智能体或agent |
| | | // console.log(val, 'val'); |
| | | dialogId.value = val; |
| | | dialogs.value.forEach((item) => { |
| | | if (item.id === val) { |
| | | Object.assign(dialogObj, item) |
| | | } |
| | | }) |
| | | console.log(dialogObj.type, 'dialogObj'); |
| | | if (dialogObj.type == 1) { |
| | | agentType.value = 1; |
| | | querySessionList(); |
| | | }; |
| | | const sentClick = () => { |
| | | sendMessage('click'); |
| | | }; |
| | | const sendMessage = async (event) => { |
| | | if (event.keyCode == 13 || event === 'click') { |
| | | if (!event.shiftKey) { |
| | | //只有enter没有shift,或进行你的其他逻辑 |
| | | if (event !== 'click') { |
| | | event.preventDefault(); // 阻止默认行为,即不换行 |
| | | } |
| | | } else { |
| | | agentType.value = 2; |
| | | queryAgentSessionList() |
| | | } |
| | | |
| | | chatDis.value = true; |
| | | loading.value = true; |
| | | if (!activeSessionId.value) { |
| | | Message.warning('请选择会话'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // if (displayedText.value) { |
| | | // querySessionList(); |
| | | // } |
| | | |
| | | if (inputMsg.value) { |
| | | sessionDetailList.value.push({ |
| | | content: inputMsg.value, |
| | | role: 'user', |
| | | }); |
| | | sessionDetailList.value.push({ role: 'last' }); |
| | | refreshScroll(); |
| | | const response = await fetch( |
| | | '/api/tech/cloudminds/query?modeltype=localragflow', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }), |
| | | // querySessionList(); |
| | | }; |
| | | const sentClick = () => { |
| | | sendMessage('click'); |
| | | }; |
| | | const sendMessage = async (event) => { |
| | | if (event.keyCode == 13 || event === 'click') { |
| | | if (!event.shiftKey) { |
| | | //只有enter没有shift,或进行你的其他逻辑 |
| | | if (event !== 'click') { |
| | | event.preventDefault(); // 阻止默认行为,即不换行 |
| | | } |
| | | |
| | | chatDis.value = true; |
| | | loading.value = true; |
| | | if (!activeSessionId.value) { |
| | | Message.warning('请选择会话'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // if (displayedText.value) { |
| | | // querySessionList(); |
| | | // } |
| | | |
| | | if (inputMsg.value) { |
| | | sessionDetailList.value.push({ |
| | | content: inputMsg.value, |
| | | role: 'user', |
| | | }); |
| | | sessionDetailList.value.push({ role: 'last' }); |
| | | refreshScroll(); |
| | | const response = await fetch( |
| | | '/api/tech/cloudminds/query?modeltype=localragflow', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }), |
| | | } |
| | | ); |
| | | |
| | | const reader = response?.body |
| | | ?.pipeThrough(new TextDecoderStream()) |
| | | .pipeThrough(new EventSourceParserStream()) |
| | | .getReader(); |
| | | currIndex.value = 0; |
| | | while (true) { |
| | | const x = await reader?.read(); |
| | | if (x) { |
| | | const { done, value } = x; |
| | | console.log(x, 999); |
| | | try { |
| | | const val = JSON.parse(value?.data || ''); |
| | | const d = val?.data; |
| | | if (typeof d !== 'boolean') { |
| | | console.info('data:', d); |
| | | streamStr.value = d.content; |
| | | startDisplayStr(); |
| | | } |
| | | } catch (e) { |
| | | console.warn(e); |
| | | } |
| | | ); |
| | | |
| | | const reader = response?.body |
| | | ?.pipeThrough(new TextDecoderStream()) |
| | | .pipeThrough(new EventSourceParserStream()) |
| | | .getReader(); |
| | | currIndex.value = 0; |
| | | while (true) { |
| | | const x = await reader?.read(); |
| | | if (x) { |
| | | const { done, value } = x; |
| | | console.log(x, 999); |
| | | try { |
| | | const val = JSON.parse(value?.data || ''); |
| | | const d = val?.data; |
| | | if (typeof d !== 'boolean') { |
| | | console.info('data:', d); |
| | | streamStr.value = d.content; |
| | | startDisplayStr(); |
| | | } |
| | | } catch (e) { |
| | | console.warn(e); |
| | | } |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | querySessionDetail(sectionList.value); |
| | | break; |
| | | } |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | querySessionDetail(sectionList.value); |
| | | break; |
| | | } |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } else { |
| | | Message.warning('消息不能为空'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } else { |
| | | Message.warning('消息不能为空'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | } |
| | | } |
| | | }; |
| | | const querySessionDetail = async (session) => { |
| | | sectionList.value = session; |
| | | activeSessionId.value = session.id; |
| | | const { code, data } = await getSessionDetailsApi(session.id); |
| | | if (code === 200) { |
| | | sessionDetailList.value = data.message; |
| | | refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | const scrollbar = ref(null); |
| | | const refreshScroll = () => { |
| | | nextTick(() => { |
| | | const container = document.getElementById('home'); |
| | | scrollbar.value.scrollTop(container.scrollHeight); |
| | | }); |
| | | }; |
| | | // 查询会话列表 |
| | | const querySessionList = async () => { |
| | | const { code, data } = await sessionListApi(selectValue.value); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | activeSessionId.value = data[0].id; //默认选择第一个 |
| | | querySessionDetail(data[0]); |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | | }; |
| | | //新增会话之后刷新会话列表 |
| | | const addSession = () => { |
| | | querySessionList(); |
| | | }; |
| | | onMounted(() => { |
| | | DialogList(); |
| | | } |
| | | }; |
| | | const querySessionDetail = async (session) => { |
| | | sectionList.value = session; |
| | | activeSessionId.value = session.id; |
| | | const { code, data } = await getSessionDetailsApi(session.id); |
| | | if (code === 200) { |
| | | sessionDetailList.value = data.message; |
| | | refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | const queryAgentSessionDetail = async (id) => { |
| | | const { code, data } = await getAgentSessionDetailsApi(id); |
| | | if (code == 0) { |
| | | Object.assign(agentObj, data) |
| | | // sessionDetailList.value = data.message; |
| | | // refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | const scrollbar = ref(null); |
| | | const refreshScroll = () => { |
| | | nextTick(() => { |
| | | const container = document.getElementById('home'); |
| | | scrollbar.value.scrollTop(container.scrollHeight); |
| | | }); |
| | | }; |
| | | // 查询会话列表 |
| | | const querySessionList = async () => { |
| | | const { code, data } = await sessionListApi(selectValue.value); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | activeSessionId.value = data[0].id; //默认选择第一个 |
| | | querySessionDetail(data[0]); |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | | }; |
| | | |
| | | const appStore = useAppStore(); |
| | | const theme = computed(() => { |
| | | return appStore.theme; |
| | | }); |
| | | |
| | | //文字动态输出 |
| | | const startDisplayStr = () => { |
| | | if (timer) { |
| | | clearTimeout(timer!); |
| | | } |
| | | const res = streamStr.value; |
| | | // 将数组中的字符串拼接起来 |
| | | if (currIndex.value < res.length) { |
| | | displayedText.value += res[currIndex.value]; |
| | | currIndex.value++; |
| | | setTimeout(startDisplayStr, 100); |
| | | refreshScroll(); |
| | | } else { |
| | | clearTimeout(timer!); |
| | | timer = null; |
| | | } |
| | | }; |
| | | // 查询会话列表 |
| | | const queryAgentSessionList = async () => { |
| | | // const { code, data } = await sessionListApi(selectValue.value); |
| | | // if (code === 200) { |
| | | // |
| | | // } else { |
| | | // Message.warning('查询失败'); |
| | | // } |
| | | queryAgentSessionDetail(selectValue.value); |
| | | }; |
| | | |
| | | |
| | | //新增会话之后刷新会话列表 |
| | | const addSession = () => { |
| | | querySessionList(); |
| | | }; |
| | | onMounted(() => { |
| | | DialogList(); |
| | | }); |
| | | |
| | | const appStore = useAppStore(); |
| | | const theme = computed(() => { |
| | | return appStore.theme; |
| | | }); |
| | | |
| | | //文字动态输出 |
| | | const startDisplayStr = () => { |
| | | if (timer) { |
| | | clearTimeout(timer!); |
| | | } |
| | | const res = streamStr.value; |
| | | // 将数组中的字符串拼接起来 |
| | | if (currIndex.value < res.length) { |
| | | displayedText.value += res[currIndex.value]; |
| | | currIndex.value++; |
| | | setTimeout(startDisplayStr, 100); |
| | | refreshScroll(); |
| | | } else { |
| | | clearTimeout(timer!); |
| | | timer = null; |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .isLeftActive { |
| | | background-color: #ededf5; |
| | | } |
| | | .left-list-item { |
| | | margin-bottom: 2px; |
| | | } |
| | | .left-list-item:hover { |
| | | background-color: #ededf5; |
| | | } |
| | | .isLeftActive { |
| | | background-color: #ededf5; |
| | | } |
| | | .left-list-item { |
| | | margin-bottom: 2px; |
| | | } |
| | | .left-list-item:hover { |
| | | background-color: #ededf5; |
| | | } |
| | | |
| | | .dark { |
| | | color: gray !important; |
| | | } |
| | | .dark { |
| | | color: gray !important; |
| | | } |
| | | |
| | | .container { |
| | | .top-title { |
| | | line-height: 32px; |
| | | font-size: 16px; |
| | | color: #333; |
| | | .container { |
| | | .top-title { |
| | | line-height: 32px; |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | .left-select { |
| | | :deep(.arco-select-view-single) { |
| | | border-radius: 5px; |
| | | } |
| | | .left-select { |
| | | :deep(.arco-select-view-single) { |
| | | border-radius: 5px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .center, |
| | | .right { |
| | | box-sizing: border-box; |
| | | height: calc(100vh - 200px); |
| | | } |
| | | .center, |
| | | .right { |
| | | box-sizing: border-box; |
| | | height: calc(100vh - 200px); |
| | | } |
| | | |
| | | .left { |
| | | /* height: calc(100vh - 160px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden;*/ |
| | | border: 0px; |
| | | .left { |
| | | /* height: calc(100vh - 160px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden;*/ |
| | | border: 0px; |
| | | |
| | | .left-list { |
| | | .item { |
| | | cursor: pointer; |
| | | .left-list { |
| | | .item { |
| | | cursor: pointer; |
| | | |
| | | .text, |
| | | .time { |
| | | line-height: 30px; |
| | | } |
| | | .text, |
| | | .time { |
| | | line-height: 30px; |
| | | } |
| | | |
| | | .text { |
| | | color: black; |
| | | padding-left: 10px; |
| | | } |
| | | .text { |
| | | color: black; |
| | | padding-left: 10px; |
| | | } |
| | | |
| | | .time { |
| | | color: gray; |
| | | font-size: 12px; |
| | | padding-left: 10px; |
| | | } |
| | | .time { |
| | | color: gray; |
| | | font-size: 12px; |
| | | padding-left: 10px; |
| | | } |
| | | } |
| | | } |
| | | .card-btn-1 { |
| | | margin: 8px 15px; |
| | | width: 100%; |
| | | border-radius: 5px; |
| | | } |
| | | } |
| | | .card-btn-1 { |
| | | margin: 8px 15px; |
| | | width: 100%; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .card-btn-2 { |
| | | margin: 10px 10px; |
| | | } |
| | | .chatItemAnswer { |
| | | .card-btn-2 { |
| | | margin: 10px 10px; |
| | | } |
| | | .chatItemAnswer { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | .light { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | .light { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | } |
| | | } |
| | | .textItemAnswer { |
| | | background-color: #373739; |
| | | } |
| | | .textItemAnswer { |
| | | background-color: #373739; |
| | | } |
| | | |
| | | .center { |
| | | position: relative; |
| | | |
| | | .center-title { |
| | | line-height: 60px; |
| | | font-size: 25px; |
| | | font-family: 黑体; |
| | | color: deepskyblue; |
| | | } |
| | | |
| | | .center { |
| | | position: relative; |
| | | .center-content { |
| | | font-size: 14px; |
| | | color: gray; |
| | | } |
| | | |
| | | .center-title { |
| | | line-height: 60px; |
| | | font-size: 25px; |
| | | font-family: 黑体; |
| | | color: deepskyblue; |
| | | .center-question { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .center-question-left { |
| | | margin-top: 5px; |
| | | margin-left: 20px; |
| | | } |
| | | |
| | | .center-content { |
| | | font-size: 14px; |
| | | color: gray; |
| | | .center-question-right { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | .center-list { |
| | | margin-top: 10px; |
| | | |
| | | .center-question { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .center-question-left { |
| | | margin-top: 5px; |
| | | margin-left: 20px; |
| | | } |
| | | |
| | | .center-question-right { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | .center-list { |
| | | .item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | |
| | | .item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | .item-content { |
| | | color: #666; |
| | | } |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | .item-content { |
| | | color: #666; |
| | | } |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | } |
| | | .chartStart { |
| | | color: #4955f5; |
| | | cursor: pointer; |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | .chat_bottom { |
| | | } |
| | | .chartStart { |
| | | color: #4955f5; |
| | | cursor: pointer; |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | .chat_bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | .center-bottom { |
| | | // position: absolute; |
| | | // width: 90%; |
| | | // bottom: 20px; |
| | | // left: 5%; |
| | | background: #fff; |
| | | border: 1px solid #00000014; |
| | | border-radius: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | .center-bottom { |
| | | // position: absolute; |
| | | // width: 90%; |
| | | // bottom: 20px; |
| | | // left: 5%; |
| | | background: #fff; |
| | | border: 1px solid #00000014; |
| | | border-radius: 24px; |
| | | display: flex; |
| | | flex: 1 1; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | position: relative; |
| | | // padding-top:10px; |
| | | :deep(.arco-textarea-wrapper) { |
| | | border-radius: 24px; |
| | | } |
| | | |
| | | .btn-send { |
| | | position: absolute !important; |
| | | right: 10px; |
| | | bottom: 10px; |
| | | z-index: 10; |
| | | } |
| | | :deep(.arco-btn-size-large) { |
| | | height: 28px; |
| | | width: 60px; |
| | | } |
| | | } |
| | | flex: 1 1; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | position: relative; |
| | | // padding-top:10px; |
| | | :deep(.arco-textarea-wrapper) { |
| | | padding-top: 5px; |
| | | border-radius: 24px; |
| | | } |
| | | |
| | | .btn-send { |
| | | position: absolute !important; |
| | | right: 10px; |
| | | bottom: 10px; |
| | | z-index: 10; |
| | | } |
| | | :deep(.arco-btn-size-large) { |
| | | height: 28px; |
| | | width: 60px; |
| | | } |
| | | } |
| | | :deep(.arco-textarea-wrapper) { |
| | | padding-top: 5px; |
| | | } |
| | | } |
| | | .chat-item { |
| | | padding: 10px 0; |
| | | .chartUserText { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-top: 4px; |
| | | } |
| | | .chat-item { |
| | | padding: 10px 0; |
| | | .chartUserText { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-top: 4px; |
| | | } |
| | | .icon-user-jpg { |
| | | border: 1px solid #d9d9d9; |
| | | } |
| | | } |
| | | .right { |
| | | .right-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .right-title { |
| | | font-size: 25px; |
| | | color: black; |
| | | } |
| | | .icon-user-jpg { |
| | | border: 1px solid #d9d9d9; |
| | | |
| | | .right-btn { |
| | | position: relative; |
| | | left: 20px; |
| | | top: 0px; |
| | | } |
| | | } |
| | | .right { |
| | | .right-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .right-title { |
| | | font-size: 25px; |
| | | color: black; |
| | | } |
| | | |
| | | .right-btn { |
| | | position: relative; |
| | | left: 20px; |
| | | top: 0px; |
| | | } |
| | | } |
| | | .right-tag { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | :deep(.arco-btn-primary) { |
| | | margin-bottom: 10px !important; |
| | | &:hover { |
| | | background-color: #e9f3ff; |
| | | color: rgb(22, 93, 255); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .right-list { |
| | | .right-item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | .right-tag { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | :deep(.arco-btn-primary) { |
| | | margin-bottom: 10px !important; |
| | | &:hover { |
| | | background-color: #e9f3ff; |
| | | color: rgb(22, 93, 255); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | .right-list { |
| | | .right-item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="container"> |
| | | <AddSession |
| | | :modalObj="modalObj" |
| | | @addSession="addSession" |
| | | :dialogId="dialogId" |
| | | ></AddSession> |
| | | <a-card class="top-title">AI会话记录</a-card> |
| | | <a-row :gutter="[5, 5]" style="margin-top: 3px"> |
| | | <a-col :span="6"> |
| | | <a-card class="left-select"> |
| | | <a-select |
| | | v-model="selectValue" |
| | | :options="dialogs" |
| | | :field-names="fieldNames" |
| | | @change="dialogChange" |
| | | > |
| | | </a-select> |
| | | </a-card> |
| | | <a-card style="height: 50px"> |
| | | <template #cover> |
| | | <div style="display: flex; justify-content: space-between"> |
| | | <a-button |
| | | type="primary" |
| | | shape="round" |
| | | class="card-btn-1" |
| | | @click="modalObj.add = true" |
| | | > |
| | | +新建会话 |
| | | </a-button> |
| | | <!-- <a-button type="text" shape="circle" class="card-btn-2"> |
| | | <icon-search /> |
| | | </a-button> --> |
| | | </div> |
| | | </template> |
| | | </a-card> |
| | | <a-card class="left"> |
| | | <a-scrollbar |
| | | class="left-list" |
| | | style=" |
| | | height: calc(100vh - 350px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden; |
| | | " |
| | | > |
| | | <div |
| | | class="item left-list-item" |
| | | v-for="session in sessionList" |
| | | @click="querySessionDetail(session)" |
| | | :class="{ isLeftActive: activeSessionId === session.id }" |
| | | > |
| | | <div class="text" :class="{ time: theme === 'dark' }" |
| | | >{{ session.name }} |
| | | </div> |
| | | <div class="time" |
| | | >{{ |
| | | moment(new Date(session.create_time)).format( |
| | | 'YYYY-MM-DD HH:mm:ss' |
| | | ) |
| | | }} |
| | | </div> |
| | | </div> |
| | | </a-scrollbar> |
| | | </a-card> |
| | | </a-col> |
| | | <!-- 智能体会话--> |
| | | <a-col :span="18" v-show="agentType == '1'"> |
| | | <a-card class="center"> |
| | | <!-- <div |
| | | v-if="sessionDetailList.length === 0" |
| | | style=" |
| | | width: 90%; |
| | | overflow: auto; |
| | | height: 65vh; |
| | | margin: 0px auto 20px; |
| | | " |
| | | > |
| | | <div class="center-title">智能问答</div> |
| | | <div class="center-content"> |
| | | 我可以理解和学习人类的语言,具备多轮对话的能力,现在和我开始交流吧~ |
| | | </div> |
| | | <div class="center-question"> |
| | | <div class="center-question-left">试一试这样问我</div> |
| | | <div class="center-question-right"> |
| | | <a-button type="primary">换一换</a-button> |
| | | </div> |
| | | </div> |
| | | <a-row justify="space-around" class="center-list"> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | <a-col :span="7" class="item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </a-col> |
| | | </a-row> |
| | | </div> --> |
| | | <a-scrollbar |
| | | ref="scrollbar" |
| | | id="home" |
| | | class="chat-list" |
| | | style=" |
| | | width: 90%; |
| | | overflow: auto; |
| | | height: calc(100vh - 380px); |
| | | margin: 0px auto 20px; |
| | | " |
| | | > |
| | | <div class="chat-item" v-for="sessionDetail in sessionDetailList"> |
| | | <a-comment v-if="sessionDetail.role === 'user'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../assets/images/icon-user.jpg" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <div :class="{ chartUserText: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </template> |
| | | </a-comment> |
| | | <a-comment v-else-if="sessionDetail.role === 'assistant'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../assets/images/icon-chart.png" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <a-card :class="{ chatItemAnswer: theme === 'light' }"> |
| | | <div :class="{ light: theme === 'light' }" |
| | | >{{ sessionDetail.content }} |
| | | </div> |
| | | </a-card> |
| | | </template> |
| | | </a-comment> |
| | | <a-comment v-else-if="sessionDetail.role === 'last'"> |
| | | <template #avatar> |
| | | <img |
| | | class="icon-user-jpg" |
| | | src="../../assets/images/icon-chart.png" |
| | | alt="本地图片" |
| | | /> |
| | | </template> |
| | | <template #content> |
| | | <a-textarea |
| | | readonly |
| | | auto-size |
| | | v-model="displayedText" |
| | | :class="{ chatItemAnswer: theme === 'light' }" |
| | | > |
| | | </a-textarea> |
| | | </template> |
| | | </a-comment> |
| | | </div> |
| | | <!-- <div class="chartStart" v-if="isStart" @click="startChat" |
| | | >停止生成</div |
| | | > |
| | | <div class="chartStart v-else" @click="stopChat">重新生成</div> --> |
| | | </a-scrollbar> |
| | | <div class="chat_bottom"> |
| | | <div class="center-bottom"> |
| | | <!-- <a-textarea |
| | | v-model="inputMsg" |
| | | @keydown.shift.enter="sendMessage" |
| | | style="height: 180px" |
| | | placeholder="输入您想了解的内容,Shift+Enter发送" |
| | | :max-length="500" |
| | | allow-clear |
| | | show-word-limit |
| | | > |
| | | </a-textarea> --> |
| | | <a-textarea |
| | | v-model="inputMsg" |
| | | @keydown.shift.enter="handleShiftEnter" |
| | | @keydown.enter="sendMessage" |
| | | placeholder="输入您想了解的内容,Shift+Enter换行,Enter发送" |
| | | allow-clear |
| | | show-word-limit |
| | | :disabled="chatDis" |
| | | :class="{ textItemAnswer: theme === 'dark' }" |
| | | :auto-size="{ |
| | | minRows: 12, |
| | | maxRows: 5, |
| | | }" |
| | | /> |
| | | <div class="btn-send"> |
| | | <!-- <icon-send size="32" /> --> |
| | | <a-button |
| | | :disabled="chatDis" |
| | | @click="sentClick" |
| | | type="primary" |
| | | style="border-radius: 24px" |
| | | :loading="loading" |
| | | size="large" |
| | | >发送</a-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </a-card> |
| | | </a-col> |
| | | <a-col :span="18" v-show="agentType == '2'"> |
| | | <a-card class="center"> |
| | | <agentSession ></agentSession> |
| | | </a-card> |
| | | </a-col> |
| | | |
| | | |
| | | |
| | | |
| | | <!-- <a-col :span="5"> |
| | | <a-card class="right"> |
| | | <div class="right-top"> |
| | | <div class="right-title">数智库</div> |
| | | <div class="right-btn"> |
| | | <a-button type="outline" shape="circle" style="border: none"> |
| | | <icon-search /> |
| | | </a-button> |
| | | <a-button |
| | | type="outline" |
| | | shape="circle" |
| | | style="border: none; margin-left: -10px" |
| | | > |
| | | <icon-close /> |
| | | </a-button> |
| | | </div> |
| | | </div> |
| | | <div class="right-tag"> |
| | | <a-button type="primary" size="mini" class="btn">全部 </a-button> |
| | | <a-button type="outline" size="mini" class="btn" |
| | | >文档创作 |
| | | </a-button> |
| | | <a-button type="outline" size="mini" class="btn" |
| | | >知识学习 |
| | | </a-button> |
| | | <a-button type="outline" size="mini" class="btn" |
| | | >效率提升 |
| | | </a-button> |
| | | </div> |
| | | <div class="right-list"> |
| | | <div class="right-item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </div> |
| | | <div class="right-item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </div> |
| | | <div class="right-item"> |
| | | <div class="item-title"> |
| | | <IconTiktokColor></IconTiktokColor> |
| | | 抖音带货脚本 |
| | | </div> |
| | | <div class="item-content" :class="{ dark: theme === 'dark' }"> |
| | | 编写引人注目且具有说服力的、适用于产品的... |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </a-card> |
| | | </a-col> --> |
| | | </a-row> |
| | | </div> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { |
| | | IconClose, |
| | | IconSearch, |
| | | IconTiktokColor, |
| | | } from '@arco-design/web-vue/es/icon'; |
| | | import { useAppStore, useUserStore } from '@/store'; |
| | | import { computed, nextTick, onMounted, watch, reactive, ref } from 'vue'; |
| | | |
| | | import { Message } from '@arco-design/web-vue'; |
| | | import { EventSourceParserStream } from 'eventsource-parser/stream'; |
| | | import moment from 'moment'; |
| | | import AddSession from '@/views/sessionManager/components/addSession.vue'; |
| | | import agentSession from '@/views/sessionManager/components/agentSession.vue'; |
| | | import { |
| | | chatApi, |
| | | getDialogListApi, |
| | | getSessionDetailsApi, |
| | | sessionListApi, |
| | | } from '@/api/session'; |
| | | import { getAuthorization } from '@/utils/auth'; |
| | | import { queryCanvasList } from "@/api/Agent"; |
| | | import { getAgentSessionDetailsApi } from "@/api/agentSession"; |
| | | |
| | | const sessionDetailList = ref([]); //根据会话id出来的会话详情 |
| | | const sessionList = ref([]); //会话列表 |
| | | const modalObj = reactive({ add: false }); |
| | | const dialogId = ref(''); |
| | | const chatDis = ref(false); |
| | | const loading = ref(false); |
| | | const agentType = ref('1'); |
| | | |
| | | const currIndex = ref(0); |
| | | const displayedText = ref(''); // 正在显示的文字 |
| | | let timer: number | null = null; |
| | | const streamStr = ref(''); |
| | | const inputMsg = ref(''); |
| | | const activeSessionId = ref(''); |
| | | const fieldNames = { value: 'id', label: 'name' }; |
| | | const dialogs = ref([]); |
| | | const dialogObj = reactive({}); |
| | | const agentList = ref([]); |
| | | const selectValue = ref(''); |
| | | const sectionList = ref({}); |
| | | const DialogList = async () => { |
| | | const { code, data } = await getDialogListApi(); |
| | | if (code === 200) { |
| | | if (data) { |
| | | selectValue.value = data[0].id; |
| | | dialogs.value = data.map((item) => { |
| | | return { |
| | | ...item, |
| | | type: 1,//智能体 |
| | | } |
| | | }); |
| | | console.log(data, 'dialogs'); |
| | | queryCanvas(); |
| | | // querySessionList(); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const queryCanvas = async (params = {}) => { |
| | | try { |
| | | const { data } = await queryCanvasList(params); |
| | | console.log(data, 'agent'); |
| | | agentList.value = data.map((item) => { |
| | | return { |
| | | ...item, |
| | | name: item.title, |
| | | type: 2,//agent |
| | | } |
| | | }); |
| | | // 合并数组 |
| | | dialogs.value = dialogs.value.concat(agentList.value); |
| | | |
| | | // 判断当前是智能体或agent |
| | | // console.log(val, 'val'); |
| | | if(dialogs.value.length>0){ |
| | | dialogChange(dialogs.value[0].id); |
| | | } |
| | | |
| | | } catch (err) { |
| | | // you can report use errorHandler or other |
| | | } finally { |
| | | |
| | | } |
| | | }; |
| | | |
| | | const handleShiftEnter = (event) => { |
| | | event.preventDefault(); |
| | | inputMsg.value += '\n'; |
| | | }; |
| | | const dialogChange = (val) => { |
| | | // 判断当前是智能体或agent |
| | | // console.log(val, 'val'); |
| | | dialogId.value = val; |
| | | dialogs.value.forEach((item) => { |
| | | if (item.id === val) { |
| | | Object.assign(dialogObj, item) |
| | | } |
| | | }) |
| | | console.log(dialogObj.type, 'dialogObj'); |
| | | if (dialogObj.type == 1) { |
| | | agentType.value = 1; |
| | | querySessionList(); |
| | | } else { |
| | | agentType.value = 2; |
| | | queryAgentSessionList() |
| | | } |
| | | |
| | | |
| | | |
| | | // querySessionList(); |
| | | }; |
| | | const sentClick = () => { |
| | | sendMessage('click'); |
| | | }; |
| | | const sendMessage = async (event) => { |
| | | if (event.keyCode == 13 || event === 'click') { |
| | | if (!event.shiftKey) { |
| | | //只有enter没有shift,或进行你的其他逻辑 |
| | | if (event !== 'click') { |
| | | event.preventDefault(); // 阻止默认行为,即不换行 |
| | | } |
| | | |
| | | chatDis.value = true; |
| | | loading.value = true; |
| | | if (!activeSessionId.value) { |
| | | Message.warning('请选择会话'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // if (displayedText.value) { |
| | | // querySessionList(); |
| | | // } |
| | | |
| | | if (inputMsg.value) { |
| | | sessionDetailList.value.push({ |
| | | content: inputMsg.value, |
| | | role: 'user', |
| | | }); |
| | | sessionDetailList.value.push({ role: 'last' }); |
| | | refreshScroll(); |
| | | const response = await fetch( |
| | | '/api/tech/cloudminds/query?modeltype=localragflow', |
| | | { |
| | | method: 'POST', |
| | | headers: { |
| | | 'Authorization': getAuthorization(), |
| | | 'Content-Type': 'application/json', |
| | | }, |
| | | body: JSON.stringify({ |
| | | conversation_id: activeSessionId.value, |
| | | messages: inputMsg.value, |
| | | }), |
| | | } |
| | | ); |
| | | |
| | | const reader = response?.body |
| | | ?.pipeThrough(new TextDecoderStream()) |
| | | .pipeThrough(new EventSourceParserStream()) |
| | | .getReader(); |
| | | currIndex.value = 0; |
| | | while (true) { |
| | | const x = await reader?.read(); |
| | | if (x) { |
| | | const { done, value } = x; |
| | | console.log(x, 999); |
| | | try { |
| | | const val = JSON.parse(value?.data || ''); |
| | | const d = val?.data; |
| | | if (typeof d !== 'boolean') { |
| | | console.info('data:', d); |
| | | streamStr.value = d.content; |
| | | startDisplayStr(); |
| | | } |
| | | } catch (e) { |
| | | console.warn(e); |
| | | } |
| | | if (done) { |
| | | console.info('done'); |
| | | displayedText.value = ''; |
| | | querySessionDetail(sectionList.value); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | inputMsg.value = ''; |
| | | } else { |
| | | Message.warning('消息不能为空'); |
| | | chatDis.value = false; |
| | | loading.value = false; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | const querySessionDetail = async (session) => { |
| | | sectionList.value = session; |
| | | activeSessionId.value = session.id; |
| | | const { code, data } = await getSessionDetailsApi(session.id); |
| | | if (code === 200) { |
| | | sessionDetailList.value = data.message; |
| | | refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | const queryAgentSessionDetail = async (id) => { |
| | | const { code, data } = await getAgentSessionDetailsApi(id); |
| | | if (code === 200) { |
| | | // sessionDetailList.value = data.message; |
| | | // refreshScroll(); //刷新滚动条位置 |
| | | } |
| | | }; |
| | | const scrollbar = ref(null); |
| | | const refreshScroll = () => { |
| | | nextTick(() => { |
| | | const container = document.getElementById('home'); |
| | | scrollbar.value.scrollTop(container.scrollHeight); |
| | | }); |
| | | }; |
| | | // 查询会话列表 |
| | | const querySessionList = async () => { |
| | | const { code, data } = await sessionListApi(selectValue.value); |
| | | if (code === 200) { |
| | | sessionList.value = data; |
| | | activeSessionId.value = data[0].id; //默认选择第一个 |
| | | querySessionDetail(data[0]); |
| | | } else { |
| | | Message.warning('查询失败'); |
| | | } |
| | | }; |
| | | |
| | | |
| | | // 查询会话列表 |
| | | const queryAgentSessionList = async () => { |
| | | // const { code, data } = await sessionListApi(selectValue.value); |
| | | // if (code === 200) { |
| | | // |
| | | // } else { |
| | | // Message.warning('查询失败'); |
| | | // } |
| | | queryAgentSessionDetail(selectValue.value); |
| | | }; |
| | | |
| | | |
| | | //新增会话之后刷新会话列表 |
| | | const addSession = () => { |
| | | querySessionList(); |
| | | }; |
| | | onMounted(() => { |
| | | DialogList(); |
| | | }); |
| | | |
| | | const appStore = useAppStore(); |
| | | const theme = computed(() => { |
| | | return appStore.theme; |
| | | }); |
| | | |
| | | //文字动态输出 |
| | | const startDisplayStr = () => { |
| | | if (timer) { |
| | | clearTimeout(timer!); |
| | | } |
| | | const res = streamStr.value; |
| | | // 将数组中的字符串拼接起来 |
| | | if (currIndex.value < res.length) { |
| | | displayedText.value += res[currIndex.value]; |
| | | currIndex.value++; |
| | | setTimeout(startDisplayStr, 100); |
| | | refreshScroll(); |
| | | } else { |
| | | clearTimeout(timer!); |
| | | timer = null; |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .isLeftActive { |
| | | background-color: #ededf5; |
| | | } |
| | | .left-list-item { |
| | | margin-bottom: 2px; |
| | | } |
| | | .left-list-item:hover { |
| | | background-color: #ededf5; |
| | | } |
| | | |
| | | .dark { |
| | | color: gray !important; |
| | | } |
| | | |
| | | .container { |
| | | .top-title { |
| | | line-height: 32px; |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | .left-select { |
| | | :deep(.arco-select-view-single) { |
| | | border-radius: 5px; |
| | | } |
| | | } |
| | | |
| | | .center, |
| | | .right { |
| | | box-sizing: border-box; |
| | | height: calc(100vh - 200px); |
| | | } |
| | | |
| | | .left { |
| | | /* height: calc(100vh - 160px); |
| | | overflow-y: auto; |
| | | overflow-x: hidden;*/ |
| | | border: 0px; |
| | | |
| | | .left-list { |
| | | .item { |
| | | cursor: pointer; |
| | | |
| | | .text, |
| | | .time { |
| | | line-height: 30px; |
| | | } |
| | | |
| | | .text { |
| | | color: black; |
| | | padding-left: 10px; |
| | | } |
| | | |
| | | .time { |
| | | color: gray; |
| | | font-size: 12px; |
| | | padding-left: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .card-btn-1 { |
| | | margin: 8px 15px; |
| | | width: 100%; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .card-btn-2 { |
| | | margin: 10px 10px; |
| | | } |
| | | .chatItemAnswer { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | .light { |
| | | box-sizing: border-box; |
| | | background: #f1f1f1; |
| | | border-radius: 14px; |
| | | } |
| | | } |
| | | .textItemAnswer { |
| | | background-color: #373739; |
| | | } |
| | | |
| | | .center { |
| | | position: relative; |
| | | |
| | | .center-title { |
| | | line-height: 60px; |
| | | font-size: 25px; |
| | | font-family: 黑体; |
| | | color: deepskyblue; |
| | | } |
| | | |
| | | .center-content { |
| | | font-size: 14px; |
| | | color: gray; |
| | | } |
| | | |
| | | .center-question { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .center-question-left { |
| | | margin-top: 5px; |
| | | margin-left: 20px; |
| | | } |
| | | |
| | | .center-question-right { |
| | | margin-right: 20px; |
| | | } |
| | | } |
| | | .center-list { |
| | | margin-top: 10px; |
| | | |
| | | .item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | .item-content { |
| | | color: #666; |
| | | } |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | .chartStart { |
| | | color: #4955f5; |
| | | cursor: pointer; |
| | | font-family: PingFangSC-Medium; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | .chat_bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | .center-bottom { |
| | | // position: absolute; |
| | | // width: 90%; |
| | | // bottom: 20px; |
| | | // left: 5%; |
| | | background: #fff; |
| | | border: 1px solid #00000014; |
| | | border-radius: 24px; |
| | | display: flex; |
| | | flex: 1 1; |
| | | flex-direction: column; |
| | | overflow: hidden; |
| | | position: relative; |
| | | // padding-top:10px; |
| | | :deep(.arco-textarea-wrapper) { |
| | | border-radius: 24px; |
| | | } |
| | | |
| | | .btn-send { |
| | | position: absolute !important; |
| | | right: 10px; |
| | | bottom: 10px; |
| | | z-index: 10; |
| | | } |
| | | :deep(.arco-btn-size-large) { |
| | | height: 28px; |
| | | width: 50px; |
| | | } |
| | | } |
| | | :deep(.arco-textarea-wrapper) { |
| | | padding-top: 5px; |
| | | } |
| | | } |
| | | } |
| | | .chat-item { |
| | | padding: 10px 0; |
| | | .chartUserText { |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | color: #333; |
| | | margin-top: 4px; |
| | | } |
| | | .icon-user-jpg { |
| | | border: 1px solid #d9d9d9; |
| | | } |
| | | } |
| | | .right { |
| | | .right-top { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | .right-title { |
| | | font-size: 25px; |
| | | color: black; |
| | | } |
| | | |
| | | .right-btn { |
| | | position: relative; |
| | | left: 20px; |
| | | top: 0px; |
| | | } |
| | | } |
| | | .right-tag { |
| | | margin-top: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | flex-wrap: wrap; |
| | | :deep(.arco-btn-primary) { |
| | | margin-bottom: 10px !important; |
| | | &:hover { |
| | | background-color: #e9f3ff; |
| | | color: rgb(22, 93, 255); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .right-list { |
| | | .right-item { |
| | | border-radius: 10px; |
| | | margin-top: 10px; |
| | | padding: 10px; |
| | | min-height: 120px; |
| | | background-color: #e9f3ff; |
| | | |
| | | .item-title { |
| | | text-align: center; |
| | | line-height: 40px; |
| | | font-size: 20px; |
| | | font-family: 黑体; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |