CzRger 1 개월 전
부모
커밋
1c6286802a

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 0
src/assets/svg/qa.svg


+ 2 - 15
src/views/manage/knowledge/documents/document/index.vue

@@ -17,8 +17,8 @@
               id: ID
             }
           })"/>
-          <CzrButton title="迁移" icon="move"/>
-          <CzrButton title="归档" icon="cloud" @click="onKnowledge()"/>
+          <CzrButton title="迁移" icon="move" @click="onKnowledge()"/>
+          <CzrButton title="归档" icon="cloud"/>
           <CzrButton type="del" title="删除" icon="czr_del" @click="onDel()"/>
         </div>
       </template>
@@ -199,19 +199,6 @@ const onReset = () => {
   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 = null) => {
   if (row) {
     DialogStore.confirm({

+ 1 - 1
src/views/manage/knowledge/documents/document/knowledge-select.vue

@@ -58,7 +58,7 @@ const initDictionary = () => {
 const onSubmit = () => {
   if (state.active.id) {
     DialogStore.confirm({
-      content: `请确认是否将文档迁移至${state.active.name}?`,
+      content: `请确认是否将${props.transfer.row ? props.transfer.row.name : (props.transfer.list.length + '个' + (props.transfer.type === 'text' ? '文档' : '问答'))}迁移至${state.active.name}?`,
       onSubmit: () => {
         state.loading = true
         ElMessage.success(`迁移成功!`)

+ 1 - 0
src/views/manage/knowledge/documents/index.vue

@@ -27,6 +27,7 @@ const props = defineProps({})
 const {proxy}: any = getCurrentInstance()
 const menus = [
   {label: '文档', value: 'document', icon: 'document', com: defineAsyncComponent(() => import("./document/index.vue"))},
+  {label: '问答', value: 'qa', icon: 'qa', com: defineAsyncComponent(() => import("./qa/index.vue"))},
   {label: '召回测试', value: 'test', icon: 'back_1', com: defineAsyncComponent(() => import("./test/index.vue"))},
   {label: '设置', value: 'config', icon: 'config'},
 ]

+ 108 - 0
src/views/manage/knowledge/documents/qa/detail.vue

@@ -0,0 +1,108 @@
+<template>
+  <CzrDialog
+    :show="show"
+    :title="titleCpt"
+    @onClose="$emit('update:show', false)"
+    @onSubmit="onSubmit"
+    width="62.5rem"
+    height="auto"
+    max-height="36rem"
+    :loading="state.loading"
+  >
+    <div class="bm-form">
+      <div class="__czr-title_1">基本信息</div>
+      <CzrForm ref="ref_form" label-width="3.5rem" :form-view="isViewCpt">
+        <CzrFormColumn
+          required
+          :span="24"
+          label="问题"
+          v-model:param="state.form.name"
+          type="textarea"
+          :rows="4"
+        />
+        <CzrFormColumn
+          required
+          :span="24"
+          label="回答"
+          v-model:param="state.form.remark"
+          type="textarea"
+          :rows="10"
+        />
+      </CzrForm>
+    </div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from "vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {useDialogStore, useDictionaryStore} from "@/stores";
+import {useRouter} from "vue-router";
+
+const router = useRouter()
+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: {}
+})
+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 = {}
+    if (props.transfer.mode !== 'add') {
+      initData()
+    }
+    nextTick(() => {
+      ref_form.value.reset()
+    })
+  }
+})
+const initDictionary = () => {
+}
+const initData = () => {
+}
+const onSubmit = (isImport) => {
+  ref_form.value.submit().then(() => {
+    DialogStore.confirm({
+      content: `请确认是否提交?`,
+      onSubmit: () => {
+        state.loading = true
+        ElMessage.success(`${titleCpt.value}成功!`)
+        emit('update:show', false)
+        emit('refresh')
+        state.loading = false
+      }
+    })
+  }).catch((e) => {
+    ElMessage({
+      message: e[0].message,
+      grouping: true,
+      type: 'warning',
+    })
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 267 - 0
src/views/manage/knowledge/documents/qa/index.vue

@@ -0,0 +1,267 @@
+<template>
+  <div class="bm-main-box">
+    <div class="flex items-center">
+      <div class="bm-main-box-title">问答</div>
+    </div>
+    <CzrContent
+      v-model:tableHead="state.query.tableHead"
+      @handleReset="onReset"
+      @handleSearch="onSearch"
+      v-model:full="state.query.isFull"
+    >
+      <template #tableTitle>
+        <div class="flex gap-[var(--czr-gap)]">
+          <CzrButton type="add" title="创建问题" @click="onAdd"/>
+          <CzrButton title="迁移" icon="move" @click="onKnowledge()"/>
+          <CzrButton type="del" title="删除" icon="czr_del" @click="onDel()"/>
+        </div>
+      </template>
+      <template #buttons>
+        <div class="flex items-center gap-[var(--czr-gap)]">
+          <CzrForm class="bm-filter" label-width="0px" @handleEnter="onSearch">
+            <CzrFormColumn
+              width="15.63rem"
+              class="__czr-table-form-column"
+              :span="24"
+              label-width="0px"
+              v-model:param="state.text"
+              placeholder="按问答名称搜索"
+              :prefix-icon="Search"
+            />
+          </CzrForm>
+        </div>
+      </template>
+      <template #table>
+        <CzrTable
+          v-loading="state.query.loading"
+          ref="ref_cusTable"
+          :data="state.query.result.data"
+          :head="state.query.head"
+          :total="state.query.result.total"
+          :page="state.query.page.pageNum"
+          :pageSize="state.query.page.pageSize"
+          @handlePage="onPage"
+          v-model:selected="state.query.selected"
+        >
+          <template #importAndExportType-column-value="{ scope }">
+<!--            <dict-tag :options="import_and_export_type" :value="scope.row.importAndExportType"/>-->
+          </template>
+          <template #caozuo-column-value="{ scope }">
+            <div class="__czr-table-operations">
+              <CzrButton type="table" title="重命名" @click="onRename(scope.row)"/>
+              <CzrButton type="table" title="迁移" @click="onKnowledge(scope.row)"/>
+              <CzrButton type="table" title="编辑" @click="onEdit(scope.row)"/>
+              <CzrButton type="table-del" @click="onDel(scope.row)"/>
+            </div>
+          </template>
+        </CzrTable>
+      </template>
+    </CzrContent>
+    <detailCom v-model:show="state.detail.show" :transfer="state.detail.transfer" @refresh="onSearch"/>
+    <renameCom v-model:show="state.rename.show" :transfer="state.rename.transfer" @refresh="onSearch"/>
+    <knowledgeSelectCom v-model:show="state.knowledge.show" :transfer="state.knowledge.transfer" @refresh="onSearch"/>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {getCurrentInstance, inject, onMounted, reactive, ref, watch} from "vue";
+import { Search } from '@element-plus/icons-vue'
+import {debounce} from "lodash";
+import {useDialogStore, useDictionaryStore} from "@/stores";
+import {ElMessage} from "element-plus";
+import detailCom from './detail.vue'
+import renameCom from './rename.vue'
+import knowledgeSelectCom from '../document/knowledge-select.vue'
+
+const DialogStore = useDialogStore();
+const DictionaryStore = useDictionaryStore();
+const emits = defineEmits([])
+const props = defineProps({
+  knowledge: <any>{}
+})
+const {proxy}: any = getCurrentInstance()
+const ID = inject('ID')
+const state: any = reactive({
+  text: '',
+  query: {
+    loading: false,
+    head: [
+      {value: 'p1', label: '问答名称', show: true},
+      {value: 'p1', label: '创建时间', show: true},
+      {value: 'p1', label: '更新时间', show: true},
+      {value: 'caozuo', label: '操作', show: true, width: 300, fixed: 'right', popover: false},
+    ],
+    page: {
+      pageNum: 1,
+      pageSize: 20
+    },
+    form: {},
+    formReal: {},
+    result: {
+      total: 0,
+      data: []
+    },
+    selected: []
+  },
+  detail: {
+    show: false,
+    transfer: {}
+  },
+  rename: {
+    show: false,
+    transfer: {}
+  },
+  knowledge: {
+    show: false,
+    transfer: {}
+  },
+})
+const setText = debounce((v) => {
+  state.query.form.name = v
+}, 1000)
+watch(() => state.text, (n) => {
+  setText(n)
+})
+watch(() => state.query.form, (n) => {
+  onSearch()
+}, {deep: true})
+const onPage = (pageNum, pageSize) => {
+  state.query.page = {
+    pageNum: pageNum,
+    pageSize: pageSize,
+  }
+  const params = {
+    pageNum: state.query.page.pageNum,
+    pageSize: 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
+  setTimeout(() => {
+    state.query.result.total = 100
+    const arr: any = []
+    for (let i = 1; i <= params.pageSize; i++) {
+      const n = (params.pageNum - 1) * params.pageSize + i
+      arr.push({
+        id: i + '',
+        p1: '文件' + n + '.md',
+      })
+    }
+    state.query.result.data = arr
+    // setTimeout(() => {
+    //   state.query.selected = [arr[1], arr[5]]
+    // })
+    state.query.loading = false
+  }, 1000)
+  // state.query.loading = true
+  // listRuleLogisticsDataSubscribeInfo(params).then(res => {
+  //   if (res.code == 200) {
+  //     state.query.result.total = res.total
+  //     state.query.result.data = res.rows
+  //     state.query.loading = false
+  //   } else {
+  //     ElMessage.error(res.msg)
+  //   }
+  // }).catch(() => {
+  //   state.query.loading = false
+  // })
+}
+const onSearch = () => {
+  state.query.selected = []
+  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 = null) => {
+  if (row) {
+    DialogStore.confirm({
+      title: '删除确认',
+      content: `是否删除问答:${row.p1}?<br/>请谨慎操作。`,
+      onSubmit: () => {
+        ElMessage.success('删除成功!')
+        onSearch()
+      }
+    })
+  } else {
+    if (state.query.selected.length === 0) {
+      ElMessage.warning('请至少选择一条记录!')
+      return
+    }
+    DialogStore.confirm({
+      title: '删除确认',
+      content: `是否批量删除${state.query.selected.length}个问答?<br/>请谨慎操作。`,
+      onSubmit: () => {
+        ElMessage.success('删除成功!')
+        onSearch()
+      }
+    })
+  }
+}
+const onRename = (row) => {
+  state.rename.transfer = {
+    row: JSON.parse(JSON.stringify(row))
+  }
+  state.rename.show = true
+}
+const onKnowledge = (row: any = null) => {
+  if (row) {
+    state.knowledge.transfer = {
+      row: JSON.parse(JSON.stringify(row)),
+      type: 'qa',
+    }
+    state.knowledge.show = true
+  } else {
+    if (state.query.selected.length === 0) {
+      ElMessage.warning('请至少选择一条记录!')
+      return
+    }
+    state.knowledge.transfer = {
+      list: [...state.query.selected],
+      type: 'qa',
+    }
+    state.knowledge.show = true
+  }
+}
+onMounted(() => {
+  initDictionary()
+  onReset()
+})
+const initDictionary = () => {
+  DictionaryStore.initKnowledgeGroups()
+}
+</script>
+
+<style lang="scss" scoped>
+.knowledge {
+  width: 100%;
+  height: 11.81rem;
+  background-image: url("@/assets/images/knowledge-item-bg.png");
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  padding: 1rem 1.5rem;
+}
+</style>

+ 83 - 0
src/views/manage/knowledge/documents/qa/rename.vue

@@ -0,0 +1,83 @@
+<template>
+  <CzrDialog
+    :show="show"
+    title="重命名"
+    @onClose="$emit('update:show', false)"
+    @onSubmit="onSubmit"
+    width="33rem"
+    :loading="state.loading"
+  >
+    <div class="bm-form">
+      <CzrForm ref="ref_form" layout="y">
+        <CzrFormColumn
+          required
+          :span="24"
+          label="问答名称"
+          v-model:param="state.form.p1"
+        />
+      </CzrForm>
+    </div>
+  </CzrDialog>
+</template>
+
+<script setup lang="ts">
+import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from "vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {useDialogStore, useDictionaryStore} from "@/stores";
+import {useRouter} from "vue-router";
+
+const router = useRouter()
+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: {}
+})
+const ref_form = ref()
+watch(() => props.show, (n) => {
+  if (n) {
+    initDictionary()
+    state.form = {}
+    if (props.transfer.mode !== 'add') {
+      initData()
+    }
+    nextTick(() => {
+      ref_form.value.reset()
+    })
+  }
+})
+const initDictionary = () => {
+}
+const initData = () => {
+  state.form = props.transfer.row
+}
+const onSubmit = (isImport) => {
+  ref_form.value.submit().then(() => {
+    DialogStore.confirm({
+      content: `请确认是否重命名问答?`,
+      onSubmit: () => {
+        state.loading = true
+        ElMessage.success(`重命名成功!`)
+        emit('update:show', false)
+        emit('refresh')
+        state.loading = false
+      }
+    })
+  }).catch((e) => {
+    ElMessage({
+      message: e[0].message,
+      grouping: true,
+      type: 'warning',
+    })
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+</style>