Quellcode durchsuchen

1、添加问卷添加试题管理功能
2、评估管理
3、数字人问题引导、课程问题弹框配置的问题引导

liyanbo vor 11 Monaten
Ursprung
Commit
a535ebc9b6

+ 71 - 0
src/api/bjdx/questionnaire/index.ts

@@ -0,0 +1,71 @@
+import request from '@/config/axios'
+
+// 问卷 VO
+export interface QuestionnaireVO {
+  id: number // id
+  bqQuestionnaire: string // 问卷名称
+  bqDetails: string // 问卷介绍
+  bqOrder: number // 问卷排序
+  bqStartInfo: string // 问卷开始指导语
+  bqEndInfo: string // 问卷结束指导语
+  bqQuestIds: string // 问题id集
+}
+// 课程-试题 VO
+export interface CourseQuestionVO {
+  questionnaireId: number // 试卷id
+  cqQuestion: string // 试题内容
+  cqQuestType: string // 试题类型
+}
+
+// 问卷 API
+export const QuestionnaireApi = {
+  // 查询问卷分页
+  getQuestionnairePage: async (params: any) => {
+    return await request.get({ url: `/bjdx/questionnaire/page`, params })
+  },
+
+  // 查询问卷详情
+  getQuestionnaire: async (id: number) => {
+    return await request.get({ url: `/bjdx/questionnaire/get?id=` + id })
+  },
+
+  // 新增问卷
+  createQuestionnaire: async (data: QuestionnaireVO) => {
+    return await request.post({ url: `/bjdx/questionnaire/create`, data })
+  },
+
+  // 修改问卷
+  updateQuestionnaire: async (data: QuestionnaireVO) => {
+    return await request.put({ url: `/bjdx/questionnaire/update`, data })
+  },
+
+  // 删除问卷
+  deleteQuestionnaire: async (id: number) => {
+    return await request.delete({ url: `/bjdx/questionnaire/delete?id=` + id })
+  },
+
+  // 导出问卷 Excel
+  exportQuestionnaire: async (params) => {
+    return await request.download({ url: `/bjdx/questionnaire/export-excel`, params })
+  },
+
+  // 查询问卷配置
+  getConfigQuest: async (params: any) => {
+    return await request.get({ url: `/bjdx/questionnaire/getConfigQuest`, params })
+  },
+
+  // 查询问卷配置
+  getConfigQuestNo: async (params: any) => {
+    return await request.get({ url: `/bjdx/questionnaire/getConfigQuestNo`, params })
+  },
+
+  // 查询问卷配置
+  addConfigQuest: async (params: any) => {
+    return await request.get({ url: `/bjdx/questionnaire/addConfigQuest`, params })
+  },
+
+  // 查询问卷配置
+  delConfigQuest: async (params: any) => {
+    return await request.get({ url: `/bjdx/questionnaire/delConfigQuest`, params })
+  },
+}

+ 47 - 0
src/api/bjdxReport/reportmanage/index.ts

@@ -0,0 +1,47 @@
+import request from '@/config/axios'
+
+// 评估报告-评语 VO
+export interface ManageVO {
+  brcId: number // 主键id
+  brcReportCourseMin: number // 开课率最小
+  brcReportCourseMax: number // 开课率最大
+  brcReportQuestMin: number // 互动最小
+  brcReportQuestMax: number // 互动最大
+  brcReportAiCountMin: number // ai问答次数最小
+  brcReportAiCountMax: number // ai问答次数最大
+  brcReportLevel: string // 等级
+  brcReportComment: string // 评语
+}
+
+// 评估报告-评语 API
+export const ManageApi = {
+  // 查询评估报告-评语分页
+  getManagePage: async (params: any) => {
+    return await request.get({ url: `/bjdxReport/manage/page`, params })
+  },
+
+  // 查询评估报告-评语详情
+  getManage: async (id: number) => {
+    return await request.get({ url: `/bjdxReport/manage/get?id=` + id })
+  },
+
+  // 新增评估报告-评语
+  createManage: async (data: ManageVO) => {
+    return await request.post({ url: `/bjdxReport/manage/create`, data })
+  },
+
+  // 修改评估报告-评语
+  updateManage: async (data: ManageVO) => {
+    return await request.put({ url: `/bjdxReport/manage/update`, data })
+  },
+
+  // 删除评估报告-评语
+  deleteManage: async (id: number) => {
+    return await request.delete({ url: `/bjdxReport/manage/delete?id=` + id })
+  },
+
+  // 导出评估报告-评语 Excel
+  exportManage: async (params) => {
+    return await request.download({ url: `/bjdxReport/manage/export-excel`, params })
+  }
+}

+ 10 - 0
src/router/modules/remaining.ts

@@ -774,6 +774,16 @@ const remainingRouter: AppRouteRecordRaw[] = [
           icon: 'ep:setting',
           noCache: false
         }
+      },
+      {
+        path: 'questionnaire/quest',
+        component: () => import('@/views/bjdx/questionnaire/ConfigQuestion.vue'),
+        name: 'configQuest',
+        meta: {
+          title: '配置问卷',
+          icon: 'ep:setting',
+          noCache: false
+        }
       }
     ]
   },

+ 4 - 0
src/types/auto-components.d.ts

@@ -23,6 +23,7 @@ declare module 'vue' {
     ConditionDialog: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue')['default']
     ConditionNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue')['default']
     ConfigGlobal: typeof import('./../components/ConfigGlobal/src/ConfigGlobal.vue')['default']
+    ConfigQuestion: typeof import('./../views/bjdx/questionnaire/ConfigQuestion.vue')['default']
     ContentDetailWrap: typeof import('./../components/ContentDetailWrap/src/ContentDetailWrap.vue')['default']
     ContentWrap: typeof import('./../components/ContentWrap/src/ContentWrap.vue')['default']
     CopperModal: typeof import('./../components/Cropper/src/CopperModal.vue')['default']
@@ -143,6 +144,7 @@ declare module 'vue' {
     InputPassword: typeof import('./../components/InputPassword/src/InputPassword.vue')['default']
     InputWithColor: typeof import('./../components/InputWithColor/index.vue')['default']
     MagicCubeEditor: typeof import('./../components/MagicCubeEditor/index.vue')['default']
+    ManageForm: typeof import('./../views/report/reportmanage/ManageForm.vue')['default']
     MarkdownView: typeof import('./../components/MarkdownView/index.vue')['default']
     NodeHandler: typeof import('./../components/SimpleProcessDesignerV2/src/NodeHandler.vue')['default']
     OperateLogV2: typeof import('./../components/OperateLogV2/src/OperateLogV2.vue')['default']
@@ -156,7 +158,9 @@ declare module 'vue' {
     ProcessViewer: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessViewer.vue')['default']
     PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
     Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
+    Questionnaire: typeof import('./../api/bjdx/questionnaire/index.ts')['default']
     ReceiveTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue')['default']
+    Reportmanage: typeof import('./../views/report/reportmanage/index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/RouterNode.vue')['default']
     RouterNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue')['default']

+ 5 - 0
src/views/ai/model/chatRole/ChatRoleForm.vue

@@ -45,6 +45,9 @@
       <el-form-item label="角色设定" prop="systemMessage">
         <el-input type="textarea" v-model="formData.systemMessage" placeholder="请输入角色设定" />
       </el-form-item>
+      <el-form-item label="问题引导" prop="questTip">
+        <el-input type="textarea" v-model="formData.questTip" placeholder="请输入角色问题引导" />
+      </el-form-item>
       <el-form-item label="引用知识库" prop="knowledgeIds">
         <el-select v-model="formData.knowledgeIds" placeholder="请选择知识库" clearable multiple>
           <el-option
@@ -123,6 +126,7 @@ const formData = ref({
   sort: undefined,
   description: undefined,
   systemMessage: undefined,
+  questTip: undefined,
   publicStatus: true,
   status: CommonStatusEnum.ENABLE,
   knowledgeIds: [] as number[],
@@ -218,6 +222,7 @@ const resetForm = () => {
     sort: undefined,
     description: undefined,
     systemMessage: undefined,
+    questTip: undefined,
     publicStatus: true,
     status: CommonStatusEnum.ENABLE,
     knowledgeIds: [],

+ 137 - 0
src/views/bjdx/course/CourseForm.vue

@@ -68,7 +68,117 @@
       <template v-else-if="formData.courseContentType === 'quest'">
         <el-form-item >
           <br/><h2>问题</h2><br/>
+
         </el-form-item>
+
+        <div style="width: 80%;margin: 0px auto">
+          <!-- 基础信息 -->
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">题目标题</label>
+            <input
+              v-model="formData.courseBlocklyJson.title"
+              class="w-full border border-gray-300 rounded p-2"
+              placeholder="输入题目标题"
+            />
+          </div>
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">题目描述</label>
+            <textarea
+              v-model="formData.courseBlocklyJson.description"
+              class="w-full border border-gray-300 rounded p-2"
+              rows="3"
+              placeholder="输入题目描述"
+            ></textarea>
+          </div>
+
+          <!-- 迷宫地图配置 -->
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">迷宫尺寸</label>
+            <div class="flex gap-2">
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.width"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                min="5"
+                max="20"
+                placeholder="宽度"
+              />
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.height"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                min="5"
+                max="20"
+                placeholder="高度"
+              />
+            </div>
+          </div>
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">墙坐标(JSON 数组,如 [[0,1]])</label>
+            <textarea
+              v-model="formData.courseBlocklyJson.mazeConfig.walls"
+              class="w-full border border-gray-300 rounded p-2"
+              rows="3"
+              placeholder="输入墙坐标"
+            ></textarea>
+          </div>
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">起点坐标</label>
+            <div class="flex gap-2">
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.start[0]"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                placeholder="X"
+              />
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.start[1]"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                placeholder="Y"
+              />
+            </div>
+          </div>
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">终点坐标</label>
+            <div class="flex gap-2">
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.end[0]"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                placeholder="X"
+              />
+              <input
+                v-model.number="formData.courseBlocklyJson.mazeConfig.end[1]"
+                class="w-1/2 border border-gray-300 rounded p-2"
+                type="number"
+                placeholder="Y"
+              />
+            </div>
+          </div>
+
+          <!-- 初始积木配置 -->
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">初始积木(JSON 数组,如 {"type":"move_forward","count":3} )</label>
+            <textarea
+              v-model="formData.courseBlocklyJson.initialBlocks"
+              class="w-full border border-gray-300 rounded p-2"
+              rows="3"
+              placeholder="输入初始积木配置"
+            ></textarea>
+          </div>
+
+          <!-- 答案配置 -->
+          <div class="mb-4">
+            <label class="block text-gray-700 font-medium mb-1">参考解法代码</label>
+            <textarea
+              v-model="formData.courseBlocklyJson.solutionCode"
+              class="w-full border border-gray-300 rounded p-2"
+              rows="3"
+              placeholder="输入参考代码(如 moveForward(3); turnRight(); )"
+            ></textarea>
+          </div>
+        </div>
       </template>
 
       <template v-else>
@@ -157,6 +267,19 @@ const formData = ref({
   courseVideoPath: undefined,
   courseMusicPath: undefined,
   courseContent: undefined,
+  courseBlocklyJson:{
+    title: '',
+    description: '',
+    mazeConfig: {
+      width: 10,
+      height: 10,
+      walls: [],
+      start: [0, 0],
+      end: [9, 9]
+    },
+    initialBlocks: [],
+    solutionCode: ''
+  },
   courseAuthor: undefined,
   courseTeacher: undefined,
   courseSize: undefined,
@@ -167,6 +290,7 @@ const formData = ref({
   courseOrder: undefined,
   courseStatus: undefined
 })
+
 const formRules = reactive({
   courseName: [{ required: true, message: '课程名称不能为空', trigger: 'blur' }],
   courseContent: [{ required: true, message: '课程内容不能为空', trigger: 'blur' }],
@@ -240,6 +364,19 @@ const resetForm = () => {
     courseImagePath: undefined,
     courseVideoPath: undefined,
     courseContent: undefined,
+    courseBlocklyJson:{
+      title: '',
+      description: '',
+      mazeConfig: {
+        width: 10,
+        height: 10,
+        walls: [],
+        start: [0, 0],
+        end: [9, 9]
+      },
+      initialBlocks: [],
+      solutionCode: ''
+    },
     courseAuthor: undefined,
     courseTeacher: undefined,
     courseSize: undefined,

+ 6 - 0
src/views/bjdx/courseconfig/CourseConfigForm.vue

@@ -54,6 +54,10 @@
             <el-input v-model="formData.ccAnswer" placeholder="请输入答案" />
           </el-form-item>
 
+          <el-form-item label="Ai问题提示" prop="ccAiQuestTip">
+            <el-input v-model="formData.ccAiQuestTip" placeholder="请输入Ai问题提示(多条请使用英文,豆包分割)" />
+          </el-form-item>
+
           <el-form-item label="Ai答案" prop="ccAiAnswer">
             <el-input v-model="formData.ccAiAnswer" placeholder="请输入Ai答案" />
           </el-form-item>
@@ -184,6 +188,7 @@ const formData = ref({
   ccQuestSource: '0', // 问题呈现类型
   ccQuestContent: undefined,  // 问题内容
   ccQuestOption: undefined,  // 问题选项
+  ccAiQuestTip: undefined,  // AI问题提示
   ccAiAnswer: undefined,  // AI答案
   ccAnswer: undefined,  // 答案
 })
@@ -300,6 +305,7 @@ const resetForm = () => {
     ccQuestSource: '0', // 问题呈现类型
     ccQuestContent: undefined,  // 问题内容
     ccQuestOption: undefined,  // 问题选项
+    ccAiQuestTip: undefined,  // AI问题提示
     ccAiAnswer: undefined,  // AI答案
     ccAnswer: undefined,  // 答案
   }

+ 347 - 0
src/views/bjdx/questionnaire/ConfigQuestion.vue

@@ -0,0 +1,347 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="问卷名称" prop="questionnaire  ">
+        <el-input
+          v-model="queryParams.questionnaire"
+          placeholder="请输入问卷名称"
+          clearable
+          disabled
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="试题类型" prop="cqQuestType">
+        <el-select
+          v-model="queryParams.cqQuestType"
+          placeholder="请选择试题类型"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.COURSE_QUESTION_TYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="试题内容" prop="cqQuestion">
+        <el-input
+          v-model="queryParams.cqQuestion"
+          placeholder="请输入试题内容"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openSelectQuestionDialog"
+          v-hasPermi="['bjdx:course-question:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 添加
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+<!--      <el-table-column label="试题id" align="center" prop="id" width="100px"/>-->
+      <el-table-column label="试题类型" align="center" prop="cqQuestType" width="120px">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.COURSE_QUESTION_TYPE" :value="scope.row.cqQuestType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="试题内容" align="center" prop="cqQuestion" >
+        <template #default="scope">
+          <div v-html="scope.row.cqQuestion"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="试题解析" align="center" prop="cqQuestAnalysis" >
+        <template #default="scope">
+          <div v-html="scope.row.cqQuestAnalysis"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" align="center" prop="bqOrder" />
+      <el-table-column label="操作" align="center" min-width="120px">
+        <template #default="scope">
+<!--          <el-button-->
+<!--            link-->
+<!--            type="primary"-->
+<!--            @click="openForm('update', scope.row.id)"-->
+<!--            v-hasPermi="['bjdx:course-question:update']"-->
+<!--          >-->
+<!--            编辑-->
+<!--          </el-button>-->
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['bjdx:course-question:delete']"
+          >
+            删除
+          </el-button>
+          <el-button
+            link
+            type="info"
+            @click="goToOptionList(scope.row.id, scope.row.cqQuestion)"
+            v-hasPermi="['bjdx:course-question:update']"
+          >
+            选项列表
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 选择试题弹窗 -->
+  <el-dialog
+    v-model="selectQuestionDialogVisible"
+    title="选择试题"
+    width="80%"
+  >
+    <el-form
+      class="-mb-15px"
+      :model="selectQueryParams"
+      ref="selectQueryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="试题类型" prop="cqQuestType">
+        <el-select
+          v-model="selectQueryParams.cqQuestType"
+          placeholder="请选择试题类型"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.COURSE_QUESTION_TYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="试题内容" prop="cqQuestion">
+        <el-input
+          v-model="selectQueryParams.cqQuestion"
+          placeholder="请输入试题内容"
+          clearable
+          @keyup.enter="handleSelectQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleSelectQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetSelectQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table v-loading="selectLoading" :data="selectList" ref="selectTableRef" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="试题类型" align="center" prop="cqQuestType" width="120px">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.COURSE_QUESTION_TYPE" :value="scope.row.cqQuestType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="试题内容" align="center" prop="cqQuestion" >
+        <template #default="scope">
+          <div v-html="scope.row.cqQuestion"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="试题解析" align="center" prop="cqQuestAnalysis" >
+        <template #default="scope">
+          <div v-html="scope.row.cqQuestAnalysis"></div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <template #footer>
+      <span class="dialog-footer">
+        <el-button @click="selectQuestionDialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="confirmSelectQuestions">确定</el-button>
+      </span>
+    </template>
+  </el-dialog>
+
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted } from 'vue'
+import { QuestionnaireApi, CourseQuestionVO } from '@/api/bjdx/questionnaire'
+import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
+import { useRoute, useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+
+
+/** 课程-试题 列表 */
+defineOptions({ name: 'Questionnaire' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<CourseQuestionVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  questionnaireId: undefined, // 试卷id
+  questionIds: [], // 题id
+  questionnaire: undefined, // 试卷名称
+  cqQuestion: undefined, // 试题内容
+  cqQuestType: undefined // 试题类型
+})
+const queryFormRef = ref() // 搜索的表单
+const route = useRoute()
+
+// 选择试题弹窗相关
+const selectQuestionDialogVisible = ref(false)
+const selectLoading = ref(true)
+const selectList = ref<CourseQuestionVO[]>([])
+const selectQueryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  id: undefined, // 试题id
+  questionnaireId: undefined, // 试题id
+  questionIds: [], // 试题id
+  cqQuestion: undefined, // 试题内容
+  cqQuestType: undefined // 试题类型
+})
+const selectQueryFormRef = ref()
+const selectTableRef = ref()
+
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+
+    queryParams.questionnaireId = route.query.questionnaireId
+    queryParams.questionnaire = route.query.questionnaire
+
+    const data = await QuestionnaireApi.getConfigQuest(queryParams)
+    console.log(data)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 打开选择试题弹窗 */
+const openSelectQuestionDialog = () => {
+  selectQuestionDialogVisible.value = true
+  selectQueryParams.questionnaireId = route.query.questionnaireId
+  getSelectList()
+}
+
+/** 查询选择试题列表 */
+const getSelectList = async () => {
+  selectLoading.value = true
+  try {
+    const data = await QuestionnaireApi.getConfigQuestNo(selectQueryParams)
+    selectList.value = data.list
+  } finally {
+    selectLoading.value = false
+  }
+}
+
+/** 选择试题列表搜索按钮操作 */
+const handleSelectQuery = () => {
+  selectQueryParams.pageNo = 1
+  getSelectList()
+}
+
+/** 选择试题列表重置按钮操作 */
+const resetSelectQuery = () => {
+  selectQueryFormRef.value.resetFields()
+  handleSelectQuery()
+}
+
+/** 确认选择试题 */
+const confirmSelectQuestions = async () => {
+  const selectedRows = selectTableRef.value?.getSelectionRows() || []
+  queryParams.questionIds = selectedRows.map(row => row.id)
+  if (queryParams.questionIds.length === 0) {
+    message.warning(t('请选择至少一个试题'))
+    return
+  }
+  try {
+    await QuestionnaireApi.addConfigQuest(queryParams)
+    message.success(t('添加试题成功'))
+    selectQuestionDialogVisible.value = false
+    getList()
+  } catch (error) {
+    message.error(t('添加试题失败'))
+  }
+}
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    queryParams.questionIds = [id]
+    await QuestionnaireApi.delConfigQuest(queryParams)
+
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+
+const router = useRouter()
+
+// 跳转选项列表页
+const goToOptionList = (id: number, question: String) => {
+  router.push({
+    name: 'questOption',
+    query: { questId: id , question: question}
+  })
+}
+</script>

+ 115 - 0
src/views/bjdx/questionnaire/QuestionnaireForm.vue

@@ -0,0 +1,115 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible" width="800px">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="120px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="问卷名称" prop="bqQuestionnaire">
+        <el-input v-model="formData.bqQuestionnaire" placeholder="请输入问卷名称" />
+      </el-form-item>
+      <el-form-item label="问卷介绍" prop="bqDetails">
+        <Editor v-model="formData.bqDetails" height="150px" />
+      </el-form-item>
+      <el-form-item label="问卷排序" prop="bqOrder">
+        <el-input-number v-model="formData.bqOrder" placeholder="请输入问卷排序" :min="0" clearable controls-position="right" class="!w-1/1" />
+      </el-form-item>
+      <el-form-item label="问卷开始指导语" prop="bqStartInfo">
+        <Editor v-model="formData.bqStartInfo" height="150px" />
+      </el-form-item>
+      <el-form-item label="问卷结束指导语" prop="bqEndInfo">
+        <Editor v-model="formData.bqEndInfo" height="150px" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { QuestionnaireApi, QuestionnaireVO } from '@/api/bjdx/questionnaire'
+
+/** 问卷 表单 */
+defineOptions({ name: 'QuestionnaireForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  id: undefined,
+  bqQuestionnaire: undefined,
+  bqDetails: undefined,
+  bqOrder: undefined,
+  bqStartInfo: undefined,
+  bqEndInfo: undefined,
+  bqQuestIds: undefined
+})
+const formRules = reactive({
+  bqQuestionnaire: [{ required: true, message: '问卷名称不能为空', trigger: 'blur' }],
+  bqOrder: [{ required: true, message: '问卷排序不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await QuestionnaireApi.getQuestionnaire(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as QuestionnaireVO
+    if (formType.value === 'create') {
+      await QuestionnaireApi.createQuestionnaire(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await QuestionnaireApi.updateQuestionnaire(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    bqQuestionnaire: undefined,
+    bqDetails: undefined,
+    bqOrder: undefined,
+    bqStartInfo: undefined,
+    bqEndInfo: undefined,
+    bqQuestIds: undefined
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 218 - 0
src/views/bjdx/questionnaire/index.vue

@@ -0,0 +1,218 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="问卷名称" prop="bqQuestionnaire">
+        <el-input
+          v-model="queryParams.bqQuestionnaire"
+          placeholder="请输入问卷名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-220px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['bjdx:questionnaire:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['bjdx:questionnaire:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+<!--      <el-table-column label="id" align="center" prop="id" />-->
+      <el-table-column label="问卷名称" align="center" prop="bqQuestionnaire" />
+      <el-table-column label="问卷介绍" align="center" prop="bqDetails" >
+        <template #default="scope">
+          <div v-html="scope.row.bqDetails"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="问卷排序" align="center" prop="bqOrder" />
+      <el-table-column label="问卷开始指导语" align="center" prop="bqStartInfo" >
+        <template #default="scope">
+          <div v-html="scope.row.bqStartInfo"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="问卷结束指导语" align="center" prop="bqEndInfo" >
+        <template #default="scope">
+          <div v-html="scope.row.bqStartInfo"></div>
+        </template>
+      </el-table-column>
+      <el-table-column label="问题id集" align="center" prop="bqQuestIds" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="操作" align="center" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['bjdx:questionnaire:delete']"
+          >
+            删除
+          </el-button>
+          <el-button
+            link
+            type="success"
+            @click="handleConfig(scope.row.id,scope.row.bqQuestionnaire)"
+          >
+            试题配置
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <QuestionnaireForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { QuestionnaireApi, QuestionnaireVO } from '@/api/bjdx/questionnaire'
+import QuestionnaireForm from './QuestionnaireForm.vue'
+import { useRouter } from 'vue-router'
+
+/** 问卷 列表 */
+defineOptions({ name: 'Questionnaire' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<QuestionnaireVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  bqQuestionnaire: undefined,
+  bqDetails: undefined,
+  bqOrder: undefined,
+  bqStartInfo: undefined,
+  bqEndInfo: undefined,
+  bqQuestIds: undefined,
+  createTime: []
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await QuestionnaireApi.getQuestionnairePage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await QuestionnaireApi.deleteQuestionnaire(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await QuestionnaireApi.exportQuestionnaire(queryParams)
+    download.excel(data, '问卷.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 配置按钮操作 */
+const router = useRouter()
+const handleConfig = (id: number,bqQuestionnaire: string) => {
+  router.push({
+    name: 'configQuest',
+    query: { questionnaireId: id , questionnaire: bqQuestionnaire}
+  })
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 126 - 0
src/views/bjdxReport/reportmanage/ManageForm.vue

@@ -0,0 +1,126 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="100px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="开课率最小" prop="brcReportCourseMin">
+        <el-input v-model="formData.brcReportCourseMin" placeholder="请输入开课率最小" />
+      </el-form-item>
+      <el-form-item label="开课率最大" prop="brcReportCourseMax">
+        <el-input v-model="formData.brcReportCourseMax" placeholder="请输入开课率最大" />
+      </el-form-item>
+      <el-form-item label="互动最小" prop="brcReportQuestMin">
+        <el-input v-model="formData.brcReportQuestMin" placeholder="请输入互动最小" />
+      </el-form-item>
+      <el-form-item label="互动最大" prop="brcReportQuestMax">
+        <el-input v-model="formData.brcReportQuestMax" placeholder="请输入互动最大" />
+      </el-form-item>
+      <el-form-item label="ai问答次数最小" prop="brcReportAiCountMin">
+        <el-input v-model="formData.brcReportAiCountMin" placeholder="请输入ai问答次数最小" />
+      </el-form-item>
+      <el-form-item label="ai问答次数最大" prop="brcReportAiCountMax">
+        <el-input v-model="formData.brcReportAiCountMax" placeholder="请输入ai问答次数最大" />
+      </el-form-item>
+      <el-form-item label="等级" prop="brcReportLevel">
+        <el-input v-model="formData.brcReportLevel" placeholder="请输入等级" />
+      </el-form-item>
+      <el-form-item label="评语" prop="brcReportComment">
+        <el-input v-model="formData.brcReportComment" placeholder="请输入评语" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { ManageApi, ManageVO } from '@/api/bjdxReport/reportmanage'
+
+/** 评估报告-评语 表单 */
+defineOptions({ name: 'ManageForm' })
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  brcId: undefined,
+  brcReportCourseMin: undefined,
+  brcReportCourseMax: undefined,
+  brcReportQuestMin: undefined,
+  brcReportQuestMax: undefined,
+  brcReportAiCountMin: undefined,
+  brcReportAiCountMax: undefined,
+  brcReportLevel: undefined,
+  brcReportComment: undefined
+})
+const formRules = reactive({
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await ManageApi.getManage(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as ManageVO
+    if (formType.value === 'create') {
+      await ManageApi.createManage(data)
+      message.success(t('common.createSuccess'))
+    } else {
+      await ManageApi.updateManage(data)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    brcId: undefined,
+    brcReportCourseMin: undefined,
+    brcReportCourseMax: undefined,
+    brcReportQuestMin: undefined,
+    brcReportQuestMax: undefined,
+    brcReportAiCountMin: undefined,
+    brcReportAiCountMax: undefined,
+    brcReportLevel: undefined,
+    brcReportComment: undefined
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 265 - 0
src/views/bjdxReport/reportmanage/index.vue

@@ -0,0 +1,265 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="开课率最小" prop="brcReportCourseMin">
+        <el-input
+          v-model="queryParams.brcReportCourseMin"
+          placeholder="请输入开课率最小"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="开课率最大" prop="brcReportCourseMax">
+        <el-input
+          v-model="queryParams.brcReportCourseMax"
+          placeholder="请输入开课率最大"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="互动最小" prop="brcReportQuestMin">
+        <el-input
+          v-model="queryParams.brcReportQuestMin"
+          placeholder="请输入互动最小"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="互动最大" prop="brcReportQuestMax">
+        <el-input
+          v-model="queryParams.brcReportQuestMax"
+          placeholder="请输入互动最大"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="ai问答次数最小" prop="brcReportAiCountMin">
+        <el-input
+          v-model="queryParams.brcReportAiCountMin"
+          placeholder="请输入ai问答次数最小"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="ai问答次数最大" prop="brcReportAiCountMax">
+        <el-input
+          v-model="queryParams.brcReportAiCountMax"
+          placeholder="请输入ai问答次数最大"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="等级" prop="brcReportLevel">
+        <el-input
+          v-model="queryParams.brcReportLevel"
+          placeholder="请输入等级"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="评语" prop="brcReportComment">
+        <el-input
+          v-model="queryParams.brcReportComment"
+          placeholder="请输入评语"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTime">
+        <el-date-picker
+          v-model="queryParams.createTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+          class="!w-220px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['report:manage:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['report:manage:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="主键id" align="center" prop="brcId" />
+      <el-table-column label="开课率最小" align="center" prop="brcReportCourseMin" />
+      <el-table-column label="开课率最大" align="center" prop="brcReportCourseMax" />
+      <el-table-column label="互动最小" align="center" prop="brcReportQuestMin" />
+      <el-table-column label="互动最大" align="center" prop="brcReportQuestMax" />
+      <el-table-column label="ai问答次数最小" align="center" prop="brcReportAiCountMin" />
+      <el-table-column label="ai问答次数最大" align="center" prop="brcReportAiCountMax" />
+      <el-table-column label="等级" align="center" prop="brcReportLevel" />
+      <el-table-column label="评语" align="center" prop="brcReportComment" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="操作" align="center" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['report:manage:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['report:manage:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <ManageForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+// 修复导入路径,使用 @ 别名代替 src/
+import { ManageApi, ManageVO } from '@/api/bjdxReport/reportmanage'
+import ManageForm from './ManageForm.vue'
+
+/** 评估报告-评语 列表 */
+defineOptions({ name: 'ReportManage' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<ManageVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  brcReportCourseMin: undefined,
+  brcReportCourseMax: undefined,
+  brcReportQuestMin: undefined,
+  brcReportQuestMax: undefined,
+  brcReportAiCountMin: undefined,
+  brcReportAiCountMax: undefined,
+  brcReportLevel: undefined,
+  brcReportComment: undefined,
+  createTime: []
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await ManageApi.getManagePage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ManageApi.deleteManage(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await ManageApi.exportManage(queryParams)
+    download.excel(data, '评估报告-评语.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>