| | |
| | | </el-button> |
| | | </div> |
| | | |
| | | <div class="set-input "> |
| | | <div class="set-input"> |
| | | <div v-if="attachList?.length > 0" class="flex gap-3.5 w-full overflow-x-auto px-2 pb-2"> |
| | | <div |
| | | v-for="(item, index) in attachList" |
| | | :key="index" |
| | | class="flex items-center gap-2 bg-[#f5f5f5] px-2 py-3 rounded-lg w-[220px] relative group" |
| | | :class="{ 'cursor-pointer': item.type === 'table' }" |
| | | @click="openAttachPreview(item)" |
| | | > |
| | | <template v-if="item.type === 'file'"> |
| | | <el-image |
| | |
| | | </template> |
| | | <div |
| | | class="group-hover:visible invisible absolute right-0.5 top-0.5 bg-red-500 flex-center rounded-full p-0.5 cursor-pointer" |
| | | @click="deleteAttachInIndex(index)" |
| | | @click.stop="deleteAttachInIndex(index)" |
| | | > |
| | | <span class="ywifont ywicon-guanbi text-white !text-[10px] font-bold"></span> |
| | | </div> |
| | |
| | | @updateInput="updateInputValue" |
| | | /> |
| | | <BusinessTable v-model="businessTableIsShow" @submit="submitBusinessTable" /> |
| | | <BusinessTablePreview :data="attachPreviewData" v-model="attachPreviewIsShow" @submit="submitBusinessTable" /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <script setup lang="ts"> |
| | | import type { InputInstance } from 'element-plus'; |
| | | import { nextTick, ref } from 'vue'; |
| | | import BusinessTable from './businessTable/index.vue'; |
| | | import BusinessTablePreview from './businessTablePreview/index.vue'; |
| | | import type { Attach } from './hook/useAttach'; |
| | | import { useAttach } from './hook/useAttach'; |
| | | import { useInputEvent } from './hook/useInputEvent'; |
| | | import { useUploadFile } from './hook/useUploadFile'; |
| | | import InputTip from './inputTip/index.vue'; |
| | | import CommonPhrases from './phrase/CommonPhrases.vue'; |
| | | import SceneSwitch from './SceneSwitch.vue'; |
| | | import VoicePage from './voicePage/VoicePage.vue'; |
| | | import { useCompRef } from '/@/utils/types'; |
| | | import { useUploadFile } from './hook/useUploadFile'; |
| | | import BusinessTable from './businessTable/index.vue'; |
| | | import { useAttach } from './hook/useAttach'; |
| | | |
| | | const emits = defineEmits(['sendClick', 'stopGenClick']); |
| | | const props = defineProps({ |
| | | isTalking: Boolean, |
| | |
| | | businessTableIsShow.value = true; |
| | | }; |
| | | //#endregion |
| | | |
| | | //#region ====================== éä»¶é¢è§ ====================== |
| | | const attachPreviewIsShow = ref(false); |
| | | const attachPreviewData = ref<Attach>(); |
| | | const openAttachPreview = (item: Attach) => { |
| | | if (item.type === 'file') return; |
| | | attachPreviewIsShow.value = true; |
| | | attachPreviewData.value = item; |
| | | }; |
| | | //#endregion |
| | | defineExpose({ |
| | | addPhrase, |
| | | showSyncTip, |
| | |
| | | </template> |
| | | <template #main> |
| | | <div class="w100 h100"> |
| | | <div class="h-full"> |
| | | <div class="h-full flex-column"> |
| | | <ColFilter class="flex-0 ml-auto mb-2" :column-list="tableCheckData" /> |
| | | <el-table |
| | | v-loading="tableLoading" |
| | | ref="draggableTableRef" |
| | | class="h100" |
| | | class="flex-auto" |
| | | border |
| | | :row-class-name="isDragStatus ? 'cursor-move' : 'cursor-pointer'" |
| | | :data="tableData" |
| | | highlight-current-row |
| | | @sort-change="handleSortChange" |
| | | > |
| | | <el-table-column |
| | | v-for="item in tableColumns" |
| | | v-for="item in visibleTableColumns" |
| | | :prop="item.name" |
| | | sortable="custom" |
| | | :key="item.name" |
| | |
| | | import { useCompRef } from '/@/utils/types'; |
| | | import { convertListToTree, debounce, travelTree } from '/@/utils/util'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import ColFilter from '/@/components/table/colFilter/ColFilter.vue'; |
| | | const dialogIsShow = defineModel({ |
| | | type: Boolean, |
| | | }); |
| | |
| | | submitLoading.value = false; |
| | | }); |
| | | const tables = checkedList.map((item) => { |
| | | const indexMapItem = getIndexMapItem(item.columns); |
| | | return { |
| | | title: item.title, |
| | | columns: item.columns.map((item) => { |
| | | return item.title; |
| | | }), |
| | | columns: item.columns |
| | | .filter((item) => item.isShow) |
| | | .map((item) => { |
| | | return item.title; |
| | | }), |
| | | values: item.tableData.map((item) => { |
| | | return Object.values(item); |
| | | return Object.values(item).filter((item, index) => { |
| | | return indexMapItem.get(index).isShow; |
| | | }); |
| | | }), |
| | | }; |
| | | }); |
| | |
| | | }; |
| | | const submitFormValue = async () => { |
| | | const data = await getSubmitData(); |
| | | |
| | | emit('submit', data); |
| | | dialogIsShow.value = false; |
| | | }; |
| | |
| | | ...item, |
| | | // åå§æ¥è¯¢å¼ |
| | | values: [''], |
| | | isShow: true, |
| | | }; |
| | | }); |
| | | } |
| | |
| | | const tableData = computed(() => { |
| | | return currentNode.value?.tableData || []; |
| | | }); |
| | | const isDragStatus = ref(false); |
| | | |
| | | const tableColumns = computed(() => { |
| | | return currentNode.value?.columns || []; |
| | | }); |
| | | |
| | | const tableCheckData = computed(() => { |
| | | return tableColumns.value.map((item) => { |
| | | return { |
| | | prop: item.name, |
| | | label: item.title, |
| | | get isShow() { |
| | | return item.isShow; |
| | | }, |
| | | set isShow(value) { |
| | | item.isShow = value; |
| | | }, |
| | | }; |
| | | }); |
| | | }); |
| | | |
| | | const visibleTableColumns = computed(() => { |
| | | return tableColumns.value.filter((item) => item.isShow); |
| | | }); |
| | | const getTableData = async () => { |
| | | // allTableData.value = (res.values || []).map((item) => { |
| | |
| | | ); |
| | | }; |
| | | |
| | | const indexMapItem = computed<Map<number, any>>(() => { |
| | | return new Map( |
| | | tableColumns.value.map((item, index) => { |
| | | return [index, item]; |
| | | }) |
| | | ); |
| | | }); |
| | | //#region ====================== æ¥è¯¢ ====================== |
| | | const getFilterColumns = (node) => { |
| | | return node?.columns?.filter((item) => item.filter) as any[]; |
| | | return node?.columns?.filter((item) => item.filter && item.isShow) as any[]; |
| | | }; |
| | | const filterColumns = computed(() => { |
| | | return getFilterColumns(currentNode.value); |
| | |
| | | height: calc(90vh - 111px) !important; |
| | | } |
| | | } |
| | | |
| | | .yw-layout-main { |
| | | .el-card__body { |
| | | padding: 10px; |
| | | } |
| | | } |
| | | </style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | class="limit-height" |
| | | :destroy-on-close="true" |
| | | v-model="dialogIsShow" |
| | | width="70%" |
| | | :close-on-click-modal="false" |
| | | @closed="closeDialog" |
| | | > |
| | | <template #header> |
| | | <div style="color: #fff"> |
| | | <SvgIcon name="ele-Document" :size="16" style="margin-right: 3px; display: inline; vertical-align: middle" /> |
| | | <span>æ¥çä¸å¡è¡¨</span> |
| | | </div> |
| | | </template> |
| | | <div class="w100 h100"> |
| | | <div class="h-full flex-column"> |
| | | <ColFilter class="flex-0 ml-auto mb-2" :column-list="tableCheckData" /> |
| | | <el-table v-loading="tableLoading" ref="draggableTableRef" class="flex-auto" border :data="tableData" highlight-current-row> |
| | | <el-table-column |
| | | v-for="item in visibleTableColumns" |
| | | :prop="item.name" |
| | | sortable |
| | | :key="item.name" |
| | | :label="item.title" |
| | | show-overflow-tooltip |
| | | > |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="BusinessTablePreview"> |
| | | import type { PropType } from 'vue'; |
| | | import { computed, ref, watch } from 'vue'; |
| | | // import TableSearch from './search/index.vue'; |
| | | import type { Attach } from '../hook/useAttach'; |
| | | import ColFilter from '/@/components/table/colFilter/ColFilter.vue'; |
| | | const dialogIsShow = defineModel({ |
| | | type: Boolean, |
| | | }); |
| | | const props = defineProps({ |
| | | data: { |
| | | type: Object as PropType<Attach>, |
| | | default: () => {}, |
| | | }, |
| | | }); |
| | | const closeDialog = () => { |
| | | dialogIsShow.value = false; |
| | | tableData.value = []; |
| | | tableColumns.value = []; |
| | | }; |
| | | |
| | | //#region ====================== ææ ç®¡çè¡¨æ ¼æ°æ®ï¼table init ====================== |
| | | const tableLoading = ref(false); |
| | | const tableData = ref([]); |
| | | |
| | | const tableColumns = ref([]); |
| | | |
| | | const tableCheckData = computed(() => { |
| | | return tableColumns.value.map((item) => { |
| | | return { |
| | | prop: item.name, |
| | | label: item.title, |
| | | get isShow() { |
| | | return item.isShow; |
| | | }, |
| | | set isShow(value) { |
| | | item.isShow = value; |
| | | }, |
| | | }; |
| | | }); |
| | | }); |
| | | |
| | | const visibleTableColumns = computed(() => { |
| | | return tableColumns.value.filter((item) => item.isShow); |
| | | }); |
| | | |
| | | //#endregion |
| | | |
| | | const getIndexMapItem = (columns) => { |
| | | return new Map<number, any>( |
| | | columns.map((item, index) => { |
| | | return [index, item]; |
| | | }) |
| | | ); |
| | | }; |
| | | |
| | | //#region ====================== æ¥è¯¢ ====================== |
| | | |
| | | const parseRecordData = (values, columns) => { |
| | | const indexMapItem = getIndexMapItem(columns); |
| | | return (values || []).map((item, index) => { |
| | | const row = {} as any; |
| | | item?.forEach((item, index) => { |
| | | row[indexMapItem.get(index).name] = item; |
| | | }); |
| | | return row; |
| | | }); |
| | | }; |
| | | |
| | | //#endregion |
| | | watch( |
| | | () => dialogIsShow.value, |
| | | (val) => { |
| | | if (!val) return; |
| | | tableColumns.value = (props.data?.model?.columns || []).map((item) => { |
| | | return { |
| | | name: item, |
| | | title: item, |
| | | isShow: true, |
| | | }; |
| | | }); |
| | | tableData.value = parseRecordData(props.data?.model?.values || [], tableColumns.value); |
| | | } |
| | | ); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .set-permission { |
| | | padding-block: 16px; |
| | | padding-block-end: 0; |
| | | } |
| | | .set-form { |
| | | display: block; |
| | | box-sizing: border-box; |
| | | height: 100%; |
| | | padding-block: 16px; |
| | | .set-form-item { |
| | | font-weight: 500; |
| | | color: #667085; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | |
| | | :deep(.el-dialog__body) { |
| | | height: calc(90vh - 111px) !important; |
| | | } |
| | | </style> |
| | | <style lang="scss"> |
| | | .limit-height { |
| | | .el-dialog__body { |
| | | height: calc(90vh - 111px) !important; |
| | | } |
| | | } |
| | | |
| | | .yw-layout-main { |
| | | .el-card__body { |
| | | padding: 10px; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | v-for="(item, index) in msg.attachList" |
| | | :key="index" |
| | | class="flex items-center gap-2 bg-[#e9e9e9] px-2 py-3 rounded-lg w-[220px] relative group" |
| | | @click="openAttachPreview(item)" |
| | | :class="{ 'cursor-pointer': item.type === 'table' }" |
| | | > |
| | | <template v-if="item.type === 'file'"> |
| | | <el-image |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <BusinessTablePreview :data="attachPreviewData" v-model="attachPreviewIsShow" /> |
| | | <!-- #endregion --> |
| | | |
| | | <div class="flex px-4 rounded-lg relative flex-row-reverse items-center" :key="`${msg.historyId}_${msg.role}`"> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="UserMsg"> |
| | | import { useClipboard } from '@vueuse/core'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { AnswerState, answerTypeMapCom, roleImageMap, type ChatMessage } from '../model/types'; |
| | | import { isSharePage } from '/@/stores/chatRoom'; |
| | | import { onClickOutside, useClipboard } from '@vueuse/core'; |
| | | import { ref } from 'vue'; |
| | | import BusinessTablePreview from '../components/playBar/businessTablePreview/index.vue'; |
| | | import { Attach } from '../components/playBar/hook/useAttach'; |
| | | |
| | | const emit = defineEmits<{ |
| | | (event: 'copyMsg', msgObj: ChatMessage): void; |
| | |
| | | const shareClick = (msg) => { |
| | | emit('shareClick', msg); |
| | | }; |
| | | |
| | | //#region ====================== éä»¶é¢è§ ====================== |
| | | const attachPreviewIsShow = ref(false); |
| | | const attachPreviewData = ref<Attach>(); |
| | | const openAttachPreview = (item: Attach) => { |
| | | if (item.type === 'file') return; |
| | | attachPreviewIsShow.value = true; |
| | | attachPreviewData.value = item; |
| | | }; |
| | | //#endregion |
| | | </script> |
| | | <style scoped lang="scss"></style> |
| | |
| | | <template> |
| | | <el-dropdown trigger="click" placement="bottom-end" :hideOnClick="false"> |
| | | <span |
| | | title="ç¹å»éæ©æ¾ç¤ºå" |
| | | :title="title" |
| | | class="rounded-full p-1.5 border-[1.5px] hover:text-blue-400 border-gray-200 border-solid cursor-pointer ywifont ywicon-grid !text-[13px] h-fit" |
| | | ></span> |
| | | |
| | |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: 'ç¹å»éæ©æ¾ç¤ºå', |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits<{ |