yangg 2 сар өмнө
parent
commit
65f75a049f

+ 68 - 25
package-lock.json

@@ -46,6 +46,7 @@
 				"print-js": "^1.6.0",
 				"qrcodejs2-fixes": "^0.0.2",
 				"qs": "^6.11.0",
+				"quill": "^2.0.3",
 				"screenfull": "^6.0.2",
 				"sortablejs": "^1.15.0",
 				"splitpanes": "^3.1.5",
@@ -1968,6 +1969,47 @@
 				"vue-cropperjs": "^5.0.0"
 			}
 		},
+		"node_modules/@fast-crud/fast-extends/node_modules/eventemitter3": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-2.0.3.tgz",
+			"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+		},
+		"node_modules/@fast-crud/fast-extends/node_modules/fast-diff": {
+			"version": "1.1.2",
+			"resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.1.2.tgz",
+			"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+		},
+		"node_modules/@fast-crud/fast-extends/node_modules/parchment": {
+			"version": "1.1.4",
+			"resolved": "https://registry.npmmirror.com/parchment/-/parchment-1.1.4.tgz",
+			"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+		},
+		"node_modules/@fast-crud/fast-extends/node_modules/quill": {
+			"version": "1.3.7",
+			"resolved": "https://registry.npmmirror.com/quill/-/quill-1.3.7.tgz",
+			"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+			"dependencies": {
+				"clone": "^2.1.1",
+				"deep-equal": "^1.0.1",
+				"eventemitter3": "^2.0.3",
+				"extend": "^3.0.2",
+				"parchment": "^1.1.4",
+				"quill-delta": "^3.6.2"
+			}
+		},
+		"node_modules/@fast-crud/fast-extends/node_modules/quill-delta": {
+			"version": "3.6.3",
+			"resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-3.6.3.tgz",
+			"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+			"dependencies": {
+				"deep-equal": "^1.0.1",
+				"extend": "^3.0.2",
+				"fast-diff": "1.1.2"
+			},
+			"engines": {
+				"node": ">=0.10"
+			}
+		},
 		"node_modules/@fast-crud/ui-element": {
 			"version": "1.25.0",
 			"resolved": "https://registry.npmmirror.com/@fast-crud/ui-element/-/ui-element-1.25.0.tgz",
@@ -6223,9 +6265,9 @@
 			}
 		},
 		"node_modules/eventemitter3": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-2.0.3.tgz",
-			"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="
+			"version": "5.0.1",
+			"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.1.tgz",
+			"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
 		},
 		"node_modules/ext": {
 			"version": "1.7.0",
@@ -6257,9 +6299,9 @@
 			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
 		},
 		"node_modules/fast-diff": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.1.2.tgz",
-			"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig=="
+			"version": "1.3.0",
+			"resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.3.0.tgz",
+			"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
 		},
 		"node_modules/fast-glob": {
 			"version": "3.3.3",
@@ -8074,9 +8116,9 @@
 			"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
 		},
 		"node_modules/parchment": {
-			"version": "1.1.4",
-			"resolved": "https://registry.npmmirror.com/parchment/-/parchment-1.1.4.tgz",
-			"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg=="
+			"version": "3.0.0",
+			"resolved": "https://registry.npmmirror.com/parchment/-/parchment-3.0.0.tgz",
+			"integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A=="
 		},
 		"node_modules/parent-module": {
 			"version": "1.0.1",
@@ -8570,29 +8612,30 @@
 			]
 		},
 		"node_modules/quill": {
-			"version": "1.3.7",
-			"resolved": "https://registry.npmmirror.com/quill/-/quill-1.3.7.tgz",
-			"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
+			"version": "2.0.3",
+			"resolved": "https://registry.npmmirror.com/quill/-/quill-2.0.3.tgz",
+			"integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
 			"dependencies": {
-				"clone": "^2.1.1",
-				"deep-equal": "^1.0.1",
-				"eventemitter3": "^2.0.3",
-				"extend": "^3.0.2",
-				"parchment": "^1.1.4",
-				"quill-delta": "^3.6.2"
+				"eventemitter3": "^5.0.1",
+				"lodash-es": "^4.17.21",
+				"parchment": "^3.0.0",
+				"quill-delta": "^5.1.0"
+			},
+			"engines": {
+				"npm": ">=8.2.3"
 			}
 		},
 		"node_modules/quill-delta": {
-			"version": "3.6.3",
-			"resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-3.6.3.tgz",
-			"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
+			"version": "5.1.0",
+			"resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-5.1.0.tgz",
+			"integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
 			"dependencies": {
-				"deep-equal": "^1.0.1",
-				"extend": "^3.0.2",
-				"fast-diff": "1.1.2"
+				"fast-diff": "^1.3.0",
+				"lodash.clonedeep": "^4.5.0",
+				"lodash.isequal": "^4.5.0"
 			},
 			"engines": {
-				"node": ">=0.10"
+				"node": ">= 12.0.0"
 			}
 		},
 		"node_modules/rc9": {

+ 1 - 0
package.json

@@ -47,6 +47,7 @@
 		"print-js": "^1.6.0",
 		"qrcodejs2-fixes": "^0.0.2",
 		"qs": "^6.11.0",
+		"quill": "^2.0.3",
 		"screenfull": "^6.0.2",
 		"sortablejs": "^1.15.0",
 		"splitpanes": "^3.1.5",

+ 97 - 0
src/components/RichTextEditor.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="editor-container">
+    <div ref="editorRef" class="quill-editor"></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
+import Quill from 'quill';
+import 'quill/dist/quill.snow.css';
+
+const props = defineProps({
+  modelValue: {
+    type: String,
+    default: ''
+  },
+  placeholder: {
+    type: String,
+    default: '请输入内容'
+  },
+  height: {
+    type: Number,
+    default: 300
+  }
+});
+
+const emit = defineEmits(['update:modelValue']);
+
+const editorRef = ref<HTMLElement | null>(null);
+let editor: any = null;
+
+onMounted(() => {
+  if (editorRef.value) {
+    editor = new Quill(editorRef.value, {
+      theme: 'snow',
+      modules: {
+        toolbar: [
+          ['bold', 'italic', 'underline', 'strike'],
+          ['blockquote', 'code-block'],
+          [{ 'header': 1 }, { 'header': 2 }],
+          [{ 'list': 'ordered' }, { 'list': 'bullet' }],
+          [{ 'script': 'sub' }, { 'script': 'super' }],
+          [{ 'indent': '-1' }, { 'indent': '+1' }],
+          [{ 'direction': 'rtl' }],
+          [{ 'size': ['small', false, 'large', 'huge'] }],
+          [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
+          [{ 'color': [] }, { 'background': [] }],
+          [{ 'font': [] }],
+          [{ 'align': [] }],
+          ['clean']
+        ]
+      },
+      placeholder: props.placeholder
+    });
+    
+    // 设置初始内容
+    if (props.modelValue) {
+      editor.clipboard.dangerouslyPasteHTML(props.modelValue);
+    }
+    
+    // 监听内容变化
+    editor.on('text-change', () => {
+      const html = editor.root.innerHTML;
+      emit('update:modelValue', html);
+    });
+  }
+});
+
+// 监听 modelValue 变化
+watch(() => props.modelValue, (newValue) => {
+  if (editor && newValue !== editor.root.innerHTML) {
+    editor.clipboard.dangerouslyPasteHTML(newValue);
+  }
+});
+
+onBeforeUnmount(() => {
+  editor = null;
+});
+
+// 暴露获取编辑器内容的方法
+defineExpose({
+  getContent: () => {
+    return editor ? editor.root.innerHTML : '';
+  }
+});
+</script>
+
+<style scoped>
+.editor-container {
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+}
+
+.quill-editor {
+  height: v-bind('props.height + "px"');
+}
+</style> 

+ 573 - 0
src/views/position/create/index.vue

@@ -0,0 +1,573 @@
+<template>
+  <div class="position-create-container">
+    <div class="header-container">
+      <page-header title="新增职位" @back="goBack" />
+    <!--   <div class="header-right">应用至人力资源-对外</div> -->
+    </div>
+    
+    <el-card class="form-card">
+      <div class="section-title">
+        <div class="section-line"></div>
+        <span>职位详情</span>
+      </div>
+      
+      <el-form 
+        ref="formRef" 
+        :model="formData" 
+        :rules="rules" 
+        label-width="120px"
+        label-position="right"
+      >
+        <el-form-item label="职位名称" prop="title">
+          <el-input v-model="formData.title" placeholder="请输入职位名称" maxlength="20" show-word-limit />
+        </el-form-item>
+        
+        <el-form-item label="职位类别" prop="job_category">
+          <el-select v-model="formData.job_category" placeholder="请选择职位类别">
+            <el-option label="技术" value="技术" />
+            <el-option label="产品" value="产品" />
+            <el-option label="设计" value="设计" />
+            <el-option label="运营" value="运营" />
+            <el-option label="市场" value="市场" />
+            <el-option label="销售" value="销售" />
+            <el-option label="行政" value="行政" />
+            <el-option label="财务" value="财务" />
+            <el-option label="人力资源" value="人力资源" />
+            <el-option label="法务" value="法务" />
+            <el-option label="其他" value="其他" />
+          </el-select>
+        </el-form-item>
+        
+        <el-form-item label="职位性质" prop="job_type_display">
+          <el-select v-model="formData.job_type_display" placeholder="请选择职位性质">
+            <el-option label="全职" value="全职" />
+            <el-option label="兼职" value="兼职" />
+            <el-option label="实习" value="实习" />
+            <el-option label="其他" value="其他" />
+          </el-select>
+        </el-form-item>
+        
+       <!--  <el-form-item label="工作城市" prop="city">
+          <el-select v-model="formData.city" placeholder="请选择工作城市">
+            <el-option label="北京" value="北京" />
+            <el-option label="上海" value="上海" />
+            <el-option label="广州" value="广州" />
+            <el-option label="深圳" value="深圳" />
+            <el-option label="杭州" value="杭州" />
+            <el-option label="成都" value="成都" />
+            <el-option label="武汉" value="武汉" />
+            <el-option label="西安" value="西安" />
+            <el-option label="南京" value="南京" />
+            <el-option label="其他" value="其他" />
+          </el-select>
+        </el-form-item> -->
+        
+        <el-form-item label="工作地点" prop="location">
+          <el-cascader
+            v-model="formData.location"
+            :options="locationOptions"
+            :props="{ 
+              expandTrigger: 'hover',
+              checkStrictly: false
+            }"
+            style="width: 100%"
+            placeholder="请选择工作地点"
+            clearable
+            @change="handleLocationChange"
+          />
+        </el-form-item>
+        
+        <el-form-item label="门牌号码" prop="address_detail">
+          <el-input v-model="formData.address_detail" placeholder="请输入详细地址" />
+        </el-form-item>
+        
+        <el-form-item label="福利待遇" prop="benefits">
+          <el-select v-model="formData.benefits" placeholder="请选择福利待遇" multiple>
+            <el-option label="五险一金" value="五险一金" />
+            <el-option label="年终奖" value="年终奖" />
+            <el-option label="带薪年假" value="带薪年假" />
+            <el-option label="定期体检" value="定期体检" />
+            <el-option label="节日福利" value="节日福利" />
+            <el-option label="员工旅游" value="员工旅游" />
+            <el-option label="弹性工作" value="弹性工作" />
+            <el-option label="免费班车" value="免费班车" />
+            <el-option label="餐补" value="餐补" />
+            <el-option label="交通补贴" value="交通补贴" />
+          </el-select>
+        </el-form-item>
+        
+        <el-form-item label="职位要求" prop="requirements">
+          <div class="editor-container">
+            <div ref="quillEditor" class="quill-editor"></div>
+          </div>
+        </el-form-item>
+        
+        <!-- 添加职位描述字段 -->
+        <el-form-item label="职位描述" prop="description">
+          <div class="editor-container">
+            <div ref="descriptionEditor" class="quill-editor"></div>
+          </div>
+        </el-form-item>
+        
+        <!-- 添加职位薪资字段 -->
+        <el-form-item label="职位薪资" prop="salary_range">
+          <div class="salary-range-container">
+            <el-select v-model="formData.salary_type" placeholder="薪资类型" class="salary-type-select">
+              <el-option label="月薪" value="月薪" />
+              <el-option label="年薪" value="年薪" />
+              <el-option label="日薪" value="日薪" />
+              <el-option label="时薪" value="时薪" />
+            </el-select>
+            <el-input v-model="formData.start_salary" placeholder="起始薪资" class="salary-input" />
+            <span class="salary-separator">-</span>
+            <el-input v-model="formData.end_salary" placeholder="最高薪资" class="salary-input" />
+          </div>
+        </el-form-item>
+        
+        <!-- 添加职位条件字段 -->
+        <el-form-item label="职位条件">
+          <div class="job-conditions-container">
+            <el-select v-model="formData.experience" placeholder="工作经验" class="condition-select">
+              <el-option label="不限" value="不限" />
+              <el-option label="应届毕业生" value="应届毕业生" />
+              <el-option label="1年以下" value="1年以下" />
+              <el-option label="1-3年" value="1-3年" />
+              <el-option label="3-5年" value="3-5年" />
+              <el-option label="5-10年" value="5-10年" />
+              <el-option label="10年以上" value="10年以上" />
+            </el-select>
+            <el-select v-model="formData.education" placeholder="学历要求" class="condition-select">
+              <el-option label="不限" value="不限" />
+              <el-option label="高中" value="高中" />
+              <el-option label="大专" value="大专" />
+              <el-option label="本科" value="本科" />
+              <el-option label="硕士" value="硕士" />
+              <el-option label="博士" value="博士" />
+            </el-select>
+          </div>
+        </el-form-item>
+        
+        <el-form-item label="所属部门" prop="department">
+          <el-input v-model="formData.department" placeholder="请输入所属部门" />
+        </el-form-item>
+        
+        <el-form-item label="职位状态" prop="job_type">
+          <el-select v-model="formData.job_type" placeholder="请选择职位状态">
+            <el-option label="未发布" :value="0" />
+            <el-option label="已发布" :value="1" />
+            <el-option label="已结束" :value="2" />
+          </el-select>
+        </el-form-item>
+        
+        <el-form-item label="截止日期" prop="end_date">
+          <el-date-picker
+            v-model="formData.end_date"
+            type="datetime"
+            placeholder="请选择截止日期"
+            value-format="YYYY-MM-DD HH:mm:ss"
+          />
+        </el-form-item>
+        
+        <el-form-item>
+          <el-button type="primary" @click="submitForm">保存</el-button>
+          <el-button @click="goBack">取消</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
+import { useRouter } from 'vue-router';
+import { ElMessage } from 'element-plus';
+import * as api from '../list/api';
+import type { FormInstance } from 'element-plus';
+import Quill from 'quill';
+import 'quill/dist/quill.snow.css'; // 引入样式
+
+const router = useRouter();
+const formRef = ref<FormInstance>();
+
+// 定义表单数据接口
+interface PositionFormData {
+  title: string;
+  job_category: string;
+  job_type_display: string;
+  city: string;
+  location: string[];
+  address_detail: string;
+  benefits: string[];
+  requirements: string;
+  job_type?: number;
+  salary_type: string;
+  start_salary: string;
+  end_salary: string;
+  experience: string;
+  education: string;
+  salary_range?: string;
+  department?: string;
+  end_date?: string;
+  description?: string;
+  province: string;
+  district: string;
+  location_str?: string;
+  status: number;
+}
+
+// 表单数据
+const formData = reactive<PositionFormData>({
+  title: '',
+  job_category: '',
+  job_type_display: '',
+  city: '',
+  location: [],
+  address_detail: '',
+  benefits: [],
+  requirements: '',
+  job_type: 0,
+  salary_type: '月薪',
+  start_salary: '',
+  end_salary: '',
+  experience: '',
+  education: '',
+  salary_range: '',
+  department: '',
+  end_date: '',
+  description: '',
+  province: '',
+  district: '',
+  location_str: '',
+  status: 0
+});
+
+// 表单验证规则
+const rules = {
+  title: [{ required: true, message: '职位名称必填', trigger: 'blur' }],
+  job_category: [{ required: true, message: '职位类别必填', trigger: 'change' }],
+  job_type_display: [{ required: true, message: '职位性质必填', trigger: 'change' }],
+  location: [{ required: true, message: '工作地点必填', trigger: 'change' }],
+  department: [{ required: true, message: '所属部门必填', trigger: 'blur' }],
+  job_type: [{ required: true, message: '职位状态必填', trigger: 'change' }],
+  end_date: [{ required: true, message: '截止日期必填', trigger: 'change' }],
+  requirements: [{ required: true, message: '职位要求必填', trigger: 'blur' }],
+  description: [{ required: true, message: '职位描述必填', trigger: 'blur' }],
+  salary_range: [{ required: true, message: '薪资范围必填', trigger: 'blur' }],
+};
+
+// 添加对描述编辑器的引用
+const quillEditor = ref<HTMLElement | null>(null);
+const descriptionEditor = ref<HTMLElement | null>(null);
+let editor: any = null;
+let descEditor: any = null;
+
+// 工作地点选项
+const locationOptions = [
+  {
+    value: '上海市',
+    label: '上海市',
+    children: [
+      {
+        value: '浦东新区',
+        label: '浦东新区',
+        children: [
+          { value: '张江', label: '张江' },
+          { value: '金桥', label: '金桥' },
+          { value: '陆家嘴', label: '陆家嘴' }
+        ]
+      },
+      {
+        value: '徐汇区',
+        label: '徐汇区',
+        children: [
+          { value: '漕河泾', label: '漕河泾' },
+          { value: '徐家汇', label: '徐家汇' }
+        ]
+      },
+    ]
+  },
+  {
+    value: '北京市',
+    label: '北京市',
+    children: [
+      {
+        value: '海淀区',
+        label: '海淀区',
+        children: [
+          { value: '中关村', label: '中关村' },
+          { value: '上地', label: '上地' }
+        ]
+      },
+      {
+        value: '朝阳区',
+        label: '朝阳区',
+        children: [
+          { value: 'CBD', label: 'CBD' },
+          { value: '望京', label: '望京' }
+        ]
+      },
+    ]
+  },
+];
+
+// 处理地点选择变化
+const handleLocationChange = (value: any) => {
+  console.log('地址选择变化:', value);
+  if (value && Array.isArray(value) && value.length > 0) {
+    formData.province = value[0];
+    formData.city = value[1] || '';
+    formData.district = value[2] || '';
+  }
+};
+
+onMounted(() => {
+  // 初始化职位要求编辑器
+  if (quillEditor.value) {
+    editor = new Quill(quillEditor.value, {
+      theme: 'snow',
+      modules: {
+        toolbar: [
+          ['bold', 'italic', 'underline', 'strike'],
+          ['blockquote', 'code-block'],
+          [{ 'header': 1 }, { 'header': 2 }],
+          [{ 'list': 'ordered' }, { 'list': 'bullet' }],
+          [{ 'script': 'sub' }, { 'script': 'super' }],
+          [{ 'indent': '-1' }, { 'indent': '+1' }],
+          [{ 'direction': 'rtl' }],
+          [{ 'size': ['small', false, 'large', 'huge'] }],
+          [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
+          [{ 'color': [] }, { 'background': [] }],
+          [{ 'font': [] }],
+          [{ 'align': [] }],
+          ['clean']
+        ]
+      },
+      placeholder: '请输入职位要求'
+    });
+    
+    // 设置初始内容
+    if (formData.requirements) {
+      editor.clipboard.dangerouslyPasteHTML(formData.requirements);
+    }
+    
+    // 监听内容变化
+    editor.on('text-change', () => {
+      formData.requirements = editor.root.innerHTML;
+    });
+  }
+  
+  // 初始化职位描述编辑器
+  if (descriptionEditor.value) {
+    descEditor = new Quill(descriptionEditor.value, {
+      theme: 'snow',
+      modules: {
+        toolbar: [
+          ['bold', 'italic', 'underline', 'strike'],
+          ['blockquote', 'code-block'],
+          [{ 'header': 1 }, { 'header': 2 }],
+          [{ 'list': 'ordered' }, { 'list': 'bullet' }],
+          [{ 'script': 'sub' }, { 'script': 'super' }],
+          [{ 'indent': '-1' }, { 'indent': '+1' }],
+          [{ 'direction': 'rtl' }],
+          [{ 'size': ['small', false, 'large', 'huge'] }],
+          [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
+          [{ 'color': [] }, { 'background': [] }],
+          [{ 'font': [] }],
+          [{ 'align': [] }],
+          ['clean']
+        ]
+      },
+      placeholder: '请输入职位描述'
+    });
+    
+    // 设置初始内容
+    if (formData.description) {
+      descEditor.clipboard.dangerouslyPasteHTML(formData.description);
+    }
+    
+    // 监听内容变化
+    descEditor.on('text-change', () => {
+      formData.description = descEditor.root.innerHTML;
+    });
+  }
+});
+
+onBeforeUnmount(() => {
+  editor = null;
+  descEditor = null;
+});
+
+// 返回列表页
+const goBack = () => {
+  router.push('/position/list');
+};
+
+// 提交表单
+const submitForm = async () => {
+  if (!formRef.value) return;
+  
+  // 确保获取最新内容
+  if (editor) {
+    formData.requirements = editor.root.innerHTML;
+  }
+  
+  if (descEditor) {
+    formData.description = descEditor.root.innerHTML;
+  }
+  
+  // 在验证前设置薪资范围
+  if (formData.salary_type && formData.start_salary && formData.end_salary) {
+    formData.salary_range = `${formData.salary_type} ${formData.start_salary}-${formData.end_salary}`;
+  }
+  
+  await formRef.value.validate(async (valid: boolean, fields: any) => {
+    if (valid) {
+      try {
+        // 处理数据
+        const formToSubmit = { ...formData };
+        
+        // 处理地址信息
+        if (Array.isArray(formToSubmit.location) && formToSubmit.location.length > 0) {
+          formToSubmit.province = formToSubmit.location[0];
+          formToSubmit.city = formToSubmit.location[1] || '';
+          formToSubmit.district = formToSubmit.location[2] || '';
+          // 使用location_str字段存储字符串形式的位置
+          formToSubmit.location_str = formToSubmit.location.join(' ');
+        }
+        
+        // 调用API保存数据
+        const apiData = {
+          ...formToSubmit,
+          // 确保API接收到的是正确的字段
+          location: formToSubmit.location_str
+        };
+        delete apiData.location_str; // 删除临时字段
+        const response = await api.AddObj(apiData);
+        ElMessage.success('职位添加成功');
+        // 修改这里:跳转到详情页而不是列表页
+        router.push(`/position/detail?id=${response.data.id}`);
+      } catch (error) {
+        console.error('保存失败:', error);
+        ElMessage.error('保存失败,请重试');
+      }
+    } else {
+      console.log('验证失败:', fields);
+    }
+  });
+};
+</script>
+
+<style scoped>
+.position-create-container {
+  padding: 20px;
+}
+
+.form-card {
+  margin: 0 auto;
+  margin-top: 20px;
+  width: 40%;
+
+}
+
+.section-title {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+  font-weight: bold;
+  color: #333;
+}
+
+.section-line {
+  width: 4px;
+  height: 16px;
+  background-color: #67C23A;
+  margin-right: 8px;
+}
+
+.editor-container {
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+}
+
+.editor-toolbar {
+  display: flex;
+  padding: 8px;
+  border-bottom: 1px solid #dcdfe6;
+  background-color: #f5f7fa;
+}
+
+.toolbar-btn {
+  margin-right: 5px;
+  padding: 4px 8px;
+  background: none;
+  border: none;
+  cursor: pointer;
+  border-radius: 3px;
+}
+
+.toolbar-btn:hover {
+  background-color: #e6e6e6;
+}
+
+.toolbar-btn.active {
+  background-color: #ffecd1;
+}
+
+.toolbar-select {
+  margin-right: 5px;
+  padding: 4px;
+  border: 1px solid #dcdfe6;
+  border-radius: 3px;
+}
+
+.header-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.header-right {
+  color: #909399;
+  font-size: 14px;
+}
+
+.editable-content {
+  min-height: 200px;
+  padding: 10px;
+  border: 1px solid #dcdfe6;
+  border-top: none;
+  overflow-y: auto;
+  background-color: #fff;
+}
+
+.quill-editor {
+  height: 300px;
+}
+
+.salary-range-container {
+  display: flex;
+  align-items: center;
+}
+
+.salary-type-select {
+  width: 100px;
+  margin-right: 10px;
+}
+
+.salary-input {
+  width: 120px;
+}
+
+.salary-separator {
+  margin: 0 10px;
+}
+
+.job-conditions-container {
+  display: flex;
+  gap: 20px;
+}
+
+.condition-select {
+  width: 200px;
+}
+</style> 

+ 3236 - 0
src/views/position/detail/index.vue

@@ -0,0 +1,3236 @@
+<template>
+  <div class="position-detail-container">
+    <div class="header-container">
+      <page-header title="测试" @back="goBack" />
+      <div class="header-actions">
+        <el-button type="primary" @click="handleEdit">编辑</el-button>
+        <el-button @click="handleShare">分享职位</el-button>
+      </div>
+    </div>
+    
+    <div class="detail-content">
+      <!-- 左侧详情信息 -->
+      <el-card class="detail-card">
+        <div class="section-title">
+          <div class="section-line"></div>
+          <span>职位详情</span>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">职位名称</div>
+          <div class="detail-value">{{ positionData.title }}</div>
+        </div>
+        
+       <!--  <div class="detail-item">
+          <div class="detail-label">职位性质</div>
+          <div class="detail-value">{{ getJobTypeText(positionData.job_type) }}</div>
+        </div> -->
+        
+        <!-- <div class="detail-item">
+          <div class="detail-label">职位性质</div>
+          <div class="detail-value">{{ positionData.job_type_display }}</div>
+        </div> -->
+        
+        <!-- <div class="detail-item">
+          <div class="detail-label">工作城市</div>
+          <div class="detail-value">{{ positionData.city || '暂无' }}</div>
+        </div> -->
+        
+        <div class="detail-item">
+          <div class="detail-label">工作地点</div>
+          <div class="detail-value">{{ positionData.location || '暂无' }}</div>
+        </div>
+        
+       <!--  <div class="detail-item">
+          <div class="detail-label">门牌号码</div>
+          <div class="detail-value">{{ positionData.address_detail || '暂无' }}</div>
+        </div> -->
+        
+       <!--  <div class="detail-item">
+          <div class="detail-label">福利待遇</div>
+          <div class="detail-value">
+            <el-tag v-for="(benefit, index) in positionData.benefits" :key="index" class="benefit-tag">
+              {{ benefit }}
+            </el-tag>
+            <span v-if="!positionData.benefits || positionData.benefits.length === 0">暂无</span>
+          </div>
+        </div> -->
+        
+        <div class="detail-item">
+          <div class="detail-label">职位薪资</div>
+          <div class="detail-value">{{ positionData.salary_range || '暂无' }}</div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">工作经验</div>
+          <div class="detail-value">{{ positionData.experience || '暂无' }}</div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">学历要求</div>
+          <div class="detail-value">{{ positionData.education || '暂无' }}</div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">所属部门</div>
+          <div class="detail-value">{{ positionData.department || '暂无' }}</div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">职位状态</div>
+          <div class="detail-value">
+            <el-tag :type="getStatusType(positionData.job_type)">
+              {{ getStatusText(positionData.job_type) }}
+            </el-tag>
+          </div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">截止日期</div>
+          <div class="detail-value">{{ positionData.end_date || '暂无' }}</div>
+        </div>
+           
+        <div class="detail-item">
+          <div class="detail-label">职位要求</div>
+          <div class="detail-value html-content" v-html="positionData.requirements"></div>
+        </div>
+        
+        <div class="detail-item">
+          <div class="detail-label">职位描述</div>
+          <div class="detail-value html-content" v-html="positionData.description"></div>
+        </div>
+      </el-card>
+      
+      <!-- 右侧状态信息 -->
+      <div class="status-cards">
+        <el-card class="status-card">
+          <div class="section-title">
+            <div class="section-line"></div>
+            <span>职位状态</span>
+          </div>
+          <div class="status-switch">
+            <el-switch
+              v-model="positionStatus"
+              inactive-text=""
+              @change="handleStatusChange"
+            />
+            <span class="status-text">{{ positionStatus ? '开启职位' : '关闭职位' }}</span>
+          </div>
+        </el-card>
+        
+        <el-card class="status-card">
+          <div class="section-title">
+            <div class="section-line"></div>
+            <span>职位用途</span>
+            <el-button type="text" class="edit-btn" @click="handleEditUsage">编辑</el-button>
+          </div>
+          <div class="usage-content">
+            <div class="usage-label">职位用途</div>
+            <div class="usage-value">正式招聘</div>
+          </div>
+        </el-card>
+        
+        <el-card class="status-card">
+          <div class="section-title">
+            <div class="section-line"></div>
+            <span>招聘流程</span>
+            <el-button type="text" class="edit-btn" @click="handleEditProcess">设置流程</el-button>
+          </div>
+          <div class="process-steps">
+            <div 
+              v-for="(step, index) in recruitmentProcess" 
+              :key="step.id" 
+              class="process-step" 
+              :class="{ 'disabled': !step.active }"
+            >
+              <div class="step-number">{{ index + 1 }}</div>
+              <div class="step-content">
+                <div class="step-title">{{ step.name }}</div>
+                <div class="step-desc">{{ step.description }}</div>
+              </div>
+            </div>
+          </div>
+        </el-card>
+      </div>
+    </div>
+
+    <!-- 添加招聘流程编辑对话框 -->
+    <el-dialog
+      title="设置招聘流程"
+      v-model="showProcessDialog"
+      width="500px"
+      :close-on-click-modal="false"
+    >
+      <div class="process-dialog-content">
+        <div v-for="(step, index) in recruitmentProcess" :key="step.id">
+          <!-- 添加在每个步骤上方的加号按钮 -->
+          <div class="add-process-btn-top" v-if="index === 0 || true">
+            <el-button type="text" @click="showStepOptions(index, $event)">
+              <el-icon><Plus /></el-icon>
+            </el-button>
+          </div>
+          
+          <div 
+            class="process-edit-item"
+            :class="{ 'highlight': step.active }"
+          >
+            <div class="process-number">{{ index + 1 }}</div>
+            <div class="process-edit-content">
+              <div>{{ step.name }}</div>
+              <div class="process-edit-desc">{{ step.description }}</div>
+            </div>
+            <el-button 
+              type="danger" 
+              size="small" 
+              plain 
+              class="delete-btn"
+              @click="deleteProcessStep(index)"
+            >
+              删除
+            </el-button>
+          </div>
+        </div>
+        
+        <!-- 最后一个步骤下方的加号按钮 -->
+        <div class="add-process-btn">
+          <el-button type="text" @click="showStepOptions(recruitmentProcess.length, $event)">
+            <el-icon><Plus /></el-icon>
+          </el-button>
+        </div>
+      </div>
+      
+      <!-- 添加选项菜单 -->
+      <div 
+        v-if="showOptionsMenu" 
+        class="process-options-menu"
+        :style="{ top: menuPosition.top, left: menuPosition.left }"
+        @click.stop
+      >
+        <div 
+          v-for="option in processStepOptions" 
+          :key="option.value"
+          class="process-option-item"
+          @click="addSelectedStepType(option.value, option.label)"
+        >
+          {{ option.label }}
+        </div>
+      </div>
+      
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelEditProcess">取消</el-button>
+          <el-button type="primary" @click="saveProcess">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    
+    <!-- AI视频配置对话框 -->
+    <el-drawer
+      title="AI视频"
+      v-model="showAIVideoDialog"
+      direction="rtl"
+      size="60%"
+      :close-on-click-modal="false"
+      class="ai-video-drawer"
+      :destroy-on-close="false"
+    >
+      <!-- 步骤指示器 -->
+      <div class="ai-video-steps">
+        <div class="step-item" :class="{ 'active': currentStep === 1 }" @click="jumpToStep(1)">
+          <div class="step-number">1</div>
+          <div class="step-title">考察能力</div>
+        </div>
+        <div class="step-line" :class="{ 'active-line': currentStep >= 2 }"></div>
+        <div class="step-item" :class="{ 'active': currentStep === 2 }" @click="jumpToStep(2)">
+          <div class="step-number">2</div>
+          <div class="step-title">面试题目</div>
+        </div>
+        <div class="step-line" :class="{ 'active-line': currentStep >= 3 }"></div>
+        <div class="step-item" :class="{ 'active': currentStep === 3 }" @click="jumpToStep(3)">
+          <div class="step-number">3</div>
+          <div class="step-title">系统设置</div>
+        </div>
+      </div>
+
+      <!-- 步骤1:考察能力 -->
+      <div v-if="currentStep === 1" class="ai-video-content">
+        <div class="ai-video-options">
+          <p class="option-tip">请选择要优先使用的考察能力,也可以点击"下一步"直接出题</p>
+          
+          <div class="new-feature-tip">
+            <span class="new-tag">NEW</span>
+            AI根据岗位信息生成的能力,创建完步骤后,会自动将选择的新智能能力加入到该职位的考察能力列表中。
+          </div>
+          
+          <div class="ability-options">
+
+            <el-checkbox v-model="aiVideoOptions.qualityControl" label="质量控制">
+              <div class="ability-label">质量控制</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.teamwork" label="团队协作">
+              <div class="ability-label">团队协作</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.problemSolving" label="问题解决">
+              <div class="ability-label">问题解决</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.dataAnalysis" label="问题分析">
+              <div class="ability-label">问题分析</div>
+            </el-checkbox>
+            
+           <!--  <el-checkbox v-model="aiVideoOptions.taskManagement" label="分析问题">
+              <div class="ability-label">分析问题</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.productivity" label="生产效率">
+              <div class="ability-label">生产效率</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.manufacturingSkills" label="制造制作技能">
+              <div class="ability-label">制造制作技能</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.customerService" label="客户服务技能">
+              <div class="ability-label">客户服务技能</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.resistanceToPressure" label="抗压能力-客户服务">
+              <div class="ability-label">抗压能力-客户服务</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.workDefinition" label="工作稳定-宣誓">
+              <div class="ability-label">工作稳定-宣誓</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.selfIntroduction" label="自我介绍-宣誓">
+              <div class="ability-label">自我介绍-宣誓</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.detailOrientation" label="细节关注">
+              <div class="ability-label">细节关注</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.logicalThinking" label="清晰逻辑思维">
+              <div class="ability-label">清晰逻辑思维</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.safetyAwareness" label="安全意识">
+              <div class="ability-label">安全意识</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.customerServiceAwareness" label="客户服务意识">
+              <div class="ability-label">客户服务意识</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.timeManagement" label="时间管理">
+              <div class="ability-label">时间管理</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.teamCooperation" label="团队合作">
+              <div class="ability-label">团队合作</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.timeManagementSkills" label="时间管理能力">
+              <div class="ability-label">时间管理能力</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.productEvaluation" label="品鉴评估能力">
+              <div class="ability-label">品鉴评估能力</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.basicQualifications" label="基本素质">
+              <div class="ability-label">基本素质</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.networkDeployment" label="网位布署">
+              <div class="ability-label">网位布署</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.remoteCooperation" label="泡通协作">
+              <div class="ability-label">泡通协作</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.executionAbility" label="执行能力">
+              <div class="ability-label">执行能力</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.selfDiscipline" label="自驱力">
+              <div class="ability-label">自驱力</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.managementAbility" label="管理能力">
+              <div class="ability-label">管理能力</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.customerOrientation" label="客户导向">
+              <div class="ability-label">客户导向</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.stability" label="稳定性">
+              <div class="ability-label">稳定性</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.salesSkills" label="销售技巧">
+              <div class="ability-label">销售技巧</div>
+            </el-checkbox>
+            
+            <el-checkbox v-model="aiVideoOptions.responseAbility" label="应变能力">
+              <div class="ability-label">应变能力</div>
+            </el-checkbox> -->
+          </div>
+        </div>
+      </div>
+
+      <!-- 步骤2:面试题目 -->
+      <div v-if="currentStep === 2" class="ai-video-content">
+        <div class="interview-settings">
+          <div class="interview-header">
+            <div class="interview-duration">
+              <span>预计面试时长: </span>
+              <span class="duration-value">0秒</span>
+              <span class="duration-tip">拖动试题卡片可改变试题顺序</span>
+            </div>
+            
+            <div class="interview-actions">
+              <el-button type="primary" plain class="import-btn">
+                <el-icon><Document /></el-icon>
+                导入题目
+              </el-button>
+              <el-button type="success" plain class="custom-btn">
+                <el-icon><Plus /></el-icon>
+                自定义题目
+              </el-button>
+            </div>
+          </div>
+          
+          <div class="interview-mode">
+            <span>面试问答方式: </span>
+            <span class="mode-value">传统读题模式</span>
+            <el-button type="primary" plain size="small" class="customize-btn">定制面试间</el-button>
+          </div>
+          
+          <div class="interview-questions-container">
+            <div class="no-questions">
+              <p>暂无题目</p>
+              <p class="ai-tip">点击"AI自动组题"按钮</p>
+              <p class="ai-tip">可根据您选择的能力类型一键组题</p>
+              <el-button type="success" class="auto-generate-btn">AI自动组题</el-button>
+            </div>
+            
+            <div class="question-list">
+              <div v-for="(question, index) in chatQuestions" :key="index" class="question-card">
+                <div class="question-header">
+                  <div class="question-title">
+                    <span class="question-number">题目{{ index + 1 }}</span>
+                    <span>{{ question.title }}</span>
+                  </div>
+                  <div class="question-actions">
+                    <div class="weight-control">
+                      <span class="weight-label">权重占比:</span>
+                      <el-input-number 
+                        v-model="question.weight" 
+                        :min="0" 
+                        :max="100"
+                        :step="1"
+                        size="small"
+                        controls-position="right"
+                      >
+                        <template #suffix>%</template>
+                      </el-input-number>
+                    </div>
+                    <div class="answer-limit">
+                      <span class="answer-label">最多回答次数</span>
+                      <el-select v-model="question.maxAnswers" size="small" placeholder="请选择">
+                        <el-option label="1次" :value="1" />
+                        <el-option label="2次" :value="2" />
+                        <el-option label="3次" :value="3" />
+                      </el-select>
+                    </div>
+                    <el-button type="text" @click="editQuestion(index)">
+                      <el-icon><Edit /></el-icon>
+                    </el-button>
+                    <el-button type="text" @click="deleteQuestion(index)">
+                      <el-icon><Delete /></el-icon>
+                    </el-button>
+                  </div>
+                </div>
+                
+                <div class="question-info">
+                  <div class="info-item">
+                    <span class="info-label">考察能力:</span>
+                    <span>{{ question.ability }}</span>
+                  </div>
+                  <div class="info-item">
+                    <span class="info-label">面试内容:</span>
+                    <span>{{ question.content }}</span>
+                  </div>
+                  <div class="info-item">
+                    <span class="info-label">对话目标:</span>
+                    <span>{{ question.target }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          
+          <div class="multi-dimension-questions">
+            <div class="dimension-title">多维度能力测评题</div>
+            <div class="dimension-list">
+              <div v-for="ability in selectedAbilities" :key="ability.value" class="dimension-item">
+                <div class="dimension-header">
+                  <span>{{ ability.label }}</span>
+                  <span class="new-tag" v-if="ability.isNew">NEW</span>
+                  <el-icon class="expand-icon"><ArrowDown /></el-icon>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 步骤3:系统设置 -->
+      <div v-if="currentStep === 3" class="ai-video-content">
+        <div class="system-settings">
+          <!-- 排名区间设置 -->
+          <div class="setting-section">
+            <div class="section-header">排名区间设置</div>
+            <div class="rank-settings">
+              <div class="rank-range">
+                <span>排名前</span>
+                <div class="range-inputs">
+                  <el-input v-model="rankSettings.min" size="small" class="percent-input">
+                    <template #suffix>%</template>
+                  </el-input>
+                  <span>-</span>
+                  <el-input v-model="rankSettings.max" size="small" class="percent-input">
+                    <template #suffix>%</template>
+                  </el-input>
+                </div>
+              </div>
+              
+              <div class="score-display">
+                <span>分数</span>
+                <div class="score-range">{{ rankSettings.minScore }} - {{ rankSettings.maxScore }} 分</div>
+              </div>
+            </div>
+            
+            <el-button type="primary" plain class="add-rank-btn">
+              <el-icon><Plus /></el-icon>
+              添加排名区间
+            </el-button>
+          </div>
+          
+          <!-- AI视频有效期 -->
+          <div class="setting-section">
+            <div class="section-header">AI视频有效期</div>
+            <div class="validity-setting">
+              <el-switch v-model="validityEnabled" />
+              <span class="validity-label">开启AI视频有效期</span>
+            </div>
+            <div class="validity-tip">暂未设置,设置后候选人超过有效期则不可进入</div>
+          </div>
+          
+          <!-- AI模型版本 -->
+          <div class="setting-section">
+            <div class="section-header">AI模型版本</div>
+            <el-select v-model="aiModelVersion" placeholder="请选择" class="model-select">
+              <el-option label="标准版" value="standard"></el-option>
+            </el-select>
+          </div>
+          
+          <!-- 评分AI -->
+          <div class="setting-section">
+            <div class="section-header">评分AI</div>
+            <!-- 评分AI设置内容 -->
+          </div>
+        </div>
+      </div>
+      
+      <template #footer>
+        <div class="drawer-footer">
+          <el-button v-if="currentStep > 1" @click="prevStep">上一步</el-button>
+          <el-button @click="cancelAIVideoConfig">取消</el-button>
+          <el-button v-if="currentStep < 3" type="primary" @click="nextStep">下一步</el-button>
+          <el-button v-else type="success" @click="finishConfig">新增</el-button>
+        </div>
+      </template>
+    </el-drawer>
+
+    <!-- 在 template 中添加视频宣讲弹窗 -->
+    <el-dialog
+      title="新增视频宣讲"
+      v-model="showVideoLectureDialog"
+      width="35%"
+      :close-on-click-modal="false"
+      class="video-lecture-dialog"
+    >
+      <div class="video-lecture-form">
+       <!--  <div class="form-item">
+          <div class="form-label">步骤名称</div>
+          <el-input 
+            v-model="videoLectureForm.title" 
+            placeholder="请输入步骤名称"
+            maxlength="30"
+            show-word-limit
+          />
+        </div> -->
+        
+        <div class="form-item">
+          <div class="form-label">上传视频</div>
+          <el-upload
+            class="video-uploader"
+            action="#"
+            :auto-upload="false"
+            :show-file-list="false"
+            accept="video/*"
+          >
+            <div class="upload-area">
+              <el-icon><Plus /></el-icon>
+              <div class="upload-text">上传文件大小不超过500M</div>
+            </div>
+          </el-upload>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">视频简介</div>
+          <el-input
+            v-model="videoLectureForm.description"
+            type="textarea"
+            rows="4"
+            placeholder="视频简介会显示在视频下方的标题下方"
+            maxlength="200"
+            show-word-limit
+          />
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">播放设置</div>
+          <el-radio-group v-model="videoLectureForm.broadcastType">
+            <el-radio label="required">必须看完</el-radio>
+            <el-radio label="optional">看过即可</el-radio>
+          </el-radio-group>
+        </div>
+      </div>
+      
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelVideoLecture">取消</el-button>
+          <el-button type="primary" @click="confirmVideoLecture">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- AI实时对话抽屉 -->
+    <el-drawer
+      title="AI实时对话"
+      v-model="showAIChatDialog"
+      direction="rtl"
+      size="60%"
+      :close-on-click-modal="false"
+      class="ai-chat-drawer"
+      :destroy-on-close="false"
+    >
+      <div class="ai-chat-content">
+        <!-- AI实时对话的配置内容 -->
+        <div class="chat-settings">
+          <div class="section-title">
+            <div class="section-line"></div>
+            <span>对话设置</span>
+          </div>
+          
+          <!-- 添加按钮组 -->
+          <div class="chat-actions">
+            <el-button type="primary" plain @click="handleAddQuestion">
+              <el-icon><Plus /></el-icon>
+              添加问题
+            </el-button>
+            <el-button type="success" plain @click="handleImportQuestion">
+              <el-icon><Document /></el-icon>
+              导入问题
+            </el-button>
+          </div>
+
+          <!-- 添加问题列表容器 -->
+          <div class="chat-questions">
+            <div v-if="chatQuestions.length === 0" class="empty-questions">
+              <p>暂无问题</p>
+              <p class="tip-text">点击"添加问题"或"导入问题"添加面试问题</p>
+            </div>
+            <div v-else class="question-list">
+              <div v-for="(question, index) in chatQuestions" :key="index" class="question-card">
+                <div class="question-header">
+                  <div class="question-title">
+                    <span class="question-number">题目{{ index + 1 }}</span>
+                    <span>{{ question.title }}</span>
+                  </div>
+                  <div class="question-actions">
+                    <div class="weight-control">
+                      <span class="weight-label">权重占比:</span>
+                      <el-input-number 
+                        v-model="question.weight" 
+                        :min="0" 
+                        :max="100"
+                        :step="1"
+                        size="small"
+                        controls-position="right"
+                      >
+                        <template #suffix>%</template>
+                      </el-input-number>
+                    </div>
+                    <div class="answer-limit">
+                      <span class="answer-label">最多回答次数</span>
+                      <el-select v-model="question.maxAnswers" size="small" placeholder="请选择">
+                        <el-option label="1次" :value="1" />
+                        <el-option label="2次" :value="2" />
+                        <el-option label="3次" :value="3" />
+                      </el-select>
+                    </div>
+                    <el-button type="text" @click="editQuestion(index)">
+                      <el-icon><Edit /></el-icon>
+                    </el-button>
+                    <el-button type="text" @click="deleteQuestion(index)">
+                      <el-icon><Delete /></el-icon>
+                    </el-button>
+                  </div>
+                </div>
+                
+                <div class="question-info">
+                  <div class="info-item">
+                    <span class="info-label">考察能力:</span>
+                    <span>{{ question.ability }}</span>
+                  </div>
+                  <div class="info-item">
+                    <span class="info-label">面试内容:</span>
+                    <span>{{ question.content }}</span>
+                  </div>
+                  <div class="info-item">
+                    <span class="info-label">对话目标:</span>
+                    <span>{{ question.target }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      
+      <template #footer>
+        <div class="drawer-footer">
+          <el-button @click="cancelAIChatConfig">取消</el-button>
+          <el-button type="primary" @click="handleAIChatConfig">确认</el-button>
+        </div>
+      </template>
+    </el-drawer>
+
+    <!-- 在 template 中添加问题编辑弹框 -->
+    <el-dialog
+      title="添加问题"
+      v-model="showQuestionDialog"
+      width="500px"
+      :close-on-click-modal="false"
+      class="question-dialog"
+    >
+      <div class="question-form">
+        <div class="form-item">
+          <div class="form-label">
+            标题<span class="required">*</span>
+          </div>
+          <el-input 
+            v-model="questionForm.title"
+            placeholder="请输入标题"
+            maxlength="15"
+            show-word-limit
+          />
+        </div>
+
+        <div class="form-item">
+          <div class="form-label">考察能力</div>
+          <el-select
+            v-model="questionForm.ability"
+            placeholder="请选择考察能力"
+            class="full-width"
+          >
+            <el-option label="深入考察抗压能力" value="pressure" />
+            <el-option label="候选人回答中包含一个详细的案例" value="case" />
+            <el-option label="获取候选人明确的毕业院校和专业" value="education" />
+          </el-select>
+        </div>
+
+        <div class="form-item">
+          <div class="form-label">
+            面试内容<span class="required">*</span>
+          </div>
+          <el-input
+            v-model="questionForm.content"
+            type="textarea"
+            rows="4"
+            placeholder="请输入面试内容"
+            maxlength="300"
+            show-word-limit
+          />
+        </div>
+
+        <div class="form-item">
+          <div class="form-label">对话目标</div>
+          <el-input
+            v-model="questionForm.target"
+            type="textarea"
+            rows="3"
+            placeholder="输入你想在对话中达成的目标,示例:
+• 深入考察抗压能力
+• 候选人回答中包含一个详细的案例
+• 获取候选人明确的毕业院校和专业"
+            maxlength="100"
+            show-word-limit
+          />
+        </div>
+      </div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelAddQuestion">取消</el-button>
+          <el-button type="primary" @click="confirmAddQuestion">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 修改资料收集对话框模板 -->
+    <el-dialog
+      title="资料收集"
+      v-model="showDataCollectionDialog"
+      width="500px"
+      :close-on-click-modal="false"
+      class="data-collection-dialog"
+    >
+      <div class="data-collection-form">
+        <div class="question-list">
+          <div v-for="(question, index) in questionTypes" :key="index" class="question-item">
+            <!-- 问题标题栏 -->
+            <div class="question-header">
+              <div class="question-title">
+                <span>{{ question.label }}</span>
+              </div>
+              <div class="question-type">
+                <span>问答类</span>
+                <el-icon><ArrowDown /></el-icon>
+              </div>
+            </div>
+            
+            <!-- 问题内容区 -->
+            <div class="question-content">
+              <div class="user-answer">用户回答</div>
+              
+              <!-- 操作按钮区 -->
+              <div class="question-actions">
+                <div class="action-left">
+                  <el-switch v-model="question.isVisible" />
+                  <span class="action-text">{{ question.isVisible ? '显示' : '隐藏' }}</span>
+                </div>
+                <div class="action-right">
+                  <el-icon class="action-icon"><Document /></el-icon>
+                  <el-icon class="action-icon"><Delete /></el-icon>
+                </div>
+              </div>
+              
+              <!-- 设置区域 -->
+              <div class="question-settings">
+                <div class="setting-item">
+                  <span>开启评分</span>
+                  <el-switch v-model="question.enableScoring" />
+                </div>
+                <div class="setting-item">
+                  <span>必答</span>
+                  <el-switch v-model="question.isRequired" />
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 添加问题按钮 -->
+        <div class="add-question">
+          <el-button type="primary" plain @click="handleAddQuestion">
+            <el-icon><Plus /></el-icon>
+            添加问题
+          </el-button>
+        </div>
+      </div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelDataCollection">取消</el-button>
+          <el-button type="primary" @click="confirmDataCollection">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 添加简历收集对话框 -->
+    <el-dialog
+      title="简历收集"
+      v-model="showResumeCollectionDialog"
+      width="500px"
+      :close-on-click-modal="false"
+      class="resume-collection-dialog"
+    >
+      <div class="resume-collection-form">
+        <div class="form-item">
+          <div class="form-label">步骤名称</div>
+          <el-input 
+            v-model="resumeCollectionForm.title" 
+            placeholder="请输入步骤名称"
+            maxlength="30"
+            show-word-limit
+          />
+        </div>
+        
+        <!-- <div class="form-item">
+          <div class="form-label">必填项</div>
+          <el-switch v-model="resumeCollectionForm.isRequired" />
+          <span class="switch-label">{{ resumeCollectionForm.isRequired ? '开启' : '关闭' }}</span>
+        </div>
+        
+        <div class="resume-preview">
+          <div class="preview-title">简历收集预览</div>
+          <div class="preview-content">
+            <div class="preview-item">
+              <div class="item-label">姓名</div>
+              <div class="item-input"></div>
+              <div class="item-required" v-if="resumeCollectionForm.isRequired">*</div>
+            </div>
+            <div class="preview-item">
+              <div class="item-label">手机号</div>
+              <div class="item-input"></div>
+              <div class="item-required" v-if="resumeCollectionForm.isRequired">*</div>
+            </div>
+            <div class="preview-item">
+              <div class="item-label">邮箱</div>
+              <div class="item-input"></div>
+              <div class="item-required" v-if="resumeCollectionForm.isRequired">*</div>
+            </div>
+            <div class="preview-item">
+              <div class="item-label">上传简历</div>
+              <div class="item-upload">
+                <el-icon><Plus /></el-icon>
+              </div>
+              <div class="item-required" v-if="resumeCollectionForm.isRequired">*</div>
+            </div>
+          </div>
+        </div> -->
+      </div>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelResumeCollection">取消</el-button>
+          <el-button type="primary" @click="confirmResumeCollection">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 添加代码测试对话框 -->
+    <el-dialog
+      title="添加代码笔试步骤"
+      v-model="showCodeTestDialog"
+      width="500px"
+      :close-on-click-modal="false"
+      class="code-test-dialog"
+    >
+      <div class="code-test-form">
+        <div class="form-item">
+          <div class="form-label">步骤名称</div>
+          <el-input 
+            v-model="codeTestForm.title" 
+            placeholder="请输入步骤名称"
+            maxlength="30"
+            show-word-limit
+          />
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">自动评判试卷</div>
+          <el-switch v-model="codeTestForm.autoJudge" />
+          <span class="switch-label">{{ codeTestForm.autoJudge ? '开启' : '关闭' }}</span>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">添加考试试卷</div>
+          <div class="test-paper-selector">
+            <div class="empty-paper" v-if="!codeTestForm.selectedPaper">
+              <el-button type="primary" plain @click="handleSelectPaper">
+                <el-icon><Plus /></el-icon>
+                添加考卷
+              </el-button>
+              <p class="tip-text">多选时,考生会随机分配到一套试卷</p>
+            </div>
+            <div class="selected-paper" v-else>
+              <div class="paper-info">
+                <div class="paper-title">{{ codeTestForm.selectedPaper.title }}</div>
+                <div class="paper-meta">
+                  <span>{{ codeTestForm.selectedPaper.questionCount }}道题</span>
+                  <span>{{ codeTestForm.selectedPaper.duration }}分钟</span>
+                  <span>{{ codeTestForm.selectedPaper.difficulty }}</span>
+                </div>
+              </div>
+              <div class="paper-actions">
+                <el-button type="text" @click="handleViewPaper">查看</el-button>
+                <el-button type="text" @click="handleChangePaper">更换</el-button>
+                <el-button type="text" @click="handleRemovePaper">删除</el-button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelCodeTest">取消</el-button>
+          <el-button type="primary" @click="confirmCodeTest">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+
+    <!-- 添加打字测试对话框 -->
+    <el-drawer
+      title="添加打字测试步骤"
+      v-model="showTypingTestDialog"
+      size="60%"
+      :close-on-click-modal="false"
+      class="typing-test-dialog"
+      :destroy-on-close="false"
+    >
+      <div class="typing-test-form">
+        <div class="form-item">
+          <div class="form-label">选择文章</div>
+          <div class="article-selection">
+            <el-button type="primary" size="small" class="add-article-btn">
+              <el-icon><Plus /></el-icon>
+              添加文章
+            </el-button>
+          </div>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">候选人选择文章方式</div>
+          <el-radio-group v-model="typingTestForm.selectionMode">
+            <el-radio label="random">随机抽取</el-radio>
+            <el-radio label="self">候选人自主选择</el-radio>
+          </el-radio-group>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">测试时间</div>
+          <div class="time-input-container">
+            <el-input v-model="typingTestForm.duration" class="time-input" />
+            <span class="time-unit">分钟</span>
+          </div>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">登录界面预览图(建议尺寸1024*768像素,最大不要超过5M)</div>
+          <el-upload
+            class="preview-uploader"
+            action="#"
+            :auto-upload="false"
+            :show-file-list="false"
+            accept="image/*"
+          >
+            <div class="upload-area">
+              <el-icon><Plus /></el-icon>
+              <div class="upload-text">添加图片</div>
+            </div>
+          </el-upload>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">注意事项内容(在登录界面显示)</div>
+          <el-input
+            v-model="typingTestForm.notes"
+            type="textarea"
+            rows="4"
+            placeholder="请输入注意事项内容"
+            maxlength="300"
+            show-word-limit
+          />
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">测试页面标题</div>
+          <el-input 
+            v-model="typingTestForm.pageTitle" 
+            placeholder="测试页面标题"
+          />
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">视频监控</div>
+          <el-checkbox v-model="typingTestForm.videoMonitoring">视频监控</el-checkbox>
+        </div>
+        
+        <div class="form-item">
+          <div class="form-label">通过标准</div>
+          <div class="criteria-options">
+            <el-checkbox v-model="typingTestForm.passCriteria.speed">速度</el-checkbox>
+            <el-checkbox v-model="typingTestForm.passCriteria.accuracy">正确率</el-checkbox>
+          </div>
+        </div>
+      </div>
+      
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelTypingTest">取消</el-button>
+          <el-button type="primary" @click="confirmTypingTest">保存</el-button>
+        </span>
+      </template>
+    </el-drawer>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted, computed } from 'vue';
+import { useRouter, useRoute } from 'vue-router';
+import { ElMessage, ElMessageBox, ElDrawer } from 'element-plus';
+import * as api from '../list/api';
+import { Plus, Document, ArrowDown, Edit, Delete } from '@element-plus/icons-vue';
+
+// 添加 ChatQuestion 接口定义
+interface ChatQuestion {
+  title: string;
+  ability: string;
+  content: string;
+  target: string;
+  weight: number;
+  maxAnswers: number;
+}
+
+// 添加 Paper 接口定义
+interface Paper {
+  id: number;
+  title: string;
+  questionCount: number;
+  duration: number;
+  difficulty: string;
+}
+
+const router = useRouter();
+const route = useRoute();
+const positionId = ref(route.params.id as string);
+const positionStatus = ref(false);
+
+// 职位数据
+const positionData = reactive({
+  title: '',
+  job_category: '',
+  job_type_display: '',
+  city: '',
+  location: [],
+  location_str: '',
+  address_detail: '',
+  benefits: [],
+  requirements: '',
+  job_type: 0,
+  salary_range: '',
+  department: '',
+  end_date: '',
+  description: '',
+  experience: '',
+  education: '',
+});
+
+// 招聘流程数据 - 修改为普通数组而非 ref 对象
+const recruitmentProcess = reactive([
+  { id: 1, name: '待核验', description: '待核验', active: true },
+  { id: 2, name: 'AI视频', description: 'AI视频', active: true },
+  { id: 3, name: '已通过', description: '已通过', active: true },
+  { id: 4, name: '已淘汰', description: '已淘汰', active: false }
+]);
+
+// 是否显示流程编辑对话框
+const showProcessDialog = ref(false);
+
+// 定义可选的流程步骤类型
+const processStepOptions = [
+  { label: 'AI视频', value: 'ai_video' },
+  { label: '视频宣讲', value: 'video_presentation' },
+  { label: 'AI实时对话', value: 'ai_chat' },
+  { label: '资料收集', value: 'data_collection' },
+  { label: '简历收集', value: 'resume_collection' },
+  { label: '代码测试', value: 'code_test' },
+  { label: '打字测试', value: 'typing_test' }
+];
+
+// 当前选择的添加位置
+const currentAddIndex = ref(-1);
+// 是否显示选项菜单
+const showOptionsMenu = ref(false);
+// 选项菜单的位置
+const menuPosition = reactive({ top: '0px', left: '0px' });
+
+// AI视频对话框显示状态
+const showAIVideoDialog = ref(false);
+
+// AI视频配置选项
+const aiVideoOptions = reactive({
+  qualityControl: true,
+  teamwork: false,
+  problemSolving: false,
+  dataAnalysis: false,
+  taskManagement: false,
+  productivity: false,
+  manufacturingSkills: false,
+  customerService: false,
+  resistanceToPressure: false,
+  workDefinition: false,
+  selfIntroduction: false,
+  detailOrientation: false,
+  logicalThinking: false,
+  safetyAwareness: false,
+  customerServiceAwareness: false,
+  timeManagement: false,
+  teamCooperation: false,
+  timeManagementSkills: false,
+  productEvaluation: false,
+  basicQualifications: false,
+  networkDeployment: false,
+  remoteCooperation: false,
+  executionAbility: false,
+  selfDiscipline: false,
+  managementAbility: false,
+  customerOrientation: false,
+  stability: false,
+  salesSkills: false,
+  responseAbility: false
+});
+
+// 当前步骤
+const currentStep = ref(1);
+
+// 选中的能力列表
+const selectedAbilities = computed(() => {
+  return Object.entries(aiVideoOptions)
+    .filter(([_, value]) => value)
+    .map(([key, _]) => {
+      const label = getAbilityLabel(key);
+      return {
+        value: key,
+        label,
+        isNew: ['teamwork', 'problemSolving', 'qualityControl'].includes(key)
+      };
+    });
+});
+
+// 获取能力标签
+const getAbilityLabel = (key: string) => {
+  const abilityMap: Record<string, string> = {
+    qualityControl: '质量控制',
+    teamwork: '团队协作',
+    problemSolving: '问题解决',
+    dataAnalysis: '问题分析',
+    taskManagement: '分析问题',
+    productivity: '生产效率',
+    manufacturingSkills: '制造制作技能',
+    customerService: '客户服务技能',
+    resistanceToPressure: '抗压能力-客户服务',
+    workDefinition: '工作稳定-宣誓',
+    selfIntroduction: '自我介绍-宣誓',
+    detailOrientation: '细节关注',
+    logicalThinking: '清晰逻辑思维',
+    safetyAwareness: '安全意识',
+    customerServiceAwareness: '客户服务意识',
+    timeManagement: '时间管理',
+    teamCooperation: '团队合作',
+    timeManagementSkills: '时间管理能力',
+    productEvaluation: '品鉴评估能力',
+    basicQualifications: '基本素质',
+    networkDeployment: '网位布署',
+    remoteCooperation: '泡通协作',
+    executionAbility: '执行能力',
+    selfDiscipline: '自驱力',
+    managementAbility: '管理能力',
+    customerOrientation: '客户导向',
+    stability: '稳定性',
+    salesSkills: '销售技巧',
+    responseAbility: '应变能力'
+  };
+  return abilityMap[key] || key;
+};
+
+// 排名设置
+const rankSettings = reactive({
+  min: 0,
+  max: 100,
+  minScore: 0.00,
+  maxScore: 0.00
+});
+
+// AI模型版本
+const aiModelVersion = ref('standard');
+
+// 是否启用有效期
+const validityEnabled = ref(false);
+
+// 在 script setup 部分添加以下响应式变量
+const showVideoLectureDialog = ref(false); // 控制视频宣讲弹窗显示
+const videoLectureForm = reactive({
+  title: '', // 步骤名称
+  videoFile: null, // 视频文件
+  description: '', // 视频简介
+  broadcastType: 'required', // 播放设置:必须看完/看过即可
+});
+
+// 在 script setup 部分添加新的响应式变量
+const showAIChatDialog = ref(false); // 控制AI实时对话抽屉显示
+
+// 添加 AI 实时对话配置相关的响应式变量
+const chatDuration = ref(15); // 默认15分钟
+const maxQuestions = ref(5); // 默认5个问题
+
+// 在 script setup 部分添加以下响应式变量
+const showQuestionDialog = ref(false); // 控制添加问题弹框显示
+const questionForm = reactive({
+  title: '', // 标题
+  ability: '', // 考察能力
+  content: '', // 面试内容
+  target: '', // 对话目标
+  weight: 100, // 权重占比,默认100%
+  maxAnswers: 1 // 最多回答次数,默认1次
+});
+
+// 在 script setup 中添加以下响应式变量
+const showDataCollectionDialog = ref(false); // 控制资料收集对话框显示
+const dataCollectionForm = reactive({
+  isRequired: false, // 开启评分开关
+  questions: [] // 问题列表
+});
+
+// 修改问题类型定义
+interface QuestionType {
+  label: string;
+  value: string;
+  isVisible?: boolean;
+  enableScoring?: boolean;
+  isRequired?: boolean;
+}
+
+// 定义问题列表
+const questionTypes = ref<QuestionType[]>([
+  { 
+    label: 'Q1', 
+    value: 'q1',
+    isVisible: true,
+    enableScoring: false,
+    isRequired: false
+  },
+  { 
+    label: '请问你的毕业院校是哪里?', 
+    value: 'school',
+    isVisible: true,
+    enableScoring: false,
+    isRequired: true
+  }
+]);
+
+// 添加简历收集相关的状态和方法
+const showResumeCollectionDialog = ref(false);
+const resumeCollectionForm = reactive({
+  title: '简历收集',
+  isRequired: true,
+  steps: 4, // 默认步骤数
+});
+
+// 显示简历收集弹窗
+const showResumeCollectionConfig = () => {
+  showResumeCollectionDialog.value = true;
+};
+
+// 取消简历收集配置
+const cancelResumeCollection = () => {
+  showResumeCollectionDialog.value = false;
+  // 重置表单
+  Object.assign(resumeCollectionForm, {
+    title: '简历收集',
+    isRequired: true,
+    steps: 4
+  });
+};
+
+// 确认添加简历收集
+const confirmResumeCollection = () => {
+  // 创建新的简历收集步骤
+  const newStep = {
+    id: Date.now(),
+    name: resumeCollectionForm.title,
+    description: '简历收集',
+    active: true,
+    type: 'resume_collection',
+    config: {
+      ...resumeCollectionForm
+    }
+  };
+  
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  
+  // 关闭弹窗
+  showResumeCollectionDialog.value = false;
+  
+  // 提示成功
+  ElMessage.success('简历收集步骤已添加');
+  
+  // 重置表单
+  cancelResumeCollection();
+};
+
+// 获取职位详情
+const getPositionDetail = async () => {
+  try {
+    const id = route.query.id;
+    if (!id) {
+      ElMessage.error('职位ID不存在');
+      return;
+    }
+    
+    // 修复类型错误,创建符合InfoReq类型的对象
+    const idValue = Array.isArray(id) ? id[0] : id;
+    // 创建一个符合API要求的请求对象
+    const infoReq = { id: idValue };
+    const response = await api.GetObj(id);
+    if (response && response.data) {
+      Object.assign(positionData, response.data);
+      // 设置职位状态
+      positionStatus.value = positionData.job_type === 1;
+    }
+  } catch (error) {
+    console.error('获取职位详情失败:', error);
+    ElMessage.error('获取职位详情失败');
+  }
+};
+
+// 返回列表页
+const goBack = () => {
+  router.push('/position/list');
+};
+
+// 编辑职位
+const handleEdit = () => {
+  router.push(`/position/edit/${positionId.value}`);
+};
+
+// 分享职位
+const handleShare = () => {
+  ElMessage.success('分享链接已复制到剪贴板');
+};
+
+// 修改职位状态
+const handleStatusChange = async (value: boolean) => {
+  const id = route.query.id;
+  try {
+    const newStatus = value ? 1 : 0;
+    await api.UpdateObj({
+      id: id,
+      job_type: newStatus
+    });
+    positionData.job_type = newStatus;
+    ElMessage.success(`职位已${value ? '开启' : '关闭'}`);
+  } catch (error) {
+    console.error('修改状态失败:', error);
+    ElMessage.error('修改状态失败');
+    // 恢复原状态
+    positionStatus.value = !value;
+  }
+};
+
+// 编辑职位用途
+const handleEditUsage = () => {
+  ElMessage.info('编辑职位用途功能开发中');
+};
+
+// 编辑招聘流程
+const handleEditProcess = () => {
+  showProcessDialog.value = true;
+};
+
+// 保存招聘流程
+const saveProcess = () => {
+  showProcessDialog.value = false;
+  ElMessage.success('招聘流程已更新');
+};
+
+// 取消编辑
+const cancelEditProcess = () => {
+  showProcessDialog.value = false;
+};
+
+// 删除流程步骤
+const deleteProcessStep = (index: number) => {
+  recruitmentProcess.splice(index, 1);
+};
+
+// 在特定位置添加流程步骤
+const addProcessStepAt = (index: number) => {
+  if (recruitmentProcess.length >= 6) {
+    ElMessage.warning('最多只能添加6个流程步骤');
+    return;
+  }
+  
+  const newStep = {
+    id: Date.now(),
+    name: '新步骤',
+    description: '新步骤',
+    active: true
+  };
+  
+  recruitmentProcess.splice(index, 0, newStep);
+};
+
+// 修改原有的添加方法,调用新方法
+const addProcessStep = () => {
+  addProcessStepAt(recruitmentProcess.length);
+};
+
+// 获取状态文本
+const getStatusText = (status: number) => {
+  const statusMap: Record<number, string> = {
+    0: '未发布',
+    1: '已发布',
+    2: '已结束'
+  };
+  return statusMap[status] || '未知状态';
+};
+
+// 获取状态类型
+const getStatusType = (status: number) => {
+  const typeMap: Record<number, string> = {
+    0: 'info',
+    1: 'success',
+    2: 'danger'
+  };
+  return typeMap[status] || 'info';
+};
+
+// 获取职位性质文本
+const getJobTypeText = (type: number) => {
+  const typeMap: Record<number, string> = {
+    0: '全职',
+    1: '兼职',
+    2: '实习',
+    3: '其他'
+  };
+  return typeMap[type] || '未知';
+};
+
+// 显示选项菜单
+const showStepOptions = (index: number, event: MouseEvent) => {
+  currentAddIndex.value = index;
+  showOptionsMenu.value = true;
+  
+  // 计算菜单位置 - 获取按钮元素
+  const button = event.currentTarget as HTMLElement;
+  // 获取对话框元素,作为相对定位的参考
+  const dialogContent = button.closest('.process-dialog-content');
+  
+  if (dialogContent) {
+    // 获取按钮和对话框的位置信息
+    const buttonRect = button.getBoundingClientRect();
+    const dialogRect = dialogContent.getBoundingClientRect();
+    
+    // 计算相对于对话框的位置
+    const top = buttonRect.bottom - dialogRect.top + 5; // 按钮下方5px
+    const left = buttonRect.left - dialogRect.left;
+    
+    // 设置菜单位置
+    menuPosition.top = `${top}px`;
+    menuPosition.left = `${left}px`;
+  }
+  
+  // 阻止事件冒泡
+  event.stopPropagation();
+};
+
+// 修改添加选定类型的步骤方法
+const addSelectedStepType = (type: string, label: string) => {
+  if (type === 'ai_video') {
+    showAIVideoDialog.value = true;
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加 AI 实时对话类型的处理
+  if (type === 'ai_chat') {
+    showAIChatDialog.value = true;
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加视频宣讲类型的处理
+  if (type === 'video_presentation') {
+    showVideoLectureConfig();
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加资料收集类型的处理
+  if (type === 'data_collection') {
+    showDataCollectionDialog.value = true;
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加简历收集类型的处理
+  if (type === 'resume_collection') {
+    showResumeCollectionConfig();
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加代码测试类型的处理
+  if (type === 'code_test') {
+    showCodeTestConfig();
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 添加打字测试类型的处理
+  if (type === 'typing_test') {
+    showTypingTestDialog.value = true;
+    showOptionsMenu.value = false;
+    return;
+  }
+  
+  // 其他类型的处理保持不变
+  if (recruitmentProcess.length >= 6) {
+    ElMessage.warning('最多只能添加6个流程步骤');
+    return;
+  }
+  
+  const newStep = {
+    id: Date.now(),
+    name: label,
+    description: label,
+    active: true,
+    type: type
+  };
+  
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  showOptionsMenu.value = false;
+};
+
+// 下一步
+const nextStep = () => {
+  if (currentStep.value < 3) {
+    currentStep.value++;
+  } else {
+    finishConfig();
+  }
+};
+
+// 上一步
+const prevStep = () => {
+  if (currentStep.value > 1) {
+    currentStep.value--;
+  }
+};
+
+// 完成配置
+const finishConfig = () => {
+  // 创建新的AI视频步骤
+  const newStep = {
+    id: Date.now(),
+    name: 'AI视频',
+    description: `已选择${selectedAbilities.value.length}项能力测评`,
+    active: true,
+    type: 'ai_video',
+    abilities: selectedAbilities.value.map(a => a.value)
+  };
+  
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  
+  // 关闭对话框
+  showAIVideoDialog.value = false;
+  
+  // 重置当前步骤
+  currentStep.value = 1;
+  
+  // 提示成功
+  ElMessage.success('AI视频步骤已添加');
+};
+
+// 取消AI视频配置
+const cancelAIVideoConfig = () => {
+  showAIVideoDialog.value = false;
+  currentStep.value = 1; // 重置步骤
+};
+
+// 跳转到指定步骤
+const jumpToStep = (step: number) => {
+  // 确保步骤在有效范围内
+  if (step >= 1 && step <= 3) {
+    currentStep.value = step;
+  }
+};
+
+// 显示视频宣讲配置弹窗
+const showVideoLectureConfig = () => {
+  showVideoLectureDialog.value = true;
+};
+
+// 取消视频宣讲配置
+const cancelVideoLecture = () => {
+  showVideoLectureDialog.value = false;
+  // 重置表单
+  Object.assign(videoLectureForm, {
+    title: '',
+    videoFile: null,
+    description: '',
+    broadcastType: 'required'
+  });
+};
+
+// 确认添加视频宣讲
+const confirmVideoLecture = () => {
+  // 创建新的视频宣讲步骤
+  const newStep = {
+    id: Date.now(),
+    name: videoLectureForm.title || '视频宣讲',
+    description: videoLectureForm.description || '视频宣讲',
+    active: true,
+    type: 'video_presentation',
+    config: {
+      ...videoLectureForm
+    }
+  };
+  
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  
+  // 关闭弹窗
+  showVideoLectureDialog.value = false;
+  
+  // 提示成功
+  ElMessage.success('视频宣讲步骤已添加');
+  
+  // 重置表单
+  cancelVideoLecture();
+};
+
+// 添加 AI 实时对话相关方法
+const handleAIChatConfig = () => {
+  // 这里添加确认配置的逻辑
+  const newStep = {
+    id: Date.now(),
+    name: 'AI实时对话',
+    description: 'AI实时对话',
+    active: true,
+    type: 'ai_chat'
+  };
+  
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  showAIChatDialog.value = false;
+  ElMessage.success('AI实时对话步骤已添加');
+};
+
+const cancelAIChatConfig = () => {
+  showAIChatDialog.value = false;
+};
+
+// 添加问题列表数据
+const chatQuestions = ref<ChatQuestion[]>([]);
+
+// 添加问题处理方法
+const handleAddQuestion = () => {
+  showQuestionDialog.value = true;
+};
+
+// 取消添加问题
+const cancelAddQuestion = () => {
+  showQuestionDialog.value = false;
+  // 重置表单
+  Object.assign(questionForm, {
+    title: '',
+    ability: '',
+    content: '',
+    target: '',
+    weight: 100,
+    maxAnswers: 1
+  });
+};
+
+// 确认添加问题
+const confirmAddQuestion = () => {
+  if (!questionForm.title || !questionForm.content) {
+    ElMessage.warning('请填写必填项');
+    return;
+  }
+
+  // 创建新问题对象
+  const newQuestion = {
+    title: questionForm.title,
+    ability: questionForm.ability,
+    content: questionForm.content,
+    target: questionForm.target,
+    weight: questionForm.weight,
+    maxAnswers: questionForm.maxAnswers
+  };
+
+  // 添加到问题列表
+  chatQuestions.value.push(newQuestion);
+  
+  // 关闭弹框
+  showQuestionDialog.value = false;
+  
+  // 重置表单
+  cancelAddQuestion();
+  
+  // 提示成功
+  ElMessage.success('问题添加成功');
+};
+
+// 导入问题处理方法
+const handleImportQuestion = () => {
+  ElMessage.info('导入问题功能开发中');
+};
+
+// 在 script setup 中添加
+const editQuestion = (index: number) => {
+  // 编辑问题的逻辑
+  const question = chatQuestions.value[index];
+  Object.assign(questionForm, question);
+  showQuestionDialog.value = true;
+};
+
+const deleteQuestion = (index: number) => {
+  ElMessageBox.confirm('确认删除该问题?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  }).then(() => {
+    chatQuestions.value.splice(index, 1);
+    ElMessage.success('删除成功');
+  });
+};
+
+// 取消资料收集配置
+const cancelDataCollection = () => {
+  showDataCollectionDialog.value = false;
+  // 重置表单
+  Object.assign(dataCollectionForm, {
+    isRequired: false,
+    questions: []
+  });
+};
+
+// 确认添加资料收集
+const confirmDataCollection = () => {
+  if (dataCollectionForm.questions.length === 0) {
+    ElMessage.warning('请至少选择一个问题');
+    return;
+  }
+
+  // 创建新的资料收集步骤
+  const newStep = {
+    id: Date.now(),
+    name: '资料收集',
+    description: `已选择${dataCollectionForm.questions.length}个问题`,
+    active: true,
+    type: 'data_collection',
+    config: {
+      ...dataCollectionForm,
+      questions: dataCollectionForm.questions.map(q => {
+        // 修复 find 方法的使用
+        const question = questionTypes.value.find(type => type.value === q);
+        return {
+          type: q,
+          title: question?.label || '',
+          required: dataCollectionForm.isRequired
+        };
+      })
+    }
+  };
+
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+
+  // 关闭弹窗
+  showDataCollectionDialog.value = false;
+
+  // 提示成功
+  ElMessage.success('资料收集步骤已添加');
+
+  // 重置表单
+  cancelDataCollection();
+};
+
+// 使用 onMounted 和 onUnmounted 钩子
+onMounted(() => {
+  getPositionDetail();
+});
+
+// 添加代码测试相关的状态和方法
+const showCodeTestDialog = ref(false);
+const codeTestForm = reactive({
+  title: '代码笔试',
+  autoJudge: true,
+  selectedPaper: null as Paper | null,
+});
+
+// 显示代码测试弹窗
+const showCodeTestConfig = () => {
+  showCodeTestDialog.value = true;
+};
+
+// 取消代码测试配置
+const cancelCodeTest = () => {
+  showCodeTestDialog.value = false;
+  // 重置表单
+  Object.assign(codeTestForm, {
+    title: '代码笔试',
+    autoJudge: true,
+    selectedPaper: null
+  });
+};
+
+// 确认添加代码测试
+const confirmCodeTest = () => {
+  if (!codeTestForm.selectedPaper) {
+    ElMessage.warning('请添加考试试卷');
+    return;
+  }
+  
+  // 创建新的代码测试步骤
+  const newStep = {
+    id: Date.now(),
+    name: codeTestForm.title,
+    description: `${codeTestForm.selectedPaper.title}`,
+    active: true,
+    type: 'code_test',
+    config: {
+      ...codeTestForm
+    }
+  };
+  
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  
+  // 关闭弹窗
+  showCodeTestDialog.value = false;
+  
+  // 提示成功
+  ElMessage.success('代码笔试步骤已添加');
+  
+  // 重置表单
+  cancelCodeTest();
+};
+
+// 选择试卷
+const handleSelectPaper = () => {
+  // 模拟选择试卷
+  codeTestForm.selectedPaper = {
+    id: 1,
+    title: '前端开发工程师笔试',
+    questionCount: 4,
+    duration: 60,
+    difficulty: '中等难度'
+  } as Paper;
+};
+
+// 查看试卷
+const handleViewPaper = () => {
+  ElMessage.info('查看试卷功能开发中');
+};
+
+// 更换试卷
+const handleChangePaper = () => {
+  ElMessage.info('更换试卷功能开发中');
+};
+
+// 删除试卷
+const handleRemovePaper = () => {
+  codeTestForm.selectedPaper = null;
+};
+
+// 添加打字测试对话框
+const showTypingTestDialog = ref(false);
+const typingTestForm = reactive({
+  title: '', // 步骤名称
+  duration: 5, // 测试时间,默认5分钟
+  content: '', // 测试页面标题
+  notes: '', // 注意事项内容
+  videoMonitoring: false, // 是否启用视频监控
+  passCriteria: {
+    speed: false, // 是否通过速度标准
+    accuracy: true, // 是否通过正确率标准,默认选中
+  },
+  selectionMode: 'random', // 文章选择方式:random-随机抽取,self-候选人自主选择
+  pageTitle: '', // 测试页面标题
+  previewImage: null, // 登录界面预览图
+  articles: [] // 文章列表
+});
+
+// 取消打字测试配置
+const cancelTypingTest = () => {
+  showTypingTestDialog.value = false;
+  // 重置表单
+  Object.assign(typingTestForm, {
+    title: '',
+    duration: 5,
+    content: '',
+    notes: '',
+    videoMonitoring: false,
+    passCriteria: {
+      speed: false,
+      accuracy: true,
+    },
+    selectionMode: 'random',
+    pageTitle: '',
+    previewImage: null,
+    articles: []
+  });
+};
+
+// 确认添加打字测试
+const confirmTypingTest = () => {
+  // 创建新的打字测试步骤
+  const newStep = {
+    id: Date.now(),
+    name: typingTestForm.title,
+    description: `打字测试 ${typingTestForm.duration}分钟`,
+    active: true,
+    type: 'typing_test',
+    config: {
+      ...typingTestForm
+    }
+  };
+  
+  // 添加到流程中
+  recruitmentProcess.splice(currentAddIndex.value, 0, newStep);
+  
+  // 关闭弹窗
+  showTypingTestDialog.value = false;
+  
+  // 提示成功
+  ElMessage.success('打字测试步骤已添加');
+  
+  // 重置表单
+  cancelTypingTest();
+};
+</script>
+
+<style scoped>
+.position-detail-container {
+  padding: 20px;
+  width: 80% !important;
+  margin: 0 auto;
+}
+
+.header-container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.header-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.detail-content {
+  display: flex;
+  gap: 20px;
+}
+
+.detail-card {
+  flex: 2;
+}
+
+.status-cards {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.section-title {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+  font-weight: bold;
+  color: #333;
+  position: relative;
+}
+
+.section-line {
+  width: 4px;
+  height: 16px;
+  background-color: #67C23A;
+  margin-right: 8px;
+}
+
+.edit-btn {
+  position: absolute;
+  right: 0;
+  color: #67C23A;
+}
+
+.detail-item {
+  display: flex;
+  margin-bottom: 20px;
+  line-height: 1.5;
+}
+
+.detail-label {
+  width: 120px;
+  color: #606266;
+  font-weight: 500;
+}
+
+.detail-value {
+  flex: 1;
+  color: #303133;
+}
+
+.html-content {
+  max-height: 300px;
+  overflow-y: auto;
+  padding: 10px;
+ /*  background-color: #f9f9f9; */
+  border-radius: 4px;
+}
+
+.benefit-tag {
+  margin-right: 8px;
+  margin-bottom: 8px;
+}
+
+.status-switch {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.status-text {
+  font-size: 14px;
+  color: #303133;
+}
+
+.usage-content {
+  display: flex;
+  align-items: center;
+  margin-top: 10px;
+}
+
+.usage-label {
+  width: 80px;
+  color: #606266;
+}
+
+.usage-value {
+  color: #303133;
+  font-weight: 500;
+}
+
+.process-steps {
+  margin-top: 20px;
+}
+
+.process-step {
+  display: flex;
+  align-items: flex-start;
+  margin-bottom: 15px;
+}
+
+.step-number {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  background-color: #67C23A;
+  color: white;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 10px;
+  font-size: 14px;
+}
+
+.step-content {
+  flex: 1;
+}
+
+.step-title {
+  font-weight: 500;
+  color: #303133;
+  margin-bottom: 4px;
+}
+
+.step-desc {
+  font-size: 12px;
+  color: #909399;
+}
+
+.process-step.disabled .step-number {
+  background-color: #909399;
+}
+
+.process-step.disabled .step-title,
+.process-step.disabled .step-desc {
+  color: #C0C4CC;
+}
+
+/* 招聘流程编辑对话框样式 */
+.process-dialog-content {
+  max-height: 400px;
+  overflow-y: auto;
+}
+
+.process-edit-item {
+  display: flex;
+  align-items: center;
+  padding: 15px;
+  border-radius: 4px;
+  margin-bottom: 10px;
+  background-color: #f5f7fa;
+  position: relative;
+}
+
+.process-edit-item.highlight {
+  background-color: #f0f9eb;
+  border: 1px solid #e1f3d8;
+}
+
+.process-number {
+  width: 24px;
+  height: 24px;
+  border-radius: 50%;
+  background-color: #67C23A;
+  color: white;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 15px;
+}
+
+.process-edit-content {
+  flex: 1;
+}
+
+.process-edit-desc {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 4px;
+}
+
+.delete-btn {
+  position: absolute;
+  right: 10px;
+  top: 50%;
+  transform: translateY(-50%);
+}
+
+/* 添加在每个步骤上方的加号按钮样式 */
+.add-process-btn-top {
+  display: flex;
+  justify-content: center;
+  margin-bottom: 5px;
+}
+
+.add-process-btn-top .el-button {
+  color: #67C23A;
+  padding: 5px;
+}
+
+/* 确保原有的底部加号按钮样式保持不变 */
+.add-process-btn {
+  display: flex;
+  justify-content: center;
+  margin-top: 15px;
+}
+
+.add-process-btn .el-button {
+  color: #67C23A;
+}
+
+/* 流程步骤选项菜单 */
+.process-options-menu {
+  position: absolute;
+  background-color: white;
+  border-radius: 4px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  padding: 8px 0;
+  z-index: 2000;
+  max-height: 300px;
+  overflow-y: auto;
+  width: 150px;
+}
+
+.process-option-item {
+  padding: 8px 16px;
+  cursor: pointer;
+  font-size: 14px;
+  color: #606266;
+}
+
+.process-option-item:hover {
+  background-color: #f5f7fa;
+  color: #67C23A;
+}
+
+/* AI视频抽屉样式 */
+.ai-video-drawer {
+  --el-drawer-padding-primary: 0;
+}
+
+.ai-video-steps {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 20px 0;
+  border-bottom: 1px solid #e4e7ed;
+  background-color: #fff;
+}
+
+.step-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  color: #909399;
+  position: relative;
+  z-index: 1;
+  cursor: pointer;
+  transition: all 0.3s;
+}
+
+.step-item:hover {
+  color: #67C23A;
+}
+
+.step-item:hover .step-number {
+  border-color: #67C23A;
+}
+
+.step-number {
+  width: 30px;
+  height: 30px;
+  border-radius: 50%;
+  background-color: #f5f7fa;
+  color: #909399;
+  border: 1px solid #dcdfe6;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 8px;
+  font-weight: bold;
+}
+
+.step-item.active .step-number {
+  background-color: #67C23A;
+  color: white;
+  border-color: #67C23A;
+}
+
+.step-line {
+  width: 100px;
+  height: 1px;
+  background-color: #e4e7ed;
+  margin: 0 15px;
+  position: relative;
+  top: -15px;
+}
+
+.step-line.active-line {
+  background-color: #67C23A;
+}
+
+.step-title {
+  font-size: 14px;
+}
+
+.ai-video-content {
+  padding: 20px;
+  height: calc(100% - 120px); /* 减去header和footer高度 */
+  overflow-y: auto;
+}
+
+.drawer-footer {
+  padding: 10px 20px;
+  text-align: right;
+  border-top: 1px solid #e4e7ed;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background-color: white;
+}
+
+/* 步骤1:考察能力样式 */
+.option-tip {
+  margin-bottom: 15px;
+  color: #606266;
+}
+
+.new-feature-tip {
+  background-color: #f0f9eb;
+  padding: 10px;
+  border-radius: 4px;
+  margin-bottom: 20px;
+  font-size: 14px;
+  color: #606266;
+  line-height: 1.5;
+}
+
+.new-tag {
+  display: inline-block;
+  background-color: #f56c6c;
+  color: white;
+  padding: 2px 6px;
+  border-radius: 4px;
+  font-size: 12px;
+  margin-right: 5px;
+}
+
+.ability-options {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 15px;
+}
+
+.ability-label {
+  font-size: 14px;
+  color: #606266;
+}
+
+/* 步骤2:面试题目样式 */
+.interview-settings {
+  width: 100%;
+}
+
+.interview-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.interview-duration {
+  display: flex;
+  align-items: center;
+}
+
+.duration-value {
+  font-weight: bold;
+  margin: 0 10px;
+}
+
+.duration-tip {
+  color: #909399;
+  font-size: 12px;
+}
+
+.interview-mode {
+  display: flex;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.mode-value {
+  font-weight: bold;
+  margin: 0 10px;
+}
+
+.interview-questions-container {
+  min-height: 200px;
+  border: 1px dashed #dcdfe6;
+  border-radius: 4px;
+  margin-bottom: 20px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.no-questions {
+  text-align: center;
+  color: #909399;
+}
+
+.ai-tip {
+  font-size: 12px;
+  color: #c0c4cc;
+  margin: 5px 0;
+}
+
+.auto-generate-btn {
+  margin-top: 15px;
+}
+
+.multi-dimension-questions {
+  margin-top: 30px;
+}
+
+.dimension-title {
+  font-weight: bold;
+  margin-bottom: 15px;
+}
+
+.dimension-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.dimension-item {
+  border: 1px solid #dcdfe6;
+  border-radius: 4px;
+  padding: 10px;
+}
+
+.dimension-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.expand-icon {
+  cursor: pointer;
+}
+
+/* 步骤3:系统设置样式 */
+.system-settings {
+  width: 100%;
+}
+
+.setting-section {
+  margin-bottom: 30px;
+  border-bottom: 1px solid #ebeef5;
+  padding-bottom: 20px;
+}
+
+.section-header {
+  font-weight: bold;
+  color: #303133;
+  margin-bottom: 15px;
+  position: relative;
+  padding-left: 10px;
+}
+
+.section-header::before {
+  content: '';
+  position: absolute;
+  left: 0;
+  top: 50%;
+  transform: translateY(-50%);
+  width: 4px;
+  height: 16px;
+  background-color: #67C23A;
+}
+
+.rank-settings {
+  display: flex;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.rank-range {
+  display: flex;
+  align-items: center;
+  margin-right: 30px;
+}
+
+.range-inputs {
+  display: flex;
+  align-items: center;
+  margin-left: 10px;
+}
+
+.percent-input {
+  width: 80px;
+}
+
+.score-display {
+  display: flex;
+  align-items: center;
+}
+
+.score-range {
+  margin-left: 10px;
+  color: #67C23A;
+}
+
+.add-rank-btn {
+  margin-top: 10px;
+}
+
+.validity-setting {
+  display: flex;
+  align-items: center;
+  margin-bottom: 10px;
+}
+
+.validity-label {
+  margin-left: 10px;
+}
+
+.validity-tip {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 5px;
+}
+
+.model-select {
+  width: 200px;
+}
+
+@media (max-width: 768px) {
+  .ability-options {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  
+  .step-line {
+    width: 50px;
+  }
+}
+
+@media (max-width: 480px) {
+  .ability-options {
+    grid-template-columns: 1fr;
+  }
+  
+  .interview-header {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+  
+  .interview-actions {
+    margin-top: 10px;
+  }
+  
+  .rank-settings {
+    flex-direction: column;
+    align-items: flex-start;
+  }
+  
+  .rank-range {
+    margin-bottom: 10px;
+  }
+}
+
+/* 视频宣讲弹窗样式 */
+.video-lecture-form {
+  padding: 20px 0;
+}
+
+.form-item {
+  margin-bottom: 20px;
+}
+
+.form-label {
+  font-weight: 500;
+  margin-bottom: 8px;
+  color: #606266;
+}
+
+.video-uploader {
+  width: 100%;
+}
+
+.upload-area {
+  width: 100%;
+  height: 120px;
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  transition: border-color 0.3s;
+}
+
+.upload-area:hover {
+  border-color: #67C23A;
+}
+
+.upload-text {
+  color: #909399;
+  font-size: 12px;
+  margin-top: 8px;
+}
+
+.el-icon {
+  font-size: 24px;
+  color: #909399;
+}
+
+/* AI实时对话抽屉样式 */
+.ai-chat-drawer {
+  --el-drawer-padding-primary: 0;
+}
+
+.ai-chat-content {
+  padding: 20px;
+  height: calc(100% - 120px);
+  overflow-y: auto;
+}
+
+.chat-settings {
+  margin-bottom: 30px;
+}
+
+.chat-actions {
+  display: flex;
+  gap: 10px;
+  margin: 20px 0;
+}
+
+.chat-questions {
+  margin-top: 20px;
+  min-height: 200px;
+  border: 1px dashed #dcdfe6;
+  border-radius: 4px;
+}
+
+.empty-questions {
+  height: 200px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: #909399;
+}
+
+.tip-text {
+  font-size: 12px;
+  color: #c0c4cc;
+  margin-top: 8px;
+}
+
+.question-list {
+  padding: 16px;
+  background: #f5f7fa;
+  border-radius: 8px;
+  min-height: 200px;
+}
+
+.question-card {
+  background: #fff;
+  border-radius: 8px;
+  padding: 20px;
+  margin-bottom: 16px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+}
+
+.question-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.question-title {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.question-number {
+  color: #333;
+  font-weight: 500;
+}
+
+.question-actions {
+  display: flex;
+  align-items: center;
+  gap: 20px;
+}
+
+.weight-control, .answer-limit {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.weight-label, .answer-label {
+  color: #606266;
+  font-size: 14px;
+  white-space: nowrap;
+}
+
+:deep(.el-input-number) {
+  width: 100px;
+}
+
+:deep(.el-select) {
+  width: 120px;
+}
+
+.question-info {
+  background: #f8f9fa;
+  padding: 15px;
+  border-radius: 4px;
+}
+
+.info-item {
+  margin-bottom: 12px;
+  line-height: 1.6;
+}
+
+.info-item:last-child {
+  margin-bottom: 0;
+}
+
+.info-label {
+  color: #909399;
+  margin-right: 8px;
+  font-weight: 500;
+}
+
+/* 问题编辑弹框样式 */
+.question-form {
+  padding: 20px 0;
+}
+
+.form-item {
+  margin-bottom: 20px;
+}
+
+.form-label {
+  font-weight: 500;
+  margin-bottom: 8px;
+  color: #606266;
+  display: flex;
+  align-items: center;
+}
+
+.required {
+  color: #f56c6c;
+  margin-left: 4px;
+}
+
+.full-width {
+  width: 100%;
+}
+
+:deep(.el-input__count) {
+  background: transparent;
+}
+
+:deep(.el-textarea__count) {
+  background: transparent;
+}
+
+/* 资料收集对话框样式 */
+.data-collection-form {
+  padding: 20px;
+}
+
+/* 表单项样式 */
+.form-item {
+  margin-bottom: 24px;
+}
+
+/* 表单标签样式 */
+.form-label {
+  font-size: 14px;
+  color: #333;
+  font-weight: 500;
+  margin-bottom: 12px;
+  display: flex;
+  align-items: center;
+}
+
+/* 必填星号样式 */
+.required {
+  color: #ff4d4f;
+  margin-left: 4px;
+  font-size: 14px;
+}
+
+/* 开关样式 */
+:deep(.el-switch) {
+  margin-top: 8px;
+}
+
+/* 问题列表容器样式 */
+.question-list {
+  margin-top: 12px;
+ /*  border: 1px solid #e4e7ed; */
+  border-radius: 4px;
+  padding: 16px;
+/*   background-color: #f8f9fa; */
+}
+
+/* 问题项样式 */
+.question-item {
+  margin-bottom: 16px;
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+}
+
+/* 复选框组样式 */
+:deep(.el-checkbox-group) {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+}
+
+/* 复选框样式 */
+:deep(.el-checkbox) {
+  margin-right: 0;
+  height: auto;
+}
+
+/* 复选框标签样式 */
+:deep(.el-checkbox__label) {
+  font-size: 14px;
+  color: #606266;
+}
+
+.data-collection-dialog {
+  .data-collection-form {
+    padding: 0;
+  }
+
+  .question-list {
+    padding: 0;
+  }
+
+  .question-item {
+    border: 1px solid #DCDFE6;
+    border-radius: 4px;
+    margin-bottom: 16px;
+    overflow: hidden;
+  }
+
+  .question-header {
+    background: #F5F7FA;
+    padding: 12px 16px;
+    border-bottom: 1px solid #DCDFE6;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+
+  .question-title {
+    font-size: 14px;
+    color: #303133;
+  }
+
+  .question-type {
+    display: flex;
+    align-items: center;
+    gap: 4px;
+    color: #909399;
+    font-size: 14px;
+    cursor: pointer;
+
+    .el-icon {
+      font-size: 12px;
+    }
+  }
+
+  .question-content {
+    padding: 16px;
+  }
+
+  .user-answer {
+    color: #909399;
+    font-size: 14px;
+    margin-bottom: 16px;
+  }
+
+  .question-actions {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 16px;
+    padding-bottom: 16px;
+    border-bottom: 1px solid #EBEEF5;
+  }
+
+  .action-left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+
+    .action-text {
+      font-size: 14px;
+      color: #606266;
+    }
+  }
+
+  .action-right {
+    display: flex;
+    gap: 16px;
+
+    .action-icon {
+      font-size: 16px;
+      color: #909399;
+      cursor: pointer;
+
+      &:hover {
+        color: #409EFF;
+      }
+    }
+  }
+
+  .question-settings {
+    display: flex;
+    gap: 24px;
+  }
+
+  .setting-item {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    
+    span {
+      font-size: 14px;
+      color: #606266;
+    }
+  }
+
+  .add-question {
+    margin-top: 24px;
+    text-align: center;
+  }
+}
+
+/* 简历收集对话框样式 */
+.resume-collection-dialog {
+  .resume-collection-form {
+    padding: 20px 0;
+  }
+
+  .switch-label {
+    margin-left: 10px;
+    font-size: 14px;
+    color: #606266;
+  }
+
+  .resume-preview {
+    margin-top: 20px;
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+  }
+
+  .preview-title {
+    padding: 10px 15px;
+    background-color: #f5f7fa;
+    border-bottom: 1px solid #e4e7ed;
+    font-weight: 500;
+    color: #606266;
+  }
+
+  .preview-content {
+    padding: 15px;
+  }
+
+  .preview-item {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15px;
+  }
+
+  .item-label {
+    width: 80px;
+    color: #606266;
+  }
+
+  .item-input {
+    flex: 1;
+    height: 32px;
+    background-color: #f5f7fa;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+  }
+
+  .item-upload {
+    flex: 1;
+    height: 60px;
+    background-color: #f5f7fa;
+    border: 1px dashed #dcdfe6;
+    border-radius: 4px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-required {
+    color: #f56c6c;
+    margin-left: 5px;
+  }
+}
+
+/* 添加代码测试对话框样式 */
+.code-test-dialog {
+  .code-test-form {
+    padding: 20px 0;
+  }
+
+  .switch-label {
+    margin-left: 10px;
+    font-size: 14px;
+    color: #606266;
+  }
+
+  .test-paper-selector {
+    margin-top: 10px;
+  }
+
+  .empty-paper {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 30px;
+    border: 1px dashed #dcdfe6;
+    border-radius: 4px;
+    background-color: #f8f9fa;
+  }
+
+  .tip-text {
+    margin-top: 10px;
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .selected-paper {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 15px;
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    background-color: #f8f9fa;
+  }
+
+  .paper-info {
+    flex: 1;
+  }
+
+  .paper-title {
+    font-weight: 500;
+    color: #303133;
+    margin-bottom: 5px;
+  }
+
+  .paper-meta {
+    display: flex;
+    gap: 15px;
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .paper-actions {
+    display: flex;
+    gap: 10px;
+  }
+}
+
+/* 添加打字测试对话框样式 */
+.typing-test-dialog {
+  .typing-test-form {
+    padding: 20px;
+  }
+
+  .form-item {
+    margin-bottom: 24px;
+    position: relative;
+  }
+
+  .form-label {
+    font-weight: 500;
+    margin-bottom: 12px;
+    color: #606266;
+    font-size: 14px;
+  }
+
+  .article-selection {
+    margin-top: 10px;
+  }
+
+  .add-article-btn {
+    display: flex;
+    align-items: center;
+    gap: 5px;
+    font-size: 13px;
+  }
+
+  .time-input-container {
+    display: flex;
+    align-items: center;
+  }
+
+  .time-input {
+    width: 120px;
+  }
+
+  .time-unit {
+    margin-left: 10px;
+    color: #606266;
+  }
+
+  .preview-uploader {
+    width: 100px;
+  }
+
+  .upload-area {
+    width: 100px;
+    height: 100px;
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    transition: border-color 0.3s;
+  }
+
+  .upload-area:hover {
+    border-color: #67C23A;
+  }
+
+  .upload-text {
+    color: #909399;
+    font-size: 12px;
+    margin-top: 8px;
+  }
+
+  .notes-counter {
+    position: absolute;
+    right: 10px;
+    bottom: -20px;
+    font-size: 12px;
+    color: #909399;
+  }
+
+  .criteria-options {
+    display: flex;
+    gap: 20px;
+  }
+  
+  /* 添加以下新样式 */
+  :deep(.el-radio) {
+    margin-right: 30px;
+  }
+  
+  :deep(.el-radio__label) {
+    font-size: 14px;
+  }
+  
+  :deep(.el-textarea) {
+    margin-bottom: 5px;
+  }
+  
+  :deep(.el-checkbox__label) {
+    font-size: 14px;
+  }
+  
+  :deep(.el-input) {
+    width: auto;
+  }
+}
+</style> 

+ 7 - 7
src/views/position/list/api.ts

@@ -2,7 +2,7 @@ import { request } from '/@/utils/service';
 import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
 import { Session } from '/@/utils/storage';
 
-export const apiPrefix = '/api/job/create';
+export const apiPrefix = '/api/system/job/create';
 
 export function GetPermission() {
 	return request({
@@ -13,21 +13,21 @@ export function GetPermission() {
 
 export function GetList(query: PageQuery) {
 	return request({
-		url: '/api/job/list',
+		url: '/api/system/job/list',
 		method: 'get',
 		params: {...query,tenant_id:'1'},/* :Session.get('tenant_id').tenant_id ||  */
 	});
 }
 export function GetObj(id: InfoReq) {
 	return request({
-		url: "/api/job/detail" + id,
+		url: "/api/system/job/detail?id=" + id+"&tenant_id=1",
 		method: 'get',
 	});
 }
 
 export function AddObj(obj: AddReq) {
 	return request({
-		url: "/api/job/create",
+		url: "/api/system/job/create",
 		method: 'post',
 		data: {...obj,tenant_id: '1'},/* Session.get('tenant_id').tenant_id || */
 	});
@@ -35,15 +35,15 @@ export function AddObj(obj: AddReq) {
 
 export function UpdateObj(obj: EditReq) {
 	return request({
-		url: "/api/job/update",/* + obj.id+'/' */
-		method: 'put',
+		url: "/api/system/job/update",/* + obj.id+'/' */
+		method: 'post',
 		data: {...obj,tenant_id: '1'},
 	});
 }
 
 export function DelObj(id: DelReq) {
 	return request({
-		url: '/api/job/delete',/* + id + '/' */
+		url: '/api/system/job/delete',/* + id + '/' */
 		method: 'delete',
 		data: { id,tenant_id: '1' },
 	});

+ 19 - 6
src/views/position/list/crud.tsx

@@ -3,6 +3,7 @@ import * as api from './api';
 import { dictionary } from '/@/utils/dictionary';
 import { successMessage } from '../../../utils/message';
 import { auth } from '/@/utils/authFunction';
+import { Layout } from 'element-plus';
 
 /**
  *
@@ -40,6 +41,15 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 				buttons: {
 					add: {
 						show: auth('role:Create'),
+						click: () => {
+							context.router.push('/position/create');
+						}
+					},
+					addDialog: {
+						text: '快速添加',
+						icon: 'Plus',
+						show: auth('role:Create'),
+						order: 2
 					},
 				},
 			},
@@ -56,7 +66,10 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 					edit: {
 						show: auth('role:Update'),
 						icon:"Edit",
-						type:"text"
+						type:"text",
+						click: (ctx) => {
+							context.router.push(`/position/detail?id=${ctx.row.id}`);
+						}
 					},
 					remove: {
 						show: auth('role:Delete'),
@@ -156,7 +169,7 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 						value: 1,
 					},
 				},*/
-				job_type_display: {
+				job_type: {
 					title: '职位类型',
 					search: { show: true },
 					type: 'dict-select',
@@ -165,10 +178,10 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp
 					},
 					dict: dict({
 						data: [
-							{ value: "全职", label: '全职' },
-							{ value: "兼职", label: '兼职' },
-							{ value: "实习", label: '实习' },
-							{ value: "其他", label: "其他" }
+							{ value:0, label: '全职' },
+							{ value:1, label: '兼职' },
+							{ value: 2, label: '实习' },
+							{ value: 3, label: "其他" }
 						]
 					}),
 					form: {

+ 8 - 2
src/views/position/list/index.vue

@@ -13,7 +13,7 @@
 </template>
 
 <script lang="ts" setup name="role">
-import { defineAsyncComponent, onMounted, ref } from 'vue';
+import { defineAsyncComponent, onMounted, ref, reactive } from 'vue';
 import { useFs } from '@fast-crud/fast-crud';
 import { createCrudOptions } from './crud';
 import { RoleDrawerStores } from './stores/RoleDrawerStores';
@@ -22,6 +22,7 @@ import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
 import { RoleUsersStores } from './stores/RoleUsersStores';
 import { ElMessage } from 'element-plus';
 import axios from 'axios';
+import { useRouter } from 'vue-router';
 
 const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
 
@@ -33,13 +34,18 @@ const RoleDrawer = RoleDrawerStores(); // 角色-抽屉
 const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
 const RoleMenuField = RoleMenuFieldStores();// 角色-菜单-字段
 const RoleUsers = RoleUsersStores();// 角色-用户
+
+// 获取路由实例
+const router = useRouter();
+
 const { crudBinding, crudRef, crudExpose } = useFs({
 	createCrudOptions,
 	context: { 
 		RoleDrawer, 
 		RoleMenuBtn, 
 		RoleMenuField,
-		generateQRCode // 将二维码生成方法传递给crud配置
+		generateQRCode, // 将二维码生成方法传递给crud配置
+		router, // 添加router到上下文
 	},
 });