修改密码完成

This commit is contained in:
2026-10-08 10:00:07 +08:00
parent 9f34602b3a
commit 2e9b20d559
5 changed files with 20 additions and 706 deletions
+10
View File
@@ -24,6 +24,16 @@ export function fetchGetUserInfo() {
return request<Api.Auth.UserInfo>({ url: '/api/auth/me' });
}
// 修改密码
export function changePasswordApi(data: { old_password: string, new_password: string, confirm_password: string }) {
return request({
url: '/api/auth/change-password',
method: 'post',
data
});
}
/**
* Refresh token
*
-9
View File
@@ -100,12 +100,3 @@ export function resetPasswordApi(id: number) {
});
}
// 修改用户密码
export function changePasswordApi(params: { oldPassword: string, password: string }) {
return request({
url: `/api/user/change-password`,
method: 'post',
data: params
});
}
+1
View File
@@ -8,5 +8,6 @@ export function getToken() {
/** Clear auth storage */
export function clearAuthStorage() {
localStg.remove('token');
localStg.remove('userInfo');
localStg.remove('refreshToken');
}
-688
View File
@@ -1,688 +0,0 @@
// ===================== 数据模型与 Mock 数据 =====================
export type RoleId = "applicant" | "process" | "process2" | "safety" | "quality" | "dept" | "vp" | "admin" | "viewer";
export interface Role {
id: RoleId;
name: string;
person: string;
org: string;
desc: string;
}
export const ROLES: Role[] = [
{ id: "applicant", name: "申请人", person: "张工艺", org: "一车间 · 工艺组", desc: "发起变更申请、AI 辅助判定、跟踪进度" },
{ id: "process", name: "专业会签(仪表)", person: "王仪表", org: "技术部 · 仪表科", desc: "专业会签、HAZOP 分析、确认连带变更" },
{ id: "process2", name: "专业会签(设备)", person: "周设备", org: "设备管理部 · 设备科", desc: "专业会签、设备完整性检查、行动项落实" },
{ id: "safety", name: "安全工程师", person: "王海燕", org: "安全环保部", desc: "安全审查、PSSR 检查表确认、风险分析组织" },
{ id: "dept", name: "车间主任", person: "李主任", org: "一车间", desc: "部门审核、现场验收、变更关闭确认" },
{ id: "vp", name: "分管领导", person: "刘副总", org: "公司领导", desc: "重要变更最终批准、移动端审批" },
{ id: "admin", name: "系统管理员", person: "刘敏", org: "信息化部", desc: "流程配置、字典维护、权限分配" },
{ id: "quality", name: "质量工程师", person: "陈质量", org: "质量部", desc: "质量会签、产品合格判定、检验方案确认" },
{ id: "viewer", name: "非审批人员", person: "吴新", org: "相关部门", desc: "以信息查看为主,不参与变更流程" },
];
export type ChangeType = "工艺" | "设备" | "管理";
export type ChangeLevel = "重要" | "一般";
export type ChangeStatus =
| "审批中"
| "已批准"
| "实施中"
| "待PSSR"
| "待验收"
| "待关闭"
| "已关闭";
export interface FlowNode {
name: string;
kind: "审批" | "会签" | "最终批准";
roles: RoleId[];
members?: { name: string; done: boolean }[];
status: "done" | "current" | "todo";
locked?: boolean;
}
export interface ChangeOrder {
id: string;
title: string;
type: ChangeType;
level: ChangeLevel;
duration: "永久" | "临时";
urgent: boolean;
status: ChangeStatus;
applicant: string;
org: string;
device: string;
date: string;
purpose: string;
effect: string;
before: string;
after: string;
related: string[];
materials: string[];
riskTools: string[];
flow: FlowNode[];
overdueDays?: number;
}
export const FLOW_IMPORTANT: FlowNode[] = [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "done" },
{
name: "专业会签",
kind: "会签",
roles: ["process", "process2", "quality"],
status: "current",
members: [
{ name: "王仪表(仪表)", done: true },
{ name: "周设备(设备)", done: false },
{ name: "陈质量(质量)", done: false },
],
},
{ name: "安全审查", kind: "审批", roles: ["safety"], status: "todo", locked: true },
{ name: "分管领导最终批准", kind: "最终批准", roles: ["vp"], status: "todo", locked: true },
];
export const FLOW_SIMPLE: FlowNode[] = [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "done" },
{ name: "专业审批", kind: "审批", roles: ["process"], status: "current" },
{ name: "部门负责人批准", kind: "最终批准", roles: ["dept"], status: "todo", locked: true },
];
export const CHANGES: ChangeOrder[] = [
{
id: "MOC-2026-R01-0035",
title: "R-201 反应釜搅拌器电机更换(55kW→75kW 防爆电机)",
type: "设备",
level: "重要",
duration: "永久",
urgent: false,
status: "审批中",
applicant: "张工艺",
org: "一车间 · 工艺组",
device: "R-201 反应釜 / M-201A 搅拌电机",
date: "2026-07-28",
purpose: "原 55kW 电机在高粘度工况下频繁过载跳闸,影响反应均匀性与产品质量,需更换为 75kW 防爆电机。",
effect: "消除过载跳闸(月均 3 次降至 0),搅拌电流裕量提升至 25%,产品批次合格率预计提升 1.5%。",
before: "M-201A 搅拌电机:55kW,ExdⅡBT4,额定电流 102A,原设计工况粘度 ≤3000cP。",
after: "更换为 75kW 防爆电机:ExdⅡCT4,额定电流 138A,适配粘度 ≤6000cP;电缆与开关容量同步校核升级。",
related: ["更新 P&ID(图号 PID-R201-03)", "修订电气图纸与电缆清册", "校核联锁跳车电流设定", "更新设备台账与备件清单", "操作人员培训"],
materials: ["设备数据表", "防爆合格证与材质证明", "电气负荷校核计算书", "更新后的 P&ID", "制造商安装维护手册"],
riskTools: ["AI 分析", "JSA", "检查表法"],
flow: FLOW_IMPORTANT,
},
{
id: "MOC-2026-R01-0036",
title: "聚合反应温度控制上限调整(78℃→82℃)",
type: "工艺",
level: "重要",
duration: "永久",
urgent: false,
status: "审批中",
applicant: "孙丽",
org: "一车间 · 工艺组",
device: "R-101 聚合釜 / TIC-101",
date: "2026-07-25",
purpose: "提高反应温度上限以缩短聚合时间、提升装置产能,满足新增订单需求。",
effect: "单釜反应周期缩短约 40 分钟,年产能预计提升 8%。",
before: "聚合反应温度控制范围 65–78℃,TIC-101 高报 78℃、联锁 80℃。",
after: "控制范围调整为 65–82℃,TIC-101 高报 82℃、联锁值维持 85℃ 安全边界不变。",
related: ["修订工艺卡片与操作规程", "DCS 参数与报警值修改", "更新 HAZOP 分析报告", "岗位人员再培训"],
materials: ["工艺计算书", "热平衡与飞温风险分析", "HAZOP 分析报告", "更新后的工艺卡片"],
riskTools: ["AI 分析", "HAZOP"],
flow: [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "done" },
{
name: "专业会签",
kind: "会签",
roles: ["process", "quality"],
status: "done",
members: [
{ name: "王仪表(仪表)", done: true },
{ name: "陈质量(质量)", done: true },
],
},
{ name: "安全审查", kind: "审批", roles: ["safety"], status: "current", locked: true },
{ name: "分管领导最终批准", kind: "最终批准", roles: ["vp"], status: "todo", locked: true },
],
},
{
id: "MOC-2026-R02-0038",
title: "DCS 罐区液位报警值 LIA-301 调整",
type: "工艺",
level: "一般",
duration: "永久",
urgent: false,
status: "待PSSR",
applicant: "吴强",
org: "一车间 · 罐区",
device: "V-301 储罐 / LIA-301",
date: "2026-07-20",
purpose: "原高报值偏保守,频繁误报导致操作疲劳,按最新容积表校准报警值。",
effect: "误报次数由每周 5 次降至 0,报警响应有效性提升。",
before: "LIA-301 高报 80%(对应 7.2m)。",
after: "高报调整为 85%(对应 7.65m),联锁值 90% 不变。",
related: ["DCS 组态修改", "更新报警台账", "岗位告知培训"],
materials: ["储罐容积表", "DCS 组态修改记录", "报警台账"],
riskTools: ["AI 分析", "检查表法"],
flow: FLOW_SIMPLE.map((n) => ({ ...n, status: "done" as const })),
},
{
id: "MOC-2026-R01-0039",
title: "紧急变更:V-102 安全阀起跳压力临时调整(补办手续)",
type: "设备",
level: "一般",
duration: "临时",
urgent: true,
status: "待关闭",
applicant: "张工艺",
org: "一车间 · 工艺组",
device: "V-102 缓冲罐 / PSV-102",
date: "2026-07-15",
purpose: "上游工况波动导致安全阀频繁起跳,经紧急批准临时调整起跳压力并限期恢复原设定。",
effect: "装置维持连续运行,临时期限内风险受控。",
before: "PSV-102 起跳压力 0.8MPa。",
after: "临时调整为 0.88MPa(不超过设计压力 1.0MPa 的 90%),期限 30 天,到期恢复 0.8MPa。",
related: ["恢复性检查", "更新安全阀台账", "事后风险分析补办"],
materials: ["安全阀校验报告", "紧急变更审批单", "事后 JSA 分析"],
riskTools: ["AI 分析", "JSA"],
flow: FLOW_SIMPLE.map((n) => ({ ...n, status: "done" as const })),
overdueDays: 4,
},
{
id: "MOC-2026-R03-0040",
title: "原料环己烷供应商变更(新增 B 供应商)",
type: "管理",
level: "重要",
duration: "永久",
urgent: false,
status: "实施中",
applicant: "刘芳",
org: "供应部",
device: "原料罐区 / TK-201",
date: "2026-07-18",
purpose: "引入第二供应商保障原料供应安全,降低单一来源断供风险。",
effect: "供应保障能力提升,采购成本预计下降 3%。",
before: "环己烷单一供应商 A,纯度 ≥99.5%。",
after: "新增供应商 B(纯度 ≥99.8%,已提供 MSDS 与质检报告),双源供应。",
related: ["更新合格供应商名录", "修订进厂检验规程", "更新 MSDS 档案", "卸料操作培训"],
materials: ["新供应商资质文件", "产品质检报告与 MSDS", "进厂检验规程"],
riskTools: ["AI 分析", "检查表法"],
flow: FLOW_IMPORTANT.map((n) => ({ ...n, status: "done" as const })),
},
{
id: "MOC-2026-R01-0029",
title: "操作规程修订(夏季工况)",
type: "管理",
level: "一般",
duration: "临时",
urgent: false,
status: "审批中",
applicant: "张工艺",
org: "一车间 · 工艺组",
device: "全装置",
date: "2026-06-20",
purpose: "夏季高温工况下循环水温度升高,原操作规程冷却参数不适用,需修订夏季操作参数与巡检频次。",
effect: "夏季工况下装置运行参数受控,避免超温降负荷,预计减少非计划降量 2 次/年。",
before: "操作规程(2025 版)未区分冬夏季工况,冷却参数单一。",
after: "增加夏季工况章节:循环水温度 >28℃ 时启用备用冷却塔,巡检频次由 4h 调整为 2h。",
related: ["操作规程升版发布", "岗位人员培训"],
materials: ["修订后操作规程", "参数核算表"],
riskTools: ["AI 分析", "检查表法"],
flow: [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "current" },
{ name: "专业审批", kind: "审批", roles: ["process"], status: "todo", locked: true },
{ name: "部门负责人批准", kind: "最终批准", roles: ["dept"], status: "todo", locked: true },
],
overdueDays: 3,
},
{
id: "MOC-2026-R02-0041",
title: "公用工程氮气减压阀组改造",
type: "设备",
level: "一般",
duration: "永久",
urgent: false,
status: "审批中",
applicant: "周涛",
org: "公用工程车间",
device: "氮气总管 / PV-208 减压阀组",
date: "2026-07-29",
purpose: "氮气减压阀组单路运行,检修时需停氮气,影响装置密封气供应,需改造为双路并联。",
effect: "减压阀组可在线切换检修,氮气供应连续性提升至 100%。",
before: "PV-208 单路减压,无备用回路。",
after: "新增并联减压回路 PV-208B,双路一用一备,可在线切换。",
related: ["更新 P&ID", "修订氮气系统操作规程", "更新设备台账"],
materials: ["阀门数据表", "管道单线图", "施工方案"],
riskTools: ["AI 分析", "JSA"],
flow: [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "done" },
{ name: "专业审批", kind: "审批", roles: ["process"], status: "current" },
{ name: "部门负责人批准", kind: "最终批准", roles: ["dept"], status: "todo", locked: true },
],
overdueDays: 3,
},
{
id: "MOC-2026-R03-0042",
title: "三车间自动化和安全隐患整改项目变更",
type: "管理",
level: "重要",
duration: "永久",
urgent: false,
status: "审批中",
applicant: "刘芳",
org: "三车间",
device: "三车间装置区",
date: "2026-07-31",
purpose: "落实安全隐患整改要求,对三车间自动化控制系统升级改造,消除加料互串与超温隐患。",
effect: "隐患整改闭环率 100%,自动化水平提升,误操作风险显著降低。",
before: "加料系统手动控制,存在互串与超温隐患(隐患编号 YH-2026-017)。",
after: "改为 DCS 自动控制 + 加料顺序联锁,增设独立超温切断。",
related: ["修订操作规程", "DCS 组态修改", "更新 HAZOP 分析", "岗位再培训"],
materials: ["隐患整改方案", "HAZOP 分析报告", "联锁因果表"],
riskTools: ["AI 分析", "HAZOP"],
flow: [
{ name: "部门审核", kind: "审批", roles: ["dept"], status: "done" },
{
name: "专业会签",
kind: "会签",
roles: ["process", "process2", "quality"],
status: "done",
members: [
{ name: "王仪表(仪表)", done: true },
{ name: "周设备(设备)", done: true },
{ name: "陈质量(质量)", done: true },
],
},
{ name: "安全审查", kind: "审批", roles: ["safety"], status: "done" },
{ name: "分管领导最终批准", kind: "最终批准", roles: ["vp"], status: "current" },
],
},
];
// ===================== PSSR / 验收 =====================
export interface PssrItem {
id: number;
category: string;
content: string;
owner: string;
status: "待确认" | "已确认" | "不适用" | "整改中";
photo?: boolean;
/** 完成时点:投用前(未完成禁止投用)/ 关闭前(未完成禁止关闭) */
phase?: "投用前" | "关闭前";
}
export const PSSR_ITEMS: PssrItem[] = [
{ id: 1, category: "设备完整性", content: "搅拌电机安装就位,联轴器对中合格,地脚螺栓紧固", owner: "周设备", status: "已确认", photo: true, phase: "投用前" },
{ id: 2, category: "设备完整性", content: "电机空载/负载试车合格,轴承温度、振动值在正常范围", owner: "周设备", status: "已确认", photo: true, phase: "投用前" },
{ id: 3, category: "仪表联锁", content: "电机过载保护定值按 75kW 重新整定并传动试验合格", owner: "王仪表", status: "待确认", phase: "投用前" },
{ id: 4, category: "图纸规程", content: "P&ID(PID-R201-03)与电气图纸已更新发布", owner: "王仪表", status: "已确认", phase: "关闭前" },
{ id: 5, category: "人员培训", content: "相关岗位 12 人完成新设备操作培训并考核合格", owner: "李主任", status: "待确认", phase: "投用前" },
{ id: 6, category: "应急消防", content: "现场消防器材完好,应急通道畅通", owner: "王海燕", status: "待确认", phase: "投用前" },
{ id: 7, category: "施工确认", content: "施工遗留物清理完毕,临时用电已拆除", owner: "周设备", status: "整改中", phase: "投用前" },
];
export const ACCEPT_ITEMS: PssrItem[] = [
{ id: 1, category: "一致性", content: "实施结果与批准的变更内容一致(电机型号、参数符合批准方案)", owner: "李主任", status: "待确认" },
{ id: 2, category: "连带变更", content: "5 项连带变更全部完成(图纸、台账、联锁、备件、培训)", owner: "李主任", status: "待确认" },
{ id: 3, category: "资料更新", content: "P&ID、电气图纸、设备台账已归档最新版本", owner: "王仪表", status: "待确认" },
{ id: 4, category: "运行验证", content: "连续运行 72 小时无异常,搅拌电流稳定在 118A±5%", owner: "张工艺", status: "待确认" },
];
// ===================== 关闭校验 =====================
export interface ClosureCheck {
item: string;
done: boolean;
note?: string;
}
export const CLOSURE_CHECKS: ClosureCheck[] = [
{ item: "变更验收完成(结论:基本达到 · 遗留项 2 项已登记跟踪)", done: true },
{ item: "资料上传齐全(验收报告、运行记录、恢复确认记录)", done: false, note: "缺:更新后的安全阀台账" },
{ item: "行动项全部关闭(4/4,含「关闭前完成」标记项)", done: true },
{ item: "受控文件已更新至生效版(P&ID Rev.4、操作规程)", done: false, note: "安全阀台账待更新发布" },
{ item: "培训考核完成(12/12 人),签到与成绩已归档", done: true },
];
// ===================== 风险分析 =====================
export const HAZOP_ROWS = [
{ node: "R-101 聚合釜", guide: "过高(温度)", dev: "反应温度超过 82℃", cause: "冷却水中断;TIC-101 故障;进料配比失调", cons: "飞温、冲料、超压破裂", l: 2, s: 5, measures: "增设独立高温联锁;冷却水低流量报警;HAZOP 建议 2 项已落实" },
{ node: "R-101 聚合釜", guide: "过低(温度)", dev: "温度低于 65℃", cause: "引发剂不足;夹套加热故障", cons: "反应中止、物料积压,恢复时剧烈反应", l: 3, s: 3, measures: "低温度报警;恢复升温操作程序" },
{ node: "进料系统", guide: "无(流量)", dev: "单体进料中断", cause: "进料泵故障;过滤器堵塞", cons: "釜内配比失衡,产品质量事故", l: 2, s: 3, measures: "泵一用一备;压差报警" },
{ node: "进料系统", guide: "反向", dev: "物料反向流动", cause: "停泵时止回阀失效", cons: "串料污染、计量错误", l: 2, s: 2, measures: "止回阀定期校验(检查表项)" },
];
export const JSA_ROWS = [
{ step: "1. 停机断电隔离", hazard: "残余电能、机械能意外释放", measure: "执行上锁挂牌(LOTO),验电确认", owner: "周设备" },
{ step: "2. 拆卸旧电机", hazard: "吊装伤害、挤压", measure: "持证起重工指挥,吊具检查,警戒区隔离", owner: "吊装班" },
{ step: "3. 新电机安装对中", hazard: "对中误差导致振动超标", measure: "激光对中仪,偏差 ≤0.05mm", owner: "周设备" },
{ step: "4. 接线与送电", hazard: "触电、相序错误反转", measure: "双人复核相序,点动确认转向", owner: "电气班" },
{ step: "5. 试车", hazard: "机械伤害、异常振动", measure: "空载→负载分级试车,振动在线监测", owner: "周设备" },
];
export const SCL_ROWS = [
{ item: "新电机防爆等级不低于区域要求(ExdⅡCT4)", std: "GB 50058", result: "符合" },
{ item: "电缆载流量与开关容量匹配 75kW 负荷", std: "GB 50217", result: "符合" },
{ item: "电机接地电阻 ≤4Ω", std: "GB 50169", result: "符合" },
{ item: "防护罩、联轴器护罩安装齐全", std: "企业设备规程", result: "整改后符合" },
{ item: "润滑油牌号与加注量符合制造商要求", std: "制造商手册", result: "符合" },
];
// ===================== 资料库 =====================
export const KNOWLEDGE_DOCS = [
{ name: "PID-R201-03 反应釜工艺流程图(Rev C)", cat: "工艺技术资料", device: "一车间", ver: "Rev C", date: "2026-07-29" },
{ name: "聚合岗位操作规程(2026 版)", cat: "工艺技术资料", device: "一车间", ver: "V2026", date: "2026-07-26" },
{ name: "M-201A 搅拌电机设备台账", cat: "设备资料", device: "一车间", ver: "V3.2", date: "2026-07-28" },
{ name: "环己烷 MSDS(供应商 B)", cat: "化学品资料", device: "原料罐区", ver: "V1.0", date: "2026-07-18" },
{ name: "AQ/T 3034 化工企业工艺安全管理实施导则", cat: "法规标准库", device: "全厂", ver: "2013 版", date: "2025-12-01" },
{ name: "PSSR 检查表模板(设备类)", cat: "检查表模板库", device: "全厂", ver: "V2.1", date: "2026-05-10" },
{ name: "2025 年度典型变更案例汇编", cat: "历史变更案例库", device: "全厂", ver: "2025 版", date: "2026-01-15" },
{ name: "HAZOP 分析报告(R-101 温度变更)", cat: "历史变更案例库", device: "一车间", ver: "V1.0", date: "2026-07-26" },
];
// ===================== 报表数据 =====================
export const MONTHLY_COUNTS = [
{ m: "2月", count: 4 }, { m: "3月", count: 6 }, { m: "4月", count: 5 },
{ m: "5月", count: 8 }, { m: "6月", count: 7 }, { m: "7月", count: 9 },
];
export const TYPE_DIST = [
{ name: "工艺", value: 16 }, { name: "设备", value: 14 }, { name: "管理", value: 9 },
];
export const CYCLE_TREND = [
{ m: "2月", days: 12.5 }, { m: "3月", days: 11.2 }, { m: "4月", days: 10.8 },
{ m: "5月", days: 9.6 }, { m: "6月", days: 8.9 }, { m: "7月", days: 8.2 },
];
export const OVERDUE_LIST = [
{ id: "MOC-2026-R01-0039", title: "V-102 安全阀起跳压力临时调整", stage: "待关闭", days: 4 },
{ id: "MOC-2026-R02-0031", title: "冷冻盐水泵 P-103 叶轮材质变更", stage: "待验收", days: 7 },
{ id: "MOC-2026-R01-0029", title: "操作规程修订(夏季工况)", stage: "审批中", days: 3 },
];
// 状态色阶梯:全站状态标签唯一来源(工作台 / 台账 / 我的任务 / 审批中心共用),
// 色相全部取自品牌色板——amber=进行中提醒,品牌蓝=审批通过/执行,violet=投用前检查,emerald=验收/完成(浅→深递进),品牌红=待关闭关闸提醒
export const STATUS_COLOR: Record<ChangeStatus, string> = {
审批中: "bg-amber-100 text-amber-700 border-amber-200",
已批准: "bg-[#DFE9F6] text-[#17407F] border-[#ACC6E5]",
实施中: "bg-[#1D4E9C]/10 text-[#1D4E9C] border-[#1D4E9C]/30",
待PSSR: "bg-violet-100 text-violet-700 border-violet-200",
待验收: "bg-emerald-50 text-emerald-600 border-emerald-200",
待关闭: "bg-[#E15555]/10 text-[#E15555] border-[#E15555]/30",
已关闭: "bg-emerald-100 text-emerald-700 border-emerald-200",
};
export const LEVEL_COLOR: Record<ChangeLevel, string> = {
重要: "bg-red-100 text-red-700 border-red-200",
一般: "bg-slate-100 text-slate-600 border-slate-200",
};
// ===================== 变更台账 =====================
export interface LedgerRow {
id: string;
changeId?: string; // 关联 CHANGES,可打开完整详情
title: string;
type: ChangeType;
level: ChangeLevel;
duration: "永久" | "临时";
urgent?: boolean;
applyTime: string; // 申请时间
dept: string; // 申请部门
applicant: string; // 申请人
planUse: string; // 计划投用时间
status: ChangeStatus;
statusDetail: string; // 当前环节说明
statusTime: string; // 状态更新时间
overdueDays?: number;
approveTime?: string; // 审批通过时间
useTime?: string; // 实际投用时间
handlers: { name: string; done: boolean }[]; // 接班人(当前待办/已办)
}
export const LEDGER_ROWS: LedgerRow[] = [
{ id: "MOC-2026-R01-0035", changeId: "MOC-2026-R01-0035", title: "R-201 反应釜搅拌器电机更换(55kW→75kW 防爆电机)", type: "设备", level: "重要", duration: "永久", applyTime: "2026-07-28 09:12", dept: "一车间", applicant: "张工艺", planUse: "2026-08-10", status: "审批中", statusDetail: "专业会签中(周设备、王仪表待签)", statusTime: "2026-07-30 14:20", handlers: [{ name: "王仪表", done: true }, { name: "周设备", done: false }, { name: "王仪表", done: false }] },
{ id: "MOC-2026-R01-0036", changeId: "MOC-2026-R01-0036", title: "聚合反应温度控制上限调整(78℃→82℃)", type: "工艺", level: "重要", duration: "永久", applyTime: "2026-07-25 10:05", dept: "一车间", applicant: "孙丽", planUse: "2026-08-05", status: "审批中", statusDetail: "安全审查(王海燕)", statusTime: "2026-07-29 16:40", handlers: [{ name: "王海燕", done: false }] },
{ id: "MOC-2026-R02-0038", changeId: "MOC-2026-R02-0038", title: "DCS 罐区液位报警值 LIA-301 调整", type: "工艺", level: "一般", duration: "永久", applyTime: "2026-07-20 08:30", dept: "一车间", applicant: "吴强", planUse: "2026-07-31", status: "待PSSR", statusDetail: "培训 / PSSR 资料已传 · 待确认投用", statusTime: "2026-07-27 11:15", approveTime: "2026-07-26 16:40", handlers: [{ name: "吴强", done: false }] },
{ id: "MOC-2026-R01-0039", changeId: "MOC-2026-R01-0039", title: "V-102 安全阀起跳压力临时调整(紧急补办)", type: "设备", level: "一般", duration: "临时", urgent: true, applyTime: "2026-07-15 19:40", dept: "一车间", applicant: "张工艺", planUse: "2026-07-16(已投用)", status: "待关闭", statusDetail: "待关闭确认(资料更新核查中)", statusTime: "2026-07-27 09:02", approveTime: "2026-07-15 21:05", useTime: "2026-07-16 06:30", overdueDays: 4, handlers: [{ name: "李主任", done: false }] },
{ id: "MOC-2026-R03-0040", changeId: "MOC-2026-R03-0040", title: "原料环己烷供应商变更(新增 B 供应商)", type: "管理", level: "重要", duration: "永久", applyTime: "2026-07-18 14:22", dept: "供应部", applicant: "刘芳", planUse: "2026-08-01", status: "实施中", statusDetail: "实施准备中 · 培训 / PSSR 资料待上传", statusTime: "2026-07-26 10:30", handlers: [{ name: "刘芳", done: false }] },
{ id: "MOC-2026-R02-0031", title: "冷冻盐水泵 P-103 叶轮材质变更", type: "设备", level: "一般", duration: "永久", applyTime: "2026-06-28 09:50", dept: "二车间", applicant: "周涛", planUse: "2026-07-15", status: "待验收", statusDetail: "变更验收(72h 运行验证)", statusTime: "2026-07-24 15:44", overdueDays: 7, handlers: [{ name: "李主任", done: false }] },
{ id: "MOC-2026-R01-0029", title: "操作规程修订(夏季工况)", type: "管理", level: "一般", duration: "临时", applyTime: "2026-06-20 11:26", dept: "一车间", applicant: "张工艺", planUse: "2026-07-01", status: "审批中", statusDetail: "部门审核(李主任)", statusTime: "2026-06-21 08:40", handlers: [{ name: "李主任", done: false }] },
{ id: "MOC-2026-R02-0033", title: "包装线贴标机控制程序升级", type: "设备", level: "一般", duration: "永久", applyTime: "2026-07-08 13:35", dept: "二车间", applicant: "吴强", planUse: "2026-08-02", status: "已批准", statusDetail: "待实施(计划 8 月 2 日投用)", statusTime: "2026-07-22 09:12", handlers: [{ name: "周设备", done: false }] },
{ id: "MOC-2026-R03-0027", title: "化验室通风橱整体更换", type: "设备", level: "一般", duration: "永久", applyTime: "2026-06-12 15:10", dept: "质量部", applicant: "陈静", planUse: "2026-06-25", status: "已关闭", statusDetail: "关闭确认完成,已归档", statusTime: "2026-07-02 10:18", handlers: [{ name: "钱峰", done: true }] },
{ id: "MOC-2026-R01-0024", title: "氮气管网压力分级调整", type: "工艺", level: "重要", duration: "永久", applyTime: "2026-05-30 09:00", dept: "一车间", applicant: "孙丽", planUse: "2026-06-20", status: "已关闭", statusDetail: "关闭确认完成,已归档", statusTime: "2026-06-28 16:30", handlers: [{ name: "李主任", done: true }, { name: "刘副总", done: true }] },
];
// 演示数据:执行阶段变更的培训签到表 / PSSR 签字版上传状态(上传即视为完成确认并随单归档,系统不做内容识别)
export const PSSR_UPLOADS: Record<string, { train?: string; pssr?: string }> = {
"MOC-2026-R02-0038": { train: "培训签到表-照片.jpg", pssr: "PSSR 检查确认表-签字版.pdf" },
"MOC-2026-R02-0031": { train: "培训签到表-照片.jpg", pssr: "PSSR 检查确认表-签字版.pdf" },
"MOC-2026-R03-0027": { train: "培训签到表-归档.pdf", pssr: "PSSR 检查确认表-归档版.pdf" },
"MOC-2026-R01-0024": { train: "培训签到表-归档.pdf", pssr: "PSSR 检查确认表-归档版.pdf" },
};
// ===================== 演示用轻量全局状态(提交 / 审批真实推进,全站联动) =====================
type DemoListener = () => void;
const demoListeners = new Set<DemoListener>();
export function subscribeDemo(fn: DemoListener) {
demoListeners.add(fn);
return () => { demoListeners.delete(fn); };
}
function emitDemo() { demoListeners.forEach((f) => f()); }
// ===================== 催办记录(车间主任催办 → 申请人操作台实时提示,全站同源) =====================
export interface UrgeRecord { id: string; changeId: string; title: string; applicant: string; by: string; time: string; }
export const URGE_RECORDS: UrgeRecord[] = [];
let urgeSeq = 1;
/** 车间主任催办:写入同源记录并广播,申请人操作台即时出现催办提示 */
export function urgeChange(changeId: string, byRole: RoleId) {
const row = LEDGER_ROWS.find((r) => r.id === changeId || r.changeId === changeId);
const c = CHANGES.find((x) => x.id === changeId);
const by = ROLES.find((r) => r.id === byRole)?.person ?? byRole;
URGE_RECORDS.unshift({
id: `URGE-${urgeSeq++}`,
changeId,
title: row?.title ?? c?.title ?? changeId,
applicant: row?.applicant ?? c?.applicant ?? "",
by,
time: nowStr(),
});
emitDemo();
}
let demoSeq = 43;
export function nextChangeId() {
return `MOC-2026-R01-${String(demoSeq++).padStart(4, "0")}`;
}
function nowStr() {
const d = new Date();
const p = (n: number) => String(n).padStart(2, "0");
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;
}
/** 申请页提交:生成真实变更单,台账 / 审批中心 / 我的任务 / 角标联动 */
export function submitChange(c: ChangeOrder) {
CHANGES.unshift(c);
const cur = c.flow.find((n) => n.status === "current");
LEDGER_ROWS.unshift({
id: c.id,
changeId: c.id,
title: c.title,
type: c.type,
level: c.level,
duration: c.duration,
urgent: c.urgent || undefined,
applyTime: nowStr(),
dept: c.org.split("·")[0].trim(),
applicant: c.applicant,
planUse: c.date || "待定",
status: c.status,
statusDetail: cur ? `${cur.name}(待处理)` : "审批中",
statusTime: nowStr(),
handlers: (cur?.roles ?? []).map((rid) => ({ name: ROLES.find((r) => r.id === rid)?.person ?? rid, done: false })),
});
emitDemo();
}
/** 详情页同意:真实推进流程节点(会签按人标记,全签通过才流转;末节点后进入待PSSR) */
export function advanceFlow(id: string, role: RoleId) {
const c = CHANGES.find((x) => x.id === id);
if (!c) return;
const idx = c.flow.findIndex((n) => n.status === "current");
if (idx < 0) return;
const node = c.flow[idx];
if (node.kind === "会签" && node.members) {
const person = ROLES.find((r) => r.id === role)?.person;
const m = node.members.find((x) => x.name.startsWith(person ?? ""));
if (m) m.done = true;
if (!node.members.every((x) => x.done)) { emitDemo(); return; }
}
node.status = "done";
const next = c.flow[idx + 1];
if (next) {
next.status = "current";
next.locked = false;
} else {
c.status = "待PSSR";
}
const row = LEDGER_ROWS.find((r) => r.changeId === id || r.id === id);
if (row) {
const cur = c.flow.find((n) => n.status === "current");
row.status = c.status;
row.statusTime = nowStr();
row.statusDetail = cur ? `${cur.name}(待处理)` : "审批完成,进入投用前确认";
row.handlers = cur
? cur.roles.map((rid) => ({ name: ROLES.find((r) => r.id === rid)?.person ?? rid, done: false }))
: [{ name: c.applicant, done: false }];
}
emitDemo();
}
// ===================== 延期 / 转永久子单(申请人提交 → 属地 / 安全 / 公司领导审批 → 回写原单,全站联动) =====================
export interface SubOrder {
id: string; // 子单号:原单号-Y1(延期)/ -Z1(转永久)
parentId: string; // 原变更单号
parentTitle: string;
kind: "extend" | "permanent";
applicant: string;
reason: string;
newDeadline?: string; // 延期子单:申请延期至
status: "审批中" | "已通过" | "已驳回";
submitTime: string;
steps: { role: RoleId; name: string; done: boolean }[]; // 会签:全员同意即通过
rejectNote?: string;
}
export const SUB_ORDERS: SubOrder[] = [];
/** 申请人提交延期 / 转永久子单:延期走简化审批(属地负责人 + 变更主管部门);转永久按永久变更审批链(属地 → 安全 → 公司领导) */
export function submitSubOrder(o: { parentId: string; parentTitle: string; kind: "extend" | "permanent"; applicant: string; reason: string; newDeadline?: string }) {
const steps: SubOrder["steps"] = o.kind === "extend"
? [{ role: "dept", name: "李主任", done: false }, { role: "safety", name: "王海燕", done: false }]
: [{ role: "dept", name: "李主任", done: false }, { role: "safety", name: "王海燕", done: false }, { role: "vp", name: "刘副总", done: false }];
SUB_ORDERS.unshift({
id: `${o.parentId}-${o.kind === "extend" ? "Y1" : "Z1"}`,
...o,
status: "审批中",
submitTime: nowStr(),
steps,
});
emitDemo();
return SUB_ORDERS[0];
}
/** 子单审批(同意 / 驳回):全员同意 → 已通过并回写原单;任一驳回 → 已驳回,申请人可修改后重新提交 */
export function decideSubOrder(id: string, role: RoleId, approve: boolean, note?: string) {
const s = SUB_ORDERS.find((x) => x.id === id);
if (!s || s.status !== "审批中") return;
const st = s.steps.find((x) => x.role === role);
if (!st || st.done) return;
st.done = true;
if (!approve) {
s.status = "已驳回";
s.rejectNote = note || "";
} else if (s.steps.every((x) => x.done)) {
s.status = "已通过";
}
emitDemo();
}
// ===================== 工作台 / 个人统计共享数据源(唯一口径,避免双写漂移) =====================
/** 临时变更到期监视(申请人工作台「临时变更到期提醒情况」与个人统计报表共用同一来源) */
export const TEMP_WATCH = [
{ label: "正常(到期 > 7 天)", n: 1, c: "#7CC242", note: "循环水加药泵冲程临时调整 · 剩 17 天" },
{ label: "临期(到期 ≤ 7 天)", n: 1, c: "#F5A623", note: "循环水旁滤器临时绕流运行 · 剩 6 天,已触发提醒" },
{ label: "已超期", n: 1, c: "#E15555", note: "V-102 安全阀起跳压力临时调整 · 超期 4 天(已延期 1 次)" },
];
/** 培训确认待办(工作台「待确认培训」卡片与「我的任务 · 培训确认」同源) */
export const TRAIN_TODO = [
{ id: "MOC-2026-R01-0035", title: "搅拌电机更换操作培训", target: "R-201 岗位操作人员(4 人)、维修班(2 人)" },
];
/** 资料归档待办(工作台「待上传资料」卡片与「待我处理 · 资料关闭」同源:验收 / 归档材料补交) */
export const DOC_TODO = [
{ id: "MOC-2026-R02-0038", title: "DCS 罐区液位报警值 LIA-301 调整", missing: "验收报告与运行数据" },
{ id: "MOC-2026-R01-0039", title: "紧急变更:V-102 安全阀起跳压力临时调整(补办手续)", missing: "更新后的 P&ID / 操作规程(受控最新版)、设备 / 联锁台账更新记录" },
];
/** 尚未关闭变更状态分布:四段口径固定,数量从 CHANGES 实时推导(0 项也保留展示,保证口径稳定)
* 对应三大流转阶段:① 申请提交后 / 会签中 / 审批中;② 审批通过后 → 变更关闭前(含投用、验收);③ 变更关闭 */
export const OPEN_STAGES: { name: string; match: ChangeStatus[]; c: string }[] = [
{ name: "审批中(含会签)", match: ["审批中"], c: "#F5A623" },
{ name: "已批准待投用", match: ["已批准", "待PSSR", "实施中"], c: "#1D4E9C" },
{ name: "待验收", match: ["待验收"], c: "#7CC242" },
{ name: "待关闭", match: ["待关闭"], c: "#E15555" },
];
export function countOpenStatus(list: { status: ChangeStatus }[]) {
return OPEN_STAGES.map((s) => ({ name: s.name, c: s.c, n: list.filter((x) => s.match.includes(x.status)).length }));
}
// ===================== 统一待办推导(全站同源:工作台卡片 / 侧边栏角标 / 我的任务 / 审批中心) =====================
/** 判断变更是否停在当前角色的待办节点。
* 会签节点按成员粒度判定:已签署的成员(按角色对应人员姓名匹配)不再计入其待办。 */
export function isPendingFor(c: ChangeOrder, role: RoleId): boolean {
if (c.status !== "审批中") return false;
const node = c.flow.find((n) => n.status === "current");
if (!node) return false;
if (node.kind === "会签" && node.members && node.members.length > 0) {
const person = ROLES.find((r) => r.id === role)?.person;
const me = person ? node.members.find((m) => m.name.startsWith(person)) : undefined;
if (me) return !me.done;
}
return node.roles.includes(role);
}
/** 当前角色的实时待审批变更列表(唯一数据源) */
export function pendingApprovals(role: RoleId): ChangeOrder[] {
return CHANGES.filter((c) => isPendingFor(c, role));
}
/** 执行阶段(审批通过后 → 关闭前)的变更:投用准备与验收跟踪 */
export function executionStage(list: ChangeOrder[] = CHANGES): ChangeOrder[] {
return list.filter((c) => c.status === "待PSSR" || c.status === "待验收");
}
/** 超期未关闭变更(待关闭且已超期) */
export function overdueClosing(list: ChangeOrder[] = CHANGES): ChangeOrder[] {
return list.filter((c) => c.status === "待关闭" && (c.overdueDays ?? 0) > 0);
}
/** 专业人员「技术把关工作记录」:从 CHANGES 实时推导(与台账 / 待办同源,演示数据范围内统计)
* - signed:已完成的会签 / 审批签署次数(会签按成员粒度、审批节点按角色判定)
* - involved:涉及本专业的在办变更数(未关闭且流程中含本角色节点)
* - 驳回次数暂无结构化记录字段,演示版不展示;参与风险分析次数来自分析组成员(选择式)记录 */
export function profWorkStats(role: RoleId) {
const person = ROLES.find((r) => r.id === role)?.person ?? "";
let signed = 0;
for (const c of CHANGES) {
for (const n of c.flow) {
if (n.kind === "会签" && n.members?.length) {
const me = n.members.find((m) => m.name.startsWith(person));
if (me?.done) signed += 1;
} else if (n.status === "done" && n.roles.includes(role)) {
signed += 1;
}
}
}
const involved = CHANGES.filter(
(c) => c.status !== "已关闭" && c.flow.some((n) => n.roles.includes(role))
).length;
return { signed, involved };
}
+9 -9
View File
@@ -1,15 +1,13 @@
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { useAppStore } from '@/store/modules/app';
import { ref, onMounted } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
import { changePasswordApi } from '@/service/api/user';
import { changePasswordApi } from '@/service/api/auth';
import { clearAuthStorage } from '@/store/modules/auth/shared';
const appStore = useAppStore();
const themeStore = useThemeStore();
const { toLogin } = useRouterPush();
const gap = computed(() => (appStore.isMobile ? 0 : 16));
const formModel = ref<{oldPassword: string;password: string;confirmPassword: string;}>({
oldPassword: '',
@@ -37,11 +35,13 @@ const submitForm = async (e: MouseEvent) => {
if (!errors) {
btnLoading.value = true;
const {error} = await changePasswordApi({
oldPassword: formModel.value.oldPassword,
password: formModel.value.password,
old_password: formModel.value.oldPassword,
new_password: formModel.value.password,
confirm_password: formModel.value.confirmPassword,
});
if(!error){
window.$message?.success('修改成功')
window.$message?.success('修改成功,请重新登录')
clearAuthStorage();
toLogin();
}
btnLoading.value = false;
@@ -61,7 +61,7 @@ onMounted(() => {
<!-- 修改密码 -->
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<div class="border mb-3 py-2 px-3" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24">
<div class="h-100% flex items-center gap-2">
<Icon icon="boxicons:lock-open" class="size-16px" :style="{ color: themeStore.themeColor }" />