修改相关问题
This commit is contained in:
Vendored
-3
@@ -21,12 +21,10 @@ declare module 'vue' {
|
|||||||
ElAlert: typeof import('element-plus/es')['ElAlert']
|
ElAlert: typeof import('element-plus/es')['ElAlert']
|
||||||
ElAside: typeof import('element-plus/es')['ElAside']
|
ElAside: typeof import('element-plus/es')['ElAside']
|
||||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||||
ElBadge: typeof import('element-plus/es')['ElBadge']
|
|
||||||
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
|
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
|
||||||
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
|
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
ElCascader: typeof import('element-plus/es')['ElCascader']
|
|
||||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
@@ -52,7 +50,6 @@ declare module 'vue' {
|
|||||||
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||||
ElLink: typeof import('element-plus/es')['ElLink']
|
|
||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
|
|||||||
@@ -162,7 +162,7 @@
|
|||||||
<el-descriptions-item label="所属岗位">{{
|
<el-descriptions-item label="所属岗位">{{
|
||||||
detail.employee.positionName || employeeInfo.onboardingPosition || "-"
|
detail.employee.positionName || employeeInfo.onboardingPosition || "-"
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="员工编号">{{ detail.employee.employeeNo || employeeInfo.employeeNo || "-" }}</el-descriptions-item>
|
<el-descriptions-item label="员工编号">{{ resolvedEmployeeNo }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="入职日期">{{ formatDate(detail.employee.entryDate) }}</el-descriptions-item>
|
<el-descriptions-item label="入职日期">{{ formatDate(detail.employee.entryDate) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="员工司龄">{{ formatSeniority(detail.employee.entryDate) }}</el-descriptions-item>
|
<el-descriptions-item label="员工司龄">{{ formatSeniority(detail.employee.entryDate) }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="用工类型">{{ employmentTypeText(detail.employee.employmentType) }}</el-descriptions-item>
|
<el-descriptions-item label="用工类型">{{ employmentTypeText(detail.employee.employmentType) }}</el-descriptions-item>
|
||||||
@@ -256,6 +256,23 @@
|
|||||||
<div v-if="record.remark" class="change-record-line">
|
<div v-if="record.remark" class="change-record-line">
|
||||||
备注:{{ record.remark }}
|
备注:{{ record.remark }}
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="hasChangeSnapshot(record)" class="change-diff">
|
||||||
|
<div class="change-diff-title">变更明细</div>
|
||||||
|
<el-table
|
||||||
|
:data="changeDiffRows(record)"
|
||||||
|
border
|
||||||
|
size="small"
|
||||||
|
empty-text="前后值无差异"
|
||||||
|
class="change-diff-table"
|
||||||
|
>
|
||||||
|
<el-table-column prop="label" label="字段" min-width="120" />
|
||||||
|
<el-table-column prop="beforeText" label="修改前" min-width="150" />
|
||||||
|
<el-table-column prop="afterText" label="修改后" min-width="150" />
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div v-else class="change-record-empty">
|
||||||
|
该记录未保存修改前后值
|
||||||
|
</div>
|
||||||
<div v-if="record.attachments?.length" class="change-attachments">
|
<div v-if="record.attachments?.length" class="change-attachments">
|
||||||
<el-button
|
<el-button
|
||||||
v-for="file in record.attachments"
|
v-for="file in record.attachments"
|
||||||
@@ -456,6 +473,7 @@
|
|||||||
filterable
|
filterable
|
||||||
allow-create
|
allow-create
|
||||||
clearable
|
clearable
|
||||||
|
:value-on-clear="''"
|
||||||
default-first-option
|
default-first-option
|
||||||
placeholder="请选择或输入合同性质"
|
placeholder="请选择或输入合同性质"
|
||||||
class="full-width"
|
class="full-width"
|
||||||
@@ -724,6 +742,34 @@ const regularizationForm = reactive({
|
|||||||
remark: ""
|
remark: ""
|
||||||
});
|
});
|
||||||
const employeeInfo = computed<Record<string, any>>(() => detail.value?.employeeInfo || {});
|
const employeeInfo = computed<Record<string, any>>(() => detail.value?.employeeInfo || {});
|
||||||
|
|
||||||
|
const resolvedEmployeeNo = computed(() => {
|
||||||
|
if (detail.value?.employee?.employeeNo && String(detail.value.employee.employeeNo).trim()) {
|
||||||
|
return String(detail.value.employee.employeeNo).trim();
|
||||||
|
}
|
||||||
|
const snapshots = detail.value?.contractSnapshots || [];
|
||||||
|
for (const item of snapshots) {
|
||||||
|
if (item?.employeeNo && String(item.employeeNo).trim()) {
|
||||||
|
return String(item.employeeNo).trim();
|
||||||
|
}
|
||||||
|
if (item?.variablesJson) {
|
||||||
|
try {
|
||||||
|
const vars = typeof item.variablesJson === "string" ? JSON.parse(item.variablesJson) : item.variablesJson;
|
||||||
|
const target = vars?.["hr.EmployeeNo"] || vars?.["hr.employeeno"];
|
||||||
|
const val = typeof target === "object" ? target?.variableValue : target;
|
||||||
|
if (val && String(val).trim()) {
|
||||||
|
return String(val).trim();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 忽略变量快照反序列化异常
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (employeeInfo.value?.employeeNo && String(employeeInfo.value.employeeNo).trim()) {
|
||||||
|
return String(employeeInfo.value.employeeNo).trim();
|
||||||
|
}
|
||||||
|
return "-";
|
||||||
|
});
|
||||||
const materialPreviewUrls = reactive<Record<number, string>>({});
|
const materialPreviewUrls = reactive<Record<number, string>>({});
|
||||||
const materialPreviewLoading = reactive<Record<number, boolean>>({});
|
const materialPreviewLoading = reactive<Record<number, boolean>>({});
|
||||||
const materialPreviewFailed = reactive<Record<number, boolean>>({});
|
const materialPreviewFailed = reactive<Record<number, boolean>>({});
|
||||||
@@ -911,10 +957,10 @@ function safeDownloadName(value: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getEmployeeDownloadPrefix(): string {
|
function getEmployeeDownloadPrefix(): string {
|
||||||
|
const empNo = resolvedEmployeeNo.value !== "-" ? resolvedEmployeeNo.value : "";
|
||||||
const taskNo = String(
|
const taskNo = String(
|
||||||
detail.value?.task?.taskNo
|
detail.value?.task?.taskNo
|
||||||
|| detail.value?.employee?.employeeNo
|
|| empNo
|
||||||
|| detail.value?.employeeInfo?.employeeNo
|
|
||||||
|| ""
|
|| ""
|
||||||
).trim();
|
).trim();
|
||||||
const employeeName = String(
|
const employeeName = String(
|
||||||
@@ -1160,6 +1206,90 @@ function changeTypeText(value?: string) {
|
|||||||
return map[value || ""] || value || "人事变更";
|
return map[value || ""] || value || "人事变更";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EmployeeChangeFieldKey =
|
||||||
|
| "employmentType"
|
||||||
|
| "regularizationStatus"
|
||||||
|
| "regularizationDate"
|
||||||
|
| "contractNature"
|
||||||
|
| "socialInsuranceStatus"
|
||||||
|
| "socialInsuranceCompany";
|
||||||
|
|
||||||
|
type EmployeeChangeDiffRow = {
|
||||||
|
key: EmployeeChangeFieldKey;
|
||||||
|
label: string;
|
||||||
|
beforeText: string;
|
||||||
|
afterText: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const employeeChangeFields: Array<{ key: EmployeeChangeFieldKey; label: string }> = [
|
||||||
|
{ key: "employmentType", label: "用工类型" },
|
||||||
|
{ key: "regularizationStatus", label: "转正状态" },
|
||||||
|
{ key: "regularizationDate", label: "转正日期" },
|
||||||
|
{ key: "contractNature", label: "合同性质" },
|
||||||
|
{ key: "socialInsuranceStatus", label: "社保状态" },
|
||||||
|
{ key: "socialInsuranceCompany", label: "合同社保单位" }
|
||||||
|
];
|
||||||
|
|
||||||
|
function parseChangeSnapshot(value: unknown): Record<string, unknown> | null {
|
||||||
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
return value as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
if (typeof value !== "string" || !value.trim()) return null;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
||||||
|
? parsed as Record<string, unknown>
|
||||||
|
: null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSnapshot(record: any, field: "beforeJson" | "afterJson") {
|
||||||
|
const pascalField = field === "beforeJson" ? "BeforeJson" : "AfterJson";
|
||||||
|
return parseChangeSnapshot(record?.[field] ?? record?.[pascalField]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSnapshotValue(snapshot: Record<string, unknown>, key: string) {
|
||||||
|
const matchedKey = Object.keys(snapshot).find(item => item.toLowerCase() === key.toLowerCase());
|
||||||
|
return matchedKey ? snapshot[matchedKey] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeChangeValue(value: unknown) {
|
||||||
|
if (value === null || value === undefined) return "";
|
||||||
|
return typeof value === "string" ? value.trim() : JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatChangeValue(key: EmployeeChangeFieldKey, value: unknown) {
|
||||||
|
if (value === null || value === undefined || value === "") return "—";
|
||||||
|
const text = String(value);
|
||||||
|
if (key === "employmentType") return employmentTypeText(text);
|
||||||
|
if (key === "regularizationStatus") return regularizationText(text);
|
||||||
|
if (key === "regularizationDate") return formatDate(text);
|
||||||
|
if (key === "socialInsuranceStatus") return socialInsuranceText(text);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasChangeSnapshot(record: any) {
|
||||||
|
return Boolean(getSnapshot(record, "beforeJson") || getSnapshot(record, "afterJson"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeDiffRows(record: any): EmployeeChangeDiffRow[] {
|
||||||
|
const before = getSnapshot(record, "beforeJson") || {};
|
||||||
|
const after = getSnapshot(record, "afterJson") || {};
|
||||||
|
return employeeChangeFields.flatMap(field => {
|
||||||
|
const beforeValue = getSnapshotValue(before, field.key);
|
||||||
|
const afterValue = getSnapshotValue(after, field.key);
|
||||||
|
if (normalizeChangeValue(beforeValue) === normalizeChangeValue(afterValue)) return [];
|
||||||
|
return [{
|
||||||
|
key: field.key,
|
||||||
|
label: field.label,
|
||||||
|
beforeText: formatChangeValue(field.key, beforeValue),
|
||||||
|
afterText: formatChangeValue(field.key, afterValue)
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function canRegularize(employee?: OnboardingEmployee) {
|
function canRegularize(employee?: OnboardingEmployee) {
|
||||||
return Boolean(
|
return Boolean(
|
||||||
employee
|
employee
|
||||||
@@ -1301,9 +1431,9 @@ async function saveHrInfo() {
|
|||||||
await onboardingTaskApi.updateEmployeeHrInfo({
|
await onboardingTaskApi.updateEmployeeHrInfo({
|
||||||
id: hrForm.id,
|
id: hrForm.id,
|
||||||
employmentType: hrForm.employmentType,
|
employmentType: hrForm.employmentType,
|
||||||
contractNature: hrForm.contractNature.trim() || undefined,
|
contractNature: String(hrForm.contractNature ?? "").trim() || undefined,
|
||||||
socialInsuranceStatus: hrForm.socialInsuranceStatus,
|
socialInsuranceStatus: hrForm.socialInsuranceStatus,
|
||||||
socialInsuranceCompany: hrForm.socialInsuranceCompany.trim() || undefined
|
socialInsuranceCompany: String(hrForm.socialInsuranceCompany ?? "").trim() || undefined
|
||||||
});
|
});
|
||||||
hrEditVisible.value = false;
|
hrEditVisible.value = false;
|
||||||
await refreshEmployee(hrForm.id);
|
await refreshEmployee(hrForm.id);
|
||||||
@@ -1647,6 +1777,30 @@ onBeforeUnmount(clearMaterialPreviews);
|
|||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.change-diff {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-diff-title {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: #334155;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-diff-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-record-empty {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
.change-attachments {
|
.change-attachments {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user