|
|
@@ -137,66 +137,96 @@
|
|
|
</el-row>
|
|
|
</el-form>
|
|
|
|
|
|
- <!-- 部门信息:非 tab,直接置于组织表单底部,以分区样式区分 -->
|
|
|
+ <!-- 部门信息:tab 项可新增/删除,至少保留一项 -->
|
|
|
<template v-if="showDepartment">
|
|
|
- <div class="section-title">
|
|
|
+ <div class="section-title dept-section-title">
|
|
|
<span><i class="el-icon-s-grid"></i></span>
|
|
|
<div>
|
|
|
- <strong>部门信息</strong>
|
|
|
- <small>配置部门岗位、岗位层级与编制人数,保存后同步部门岗位关联</small>
|
|
|
+ <strong>岗位信息</strong>
|
|
|
+ <small>配置岗位、岗位层级与编制人数,保存后同步岗位关联</small>
|
|
|
</div>
|
|
|
+ <el-button
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ icon="el-icon-plus"
|
|
|
+ class="dept-section-add"
|
|
|
+ @click="addDeptTab"
|
|
|
+ >
|
|
|
+ 添加岗位信息
|
|
|
+ </el-button>
|
|
|
</div>
|
|
|
- <el-form ref="deptForm" :model="deptForm" label-position="top">
|
|
|
- <el-row :gutter="20">
|
|
|
- <el-col :xs="24" :sm="12">
|
|
|
- <el-form-item label="岗位名称" prop="positionId">
|
|
|
- <el-select
|
|
|
- v-model="deptForm.positionId"
|
|
|
- filterable
|
|
|
- clearable
|
|
|
- placeholder="请选择岗位"
|
|
|
- class="full-width"
|
|
|
- @change="onPositionChange"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="position in positions"
|
|
|
- :key="position.id"
|
|
|
- :label="position.positionName"
|
|
|
- :value="position.id"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :xs="24" :sm="12">
|
|
|
- <el-form-item label="岗位层级" prop="positionLevel">
|
|
|
- <el-select
|
|
|
- v-model="deptForm.positionLevel"
|
|
|
- clearable
|
|
|
- placeholder="请选择岗位层级"
|
|
|
- class="full-width"
|
|
|
- >
|
|
|
- <el-option
|
|
|
- v-for="level in levelOptions"
|
|
|
- :key="level"
|
|
|
- :label="level"
|
|
|
- :value="level"
|
|
|
- />
|
|
|
- </el-select>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :xs="24" :sm="12">
|
|
|
- <el-form-item label="编制人数" prop="establishmentCount">
|
|
|
- <el-input-number
|
|
|
- v-model="deptForm.establishmentCount"
|
|
|
- :min="0"
|
|
|
- :max="9999"
|
|
|
- controls-position="right"
|
|
|
- class="full-width"
|
|
|
- />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
- </el-form>
|
|
|
+ <el-tabs
|
|
|
+ v-model="activeDeptIndex"
|
|
|
+ class="dept-tabs"
|
|
|
+ >
|
|
|
+ <el-tab-pane
|
|
|
+ v-for="(item, index) in deptFormList"
|
|
|
+ :key="index"
|
|
|
+ :name="String(index)"
|
|
|
+ >
|
|
|
+ <template slot="label">
|
|
|
+ <span>{{ deptTabLabel(index) }}</span>
|
|
|
+ <i
|
|
|
+ v-if="deptFormList.length > 1"
|
|
|
+ class="el-icon-close dept-tab-close"
|
|
|
+ @click.stop="removeDeptTab(index)"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ <el-form :model="item" label-position="top">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :xs="24" :sm="12">
|
|
|
+ <el-form-item label="岗位名称">
|
|
|
+ <el-select
|
|
|
+ v-model="item.positionId"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ placeholder="请选择岗位"
|
|
|
+ class="full-width"
|
|
|
+ @change="onPositionChange(index)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="position in positions"
|
|
|
+ :key="position.id"
|
|
|
+ :label="position.positionName"
|
|
|
+ :value="position.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12">
|
|
|
+ <el-form-item label="岗位层级">
|
|
|
+ <el-select
|
|
|
+ v-model="item.positionLevel"
|
|
|
+ clearable
|
|
|
+ placeholder="请选择岗位层级"
|
|
|
+ class="full-width"
|
|
|
+ @change="onLevelChange(index)"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="level in getLevelOptions(index)"
|
|
|
+ :key="level"
|
|
|
+ :label="level"
|
|
|
+ :value="level"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :xs="24" :sm="12">
|
|
|
+ <el-form-item label="编制人数">
|
|
|
+ <el-input-number
|
|
|
+ v-model="item.establishmentCount"
|
|
|
+ :min="0"
|
|
|
+ :max="9999"
|
|
|
+ controls-position="right"
|
|
|
+ class="full-width"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
</template>
|
|
|
</el-tab-pane>
|
|
|
|
|
|
@@ -341,6 +371,8 @@ import {
|
|
|
getOrganization,
|
|
|
getOrganizationCode,
|
|
|
listOrganizations,
|
|
|
+ pageDepartmentPosition,
|
|
|
+ saveBatchDepartmentPosition,
|
|
|
updateDepartmentPosition,
|
|
|
updateOrganization,
|
|
|
} from "@/api/organization";
|
|
|
@@ -362,6 +394,7 @@ const defaultForm = () => ({
|
|
|
});
|
|
|
|
|
|
const defaultDeptForm = () => ({
|
|
|
+ id: null,
|
|
|
positionId: null,
|
|
|
positionLevel: "",
|
|
|
establishmentCount: 0,
|
|
|
@@ -398,7 +431,9 @@ export default {
|
|
|
return {
|
|
|
form: defaultForm(),
|
|
|
enterprise: defaultEnterprise(),
|
|
|
- deptForm: defaultDeptForm(),
|
|
|
+ // 部门信息:支持新增/删除 tab 项,至少保留一项
|
|
|
+ deptFormList: [defaultDeptForm()],
|
|
|
+ activeDeptIndex: "0",
|
|
|
saving: false,
|
|
|
loadingDetail: false,
|
|
|
activeTab: "organization",
|
|
|
@@ -418,13 +453,6 @@ export default {
|
|
|
showDepartment() {
|
|
|
return String(this.form.type) === "30";
|
|
|
},
|
|
|
- // 岗位层级:随所选岗位联动(取岗位的 positionLevels)
|
|
|
- levelOptions() {
|
|
|
- const position = this.positions.find(
|
|
|
- (item) => String(item.id) === String(this.deptForm.positionId),
|
|
|
- );
|
|
|
- return position?.positionLevels || [];
|
|
|
- },
|
|
|
firstManagerName() {
|
|
|
const user = this.form.managerFirst?.[0];
|
|
|
if (!user) return '';
|
|
|
@@ -484,7 +512,8 @@ export default {
|
|
|
this.activeTab = "organization";
|
|
|
this.form = defaultForm();
|
|
|
this.enterprise = defaultEnterprise();
|
|
|
- this.deptForm = defaultDeptForm();
|
|
|
+ this.deptFormList = [defaultDeptForm()];
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
this.form.parentId = this.parentId || null;
|
|
|
this.loadPositions();
|
|
|
if (this.isUpdate) {
|
|
|
@@ -505,6 +534,14 @@ export default {
|
|
|
? detail.enterprise.businessLicenseFile
|
|
|
: [],
|
|
|
};
|
|
|
+ // 部门类型:加载已有的部门岗位编制
|
|
|
+ if (String(this.form.type) === "30") {
|
|
|
+ console.log(detail,'detail')
|
|
|
+ await this.loadDepartmentPositions(detail.id);
|
|
|
+ } else {
|
|
|
+ this.deptFormList = [defaultDeptForm()];
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
this.$message.error(error.message || "组织详情加载失败");
|
|
|
} finally {
|
|
|
@@ -558,26 +595,121 @@ export default {
|
|
|
this.positions = [];
|
|
|
}
|
|
|
},
|
|
|
+ // 加载部门已有的岗位编制(编辑时回填 deptFormList)
|
|
|
+ async loadDepartmentPositions(deptId) {
|
|
|
+ try {
|
|
|
+ const result = await pageDepartmentPosition({
|
|
|
+ deptId,
|
|
|
+ pageNum: 1,
|
|
|
+ size: 1000,
|
|
|
+ sortName: "createTime",
|
|
|
+ orderBy: "ascending",
|
|
|
+ });
|
|
|
+ const list = Array.isArray(result?.list) ? result.list : [];
|
|
|
+ if (list.length === 0) {
|
|
|
+ this.deptFormList = [defaultDeptForm()];
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.deptFormList = list.map((item) => ({
|
|
|
+ id: item.id ?? null,
|
|
|
+ positionId: item.positionId ?? null,
|
|
|
+ positionLevel: item.positionLevel || "",
|
|
|
+ establishmentCount: Number(item.establishmentCount) || 0,
|
|
|
+ }));
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
+ } catch (error) {
|
|
|
+ this.deptFormList = [defaultDeptForm()];
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
+ this.$message.error(error.message || "部门岗位编制加载失败");
|
|
|
+ }
|
|
|
+ },
|
|
|
// 切换岗位时清空已选层级(联动)
|
|
|
- onPositionChange() {
|
|
|
- this.deptForm.positionLevel = "";
|
|
|
+ onPositionChange(index) {
|
|
|
+ if (this.deptFormList[index]) {
|
|
|
+ this.deptFormList[index].positionLevel = "";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 切换岗位层级时校验:同岗位下层级不能重复
|
|
|
+ onLevelChange(index) {
|
|
|
+ const item = this.deptFormList[index];
|
|
|
+ if (!item || !item.positionId || !item.positionLevel) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const duplicate = this.deptFormList.some((other, idx) => {
|
|
|
+ if (idx === index) return false;
|
|
|
+ return (
|
|
|
+ String(other.positionId) === String(item.positionId) &&
|
|
|
+ String(other.positionLevel) === String(item.positionLevel)
|
|
|
+ );
|
|
|
+ });
|
|
|
+ if (duplicate) {
|
|
|
+ this.$message.warning("同一岗位下岗位层级不能重复,请重新选择");
|
|
|
+ item.positionLevel = "";
|
|
|
+ }
|
|
|
},
|
|
|
positionLabel(positionId) {
|
|
|
return this.positions.find((item) => String(item.id) === String(positionId))
|
|
|
?.positionName || "";
|
|
|
},
|
|
|
+ // 新增一个部门信息 tab 项
|
|
|
+ addDeptTab() {
|
|
|
+ this.deptFormList.push(defaultDeptForm());
|
|
|
+ this.activeDeptIndex = String(this.deptFormList.length - 1);
|
|
|
+ },
|
|
|
+ // 删除指定 tab 项(至少保留一项)
|
|
|
+ removeDeptTab(index) {
|
|
|
+ if (this.deptFormList.length <= 1) {
|
|
|
+ this.$message.warning("部门信息至少保留一项");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.deptFormList.splice(index, 1);
|
|
|
+ if (
|
|
|
+ Number(this.activeDeptIndex) >= this.deptFormList.length
|
|
|
+ ) {
|
|
|
+ this.activeDeptIndex = String(this.deptFormList.length - 1);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // tab 标题:已选岗位则显示岗位名,否则按序号显示
|
|
|
+ deptTabLabel(index) {
|
|
|
+ const item = this.deptFormList[index];
|
|
|
+ if (item && item.positionId) {
|
|
|
+ return this.positionLabel(item.positionId) || `岗位信息 ${index + 1}`;
|
|
|
+ }
|
|
|
+ return `岗位信息 ${index + 1}`;
|
|
|
+ },
|
|
|
+ // 岗位层级:随所选岗位联动(取岗位的 positionLevels)
|
|
|
+ getLevelOptions(index) {
|
|
|
+ const item = this.deptFormList[index];
|
|
|
+ if (!item) return [];
|
|
|
+ const position = this.positions.find(
|
|
|
+ (pos) => String(pos.id) === String(item.positionId),
|
|
|
+ );
|
|
|
+ return position?.positionLevels || [];
|
|
|
+ },
|
|
|
validateDepartment() {
|
|
|
if (!this.showDepartment) {
|
|
|
return Promise.resolve(true);
|
|
|
}
|
|
|
- if (!this.deptForm.positionId) {
|
|
|
- this.$message.warning("部门类型请选择岗位名称");
|
|
|
- return Promise.resolve(false);
|
|
|
+ // 同岗位下岗位层级不能重复
|
|
|
+ const seen = new Set();
|
|
|
+ for (const item of this.deptFormList) {
|
|
|
+ if (item && item.positionId && item.positionLevel) {
|
|
|
+ const key = `${item.positionId}__${item.positionLevel}`;
|
|
|
+ if (seen.has(key)) {
|
|
|
+ this.$message.warning("同一岗位下岗位层级不能重复");
|
|
|
+ return Promise.resolve(false);
|
|
|
+ }
|
|
|
+ seen.add(key);
|
|
|
+ }
|
|
|
}
|
|
|
return Promise.resolve(true);
|
|
|
},
|
|
|
- // 保存部门岗位关联(PUT /fm/tmaindepartmentposition/updateBatch)
|
|
|
- async saveDepartmentPosition(payload, result) {
|
|
|
+ // 保存部门岗位关联
|
|
|
+ // 新增组织(isCreate=true)→ 全部走 saveBatch
|
|
|
+ // 更新组织(isCreate=false)→ 按是否有 id 拆分:
|
|
|
+ // 有 id 的项 → updateBatch;新增的 tab(无 id)→ saveBatch
|
|
|
+ async saveDepartmentPosition(payload, result, isCreate) {
|
|
|
let deptId = payload.id || this.data?.id;
|
|
|
if (!deptId && result && typeof result === "object") {
|
|
|
deptId = result.id;
|
|
|
@@ -598,18 +730,42 @@ export default {
|
|
|
this.$message.warning("组织已保存,但未能获取组织ID,部门岗位编制未保存");
|
|
|
return;
|
|
|
}
|
|
|
- const position = this.positions.find(
|
|
|
- (item) => String(item.id) === String(this.deptForm.positionId),
|
|
|
- );
|
|
|
- await updateDepartmentPosition([
|
|
|
- {
|
|
|
+ const buildItem = (item) => {
|
|
|
+ const position = this.positions.find(
|
|
|
+ (pos) => String(pos.id) === String(item.positionId),
|
|
|
+ );
|
|
|
+ const base = {
|
|
|
deptId,
|
|
|
- positionId: this.deptForm.positionId,
|
|
|
- positionLevel: this.deptForm.positionLevel || position?.positionLevels?.[0] || "",
|
|
|
+ positionId: item.positionId,
|
|
|
+ positionLevel:
|
|
|
+ item.positionLevel || position?.positionLevels?.[0] || "",
|
|
|
positionName: position?.positionName || "",
|
|
|
- establishmentCount: Number(this.deptForm.establishmentCount) || 0,
|
|
|
- },
|
|
|
- ]);
|
|
|
+ establishmentCount: Number(item.establishmentCount) || 0,
|
|
|
+ };
|
|
|
+ // updateBatch 需要主键 id
|
|
|
+ if (item.id) {
|
|
|
+ base.id = item.id;
|
|
|
+ }
|
|
|
+ return base;
|
|
|
+ };
|
|
|
+ const items = (this.deptFormList || [])
|
|
|
+ .filter((item) => item && item.positionId)
|
|
|
+ .map(buildItem);
|
|
|
+ if (items.length === 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (isCreate) {
|
|
|
+ await saveBatchDepartmentPosition(items);
|
|
|
+ } else {
|
|
|
+ const existing = items.filter((item) => item.id);
|
|
|
+ const fresh = items.filter((item) => !item.id);
|
|
|
+ if (existing.length > 0) {
|
|
|
+ await updateDepartmentPosition(existing);
|
|
|
+ }
|
|
|
+ if (fresh.length > 0) {
|
|
|
+ await saveBatchDepartmentPosition(fresh);
|
|
|
+ }
|
|
|
+ }
|
|
|
this.$message.success("部门岗位编制已保存");
|
|
|
},
|
|
|
beforeLicenseUpload(file) {
|
|
|
@@ -701,9 +857,17 @@ export default {
|
|
|
: result?.message || "保存成功",
|
|
|
);
|
|
|
// 部门类型:同步保存部门岗位关联(编制人数)
|
|
|
- if (this.showDepartment && this.deptForm.positionId) {
|
|
|
+ if (
|
|
|
+ this.showDepartment &&
|
|
|
+ this.deptFormList.some((item) => item.positionId)
|
|
|
+ ) {
|
|
|
try {
|
|
|
- await this.saveDepartmentPosition(payload, result);
|
|
|
+ // 新增组织走 saveBatch,更新组织走 updateBatch
|
|
|
+ await this.saveDepartmentPosition(
|
|
|
+ payload,
|
|
|
+ result,
|
|
|
+ !this.isUpdate,
|
|
|
+ );
|
|
|
} catch (error) {
|
|
|
this.$message.warning(
|
|
|
"组织已保存,但部门岗位编制保存失败:" +
|
|
|
@@ -723,7 +887,8 @@ export default {
|
|
|
reset() {
|
|
|
this.form = defaultForm();
|
|
|
this.enterprise = defaultEnterprise();
|
|
|
- this.deptForm = defaultDeptForm();
|
|
|
+ this.deptFormList = [defaultDeptForm()];
|
|
|
+ this.activeDeptIndex = "0";
|
|
|
this.activeTab = "organization";
|
|
|
this.parentCheckedKeys = [];
|
|
|
this.$refs.form?.clearValidate();
|