资料管理界面新增查询编辑功能添加了确定所属知识库的功能,按钮管理界面的增删改查及界面按钮开关实时操作开启和关闭功能
正在显示
16 个修改的文件
包含
845 行增加
和
235 行删除
| @@ -12,16 +12,16 @@ | @@ -12,16 +12,16 @@ | ||
| 12 | /> | 12 | /> |
| 13 | </Teleport> | 13 | </Teleport> |
| 14 | <!-- update-end--author:liaozhiyang---date:20240517---for:【TV360X-35】富文本,图片上传遮挡其他按钮 --> | 14 | <!-- update-end--author:liaozhiyang---date:20240517---for:【TV360X-35】富文本,图片上传遮挡其他按钮 --> |
| 15 | - <Editor :id="tinymceId" ref="elRef" :disabled="disabled" :init="initOptions" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline"></Editor> | 15 | + <Editor :id="tinymceId" ref="elRef" :disabled="disabled" :init="initOptions" :style="{ visibility: 'hidden' }" v-if="!initOptions.inline" /> |
| 16 | <slot v-else></slot> | 16 | <slot v-else></slot> |
| 17 | - <ProcessMask ref="processMaskRef" :show="showUploadMask"/> | 17 | + <ProcessMask ref="processMaskRef" :show="showUploadMask" /> |
| 18 | </div> | 18 | </div> |
| 19 | </template> | 19 | </template> |
| 20 | 20 | ||
| 21 | <script lang="ts"> | 21 | <script lang="ts"> |
| 22 | import type { RawEditorOptions } from 'tinymce'; | 22 | import type { RawEditorOptions } from 'tinymce'; |
| 23 | import tinymce from 'tinymce/tinymce'; | 23 | import tinymce from 'tinymce/tinymce'; |
| 24 | - import Editor from '@tinymce/tinymce-vue' | 24 | + import Editor from '@tinymce/tinymce-vue'; |
| 25 | import 'tinymce/themes/silver'; | 25 | import 'tinymce/themes/silver'; |
| 26 | import 'tinymce/icons/default/icons'; | 26 | import 'tinymce/icons/default/icons'; |
| 27 | import 'tinymce/models/dom'; | 27 | import 'tinymce/models/dom'; |
| @@ -83,27 +83,27 @@ | @@ -83,27 +83,27 @@ | ||
| 83 | }, | 83 | }, |
| 84 | showImageUpload: { | 84 | showImageUpload: { |
| 85 | type: Boolean, | 85 | type: Boolean, |
| 86 | - default: true, | 86 | + default: false, |
| 87 | }, | 87 | }, |
| 88 | showUploadMask: { | 88 | showUploadMask: { |
| 89 | type: Boolean, | 89 | type: Boolean, |
| 90 | - default: false, | 90 | + default: true, |
| 91 | }, | 91 | }, |
| 92 | //是否聚焦 | 92 | //是否聚焦 |
| 93 | - autoFocus:{ | 93 | + autoFocus: { |
| 94 | type: Boolean, | 94 | type: Boolean, |
| 95 | default: true, | 95 | default: true, |
| 96 | - } | 96 | + }, |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | export default defineComponent({ | 99 | export default defineComponent({ |
| 100 | name: 'Tinymce', | 100 | name: 'Tinymce', |
| 101 | - components: { ImgUpload,Editor,ProcessMask }, | 101 | + components: { ImgUpload, Editor, ProcessMask }, |
| 102 | inheritAttrs: false, | 102 | inheritAttrs: false, |
| 103 | props: tinymceProps as any, | 103 | props: tinymceProps as any, |
| 104 | emits: ['change', 'update:modelValue', 'inited', 'init-error'], | 104 | emits: ['change', 'update:modelValue', 'inited', 'init-error'], |
| 105 | setup(props, { emit, attrs }) { | 105 | setup(props, { emit, attrs }) { |
| 106 | - console.log("---Tinymce---初始化---") | 106 | + console.log('---Tinymce---初始化---'); |
| 107 | 107 | ||
| 108 | const editorRef = ref<Nullable<any>>(null); | 108 | const editorRef = ref<Nullable<any>>(null); |
| 109 | const fullscreen = ref(false); | 109 | const fullscreen = ref(false); |
| @@ -155,6 +155,8 @@ | @@ -155,6 +155,8 @@ | ||
| 155 | language: langName.value, | 155 | language: langName.value, |
| 156 | branding: false, | 156 | branding: false, |
| 157 | default_link_target: '_blank', | 157 | default_link_target: '_blank', |
| 158 | + forced_root_block: false, | ||
| 159 | + force_br_newlines: true, // 换行使用<br> | ||
| 158 | link_title: false, | 160 | link_title: false, |
| 159 | object_resizing: true, | 161 | object_resizing: true, |
| 160 | toolbar_mode: 'sliding', | 162 | toolbar_mode: 'sliding', |
| @@ -166,26 +168,26 @@ | @@ -166,26 +168,26 @@ | ||
| 166 | skin_url: publicPath + 'resource/tinymce/skins/ui/' + skinName.value, | 168 | skin_url: publicPath + 'resource/tinymce/skins/ui/' + skinName.value, |
| 167 | images_upload_handler: (blobInfo, process) => | 169 | images_upload_handler: (blobInfo, process) => |
| 168 | new Promise((resolve, reject) => { | 170 | new Promise((resolve, reject) => { |
| 169 | - let params = { | ||
| 170 | - file: blobInfo.blob(), | ||
| 171 | - filename: blobInfo.filename(), | ||
| 172 | - data: { biz: 'jeditor', jeditor: '1' }, | ||
| 173 | - }; | ||
| 174 | - const uploadSuccess = (res) => { | ||
| 175 | - if (res.success) { | ||
| 176 | - if (res.message == 'local') { | ||
| 177 | - const img = 'data:image/jpeg;base64,' + blobInfo.base64(); | ||
| 178 | - resolve(img); | 171 | + let params = { |
| 172 | + file: blobInfo.blob(), | ||
| 173 | + filename: blobInfo.filename(), | ||
| 174 | + data: { biz: 'jeditor', jeditor: '1' }, | ||
| 175 | + }; | ||
| 176 | + const uploadSuccess = (res) => { | ||
| 177 | + if (res.success) { | ||
| 178 | + if (res.message == 'local') { | ||
| 179 | + const img = 'data:image/jpeg;base64,' + blobInfo.base64(); | ||
| 180 | + resolve(img); | ||
| 181 | + } else { | ||
| 182 | + let img = getFileAccessHttpUrl(res.message); | ||
| 183 | + resolve(img); | ||
| 184 | + } | ||
| 179 | } else { | 185 | } else { |
| 180 | - let img = getFileAccessHttpUrl(res.message); | ||
| 181 | - resolve(img); | ||
| 182 | - } | ||
| 183 | - } else { | ||
| 184 | reject('上传失败!'); | 186 | reject('上传失败!'); |
| 185 | - } | ||
| 186 | - }; | ||
| 187 | - uploadFile(params, uploadSuccess); | ||
| 188 | - }), | 187 | + } |
| 188 | + }; | ||
| 189 | + uploadFile(params, uploadSuccess); | ||
| 190 | + }), | ||
| 189 | content_css: publicPath + 'resource/tinymce/skins/ui/' + skinName.value + '/content.min.css', | 191 | content_css: publicPath + 'resource/tinymce/skins/ui/' + skinName.value + '/content.min.css', |
| 190 | ...options, | 192 | ...options, |
| 191 | setup: (editor: any) => { | 193 | setup: (editor: any) => { |
| @@ -217,7 +219,7 @@ | @@ -217,7 +219,7 @@ | ||
| 217 | if (!editor) { | 219 | if (!editor) { |
| 218 | return; | 220 | return; |
| 219 | } | 221 | } |
| 220 | - editor?.setMode && editor.setMode(attrs.disabled ? 'readonly' : 'design'); | 222 | + editor?.setMode && editor.setMode(attrs.disabled ? 'readonly' : 'design'); |
| 221 | } | 223 | } |
| 222 | ); | 224 | ); |
| 223 | 225 | ||
| @@ -339,12 +341,12 @@ | @@ -339,12 +341,12 @@ | ||
| 339 | * @param fileList | 341 | * @param fileList |
| 340 | */ | 342 | */ |
| 341 | function handleLoading(fileLength,showMask){ | 343 | function handleLoading(fileLength,showMask){ |
| 342 | - if(fileLength && fileLength > 0){ | 344 | + if (fileLength && fileLength > 0) { |
| 343 | setTimeout(() => { | 345 | setTimeout(() => { |
| 344 | - props?.showUploadMask && processMaskRef.value.calcProcess(fileLength) | ||
| 345 | - },100) | ||
| 346 | - }else{ | ||
| 347 | - props?.showUploadMask && (processMaskRef.value.showMask = showMask); | 346 | + props?.showUploadMask && processMaskRef.value.calcProcess(fileLength); |
| 347 | + }, 100); | ||
| 348 | + } else { | ||
| 349 | + props?.showUploadMask && (processMaskRef.value.showMask = showMask); | ||
| 348 | } | 350 | } |
| 349 | } | 351 | } |
| 350 | function getUploadingImgName(name: string) { | 352 | function getUploadingImgName(name: string) { |
| @@ -421,7 +423,7 @@ | @@ -421,7 +423,7 @@ | ||
| 421 | targetElem, | 423 | targetElem, |
| 422 | 424 | ||
| 423 | handleLoading, | 425 | handleLoading, |
| 424 | - processMaskRef | 426 | + processMaskRef, |
| 425 | }; | 427 | }; |
| 426 | }, | 428 | }, |
| 427 | }); | 429 | }); |
| @@ -441,7 +443,7 @@ | @@ -441,7 +443,7 @@ | ||
| 441 | visibility: hidden; | 443 | visibility: hidden; |
| 442 | } | 444 | } |
| 443 | .tox:not(.tox-tinymce-inline) .tox-editor-header { | 445 | .tox:not(.tox-tinymce-inline) .tox-editor-header { |
| 444 | - padding:0; | 446 | + padding: 0; |
| 445 | } | 447 | } |
| 446 | // update-begin--author:liaozhiyang---date:20240527---for:【TV360X-329】富文本禁用状态下工具栏划过边框丢失 | 448 | // update-begin--author:liaozhiyang---date:20240527---for:【TV360X-329】富文本禁用状态下工具栏划过边框丢失 |
| 447 | .tox .tox-tbtn--disabled, | 449 | .tox .tox-tbtn--disabled, |
| @@ -456,7 +458,9 @@ | @@ -456,7 +458,9 @@ | ||
| 456 | 458 | ||
| 457 | html[data-theme='dark'] { | 459 | html[data-theme='dark'] { |
| 458 | .@{prefix-cls} { | 460 | .@{prefix-cls} { |
| 459 | - .tox .tox-edit-area__iframe {background-color: #141414;} | 461 | + .tox .tox-edit-area__iframe { |
| 462 | + background-color: #141414; | ||
| 463 | + } | ||
| 460 | } | 464 | } |
| 461 | } | 465 | } |
| 462 | </style> | 466 | </style> |
| @@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
| 8 | </template> | 8 | </template> |
| 9 | <script lang="ts" setup> | 9 | <script lang="ts" setup> |
| 10 | import { computed, ref } from 'vue'; | 10 | import { computed, ref } from 'vue'; |
| 11 | - import {useDesign} from "@/hooks/web/useDesign"; | 11 | + import { useDesign } from '@/hooks/web/useDesign'; |
| 12 | 12 | ||
| 13 | const props = defineProps({ | 13 | const props = defineProps({ |
| 14 | backColor: { | 14 | backColor: { |
| @@ -67,44 +67,42 @@ | @@ -67,44 +67,42 @@ | ||
| 67 | </script> | 67 | </script> |
| 68 | 68 | ||
| 69 | <style lang="less"> | 69 | <style lang="less"> |
| 70 | -//noinspection LessUnresolvedVariable | ||
| 71 | -@prefix-cls: ~'@{namespace}-tinymce-process-mask'; | 70 | + //noinspection LessUnresolvedVariable |
| 71 | + @prefix-cls: ~'@{namespace}-tinymce-process-mask'; | ||
| 72 | 72 | ||
| 73 | -.@{prefix-cls} { | ||
| 74 | - | ||
| 75 | - & { | ||
| 76 | - position: absolute; /* 或者使用固定定位等其他方式 */ | ||
| 77 | - top: 0; | ||
| 78 | - left: 0; | ||
| 79 | - right: 0; | ||
| 80 | - bottom: 0; | ||
| 81 | - background-color: rgba(0, 0, 0, 0.5); /* 半透明遮罩 */ | ||
| 82 | - display: flex; | ||
| 83 | - justify-content: center; | ||
| 84 | - align-items: center; | ||
| 85 | - overflow: hidden; | ||
| 86 | - z-index: 99; | ||
| 87 | - } | 73 | + .@{prefix-cls} { |
| 74 | + & { | ||
| 75 | + position: absolute; /* 或者使用固定定位等其他方式 */ | ||
| 76 | + top: 0; | ||
| 77 | + left: 0; | ||
| 78 | + right: 0; | ||
| 79 | + bottom: 0; | ||
| 80 | + background-color: rgba(0, 0, 0, 0.5); /* 半透明遮罩 */ | ||
| 81 | + display: flex; | ||
| 82 | + justify-content: center; | ||
| 83 | + align-items: center; | ||
| 84 | + overflow: hidden; | ||
| 85 | + z-index: 99; | ||
| 86 | + } | ||
| 88 | 87 | ||
| 89 | - .progress-bar-rear { | ||
| 90 | - width: 100px; /* 进度条宽度 */ | ||
| 91 | - height: 10px; /* 进度条高度 */ | ||
| 92 | - background-color: v-bind(rearColor); /* 进度条颜色 */ | ||
| 93 | - border-radius: 4px; | ||
| 94 | - } | 88 | + .progress-bar-rear { |
| 89 | + width: 100px; /* 进度条宽度 */ | ||
| 90 | + height: 10px; /* 进度条高度 */ | ||
| 91 | + background-color: v-bind(rearColor); /* 进度条颜色 */ | ||
| 92 | + border-radius: 4px; | ||
| 93 | + } | ||
| 95 | 94 | ||
| 96 | - .progress-bar-front { | ||
| 97 | - height: 10px; /* 进度条高度 */ | ||
| 98 | - background-color: v-bind(frontColor); /* 进度条颜色 */ | ||
| 99 | - border-radius: 4px; | ||
| 100 | - } | 95 | + .progress-bar-front { |
| 96 | + height: 10px; /* 进度条高度 */ | ||
| 97 | + background-color: v-bind(frontColor); /* 进度条颜色 */ | ||
| 98 | + border-radius: 4px; | ||
| 99 | + } | ||
| 101 | 100 | ||
| 102 | - .value { | ||
| 103 | - color: #fff; | ||
| 104 | - margin-left: 5px; | ||
| 105 | - font-size: 16px; | ||
| 106 | - font-weight: 600; | 101 | + .value { |
| 102 | + color: #fff; | ||
| 103 | + margin-left: 5px; | ||
| 104 | + font-size: 16px; | ||
| 105 | + font-weight: 600; | ||
| 106 | + } | ||
| 107 | } | 107 | } |
| 108 | -} | ||
| 109 | - | ||
| 110 | </style> | 108 | </style> |
| @@ -12,8 +12,6 @@ export const toolbar = | @@ -12,8 +12,6 @@ export const toolbar = | ||
| 12 | 12 | ||
| 13 | export const simplePlugins = 'lists image link fullscreen'; | 13 | export const simplePlugins = 'lists image link fullscreen'; |
| 14 | 14 | ||
| 15 | -export const simpleToolbar = [ | ||
| 16 | - 'undo redo styles bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen', | ||
| 17 | -]; | 15 | +export const simpleToolbar = ['styles bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link ']; |
| 18 | 16 | ||
| 19 | export const menubar = 'file edit insert view format table'; | 17 | export const menubar = 'file edit insert view format table'; |
| 1 | +import { defHttp } from '/@/utils/http/axios'; | ||
| 2 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
| 3 | + | ||
| 4 | +const { createConfirm } = useMessage(); | ||
| 5 | + | ||
| 6 | +enum Api { | ||
| 7 | + list = '/airagbutton/airagButton/list', | ||
| 8 | + save = '/airagbutton/airagButton/add', | ||
| 9 | + edit = '/airagbutton/airagButton/edit', | ||
| 10 | + deleteOne = '/airagbutton/airagButton/delete', | ||
| 11 | + deleteBatch = '/airagbutton/airagButton/deleteBatch', | ||
| 12 | + importExcel = '/airagbutton/airagButton/importExcel', | ||
| 13 | + exportXls = '/airagbutton/airagButton/exportXls', | ||
| 14 | +} | ||
| 15 | +/** | ||
| 16 | + * 导出api | ||
| 17 | + * @param params | ||
| 18 | + */ | ||
| 19 | +export const getExportUrl = Api.exportXls; | ||
| 20 | +/** | ||
| 21 | + * 导入api | ||
| 22 | + */ | ||
| 23 | +export const getImportUrl = Api.importExcel; | ||
| 24 | +/** | ||
| 25 | + * 列表接口 | ||
| 26 | + * @param params | ||
| 27 | + */ | ||
| 28 | +export const list = (params) => defHttp.get({ url: Api.list, params }); | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * 删除单个 | ||
| 32 | + */ | ||
| 33 | +export const deleteOne = (params, handleSuccess) => { | ||
| 34 | + return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { | ||
| 35 | + handleSuccess(); | ||
| 36 | + }); | ||
| 37 | +}; | ||
| 38 | +/** | ||
| 39 | + * 批量删除 | ||
| 40 | + * @param params | ||
| 41 | + */ | ||
| 42 | +export const batchDelete = (params, handleSuccess) => { | ||
| 43 | + createConfirm({ | ||
| 44 | + iconType: 'warning', | ||
| 45 | + title: '确认删除', | ||
| 46 | + content: '是否删除选中数据', | ||
| 47 | + okText: '确认', | ||
| 48 | + cancelText: '取消', | ||
| 49 | + onOk: () => { | ||
| 50 | + return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => { | ||
| 51 | + handleSuccess(); | ||
| 52 | + }); | ||
| 53 | + }, | ||
| 54 | + }); | ||
| 55 | +}; | ||
| 56 | +/** | ||
| 57 | + * 保存或者更新 | ||
| 58 | + * @param params | ||
| 59 | + * @param isUpdate - 是否为更新操作 | ||
| 60 | + */ | ||
| 61 | +export const saveOrUpdate = (params, isUpdate) => { | ||
| 62 | + const url = isUpdate ? Api.edit : Api.save; | ||
| 63 | + return defHttp.post({ url: url, params }); | ||
| 64 | +}; |
| 1 | +import { BasicColumn } from '/@/components/Table'; | ||
| 2 | +import { FormSchema } from '/@/components/Table'; | ||
| 3 | +import { Switch } from 'ant-design-vue'; | ||
| 4 | +import { h, reactive } from 'vue'; | ||
| 5 | +import { saveOrUpdate } from '@/views/super/airag/airagbutton/AiragButton.api'; | ||
| 6 | +//列表数据 | ||
| 7 | +export const columns: BasicColumn[] = [ | ||
| 8 | + { | ||
| 9 | + title: '按钮名称', | ||
| 10 | + align: 'center', | ||
| 11 | + dataIndex: 'buttonName', | ||
| 12 | + }, | ||
| 13 | + { | ||
| 14 | + title: '按钮开关', | ||
| 15 | + align: 'center', | ||
| 16 | + dataIndex: 'buttonSwitch', | ||
| 17 | + customRender: ({ text, record }) => { | ||
| 18 | + return h(Switch, { | ||
| 19 | + checked: text === 'Y', | ||
| 20 | + loading: switchLoading[record.id], | ||
| 21 | + onChange: (checked: boolean) => handleSwitchChange(checked, record), | ||
| 22 | + }); | ||
| 23 | + }, | ||
| 24 | + }, | ||
| 25 | + { | ||
| 26 | + title: '按钮值', | ||
| 27 | + align: 'center', | ||
| 28 | + dataIndex: 'buttonValues', | ||
| 29 | + }, | ||
| 30 | +]; | ||
| 31 | +// 定义开关状态映射 | ||
| 32 | +const switchLoading = reactive<Record<string, boolean>>({}); | ||
| 33 | + | ||
| 34 | +// 处理开关状态变化 | ||
| 35 | +async function handleSwitchChange(checked: boolean, record: Recordable) { | ||
| 36 | + const newValue = checked ? 'Y' : 'N'; | ||
| 37 | + const oldValue = record.buttonSwitch; | ||
| 38 | + | ||
| 39 | + // 立即更新本地状态 | ||
| 40 | + record.buttonSwitch = newValue; | ||
| 41 | + switchLoading[record.id] = true; | ||
| 42 | + | ||
| 43 | + try { | ||
| 44 | + // 调用API更新后端 | ||
| 45 | + await saveOrUpdate( | ||
| 46 | + { | ||
| 47 | + id: record.id, | ||
| 48 | + buttonSwitch: newValue, | ||
| 49 | + }, | ||
| 50 | + true | ||
| 51 | + ); | ||
| 52 | + } catch { | ||
| 53 | + // 出错时回滚状态 | ||
| 54 | + record.buttonSwitch = oldValue; | ||
| 55 | + } finally { | ||
| 56 | + switchLoading[record.id] = false; | ||
| 57 | + } | ||
| 58 | +} | ||
| 59 | +//查询数据 | ||
| 60 | +export const searchFormSchema: FormSchema[] = [ | ||
| 61 | + { | ||
| 62 | + label: '按钮名称', | ||
| 63 | + field: 'buttonName', | ||
| 64 | + component: 'JInput', | ||
| 65 | + }, | ||
| 66 | + { | ||
| 67 | + label: '按钮值', | ||
| 68 | + field: 'buttonValues', | ||
| 69 | + component: 'JInput', | ||
| 70 | + }, | ||
| 71 | +]; | ||
| 72 | +//表单数据 | ||
| 73 | +export const formSchema: FormSchema[] = [ | ||
| 74 | + { | ||
| 75 | + label: '按钮名称', | ||
| 76 | + field: 'buttonName', | ||
| 77 | + component: 'Input', | ||
| 78 | + required: true, | ||
| 79 | + }, | ||
| 80 | + { | ||
| 81 | + label: '按钮开关', | ||
| 82 | + field: 'buttonSwitch', | ||
| 83 | + component: 'JSwitch', | ||
| 84 | + required: true, | ||
| 85 | + componentProps: {}, | ||
| 86 | + }, | ||
| 87 | + { | ||
| 88 | + label: '按钮值', | ||
| 89 | + field: 'buttonValues', | ||
| 90 | + component: 'Input', | ||
| 91 | + required: true, | ||
| 92 | + }, | ||
| 93 | + // TODO 主键隐藏字段,目前写死为ID | ||
| 94 | + { | ||
| 95 | + label: '', | ||
| 96 | + field: 'id', | ||
| 97 | + component: 'Input', | ||
| 98 | + show: false, | ||
| 99 | + }, | ||
| 100 | +]; | ||
| 101 | + | ||
| 102 | +// 高级查询数据 | ||
| 103 | +export const superQuerySchema = { | ||
| 104 | + buttonName: { title: '按钮名称', order: 0, view: 'text', type: 'string' }, | ||
| 105 | + buttonSwitch: { title: '按钮开关', order: 1, view: 'switch', type: 'string' }, | ||
| 106 | + buttonValues: { title: '按钮值', order: 2, view: 'text', type: 'string' }, | ||
| 107 | +}; | ||
| 108 | + | ||
| 109 | +/** | ||
| 110 | + * 流程表单调用这个方法获取formSchema | ||
| 111 | + * @param param | ||
| 112 | + */ | ||
| 113 | +export function getBpmFormSchema(_formData): FormSchema[] { | ||
| 114 | + // 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema | ||
| 115 | + return formSchema; | ||
| 116 | +} |
| 1 | +<template> | ||
| 2 | + <div> | ||
| 3 | + <!--引用表格--> | ||
| 4 | + <BasicTable @register="registerTable" :rowSelection="rowSelection"> | ||
| 5 | + <!--插槽:table标题--> | ||
| 6 | + <template #tableTitle> | ||
| 7 | + <a-button type="primary" v-auth="'airagbutton:airag_button:add'" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button> | ||
| 8 | + <a-button type="primary" v-auth="'airagbutton:airag_button:exportXls'" preIcon="ant-design:export-outlined" @click="onExportXls"> | ||
| 9 | + 导出</a-button | ||
| 10 | + > | ||
| 11 | + <j-upload-button type="primary" v-auth="'airagbutton:airag_button:importExcel'" preIcon="ant-design:import-outlined" @click="onImportXls" | ||
| 12 | + >导入</j-upload-button | ||
| 13 | + > | ||
| 14 | + <a-dropdown v-if="selectedRowKeys.length > 0"> | ||
| 15 | + <template #overlay> | ||
| 16 | + <a-menu> | ||
| 17 | + <a-menu-item key="1" @click="batchHandleDelete"> | ||
| 18 | + <Icon icon="ant-design:delete-outlined" /> | ||
| 19 | + 删除 | ||
| 20 | + </a-menu-item> | ||
| 21 | + </a-menu> | ||
| 22 | + </template> | ||
| 23 | + <a-button v-auth="'airagbutton:airag_button:deleteBatch'" | ||
| 24 | + >批量操作 | ||
| 25 | + <Icon icon="mdi:chevron-down" /> | ||
| 26 | + </a-button> | ||
| 27 | + </a-dropdown> | ||
| 28 | + <!-- 高级查询 --> | ||
| 29 | + <super-query :config="superQueryConfig" @search="handleSuperQuery" /> | ||
| 30 | + </template> | ||
| 31 | + <!--操作栏--> | ||
| 32 | + <template #action="{ record }"> | ||
| 33 | + <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" /> | ||
| 34 | + </template> | ||
| 35 | + <!--字段回显插槽--> | ||
| 36 | + <template #bodyCell="{ column, record, index, text }"> </template> | ||
| 37 | + </BasicTable> | ||
| 38 | + <!-- 表单区域 --> | ||
| 39 | + <AiragButtonModal @register="registerModal" @success="handleSuccess" /> | ||
| 40 | + </div> | ||
| 41 | +</template> | ||
| 42 | + | ||
| 43 | +<script lang="ts" name="airagbutton-airagButton" setup> | ||
| 44 | + import { ref, reactive } from 'vue'; | ||
| 45 | + import { BasicTable, TableAction } from '/@/components/Table'; | ||
| 46 | + import { useModal } from '/@/components/Modal'; | ||
| 47 | + import { useListPage } from '/@/hooks/system/useListPage'; | ||
| 48 | + import AiragButtonModal from './components/AiragButtonModal.vue'; | ||
| 49 | + import { columns, searchFormSchema, superQuerySchema } from './AiragButton.data'; | ||
| 50 | + import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, saveOrUpdate } from './AiragButton.api'; | ||
| 51 | + import { useUserStore } from '/@/store/modules/user'; | ||
| 52 | + const queryParam = reactive<any>({}); | ||
| 53 | + const checkedKeys = ref<Array<string | number>>([]); | ||
| 54 | + const userStore = useUserStore(); | ||
| 55 | + //注册model | ||
| 56 | + const [registerModal, { openModal }] = useModal(); | ||
| 57 | + //注册table数据 | ||
| 58 | + const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ | ||
| 59 | + tableProps: { | ||
| 60 | + title: '按钮表单', | ||
| 61 | + api: list, | ||
| 62 | + columns, | ||
| 63 | + canResize: false, | ||
| 64 | + formConfig: { | ||
| 65 | + //labelWidth: 120, | ||
| 66 | + schemas: searchFormSchema, | ||
| 67 | + autoSubmitOnEnter: true, | ||
| 68 | + showAdvancedButton: true, | ||
| 69 | + fieldMapToNumber: [], | ||
| 70 | + fieldMapToTime: [], | ||
| 71 | + }, | ||
| 72 | + actionColumn: { | ||
| 73 | + width: 120, | ||
| 74 | + fixed: 'right', | ||
| 75 | + }, | ||
| 76 | + beforeFetch: (params) => { | ||
| 77 | + return Object.assign(params, queryParam); | ||
| 78 | + }, | ||
| 79 | + }, | ||
| 80 | + exportConfig: { | ||
| 81 | + name: '按钮表单', | ||
| 82 | + url: getExportUrl, | ||
| 83 | + params: queryParam, | ||
| 84 | + }, | ||
| 85 | + importConfig: { | ||
| 86 | + url: getImportUrl, | ||
| 87 | + success: handleSuccess, | ||
| 88 | + }, | ||
| 89 | + }); | ||
| 90 | + | ||
| 91 | + const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext; | ||
| 92 | + | ||
| 93 | + // 高级查询配置 | ||
| 94 | + const superQueryConfig = reactive(superQuerySchema); | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * 高级查询事件 | ||
| 98 | + */ | ||
| 99 | + function handleSuperQuery(params) { | ||
| 100 | + Object.keys(params).map((k) => { | ||
| 101 | + queryParam[k] = params[k]; | ||
| 102 | + }); | ||
| 103 | + reload(); | ||
| 104 | + } | ||
| 105 | + /** | ||
| 106 | + * 新增事件 | ||
| 107 | + */ | ||
| 108 | + function handleAdd() { | ||
| 109 | + openModal(true, { | ||
| 110 | + isUpdate: false, | ||
| 111 | + showFooter: true, | ||
| 112 | + }); | ||
| 113 | + } | ||
| 114 | + /** | ||
| 115 | + * 编辑事件 | ||
| 116 | + */ | ||
| 117 | + function handleEdit(record: Recordable) { | ||
| 118 | + openModal(true, { | ||
| 119 | + record, | ||
| 120 | + isUpdate: true, | ||
| 121 | + showFooter: true, | ||
| 122 | + }); | ||
| 123 | + } | ||
| 124 | + /** | ||
| 125 | + * 详情 | ||
| 126 | + */ | ||
| 127 | + function handleDetail(record: Recordable) { | ||
| 128 | + openModal(true, { | ||
| 129 | + record, | ||
| 130 | + isUpdate: true, | ||
| 131 | + showFooter: false, | ||
| 132 | + }); | ||
| 133 | + } | ||
| 134 | + /** | ||
| 135 | + * 删除事件 | ||
| 136 | + */ | ||
| 137 | + async function handleDelete(record) { | ||
| 138 | + await deleteOne({ id: record.id }, handleSuccess); | ||
| 139 | + } | ||
| 140 | + /** | ||
| 141 | + * 批量删除事件 | ||
| 142 | + */ | ||
| 143 | + async function batchHandleDelete() { | ||
| 144 | + await batchDelete({ ids: selectedRowKeys.value }, handleSuccess); | ||
| 145 | + } | ||
| 146 | + /** | ||
| 147 | + * 成功回调 | ||
| 148 | + */ | ||
| 149 | + function handleSuccess() { | ||
| 150 | + (selectedRowKeys.value = []) && reload(); | ||
| 151 | + } | ||
| 152 | + /** | ||
| 153 | + * 操作栏 | ||
| 154 | + */ | ||
| 155 | + function getTableAction(record) { | ||
| 156 | + return [ | ||
| 157 | + { | ||
| 158 | + label: '编辑', | ||
| 159 | + onClick: handleEdit.bind(null, record), | ||
| 160 | + auth: 'airagbutton:airag_button:edit', | ||
| 161 | + }, | ||
| 162 | + ]; | ||
| 163 | + } | ||
| 164 | + /** | ||
| 165 | + * 下拉操作栏 | ||
| 166 | + */ | ||
| 167 | + function getDropDownAction(record) { | ||
| 168 | + return [ | ||
| 169 | + { | ||
| 170 | + label: '详情', | ||
| 171 | + onClick: handleDetail.bind(null, record), | ||
| 172 | + }, | ||
| 173 | + { | ||
| 174 | + label: '删除', | ||
| 175 | + popConfirm: { | ||
| 176 | + title: '是否确认删除', | ||
| 177 | + confirm: handleDelete.bind(null, record), | ||
| 178 | + placement: 'topLeft', | ||
| 179 | + }, | ||
| 180 | + auth: 'airagbutton:airag_button:delete', | ||
| 181 | + }, | ||
| 182 | + ]; | ||
| 183 | + } | ||
| 184 | +</script> | ||
| 185 | + | ||
| 186 | +<style lang="less" scoped> | ||
| 187 | + :deep(.ant-picker), | ||
| 188 | + :deep(.ant-input-number) { | ||
| 189 | + width: 100%; | ||
| 190 | + } | ||
| 191 | +</style> |
| 1 | +<template> | ||
| 2 | + <div style="min-height: 400px"> | ||
| 3 | + <BasicForm @register="registerForm" /> | ||
| 4 | + <div style="width: 100%; text-align: center" v-if="!formDisabled"> | ||
| 5 | + <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button> | ||
| 6 | + </div> | ||
| 7 | + </div> | ||
| 8 | +</template> | ||
| 9 | + | ||
| 10 | +<script lang="ts"> | ||
| 11 | + import { BasicForm, useForm } from '/@/components/Form/index'; | ||
| 12 | + import { computed, defineComponent } from 'vue'; | ||
| 13 | + import { defHttp } from '/@/utils/http/axios'; | ||
| 14 | + import { propTypes } from '/@/utils/propTypes'; | ||
| 15 | + import { getBpmFormSchema } from '../AiragButton.data'; | ||
| 16 | + import { saveOrUpdate } from '../AiragButton.api'; | ||
| 17 | + | ||
| 18 | + export default defineComponent({ | ||
| 19 | + name: 'AiragButtonForm', | ||
| 20 | + components: { | ||
| 21 | + BasicForm, | ||
| 22 | + }, | ||
| 23 | + props: { | ||
| 24 | + formData: propTypes.object.def({}), | ||
| 25 | + formBpm: propTypes.bool.def(true), | ||
| 26 | + }, | ||
| 27 | + setup(props) { | ||
| 28 | + const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({ | ||
| 29 | + labelWidth: 150, | ||
| 30 | + schemas: getBpmFormSchema(props.formData), | ||
| 31 | + showActionButtonGroup: false, | ||
| 32 | + baseColProps: { span: 24 }, | ||
| 33 | + }); | ||
| 34 | + | ||
| 35 | + const formDisabled = computed(() => { | ||
| 36 | + if (props.formData.disabled === false) { | ||
| 37 | + return false; | ||
| 38 | + } | ||
| 39 | + return true; | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + let formData = {}; | ||
| 43 | + const queryByIdUrl = '/airagbutton/airagButton/queryById'; | ||
| 44 | + async function initFormData() { | ||
| 45 | + let params = { id: props.formData.dataId }; | ||
| 46 | + const data = await defHttp.get({ url: queryByIdUrl, params }); | ||
| 47 | + formData = { ...data }; | ||
| 48 | + //设置表单的值 | ||
| 49 | + await setFieldsValue(formData); | ||
| 50 | + //默认是禁用 | ||
| 51 | + await setProps({ disabled: formDisabled.value }); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + async function submitForm() { | ||
| 55 | + let data = getFieldsValue(); | ||
| 56 | + let params = Object.assign({}, formData, data); | ||
| 57 | + console.log('表单数据', params); | ||
| 58 | + await saveOrUpdate(params, true); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + initFormData(); | ||
| 62 | + | ||
| 63 | + return { | ||
| 64 | + registerForm, | ||
| 65 | + formDisabled, | ||
| 66 | + submitForm, | ||
| 67 | + }; | ||
| 68 | + }, | ||
| 69 | + }); | ||
| 70 | +</script> |
| 1 | +<template> | ||
| 2 | + <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit"> | ||
| 3 | + <BasicForm @register="registerForm" name="AiragButtonForm" /> | ||
| 4 | + </BasicModal> | ||
| 5 | +</template> | ||
| 6 | + | ||
| 7 | +<script lang="ts" setup> | ||
| 8 | + import { ref, computed, unref } from 'vue'; | ||
| 9 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 10 | + import { BasicForm, useForm } from '/@/components/Form/index'; | ||
| 11 | + import { formSchema } from '../AiragButton.data'; | ||
| 12 | + import { saveOrUpdate } from '../AiragButton.api'; | ||
| 13 | + // Emits声明 | ||
| 14 | + const emit = defineEmits(['register', 'success']); | ||
| 15 | + const isUpdate = ref(true); | ||
| 16 | + const isDetail = ref(false); | ||
| 17 | + //表单配置 | ||
| 18 | + const [registerForm, { setProps, resetFields, setFieldsValue, validate, scrollToField }] = useForm({ | ||
| 19 | + labelWidth: 150, | ||
| 20 | + schemas: formSchema, | ||
| 21 | + showActionButtonGroup: false, | ||
| 22 | + baseColProps: { span: 24 }, | ||
| 23 | + }); | ||
| 24 | + //表单赋值 | ||
| 25 | + const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { | ||
| 26 | + //重置表单 | ||
| 27 | + await resetFields(); | ||
| 28 | + setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter }); | ||
| 29 | + isUpdate.value = !!data?.isUpdate; | ||
| 30 | + isDetail.value = !!data?.showFooter; | ||
| 31 | + if (unref(isUpdate)) { | ||
| 32 | + //表单赋值 | ||
| 33 | + await setFieldsValue({ | ||
| 34 | + ...data.record, | ||
| 35 | + }); | ||
| 36 | + } | ||
| 37 | + // 隐藏底部时禁用整个表单 | ||
| 38 | + setProps({ disabled: !data?.showFooter }); | ||
| 39 | + }); | ||
| 40 | + //设置标题 | ||
| 41 | + const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑')); | ||
| 42 | + //表单提交事件 | ||
| 43 | + async function handleSubmit(v) { | ||
| 44 | + try { | ||
| 45 | + let values = await validate(); | ||
| 46 | + setModalProps({ confirmLoading: true }); | ||
| 47 | + //提交表单 | ||
| 48 | + await saveOrUpdate(values, isUpdate.value); | ||
| 49 | + //关闭弹窗 | ||
| 50 | + closeModal(); | ||
| 51 | + //刷新列表 | ||
| 52 | + emit('success'); | ||
| 53 | + } catch ({ errorFields }) { | ||
| 54 | + if (errorFields) { | ||
| 55 | + const firstField = errorFields[0]; | ||
| 56 | + if (firstField) { | ||
| 57 | + scrollToField(firstField.name, { behavior: 'smooth', block: 'center' }); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + return Promise.reject(errorFields); | ||
| 61 | + } finally { | ||
| 62 | + setModalProps({ confirmLoading: false }); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | +</script> | ||
| 66 | + | ||
| 67 | +<style lang="less" scoped> | ||
| 68 | + /** 时间和数字输入框样式 */ | ||
| 69 | + :deep(.ant-input-number) { | ||
| 70 | + width: 100%; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + :deep(.ant-calendar-picker) { | ||
| 74 | + width: 100%; | ||
| 75 | + } | ||
| 76 | +</style> |
| @@ -20,29 +20,29 @@ export const list = async (params) => { | @@ -20,29 +20,29 @@ export const list = async (params) => { | ||
| 20 | try { | 20 | try { |
| 21 | const res = await defHttp.get({ | 21 | const res = await defHttp.get({ |
| 22 | url: Api.list, | 22 | url: Api.list, |
| 23 | - params: { ...params, size: 1000 } | 23 | + params: { ...params, size: 1000 }, |
| 24 | }); | 24 | }); |
| 25 | 25 | ||
| 26 | if (res?.records && Array.isArray(res.records)) { | 26 | if (res?.records && Array.isArray(res.records)) { |
| 27 | - res.records = res.records.map(item => ({ | 27 | + res.records = res.records.map((item) => ({ |
| 28 | ...item, | 28 | ...item, |
| 29 | ...item.metadata, | 29 | ...item.metadata, |
| 30 | question: item.question || '', | 30 | question: item.question || '', |
| 31 | - answer: item.answer || '' | 31 | + answer: item.answer || '', |
| 32 | })); | 32 | })); |
| 33 | } | 33 | } |
| 34 | return res; | 34 | return res; |
| 35 | } catch (error) { | 35 | } catch (error) { |
| 36 | - console.error("Error fetching question embeddings:", error); | 36 | + console.error('Error fetching question embeddings:', error); |
| 37 | return { | 37 | return { |
| 38 | records: [], | 38 | records: [], |
| 39 | total: 0, | 39 | total: 0, |
| 40 | size: 10, | 40 | size: 10, |
| 41 | current: 1, | 41 | current: 1, |
| 42 | - pages: 0 | 42 | + pages: 0, |
| 43 | }; | 43 | }; |
| 44 | } | 44 | } |
| 45 | -} | 45 | +}; |
| 46 | 46 | ||
| 47 | export const deleteOne = (params, handleSuccess) => { | 47 | export const deleteOne = (params, handleSuccess) => { |
| 48 | return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { | 48 | return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { |
| @@ -12,27 +12,27 @@ export const columns: BasicColumn[] = [ | @@ -12,27 +12,27 @@ export const columns: BasicColumn[] = [ | ||
| 12 | title: '问题', | 12 | title: '问题', |
| 13 | align: 'center', | 13 | align: 'center', |
| 14 | dataIndex: 'question', | 14 | dataIndex: 'question', |
| 15 | - width: 250 | 15 | + width: 250, |
| 16 | }, | 16 | }, |
| 17 | { | 17 | { |
| 18 | title: '回答', | 18 | title: '回答', |
| 19 | align: 'center', | 19 | align: 'center', |
| 20 | dataIndex: 'answer', | 20 | dataIndex: 'answer', |
| 21 | - width: 300 | 21 | + width: 300, |
| 22 | }, | 22 | }, |
| 23 | { | 23 | { |
| 24 | title: '原文', | 24 | title: '原文', |
| 25 | align: 'center', | 25 | align: 'center', |
| 26 | dataIndex: 'text', | 26 | dataIndex: 'text', |
| 27 | - width: 300 | 27 | + width: 300, |
| 28 | }, | 28 | }, |
| 29 | { | 29 | { |
| 30 | title: '元数据', | 30 | title: '元数据', |
| 31 | align: 'center', | 31 | align: 'center', |
| 32 | dataIndex: 'metadata', | 32 | dataIndex: 'metadata', |
| 33 | width: 200, | 33 | width: 200, |
| 34 | - customRender: ({ text }) => JSON.stringify(text || {}) | ||
| 35 | - } | 34 | + customRender: ({ text }) => JSON.stringify(text || {}), |
| 35 | + }, | ||
| 36 | ]; | 36 | ]; |
| 37 | 37 | ||
| 38 | export const searchFormSchema: FormSchema[] = [ | 38 | export const searchFormSchema: FormSchema[] = [ |
| @@ -40,14 +40,14 @@ export const searchFormSchema: FormSchema[] = [ | @@ -40,14 +40,14 @@ export const searchFormSchema: FormSchema[] = [ | ||
| 40 | field: 'question', | 40 | field: 'question', |
| 41 | label: '问题', | 41 | label: '问题', |
| 42 | component: 'Input', | 42 | component: 'Input', |
| 43 | - colProps: { span: 8 } | 43 | + colProps: { span: 8 }, |
| 44 | }, | 44 | }, |
| 45 | { | 45 | { |
| 46 | field: 'answer', | 46 | field: 'answer', |
| 47 | label: '回答', | 47 | label: '回答', |
| 48 | component: 'Input', | 48 | component: 'Input', |
| 49 | - colProps: { span: 8 } | ||
| 50 | - } | 49 | + colProps: { span: 8 }, |
| 50 | + }, | ||
| 51 | ]; | 51 | ]; |
| 52 | 52 | ||
| 53 | export const formSchema: FormSchema[] = [ | 53 | export const formSchema: FormSchema[] = [ |
| @@ -55,39 +55,39 @@ export const formSchema: FormSchema[] = [ | @@ -55,39 +55,39 @@ export const formSchema: FormSchema[] = [ | ||
| 55 | field: 'id', | 55 | field: 'id', |
| 56 | label: 'ID', | 56 | label: 'ID', |
| 57 | component: 'Input', | 57 | component: 'Input', |
| 58 | - show: false | 58 | + show: false, |
| 59 | }, | 59 | }, |
| 60 | { | 60 | { |
| 61 | field: 'question', | 61 | field: 'question', |
| 62 | label: '问题', | 62 | label: '问题', |
| 63 | component: 'InputTextArea', | 63 | component: 'InputTextArea', |
| 64 | required: true, | 64 | required: true, |
| 65 | - colProps: { span: 24 } | 65 | + colProps: { span: 24 }, |
| 66 | }, | 66 | }, |
| 67 | { | 67 | { |
| 68 | field: 'answer', | 68 | field: 'answer', |
| 69 | label: '回答', | 69 | label: '回答', |
| 70 | component: 'InputTextArea', | 70 | component: 'InputTextArea', |
| 71 | required: true, | 71 | required: true, |
| 72 | - colProps: { span: 24 } | 72 | + colProps: { span: 24 }, |
| 73 | }, | 73 | }, |
| 74 | { | 74 | { |
| 75 | field: 'text', | 75 | field: 'text', |
| 76 | label: '原文', | 76 | label: '原文', |
| 77 | component: 'InputTextArea', | 77 | component: 'InputTextArea', |
| 78 | - colProps: { span: 24 } | 78 | + colProps: { span: 24 }, |
| 79 | }, | 79 | }, |
| 80 | { | 80 | { |
| 81 | field: 'metadata', | 81 | field: 'metadata', |
| 82 | label: '元数据', | 82 | label: '元数据', |
| 83 | component: 'InputTextArea', | 83 | component: 'InputTextArea', |
| 84 | - colProps: { span: 24 } | ||
| 85 | - } | 84 | + colProps: { span: 24 }, |
| 85 | + }, | ||
| 86 | ]; | 86 | ]; |
| 87 | 87 | ||
| 88 | export const superQuerySchema = { | 88 | export const superQuerySchema = { |
| 89 | question: { title: '问题', order: 0, view: 'text', type: 'string' }, | 89 | question: { title: '问题', order: 0, view: 'text', type: 'string' }, |
| 90 | - answer: { title: '回答', order: 1, view: 'text', type: 'string' } | 90 | + answer: { title: '回答', order: 1, view: 'text', type: 'string' }, |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | export function getBpmFormSchema(_formData): FormSchema[] { | 93 | export function getBpmFormSchema(_formData): FormSchema[] { |
| @@ -8,9 +8,7 @@ | @@ -8,9 +8,7 @@ | ||
| 8 | <a-dropdown v-if="selectedRowKeys.length > 0"> | 8 | <a-dropdown v-if="selectedRowKeys.length > 0"> |
| 9 | <template #overlay> | 9 | <template #overlay> |
| 10 | <a-menu> | 10 | <a-menu> |
| 11 | - <a-menu-item key="1" @click="batchHandleDelete"> | ||
| 12 | - <Icon icon="ant-design:delete-outlined" />删除 | ||
| 13 | - </a-menu-item> | 11 | + <a-menu-item key="1" @click="batchHandleDelete"> <Icon icon="ant-design:delete-outlined" />删除 </a-menu-item> |
| 14 | </a-menu> | 12 | </a-menu> |
| 15 | </template> | 13 | </template> |
| 16 | <a-button>批量操作<Icon icon="mdi:chevron-down" /></a-button> | 14 | <a-button>批量操作<Icon icon="mdi:chevron-down" /></a-button> |
| @@ -26,92 +24,90 @@ | @@ -26,92 +24,90 @@ | ||
| 26 | </template> | 24 | </template> |
| 27 | 25 | ||
| 28 | <script lang="ts" setup> | 26 | <script lang="ts" setup> |
| 29 | -import { ref, reactive } from 'vue'; | ||
| 30 | -import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
| 31 | -import { useModal } from '/@/components/Modal'; | ||
| 32 | -import { useListPage } from '/@/hooks/system/useListPage'; | ||
| 33 | -import QuestionEmbeddingModal from './components/QuestionEmbeddingModal.vue'; | ||
| 34 | -import { columns, searchFormSchema, superQuerySchema } from './QuestionEmbedding.data'; | ||
| 35 | -import { list, deleteOne, batchDelete, getImportZipUrl, getExportUrl } from './QuestionEmbedding.api'; | 27 | + import { reactive } from 'vue'; |
| 28 | + import { BasicTable, TableAction } from '/@/components/Table'; | ||
| 29 | + import { useModal } from '/@/components/Modal'; | ||
| 30 | + import { useListPage } from '/@/hooks/system/useListPage'; | ||
| 31 | + import QuestionEmbeddingModal from './components/QuestionEmbeddingModal.vue'; | ||
| 32 | + import { columns, searchFormSchema, superQuerySchema } from './QuestionEmbedding.data'; | ||
| 33 | + import { list, deleteOne, batchDelete, getImportZipUrl, getExportUrl } from './QuestionEmbedding.api'; | ||
| 36 | 34 | ||
| 37 | -const queryParam = reactive<any>({}); | ||
| 38 | -const [registerModal, { openModal }] = useModal(); | 35 | + const queryParam = reactive<any>({}); |
| 36 | + const [registerModal, { openModal }] = useModal(); | ||
| 39 | 37 | ||
| 40 | -const { tableContext, onExportXls, onImportXls } = useListPage({ | ||
| 41 | - tableProps: { | ||
| 42 | - title: '问答向量库', | ||
| 43 | - api: list, | ||
| 44 | - columns, | ||
| 45 | - formConfig: { | ||
| 46 | - schemas: searchFormSchema, | ||
| 47 | - autoSubmitOnEnter: true, | ||
| 48 | - showAdvancedButton: true | 38 | + const { tableContext, onExportXls, onImportXls } = useListPage({ |
| 39 | + tableProps: { | ||
| 40 | + title: '问答向量库', | ||
| 41 | + api: list, | ||
| 42 | + columns, | ||
| 43 | + formConfig: { | ||
| 44 | + schemas: searchFormSchema, | ||
| 45 | + autoSubmitOnEnter: true, | ||
| 46 | + showAdvancedButton: true, | ||
| 47 | + }, | ||
| 48 | + actionColumn: { | ||
| 49 | + width: 120, | ||
| 50 | + fixed: 'right', | ||
| 51 | + }, | ||
| 52 | + beforeFetch: (params) => Object.assign(params, queryParam), | ||
| 49 | }, | 53 | }, |
| 50 | - actionColumn: { | ||
| 51 | - width: 120, | ||
| 52 | - fixed: 'right' | 54 | + exportConfig: { |
| 55 | + name: '问答向量库', | ||
| 56 | + url: getExportUrl, | ||
| 53 | }, | 57 | }, |
| 54 | - beforeFetch: (params) => Object.assign(params, queryParam) | ||
| 55 | - }, | ||
| 56 | - exportConfig: { | ||
| 57 | - name: '问答向量库', | ||
| 58 | - url: getExportUrl | ||
| 59 | - }, | ||
| 60 | - importConfig: { | ||
| 61 | - url: getImportZipUrl, | ||
| 62 | - success: handleSuccess | ||
| 63 | - } | ||
| 64 | -}); | 58 | + importConfig: { |
| 59 | + url: getImportZipUrl, | ||
| 60 | + success: handleSuccess, | ||
| 61 | + }, | ||
| 62 | + }); | ||
| 65 | 63 | ||
| 66 | -const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext; | ||
| 67 | -const superQueryConfig = reactive(superQuerySchema); | 64 | + const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext; |
| 65 | + const superQueryConfig = reactive(superQuerySchema); | ||
| 68 | 66 | ||
| 69 | -function handleSuperQuery(params) { | ||
| 70 | - Object.assign(queryParam, params); | ||
| 71 | - reload(); | ||
| 72 | -} | 67 | + function handleSuperQuery(params) { |
| 68 | + Object.assign(queryParam, params); | ||
| 69 | + reload(); | ||
| 70 | + } | ||
| 73 | 71 | ||
| 74 | -function handleAdd() { | ||
| 75 | - openModal(true, { isUpdate: false, showFooter: true }); | ||
| 76 | -} | 72 | + function handleAdd() { |
| 73 | + openModal(true, { isUpdate: false, showFooter: true }); | ||
| 74 | + } | ||
| 77 | 75 | ||
| 78 | -function handleEdit(record) { | ||
| 79 | - openModal(true, { record, isUpdate: true, showFooter: true }); | ||
| 80 | -} | 76 | + function handleEdit(record) { |
| 77 | + openModal(true, { record, isUpdate: true, showFooter: true }); | ||
| 78 | + } | ||
| 81 | 79 | ||
| 82 | -function handleDetail(record) { | ||
| 83 | - openModal(true, { record, isUpdate: true, showFooter: false }); | ||
| 84 | -} | 80 | + function handleDetail(record) { |
| 81 | + openModal(true, { record, isUpdate: true, showFooter: false }); | ||
| 82 | + } | ||
| 85 | 83 | ||
| 86 | -async function handleDelete(record) { | ||
| 87 | - await deleteOne({ id: record.id }, handleSuccess); | ||
| 88 | -} | 84 | + async function handleDelete(record) { |
| 85 | + await deleteOne({ id: record.id }, handleSuccess); | ||
| 86 | + } | ||
| 89 | 87 | ||
| 90 | -async function batchHandleDelete() { | ||
| 91 | - await batchDelete({ ids: selectedRowKeys.value }, handleSuccess); | ||
| 92 | -} | 88 | + async function batchHandleDelete() { |
| 89 | + await batchDelete({ ids: selectedRowKeys.value }, handleSuccess); | ||
| 90 | + } | ||
| 93 | 91 | ||
| 94 | -function handleSuccess() { | ||
| 95 | - selectedRowKeys.value = []; | ||
| 96 | - reload(); | ||
| 97 | -} | 92 | + function handleSuccess() { |
| 93 | + selectedRowKeys.value = []; | ||
| 94 | + reload(); | ||
| 95 | + } | ||
| 98 | 96 | ||
| 99 | -function getTableAction(record) { | ||
| 100 | - return [ | ||
| 101 | - { label: '编辑', onClick: handleEdit.bind(null, record) } | ||
| 102 | - ]; | ||
| 103 | -} | 97 | + function getTableAction(record) { |
| 98 | + return [{ label: '编辑', onClick: handleEdit.bind(null, record) }]; | ||
| 99 | + } | ||
| 104 | 100 | ||
| 105 | -function getDropDownAction(record) { | ||
| 106 | - return [ | ||
| 107 | - { label: '详情', onClick: handleDetail.bind(null, record) }, | ||
| 108 | - { | ||
| 109 | - label: '删除', | ||
| 110 | - popConfirm: { | ||
| 111 | - title: '确认删除此问答?', | ||
| 112 | - confirm: handleDelete.bind(null, record) | ||
| 113 | - } | ||
| 114 | - } | ||
| 115 | - ]; | ||
| 116 | -} | 101 | + function getDropDownAction(record) { |
| 102 | + return [ | ||
| 103 | + { label: '详情', onClick: handleDetail.bind(null, record) }, | ||
| 104 | + { | ||
| 105 | + label: '删除', | ||
| 106 | + popConfirm: { | ||
| 107 | + title: '确认删除此问答?', | ||
| 108 | + confirm: handleDelete.bind(null, record), | ||
| 109 | + }, | ||
| 110 | + }, | ||
| 111 | + ]; | ||
| 112 | + } | ||
| 117 | </script> | 113 | </script> |
| @@ -5,54 +5,46 @@ | @@ -5,54 +5,46 @@ | ||
| 5 | </template> | 5 | </template> |
| 6 | 6 | ||
| 7 | <script lang="ts" setup> | 7 | <script lang="ts" setup> |
| 8 | -import { ref, computed, unref } from 'vue'; | ||
| 9 | -import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 10 | -import { BasicForm, useForm } from '/@/components/Form/index'; | ||
| 11 | -import { formSchema } from '../QuestionEmbedding.data'; | ||
| 12 | -import { saveOrUpdate } from '../QuestionEmbedding.api'; | ||
| 13 | - | ||
| 14 | -const emit = defineEmits(['register', 'success']); | ||
| 15 | -const isUpdate = ref(true); | ||
| 16 | -const isDetail = ref(false); | ||
| 17 | - | ||
| 18 | -const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ | ||
| 19 | - labelWidth: 150, | ||
| 20 | - schemas: formSchema, | ||
| 21 | - showActionButtonGroup: false, | ||
| 22 | - baseColProps: { span: 24 } | ||
| 23 | -}); | ||
| 24 | - | ||
| 25 | -const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { | ||
| 26 | - await resetFields(); | ||
| 27 | - setModalProps({ | ||
| 28 | - confirmLoading: false, | ||
| 29 | - showCancelBtn: !!data?.showFooter, | ||
| 30 | - showOkBtn: !!data?.showFooter | 8 | + import { ref, computed, unref } from 'vue'; |
| 9 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
| 10 | + import { BasicForm, useForm } from '/@/components/Form/index'; | ||
| 11 | + import { formSchema } from '../QuestionEmbedding.data'; | ||
| 12 | + import { saveOrUpdate } from '../QuestionEmbedding.api'; | ||
| 13 | + const emit = defineEmits(['register', 'success']); | ||
| 14 | + const isUpdate = ref(true); | ||
| 15 | + const isDetail = ref(false); | ||
| 16 | + const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({ | ||
| 17 | + labelWidth: 150, | ||
| 18 | + schemas: formSchema, | ||
| 19 | + showActionButtonGroup: false, | ||
| 20 | + baseColProps: { span: 24 }, | ||
| 31 | }); | 21 | }); |
| 32 | - | ||
| 33 | - isUpdate.value = !!data?.isUpdate; | ||
| 34 | - isDetail.value = !!data?.showFooter; | ||
| 35 | - | ||
| 36 | - if (unref(isUpdate)) { | ||
| 37 | - await setFieldsValue({ | ||
| 38 | - ...data.record, | 22 | + const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { |
| 23 | + await resetFields(); | ||
| 24 | + setModalProps({ | ||
| 25 | + confirmLoading: false, | ||
| 26 | + showCancelBtn: !!data?.showFooter, | ||
| 27 | + showOkBtn: !!data?.showFooter, | ||
| 39 | }); | 28 | }); |
| 29 | + isUpdate.value = !!data?.isUpdate; | ||
| 30 | + isDetail.value = !!data?.showFooter; | ||
| 31 | + if (unref(isUpdate)) { | ||
| 32 | + await setFieldsValue({ | ||
| 33 | + ...data.record, | ||
| 34 | + }); | ||
| 35 | + } | ||
| 36 | + setProps({ disabled: !data?.showFooter }); | ||
| 37 | + }); | ||
| 38 | + const title = computed(() => (!unref(isUpdate) ? '新增问答' : !unref(isDetail) ? '问答详情' : '编辑问答')); | ||
| 39 | + async function handleSubmit() { | ||
| 40 | + try { | ||
| 41 | + const values = await validate(); | ||
| 42 | + setModalProps({ confirmLoading: true }); | ||
| 43 | + await saveOrUpdate(values, isUpdate.value); | ||
| 44 | + closeModal(); | ||
| 45 | + emit('success'); | ||
| 46 | + } finally { | ||
| 47 | + setModalProps({ confirmLoading: false }); | ||
| 48 | + } | ||
| 40 | } | 49 | } |
| 41 | - | ||
| 42 | - setProps({ disabled: !data?.showFooter }); | ||
| 43 | -}); | ||
| 44 | - | ||
| 45 | -const title = computed(() => (!unref(isUpdate) ? '新增问答' : !unref(isDetail) ? '问答详情' : '编辑问答')); | ||
| 46 | - | ||
| 47 | -async function handleSubmit() { | ||
| 48 | - try { | ||
| 49 | - const values = await validate(); | ||
| 50 | - setModalProps({ confirmLoading: true }); | ||
| 51 | - await saveOrUpdate(values, isUpdate.value); | ||
| 52 | - closeModal(); | ||
| 53 | - emit('success'); | ||
| 54 | - } finally { | ||
| 55 | - setModalProps({ confirmLoading: false }); | ||
| 56 | - } | ||
| 57 | -} | ||
| 58 | </script> | 50 | </script> |
| @@ -39,18 +39,76 @@ | @@ -39,18 +39,76 @@ | ||
| 39 | </template> | 39 | </template> |
| 40 | 40 | ||
| 41 | <script lang="ts" name="test-test" setup> | 41 | <script lang="ts" name="test-test" setup> |
| 42 | - import { ref, reactive } from 'vue'; | ||
| 43 | - import { BasicTable, TableAction } from '/@/components/Table'; | 42 | + import { ref, reactive, computed, onMounted } from 'vue'; |
| 43 | + import { BasicColumn, BasicTable, TableAction } from '/@/components/Table'; | ||
| 44 | import { useModal } from '/@/components/Modal'; | 44 | import { useModal } from '/@/components/Modal'; |
| 45 | import { useListPage } from '/@/hooks/system/useListPage'; | 45 | import { useListPage } from '/@/hooks/system/useListPage'; |
| 46 | import TestModal from './components/TestModal.vue'; | 46 | import TestModal from './components/TestModal.vue'; |
| 47 | - import { columns, searchFormSchema, superQuerySchema } from './Test.data'; | ||
| 48 | - import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './Test.api'; | 47 | + import { searchFormSchema, superQuerySchema } from './Test.data'; |
| 48 | + import { list, batchDelete, getImportUrl, getExportUrl, deleteOne, listknowledge } from './Test.api'; | ||
| 49 | import { useUserStore } from '/@/store/modules/user'; | 49 | import { useUserStore } from '/@/store/modules/user'; |
| 50 | - import JUploadButton from "@/components/Button/src/JUploadButton.vue"; | 50 | + import JUploadButton from '@/components/Button/src/JUploadButton.vue'; |
| 51 | + import { columns as defaultColumns } from './Test.data'; // 导入默认列配置 | ||
| 51 | const queryParam = reactive<any>({}); | 52 | const queryParam = reactive<any>({}); |
| 52 | const checkedKeys = ref<Array<string | number>>([]); | 53 | const checkedKeys = ref<Array<string | number>>([]); |
| 53 | const userStore = useUserStore(); | 54 | const userStore = useUserStore(); |
| 55 | + // 添加知识库名称映射 | ||
| 56 | + const knowledgeMap = ref<Record<string, string>>({}); | ||
| 57 | + | ||
| 58 | + // 加载知识库列表 | ||
| 59 | + async function loadKnowledgeMap() { | ||
| 60 | + try { | ||
| 61 | + const res = await listknowledge({}); | ||
| 62 | + const map: Record<string, string> = {}; | ||
| 63 | + res.forEach((item) => { | ||
| 64 | + if (item.id && item.name) { | ||
| 65 | + map[item.id] = item.name; | ||
| 66 | + } | ||
| 67 | + }); | ||
| 68 | + knowledgeMap.value = map; | ||
| 69 | + } catch (e) { | ||
| 70 | + console.error('加载知识库列表失败', e); | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + onMounted(() => { | ||
| 75 | + loadKnowledgeMap(); | ||
| 76 | + }); | ||
| 77 | + | ||
| 78 | + // 创建符合 BasicColumn 类型的知识库名称列 | ||
| 79 | + const knowledgeColumn: BasicColumn = { | ||
| 80 | + title: '知识库名称', | ||
| 81 | + align: 'center', | ||
| 82 | + dataIndex: 'knowledgeName', | ||
| 83 | + width: 150, | ||
| 84 | + customRender: ({ record }) => { | ||
| 85 | + try { | ||
| 86 | + const metadata = typeof record.metadata === 'string' ? JSON.parse(record.metadata) : record.metadata; | ||
| 87 | + | ||
| 88 | + const knowledgeId = metadata?.knowledgeId; | ||
| 89 | + | ||
| 90 | + if (knowledgeId && knowledgeMap.value[knowledgeId]) { | ||
| 91 | + return knowledgeMap.value[knowledgeId]; | ||
| 92 | + } else if (knowledgeId) { | ||
| 93 | + return `未知知识库(${knowledgeId})`; | ||
| 94 | + } else { | ||
| 95 | + return '无知识库'; | ||
| 96 | + } | ||
| 97 | + } catch (e) { | ||
| 98 | + return '元数据解析失败'; | ||
| 99 | + } | ||
| 100 | + }, | ||
| 101 | + }; | ||
| 102 | + | ||
| 103 | + // 创建完整的列配置 | ||
| 104 | + const tableColumns = computed<BasicColumn[]>(() => { | ||
| 105 | + // 从默认列配置中过滤掉可能存在的旧知识库列 | ||
| 106 | + const filteredColumns = defaultColumns.filter((col) => col.dataIndex !== 'name' && col.title !== '知识库名称'); | ||
| 107 | + | ||
| 108 | + // 添加新的知识库列 | ||
| 109 | + return [...filteredColumns, knowledgeColumn]; | ||
| 110 | + }); | ||
| 111 | + | ||
| 54 | //注册model | 112 | //注册model |
| 55 | const [registerModal, { openModal }] = useModal(); | 113 | const [registerModal, { openModal }] = useModal(); |
| 56 | //注册table数据 | 114 | //注册table数据 |
| @@ -58,7 +116,7 @@ | @@ -58,7 +116,7 @@ | ||
| 58 | tableProps: { | 116 | tableProps: { |
| 59 | title: 'test', | 117 | title: 'test', |
| 60 | api: list, | 118 | api: list, |
| 61 | - columns, | 119 | + columns: tableColumns, |
| 62 | canResize: false, | 120 | canResize: false, |
| 63 | formConfig: { | 121 | formConfig: { |
| 64 | //labelWidth: 120, | 122 | //labelWidth: 120, |
| @@ -73,6 +131,13 @@ | @@ -73,6 +131,13 @@ | ||
| 73 | fixed: 'right', | 131 | fixed: 'right', |
| 74 | }, | 132 | }, |
| 75 | beforeFetch: (params) => { | 133 | beforeFetch: (params) => { |
| 134 | + // 处理知识库查询参数 | ||
| 135 | + if (params.knowledgeId) { | ||
| 136 | + // 直接使用对象而不是JSON字符串 | ||
| 137 | + queryParam.metadata = { knowledgeId: params.knowledgeId }; | ||
| 138 | + } else { | ||
| 139 | + delete queryParam.metadata; | ||
| 140 | + } | ||
| 76 | return Object.assign(params, queryParam); | 141 | return Object.assign(params, queryParam); |
| 77 | }, | 142 | }, |
| 78 | }, | 143 | }, |
| @@ -5,6 +5,7 @@ const { createConfirm } = useMessage(); | @@ -5,6 +5,7 @@ const { createConfirm } = useMessage(); | ||
| 5 | 5 | ||
| 6 | enum Api { | 6 | enum Api { |
| 7 | list = '/embeddings/embeddings/list', | 7 | list = '/embeddings/embeddings/list', |
| 8 | + listknowledge = '/embeddings/embeddings/listknowledge', | ||
| 8 | save = '/embeddings/embeddings/add', | 9 | save = '/embeddings/embeddings/add', |
| 9 | edit = '/embeddings/embeddings/edit', | 10 | edit = '/embeddings/embeddings/edit', |
| 10 | deleteOne = '/embeddings/embeddings/delete', | 11 | deleteOne = '/embeddings/embeddings/delete', |
| @@ -29,6 +30,7 @@ export const getImportUrl = Api.importWord; | @@ -29,6 +30,7 @@ export const getImportUrl = Api.importWord; | ||
| 29 | * @param params | 30 | * @param params |
| 30 | */ | 31 | */ |
| 31 | export const list = (params) => defHttp.get({ url: Api.list, params }); | 32 | export const list = (params) => defHttp.get({ url: Api.list, params }); |
| 33 | +export const listknowledge = (params) => defHttp.get({ url: Api.listknowledge, params }); | ||
| 32 | 34 | ||
| 33 | /** | 35 | /** |
| 34 | * 删除单个 | 36 | * 删除单个 |
| 1 | import { BasicColumn } from '/@/components/Table'; | 1 | import { BasicColumn } from '/@/components/Table'; |
| 2 | import { FormSchema } from '/@/components/Table'; | 2 | import { FormSchema } from '/@/components/Table'; |
| 3 | import { h } from 'vue'; | 3 | import { h } from 'vue'; |
| 4 | +import { listknowledge } from '@/views/super/airag/test/Test.api'; | ||
| 4 | //import { Tooltip } from 'ant-design-vue'; | 5 | //import { Tooltip } from 'ant-design-vue'; |
| 5 | 6 | ||
| 6 | //列表数据 | 7 | //列表数据 |
| @@ -43,15 +44,15 @@ export const columns: BasicColumn[] = [ | @@ -43,15 +44,15 @@ export const columns: BasicColumn[] = [ | ||
| 43 | align: 'center', | 44 | align: 'center', |
| 44 | dataIndex: 'text', | 45 | dataIndex: 'text', |
| 45 | }, | 46 | }, |
| 46 | - /* { | ||
| 47 | - title: '知识库ID', | 47 | + { |
| 48 | + title: '知识库名称', | ||
| 48 | align: 'center', | 49 | align: 'center', |
| 49 | - dataIndex: 'knowledgeId', | 50 | + dataIndex: 'knowledgeName', |
| 50 | width: 150, | 51 | width: 150, |
| 51 | - customRender: ({ record }) => { | 52 | + /*customRender: ({ record }) => { |
| 52 | return renderMetadataField(record, 'knowledgeId'); | 53 | return renderMetadataField(record, 'knowledgeId'); |
| 53 | - }, | ||
| 54 | - }, | 54 | + },*/ |
| 55 | + } /* | ||
| 55 | { | 56 | { |
| 56 | title: '文档名称', | 57 | title: '文档名称', |
| 57 | align: 'center', | 58 | align: 'center', |
| @@ -109,7 +110,7 @@ export const columns: BasicColumn[] = [ | @@ -109,7 +110,7 @@ export const columns: BasicColumn[] = [ | ||
| 109 | return h(Tooltip, { title: displayText }, () => h('span', shortText)); | 110 | return h(Tooltip, { title: displayText }, () => h('span', shortText)); |
| 110 | } | 111 | } |
| 111 | }, | 112 | }, |
| 112 | - },*/ | 113 | + },*/, |
| 113 | ]; | 114 | ]; |
| 114 | 115 | ||
| 115 | function renderMetadataField(record: any, fieldName: string) { | 116 | function renderMetadataField(record: any, fieldName: string) { |
| @@ -125,7 +126,6 @@ function renderMetadataField(record: any, fieldName: string) { | @@ -125,7 +126,6 @@ function renderMetadataField(record: any, fieldName: string) { | ||
| 125 | if (value === undefined || value === null) { | 126 | if (value === undefined || value === null) { |
| 126 | return h('span', { style: 'color: #999' }, '无'); | 127 | return h('span', { style: 'color: #999' }, '无'); |
| 127 | } | 128 | } |
| 128 | - | ||
| 129 | // 根据字段类型渲染 | 129 | // 根据字段类型渲染 |
| 130 | switch (fieldName) { | 130 | switch (fieldName) { |
| 131 | case 'knowledgeId': | 131 | case 'knowledgeId': |
| @@ -150,6 +150,21 @@ export const searchFormSchema: FormSchema[] = [ | @@ -150,6 +150,21 @@ export const searchFormSchema: FormSchema[] = [ | ||
| 150 | field: 'text', | 150 | field: 'text', |
| 151 | component: 'Input', | 151 | component: 'Input', |
| 152 | }, | 152 | }, |
| 153 | + // 新增知识库选择字段 | ||
| 154 | + { | ||
| 155 | + label: '知识库', | ||
| 156 | + field: 'knowledgeId', // 注意:这里使用knowledgeId作为字段名 | ||
| 157 | + component: 'ApiSelect', | ||
| 158 | + componentProps: { | ||
| 159 | + api: listknowledge, // 使用知识库接口 | ||
| 160 | + labelField: 'name', // 显示知识库名称 | ||
| 161 | + valueField: 'id', // 提交知识库ID | ||
| 162 | + showSearch: true, | ||
| 163 | + filterOption: (input: string, option: any) => { | ||
| 164 | + return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; | ||
| 165 | + }, | ||
| 166 | + }, | ||
| 167 | + }, | ||
| 153 | ]; | 168 | ]; |
| 154 | //表单数据 | 169 | //表单数据 |
| 155 | export const formSchema: FormSchema[] = [ | 170 | export const formSchema: FormSchema[] = [ |
| @@ -166,7 +181,23 @@ export const formSchema: FormSchema[] = [ | @@ -166,7 +181,23 @@ export const formSchema: FormSchema[] = [ | ||
| 166 | label: '文本内容', | 181 | label: '文本内容', |
| 167 | field: 'text', | 182 | field: 'text', |
| 168 | required: true, | 183 | required: true, |
| 169 | - component: 'InputTextArea', | 184 | + component: 'JEditor', |
| 185 | + }, | ||
| 186 | + // 新增知识库选择字段 | ||
| 187 | + { | ||
| 188 | + label: '知识库', | ||
| 189 | + field: 'knowledgeId', // 注意:这里使用knowledgeId作为字段名 | ||
| 190 | + component: 'ApiSelect', | ||
| 191 | + required: true, | ||
| 192 | + componentProps: { | ||
| 193 | + api: listknowledge, // 使用知识库接口 | ||
| 194 | + labelField: 'name', // 显示知识库名称 | ||
| 195 | + valueField: 'id', // 提交知识库ID | ||
| 196 | + showSearch: true, | ||
| 197 | + filterOption: (input: string, option: any) => { | ||
| 198 | + return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; | ||
| 199 | + }, | ||
| 200 | + }, | ||
| 170 | }, | 201 | }, |
| 171 | // TODO 主键隐藏字段,目前写死为ID | 202 | // TODO 主键隐藏字段,目前写死为ID |
| 172 | { | 203 | { |
| @@ -36,6 +36,9 @@ | @@ -36,6 +36,9 @@ | ||
| 36 | try { | 36 | try { |
| 37 | const metadata = typeof formData.metadata === 'string' ? JSON.parse(formData.metadata) : formData.metadata; | 37 | const metadata = typeof formData.metadata === 'string' ? JSON.parse(formData.metadata) : formData.metadata; |
| 38 | formData.docName = metadata.docName || '未命名'; | 38 | formData.docName = metadata.docName || '未命名'; |
| 39 | + | ||
| 40 | + // 关键修复:设置知识库ID | ||
| 41 | + formData.knowledgeId = metadata.knowledgeId; | ||
| 39 | } catch (e) { | 42 | } catch (e) { |
| 40 | console.error('元数据解析失败', e); | 43 | console.error('元数据解析失败', e); |
| 41 | formData.docName = '元数据格式错误'; | 44 | formData.docName = '元数据格式错误'; |
| @@ -54,11 +57,15 @@ | @@ -54,11 +57,15 @@ | ||
| 54 | try { | 57 | try { |
| 55 | let values = await validate(); | 58 | let values = await validate(); |
| 56 | 59 | ||
| 60 | + const metadata = { | ||
| 61 | + knowledgeId: values.knowledgeId, | ||
| 62 | + }; | ||
| 57 | // 仅保留需要的字段,其他由后端自动生成 | 63 | // 仅保留需要的字段,其他由后端自动生成 |
| 58 | const payload = { | 64 | const payload = { |
| 59 | id: values.id, | 65 | id: values.id, |
| 60 | docName: values.docName, // 文件名称 | 66 | docName: values.docName, // 文件名称 |
| 61 | text: values.text, // 文件内容 | 67 | text: values.text, // 文件内容 |
| 68 | + metadata: metadata, | ||
| 62 | }; | 69 | }; |
| 63 | setModalProps({ confirmLoading: true }); | 70 | setModalProps({ confirmLoading: true }); |
| 64 | //提交表单 | 71 | //提交表单 |
-
请 注册 或 登录 后发表评论