yangg 4 өдөр өмнө
parent
commit
156e7737dc

+ 1 - 1
.env.development

@@ -6,7 +6,7 @@ ENV = 'development'
 # 本地环境接口地址 121.36.251.245
 
 
-VITE_API_URL = 'http://192.168.100.187:8083'
+VITE_API_URL = 'https://backend.qicai321.com'
 # VITE_API_URL = 'https://backend.qicai321.com'
 VITE_API_WX_URL='https://api.weixin.qq.com/'
 VITE_API_URL_MINLONG='http://117.185.80.170:7861'

+ 188 - 65
src/views/position/detail/index.vue

@@ -1404,7 +1404,7 @@
       </template>
     </el-dialog>
 
-    <!-- 添加题选择对话框 -->
+    <!-- 添加心理题选择对话框 -->
     <el-dialog
       title="选择题目"
       v-model="showQuestionSelectDialog"
@@ -2054,7 +2054,7 @@
         </span>
       </template>
     </el-dialog>
-    <!-- 绑定问题 -->
+    <!-- 绑定综合素质问题 -->
     <el-dialog
       title="选择题目"
       v-model="QuestionSelectDialog"
@@ -2063,68 +2063,82 @@
       class="question-select-dialog"
     >
       <div class="question-select-content">
-        <!-- 搜索栏 -->
-        <div class="search-bar">
-          <div class="search-inputs">
-            <el-input
-              v-model="questionSearchKeyword"
-              placeholder="请输入关键词搜索题目"
-              clearable
-              @clear="handleQuestionSearch"
-              @keyup.enter="handleQuestionSearch"
-              style="width: 300px; margin-right: 10px;"
-            >
-              <template #append>
-                <el-button @click="handleQuestionSearch">
-                  <el-icon><Search /></el-icon>
-                </el-button>
-              </template>
-            </el-input>
-            <el-select 
-              v-model="questionListQuery.question_form" 
-              placeholder="题目类型"
-              clearable
-              @change="handleQuestionSearch"
-              style="width: 120px;"
-            >
-              <el-option label="开放问题" :value="0" />
-              <el-option label="单选题" :value="1" />
-              <el-option label="多选题" :value="2" />
-              <el-option label="看图选答案" :value="3" />
-              <el-option label="得分题" :value="4" />
-              <el-option label="追加型开放问题" :value="5" />
-              <el-option label="填空题" :value="6" />
-            </el-select>
-          </div>
-        </div>
-
-        <!-- 题目列表 -->
-        <div class="question-lists">
-          <el-table
-            :data="questionList"
-            style="width: 100%"
-            @selection-change="handleQuestionSelectionChange"
-          >
-            <el-table-column type="selection" width="55" />
-            <el-table-column prop="question" label="题目标题" />
-            <el-table-column prop="question_form_name" label="题目类型" width="100"/>
-            <!-- <el-table-column prop="content" label="面试内容" show-overflow-tooltip />
-            <el-table-column prop="target" label="对话目标" show-overflow-tooltip /> -->
-          </el-table>
+        
+        <el-row class="document-el-row">
+          <el-col :span="3">
+            <div class="document-box document-left-box">
+              <TreeList ref="treeListRef" :treeData="documentTreeData"
+              @treeClick="handleTreeClick"
+              @updateDocument="handleUpdateDocument"
+              @deleteDocument="handleDeleteDocument" />
+            </div>
+          </el-col>
+          <el-col :span="21">
+            <!-- 搜索栏 -->
+              <div class="search-bar">
+                <div class="search-inputs">
+                  <el-input
+                    v-model="questionSearchKeyword"
+                    placeholder="请输入关键词搜索题目"
+                    clearable
+                    @clear="handleQuestionSearch"
+                    @keyup.enter="handleQuestionSearch"
+                    style="width: 300px; margin-right: 10px;"
+                  >
+                    <template #append>
+                      <el-button @click="handleQuestionSearch">
+                        <el-icon><Search /></el-icon>
+                      </el-button>
+                    </template>
+                  </el-input>
+                  <el-select 
+                    v-model="questionListQuery.question_form" 
+                    placeholder="题目类型"
+                    clearable
+                    @change="handleQuestionSearch"
+                    style="width: 120px;"
+                  >
+                    <el-option label="开放问题" :value="0" />
+                    <el-option label="单选题" :value="1" />
+                    <el-option label="多选题" :value="2" />
+                    <el-option label="看图选答案" :value="3" />
+                    <el-option label="得分题" :value="4" />
+                    <el-option label="追加型开放问题" :value="5" />
+                    <el-option label="填空题" :value="6" />
+                  </el-select>
+                </div>
+              </div>
+                <!-- 题目列表 -->
+            <div class="question-lists">
+              <el-table
+                :data="questionList"
+                style="width: 100%"
+                @selection-change="handleQuestionSelectionChange"
+              >
+                <el-table-column type="selection" width="55" />
+                <el-table-column prop="question" label="题目标题" />
+                <el-table-column prop="question_form_name" label="题目类型" width="100"/>
+                <!-- <el-table-column prop="content" label="面试内容" show-overflow-tooltip />
+                <el-table-column prop="target" label="对话目标" show-overflow-tooltip /> -->
+              </el-table>
+
+              <!-- 分页 -->
+              <div class="pagination-container">
+                <el-pagination
+                  v-model:current-page="questionListQuery.page"
+                  v-model:page-size="questionListQuery.pageSize"
+                  :total="totalQuestions2"
+                  :page-sizes="[10, 20, 50, 100]"
+                  layout="total, sizes, prev, pager, next"
+                  @size-change="handleQSizeChange"
+                  @current-change="handleQPageChange"
+                />
+              </div>
+            </div>
+          </el-col>
+		</el-row>
 
-          <!-- 分页 -->
-          <div class="pagination-container">
-            <el-pagination
-              v-model:current-page="questionListQuery.page"
-              v-model:page-size="questionListQuery.pageSize"
-              :total="totalQuestions2"
-              :page-sizes="[10, 20, 50, 100]"
-              layout="total, sizes, prev, pager, next"
-              @size-change="handleQSizeChange"
-              @current-change="handleQPageChange"
-            />
-          </div>
-        </div>
+       
       </div>
       
       <template #footer>
@@ -2322,6 +2336,8 @@ import type { ProfileFieldsConfig } from './types';
 import { getPCAData } from '../../../utils/pcaData';
 import QuestionBankForm from '../../questionBank/list/components/QuestionBankForm.vue';
 import * as questionBankApi from '../../questionBank/list/api';
+import TreeList from './treeList.vue';
+import { GetDocumentTree, GetCategoryList, GetTagList,DeleteDocumentCategory } from '../../questionBank/positionList/api';
 
 // 添加 CompetencyTag 接口定义
 interface CompetencyTag {
@@ -4729,7 +4745,9 @@ const editAIVideo = async (step: AIVideoStep) => {
         questionListpage.page=res.data.page;
         questionListpage.pageSize=res.data.limit;
         totalQuestions2.value=res.data.total;
+        getTreeData();
         QuestionSelectDialog.value = true;
+        
       }
     })
     
@@ -4742,7 +4760,7 @@ const editAIVideo = async (step: AIVideoStep) => {
         questionListpage.page=res.data.page;
         questionListpage.pageSize=res.data.limit;
         totalQuestions2.value=res.data.total;
-        QuestionSelectDialog.value = true;
+        showQuestionSelectDialog.value = true;
       }
     })
     
@@ -6402,7 +6420,112 @@ const handleProcessConfig = (type: string) => {
     // ... existing code ...
   }
 }
-// ... existing code ...
+/* 树状 */
+const documentTreeData = ref([]);
+const treeListRef = ref();
+
+const handleTreeClick = (data: any) => {
+  console.log(data)
+  // 获取点击的节点信息
+  const { firstLevel, secondLevel, currentNode } = data;
+  
+  // 如果点击的是二级节点(标签)
+  if (secondLevel) {
+    // 根据标签ID搜索题目
+    GetQuestionList({
+      page: 1,
+      limit: 20,
+      question_tags: secondLevel.id.replace('tag_', ''), // 移除前缀获取真实ID
+      question_form: questionListQuery.question_form
+    }).then((res: any) => {
+      if (res.data) {
+        questionList.value = res.data.items;
+        questionListpage.page = res.data.page;
+        questionListpage.pageSize = res.data.limit;
+        totalQuestions2.value = res.data.total;
+      }
+    });
+  }
+  // 如果点击的是一级节点(分类)
+  else if (firstLevel) {
+    // 根据分类ID搜索题目
+    GetQuestionList({
+      page: 1,
+      limit: 20,
+      question_category: firstLevel.id.replace('category_', ''), // 移除前缀获取真实ID
+      question_form: questionListQuery.question_form
+    }).then((res: any) => {
+      if (res.data) {
+        questionList.value = res.data.items;
+        questionListpage.page = res.data.page;
+        questionListpage.pageSize = res.data.limit;
+        totalQuestions2.value = res.data.total;
+      }
+    });
+  }
+}
+
+const handleUpdateDocument = (data: any) => {
+  console.log(data)
+}
+const handleDeleteDocument = (data: any) => {
+  console.log(data)
+}
+
+// 获取文档树数据
+const getTreeData = () => {
+	GetDocumentTree({}).then((ret: any) => {
+		console.log('ret', ret);
+		const responseData = ret.data;
+		GetCategoryList({}).then((res: any) => {
+			console.log('res', res);
+			const categoryList = res.data.items.filter((item: any) => 
+				!['技术能力', '服务意识', '职业素质','基本常识','色盲检测','内容铺垫'].includes(item.name)
+			);
+			GetTagList({}).then((res: any) => {
+				console.log('res', res);
+				const tagList = res.data.items;
+			
+				// 创建根节点
+				const rootNode = [ 
+					/* {
+						id: 'root',
+						title: '职位开放题',
+						children: responseData.map((item: any) => ({
+							...item,
+							id: `open_${item.id}`,
+							title: item.name || item.title,
+							question_type: 'open',
+							chinese_explanation: item.chinese_explanation || ''
+						}))
+					},
+					{
+						id: 'professional_questions',
+						title: '专业考察题库',
+						children: responseData.map((item: any) => ({
+							...item,
+							id: `prof_${item.id}`,
+							title: item.name || item.title,
+							question_type: 'professional',
+							chinese_explanation: item.chinese_explanation || ''
+						}))
+					}, */
+					...categoryList.map((item: any) => ({
+						id: `category_${item.id}`,  
+						title: item.name,
+						children: tagList.filter((tag: any) => tag.category_id === item.id).map((tag: any) => ({
+							id: `tag_${tag.id}`,
+							title: tag.name,
+							chinese_explanation: tag.chinese_explanation || ''
+						})) 
+					}))
+				];
+				documentTreeData.value = rootNode;
+			});
+		});
+	});
+};
+
 </script>
 
 <style scoped>

+ 167 - 0
src/views/position/detail/treeList.vue

@@ -0,0 +1,167 @@
+<template>
+    <div class="document-tree-container">
+      <div class="document-tree-header">
+        <span class="document-tree-title">题库归属</span>
+       <!--  <el-button type="primary" size="small" @click="handleAddDocument">
+          <el-icon><Plus /></el-icon>添加分类
+        </el-button> -->
+      </div>
+      <el-tree
+        ref="treeRef"
+        :data="treeData"
+        node-key="id"
+        :props="defaultProps"
+        default-expand-all
+        highlight-current
+        @node-click="handleNodeClick"
+      >
+        <template #default="{ node, data }">
+          <div class="custom-tree-node">
+            <div class="node-label">
+              <el-icon><Folder /></el-icon>
+              <span class="ml-2">{{ data.title }}</span>
+            </div>
+          <!--   <div class="node-actions" v-if="data.id">
+              <el-button type="primary" link size="small" @click.stop="handleEdit(data)">
+                <el-icon><Edit /></el-icon>
+              </el-button>
+              <el-button type="danger" link size="small" @click.stop="handleDelete(node, data)">
+                <el-icon><Delete /></el-icon>
+              </el-button>
+            </div> -->
+          </div>
+        </template>
+      </el-tree>
+    </div>
+  </template>
+  
+  <script lang="ts" setup>
+  import { ref, defineProps, defineEmits } from 'vue';
+  import { Plus, Folder, Edit, Delete } from '@element-plus/icons-vue';
+  
+  const props = defineProps({
+    treeData: {
+      type: Array,
+      default: () => []
+    }
+  });
+  
+  const emit = defineEmits(['treeClick', 'updateDocument', 'deleteDocument']);
+  
+  const treeRef = ref(null);
+  
+  const defaultProps = {
+    children: 'children',
+    label: 'title'
+  };
+  
+  // 处理节点点击
+  const handleNodeClick = (data: any, node: any) => {
+    // 获取当前节点的层级路径
+    let currentNode = node;
+    let firstLevelNode = null;
+    let secondLevelNode = null;
+  
+    // 遍历父节点找到一级和二级节点
+    while (currentNode) {
+      if (currentNode.level === 1) {
+        firstLevelNode = currentNode.data;
+      } else if (currentNode.level === 2) {
+        secondLevelNode = currentNode.data;
+      }
+      currentNode = currentNode.parent;
+    }
+  
+    // 如果当前点击的是一级节点
+    if (node.level === 1) {
+      firstLevelNode = data;
+      secondLevelNode = null;
+    }
+    // 如果当前点击的是二级节点
+    else if (node.level === 2) {
+      secondLevelNode = data;
+    }
+  
+    emit('treeClick', {
+      firstLevel: firstLevelNode,
+      secondLevel: secondLevelNode,
+      currentNode: data
+    });
+  };
+  
+  // 添加文档分类
+  const handleAddDocument = () => {
+    emit('updateDocument', 'add');
+  };
+  
+  // 编辑文档分类
+  const handleEdit = (data: any) => {
+    emit('updateDocument', 'update', data);
+  };
+  
+  // 删除文档分类
+  const handleDelete = (node: any, data: any) => {
+    emit('deleteDocument', data.id, () => {
+      // 回调函数,删除成功后可以执行
+    });
+  };
+  
+  defineExpose({
+    treeRef
+  });
+  </script>
+  
+  <style lang="scss" scoped>
+  .document-tree-container {
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+  }
+  
+  .document-tree-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16px;
+  }
+  
+  .document-tree-title {
+    font-size: 16px;
+    font-weight: bold;
+  }
+  
+  .custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding-right: 8px;
+  }
+  
+  .node-label {
+    display: flex;
+    align-items: center;
+    flex: 1;
+    min-width: 0;
+    position: relative;
+    
+    .ml-2 {
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      flex: 1;
+    }
+  }
+  
+  
+  .node-actions {
+    display: none;
+  }
+  
+  .custom-tree-node:hover .node-actions {
+    display: flex;
+    overflow: hidden;
+       white-space: nowrap;
+       text-overflow: ellipsis;
+  }
+  </style>