index.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <fs-page>
  3. <el-row class="document-el-row">
  4. <el-col :span="3">
  5. <div class="document-box document-left-box">
  6. <TreeList ref="treeListRef" :treeData="documentTreeData"
  7. @treeClick="handleTreeClick"
  8. @updateDocument="handleUpdateDocument"
  9. @deleteDocument="handleDeleteDocument" />
  10. </div>
  11. </el-col>
  12. <el-col :span="21">
  13. <div class="document-box document-right-box">
  14. <fs-crud ref="crudRef" :dialog-width="800" v-bind="crudBinding">
  15. <template #cell-chinese_explanation="scope">
  16. <el-tooltip
  17. v-if="scope.row.chinese_explanation"
  18. :content="scope.row.chinese_explanation"
  19. placement="top"
  20. :hide-after="2000"
  21. >
  22. <span>{{ scope.row.chinese_explanation }}</span>
  23. </el-tooltip>
  24. <span v-else>-</span>
  25. </template>
  26. </fs-crud>
  27. </div>
  28. </el-col>
  29. </el-row>
  30. <!-- <TreeList ref="treeListRef" :treeData="treeData" /> -->
  31. <PermissionDrawerCom />
  32. <BatchTagsDialog ref="batchTagsDialogRef" :crudExpose="crudExpose" />
  33. <BatchCategoryDialog ref="batchCategoryDialogRef" :crudExpose="crudExpose" />
  34. <BatchCompetencyTagsDialog ref="batchCompetencyTagsDialogRef" :crudExpose="crudExpose" />
  35. </fs-page>
  36. </template>
  37. <script lang="ts" setup name="role">
  38. import { defineAsyncComponent, onMounted, ref } from 'vue';
  39. import { useFs } from '@fast-crud/fast-crud';
  40. import { createCrudOptions } from './crud';
  41. import { RoleDrawerStores } from './stores/RoleDrawerStores';
  42. import { RoleMenuBtnStores } from './stores/RoleMenuBtnStores';
  43. import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
  44. import { RoleUsersStores } from './stores/RoleUsersStores';
  45. import { successMessage } from '../../../utils/message';
  46. import TreeList from './components/treeList.vue';
  47. import { GetDocumentTree, GetCategoryList, GetTagList } from '../positionList/api';
  48. const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
  49. const BatchTagsDialog = defineAsyncComponent(() => import('./components/BatchTagsDialog.vue'));
  50. const BatchCategoryDialog = defineAsyncComponent(() => import('./components/BatchCategoryDialog.vue'));
  51. const BatchCompetencyTagsDialog = defineAsyncComponent(() => import('./components/BatchCompetencyTagsDialog.vue'));
  52. const batchTagsDialogRef = ref();
  53. const batchCategoryDialogRef = ref();
  54. const batchCompetencyTagsDialogRef = ref();
  55. const RoleDrawer = RoleDrawerStores(); // 角色-抽屉
  56. const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
  57. const RoleMenuField = RoleMenuFieldStores();// 角色-菜单-字段
  58. const RoleUsers = RoleUsersStores();// 角色-用户
  59. const treeListRef = ref();
  60. const treeData = ref([]);
  61. // 定义树节点的类型
  62. interface TreeNode {
  63. id: string;
  64. title: string;
  65. children?: TreeNode[];
  66. question_type?: string;
  67. chinese_explanation?: string;
  68. name?: string;
  69. category_id?: string | number;
  70. }
  71. const documentTreeData = ref<TreeNode[]>([]); // 使用定义的类型
  72. const { crudBinding, crudRef, crudExpose } = useFs({
  73. createCrudOptions,
  74. context: {
  75. RoleDrawer,
  76. RoleMenuBtn,
  77. RoleMenuField,
  78. $message: {
  79. warning: (msg: string) => successMessage(msg)
  80. },
  81. openBatchTagsDialog: (selection: any) => {
  82. batchTagsDialogRef.value.open(selection);
  83. },
  84. openBatchCategoryDialog: (selection: any) => {
  85. batchCategoryDialogRef.value.open(selection);
  86. },
  87. openBatchCompetencyTagsDialog: (selection: any) => {
  88. batchCompetencyTagsDialogRef.value.open(selection);
  89. },
  90. selectedRows: [] // 存储选中的行
  91. },
  92. });
  93. const selectedCategoryId = ref(1);
  94. const handleTreeClick = (node: any) => {
  95. console.log('record', node);
  96. // 获取当前节点ID并处理前缀
  97. const currentNodeId = node?.currentNode?.id || '';
  98. const originalId = currentNodeId.replace(/^(open_|prof_|category_|tag_)/, '');
  99. // 保存当前选中的分类ID,如果ID不是数字则使用默认值1
  100. selectedCategoryId.value = (!isNaN(Number(originalId)) && originalId !== null) ? originalId : 1;
  101. // 根据不同的问题类型设置question_form
  102. let question_form;
  103. const firstLevelId = node?.firstLevel?.id;
  104. const nodeType = currentNodeId.startsWith('open_') ? 'open' :
  105. currentNodeId.startsWith('prof_') ? 'professional' :
  106. currentNodeId.startsWith('category_') ? 'category' :
  107. currentNodeId.startsWith('tag_') ? 'tag' :
  108. firstLevelId;
  109. if (nodeType === 'open' || firstLevelId === 'root') {
  110. question_form = '0'; // 职位开放题
  111. } else if (firstLevelId === 'psychology_questions') {
  112. question_form = '4'; // 心理题库
  113. } else if (firstLevelId === 'common_questions') {
  114. question_form = '1'; // 常识题库
  115. } else if (nodeType === 'professional' || firstLevelId === 'professional_questions') {
  116. question_form = '1,2,3,4,6'; // 专业考察题库
  117. } /* else {
  118. question_form = '0'; // 默认为职位开放题
  119. } */
  120. /* // 重置上传文件状态
  121. uploadedFile.value = null; */
  122. // 构建搜索参数
  123. const searchParams = {
  124. form: {
  125. limit: 20,
  126. position_types: selectedCategoryId.value,
  127. question_form: question_form,
  128. ...(nodeType === 'category' ? { question_category: originalId } : {}),
  129. ...(nodeType === 'tag' ? { question_tags: originalId } : {})
  130. }
  131. };
  132. // 执行搜索
  133. crudExpose.doSearch(searchParams);
  134. };
  135. const handleUpdateDocument = (node: any) => {
  136. console.log('node', node);
  137. };
  138. const handleDeleteDocument = (node: any) => {
  139. console.log('node', node);
  140. };
  141. // 获取文档树数据
  142. const getTreeData = () => {
  143. GetDocumentTree({}).then((ret: any) => {
  144. console.log('ret', ret);
  145. const responseData = ret.data;
  146. GetCategoryList({}).then((res: any) => {
  147. console.log('res', res);
  148. const categoryList = res.data.items;
  149. GetTagList({}).then((res: any) => {
  150. console.log('res', res);
  151. const tagList = res.data.items;
  152. // 创建根节点
  153. const rootNode = [
  154. {
  155. id: 'root',
  156. title: '职位开放题',
  157. children: responseData.map((item: any) => ({
  158. ...item,
  159. id: `open_${item.id}`,
  160. title: item.name || item.title,
  161. question_type: 'open',
  162. chinese_explanation: item.chinese_explanation || ''
  163. }))
  164. },
  165. {
  166. id: 'professional_questions',
  167. title: '专业考察题库',
  168. children: responseData.map((item: any) => ({
  169. ...item,
  170. id: `prof_${item.id}`,
  171. title: item.name || item.title,
  172. question_type: 'professional',
  173. chinese_explanation: item.chinese_explanation || ''
  174. }))
  175. },
  176. ...categoryList.map((item: any) => ({
  177. id: `category_${item.id}`,
  178. title: item.name,
  179. children: tagList.filter((tag: any) => tag.category_id === item.id).map((tag: any) => ({
  180. id: `tag_${tag.id}`,
  181. title: tag.name,
  182. chinese_explanation: tag.chinese_explanation || ''
  183. }))
  184. }))
  185. ];
  186. documentTreeData.value = rootNode;
  187. });
  188. });
  189. });
  190. };
  191. // 页面打开后获取列表数据
  192. onMounted(async () => {
  193. getTreeData()
  194. // 刷新
  195. crudExpose.doRefresh();
  196. // 获取全部用户
  197. RoleUsers.get_all_users();
  198. });
  199. </script>
  200. <style lang="scss" scoped>
  201. .document-el-row {
  202. height: 100%;
  203. overflow: hidden;
  204. .el-col {
  205. height: 100%;
  206. padding: 10px 0;
  207. box-sizing: border-box;
  208. }
  209. }
  210. .document-box {
  211. height: 100%;
  212. padding: 10px;
  213. background-color: var(--el-fill-color-blank);
  214. box-sizing: border-box;
  215. }
  216. .document-left-box {
  217. position: relative;
  218. border-radius: 0 8px 8px 0;
  219. margin-right: 10px;
  220. overflow-y: auto;
  221. }
  222. .document-right-box {
  223. border-radius: 8px 0 0 8px;
  224. }
  225. /* 添加中文释义相关样式 */
  226. .chinese-explanation {
  227. color: #666;
  228. font-size: 14px;
  229. margin-top: 4px;
  230. &:hover {
  231. color: #409EFF;
  232. }
  233. }
  234. .tooltip-content {
  235. max-width: 300px;
  236. word-break: break-all;
  237. white-space: pre-wrap;
  238. }
  239. </style>