2026-09-15
合同管理:发起/变更/续签弹框区块调整(图片需求,多轮完成)
- 需求:①员工信息卡挪到「合同基础信息」模块下面;②标题按模式切换:
createBaseSectionTitle = 变更合同基础信息 / 续签合同基础信息 / 合同基础信息(computed,模板引用);③变更/续签时基础信息可修改:所属机构/所属部门/岗位名称由 disabled 改为 :disabled="isCreateMode" + v-model(发起模式仍禁用自动带出,即"现有禁用不变");④三者必填带星号:prop="legalEntityName/departmentName/positionName" + createRules required(blur 触发)。
- 提交链路:
buildCreatePayload 里 departmentName = form.departmentName || emp.department、legalEntityName = form.legalEntityName || emp.legalEntity(表单优先);变更模式 changedValues 含 legalEntity/department/position 的 id+name 六项;续签 renewContract(id, { contract: {...payload} }) 全量展开。fillCreateFormFromContract 回填 detail 的 id/name,员工档案兜底"为空才补"。
- 员工信息卡最终放置:基础信息区块之后、对比区(
v-if="isCompareMode")之前,class cm-create-employee-card cm-employee-below;scss 新增 .cm-employee-below{margin:14px 22px 0} 与 .cm-employee-item{margin-left:24px}(注意要放 .cm-detail-page 规则之前,避免覆盖详情页卡片的 margin)。
- 弹框字段最终顺序:签订员工 / 合同编号 / 合同类型 / 拟定薪资 / 所属机构 / 所属部门 / 岗位名称 / 合同起始日期 / 签署方式 / 合同终止日期 / 合同模版(线上)或合同附件(线下 is-span-2)。
解除/终止劳动合同弹框 UI 精简
- 去掉弹框内部标题栏(圈出来的大标题)和底部提示行(圈出来的 footer info)— 用户用图片明确圈出这两处。
- 原 header 里的员工/合同编号信息改为独立的
.cm-terminate-info 信息条,位于表单区上方:label「员工姓名」「合同编号」,值用更大更粗的字体,两者间距 48px。
- 新增样式
.cm-terminate-info{padding:18px 22px 0;display:flex;gap:48px;align-items:center}、label 15px #7e8b9d、b 17px #243955 font-weight:600。
合同详情弹框 UI 精简
- 按图片圈出位置,移除合同详情弹框底部 footer-info(合同编号 / 状态提示),仅保留「关闭」按钮。
- 校验:lint 干净。
解除弹框:签署方式联动离职证明模板/附件
- 签署方式=线上:下拉「离职证明模板」(prop
templateId,选项复用 contractTemplates,选择后 onTerminateTemplateChange 解析 templateVersionId);必填。
- 签署方式=线下:单个上传入口「离职证明附件」(prop
offlineFileIds);必填。
- 移除原「线下协议/解除依据文件」+「解除依据附件」双上传及
evidenceFileIds 字段。
- 提交 payload:ONLINE 传 templateId/templateVersionId,OFFLINE 传 offlineFileId。
- 校验:模板编译 0 error、lint 干净。
解除弹框顶部信息条样式对齐合同详情
- 将原
.cm-terminate-info 改为复用 .cm-create-employee-card 员工信息卡:左侧头像、员工姓名、合同编号,外观与合同详情 .cm-detail-employee 一致。
- 新增
.cm-terminate-employee{margin:16px 22px 0;padding:14px 18px},移除旧的信息条样式。
- 校验:模板编译 0 error、lint 干净。
解除弹框:模板/附件位置调整到生效日期下方
- 将「离职证明模板 / 离职证明附件」表单项从表单底部上移到「生效日期」之后、「最后工作日期」之前。
- 线上/线下两种场景均占满整行(
grid-column: span 2)。
- 校验:模板编译 0 error、lint 干净。
解除弹框顶部员工信息卡间距调大
- 用户反馈「员工姓名」与「合同编号」挤在一起;新增
.cm-terminate-employee .cm-employee-no{margin-left:48px},把两个标签间距拉开。
- 校验:lint 干净。
人员结构看板两页 vs 接口文档差异盘点(仅分析,未改代码)
- 目标模块:接口文档 hr 分组里 tag = 人力资源-人员结构报表(Hr Personnel Structure Report Controller),共 13 个 GET,全部挂在
/hr/personnel-structure-reports/ 下:
/dashboard/summary(顶部指标:员工总量/在岗人数/在岗率/人才库人数/当年入职/当年离职)
/dashboard/structure-trend(最近12个月在职/入职/离职/净增,仅对应"结构分析"趋势)
/dashboard/overall-distribution(用工类型 + 岗位性质)
/dashboard/age-distribution(年龄分段)
/dashboard/organization-distribution(按部门聚合)
/dashboard/talent-structure(岗位序列/岗位层级/职级)
/dashboard/quality-analysis(学历 + 政治面貌;职称留空)
/analysis/summary(在职/离职/累计入职 + 同比环比)
/analysis/{dimensionCode}(11 个白名单维度:POSITION_LEVEL、WORK_LOCATION、POSITION_SEQUENCE、DEPARTMENT、GENDER、CONTRACT_TYPE、EDUCATION、AGE、TENURE、POSITION_TENURE、PROFESSIONAL_TITLE,职称返回空值占位)
/mobility-analysis(当年入职/离职/当月净增 + 12月趋势)
/effectiveness-analysis(在岗人数 + 司龄结构;人均产出/编制使用率明确 DATA_UNAVAILABLE)
/details(分页明细,仅统计日在岗人员,支持 dimensionCode + dimensionValueCode)
/details/export(导出,复用明细口径)
- 统一入参:
organizationId/departmentId(int64) + year/month(int, 1-12) + contractType(string,字典 code)。
- 统一返回包装:
{code,message,data},业务体 = 人员结构报表响应{dataStatus, reportMonth(yyyy-MM), statisticsDate(yyyy-MM-dd), message, kpis[], dimensions[], trends[], scopeDepartmentIds[]};dimensions[].items[] = {valueCode,valueName,count,percentage};kpis[] = {metricCode,metricName,value,unit,rateValue,monthOnMonthRate,yearOnYearRate,dataStatus,message}。
- 前端现状(最大问题):
src/views/hrAnalysis/personnelStructureDashboard 与 personnelStructureAnalysisBoard 两页 100% 用本地 ./mock.js,src/api/hr/ 下没有任何 personnel-structure 封装,13 个接口一个都没接。
- 典型错位:字段名(页面
{name,value} vs 接口 {valueName,count};页面 metrics[].key/label vs 接口 kpis[].metricCode/metricName);筛选(页面月分是 '2026-08' 字符串、组织是假枚举/部门中文名,无 departmentId);页面B 4 个筛选只 chart.resize() 不取数;页面B「导出」是 window.print() 不是 /details/export;两页明细都是本地切片无分页(接口是 Pagination);页面B 明细列「招聘类型」接口无此字段;页面A「司龄」tab 用的是年龄数据;页面A「职称分析」「职业属性」(无任何维度编码)会展示假数据;页面A 用 scaleRate 按组织比例前端硬乘伪造数值;两页都没有 dataStatus/message 空值协议。
已按接口完成两页对接(本次实际改代码)
- 新增
src/api/hr/personnelStructure.js:13 个接口(/hr/personnel-structure-reports/**)+ adaptDimensions/adaptMetrics/adaptTrends/adaptDetailRows/buildQuery/pickMetric + DATA_STATUS/DIMENSION 常量 + downloadBlob 导出。
- 新增
src/views/hrAnalysis/shared.js:合同类型枚举、buildOrganizationOptions/rootOrganizationOptions/departmentOptions(基于 listOrganizations + buildOrganizationTree)、formatCount/formatRate/trendTone/ratioWidth/niceMax/recentMonths/splitMonth/monthTick/tooltipStyle。
- 重写
personnelStructureDashboard/index.vue(psd-screen):月份用 el-date-picker type="month" 取 yyyy-MM,另加组织/部门/合同类型三个筛选;6 指标卡走 dashboard/summary(按 metricCode→关键字→顺序三级匹配);趋势面板 3 个 tab 分别走 structure-trend / mobility-analysis / effectiveness-analysis(效能无趋势时回退接口返回的司龄结构柱状图);整体人员分布走 overall-distribution(按 dimensions[] 动态分组成行)、年龄/司龄走 age-distribution + analysis/TENURE、各单位走 organization-distribution、人才结构走 talent-structure(动态页签)、素质分析走 quality-analysis(动态页签,含职称空值占位);明细弹框走 /details,支持关键字、dimensionCode+dimensionValueCode 下钻、分页。
- 重写
personnelStructureAnalysisBoard/index.vue(psa-board):3 指标卡走 analysis/summary;11 个维度图表全部走 analysis/{dimensionCode};新增「人员结构趋势」(structure-trend) 与「整体人员分布」(overall-distribution) 两个缺失面板,面板数 10→12,改为 4 列 × 3 行网格;「工作地点」因接口不提供经纬度,改为按 valueName/count/percentage 的排名条形列表(保留地图底纹);学历/职称合并成一个带页签的面板;明细弹框走 /details(分页 + 关键字 + 维度下钻),「导出」改为调用 /details/export(blob 下载),不再 window.print()。
- 删除两个页面的
mock.js;两页补上 dataStatus/message 空值协议(-- + title)、不可用态占位、「统计日」显示(取 statisticsDate,不再前端拼 -31)。
- 顺手修掉两个自身 bug:①
buildQuery 原本只输出 5 个 scope 字段,会把明细的 pageNum/size/dimensionCode 吃掉,已改成调用方 compact({ ...buildQuery(filters), ... });② buildQuery 不识别 'yyyy-MM',月份选择器传进来的值会被丢掉而回退当前自然月,已加正则兼容。
- 验证:
npx vue-cli-service build 通过(45s),产物里有 view-hrAnalysis-personnelStructure* 的 js/css chunk。注意:构建生成了 dist/(已在 .gitignore 中,批量删除被安全策略拦截,未清理,保留无影响)。
隐藏职称相关模块
- 新增可开关的隐藏机制
src/views/hrAnalysis/shared.js:HIDDEN_DIMENSION_CODES = [DIMENSION.PROFESSIONAL_TITLE] + isDimensionVisible(code) + filterVisibleGroups(groups)。职称功能上线后,把该数组置空(或移除 PROFESSIONAL_TITLE)即可恢复,页面代码不用再动。
- 人员结构看板:
quality-analysis 返回的 dimensions 先过 filterVisibleGroups,素质分析面板的页签自动少掉「职称」(剩学历/政治面貌)。
- 人员结构分析看板:
DIMENSION_CODES 末尾 .filter(isDimensionVisible) —— 职称的请求也不再发起;educationTabs 由 data 改为 computed,只有一个维度时 PanelTitle 不再渲染页签(tabs.length > 1 才渲染),面板保持「学历分析」标题。
- 回归:
node tmp/check-blocks.js(模板编译 + babel 解析)与 npx vue-cli-service build 均通过。
人员结构报表模块的接口缺口盘点(查过文档确认)
- 全 hr 分组 没有任何
enum 定义(Swagger definitions 里零个 enum),所以 metricCode 取值表根本不存在,dimensionCode 也只写在 description 文本里。
- 已确认的缺口要点(可直接拿去和后端对齐):
metricCode 无枚举 → 指标卡只能"编码猜测+名称关键字+返回顺序"兜底。
- 无"可用统计月份/快照可用性"接口;人员结构报表文档只说"按该月末重算",而编制看板每个接口都写了"历史月份仅查询已生成快照",两者口径不一致,前端月份选择器只能硬生成 12 个月。
- 无维度值字典接口 →
dimensionValueCode 只能从图表返回里取,做不了筛选下拉。
- 无"当前用户可统计范围(组织+部门)"接口,
organizationId/departmentId 的范围只能靠报错;前端复用 main 分组 /main/group/getGroupList,两边 id 是否同一套需确认。
contractType 无字典接口(文档只说"由劳动合同模块维护"),前端硬编码 6 个 code。
details 同时有 deptId(机构id) 与 departmentId(统计部门主键),语义重叠、前端不知道该传哪个;且维度筛选只支持单个 dimensionCode+dimensionValueCode,做不了"部门+学历+年龄"组合筛选或维度×维度二次下钻。
details 只返回统计日在岗人员,但明细模型里有 statusOnStatisticsDate(在职/离职)→ 该字段实际恒为"在职"。
/details/export 的 200 响应 schema 是空的(只有 {"description":"OK"})、produces: ["*/*"],没有文件名/格式契约,也没有异步导出任务机制;入参里还混着 pageNum/size/offset/sortName/orderBy(导出应为全量,语义冲突)。
structure-trend 不支持 dimensionCode → 看不了"按部门/序列/学历的趋势"。
talent-structure 描述含"职级分布",但 /analysis/{dimensionCode} 的 11 个白名单维度里没有职级编码 → 职级只能从 talent-structure 的 dimensions 拿。
overall-distribution 只描述"用工类型和岗位性质",没给 dimensionCode/dimensionName 取值 → 只能动态渲染。
effectiveness-analysis 的人均产出/编制使用率固定 DATA_UNAVAILABLE,但编制使用率在编制看板 /hr/headcount/dashboard/summary 有(不过编制看板的 organizationId/departmentId 口径与人员结构报表是否一致需确认)。
mobility-analysis 与 structure-trend 的 trends 字段完全同构(month/onJobCount/onboardCount/leaveCount/netChangeCount),数据源重叠,两处易数字不一致。
rateValue 与 value/unit 的组合规则没写(比例型是否同时填 value);前端用 rateValue ?? value 容忍两种写法。
- 未被利用的返回字段:
scopeDepartmentIds("实际参与统计的部门主键集合")目前前端没用,可用来展示"本次统计覆盖 N 个部门"或校验所选部门是否真的参与统计。
fm/directory/createPersonal/{userId} 调用逻辑梳理(问答,未改代码)
- 后端:fm 分组
POST /fm/directory/createPersonal/{userId},summary「创建个人文档区」,path 参数 userId(integer, 必填),返回 响应«R»(泛型)。
- 前端封装:
src/api/organization/index.js 的 createPersonalDirectory(userId)(空 id 直接返回 null 不发请求)+ hasJobNumber(record)(record.jobNumber ?? record.user?.jobNumber 有值即视为已入库归档)+ ensurePersonalDirectory(userId, record)(导出但全项目无调用,死代码)。
- 唯一调用点:
src/views/hrManagement/onboardingHandling/index.vue,入口是保存主流程 persistOnboarding() → maybeCreatePersonalDirectory(merged, alreadyArchived)。
- 语义:"员工首次入库归档"这一刻才建个人文档区。判定顺序:
- 表单当前有工号 →
alreadyArchived=true → 只记名单、不发请求;
- 表单没工号但
userIdBefore 存在 → 再拉一次 getOnboardingByUserId 看详情有没有工号,有则回填 editing.jobNumber 并记名单(拉失败就"以保存前表单中的工号为准",不打断);
- 保存(
updateOnboarding/createOnboarding)→ mergeSavedResult(会把 saved.jobNumber || editing.jobNumber 带出来)→ 若 alreadyArchived 为 false 就发请求建目录(即"保存这一步刚拿到工号"= 首次归档,正是要建的时刻);成功后把 userId 记进 personalDirectoryUserIds。
- 幂等三层:组件内存名单(本次会话同一 userId 只请求一次)+ 保存前两次工号检查 + "有工号=已归档"业务约定;失败只
showRequestError('创建个人文档区失败'),不 reject、不打断入职保存。
- 遗留疑点(待与后端确认):接口文档没写是否幂等。若后端保存/详情都不回填
jobNumber,则刷新页面(内存名单丢失)后对同一条记录再次保存会重复调用该接口。
后续调整:清理死代码 + 跨会话幂等(已改)
src/api/organization/index.js:删掉 ensurePersonalDirectory(导出但全项目零调用)。
src/views/hrManagement/onboardingHandling/index.vue:新增 PERSONAL_DIRECTORY_CACHE_KEY = "hr:onboarding:createdPersonalDirectory" + readCreatedDirectoryUsers()/writeCreatedDirectoryUsers()(localStorage,最多保留 500 条、try/catch 兜底隐私模式);data 加 createdDirectoryUsers;新增 rememberCreatedDirectoryUser()(仅创建成功才落盘,失败不落盘以便下次重试);maybeCreatePersonalDirectory 增加"已成功创建过就不重复调"这一层判断。
- 判断顺序最终为:
!userId → existedJobNumber(已归档,只记内存名单)→ 会话内存名单 → 持久化已建名单 → 调接口 → 成功后同时记两份。
- 没有加"保存后仍无工号就不建"的判断:那会把"后端不回填 jobNumber"的场景变成永远不建目录(功能回归),因此只用持久化去重解决刷新后重复调用的问题。
合同管理:发起合同弹框补「岗位名称」禁用输入框
- 文件
src/views/contractManagement/index.vue("发起合同弹窗" ele-modal,:visible.sync="createVisible",三态复用:发起/变更/续签)。
- 在「所属机构」之后插入
<el-form-item label="岗位名称"><el-input :value="createForm.positionName" disabled placeholder="选择员工后自动带出" /></el-form-item>。没有新增数据字段 —— createForm.positionName 本来就存在,applyEmployeeToForm(选员工)、变更/续签详情回填、路由 query 带入三条路径都已赋值,并已用于模板匹配接口的 positionName 参数。
- 该页禁用型"自动带出"字段统一用
:value(单向绑定,不发 input)而不是 v-model,与相邻的「所属部门/所属机构」保持一致;disabled 只读展示字段不加 prop(createRules 里没有对应规则)。
- 布局提示:
.cm-create-grid 是 2 列 grid(gap 4px 20px),字段从 10 个变 11 个后,在线签署模式下最后一行只剩「合同模版」一个(离线模式的「合同附件」本身有 is-span-2 所以仍整齐)。嫌不整齐的话给最后一项统一加 class="is-span-2" 即可。
- 追加调整:把所属机构 与 所属部门 换了位置。
- 追加调整(变更/续签弹框结构):对比区(原合同信息/拟定信息两张卡片)挪到「合同基础信息」表单下方,弹框顺序变为 表单 → 对比区 → 页脚;对比区由内联
style="background:#fafbfd" 改为类 cm-compare-section(scss:.cm-create-section.cm-compare-section{background:#fafbfd})。表单区块标题按模式切换:createBaseSectionTitle computed → 发起「合同基础信息」/ 变更「变更合同基础信息」/ 续签「续签合同基础信息」。所属机构/所属部门/岗位名称改为 :disabled="isCreateMode"(发起时禁用自动带出,变更/续签时可编辑,v-model 绑 name 字段),并补必填规则(legalEntityName/departmentName/positionName,prop 也改到 name 字段上)带星号;签订员工(非发起禁用)与合同编号(恒禁用)不动。变更模式 changedValues 补 legalEntityId/legalEntityName/departmentId。注意:编辑的是名称文本,id 仍是详情回填值 —— 若要真正换机构/部门/岗位,需接下拉(组织树/部门/岗位列表接口)后才能同步 id。
- 追加调整:按用户要求把 签署方式 与 合同终止日期 换了位置。当前发起合同弹框字段顺序(
.cm-create-grid 2 列):签订员工 / 合同编号 / 合同类型 / 拟定薪资 / 所属机构 / 所属部门 / 岗位名称 / 合同起始日期 / 签署方式 / 合同终止日期 / 合同模版(线上)或 合同附件(线下,is-span-2)。注意这样「合同起始日期/合同终止日期」不再相邻(起始在上一行右格)。
- 以上两次换位都是纯 DOM 顺序调整,不影响校验(
el-form-item 规则按 prop 匹配)与提交参数。
- 追加调整:岗位 id 与名称都要提交给接口。
createForm 原来只有 positionName,buildCreatePayload 的 positionId/positionName 取的是 emp(选中员工对象)而不是表单,导致表单里的岗位信息不参与提交。已补齐:
blankCreateForm() 加 positionId: null;
applyEmployeeToForm / onEmployeeChange 都写 createForm.positionId = employee.positionId || null(adaptEmployee 里 positionId 来自 pickId(orgEmp.positionId, user.postId, user.positionId, seed.positionId),返回字符串,雪花 ID 不丢精度);
fillCreateFormFromContract(变更/续签)补 positionId: detail.positionId,并把 positionId 一起塞进 adaptEmployee(detail, seed),员工信息回来时补空;
buildCreatePayload 改为 positionId: form.positionId || emp.positionId、positionName: form.positionName || emp.position(表单优先,兼容 create/renew,续签是 { contract: {...payload} } 直接展开);
- 变更模式的
changedValues 也补上 positionId(与 positionName 成对)。
合同管理:合同详情弹框 UI 优化 + 附件改公共组件
- 重要发现(踩坑记录):
ele-modal 的 append-to-body 是真实 prop(组件内 dialogAppendToBody → 传给内部 el-dialog 的 append-to-body),所以弹框内容被挪到 <body> 下、脱离了页面的 .cm-page 容器。结果:src/styles/views/contractManagement/index.scss 里所有 .cm-page .xxx 规则在弹框内全部失效 —— 详情弹框的「合同状态」胶囊(.cm-page .cm-status)之前是裸文本、.cm-page .cm-link 按钮也没样式。已在 .cm-status 变体上补 .cm-detail-page 前缀,并给 .cm-detail-page,.cm-detail-page * 补 box-sizing:border-box(.cm-page,.cm-page * 同理够不到)。
- 结论:这个页面里凡是弹框内的样式,选择器前缀不能只写
.cm-page;新增弹框样式要么带上弹框自己的根类,要么和 .cm-page 一起并列。
- 详情弹框新增根类
cm-detail-page(与 cm-create-page 并存),样式收口在 scss 末尾:正文 10/11/12px → 13/14px(标签 13px、值 14px、岗位职责 14px/1.9、备注 13px、页脚 13px),区块 padding 与 grid gap 放大(gap:16px 26px),头像 48px、姓名 16px,状态胶囊 13px;把弹框内所有内联 style 换成类名(.cm-detail-employee / .cm-employee-no / .cm-detail-no / .cm-detail-status / .cm-detail-duty / .cm-detail-remark / .cm-detail-muted)。
- 去掉「签署文件」行;「合同附件」改用公共组件
<fileMain :value="detailRow.attachmentFileIds" type="view" size="small" />(与同一页发起合同弹框线下模式的用法一致;view 模式是「查看」按钮+数量角标,单个附件直接预览、多个弹文件列表,逻辑在 src/components/addDoc/main.vue 的 open())。无附件时显示「暂无附件」,避免点开空列表弹框。
adaptContract 清理:删掉 signDoc / attachment(原来只取单个文件)与只服务它们的 pickFile / adaptFile,改为 attachmentFileIds(新增 collectAttachmentFileIds():优先 filePurpose ∈ ATTACHMENT/SCAN/ARCHIVE,缺用途标记时回退全部文件)。同时删掉 viewFile 方法及其唯一依赖 import { downloadFile } from '@/api/file'。
- 回归:lint 干净;
npx sass 编译 scss 通过;vue-template-compiler 编译模板 0 error;babel 解析脚本 OK。
- 追加调整:去掉发起/变更/续签共用弹框里的
.cm-create-header(h2 {{ createDialogTitle }} + 副标题 {{ createDialogHint }})—— 弹框自带的标题栏已显示「发起合同/变更合同/续签合同」,正文再写一遍是重复;createDialogHint computed 随之删除(createDialogTitle 仍在 :title 上用)。.cm-create-header 基础样式保留(解除/终止弹框还在用,现在全页只剩那一处)。注意:该弹框正文现在第一块就是对比区(变更/续签)或「合同基础信息」(发起)。
- 追加调整(按用户要求推广到所有合同弹框):把
.cm-compare-item 的「一行显示」改成 基础样式,不再只在 .cm-detail-page 下覆盖 —— 现在详情弹框的 3 个区块、变更/续签弹框的两张对比卡片(.cm-compare-list)全部统一为「标签:值」同一行(flex-direction:row;align-items:baseline;gap:0,label flex:none,value min-width:0;word-break:break-word)。同时把 label/value 字号从 10px/12px 统一到 13px/14px、.cm-compare-list 行 gap 8→10px、.cm-change-employee 12→13px,并把 2 处 style="grid-column: span 2;" 换成 .cm-compare-item.is-span-2 类。
- 合同弹框里 label/value 展示点只有两类:详情弹框与变更/续签的对比卡片(都用
.cm-compare-item);解除/终止弹框是表单输入项(el-form-item),不属于 label/value 展示,未动。.cm-change-employee / .cm-list-container 这些类在模板里已无使用(历史遗留 CSS)。
- 追加调整:详情弹框里
.cm-compare-item 由「label 在上、值在下」改为同一行(.cm-detail-page .cm-compare-item{flex-direction:row;align-items:baseline;gap:0},label flex:none、value min-width:0;word-break:break-word 防溢出)。注意 .cm-compare-item 的基础样式是 flex-direction:column,变更/续签弹框的对比卡片(.cm-compare-list)仍保持上下两行,只有详情弹框改成一行。
- 追加调整:把直属上级从「合同期限与薪资」挪到「合同基本信息」末尾(跟 岗位名称/岗位层级 归在一起)。
- 追加调整:去掉详情弹框「签署信息」里的审核人行,
adaptContract 的 reviewer 一并删除。详情弹框最终字段:合同基本信息(合同编号/合同类型/所属机构/所属部门/岗位名称/岗位层级) → 合同期限与薪资(合同起始/合同终止/月薪资/试用期至/直属上级) → 签署信息(签署方式/合同附件/签订日期/创建时间,有备注时追加备注)。
- 追加调整:去掉详情弹框整个「岗位职责与工作信息」区块(标题 +
暂无岗位职责说明),adaptContract 的 positionDuty 与样式 .cm-detail-page .cm-detail-duty 一并删除。详情弹框最终只剩 3 个区块:合同基本信息 / 合同期限与薪资 / 签署信息。
- 追加调整:去掉详情弹框员工信息卡里的副信息行(
所属机构: · 合同编号: · 合同类型: 那行 <small>),卡片现在只剩 头像 + 「员工姓名 / 员工工号」+ 右侧合同状态。同时删掉随之失效的 .cm-detail-no、.cm-create-employee-card .cm-employee-info small(基础规则与 .cm-detail-page 覆盖规则)—— 注意 所属机构/合同编号/合同类型 在下面「合同基本信息」区块里仍然有完整展示,去重后不丢信息。
- 追加调整:去掉详情弹框「合同期限与薪资」里的工作地点行(该区块现为 合同起始/合同终止/月薪资/试用期至/直属上级),并同步删掉
adaptContract 里随之失效的 workLocation: item.workLocation || ''(buildCreatePayload 里的 workLocation: extra.workLocation 是提交侧字段,保留)。
- 追加调整:按用户截图要求去掉详情弹框内的标题块(
.cm-create-header:h2「合同详情」+ 副标题「查看合同的完整信息…」)—— 弹框自带的标题栏已经有「合同详情」,正文再写一遍是重复。员工信息卡变成弹框正文第一个元素(.cm-detail-employee{margin:16px 26px 0} 提供顶部留白),同时删掉随之失效的 3 条 .cm-detail-page .cm-create-header* 样式(.cm-create-header 本身发起合同弹框仍在用,基础样式保留)。
方法沉淀(抓接口文档的完整姿势)
Invoke-WebRequest /swagger-resources → 取分组 → Invoke-WebRequest "/v2/api-docs?group=hr" -OutFile(约 1MB,不能用 web_fetch,会截断)。
- 不要在 PowerShell 里用
node -e 写含 $ref 的 JS($ref 会被 PS 当变量插值掉,且 JSON 是单行 1MB,Select-String 只能返回整行无用)。正确做法:用 write_to_file 写一个 tmp/xxx.js 脚本再 node xxx.js。
- 解析
$ref 递归展开时要给足深度(我用 depth>14),否则嵌套的 dimensions[].items[] 会直接返回 {},误以为接口没返回字段。