CzRger 2 tygodni temu
rodzic
commit
b4562b0313

+ 2 - 0
src/App.vue

@@ -9,6 +9,8 @@
 
 <script setup lang="ts">
 import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
+import { sysDict } from '@/api/modules/global/dictionary'
+sysDict()
 </script>
 
 <style lang="scss" scoped></style>

+ 7 - 0
src/api/modules/global/dictionary.ts

@@ -0,0 +1,7 @@
+import { get, post, upload } from '@/api/request'
+
+// 查询所有字典
+export const sysDict = () => get('/sys_dict', {}, {})
+// 根据类型获取所有字典
+export const sysDictFindByDictType = (dictType) =>
+  get(`/sys_dict/findByDictType/${dictType}`, {}, {})

+ 3 - 0
src/api/modules/knowledge/document.ts

@@ -6,3 +6,6 @@ export const documentGetDocumentsByPage = (params) =>
 // 知识库文档分段预览
 export const datasetsDocumentsDealView = (params) =>
   post(`/datasets/documents/deal/view`, params, {})
+// 知识库文档获取处理状态
+export const datasetsDocumentsDealStatus = (params) =>
+  post(`/datasets/documents/deal/status`, params, {})

+ 3 - 0
src/api/modules/knowledge/index.ts

@@ -17,3 +17,6 @@ export const datasetsDetail = (id) => get(`/datasets/${id}`, {}, {})
 // 知识库取消收藏
 export const datasetsCancelCollect = (datasetId) =>
   post(`/datasets/cancelCollect/${datasetId}`, {}, {})
+// 知识库开始处理文件
+export const datasetsUpdateExport = (params) =>
+  post(`/datasets/updateExport`, params, {})

BIN
src/assets/images/app-default-logo.png


+ 11 - 0
src/stores/modules/dictionary-define.ts

@@ -0,0 +1,11 @@
+export const dictionaryDefine = {
+  //接口参数 : [ '字典数据list名', '字典数据Map名' ],
+  indexing_status: ['indexingStatusList', 'indexingStatusMap'], //  标签类型
+}
+
+const stateMap = {}
+Object.keys(dictionaryDefine).map((i) => {
+  stateMap[dictionaryDefine[i][0]] = []
+  stateMap[dictionaryDefine[i][1]] = new Map()
+})
+export const dictionary = stateMap

+ 49 - 0
src/stores/modules/dictionary.ts

@@ -3,6 +3,12 @@ import { tagsTenant } from '@/api/modules/knowledge/tags'
 import { ElMessage } from 'element-plus'
 import { datasetGroupsGetAllByTenantId } from '@/api/modules/knowledge/group'
 import { pluginConfigs, pluginGetModelTypeList } from '@/api/modules/model'
+import { dictionary, dictionaryDefine } from './dictionary-define'
+import { sysDictFindByDictType } from '@/api/modules/global/dictionary'
+import FileExcel from '@/assets/images/file-excel.png'
+import FileTxt from '@/assets/images/file-txt.png'
+import FileUnknown from '@/assets/images/file-unknown.png'
+import FileWord from '@/assets/images/file-word.png'
 
 const listToMap = ({
   list,
@@ -18,6 +24,7 @@ const listToMap = ({
 }
 export const useDictionaryStore = defineStore('dictionary', {
   state: () => ({
+    ...dictionary,
     knowledgeTags: {
       waiting: false,
       list: [],
@@ -54,6 +61,32 @@ export const useDictionaryStore = defineStore('dictionary', {
     },
   },
   actions: {
+    initDict(type) {
+      return new Promise((resolve, reject) => {
+        if (this[dictionaryDefine[type][0]].length === 0) {
+          sysDictFindByDictType(type)
+            .then(({ data }: any) => {
+              const map = new Map()
+              const objMap = new Map()
+              if (data.length > 0) {
+                data.forEach((v: any) => {
+                  v.label = v.dictName
+                  v.value = v.dictValue
+                  map.set(v.value, v.label)
+                  objMap.set(v.value, v)
+                })
+              }
+              this[dictionaryDefine[type][0]] = data
+              this[dictionaryDefine[type][1]] = map
+              this[dictionaryDefine[type]?.[2]] = objMap
+              resolve(data)
+            })
+            .catch(() => {})
+        } else {
+          resolve(this[dictionaryDefine[type][0]])
+        }
+      })
+    },
     initKnowledgeTags(tenantId) {
       if (!this.knowledgeTags.waiting) {
         this.knowledgeTags.waiting = true
@@ -140,5 +173,21 @@ export const useDictionaryStore = defineStore('dictionary', {
           })
       }
     },
+    getFileIcon(name) {
+      if (name.toLowerCase().includes('.txt')) {
+        return FileTxt
+      } else if (
+        name.toLowerCase().includes('.xls') ||
+        name.toLowerCase().includes('.xlsx')
+      ) {
+        return FileExcel
+      } else if (
+        name.toLowerCase().includes('.doc') ||
+        name.toLowerCase().includes('.docx')
+      ) {
+        return FileWord
+      }
+      return FileUnknown
+    },
   },
 })

+ 12 - 0
src/utils/czr-util.ts

@@ -774,3 +774,15 @@ export const domRootHasAttr = (dom, attr) => {
   }
   return domRootHasAttr(dom.parentElement, attr)
 }
+
+export const formatFileSize = (size) => {
+  if (size < 1024) {
+    return size + 'B'
+  } else if (size < 1024 * 1024) {
+    return (size / 1024).toFixed(2) + 'KB'
+  } else if (size < 1024 * 1024 * 1024) {
+    return (size / (1024 * 1024)).toFixed(2) + 'MB'
+  } else {
+    return (size / (1024 * 1024 * 1024)).toFixed(2) + 'GB'
+  }
+}

+ 215 - 0
src/views/manage/app/detail.vue

@@ -0,0 +1,215 @@
+<template>
+  <CzrDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    @onSubmit="onSubmit"
+    width="62.5rem"
+    height="auto"
+    max-height="90%"
+    :loading="state.loading"
+  >
+    <div class="bm-form">
+      <CzrForm ref="ref_form" label-width="100px" :form-view="isViewCpt">
+        <div class="__czr-title_1">基本信息</div>
+        <CzrFormColumn
+          required
+          :span="12"
+          label="模型类型"
+          v-model:param="state.form.type"
+          link="select"
+          :options="DictionaryStore.modelTypes.list"
+          @change="state.form.pluginClass = ''"
+        />
+        <template v-if="state.form.type">
+          <CzrFormColumn
+            required
+            :span="12"
+            label="模型供应商"
+            v-model:param="state.form.pluginClass"
+            link="select"
+            :options="
+              DictionaryStore.modelProvides.list.filter(
+                (v) => v.type === state.form.type,
+              )
+            "
+            @getObject="getModelProvide"
+          />
+        </template>
+        <template v-if="state.form.pluginClass">
+          <CzrFormColumn
+            required
+            :span="24"
+            label="模型名称"
+            v-model:param="state.form.name"
+          />
+          <CzrFormColumn
+            :span="24"
+            label="模型简介"
+            v-model:param="state.form.description"
+            type="textarea"
+            :rows="4"
+          />
+        </template>
+        <CzrFormColumn
+          required
+          :span="24"
+          label="共享条件"
+          v-model:param="state.form.openStrategy"
+          link="radio"
+          :options="DictionaryStore.shareConditions"
+        />
+      </CzrForm>
+    </div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {
+  computed,
+  getCurrentInstance,
+  nextTick,
+  reactive,
+  ref,
+  watch,
+} from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
+import { useRouter } from 'vue-router'
+import {
+  pluginAddInstance,
+  pluginDetail,
+  pluginUpdateInstance,
+} from '@/api/modules/model'
+
+const router = useRouter()
+const AppStore = useAppStore()
+const DictionaryStore = useDictionaryStore()
+const DialogStore = useDialogStore()
+const emit = defineEmits(['update:show', 'refresh'])
+const { proxy } = getCurrentInstance()
+const props = defineProps({
+  show: { default: false },
+  transfer: <any>{},
+})
+const state: any = reactive({
+  loading: false,
+  form: {
+    basicConfigs: {},
+    paramConfigs: {},
+    bizConfigs: {},
+  },
+  baseForms: [],
+  paramForms: [],
+  bizForms: [],
+})
+const ref_form = ref()
+const titleCpt = computed(() => {
+  let t = '模型'
+  switch (props.transfer.mode) {
+    case 'add':
+      t = '创建' + t
+      break
+    case 'edit':
+      t = '编辑' + t
+      break
+    case 'view':
+      t = '查看' + t
+      break
+  }
+  return t
+})
+const isViewCpt = computed(() => props.transfer?.mode === 'view')
+watch(
+  () => props.show,
+  (n) => {
+    if (n) {
+      initDictionary()
+      state.form = {
+        tenantId: AppStore.tenantInfo?.id,
+        basicConfigs: {},
+        paramConfigs: {},
+        bizConfigs: {},
+      }
+      state.baseForms = []
+      state.paramForms = []
+      state.bizForms = []
+      if (props.transfer.mode !== 'add') {
+        initData()
+      }
+      nextTick(() => {
+        ref_form.value.reset()
+      })
+    }
+  },
+)
+const initDictionary = () => {
+  DictionaryStore.initModelProvides()
+}
+const initData = () => {
+  state.loading = true
+  pluginDetail(props.transfer.id)
+    .then(({ data }: any) => {
+      state.form = data
+    })
+    .catch(() => {})
+    .finally(() => {
+      state.loading = false
+    })
+}
+const onSubmit = () => {
+  ref_form.value
+    .submit()
+    .then(() => {
+      DialogStore.confirm({
+        content: `请确认是否提交?`,
+        onSubmit: () => {
+          state.loading = true
+          if (props.transfer.mode === 'add') {
+            pluginAddInstance(state.form)
+              .then(() => {
+                ElMessage.success(`${titleCpt.value}成功!`)
+                emit('update:show', false)
+                emit('refresh')
+              })
+              .catch(() => {})
+              .finally(() => {
+                state.loading = false
+              })
+          } else {
+            pluginUpdateInstance(state.form)
+              .then(() => {
+                ElMessage.success(`${titleCpt.value}成功!`)
+                emit('refresh')
+              })
+              .catch(() => {})
+              .finally(() => {
+                state.loading = false
+              })
+          }
+        },
+      })
+    })
+    .catch((e) => {
+      ElMessage({
+        message: e[0].message,
+        grouping: true,
+        type: 'warning',
+      })
+    })
+}
+const getModelProvide = (obj) => {
+  console.log(obj)
+  state.form.name = obj.name
+  state.form.description = obj.description
+  state.baseForms = obj.basicConfigAttr
+    ? Object.values(obj.basicConfigAttr)
+    : []
+  state.paramForms = obj.paramConfigAttr
+    ? Object.values(obj.paramConfigAttr)
+    : []
+  state.bizForms = obj.bizConfigAttr ? Object.values(obj.bizConfigAttr) : []
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 252 - 40
src/views/manage/app/index.vue

@@ -1,58 +1,270 @@
 <template>
-  <div>
-    <el-card>
-      {{ state.text }}
-    </el-card>
-
-    <el-card>
-      <div class="h-[400px]">
-        <CzrMarkdown
-          v-model="state.text"
-          :rendererFunc="
-            ({ text }) => {
-              return text.replace(/\$\{([^}]+)\}/g, (match, p1) => {
-                return `<span class='vars-params'>${state.optionsMap.get(p1)?.label}</span>`
-              })
-            }
-          "
-        />
+  <div class="bm-main-box">
+    <div class="flex items-center">
+      <div class="bm-main-box-title">{{ $route.meta.title }}</div>
+      <div class="ml-auto flex items-center gap-[var(--czr-gap)]">
+        <CzrForm class="bm-filter" label-width="0px" @handleEnter="onSearch">
+          <CzrFormColumn
+            width="6.68rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.query.form.modeType"
+            link="select"
+            :options="[]"
+            placeholder="应用状态"
+          />
+          <CzrFormColumn
+            width="6.68rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.query.form.status"
+            link="select"
+            :options="[]"
+            placeholder="应用类型"
+          />
+          <CzrFormColumn
+            width="15.63rem"
+            class="__czr-table-form-column"
+            :span="24"
+            label-width="0px"
+            v-model:param="state.text"
+            placeholder="输入关键词以检索"
+            :prefix-icon="Search"
+          />
+          <CzrButton type="add" @click="onAdd" />
+        </CzrForm>
       </div>
-    </el-card>
+    </div>
+    <div
+      class="mt-[1rem] flex-1 overflow-hidden"
+      v-loading="state.query.loading"
+    >
+      <CzrTableCard
+        class="table-card"
+        :page="state.query.page.pageNum"
+        :pageSize="state.query.page.pageSize"
+        :total="state.query.result.total"
+        :data="state.query.result.data"
+        @handlePage="onPage"
+        :col="4"
+      >
+        <template #model="{ row, index }">
+          <div class="model __hover">
+            <div class="flex">
+              <img
+                src="@/assets/images/app-default-logo.png"
+                class="mr-[var(--czr-gap)] h-[3.25rem] w-[3.25rem]"
+              />
+              <div class="flex flex-1 flex-col justify-between overflow-hidden">
+                <div class="flex">
+                  <template v-if="index % 2 === 0">
+                    <div
+                      class="rounded-xs bg-[#5AD8A6] px-2.5 py-1 text-xs text-white"
+                    >
+                      已发布
+                    </div>
+                  </template>
+                  <template v-else>
+                    <div>简介</div>
+                  </template>
+                </div>
+                <div class="text-[1.25rem] font-bold text-[#2E3238]" v-title>
+                  {{ row.name }}
+                </div>
+              </div>
+            </div>
+          </div>
+        </template>
+      </CzrTableCard>
+    </div>
+    <detailCom
+      v-model:show="state.detail.show"
+      :transfer="state.detail.transfer"
+      @refresh="onSearch"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
-import { reactive } from 'vue'
+import { getCurrentInstance, onMounted, reactive, ref, watch } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import { debounce } from 'lodash'
+import { useAppStore, useDialogStore, useDictionaryStore } from '@/stores'
 import { ElMessage } from 'element-plus'
-import CzrMarkdown from '@/components/czr-ui/CzrMarkdown/CzrMarkdown.vue'
+import detailCom from './detail.vue'
+import {
+  pluginDel,
+  pluginGetInstanceList,
+  pluginUpdateStatus,
+} from '@/api/modules/model'
+import { YMDHms } from '@/utils/czr-util'
 
+const AppStore = useAppStore()
+const DialogStore = useDialogStore()
+const DictionaryStore = useDictionaryStore()
+const emit = defineEmits([])
 const props = defineProps({})
+const { proxy }: any = getCurrentInstance()
 const state: any = reactive({
   text: '',
-  optionsMap: new Map([
-    ['123', { label: '变量1', id: '123', type: 'String' }],
-    ['223', { label: '变量变量变量变量变量2', id: '223', type: 'String' }],
-    [
-      '333',
-      {
-        label: '变量变量变量变量变量变量变量变量变量变量变量3',
-        id: '333',
-        type: 'Number',
+  query: {
+    init: false,
+    loading: false,
+    page: {
+      pageNum: 1,
+      pageSize: 20,
+    },
+    form: {},
+    formReal: {},
+    result: {
+      total: 0,
+      data: [],
+    },
+  },
+  detail: {
+    show: false,
+    transfer: {},
+  },
+})
+const setText = debounce((v) => {
+  state.query.form.keyword = v
+}, 1000)
+watch(
+  () => state.text,
+  (n) => {
+    setText(n)
+  },
+)
+watch(
+  () => state.query.form,
+  (n) => {
+    if (state.query.init) {
+      onSearch()
+    }
+  },
+  { deep: true },
+)
+const onPage = (pageNum, pageSize) => {
+  setTimeout(() => {
+    state.query.init = true
+  }, 100)
+  state.query.page = {
+    pageNum: pageNum,
+    pageSize: pageSize,
+  }
+  const params = {
+    page: state.query.page.pageNum,
+    size: state.query.page.pageSize,
+  }
+  //  添加表单参数
+  for (const [k, v] of Object.entries(state.query.formReal)) {
+    if (proxy.$czrUtil.isValue(v)) {
+      params[k] = v
+    }
+  }
+  state.query.loading = true
+  pluginGetInstanceList(params)
+    .then(({ data }: any) => {
+      state.query.result.total = data.total
+      state.query.result.data = data.records
+    })
+    .catch(() => {})
+    .finally(() => {
+      state.query.loading = false
+    })
+}
+const onSearch = () => {
+  state.query.formReal = JSON.parse(JSON.stringify(state.query.form))
+  onPage(1, state.query.page.pageSize)
+}
+const onReset = () => {
+  state.query.page = {
+    pageNum: 1,
+    pageSize: 20,
+  }
+  state.query.form = {}
+  onSearch()
+}
+const onAdd = () => {
+  state.detail.transfer = {
+    mode: 'add',
+  }
+  state.detail.show = true
+}
+const onEdit = (row) => {
+  state.detail.transfer = {
+    mode: 'edit',
+    id: row.id,
+  }
+  state.detail.show = true
+}
+const onDel = (row: any) => {
+  DialogStore.confirm({
+    title: '删除确认',
+    content: `${row.p6}个应用正在使用该大模型,删除将导致不可用,请确认是否删除`,
+    onSubmit: () => {
+      pluginDel(row.id)
+        .then(() => {
+          ElMessage.success('删除成功!')
+        })
+        .catch(() => {})
+        .finally(() => {
+          onSearch()
+        })
+    },
+  })
+}
+const onSwitch = (row) => {
+  if (row.status == 1) {
+    DialogStore.confirm({
+      title: '停用确认',
+      content: `${row.p6}个应用正在使用该大模型,停用将导致不可用,请确认是否停用`,
+      onSubmit: () => {
+        pluginUpdateStatus({ ids: [row.id], status: 0 })
+          .then(() => {
+            ElMessage.success('停用成功!')
+          })
+          .catch(() => {})
+          .finally(() => {
+            onSearch()
+          })
       },
-    ],
-  ]),
+      onCancel: () => {},
+    })
+  } else {
+    pluginUpdateStatus({ ids: [row.id], status: 1 })
+      .then(() => {
+        ElMessage.success('启用成功!')
+      })
+      .catch(() => {})
+      .finally(() => {
+        onSearch()
+      })
+  }
+}
+onMounted(() => {
+  initDictionary()
+  onReset()
 })
+const initDictionary = () => {
+  DictionaryStore.initModelTypes()
+  DictionaryStore.initModelProvides()
+}
 </script>
 
 <style lang="scss" scoped>
-:deep(.vars-params) {
-  margin: 0 10px;
-  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
-  background-color: #ffffff;
-  border-radius: 4px;
-  padding: 2px 8px;
-  .svg-icon {
-    margin-right: 4px;
-  }
+.model {
+  width: 100%;
+  background-image: url('@/assets/images/model-icon-7.png');
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  padding: 1rem;
+  border-radius: var(--czr-gap);
+  box-shadow: 0rem 0.25rem 0.63rem 0rem rgba(40, 83, 247, 0.05);
+  border: var(--czr-border);
+  display: flex;
+  flex-direction: column;
 }
 </style>

+ 58 - 0
src/views/manage/app/index_back.vue

@@ -0,0 +1,58 @@
+<template>
+  <div>
+    <el-card>
+      {{ state.text }}
+    </el-card>
+
+    <el-card>
+      <div class="h-[400px]">
+        <CzrMarkdown
+          v-model="state.text"
+          :rendererFunc="
+            ({ text }) => {
+              return text.replace(/\$\{([^}]+)\}/g, (match, p1) => {
+                return `<span class='vars-params'>${state.optionsMap.get(p1)?.label}</span>`
+              })
+            }
+          "
+        />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive } from 'vue'
+import { ElMessage } from 'element-plus'
+import CzrMarkdown from '@/components/czr-ui/CzrMarkdown/CzrMarkdown.vue'
+
+const props = defineProps({})
+const state: any = reactive({
+  text: '',
+  optionsMap: new Map([
+    ['123', { label: '变量1', id: '123', type: 'String' }],
+    ['223', { label: '变量变量变量变量变量2', id: '223', type: 'String' }],
+    [
+      '333',
+      {
+        label: '变量变量变量变量变量变量变量变量变量变量变量3',
+        id: '333',
+        type: 'Number',
+      },
+    ],
+  ]),
+})
+</script>
+
+<style lang="scss" scoped>
+:deep(.vars-params) {
+  margin: 0 10px;
+  box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
+  background-color: #ffffff;
+  border-radius: 4px;
+  padding: 2px 8px;
+  .svg-icon {
+    margin-right: 4px;
+  }
+}
+</style>

+ 0 - 6
src/views/manage/knowledge/detail.vue

@@ -166,12 +166,6 @@ const onSubmit = (isImport) => {
             datasetsCreate({
               ...state.form,
               ...ref_modelConfig.value.getData(),
-              contentConfig: {
-                maxParentSize: 500,
-                overlapSize: 20,
-                parentSeparator: '\n\n',
-                splitType: 'CustomSymbolSplitter',
-              },
             })
               .then(({ data }: any) => {
                 ElMessage.success(`${titleCpt.value}成功!`)

+ 150 - 81
src/views/manage/knowledge/upload/index.vue

@@ -12,7 +12,7 @@
       />文档列表
     </div>
     <div class="bm-main-box mt-[1.25rem]" v-if="state.knowledge.ID">
-      <div class="flex gap-[1rem]">
+      <div class="flex gap-[1rem]" v-if="state.step === 1">
         <CzrButton
           :type="state.uploadType == UploadTypeEnum.Text ? 'primary' : 'normal'"
           title="文本文件"
@@ -124,7 +124,7 @@
               @mouseleave="file.hover__ = false"
             >
               <img
-                src="@/assets/images/file-word.png"
+                :src="DictionaryStore.getFileIcon(file.name)"
                 class="h-[1.25rem] w-[1.25rem]"
               />
               <div
@@ -178,7 +178,7 @@
         >
           <CzrButton
             type="primary"
-            title="下一步"
+            title="保存并处理"
             @click="onNextOne"
           ></CzrButton>
         </div>
@@ -298,7 +298,7 @@
               >
                 <img
                   class="h-[3rem] w-[3rem]"
-                  src="@/assets/images/file-word.png"
+                  :src="DictionaryStore.getFileIcon(value.name)"
                 />
                 <div class="flex flex-1 flex-col gap-[0.5rem]">
                   <div
@@ -332,29 +332,15 @@
                       class="flex items-center gap-[0.25rem] text-[0.75rem] text-[#909399]"
                     >
                       <div>{{ value.date }}</div>
-                      <div>{{ (value.size / 1024 / 1024).toFixed(2) }}MB</div>
-                      <div class="ml-auto">
-                        {{ value.process }}%(剩余时间{{
-                          comTime(value.timestamp, true)
-                        }})
-                      </div>
-                    </div>
-                    <div
-                      class="relative h-[0.25rem] w-full rounded-[0.25rem]"
-                      :style="{
-                        backgroundColor: `rgba(var(--czr-main-color-rgb), 0.3)`,
-                      }"
-                    >
-                      <div
-                        class="absolute h-[0.25rem] rounded-[0.25rem]"
-                        :style="{
-                          backgroundColor: `rgba(var(--czr-main-color-rgb), 1)`,
-                          width: `${value.process}%`,
-                        }"
-                      />
+                      <div class="ml-2">{{ formatFileSize(value.size) }}</div>
                     </div>
                   </template>
                 </div>
+                <div
+                  class="flex items-center gap-[var(--czr-gap)] text-[0.75rem] text-[#6F7889]"
+                >
+                  {{ DictionaryStore.indexingStatusMap.get(value.status) }}
+                </div>
               </div>
             </template>
           </div>
@@ -367,7 +353,7 @@
               >
                 <img
                   class="h-[3rem] w-[3rem]"
-                  src="@/assets/images/file-word.png"
+                  :src="DictionaryStore.getFileIcon(value.name)"
                 />
                 <div class="flex flex-1 flex-col gap-[0.5rem]">
                   <div
@@ -381,16 +367,14 @@
                     class="flex items-center gap-[0.25rem] text-[0.75rem] text-[#909399]"
                   >
                     <div>{{ value.date }}</div>
-                    <div>{{ (value.size / 1024 / 1024).toFixed(2) }}MB</div>
+                    <div class="ml-2">{{ formatFileSize(value.size) }}</div>
                   </div>
                 </div>
                 <div
                   class="flex items-center gap-[var(--czr-gap)] text-[0.75rem] text-[#6F7889]"
                 >
-                  处理完成<SvgIcon
-                    name="success"
-                    color="var(--czr-success-color)"
-                  />
+                  {{ value.status }}
+                  <SvgIcon name="success" color="var(--czr-success-color)" />
                 </div>
               </div>
             </template>
@@ -409,6 +393,7 @@ import {
   getCurrentInstance,
   inject,
   onMounted,
+  onUnmounted,
   reactive,
   ref,
   watch,
@@ -416,12 +401,16 @@ import {
 import { useRoute, useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
 import { v4 } from 'uuid'
-import { useDialogStore } from '@/stores'
-import { comTime } from '@/utils/czr-util'
+import { useDialogStore, useDictionaryStore } from '@/stores'
+import { comTime, formatFileSize, YMD, YMDHms } from '@/utils/czr-util'
 import { fileUploadFile } from '@/api/modules/global/upload'
-import { datasetsDetail } from '@/api/modules/knowledge'
-import { datasetsDocumentsDealView } from '@/api/modules/knowledge/document'
+import { datasetsDetail, datasetsUpdateExport } from '@/api/modules/knowledge'
+import {
+  datasetsDocumentsDealStatus,
+  datasetsDocumentsDealView,
+} from '@/api/modules/knowledge/document'
 
+const DictionaryStore = useDictionaryStore()
 const DialogStore = useDialogStore()
 const route = useRoute()
 const router = useRouter()
@@ -453,51 +442,54 @@ const state: any = reactive({
     },
   },
   taskFiles: {
-    waiting: new Map([
-      [
-        1,
-        {
-          name: '高效办成一件事视频脚本20250411-调整.docx',
-          date: '2022-09-17',
-          size: 123123132,
-          process: 80,
-          timestamp: 1000 * 60 * 23,
-          error: '',
-        },
-      ],
-      [
-        2,
-        {
-          name: '高效办成一件事视频脚本20250411-调整.docx',
-          date: '2022-09-17',
-          size: 1231231321,
-          process: 100,
-          timestamp: 1000 * 60 * 17,
-          error: '',
-        },
-      ],
-      [
-        22,
-        {
-          name: '高效办成一件事视频脚本20250411-调整.docx',
-          date: '2022-09-17',
-          size: 1231231321,
-          process: 100,
-          timestamp: 1000 * 60 * 17,
-          error: '123123123123123',
-        },
-      ],
-    ]),
-    success: new Map([
-      [
-        3,
-        {
-          name: '高效办成一件事视频脚本20250411-调整.docx',
-          date: '2022-09-17',
-          size: 1231231321,
-        },
-      ],
-    ]),
+    timer: null,
+    waiting: new Map(),
+    success: new Map(),
+    // waiting: new Map([
+    //   [
+    //     1,
+    //     {
+    //       name: '高效办成一件事视频脚本20250411-调整.docx',
+    //       date: '2022-09-17',
+    //       size: 123123132,
+    //       process: 80,
+    //       timestamp: 1000 * 60 * 23,
+    //       error: '',
+    //     },
+    //   ],
+    //   [
+    //     2,
+    //     {
+    //       name: '高效办成一件事视频脚本20250411-调整.docx',
+    //       date: '2022-09-17',
+    //       size: 1231231321,
+    //       process: 100,
+    //       timestamp: 1000 * 60 * 17,
+    //       error: '',
+    //     },
+    //   ],
+    //   [
+    //     22,
+    //     {
+    //       name: '高效办成一件事视频脚本20250411-调整.docx',
+    //       date: '2022-09-17',
+    //       size: 1231231321,
+    //       process: 100,
+    //       timestamp: 1000 * 60 * 17,
+    //       error: '123123123123123',
+    //     },
+    //   ],
+    // ]),
+    // success: new Map([
+    //   [
+    //     3,
+    //     {
+    //       name: '高效办成一件事视频脚本20250411-调整.docx',
+    //       date: '2022-09-17',
+    //       size: 1231231321,
+    //     },
+    //   ],
+    // ]),
   },
 })
 const UploadConfig = {
@@ -566,6 +558,7 @@ const handleBeforeUpload = (file) => {
     url: '',
     success: false,
     process: 0,
+    size: file.size,
   })
   return true
 }
@@ -635,16 +628,92 @@ watch(
   (n) => {
     if (
       (n === 2 && state.uploadType === UploadTypeEnum.QA) ||
-      (n && state.uploadType === UploadTypeEnum.Text)
+      (n === 3 && state.uploadType === UploadTypeEnum.Text)
     ) {
       initTask()
     }
   },
 )
-const initTask = () => {}
+const initTask = () => {
+  const refreshStatus = () => {
+    datasetsDocumentsDealStatus({
+      fileIds: state.uploadFileList.map((v) => v.url),
+    }).then(({ data }: any) => {
+      data.forEach((v) => {
+        const f = state.taskFiles.waiting.get(v.fileId)
+        f.status = v.indexingStatus
+        if (f.status === 'completed') {
+          state.taskFiles.success.set(v.fileId, f)
+          state.taskFiles.waiting.delete(v.fileId)
+        }
+      })
+      if (state.taskFiles.waiting.size === 0) {
+        clearInterval(state.taskFiles.timer)
+      }
+    })
+  }
+  if (state.uploadType === UploadTypeEnum.Text) {
+    datasetsUpdateExport({
+      datasetId: state.ID,
+      datasetDocumentList: state.uploadFileList.map((v) => ({
+        name: v.name,
+        fileId: v.url,
+        contentConfig: {
+          maxParentSize: 500,
+          overlapSize: 20,
+          parentSeparator: '\n\n',
+          splitType: 'CustomSymbolSplitter',
+        },
+      })),
+    }).then(() => {
+      state.uploadFileList.forEach((v) => {
+        state.taskFiles.waiting.set(v.url, {
+          name: v.name,
+          url: v.url,
+          size: v.size,
+          date: YMD(new Date()),
+          status: '',
+        })
+      })
+      state.taskFiles.timer = setInterval(() => {
+        refreshStatus()
+      }, 1000 * 5)
+      refreshStatus()
+    })
+  } else {
+    datasetsUpdateExport({
+      datasetId: state.ID,
+      datasetQASList: state.uploadFileList.map((v) => ({
+        name: v.name,
+        fileId: v.url,
+      })),
+    }).then(() => {
+      state.uploadFileList.forEach((v) => {
+        state.taskFiles.waiting.set(v.url, {
+          name: v.name,
+          url: v.url,
+          size: v.size,
+          date: YMD(new Date()),
+          status: '',
+        })
+      })
+      state.taskFiles.timer = setInterval(() => {
+        refreshStatus()
+      }, 1000 * 5)
+      refreshStatus()
+    })
+  }
+}
 onMounted(() => {
   initDetail()
+  initDictionary()
+})
+onUnmounted(() => {
+  clearInterval(state.taskFiles.timer)
 })
+const initDictionary = () => {
+  DictionaryStore.initDict('indexing_status')
+}
 </script>
 
 <style lang="scss" scoped>