|
@@ -308,23 +308,7 @@
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="岗位性质" min-width="140" align="center">
|
|
<el-table-column label="岗位性质" min-width="140" align="center">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <el-select
|
|
|
|
|
- v-if="!row.id"
|
|
|
|
|
- v-model="row.positionType"
|
|
|
|
|
- filterable
|
|
|
|
|
- clearable
|
|
|
|
|
- placeholder="请选择"
|
|
|
|
|
- style="width: 100%"
|
|
|
|
|
- @change="onDeptPositionTypeChange(row)"
|
|
|
|
|
- >
|
|
|
|
|
- <el-option
|
|
|
|
|
- v-for="item in positionNatureOptions"
|
|
|
|
|
- :key="item.id"
|
|
|
|
|
- :label="item.name"
|
|
|
|
|
- :value="item.id"
|
|
|
|
|
- />
|
|
|
|
|
- </el-select>
|
|
|
|
|
- <span v-else>{{ row.positionTypeName }}</span>
|
|
|
|
|
|
|
+ <span>{{ row.positionTypeName || '-' }}</span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column label="编制人数" min-width="120" align="center">
|
|
<el-table-column label="编制人数" min-width="120" align="center">
|
|
@@ -335,6 +319,7 @@
|
|
|
:precision="0"
|
|
:precision="0"
|
|
|
controls-position="right"
|
|
controls-position="right"
|
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
|
|
+ @change="onDeptEstablishmentCountChange(row)"
|
|
|
/>
|
|
/>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
@@ -678,34 +663,30 @@
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
buildDepartmentPositionPayload() {
|
|
buildDepartmentPositionPayload() {
|
|
|
- if (!this.form.id) {
|
|
|
|
|
- return [];
|
|
|
|
|
- }
|
|
|
|
|
const rows = [];
|
|
const rows = [];
|
|
|
for (const row of this.departmentPositionList) {
|
|
for (const row of this.departmentPositionList) {
|
|
|
const isNew = !row.id;
|
|
const isNew = !row.id;
|
|
|
- const emptyNew =
|
|
|
|
|
- isNew &&
|
|
|
|
|
- !row.positionId &&
|
|
|
|
|
- !row.positionLevelId &&
|
|
|
|
|
- (row.establishmentCount === undefined ||
|
|
|
|
|
- row.establishmentCount === null ||
|
|
|
|
|
- row.establishmentCount === '');
|
|
|
|
|
- if (emptyNew) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const rowNo = this.departmentPositionList.indexOf(row) + 1;
|
|
|
if (isNew) {
|
|
if (isNew) {
|
|
|
- if (
|
|
|
|
|
- !row.positionId ||
|
|
|
|
|
- !row.positionName ||
|
|
|
|
|
- !row.positionLevelId ||
|
|
|
|
|
- row.establishmentCount === undefined ||
|
|
|
|
|
- row.establishmentCount === null ||
|
|
|
|
|
- row.establishmentCount === ''
|
|
|
|
|
- ) {
|
|
|
|
|
- this.$message.warning('请完善部门岗位信息');
|
|
|
|
|
|
|
+ const emptyNew =
|
|
|
|
|
+ !row.positionId &&
|
|
|
|
|
+ !row.positionLevelId &&
|
|
|
|
|
+ this.isEmptyEstablishmentCount(row.establishmentCount);
|
|
|
|
|
+ if (emptyNew) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.isDeptPositionFilled(row)) {
|
|
|
|
|
+ this.$message.warning(this.getDeptPositionMissingTip(row, rowNo));
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if (!this.isValidEstablishmentCount(row.establishmentCount)) {
|
|
|
|
|
+ // 已保存的岗位编制也允许调整人数,同样不允许 0 或空
|
|
|
|
|
+ this.$message.warning(this.getEstablishmentCountTip(row, rowNo));
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.form.id) {
|
|
|
|
|
+ // 新增部门时还没有部门 id,岗位编制需在部门保存后再维护
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
rows.push({
|
|
rows.push({
|
|
|
...(row.id ? { id: row.id } : {}),
|
|
...(row.id ? { id: row.id } : {}),
|
|
@@ -727,17 +708,59 @@
|
|
|
return (
|
|
return (
|
|
|
!!row.positionId &&
|
|
!!row.positionId &&
|
|
|
!!row.positionLevelId &&
|
|
!!row.positionLevelId &&
|
|
|
- row.establishmentCount !== undefined &&
|
|
|
|
|
- row.establishmentCount !== null &&
|
|
|
|
|
- row.establishmentCount !== ''
|
|
|
|
|
|
|
+ this.isValidEstablishmentCount(row.establishmentCount)
|
|
|
);
|
|
);
|
|
|
},
|
|
},
|
|
|
|
|
+ // 编制人数是否未填
|
|
|
|
|
+ isEmptyEstablishmentCount(value) {
|
|
|
|
|
+ return value === undefined || value === null || value === '';
|
|
|
|
|
+ },
|
|
|
|
|
+ // 编制人数填 0 时即时提示(输入完成后触发)
|
|
|
|
|
+ onDeptEstablishmentCountChange(row) {
|
|
|
|
|
+ if (
|
|
|
|
|
+ !this.isEmptyEstablishmentCount(row.establishmentCount) &&
|
|
|
|
|
+ !this.isValidEstablishmentCount(row.establishmentCount)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ this.$message.warning('编制人数必须大于 0');
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 编制人数必须是大于 0 的整数(0 不允许)
|
|
|
|
|
+ isValidEstablishmentCount(value) {
|
|
|
|
|
+ return !this.isEmptyEstablishmentCount(value) && Number(value) > 0;
|
|
|
|
|
+ },
|
|
|
|
|
+ // 编制人数的提示文案
|
|
|
|
|
+ getEstablishmentCountTip(row, rowNo) {
|
|
|
|
|
+ const no = rowNo ? `第 ${rowNo} 行` : '当前行';
|
|
|
|
|
+ return this.isEmptyEstablishmentCount(row.establishmentCount)
|
|
|
|
|
+ ? `${no}请填写编制人数`
|
|
|
|
|
+ : `${no}的编制人数必须大于 0`;
|
|
|
|
|
+ },
|
|
|
|
|
+ // 新增行未填完时按「缺什么提示什么」给出提示
|
|
|
|
|
+ getDeptPositionMissingTip(row, rowNo) {
|
|
|
|
|
+ const no = rowNo ? `第 ${rowNo} 行` : '当前行';
|
|
|
|
|
+ if (!row.positionSequenceId) {
|
|
|
|
|
+ return `${no}请选择岗位序列`;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!row.positionId) {
|
|
|
|
|
+ return `${no}请选择岗位名称`;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!row.positionLevelId) {
|
|
|
|
|
+ return `${no}请选择岗位层级`;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.isValidEstablishmentCount(row.establishmentCount)) {
|
|
|
|
|
+ return this.getEstablishmentCountTip(row, rowNo);
|
|
|
|
|
+ }
|
|
|
|
|
+ return '';
|
|
|
|
|
+ },
|
|
|
addDeptPosition() {
|
|
addDeptPosition() {
|
|
|
- const hasEmptyNew = this.departmentPositionList
|
|
|
|
|
|
|
+ const emptyRow = this.departmentPositionList
|
|
|
.filter((item) => !item.id)
|
|
.filter((item) => !item.id)
|
|
|
- .some((item) => !this.isDeptPositionFilled(item));
|
|
|
|
|
- if (hasEmptyNew) {
|
|
|
|
|
- this.$message.warning('请先填写岗位名称、岗位层级和编制人数');
|
|
|
|
|
|
|
+ .find((item) => !this.isDeptPositionFilled(item));
|
|
|
|
|
+ if (emptyRow) {
|
|
|
|
|
+ const rowNo = this.departmentPositionList.indexOf(emptyRow) + 1;
|
|
|
|
|
+ this.$message.warning(
|
|
|
|
|
+ this.getDeptPositionMissingTip(emptyRow, rowNo)
|
|
|
|
|
+ );
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
this.ensurePositionOptions();
|
|
this.ensurePositionOptions();
|
|
@@ -867,7 +890,15 @@
|
|
|
)
|
|
)
|
|
|
.map((item) => ({
|
|
.map((item) => ({
|
|
|
positionLevelId: item.positionLevelId ?? item.id,
|
|
positionLevelId: item.positionLevelId ?? item.id,
|
|
|
- positionLevel: item.positionLevel || item.level || ''
|
|
|
|
|
|
|
+ positionLevel: item.positionLevel || item.level || '',
|
|
|
|
|
+ // 层级若携带岗位性质,选中层级时用于自动带出(不可手动选择)
|
|
|
|
|
+ positionType:
|
|
|
|
|
+ item.positionType ??
|
|
|
|
|
+ item.positionTypeId ??
|
|
|
|
|
+ item.positionNature ??
|
|
|
|
|
+ '',
|
|
|
|
|
+ positionTypeName:
|
|
|
|
|
+ item.positionTypeName || item.positionNatureName || ''
|
|
|
}));
|
|
}));
|
|
|
// 详情接口的岗位序列覆盖列表值
|
|
// 详情接口的岗位序列覆盖列表值
|
|
|
if (detail && (detail.positionSequenceId || detail.sequenceId)) {
|
|
if (detail && (detail.positionSequenceId || detail.sequenceId)) {
|
|
@@ -875,29 +906,18 @@
|
|
|
row.positionSequence =
|
|
row.positionSequence =
|
|
|
detail.positionSequence || detail.sequenceName || '';
|
|
detail.positionSequence || detail.sequenceName || '';
|
|
|
}
|
|
}
|
|
|
- // 详情/列表的岗位性质可能是 id 或名称,通过字典反查统一为 id+名称
|
|
|
|
|
- const typeRaw =
|
|
|
|
|
|
|
+ // 岗位性质不可手动选择:先按岗位(详情优先、列表兜底)自动带出
|
|
|
|
|
+ const type = await this.resolveDeptPositionType(
|
|
|
(detail && detail.positionType) ||
|
|
(detail && detail.positionType) ||
|
|
|
- (position && position.positionType) ||
|
|
|
|
|
- '';
|
|
|
|
|
- if (typeRaw) {
|
|
|
|
|
- if (!this.positionNatureOptions.length) {
|
|
|
|
|
- await this.ensurePositionOptions();
|
|
|
|
|
- }
|
|
|
|
|
- const matched = this.positionNatureOptions.find(
|
|
|
|
|
- (item) =>
|
|
|
|
|
- String(item.id) === String(typeRaw) || item.name === typeRaw
|
|
|
|
|
- );
|
|
|
|
|
- if (matched) {
|
|
|
|
|
- row.positionType = matched.id;
|
|
|
|
|
- row.positionTypeName = matched.name;
|
|
|
|
|
- } else {
|
|
|
|
|
- row.positionType = typeRaw;
|
|
|
|
|
- row.positionTypeName =
|
|
|
|
|
- (detail && detail.positionTypeName) ||
|
|
|
|
|
- (position && position.positionTypeName) ||
|
|
|
|
|
- '';
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ (position && position.positionType) ||
|
|
|
|
|
+ '',
|
|
|
|
|
+ (detail && detail.positionTypeName) ||
|
|
|
|
|
+ (position && position.positionTypeName) ||
|
|
|
|
|
+ ''
|
|
|
|
|
+ );
|
|
|
|
|
+ if (type) {
|
|
|
|
|
+ row.positionType = type.id;
|
|
|
|
|
+ row.positionTypeName = type.name;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
onDeptPositionSequenceChange(row) {
|
|
onDeptPositionSequenceChange(row) {
|
|
@@ -915,12 +935,25 @@
|
|
|
row.positionTypeName = '';
|
|
row.positionTypeName = '';
|
|
|
row.levelOptions = [];
|
|
row.levelOptions = [];
|
|
|
},
|
|
},
|
|
|
- onDeptPositionTypeChange(row) {
|
|
|
|
|
- // 选中岗位性质时同步名称
|
|
|
|
|
- const type = this.positionNatureOptions.find(
|
|
|
|
|
- (item) => item.id === row.positionType
|
|
|
|
|
|
|
+ // 岗位性质不允许手动选择:把层级/岗位带出的原始值(字典 id 或文案)统一成 id+名称
|
|
|
|
|
+ async resolveDeptPositionType(raw, fallbackName) {
|
|
|
|
|
+ const value =
|
|
|
|
|
+ raw === null || raw === undefined ? '' : String(raw).trim();
|
|
|
|
|
+ const name = String(fallbackName || '').trim();
|
|
|
|
|
+ if (!value && !name) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.positionNatureOptions.length) {
|
|
|
|
|
+ await this.ensurePositionOptions();
|
|
|
|
|
+ }
|
|
|
|
|
+ const matched = this.positionNatureOptions.find(
|
|
|
|
|
+ (item) =>
|
|
|
|
|
+ String(item.id) === value || String(item.name) === value
|
|
|
);
|
|
);
|
|
|
- row.positionTypeName = type ? type.name : '';
|
|
|
|
|
|
|
+ if (matched) {
|
|
|
|
|
+ return { id: matched.id, name: matched.name };
|
|
|
|
|
+ }
|
|
|
|
|
+ return { id: value || name, name };
|
|
|
},
|
|
},
|
|
|
// 按岗位序列过滤岗位名称选项(未选序列时返回全部)
|
|
// 按岗位序列过滤岗位名称选项(未选序列时返回全部)
|
|
|
getPositionsBySequence(sequenceId) {
|
|
getPositionsBySequence(sequenceId) {
|
|
@@ -947,11 +980,22 @@
|
|
|
? `${item.positionName}(${type})`
|
|
? `${item.positionName}(${type})`
|
|
|
: item.positionName;
|
|
: item.positionName;
|
|
|
},
|
|
},
|
|
|
- onDeptPositionLevelChange(row) {
|
|
|
|
|
|
|
+ async onDeptPositionLevelChange(row) {
|
|
|
const level = (row.levelOptions || []).find(
|
|
const level = (row.levelOptions || []).find(
|
|
|
(item) => item.positionLevelId === row.positionLevelId
|
|
(item) => item.positionLevelId === row.positionLevelId
|
|
|
);
|
|
);
|
|
|
row.positionLevel = level ? level.positionLevel : '';
|
|
row.positionLevel = level ? level.positionLevel : '';
|
|
|
|
|
+ // 岗位性质不可选:层级若带出性质则按层级刷新,否则保留已带出的性质
|
|
|
|
|
+ if (level && (level.positionType || level.positionTypeName)) {
|
|
|
|
|
+ const type = await this.resolveDeptPositionType(
|
|
|
|
|
+ level.positionType,
|
|
|
|
|
+ level.positionTypeName
|
|
|
|
|
+ );
|
|
|
|
|
+ if (type) {
|
|
|
|
|
+ row.positionType = type.id;
|
|
|
|
|
+ row.positionTypeName = type.name;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
async loadDepartmentPositions() {
|
|
async loadDepartmentPositions() {
|
|
|
if (!this.form.id || !this.isDeptType) {
|
|
if (!this.form.id || !this.isDeptType) {
|