Преглед на файлове

feat: 调整文档出卷的实现逻辑

zhupei@smartai.com преди 1 година
родител
ревизия
8d50e0b6b4

+ 19 - 0
public/i18n/lang-en.json

@@ -414,6 +414,25 @@
 
     "copy": "Copy"
   },
+  "wendangchujuan": {
+    "agent_title": "Document paper",
+
+    "dificulty": "Difficulty",
+    "should_generate_paper": "Whether to generate a test paper",
+    "count_q_single_choice": "Number of Single choice question",
+    "count_q_muilty_choice": "Multiple Choice Question Quantity",
+    "count_q_fill_blank": "Number of fill in the blank questions",
+    "count_q_judge": "Number of True or False Questions",
+    "count_q_ask": "Number of short answer questions",
+    "count_q_case": "Number of Case Questions",
+    "keywords": "Topic direction or keywords",
+
+    "optional": "(Optional)",
+    "type_easy": "Easy",
+    "type_difficulty": "Difficult",
+    "type_yes": "Yes",
+    "type_no": "No"
+  },
   "common": {
     "confirm_delete": "Are you sure delete?",
     "doc_error": "Document loading error",

+ 19 - 0
public/i18n/lang-zh.json

@@ -409,6 +409,25 @@
 
     "copy": "复制"
   },
+  "wendangchujuan": {
+    "agent_title": "文档出卷",
+
+    "dificulty": "难度",
+    "should_generate_paper": "是否生成试卷",
+    "count_q_single_choice": "单选题数量",
+    "count_q_muilty_choice": "多选题数量",
+    "count_q_fill_blank": "填空题数量",
+    "count_q_judge": "判断题数量",
+    "count_q_ask": "简答题数量",
+    "count_q_case": "案例题数量",
+    "keywords": "出题方向或关键字",
+
+    "optional": "(可选)",
+    "type_easy": "简单",
+    "type_difficulty": "困难",
+    "type_yes": "是",
+    "type_no": "否"
+  },
   "common": {
     "confirm_delete": "确定删除吗?",
     "doc_error": "文档加载出错",

+ 73 - 0
src/modules/btn-iframe-chujuan/BtnConfigChujuan.vue

@@ -0,0 +1,73 @@
+<template>
+  <a-button @click="handleClick" class="chujuan-btn">
+    <img class="chujuan-logo-img" :src="logo" /> {{ $t('wendangchujuan.agent_title') }}
+  </a-button>
+
+  <a-modal
+    v-model:visible="visible"
+    @ok="handleOk"
+    @cancel="handleCancel"
+    modal-class="chujuan-config-container-modal"
+    body-class="chujuan-config-container-body"
+  >
+    <template #title> <img class="chujuan-logo-img" :src="logo" /> {{ $t('wendangchujuan.agent_title') }} </template>
+
+    <ConversationChujuan ref="confForm" />
+  </a-modal>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+
+import logo from '../../assets/1.png';
+
+import ConversationChujuan from '../conversation-chujuan/ConversationChujuan.vue';
+
+const emits = defineEmits(['confirm']);
+
+const confForm = ref(null);
+const visible = ref(false);
+
+const handleClick = () => {
+  visible.value = true;
+};
+const handleOk = () => {
+  const target = confForm.value;
+  if (target && typeof target.getValues === 'function') {
+    const data = target.getValues();
+
+    emits('confirm', data);
+  }
+
+  visible.value = false;
+};
+const handleCancel = () => {
+  visible.value = false;
+};
+</script>
+
+<style scoped>
+.chujuan-btn {
+  border-radius: 30px;
+  color: #353535;
+}
+.chujuan-logo-img {
+  width: 22px;
+  display: inline-block;
+  margin-right: 5px;
+}
+</style>
+
+<style>
+.chujuan-config-container-modal.arco-modal {
+  width: 50%;
+}
+.chujuan-config-container-body.arco-modal-body {
+  /* width: 50%; */
+  padding: 30px;
+}
+.chujuan-config-container-body.arco-modal-body .chujuan-iframe {
+  width: 100%;
+  height: 80vh;
+}
+</style>

+ 2 - 2
src/modules/btn-iframe-chujuan/BtnIframeChujuan.vue

@@ -53,11 +53,11 @@ const handleCancel = () => {
 <style>
 .chujuan-container-modal {
 }
-.arco-modal-body.chujuan-container-body {
+.chujuan-container-body.arco-modal-body {
   width: 100%;
   padding: 0;
 }
-.arco-modal-body.chujuan-container-body .chujuan-iframe {
+.chujuan-container-body.arco-modal-body .chujuan-iframe {
   width: 100%;
   height: 80vh;
 }

+ 40 - 0
src/modules/conversation-chat/DialogInputAttachedAttrs.vue

@@ -0,0 +1,40 @@
+<template>
+  <div>
+    <slot name="left"></slot>
+    <div class="dialog-input-attach-attrs-container">
+      <BtnIframeChujuan />
+    </div>
+    <slot name="right"></slot>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onUnmounted } from 'vue';
+
+import BtnIframeChujuan from '../btn-iframe-chujuan/BtnIframeChujuan.vue';
+
+const props = defineProps({});
+
+const emit = defineEmits(['submit', 'sizeChange']);
+
+onMounted(() => {});
+
+onUnmounted(() => {});
+</script>
+
+<style lang="css" scoped>
+.dialog-input-attach-attrs-container {
+  display: flex;
+  flex-direction: column;
+
+  border-radius: 12px;
+  padding-left: 30px;
+  padding-right: 30px;
+  padding-bottom: 18px;
+  padding-top: 18px;
+
+  background-color: var(--color-bg-1);
+  color: var(--color-text-1);
+  flex-grow: 1;
+}
+</style>

+ 33 - 5
src/modules/conversation-chat/DialogInputTop.vue

@@ -1,8 +1,10 @@
 <template>
   <div class="dialog-input-area-top-container">
+    <!-- 文档出卷 -->
     <template v-if="menu_id === 7">
-      <!-- 文档出卷 -->
-      <BtnIframeChujuan />
+      <!-- <BtnIframeChujuan /> -->
+
+      <BtnConfigChujuan @confirm="handleChujuanConfirm" />
     </template>
 
     <template v-if="menu_id === 9">
@@ -24,6 +26,7 @@
 import { ref, onMounted, onUnmounted } from 'vue';
 
 import BtnIframeChujuan from '../btn-iframe-chujuan/BtnIframeChujuan.vue';
+import BtnConfigChujuan from '../btn-iframe-chujuan/BtnConfigChujuan.vue';
 
 /**
  * 此组件用以处理对话的附加参数
@@ -45,6 +48,8 @@ const radio_qingxi_text = '对上传的文档进行清洗,输出生成清洗
 const radio_shengcheng_text = '对上传的(经过清洗的)文档生成报告,输出生成的报告文档';
 // const emit = defineEmits(['change']);
 
+const menuid7_config_datas = ref({});
+
 const handleRadioClick = (value) => {
   act_type.value = value / 1;
 };
@@ -54,14 +59,37 @@ const handleRadioClick = (value) => {
  */
 const clear = () => {};
 
+/**
+ * 出卷的数据
+ */
+const handleChujuanConfirm = (data) => {
+  menuid7_config_datas.value = data;
+};
+
 /**
  * 获取所有的数据
  * 父组件应该使用 ref,调用此参数
  */
 const getOptions = () => {
-  return {
-    workflow: act_type.value
-  };
+  if (props.menu_id === 7) {
+    const obj = {};
+
+    const params = menuid7_config_datas.value;
+
+    for (let key in params) {
+      obj[key] = params[key];
+    }
+
+    return obj;
+  }
+
+  if (props.menu_id === 9) {
+    return {
+      workflow: act_type.value
+    };
+  }
+
+  return {};
 };
 
 defineExpose({

+ 8 - 1
src/modules/conversation-chat/DialogWelcome.vue

@@ -13,10 +13,17 @@ const props = defineProps({
 </script>
 
 <style lang="css" scoped>
-.dialog-welcome {
+.dialog-welcome-content {
   margin-top: 30px;
   margin-bottom: 30px;
 
+  margin-left: auto;
+  margin-right: auto;
+
   color: var(--color-text-1);
+
+  /* background-color: #aaa; */
+  width: 300px;
+  height: 300px;
 }
 </style>

+ 248 - 0
src/modules/conversation-chujuan/ConversationChujuan.vue

@@ -0,0 +1,248 @@
+<template>
+  <div>
+    <a-form :model="form" :style="{ width: '100%' }" @submit="handleSubmit">
+      <a-form-item field="difficulty" :label="$t('wendangchujuan.dificulty')">
+        <a-select
+          v-model="form.difficulty"
+          :placeholder="$t('wendangchujuan.dificulty') + $t('wendangchujuan.optional')"
+          allow-clear
+        >
+          <a-option :value="1">{{ $t('wendangchujuan.type_easy') }}</a-option>
+          <a-option :value="2">{{ $t('wendangchujuan.type_difficulty') }}</a-option>
+        </a-select>
+      </a-form-item>
+
+      <a-form-item field="gen_paper" :label="$t('wendangchujuan.should_generate_paper')">
+        <a-select
+          v-model="form.gen_paper"
+          :placeholder="$t('wendangchujuan.should_generate_paper') + $t('wendangchujuan.optional')"
+          allow-clear
+        >
+          <a-option :value="1">{{ $t('wendangchujuan.type_yes') }}</a-option>
+          <a-option :value="0">{{ $t('wendangchujuan.type_no') }}</a-option>
+        </a-select>
+      </a-form-item>
+
+      <a-form-item field="count_select_single" :label="$t('wendangchujuan.count_q_single_choice')">
+        <a-input
+          v-model="form.count_select_single"
+          :placeholder="$t('wendangchujuan.count_q_single_choice') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_fill_blank" :label="$t('wendangchujuan.count_q_fill_blank')">
+        <a-input
+          v-model="form.count_fill_blank"
+          :placeholder="$t('wendangchujuan.count_q_fill_blank') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_judge" :label="$t('wendangchujuan.count_q_judge')">
+        <a-input
+          v-model="form.count_judge"
+          :placeholder="$t('wendangchujuan.count_q_judge') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_select_muilty" :label="$t('wendangchujuan.count_q_muilty_choice')">
+        <a-input
+          v-model="form.count_select_muilty"
+          :placeholder="$t('wendangchujuan.count_q_muilty_choice') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_ask" :label="$t('wendangchujuan.count_q_ask')">
+        <a-input
+          v-model="form.count_ask"
+          :placeholder="$t('wendangchujuan.count_q_ask') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_example_case" :label="$t('wendangchujuan.count_q_case')">
+        <a-input
+          v-model="form.count_example_case"
+          :placeholder="$t('wendangchujuan.count_q_case') + $t('wendangchujuan.optional')"
+          type="number"
+          :min="0"
+          :max="100"
+        />
+      </a-form-item>
+
+      <a-form-item field="count_keywords" :label="$t('wendangchujuan.keywords')">
+        <a-textarea
+          v-model="form.count_keywords"
+          :placeholder="$t('wendangchujuan.keywords') + $t('wendangchujuan.optional')"
+          :auto-size="text_area_autosize"
+        />
+      </a-form-item>
+    </a-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue';
+
+const text_area_autosize = {
+  minRows: 2,
+  maxRows: 5
+};
+
+const form = reactive({
+  // 难度
+  difficulty: '',
+  // 是否生成试卷
+  gen_paper: '',
+  // 单选数量
+  count_select_single: '',
+  // 填空数量
+  count_fill_blank: '',
+  // 判断题数量
+  count_judge: '',
+  // 多选数量
+  count_select_muilty: '',
+  // 简答数量
+  count_ask: '',
+  // 案例题数量
+  count_example_case: '',
+  // 关键字或者出题方向
+  count_keywords: ''
+});
+
+const handleSubmit = (data) => {
+  console.log(data);
+};
+
+/**
+ * 获取表单里的所有数据
+ */
+const getFormFiledValues = () => {
+  const obj = {
+    // // 难度
+    // difficulty: form.difficulty, // 0/1
+    // // 是否生成试卷
+    // is_paper: form.gen_paper, // 0/1
+    // // 单选数量
+    // single_choice: form.count_select_single, // 数量
+    // // 填空数量
+    // gap_filling: form.count_fill_blank,
+    // // 判断题数量
+    // true_or_false: form.count_judge,
+    // // 多选数量
+    // multiple_choice: form.count_select_muilty,
+    // // 简答数量
+    // easy_question: form.count_ask,
+    // // 案例题数量
+    // case_questions: form.count_example_case,
+    // // 关键字或者出题方向
+    // key_words: form.count_keywords
+  };
+
+  if (form.difficulty === 0 || form.difficulty === 1) {
+    obj.difficulty = form.difficulty;
+  }
+
+  if (form.gen_paper === 0 || form.gen_paper === 1) {
+    obj.is_paper = form.gen_paper;
+  }
+
+  // 单选数量
+  if (form.count_select_single.length !== 0) {
+    if (form.count_select_single / 1 > 0) {
+      obj.single_choice = form.count_select_single / 1;
+    }
+  }
+
+  // 填空数量
+  if (form.count_fill_blank.length !== 0) {
+    if (form.count_fill_blank / 1 > 0) {
+      obj.gap_filling = form.count_fill_blank / 1;
+    }
+  }
+
+  // 判断题数量
+  if (form.count_judge.length !== 0) {
+    if (form.count_judge / 1 > 0) {
+      obj.true_or_false = form.count_judge / 1;
+    }
+  }
+
+  // 多选数量
+  if (form.count_select_muilty.length !== 0) {
+    if (form.count_select_muilty / 1 > 0) {
+      obj.multiple_choice = form.count_select_muilty / 1;
+    }
+  }
+
+  // 简答数量
+  if (form.count_ask.length !== 0) {
+    if (form.count_ask / 1 > 0) {
+      obj.easy_question = form.count_ask / 1;
+    }
+  }
+
+  // 案例题数量
+  if (form.count_example_case.length !== 0) {
+    if (form.count_example_case / 1 > 0) {
+      obj.case_questions = form.count_example_case / 1;
+    }
+  }
+
+  // 关键字或者出题方向
+  if (form.count_keywords.length !== 0) {
+    obj.key_words = form.count_keywords;
+  }
+
+  return obj;
+};
+/**
+ * 清空表单
+ */
+const clearFormFiledValues = () => {
+  // 难度
+  form.difficulty = '';
+  // 是否生成试卷
+  form.gen_paper = '';
+  // 单选数量
+  form.count_select_single = '';
+  // 填空数量
+  form.count_fill_blank = '';
+  // 判断题数量
+  form.count_judge = '';
+  // 多选数量
+  form.count_select_muilty = '';
+  // 简答数量
+  form.count_ask = '';
+  // 案例题数量
+  form.count_example_case = '';
+  // 关键字或者出题方向
+  form.count_keywords = '';
+};
+
+defineExpose({
+  /**
+   * 父组件通过ref,调用getValues方法,可以获取到表单里的所有数据
+   */
+  getValues: getFormFiledValues,
+  /**
+   * 父组件通过ref,调用clear方法,可以将表单里数据清空
+   */
+  clear: clearFormFiledValues
+});
+</script>
+
+<style scoped></style>

+ 15 - 0
src/modules/conversation-dialog/format-dialog-send-options.js

@@ -63,6 +63,21 @@ export default function formatDialogSendOptions(text, file_list, menu_id) {
       break;
     case 7:
       // 文档出卷
+      send_data = {
+        message: text
+        // upload_file_id: [] // 文件ID的列表
+      };
+
+      if (file_list && Array.isArray(file_list)) {
+        const upload_file_ids = [];
+        const len = file_list.length;
+        for (let i = 0; i < len; i++) {
+          const file_item = file_list[i];
+          upload_file_ids.push(file_item.id);
+        }
+        send_data.upload_files = upload_file_ids;
+      }
+
       break;
     case 8:
       // 出题组卷

+ 35 - 6
src/views/conversation/ConversationChatContainer.vue

@@ -39,6 +39,15 @@
           </DialogList>
         </div>
 
+        <!-- <DialogInputAttachedAttrs class="conversation-input-attached">
+          <template v-slot:left>
+            <div class="scroll-left"></div>
+          </template>
+          <template v-slot:right>
+            <div class="scroll-right"></div>
+          </template>
+        </DialogInputAttachedAttrs> -->
+
         <DialogInput
           ref="dialog_input"
           class="conversation-chat-input"
@@ -78,6 +87,7 @@ import DialogHeader from '../../modules/conversation-chat/DialogHeader.vue';
 import DialogWelcome from '../../modules/conversation-chat/DialogWelcome.vue';
 import DialogList from '../../modules/conversation-chat/DialogList.vue';
 import DialogInput from '../../modules/conversation-chat/DialogInput.vue';
+// import DialogInputAttachedAttrs from '../../modules/conversation-chat/DialogInputAttachedAttrs.vue';
 import DialogInputTop from '../../modules/conversation-chat/DialogInputTop.vue';
 import DialogFooter from '../../modules/conversation-chat/DialogFooter.vue';
 
@@ -270,6 +280,10 @@ const enable_text_input = computed(() => {
     return false;
   }
 
+  // if (menu_id === 7) {
+  //   return false;
+  // }
+
   return true;
 });
 
@@ -310,6 +324,10 @@ const enable_file_upload = computed(() => {
     return true;
   }
 
+  if (menu_id === 7) {
+    return true;
+  }
+
   return false;
 });
 /**
@@ -388,7 +406,7 @@ const handleErrorMessage = (msg) => {
  * 异常处理过程是一个会话模拟的过程
  * 先在界面上显示加载动画,然后紧接着显示错误提示
  * 让用户感知到智能体有处理数据的过程
- * 所以在异常处理阶段,有一些需要处理的关键点,比如欢迎界面的显示(如果在现实,则需要隐藏,否则对话显示不了)
+ * 所以在异常处理阶段,有一些需要处理的关键点,比如欢迎界面的显示(如果在显示,则需要隐藏,否则对话显示不了)
  * @param exceptionInfo
  */
 const handleChatRequestionException = (exceptionInfo) => {
@@ -585,7 +603,7 @@ const handleInputSubmit = async (options) => {
    * 在某些情况下,仅有文本和文件还不够,可能还有其他控制参数
    * 在这种情况下,可以通过 DialogInputTop 获取到附加参数
    * 添加附加参数
-   * 附加参数应该是一个键值对对象,最终和和已有的文本参数和文件参数合并成一个新的键值对对象发送给websocket
+   * 附加参数应该是 一个 键值对 对象,最终和和已有的 文本参数和文件参数 合并成 一个 新的键值对 对象 发送给websocket
    */
   // 获取附加表单的数据项目
   if (other_options && typeof other_options === 'object') {
@@ -864,17 +882,28 @@ onUnmounted(() => {
   justify-content: center;
   align-items: center;
 }
+.conversation-input-attached {
+  flex-shrink: 0;
+
+  width: 100%;
+
+  margin-left: auto;
+  margin-right: auto;
+
+  /* margin-top: 5px; */
+  margin-bottom: -10px;
+  padding: 5px;
+  border-radius: 10px;
+
+  display: flex;
+}
 .conversation-chat-input {
-  /* height: 100px; */
-  /* background-color: #a67777; */
   flex-shrink: 0;
 
-  /* max-width: 960px; */
   width: 100%;
 
   margin-left: auto;
   margin-right: auto;
-  /* flex-grow: 1; */
 
   margin-top: 5px;
   margin-bottom: 5px;