@@ -1405,7 +1396,7 @@
import { useMessage, useMessageBox } from '/@/hooks/message'
import axios from 'axios'
// 导入图标
- import { User, Phone, Document, CreditCard, Briefcase, Flag, Plus, Edit, Delete, Connection, School, Medal, Files, Clock, Setting } from '@element-plus/icons-vue'
+ import { User, Phone, Document, CreditCard, Briefcase, Flag, Plus, Edit, Delete, Connection, School, Medal, Files, Clock, Setting, Operation, Switch, CircleCheck, CircleClose, Refresh, Download } from '@element-plus/icons-vue'
// 导入api(统一使用 /@/ 路径别名)
import {
@@ -1420,6 +1411,7 @@
updateInout,
exportTeacherInfo as exportTeacherInfoApi
} from '/@/api/professional/professionaluser/teacherbase'
+ import {getDictsByTypes} from '/@/api/admin/dict'
import {getNationalList} from '/@/api/basic/basicnation'
import {addPoliticssStatus, dePoObj} from '/@/api/professional/professionaluser/professionalpoliticsstatus'
import {addAcadeRelation, delEduObj} from '/@/api/professional/professionaluser/professionalteacheracademicrelation'
@@ -1444,7 +1436,11 @@
// 导入工具
import { Session } from '/@/utils/storage'
+ // 导入 composables(已移除,改为通过 TableColumnControl 组件暴露)
// 导入组件(使用 defineAsyncComponent 异步加载,优化性能)
+ const TeacherNameNo = defineAsyncComponent(() => import('/@/components/TeacherNameNo/index.vue'))
+ const GenderTag = defineAsyncComponent(() => import('/@/components/GenderTag/index.vue'))
+ const StatusTag = defineAsyncComponent(() => import('/@/components/StatusTag/index.vue'))
const ShowEvidence = defineAsyncComponent(() => import("../common/showEvidence.vue"));
const ShowHonorEdvince = defineAsyncComponent(() => import("../common/showHonorEdvince.vue"));
const ExportTeacherInfoDialog = defineAsyncComponent(() => import('./export-teacher-info.vue'));
@@ -1453,6 +1449,10 @@
const PoliticsDialog = defineAsyncComponent(() => import('./politics-dialog.vue'));
const RelationDialog = defineAsyncComponent(() => import('./relation-dialog.vue'));
const StatusLockDialog = defineAsyncComponent(() => import('./status-lock-dialog.vue'));
+ const ActionDropdown = defineAsyncComponent(() => import('./action-dropdown.vue'));
+ const TableColumnControl = defineAsyncComponent(() => import('/@/components/TableColumnControl/index.vue'));
+ const TableColumn = defineAsyncComponent(() => import('/@/components/TableColumn/index.vue'));
+ const TableColumnProvider = defineAsyncComponent(() => import('/@/components/TableColumn/Provider.vue'));
// Pagination 组件已在模板中使用,无需导入(全局组件)
// 导入工具
import {validateNull} from "/@/utils/validate";
@@ -1570,6 +1570,7 @@
const qualificationList = ref([])
const degreeList = ref([])
const activeName = ref('')
+ const subActiveName = ref('subBaseInfo') // 子标签页当前激活的标签
const dialogImageUrl = ref('')
const nationalList = ref([])
const fileList = ref([])
@@ -1588,6 +1589,33 @@
const zgzData = ref([])
const nowImage = ref("")
const dataPolitics = ref([])
+
+ // 表格引用
+ const tableRef = ref()
+ // TableColumnControl 组件引用
+ const tableColumnControlRef = ref()
+
+ // 调试:监听 tableRef.value 的变化
+ watch(() => tableRef.value, (newVal, oldVal) => {
+ console.log('[index.vue] tableRef.value 变化:', { newVal, oldVal, hasValue: !!newVal })
+ if (newVal) {
+ console.log('[index.vue] tableRef.value 已赋值,表格实例:', newVal)
+ const tableEl = (newVal as any).$el
+ console.log('[index.vue] tableRef.value.$el:', tableEl)
+ }
+ }, { immediate: true })
+
+ // 从 TableColumnControl 获取 isColumnVisible 和 visibleTableColumns
+ const isColumnVisible = (propOrLabel: string) => {
+ if (tableColumnControlRef.value?.isColumnVisible) {
+ return tableColumnControlRef.value.isColumnVisible(propOrLabel)
+ }
+ // 默认显示所有列(在 TableColumnControl 初始化之前)
+ return true
+ }
+
+ const visibleTableColumns = ref
([])
+
// 静态配置数据
const defaultProps = {
label: "deptName",
@@ -1646,14 +1674,20 @@
],
telPhone: [
{required: true, message: '请输入正确的电话号码', trigger: 'blur'},
- {min: 11, max: 11, message: '长度为 11', trigger: 'blur'}
+ {pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur'}
],
idCard: [
{required: true, message: '请输入正确身份证', trigger: 'blur'},
- {min: 15, max: 18, message: '长度在 15 到 18 个字符', trigger: 'blur'}
+ {min: 15, max: 18, message: '长度在 15 到 18 个字符', trigger: 'blur'},
+ {pattern: /^(\d{15}|\d{17}[\dXx])$/, message: '身份证号格式不正确(15位或18位,18位最后一位可以是X)', trigger: 'blur'}
],
telPhoneTwo: [
- {required: false, min: 11, max: 11, message: '长度为 11', trigger: 'blur'}
+ {required: false, pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur'}
+ ],
+ bankNo: [
+ {required: true, message: '请输入银行卡号', trigger: 'blur'},
+ {pattern: /^\d{16,30}$/, message: '银行卡号格式不正确(16-30位数字)', trigger: 'blur'},
+ {min: 16, max: 30, message: '银行卡号长度为 16 到 30 位', trigger: 'blur'}
],
bankOpen: [
{required: true, message: '请输入开户行', trigger: 'blur'}
@@ -1793,6 +1827,46 @@
}
})
+ // 合并表单验证规则
+ const mergedRules = computed(() => {
+ // 将 baseInfo 的规则加上 baseInfo 前缀
+ const baseInfoRules: Record = {}
+ Object.keys(rules).forEach(key => {
+ // 在编辑模式下,某些字段被禁用(如 realName, teacherNo),不需要验证
+ // 根据 isAdd 状态动态调整验证规则
+ if (isAdd.value) {
+ // 新增模式:使用原始规则
+ baseInfoRules[`baseInfo.${key}`] = rules[key]
+ } else {
+ // 编辑模式:对于被禁用的字段,移除必填验证
+ if (key === 'realName' || key === 'teacherNo') {
+ // 这些字段在编辑模式下被禁用,移除必填验证
+ const rule = rules[key]
+ if (Array.isArray(rule)) {
+ baseInfoRules[`baseInfo.${key}`] = rule.filter((r: any) => !r.required)
+ } else {
+ baseInfoRules[`baseInfo.${key}`] = rule
+ }
+ } else {
+ baseInfoRules[`baseInfo.${key}`] = rules[key]
+ }
+ }
+ })
+
+ // 岗位信息规则:始终包含所有岗位信息规则,以便在保存时能够验证
+ const stationRules: Record = {}
+ Object.keys(stationFormValidate).forEach(key => {
+ stationRules[`professionalStationRelation.${key}`] = stationFormValidate[key]
+ })
+
+ return {
+ // baseInfo 的规则(加上 baseInfo 前缀)
+ ...baseInfoRules,
+ // professionalStationRelation 的规则(始终包含)
+ ...stationRules
+ }
+ })
+
// 生命周期
onMounted(async () => {
// 先初始化基础数据
@@ -1801,6 +1875,17 @@
await loadSearchDictData()
// 初始化完成后加载表格数据
getDataList()
+
+ // 调试:检查 tableRef.value 是否被赋值
+ await nextTick()
+ setTimeout(() => {
+ console.log('[index.vue] onMounted: tableRef.value:', tableRef.value)
+ if (tableRef.value) {
+ console.log('[index.vue] onMounted: tableRef.value.$el:', (tableRef.value as any).$el)
+ } else {
+ console.warn('[index.vue] onMounted: tableRef.value 仍未赋值')
+ }
+ }, 500)
})
// 加载搜索条件字典数据
@@ -1836,16 +1921,19 @@
// 暴露方法给模板使用(如果需要)
// watch 监听器
- watch(activeName, (val) => {
+ watch(activeName, (val, oldVal) => {
//监听切换状态-计划单
- if (val != "first") {
- setTimeout(() => {
+ // 从其他标签页切换到非"first"标签页时检查基础信息
+ // 避免在初始化时触发检查(oldVal 为空字符串表示初始化)
+ // 同时需要确保对话框已打开(dialogFromVisible 为 true)
+ if (val != "first" && oldVal && oldVal !== '' && dialogFromVisible.value) {
+ setTimeout(() => {
if (!form.baseInfo.id || form.baseInfo.id == '') {
message.info("请先完善基础信息")
- saveSubmit();
- }
- }, 500)
+ activeName.value = "first"
}
+ }, 500)
+ }
})
watch(() => form.professionalStationRelation.employmentNature, (newVal) => {
@@ -1987,10 +2075,75 @@
multiDialogRef.value?.init(val)
})
}
+
+ // 获取操作菜单项配置
+ const getActionMenuItems = (row: any) => {
+ return [
+ {
+ command: 'export',
+ label: '导出',
+ icon: Download,
+ visible: permissions.value.professional_teacherbase_export
+ },
+ {
+ command: 'personnel-transfer',
+ label: '人员调动',
+ icon: Switch,
+ visible: permissions.value.professional_teacherbase_status_lock
+ },
+ {
+ command: 'party-transfer',
+ label: '党员调动',
+ icon: Switch,
+ visible: permissions.value.professional_teacherbase_status_lock
+ },
+ {
+ command: 'allow-inout',
+ label: '允许进出',
+ icon: CircleCheck,
+ visible: permissions.value.professional_teacherbase_inout && row.inoutFlag == '0'
+ },
+ {
+ command: 'forbid-inout',
+ label: '禁止进出',
+ icon: CircleClose,
+ visible: permissions.value.professional_teacherbase_inout && row.inoutFlag == '1'
+ },
+ {
+ command: 'reset-password',
+ label: '重置密码',
+ icon: Refresh,
+ visible: permissions.value.professional_teacherbase_resetpw
+ }
+ ]
+ }
+
+ // 处理更多操作下拉菜单命令
+ const handleMoreCommand = (command: string, row: any, index: number) => {
+ switch (command) {
+ case 'export':
+ handleDownLoadWord(row.teacherNo)
+ break
+ case 'personnel-transfer':
+ handleWaitExam(row, 5)
+ break
+ case 'party-transfer':
+ handleWaitExam(row, 6)
+ break
+ case 'allow-inout':
+ updateInoutFlag(row, 1)
+ break
+ case 'forbid-inout':
+ updateInoutFlag(row, 0)
+ break
+ case 'reset-password':
+ resetPassword(row)
+ break
+ }
+ }
// 分页处理方法已由 useTable 提供,无需手动实现
-
- const tableRef = ref()
+ // tableRef 已在上面定义(用于 useTableColumns)
const exportExcel = (form: any, url: string) => {
return axios({
@@ -2028,44 +2181,71 @@
const saveSubmit = () => {
canSave.value = false
if (activeName.value == "first") {
- baseForm.value?.validate((valid: boolean) => {
- if (valid) {
+ // 构建基本信息需要验证的字段列表(始终包含所有基本信息字段)
+ const baseInfoFields = Object.keys(rules).map(key => `baseInfo.${key}`)
+
+ // 构建岗位信息需要验证的字段列表(始终包含所有岗位信息字段)
+ const stationFields = Object.keys(stationFormValidate).map(key => `professionalStationRelation.${key}`)
+
+ // 根据当前子标签页决定先验证哪个
+ const currentFields = subActiveName.value === 'subBaseInfo'
+ ? baseInfoFields
+ : stationFields
+
+ const otherFields = subActiveName.value === 'subBaseInfo'
+ ? stationFields
+ : baseInfoFields
+
+ // 先验证当前子标签页的字段
+ baseForm.value?.validateField(currentFields, (isCurrentValid: boolean, currentInvalidFields: any) => {
+ if (!isCurrentValid) {
+ // 当前子标签页验证失败,提示用户
+ console.log('当前子标签页验证失败的字段:', currentInvalidFields);
+ if (subActiveName.value === 'subBaseInfo') {
+ message.info("请完善基本信息");
+ } else {
+ message.info("请完善岗位信息");
+ }
+ setTimeout(() => {
+ canSave.value = true
+ }, 1000)
+ return
+ }
+
+ // 当前子标签页验证通过,继续验证另一个子标签页
+ baseForm.value?.validateField(otherFields, (isOtherValid: boolean, otherInvalidFields: any) => {
+ if (!isOtherValid) {
+ // 另一个子标签页验证失败,跳转到那个子标签页
+ console.log('另一个子标签页验证失败的字段:', otherInvalidFields);
+ if (subActiveName.value === 'subBaseInfo') {
+ subActiveName.value = 'subStation'
+ message.info("基本信息已完善,请完善岗位信息");
+ } else {
+ subActiveName.value = 'subBaseInfo'
+ message.info("岗位信息已完善,请完善基本信息");
+ }
+ setTimeout(() => {
+ canSave.value = true
+ }, 1000)
+ return
+ }
+
+ // 两个子标签页都验证通过,执行保存
addInformation(form).then((response: any) => {
- const data = response.data.data;
+ const data = response.data;
message.success('保存成功')
form.baseInfo.id = data.baseId;
form.professionalStationRelation.id = data.relationId;
getDataList()
- }).catch(()=>{
- });
- } else {
- message.info("请完善基础信息");
- console.log('error submit!!');
- }
+ }).catch(() => {
+ // 错误处理
});
+ setTimeout(() => {
+ canSave.value = true
+ }, 1000)
+ })
+ })
}
-
- if (activeName.value == "seven") {
- stationForm.value?.validate((valid: boolean) => {
- if (valid) {
- addInformation(form).then((response: any) => {
- const data = response.data.data;
- message.success('保存成功')
- form.baseInfo.id = data.baseId;
- form.professionalStationRelation.id = data.relationId;
- getDataList()
- }).catch(()=>{
- });
- } else {
- message.info("请完善岗位信息");
- console.log('error submit!!');
- }
- });
- }
-
- setTimeout(()=>{
- canSave.value = true
- },1000)
}
// getNodeData 方法已移除,如需要请重新实现
// 政治面貌相关
@@ -2532,6 +2712,13 @@
getDicts(religiousBelief).then((response: any) => {
religiousBeliefDic.value = response.data;
}),
+ // 批量获取字典数据
+ getDictsByTypes(['religious_belief', 'heath', 'teacher_cate']).then((response: any) => {
+ religiousBeliefDic.value = response.data.religious_belief;
+ healthList.value = response.data.heath;
+ teacherCateList.value = response.data.teacher_cate;
+
+ }),
// 民族
getNationalList().then((response: any) => {
nationalList.value = response.data;
@@ -2942,7 +3129,16 @@
const handleImportDialog = () => {
importTeacherInfoRef.value?.init()
- }
+ }
+
+ // 身份证号输入限制:只允许数字和X/x,最大长度18
+ const handleIdCardInput = (value: string) => {
+ // 只保留数字和X/x
+ const filtered = value.replace(/[^\dXx]/g, '')
+ if (filtered !== value) {
+ form.baseInfo.idCard = filtered
+ }
+ }
+
diff --git a/src/composables/useTableColumns.ts b/src/composables/useTableColumns.ts
index b0db92a..ae959a5 100644
--- a/src/composables/useTableColumns.ts
+++ b/src/composables/useTableColumns.ts
@@ -76,23 +76,50 @@ export function useTableColumns(
if (store.states && store.states.columns) {
tableColumns = store.states.columns.value || []
+ console.log('[useTableColumns] 从 store.states.columns 获取到列数:', tableColumns.length)
+ console.log('[useTableColumns] store.states.columns 内容:', tableColumns)
} else if (store.columns) {
tableColumns = Array.isArray(store.columns) ? store.columns : (store.columns.value || [])
+ console.log('[useTableColumns] 从 store.columns 获取到列数:', tableColumns.length)
} else if ((table as any).columns) {
tableColumns = Array.isArray((table as any).columns) ? (table as any).columns : ((table as any).columns.value || [])
+ console.log('[useTableColumns] 从 table.columns 获取到列数:', tableColumns.length)
}
if (tableColumns.length > 0) {
- tableColumns.forEach((col: any) => {
- // 跳过序号列和没有 label 的列
- if (!col.label || col.type === 'index') return
+ tableColumns.forEach((col: any, idx: number) => {
+ console.log(`[useTableColumns] store 列 ${idx}:`, {
+ type: col.type,
+ label: col.label,
+ property: col.property,
+ prop: col.prop,
+ fixed: col.fixed,
+ fullCol: col
+ })
+
+ // 跳过序号列
+ if (col.type === 'index' || col.type === 'selection') {
+ console.log(`[useTableColumns] 列 ${idx} 被跳过(类型: ${col.type})`)
+ return
+ }
+
+ // 尝试多种方式获取 label
+ const label = col.label || col.columnKey || col.property || col.prop || ''
+
+ // 如果没有 label,尝试从其他属性推断
+ if (!label) {
+ console.log(`[useTableColumns] 列 ${idx} 没有 label,尝试从其他属性推断`)
+ // 如果还是没有,跳过这一列
+ return
+ }
const config: ColumnConfig = {
prop: col.property || col.prop || '',
- label: col.label || '',
+ label: label,
width: col.width,
minWidth: col.minWidth,
- fixed: col.fixed,
+ // Element Plus 中非固定列的 fixed 通常是 false,这里统一将 false 归一为 undefined
+ fixed: col.fixed ? col.fixed : undefined,
}
// 应用自定义映射
@@ -111,12 +138,16 @@ export function useTableColumns(
}
}
+ console.log(`[useTableColumns] 从 store 提取到列配置:`, config)
extracted.push(config)
})
+ console.log('[useTableColumns] 从 store 总共提取到列数:', extracted.length)
if (extracted.length > 0) {
return extracted
}
+ } else {
+ console.warn('[useTableColumns] store 中没有找到列数据')
}
}
@@ -174,8 +205,45 @@ export function useTableColumns(
}
columnHeaders.forEach((th: HTMLElement, index: number) => {
- const label = th.textContent?.trim() || ''
- console.log(`[useTableColumns] 列 ${index}: label="${label}"`)
+ // 尝试多种方式获取 label 文本
+ // 1. 从 .cell 元素
+ const cell = th.querySelector('.cell') as HTMLElement | null
+ // 2. 从所有可能的文本节点
+ let rawLabel = ''
+
+ if (cell) {
+ rawLabel = cell.innerText || cell.textContent || ''
+ } else {
+ // 尝试从 th 的所有子元素中查找文本
+ const textNodes: string[] = []
+ const walker = document.createTreeWalker(
+ th,
+ NodeFilter.SHOW_TEXT,
+ null
+ )
+ let node: Node | null
+ while ((node = walker.nextNode())) {
+ const text = node.textContent?.trim()
+ if (text) {
+ textNodes.push(text)
+ }
+ }
+ rawLabel = textNodes.join(' ') || th.innerText || th.textContent || ''
+ }
+
+ const label = rawLabel.trim()
+
+ // 调试:打印 th 的完整结构
+ console.log(`[useTableColumns] DOM 列 ${index}:`, {
+ label,
+ rawLabel,
+ thHTML: th.innerHTML.substring(0, 100),
+ hasCell: !!cell,
+ cellText: cell?.innerText || cell?.textContent || '',
+ thInnerText: th.innerText,
+ thTextContent: th.textContent
+ })
+
// 排除序号列和空列
if (!label || label === '序号') {
console.log(`[useTableColumns] 列 ${index} 被跳过(序号列或空列)`)
@@ -234,7 +302,8 @@ export function useTableColumns(
prop: prop || `column_${index}`,
label,
width,
- fixed,
+ // DOM 提取的 fixed 只有 left/right,这里也归一为 undefined 或 'left'/'right'
+ fixed: fixed ? fixed : undefined,
}
console.log(`[useTableColumns] 提取到列配置:`, columnConfig)
extracted.push(columnConfig)
@@ -304,12 +373,13 @@ export function useTableColumns(
// 初始化默认可见列
const initDefaultVisibleColumns = () => {
const defaultHidden = options?.defaultHidden || []
- // 默认显示所有列(除了默认隐藏的列)
+ // 默认显示所有列(除了默认隐藏的列和固定列/alwaysShow列)
+ // 注意:固定列和 alwaysShow 列不需要在 visibleColumns 中,因为它们始终显示
visibleColumns.value = columns.value
.filter(col => {
const key = col.prop || col.label
return !col.alwaysShow &&
- col.fixed === undefined &&
+ !col.fixed &&
!defaultHidden.includes(key)
})
.map(col => col.prop || col.label)
@@ -317,7 +387,7 @@ export function useTableColumns(
// 如果所有列都被隐藏了,至少显示所有非固定列
if (visibleColumns.value.length === 0 && columns.value.length > 0) {
visibleColumns.value = columns.value
- .filter(col => !col.alwaysShow && col.fixed === undefined)
+ .filter(col => !col.alwaysShow && !col.fixed)
.map(col => col.prop || col.label)
}
}
@@ -339,7 +409,7 @@ export function useTableColumns(
}
// 固定列和始终显示的列始终显示
- if (column.fixed !== undefined || column.alwaysShow) {
+ if (column.fixed || column.alwaysShow) {
return true
}
diff --git a/src/views/professional/stayschool/outercompany/index.vue b/src/views/professional/outercompany/index.vue
similarity index 99%
rename from src/views/professional/stayschool/outercompany/index.vue
rename to src/views/professional/outercompany/index.vue
index d1e215e..e8f6424 100755
--- a/src/views/professional/stayschool/outercompany/index.vue
+++ b/src/views/professional/outercompany/index.vue
@@ -153,7 +153,7 @@ import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message'
-import { fetchList, addObj, putObj, delObj, getObj } from '/@/api/professional/outercompany'
+import { fetchList, addObj, putObj, delObj, getObj } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/stayschool/outercompany/indexSecond.vue b/src/views/professional/outercompany/indexSecond.vue
similarity index 99%
rename from src/views/professional/stayschool/outercompany/indexSecond.vue
rename to src/views/professional/outercompany/indexSecond.vue
index 49c0cfc..625ef2e 100755
--- a/src/views/professional/stayschool/outercompany/indexSecond.vue
+++ b/src/views/professional/outercompany/indexSecond.vue
@@ -153,7 +153,7 @@ import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage } from '/@/hooks/message'
import { useMessageBox } from '/@/hooks/message'
-import { fetchList, addObj, putObj, delObj, getObj } from '/@/api/professional/outercompany'
+import { fetchList, addObj, putObj, delObj, getObj } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/stayschool/outercompany/indexTrain.vue b/src/views/professional/outercompany/indexTrain.vue
similarity index 98%
rename from src/views/professional/stayschool/outercompany/indexTrain.vue
rename to src/views/professional/outercompany/indexTrain.vue
index 3e3a6e5..e98ec87 100755
--- a/src/views/professional/stayschool/outercompany/indexTrain.vue
+++ b/src/views/professional/outercompany/indexTrain.vue
@@ -100,7 +100,7 @@ import { ref, reactive, computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table'
-import { fetchList } from '/@/api/professional/outercompany'
+import { fetchList } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/stayschool/outercompanyemployee/index.vue b/src/views/professional/outercompanyemployee/index.vue
similarity index 99%
rename from src/views/professional/stayschool/outercompanyemployee/index.vue
rename to src/views/professional/outercompanyemployee/index.vue
index 968727d..ec99152 100755
--- a/src/views/professional/stayschool/outercompanyemployee/index.vue
+++ b/src/views/professional/outercompanyemployee/index.vue
@@ -405,8 +405,8 @@ import {
delObj,
batchDel,
resetPassWord
-} from '/@/api/professional/outercompanyemployee'
-import { getList as getCompanyList } from '/@/api/professional/outercompany'
+} from '/@/api/professional/stayschool/outercompanyemployee'
+import { getList as getCompanyList } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/stayschool/outercompanyemployee/indexSecond.vue b/src/views/professional/outercompanyemployee/indexSecond.vue
similarity index 99%
rename from src/views/professional/stayschool/outercompanyemployee/indexSecond.vue
rename to src/views/professional/outercompanyemployee/indexSecond.vue
index 3fc8ffd..54d0374 100755
--- a/src/views/professional/stayschool/outercompanyemployee/indexSecond.vue
+++ b/src/views/professional/outercompanyemployee/indexSecond.vue
@@ -406,8 +406,8 @@ import {
delObj,
batchDel,
resetPassWord
-} from '/@/api/professional/outercompanyemployee'
-import { getList as getCompanyList } from '/@/api/professional/outercompany'
+} from '/@/api/professional/stayschool/outercompanyemployee'
+import { getList as getCompanyList } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/stayschool/outercompanyemployee/indexTrain.vue b/src/views/professional/outercompanyemployee/indexTrain.vue
similarity index 99%
rename from src/views/professional/stayschool/outercompanyemployee/indexTrain.vue
rename to src/views/professional/outercompanyemployee/indexTrain.vue
index 125ebf1..b26bc1e 100755
--- a/src/views/professional/stayschool/outercompanyemployee/indexTrain.vue
+++ b/src/views/professional/outercompanyemployee/indexTrain.vue
@@ -385,8 +385,8 @@ import {
delObj,
batchDel,
resetPassWord
-} from '/@/api/professional/outercompanyemployee'
-import { getList as getCompanyList } from '/@/api/professional/outercompany'
+} from '/@/api/professional/stayschool/outercompanyemployee'
+import { getList as getCompanyList } from '/@/api/professional/stayschool/outercompany'
// 使用 Pinia store
const userInfoStore = useUserInfo()
diff --git a/src/views/professional/professionalqualificationrelation/form.vue b/src/views/professional/professionalqualificationrelation/form.vue
index 0ea73b5..8e054e8 100644
--- a/src/views/professional/professionalqualificationrelation/form.vue
+++ b/src/views/professional/professionalqualificationrelation/form.vue
@@ -96,8 +96,8 @@
import { ref, reactive, computed } from 'vue'
import { Session } from '/@/utils/storage'
import { useMessage } from '/@/hooks/message'
-import { getMyTeacherNo, updateOtherInfo } from '/@/api/professional/professionaluser/teacherbase'
-import { putObj } from '/@/api/professional/professionaluser/professionalqualificationrelation'
+import { getMyTeacherNo } from '/@/api/professional/professionaluser/teacherbase'
+import { addObj } from '/@/api/professional/professionaluser/professionalqualificationrelation'
import { checkLocked } from '/@/api/professional/professionalstatuslock'
import { getLevelList } from '/@/api/professional/rsbase/professionalqualificationconfig'
import { getWorkTypeList } from '/@/api/professional/rsbase/professionalworktype'
@@ -284,34 +284,26 @@ const dialogSubmit = async () => {
if (valid) {
submitLoading.value = true
try {
+ // 统一使用 addObj 接口(新增和编辑都使用同一个接口)
+ // 确保 evidenceA 或 materialA 有值
+ if (!dataForm.evidenceA && dataForm.materialA) {
+ dataForm.evidenceA = dataForm.materialA
+ }
+
if (dataForm.id) {
- // 编辑:使用 putObj 接口(管理员编辑)
+ // 编辑模式
dataForm.state = '0'
- await putObj(dataForm)
+ await addObj(dataForm)
message.success("修改成功")
} else {
- // 新增:使用 updateOtherInfo 接口(与 MultiDialog 保持一致)
- const submitData: any = {
- type: 3, // 职业资格类型
- teacherNo: dataForm.teacherNo,
- worker: dataForm.worker,
- qualificationConfigId: dataForm.qualificationConfigId,
- certificateTime: dataForm.certificateTime,
- certificateNumber: dataForm.certificateNumber,
- mateA: dataForm.evidenceA || dataForm.materialA // 使用 mateA 字段(与 MultiDialog 一致)
- }
-
- const res = await updateOtherInfo(submitData)
- if (res.data == '-1') {
- message.warning("当前不允许提交")
- } else {
- message.success("提交成功")
- }
+ // 新增模式
+ await addObj(dataForm)
+ message.success("提交成功")
}
dialogVisible.value = false
emit('refreshData')
} catch (error: any) {
- message.error(error?.msg || '操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
} finally {
submitLoading.value = false
}
diff --git a/src/views/professional/professionalteacheracademicrelation/form.vue b/src/views/professional/professionalteacheracademicrelation/form.vue
index 56d9a82..f1b0421 100644
--- a/src/views/professional/professionalteacheracademicrelation/form.vue
+++ b/src/views/professional/professionalteacheracademicrelation/form.vue
@@ -147,8 +147,8 @@
import { ref, reactive, computed } from 'vue'
import { Session } from '/@/utils/storage'
import { useMessage } from '/@/hooks/message'
-import { getMyTeacherNo, updateOtherInfo } from '/@/api/professional/professionaluser/teacherbase'
-import { putObj } from '/@/api/professional/professionaluser/professionalteacheracademicrelation'
+import { getMyTeacherNo } from '/@/api/professional/professionaluser/teacherbase'
+import { addObj } from '/@/api/professional/professionaluser/professionalteacheracademicrelation'
import { getAllTypeList } from '/@/api/professional/rsbase/professionalacademiceducationtypeconfig'
import { getQualificationList } from '/@/api/professional/rsbase/academicqualificationsconfig'
import { getDegreeList } from '/@/api/professional/rsbase/professionalacademicdegreeconfig'
@@ -370,42 +370,30 @@ const dialogSubmit = async () => {
if (valid) {
submitLoading.value = true
try {
+ // 统一使用 addObj 接口(新增和编辑都使用同一个接口)
+ // 确保 qualificationImg 或 materialA 有值
+ if (!dataForm.qualificationImg && dataForm.materialA) {
+ dataForm.qualificationImg = dataForm.materialA
+ }
+ // 确保 degreeImg 或 materialB 有值
+ if (!dataForm.degreeImg && dataForm.materialB) {
+ dataForm.degreeImg = dataForm.materialB
+ }
+
if (dataForm.id) {
- // 编辑:使用 putObj 接口(管理员编辑)
+ // 编辑模式
dataForm.state = '0'
- await putObj(dataForm)
+ await addObj(dataForm)
message.success("修改成功")
} else {
- // 新增:使用 updateOtherInfo 接口(与 MultiDialog 保持一致)
- // 注意:MultiDialog 中 type 字段在提交时会被设置为 val(1),但表单中也有 type 字段用于教育类型
- // 这里直接使用 dataForm 的所有字段,后端应该能够处理
- const submitData: any = {
- type: 1, // 学历更新类型(固定值,会覆盖表单中的 type)
- teacherNo: dataForm.teacherNo,
- graduateTime: dataForm.graduateTime,
- qualificationConfigId: dataForm.qualificationConfigId,
- degreeConfigId: dataForm.degreeConfigId,
- graduateSchool: dataForm.graduateSchool,
- major: dataForm.major,
- certificateNumber: dataForm.certificateNumber,
- mateA: dataForm.qualificationImg || dataForm.materialA, // 学历证书
- mateB: dataForm.degreeImg || dataForm.materialB // 学位证书
- }
-
- // 注意:MultiDialog 中教育类型字段也是 type,但在提交时会被覆盖为 val(1)
- // 如果后端需要教育类型,可能需要单独传递,这里先不传,保持与 MultiDialog 一致
-
- const res = await updateOtherInfo(submitData)
- if (res.data == '-1') {
- message.warning("当前不允许提交")
- } else {
- message.success("提交成功")
- }
+ // 新增模式
+ await addObj(dataForm)
+ message.success("提交成功")
}
dialogVisible.value = false
emit('refreshData')
} catch (error: any) {
- message.error(error?.msg || '操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
} finally {
submitLoading.value = false
}
diff --git a/src/views/professional/professionalteachercertificaterelation/form.vue b/src/views/professional/professionalteachercertificaterelation/form.vue
index f15932e..73c7f61 100644
--- a/src/views/professional/professionalteachercertificaterelation/form.vue
+++ b/src/views/professional/professionalteachercertificaterelation/form.vue
@@ -97,8 +97,8 @@
import { ref, reactive, computed } from 'vue'
import { Session } from '/@/utils/storage'
import { useMessage } from '/@/hooks/message'
-import { getMyTeacherNo, updateOtherInfo } from '/@/api/professional/professionaluser/teacherbase'
-import { putObj } from '/@/api/professional/professionaluser/professionalteachercertificaterelation'
+import { getMyTeacherNo } from '/@/api/professional/professionaluser/teacherbase'
+import { addObj } from '/@/api/professional/professionaluser/professionalteachercertificaterelation'
import { getTeacherCertificateList } from '/@/api/professional/rsbase/professionalteachercertificateconf'
import { checkLocked } from '/@/api/professional/professionalstatuslock'
@@ -280,33 +280,30 @@ const dialogSubmit = async () => {
if (valid) {
submitLoading.value = true
try {
+ // 统一使用 addObj 接口(新增和编辑都使用同一个接口)
+ // 确保 evidenceA 或 materialA 有值
+ if (!dataForm.evidenceA && dataForm.materialA) {
+ dataForm.evidenceA = dataForm.materialA
+ }
+ // 确保 evidenceB 或 materialB 有值
+ if (!dataForm.evidenceB && dataForm.materialB) {
+ dataForm.evidenceB = dataForm.materialB
+ }
+
if (dataForm.id) {
- // 编辑:使用 putObj 接口(管理员编辑)
+ // 编辑模式
dataForm.state = '0'
- await putObj(dataForm)
+ await addObj(dataForm)
message.success("修改成功")
} else {
- // 新增:使用 updateOtherInfo 接口(与 MultiDialog 保持一致)
- // 注意:MultiDialog 的 type=0 表单只有 certificateConfId 和 certificateNumber,没有 certificateTime
- const submitData: any = {
- type: 0, // 教师资格证类型
- teacherNo: dataForm.teacherNo,
- certificateConfId: dataForm.certificateConfId,
- certificateNumber: dataForm.certificateNumber,
- mateA: dataForm.evidenceA || dataForm.materialA // 使用 mateA 字段(与 MultiDialog 一致)
- }
-
- const res = await updateOtherInfo(submitData)
- if (res.data == '-1') {
- message.warning("当前不允许提交")
- } else {
- message.success("提交成功")
- }
+ // 新增模式
+ await addObj(dataForm)
+ message.success("提交成功")
}
dialogVisible.value = false
emit('refreshData')
} catch (error: any) {
- message.error(error?.msg || '操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
} finally {
submitLoading.value = false
}
diff --git a/src/views/professional/professionalteacherhonor/form.vue b/src/views/professional/professionalteacherhonor/form.vue
index 5e0d6d0..09dd438 100644
--- a/src/views/professional/professionalteacherhonor/form.vue
+++ b/src/views/professional/professionalteacherhonor/form.vue
@@ -64,8 +64,8 @@
import { ref, reactive, computed } from 'vue'
import { Session } from '/@/utils/storage'
import { useMessage } from '/@/hooks/message'
-import { getMyTeacherNo, updateOtherInfo } from '/@/api/professional/professionaluser/teacherbase'
-import { putObj } from '/@/api/professional/professionaluser/professionalteacherhonor'
+import { getMyTeacherNo } from '/@/api/professional/professionaluser/teacherbase'
+import { addObj } from '/@/api/professional/professionaluser/professionalteacherhonor'
import { checkLocked } from '/@/api/professional/professionalstatuslock'
// Emits
@@ -215,33 +215,26 @@ const dialogSubmit = async () => {
if (valid) {
submitLoading.value = true
try {
+ // 统一使用 addObj 接口(新增和编辑都使用同一个接口)
+ // 确保 attachment 或 materialA 有值
+ if (!dataForm.attachment && dataForm.materialA) {
+ dataForm.attachment = dataForm.materialA
+ }
+
if (dataForm.id) {
- // 编辑:使用 putObj 接口(管理员编辑)
+ // 编辑模式
dataForm.state = '0'
- await putObj(dataForm)
+ await addObj(dataForm)
message.success("修改成功")
} else {
- // 新增:使用 updateOtherInfo 接口(与 MultiDialog 保持一致)
- const submitData: any = {
- type: 4, // 综合表彰类型
- teacherNo: dataForm.teacherNo,
- honor: dataForm.honor,
- honorCompany: dataForm.honorCompany,
- year: dataForm.year,
- mateA: dataForm.attachment || dataForm.materialA // 使用 mateA 字段(与 MultiDialog 一致)
- }
-
- const res = await updateOtherInfo(submitData)
- if (res.data == '-1') {
- message.warning("当前不允许提交")
- } else {
- message.success("提交成功")
- }
+ // 新增模式
+ await addObj(dataForm)
+ message.success("提交成功")
}
dialogVisible.value = false
emit('refreshData')
} catch (error: any) {
- message.error(error?.msg || '操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
} finally {
submitLoading.value = false
}
diff --git a/src/views/professional/professionaltitlerelation/form.vue b/src/views/professional/professionaltitlerelation/form.vue
index cd8ba39..19c1123 100644
--- a/src/views/professional/professionaltitlerelation/form.vue
+++ b/src/views/professional/professionaltitlerelation/form.vue
@@ -229,7 +229,7 @@ const openDialog = async (row?: any) => {
return
}
} catch (error) {
- message.error('操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
return
}
}
@@ -306,7 +306,7 @@ const dialogSubmit = async () => {
dialogVisible.value = false
emit('refreshData')
} catch (error: any) {
- message.error(error?.msg || '操作失败')
+ // 错误处理已在数据请求层统一处理,此处不需要提示
} finally {
submitLoading.value = false
}
diff --git a/src/views/professional/salaries/professionalyearbounds/index.vue b/src/views/professional/professionalyearbounds/index.vue
similarity index 100%
rename from src/views/professional/salaries/professionalyearbounds/index.vue
rename to src/views/professional/professionalyearbounds/index.vue
diff --git a/src/views/professional/salaries/salaryexportrecord/index.vue b/src/views/professional/salaryexportrecord/index.vue
similarity index 100%
rename from src/views/professional/salaries/salaryexportrecord/index.vue
rename to src/views/professional/salaryexportrecord/index.vue
diff --git a/src/views/professional/salaries/teacherawardtax/importAwardTax.vue b/src/views/professional/teacherawardtax/importAwardTax.vue
similarity index 100%
rename from src/views/professional/salaries/teacherawardtax/importAwardTax.vue
rename to src/views/professional/teacherawardtax/importAwardTax.vue
diff --git a/src/views/professional/salaries/teacherawardtax/index.vue b/src/views/professional/teacherawardtax/index.vue
similarity index 100%
rename from src/views/professional/salaries/teacherawardtax/index.vue
rename to src/views/professional/teacherawardtax/index.vue
diff --git a/src/views/professional/teacherbase/index.vue b/src/views/professional/teacherbase/index.vue
index 473e554..217fb19 100644
--- a/src/views/professional/teacherbase/index.vue
+++ b/src/views/professional/teacherbase/index.vue
@@ -369,24 +369,26 @@