diff --git a/admin-tools/crawler/src/edu_crawler/schemas/external-job-source.schema.json b/admin-tools/crawler/src/edu_crawler/schemas/external-job-source.schema.json index ea8d4c4..1133d7c 100644 --- a/admin-tools/crawler/src/edu_crawler/schemas/external-job-source.schema.json +++ b/admin-tools/crawler/src/edu_crawler/schemas/external-job-source.schema.json @@ -210,7 +210,7 @@ "maxLength": 100 }, "uniqueItems": true, - "description": "基于技能词典提取并归一的技能标签。" + "description": "使用技能词典提取并统一名称的技能标签。" }, "keywords": { "type": "array", diff --git a/admin-tools/crawler/src/edu_crawler/schemas/school-employment.schema.json b/admin-tools/crawler/src/edu_crawler/schemas/school-employment.schema.json index 23f58b1..917ef09 100644 --- a/admin-tools/crawler/src/edu_crawler/schemas/school-employment.schema.json +++ b/admin-tools/crawler/src/edu_crawler/schemas/school-employment.schema.json @@ -1,8 +1,8 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.edu-industry.cn/school-employment/2.2.0/schema.json", - "title": "SCHOOL-EMPLOYMENT V2.2 校内就业事实", - "description": "职业院校毕业生就业事实统一契约,采用租户隔离和身份最小化设计。", + "title": "SCHOOL-EMPLOYMENT V2.2 校内就业数据", + "description": "职业院校毕业生就业数据契约,要求租户隔离,并将身份字段限制在业务必需的最少范围。", "type": "object", "additionalProperties": false, "required": [ diff --git a/admin-tools/crawler/src/edu_crawler/schemas/school-internship.schema.json b/admin-tools/crawler/src/edu_crawler/schemas/school-internship.schema.json index fd494f0..c58b45b 100644 --- a/admin-tools/crawler/src/edu_crawler/schemas/school-internship.schema.json +++ b/admin-tools/crawler/src/edu_crawler/schemas/school-internship.schema.json @@ -1,8 +1,8 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.edu-industry.cn/school-internship/2.1.0/schema.json", - "title": "SCHOOL-INTERNSHIP V2.1 校内实习事实", - "description": "职业院校学生实习事实统一契约,采用租户隔离、身份最小化和证据引用设计。", + "title": "SCHOOL-INTERNSHIP V2.1 校内实习数据", + "description": "职业院校学生实习数据契约,要求租户隔离,将身份字段限制在业务必需的最少范围,并引用评价记录。", "type": "object", "additionalProperties": false, "required": [ diff --git a/admin-tools/demo/PRODUCTION_ARCHITECTURE.md b/admin-tools/demo/PRODUCTION_ARCHITECTURE.md index 30f73d3..0d8aba6 100644 --- a/admin-tools/demo/PRODUCTION_ARCHITECTURE.md +++ b/admin-tools/demo/PRODUCTION_ARCHITECTURE.md @@ -44,7 +44,7 @@ | Data Query Service | 标准、源端、原始快照和隔离记录的分页检索、字段权限与证据追溯 | Lakehouse/OLAP + 检索引擎 | | Audit Service | 统一 trace_id、事件签名、证据和留存 | WORM/Object Lock | | Operations Service | 告警、问题、工单、SLA、指派、处置时间线和通知待办 | PostgreSQL + 事件总线 | -| Release Approval Service | 候选版本、质量门禁、职责分离审批、稳定别名发布与回滚 | PostgreSQL + 策略引擎 | +| Release Approval Service | 候选版本、发布质量检查、职责分离审批、稳定别名发布与回滚 | PostgreSQL + 策略引擎 | | Tenant Delivery Service | 逐租户发送状态、幂等重试、回执验签、记录数/SHA校验和单租户回滚 | PostgreSQL + 消息队列 | ## 3. 连接器 SPI @@ -62,13 +62,13 @@ parse(snapshot) 解析为来源 Schema health() 返回入口可达性、延迟和错误分类 ``` -参考实现位于 [`../crawler/`](../crawler/),逐来源接入方式和授权门禁见 [`../../docs/crawler-source-implementation.md`](../../docs/crawler-source-implementation.md)。连接器运行时必须遵守以下硬约束: +参考实现位于 [`../crawler/`](../crawler/),逐来源接入方式和启用条件见 [`../../docs/crawler-source-implementation.md`](../../docs/crawler-source-implementation.md)。连接器运行时必须遵守以下要求: - 所有外部来源默认禁用,只有来源审批状态为 `approved` 才允许公网运行; - 商业平台仅接入官方合作 API 或授权数据包,不实现登录自动化、验证码处理、私有接口逆向和反自动化规避; - 公开页面任务同时执行书面授权、robots.txt、域名 allowlist、公共地址解析和来源级限速检查; - 重定向后的每个 URL 重新执行相同安全校验,禁止访问回环、内网、链路本地和云元数据地址; -- User-Agent 必须标识本系统并提供真实技术联系邮箱,不伪装普通浏览器; +- User-Agent 必须标识本系统并提供可联系的技术邮箱,不伪装普通浏览器; - Authorization、Cookie 和签名密钥只从 Vault/KMS 引用注入,不写入任务、Raw、日志或异常; - 登录页、验证码、安全验证、访问封禁和结构变化均触发停止或隔离,不尝试绕过。 @@ -148,7 +148,7 @@ RUNNING → THROTTLED → RUNNING - 来源状态和平台状态; - 原始版本、解析版本、标准版本和数据产品版本。 -跨来源相似岗位不能直接删除,应形成岗位信号簇: +跨来源相似岗位不能直接删除,应归入同一个岗位信号组: ```text JobSignalCluster @@ -197,7 +197,7 @@ JobSignalCluster - 每个文件的 SHA-256; - 租户范围、截止日期和上一稳定版本。 -### 候选、审批与租户交付闭环 +### 候选、审批与租户交付流程 Manifest 生成与发布必须是两个不同事务: @@ -216,17 +216,17 @@ ISSUE / WORK_ORDER → ACKNOWLEDGED(record_count 与 SHA-256 同时通过) ``` -- `FIX_REPLAY`、`WAIVE`、`DISCARD` 必须记录原因、复核人、操作者、时间、trace_id 和证据;动作只追加,不可覆盖。只有 `FIX_REPLAY` 同时满足重放记录数一致、质量规则全量通过和独立复核签名时,才可写入 `VERIFIED` 并解除候选版本质量门禁。 +- `FIX_REPLAY`、`WAIVE`、`DISCARD` 必须记录原因、复核人、操作者、时间、trace_id 和证据;动作只追加,不可覆盖。只有 `FIX_REPLAY` 同时满足重放记录数一致、质量规则全部通过和独立复核签名时,才可写入 `VERIFIED` 并允许候选版本继续提交。 - `WAIVE` 不等于质量验证通过,若产品允许风险放行,必须进入单独的风险豁免审批状态、风险接受人和到期时间;`DISCARD` 必须先验证丢弃范围、完整性阈值和候选差异并重建候选。两者不得复用普通 `VERIFIED/PASS`。 - `PACKAGE-MANIFEST V1.2` 增加 `release_id` 与 `release_status`。每个租户数据文件必须携带自身记录数和 SHA-256,`tenant_scope`、文件路径和租户授权清单必须一致。 -- 候选 Manifest 的 `release_status` 必须为 `DRAFT`,并在提交审批时冻结;驳回后旧候选失效。发布事务生成 `PUBLISHED` Manifest,`approval_reference` 固定引用真实 `APPROVED` 审批单。 +- 候选 Manifest 的 `release_status` 必须为 `DRAFT`,提交审批后不可修改;驳回后旧候选失效。发布事务生成 `PUBLISHED` Manifest,`approval_reference` 必须引用状态为 `APPROVED` 的审批单。 - 候选 Manifest 生成接口必须接受幂等键或服务端输入指纹;相同产品、租户、截止日期、格式、质量处置和交付摘要不得重复产生候选或审计事件。 - 后端必须强制申请人与审批人不同,前端校验只能作为交互提示。批准后再以原子别名切换发布稳定版本。 - 每个学校是独立交付状态机:`PENDING → SENDING → DELIVERED → ACKNOWLEDGED`;异常使用 `FAILED → RETRYING`,并支持单租户 `ROLLED_BACK`。成功租户的幂等键阻止重复发送。 - 只有回执记录数等于包记录数、回执 SHA-256 等于 Manifest 文件摘要且回执签名有效时,服务端才能写入 `ACKNOWLEDGED`。 - 全局版本回滚和单租户回滚是不同操作。全局回滚必须先创建独立回滚审批,审批人与申请人分离,再执行稳定别名切换;两类回滚均需目标上一稳定版本、范围锁与不可变审计事件。 -原型中的 `localStorage` 只用于静态演示刷新持久化,不能作为跨端协议或生产事实源。 +原型中的 `localStorage` 只用于静态演示刷新后继续操作,不能作为跨端协议或正式数据来源。 ## 9. 安全与运维 @@ -250,7 +250,7 @@ ISSUE / WORK_ORDER - `POST /issues/{id}/acknowledge|assign|investigate|resolve|close` 与带版本条件的工单更新; - `POST /quality-dispositions`、`POST /quality-dispositions/{id}/verify`,处置动作写不可变事件存储; -- `POST /releases/{id}/manifest|submit|approve|reject|publish|rollback`,服务端执行质量门禁和职责分离; +- `POST /releases/{id}/manifest|submit|approve|reject|publish|rollback`,服务端检查发布质量条件和职责分离; - `POST /deliveries/{tenant_id}/send|retry|acknowledge|rollback`,执行租户授权、幂等、签名和回执校验; - `GET /notifications` 与统一审计事件查询/导出 API; - OAuth/OIDC、RBAC/ABAC、审批人实时身份、请求签名、幂等键、乐观锁、限流和 WORM 审计。 diff --git a/admin-tools/demo/README.md b/admin-tools/demo/README.md index 6ef31c9..8221806 100644 --- a/admin-tools/demo/README.md +++ b/admin-tools/demo/README.md @@ -1,6 +1,6 @@ # 产教数据中台,厂商运营原型 -本目录用于讨论厂商侧招聘数据采集与治理产品。商业招聘平台、公共就业平台和校内系统统一作为正式数据来源纳入数据生产与治理体系。 +本目录展示厂商如何管理招聘数据采集、检查、发布和学校交付。数据来源包括商业招聘平台、公共就业平台和校内系统。 ## 运行 @@ -14,7 +14,7 @@ python3 -m http.server 8080 ## 产品定位 -这不是多个招聘网站爬虫脚本的简单集合,而是面向产教分析的数据生产控制面: +该页面用于管理产教分析所需的数据: 1. 注册和版本化管理商业、公共、校内三类数据源; 2. 调度采集任务,管理地域、行业、岗位族、分片、失败隔离和增量水位; @@ -49,40 +49,40 @@ python3 -m http.server 8080 - **数据标准**:外部岗位、校内就业、交付 Manifest 三套版本化契约。 - **导入与导出**:文件拖放、CSV 头部预检、样例下载、Manifest 生成和记录导出。 - **质量与归一**:质量规则、发布阈值、岗位别名人工确认和批量处理。 -- **审计与交付**:采集、质量、发布、导入导出事件及证据链。 +- **审计与交付**:采集、质量、发布、导入导出事件及相关记录。 -## 原型黄金闭环 +## 可重复演示流程 -“运营处置”提供一条可重复演示、刷新后保留的最小生产黄金路径: +“运营处置”提供一条刷新后仍可继续的示例流程: ```text 告警 → 确认 → 指派 → 开始排障 → 修复并重放 → 记录数 / 规则 / 复核签名 VERIFIED → 豁免 / 丢弃 → REVIEWED_BLOCKED,继续阻断 - → REL-20260823-01 候选版本 → 生成并冻结候选 Manifest → 提交审批 + → REL-20260823-01 候选版本 → 生成候选 Manifest → 提交后不可修改 → 独立审批人批准 / 驳回 → 发布 → 逐学校发送状态 → 记录数 + SHA-256 回执 → ACKNOWLEDGED / 单校失败重试 / 单租户回滚 → 全局回滚申请 → 独立回滚审批 → 执行稳定别名回滚 ``` -- 杭州人才网问题 `ISSUE-HZRC-20260823-01` 可完整流转。只有最后一次处置是 `FIX_REPLAY`,且重放记录数一致、质量规则通过、复核签名存在时,候选版本质量门禁才进入 `PASS`。 +- 杭州人才网问题 `ISSUE-HZRC-20260823-01` 可走完上述流程。只有最后一次处置是 `FIX_REPLAY`,且重放记录数一致、质量规则通过、复核签名存在时,候选版本的发布质量检查才进入 `PASS`。 - `WAIVE` 与 `DISCARD` 的独立复核会写入 `REVIEWED_BLOCKED`,分别提示另行风险审批或重建候选,不会复用 `VERIFIED/PASS`。 - 发布申请人默认为陈致远,审批人若选择同一人会被四眼规则阻止。 -- 候选发布必须同时满足质量门禁和候选 Manifest 已生成;审批中 Manifest 冻结,驳回后返回草稿并使旧候选失效。 +- 候选版本必须通过发布质量检查并生成 Manifest 后才能提交;审批期间 Manifest 不可修改,驳回后返回草稿并使旧候选失效。 - 候选 Manifest 使用输入指纹保证重复生成幂等;产品、租户、截止日期、格式、质量处置和交付摘要未变化时复用原候选,不重复写审计或交换日志。 - 候选版本、数据版本和包分别为 `REL-20260823-01`、`V2026.08.23`、`EDU-PKG-20260823-01`。 - 杭州科技职业技术学院使用共享标识 `TENANT-HZVTC`。另外展示浙江机电职业技术大学和宁波城市职业技术学院,交付状态按租户隔离。 - 原型仓库使用 `localStorage` 命名空间 `eduIndustry.vendorOperations.v1`,当前 `schemaVersion=2`,包含 issues、workOrders、qualityDispositions、releases、approvals、deliveries、auditEvents。页面提供“重置演示数据”恢复种子。 - `PACKAGE-MANIFEST V1.2` 新增 `release_id` 和 `release_status`,并按三个租户输出彼此独立的记录数与 SHA-256 文件项。候选 Manifest 保持 `DRAFT`,正式发布时生成 `PUBLISHED` Manifest,`approval_reference` 固定引用 `APPROVED` 审批单。 -- 全局回滚和单租户回滚严格分离。全局回滚必须填写原因、由不同于申请人的审批人批准后才可执行,审计证据保存目标稳定版本、审批引用和影响范围锁。 +- 全局回滚和单租户回滚分开办理。全局回滚必须填写原因,并由另一名审批人批准后才可执行;审计记录保存目标稳定版本、审批引用和执行时确定的影响范围,执行过程中不得扩大范围。 - 静态演示的审计、质量处置、问题时间线和交换日志采用明确保留上限;正式系统必须使用服务端分页、归档和 WORM 审计。 ## 静态跨端边界 本目录是**厂商端静态 SPA 原型**,与仓库根目录下的校园端 `/demo/` 没有运行时连接。双方仅通过约定标识(`TENANT-HZVTC`、`EDU-PKG-20260823-01`、`V2026.08.23`)对照展示,不共享浏览器存储,也不通过静态页面传输数据。 -按钮中的发送、回执、重试与回滚均为本地状态机模拟:不会访问学校接口、不会写入校园端、不会发送真实数据。正式跨端同步必须由经过鉴权、签名、幂等和审计控制的服务端 API 执行。 +按钮中的发送、回执、重试与回滚均为本地状态机模拟:不会访问学校接口、不会写入校园端,也不会发送数据。正式跨端同步必须由服务端 API 完成身份校验、签名、重复请求处理和操作记录。 ## 标准文件 @@ -91,10 +91,10 @@ python3 -m http.server 8080 - 商业和公共招聘平台的统一岗位信号契约 - `schemas/school-employment.schema.json` - `SCHOOL-EMPLOYMENT V2.2` - - 校内就业事实契约,包含租户隔离和学生令牌化要求 + - 校内就业数据契约,包含租户隔离和学生令牌化要求 - `schemas/school-internship.schema.json` - `SCHOOL-INTERNSHIP V2.1` - - 校内实习事实契约,包含租户隔离、学生令牌化、岗位任务和评价证据 + - 校内实习数据契约,包含租户隔离、学生令牌化、岗位任务和评价记录 - `schemas/package-manifest.schema.json` - `PACKAGE-MANIFEST V1.2` - 版本化导入、导出和学校交付包清单 @@ -124,11 +124,11 @@ python3 -m http.server 8080 - 移动:`390 × 844` - 可见业务文字不小于 13px - 页面级无横向溢出,宽表仅在自身容器内横向滚动 -- 所有深层按钮必须打开业务内容或形成列表状态变化 +- 所有深层按钮必须打开业务内容或改变列表状态 - JavaScript 语法检查:`node --check app.js` - JSON 文件检查:`python3 -m json.tool ` -新增闭环预览: +运营流程预览: - `preview-admin-operations.png` - `preview-admin-operations-mobile.png` diff --git a/admin-tools/demo/app.js b/admin-tools/demo/app.js index 6c4d54c..ebf6938 100644 --- a/admin-tools/demo/app.js +++ b/admin-tools/demo/app.js @@ -738,7 +738,7 @@ const contracts = { key: "JOB-SIGNAL", title: "外部招聘岗位信号标准", version: "V3.0.0", - description: "统一商业招聘平台、公共就业平台和活动聚合平台的岗位、企业、薪资、技能与来源证据,用于产教供需分析。", + description: "规定商业招聘平台、公共就业平台和招聘活动数据中的岗位、企业、薪资、技能与来源字段,供产教分析使用。", schemaPath: "./schemas/external-job-source.schema.json", fields: 39, required: 19, @@ -748,7 +748,7 @@ const contracts = { compatibility: "向后兼容 V2.6", fieldsPreview: [ ["record_id", "string/uuid", "是", "平台记录唯一标识", "UUID v4"], - ["source_platform", "string", "是", "来源平台代码", "受控代码表"], + ["source_platform", "string", "是", "来源平台代码", "固定代码表"], ["source_record_id", "string", "是", "来源记录标识", "同平台唯一"], ["source_url", "string/uri", "是", "来源页面或接口定位", "http/https"], ["collected_at", "datetime", "是", "实际采集时间", "ISO-8601 +08:00"], @@ -767,14 +767,14 @@ const contracts = { ["来源证据", "必须保留 source_url、collected_at、content_hash 和采集任务编号。"], ["薪资口径", "统一折算为税前月薪;面议、日薪、时薪保留原文并标注换算状态。"], ["时效与失效", "岗位状态和最后发现时间分开记录;失效采用版本化软删除。"], - ["文本治理", "岗位职责原文进入原始层,分析层只保留去标记、去联系方式后的业务文本。"], + ["文本处理", "岗位职责原文保存在原始层,分析层只保留去标记、去联系方式后的业务文本。"], ], }, "school-employment": { key: "SCHOOL-EMPLOYMENT", - title: "校内就业事实数据标准", + title: "校内就业数据标准", version: "V2.2.0", - description: "统一学校毕业生就业状态、岗位、企业、薪资、专业相关度和去向确认事实,支持租户隔离和敏感字段最小化。", + description: "规定学校毕业生就业状态、岗位、企业、薪资、专业相关度和去向确认字段,并要求租户隔离,只保留业务必需的敏感字段。", schemaPath: "./schemas/school-employment.schema.json", fields: 32, required: 16, @@ -787,7 +787,7 @@ const contracts = { ["student_token", "string", "是", "学生不可逆令牌", "禁止明文学号"], ["cohort", "integer", "是", "毕业届次", "YYYY"], ["program_code", "string", "是", "专业代码", "教育部专业目录"], - ["employment_status", "string", "是", "就业状态", "受控枚举"], + ["employment_status", "string", "是", "就业状态", "固定选项"], ["job_title", "string", "否", "就业岗位", "业务原文"], ["enterprise_token", "string", "否", "企业统一标识", "信用代码令牌化"], ["salary_monthly", "number", "否", "税前月薪", "元/月"], @@ -806,9 +806,9 @@ const contracts = { }, "school-internship": { key: "SCHOOL-INTERNSHIP", - title: "校内实习事实数据标准", + title: "校内实习数据标准", version: "V2.1.0", - description: "统一学生实习岗位、企业、起止日期、状态、工资、岗位任务和评价事实,支持租户隔离和敏感身份最小化。", + description: "规定学生实习岗位、企业、起止日期、状态、工资、岗位任务和评价字段,并要求租户隔离,只保留业务必需的身份字段。", schemaPath: "./schemas/school-internship.schema.json", fields: 30, required: 14, @@ -826,7 +826,7 @@ const contracts = { ["job_tasks", "array", "否", "实习岗位任务", "学校确认"], ["start_date", "date", "是", "开始日期", "YYYY-MM-DD"], ["end_date", "date", "否", "结束日期", "YYYY-MM-DD"], - ["status", "string", "是", "实习状态", "受控枚举"], + ["status", "string", "是", "实习状态", "固定选项"], ["salary_monthly", "number", "否", "税前月实习工资", "元/月"], ["evidence_reference", "string", "否", "校内证据引用", "不传附件"], ["source_updated_at", "datetime", "否", "业务更新时间", "增量水位"], @@ -837,7 +837,7 @@ const contracts = { ["身份最小化", "平台只接收 student_token,拒绝姓名、身份证、手机号、邮箱和明文学号。"], ["企业要求", "进行中或已完成实习必须提供企业令牌或企业名称。"], ["证据引用", "敏感附件保留在学校系统,平台只保存 evidence_reference。"], - ["增量幂等", "tenant_id + source_record_id + source_updated_at 形成增量与幂等边界。"], + ["增量重复处理", "使用 tenant_id + source_record_id + source_updated_at 判断增量更新,并确保重复提交不会重复写入。"], ], }, "package-manifest": { @@ -1381,7 +1381,7 @@ const operationsStatusLabels = { INVESTIGATING: "排障中", QUALITY_REVIEW_PENDING: "待质量复核", VERIFIED: "复核通过", - REVIEWED_BLOCKED: "复核后仍阻断", + REVIEWED_BLOCKED: "复核后仍不能发布", RESOLVED: "已解决", CLOSED: "已关闭", OPEN: "已建单", @@ -1401,7 +1401,7 @@ const operationsStatusLabels = { PENDING_REVIEW: "待复核", RECORDED: "已记录", PASS: "通过", - BLOCKED: "阻断", + BLOCKED: "不能继续", ROLLBACK_PENDING_APPROVAL: "回滚待审批", ROLLBACK_APPROVED: "回滚已批准", ROLLBACK_REJECTED: "回滚已驳回", @@ -1537,7 +1537,7 @@ function renderOperationsMetrics() { const deliveryAttention = operationsStore.deliveries.filter((delivery) => ["PENDING", "SENDING", "FAILED", "RETRYING"].includes(delivery.status)).length; const acknowledged = operationsStore.deliveries.filter((delivery) => delivery.status === "ACKNOWLEDGED").length; document.getElementById("operationsMetrics").innerHTML = ` -
未闭环问题${openIssues}确认、指派、排障与质量处置
+
未处理完问题${openIssues}确认、指派、排障与质量处置
审批待办${pendingApprovals}申请人与审批人强制分离
交付待办 / 异常${deliveryAttention}按租户隔离,不重复发送成功学校
已核验回执${acknowledged}记录数与 SHA-256 均一致
@@ -1552,8 +1552,8 @@ function renderOperationsMetrics() { const qualityDetail = document.getElementById("qualityReleaseDetail"); if (overviewState) overviewState.textContent = release?.status === "PUBLISHED" ? "稳定版本已发布" : releaseReady ? "候选可提交审批" : "候选发布受阻"; if (overviewDetail) overviewDetail.textContent = release?.qualityGate === "PASS" ? (release?.manifestGeneratedAt ? "质量与候选 Manifest 已就绪" : "质量通过,待生成候选 Manifest") : "杭州人才网修复重放尚未验证"; - if (qualityState) qualityState.textContent = release?.qualityGate === "PASS" ? "当前批次质量门禁已通过" : "当前批次仍需修复重放复核"; - if (qualityDetail) qualityDetail.textContent = release?.qualityGate === "PASS" ? "质量证据已通过独立复核,可继续生成候选包" : "质量分达标不等于门禁通过,稳定版本继续保持不变"; + if (qualityState) qualityState.textContent = release?.qualityGate === "PASS" ? "当前批次已满足发布质量要求" : "当前批次仍需修复重放复核"; + if (qualityDetail) qualityDetail.textContent = release?.qualityGate === "PASS" ? "质量记录已经另一名复核人确认,可继续生成候选包" : "仅质量分达标还不能发布,当前稳定版本保持不变"; } function renderOverviewIssues() { @@ -1571,7 +1571,7 @@ function renderOverviewIssues() { `, ) .join("") - : `
当前没有待处理问题,所有事项均已闭环。
`; + : `
当前没有待处理问题。
`; const countBadge = list.closest(".alert-panel").querySelector(".panel-head > em"); countBadge.textContent = `${issues.length} 项`; } @@ -1595,7 +1595,7 @@ function renderOperationsIssues() { .join(""); document.getElementById("operationsIssueTable").innerHTML = rows; const openCount = operationsStore.issues.filter((issue) => !["RESOLVED", "CLOSED"].includes(issue.status)).length; - document.getElementById("issueQueueSummary").textContent = `${openCount} 项未闭环 · 状态刷新后保留`; + document.getElementById("issueQueueSummary").textContent = `${openCount} 项未处理完 · 状态刷新后保留`; } function releaseNextAction(release, approval) { @@ -1606,7 +1606,7 @@ function releaseNextAction(release, approval) { if (release.status === "PENDING_APPROVAL") { return ` - + `; @@ -1654,7 +1654,7 @@ function renderReleaseWorkspace() { 上一稳定版本${h(release.previousStableVersion)}
- 质量门禁${h(operationStatusLabel(release.qualityGate))} · ${release.qualityScore} + 发布质量检查${h(operationStatusLabel(release.qualityGate))} · ${release.qualityScore} 影响租户${release.impactTenants.length} 所学校 申请人${h(release.applicant)} Manifest${release.publishedManifestGeneratedAt ? `发布版已生成 · ${h(operationTime(release.publishedManifestGeneratedAt))}` : release.manifestGeneratedAt ? `候选已生成 · ${h(operationTime(release.manifestGeneratedAt))}` : "尚未生成"} @@ -1662,11 +1662,11 @@ function renderReleaseWorkspace() {
${ release.status === "PUBLISHED" - ? "质量证据、候选 Manifest 与独立审批已冻结,正式发布 Manifest 已生成;当前尚未代表学校接收。" + ? "发布使用的质量记录、候选 Manifest 和审批结果均不可修改,正式发布 Manifest 已生成;这不表示学校已经接收。" : release.status === "ROLLED_BACK" ? `稳定别名已回滚到 ${h(release.previousStableVersion)},原发布、审批和租户交付记录继续保留审计。` : release.status === "PENDING_APPROVAL" - ? "候选 Manifest 已冻结,正在等待不同于申请人的独立审批人处理。" + ? "候选 Manifest 已提交,审批完成前不能修改,正在等待另一名审批人处理。" : release.status === "APPROVED" ? "独立审批已通过,可以执行稳定别名切换并生成正式发布 Manifest。" : release.status === "REJECTED" @@ -1675,7 +1675,7 @@ function renderReleaseWorkspace() { ? release.manifestGeneratedAt ? "修复重放证据与候选 Manifest 已就绪,可以提交独立发布审批。" : "修复重放已由独立复核人验证;还必须生成候选 Manifest 后才能提交审批。" - : "质量门禁阻断:只有 FIX_REPLAY 的记录数、规则结果与复核签名全部验证通过才能解锁;豁免或丢弃均保持阻断。" + : "当前不能发布:只有 FIX_REPLAY 的记录数、规则结果和复核签名全部通过检查才可继续;豁免或丢弃仍不能发布。" }
@@ -1684,9 +1684,9 @@ function renderReleaseWorkspace() { ? `` : release.status === "DRAFT" ? `` - : `候选 Manifest 已冻结,审批中不可重建。` + : `候选 Manifest 已提交,审批中不能重建。` } - +
@@ -1771,7 +1771,7 @@ function issueActionFooter(issue) { const qualityReviewAction = disposition?.action === "FIX_REPLAY" ? `` - : ``; + : ``; const actions = { ALERTED: ``, ACKNOWLEDGED: ``, @@ -1782,7 +1782,7 @@ function issueActionFooter(issue) { QUALITY_REVIEW_PENDING: qualityReviewAction, VERIFIED: ``, RESOLVED: ``, - CLOSED: `问题已闭环,所有动作与证据已保留。`, + CLOSED: `问题已完成处理,操作记录和附件已保留。`, }; return `${actions[issue.status] || ""}`; } @@ -2063,7 +2063,7 @@ function renderSourceMapping(source) {

样本回归

-

最近回归样本 1,000 条,结构通过率 100%,必填完整率 98.8%,岗位归一覆盖率 96.4%。未匹配岗位进入人工复核队列,不以模型推断覆盖原始事实。

+

最近回归样本 1,000 条,结构通过率 100%,必填完整率 98.8%,岗位归一覆盖率 96.4%。未匹配岗位进入人工复核队列,不用模型推断替换原始记录。

`; } @@ -2103,7 +2103,7 @@ function renderSourceAudit(source) {

数据使用边界

-

平台只向产教分析产品交付经契约治理的岗位信号、企业画像和统计结果。原始层与交付层分区存储,租户交付范围由 Manifest 和平台数据范围策略共同控制。

+

平台只向产教分析产品交付符合数据契约的岗位信息、企业信息和统计结果。原始数据与交付数据分开存储,Manifest 和租户授权共同决定每所学校可收到的数据。

`; } @@ -2461,7 +2461,7 @@ function openStandardRecord(recordId) {
-

全链路证据

+

来源与处理记录

01采集任务${h(record.taskId)} · ${h(record.collectorVersion)} 02原始快照${h(record.snapshotId)} · payload SHA-256 ${h(record.payloadHash)} @@ -2843,8 +2843,8 @@ function buildPackageManifest(options = {}) { generated_by: "陈致远", approval_reference: approval ? `${approval.id}:${approvalStatus}` : null, notes: published - ? "该文件是独立审批通过后生成的发布 Manifest;静态原型只记录本地稳定版本状态,不会向学校真实发送。" - : "该文件仅为候选包 Manifest;只有独立审批通过并执行发布后才成为稳定版本,静态原型不会向学校真实发送。", + ? "该文件是独立审批通过后生成的发布 Manifest;静态原型只记录本地稳定版本状态,不会向学校发送。" + : "该文件仅为候选包 Manifest;只有独立审批通过并执行发布后才成为稳定版本,静态原型不会向学校发送。", }; } @@ -2852,11 +2852,11 @@ function generateCandidateManifest() { const release = currentRelease(); updateReleaseQualityGate(); if (!release || release.status !== "DRAFT") { - showToast("候选已进入审批或发布流程,Manifest 已冻结;驳回后需返回草稿重建", "无法重建候选 Manifest"); + showToast("候选已提交审批或发布,当前 Manifest 不能修改;驳回后可返回草稿重建", "无法重建候选 Manifest"); return; } if (release.qualityGate !== "PASS") { - showToast("只有 FIX_REPLAY 的完整验证证据通过后才能生成候选 Manifest", "质量门禁阻断"); + showToast("只有 FIX_REPLAY 的记录数、规则结果和复核签名全部通过检查后,才能生成候选 Manifest", "当前不能生成候选"); return; } const inputFingerprint = candidateManifestInputFingerprint(); @@ -3428,7 +3428,7 @@ function setupAudit() { openInfoModal( "AUDIT POLICY", "生产审计与留存策略", - `
关键事件留存36个月审计存储WORM每日完整性校验SHA-256追踪覆盖率100%
采集请求、连接器版本、原始快照、映射规则、质量结果、审批和租户交付都写入统一 trace_id。敏感配置只记录密钥引用和变更摘要,不在日志中保存明文凭据。
`, + `
关键事件留存36个月审计存储WORM每日完整性校验SHA-256追踪覆盖率100%
采集请求、连接器版本、原始快照、映射规则、质量结果、审批和租户交付都使用同一个 trace_id。敏感配置只记录密钥引用和变更摘要,不在日志中保存明文凭据。
`, ); }); } @@ -3482,7 +3482,7 @@ function setupOperations() { return; } if (action === "investigate" && issue.status === "ASSIGNED") { - transitionIssue(issue, "INVESTIGATING", "已锁定源端时延与解析隔离记录,开始执行排障。", ["排障工作区快照", issue.relatedTask]); + transitionIssue(issue, "INVESTIGATING", "已确认问题来自源端延迟,并找到对应的解析隔离记录,开始排障。", ["排障工作区快照", issue.relatedTask]); return; } if (action === "submit-quality" && issue.status === "INVESTIGATING") { @@ -3548,7 +3548,7 @@ function setupOperations() { renderOperations(); renderAudit(); openIssueDrawer(issue.id); - showToast("处置动作已固化并写入审计,等待独立质量复核", "质量处置已提交"); + showToast("处置动作已保存且不能修改,等待另一名质量复核人处理", "质量处置已提交"); return; } if (action === "verify-blocked" && issue.status === "QUALITY_REVIEW_PENDING") { @@ -3574,8 +3574,8 @@ function setupOperations() { evidence: [...metadata.evidence], note: disposition.action === "WAIVE" - ? "风险豁免不等同于质量验证通过;候选门禁保持阻断,必须另行提交风险审批。" - : "丢弃可能改变数据完整性;候选门禁保持阻断,必须重建候选并重新执行质量验证。", + ? "风险豁免不等同于质量验证通过;候选版本仍不能发布,必须另行提交风险审批。" + : "丢弃可能改变数据完整性;候选版本仍不能发布,必须重建候选并重新执行质量检查。", }); const workOrder = operationsStore.workOrders.find((item) => item.issueId === issue.id); if (workOrder) migrateOperationsEntity(workOrder, "INVESTIGATING", metadata); @@ -3584,13 +3584,13 @@ function setupOperations() { renderOperations(); renderAudit(); openIssueDrawer(issue.id); - showToast(`${actionLabel}已复核,但不能解除发布门禁`, "质量门禁仍阻断"); + showToast(`${actionLabel}已复核,但当前候选版本仍不能发布`, "仍不满足发布条件"); return; } if (action === "verify" && issue.status === "QUALITY_REVIEW_PENDING") { const disposition = latestQualityDisposition(issue.id); if (!disposition || disposition.action !== "FIX_REPLAY") { - showToast("只有修复并重放可以进入质量验证通过状态", "质量门禁仍阻断"); + showToast("只有修复并重放可以进入质量检查通过状态", "仍不满足发布条件"); return; } const metadata = addOperationsAudit({ @@ -3616,7 +3616,7 @@ function setupOperations() { time: metadata.time, trace: metadata.trace, evidence: [...metadata.evidence], - note: "记录数、质量规则与重放证据已复核,候选版本质量门禁解除。", + note: "记录数、质量规则和重放记录已复核,候选版本可以继续提交审批。", }); const workOrder = operationsStore.workOrders.find((item) => item.issueId === issue.id); if (workOrder) migrateOperationsEntity(workOrder, "VERIFIED", metadata); @@ -3625,7 +3625,7 @@ function setupOperations() { renderOperations(); renderAudit(); openIssueDrawer(issue.id); - showToast("质量处置已 VERIFIED,候选版本现在可提交审批", "质量门禁已通过"); + showToast("质量处置已 VERIFIED,候选版本现在可提交审批", "已满足发布质量要求"); return; } if (action === "resolve" && (issue.status === "VERIFIED" || (issue.status === "INVESTIGATING" && !issue.qualityRequired))) { @@ -3645,7 +3645,7 @@ function setupOperations() { } if (event.target.closest("[data-release-official-manifest]")) { if (!release.publishedManifest) { - showToast("尚未形成发布 Manifest", "下载不可用"); + showToast("尚未生成发布 Manifest", "下载不可用"); return; } downloadJson(`${release.packageId}-published-manifest.json`, release.publishedManifest); @@ -3656,7 +3656,7 @@ function setupOperations() { updateReleaseQualityGate(); if (!releaseReadyForApproval(release)) { showToast( - release.qualityGate === "PASS" ? "质量门禁已通过,但必须先生成并冻结候选 Manifest" : "只有验证通过的 FIX_REPLAY 才能解除候选版本门禁", + release.qualityGate === "PASS" ? "质量检查已通过,但必须先生成候选 Manifest 并提交审批" : "只有通过检查的 FIX_REPLAY 才能让候选版本继续提交", "候选尚不可提交", ); return; @@ -3666,7 +3666,7 @@ function setupOperations() { event: "候选版本提交独立审批", object: release.id, result: "待审批", - evidence: ["候选 Manifest", "质量门禁 PASS", "影响租户清单"], + evidence: ["候选 Manifest", "发布质量检查 PASS", "影响租户清单"], }); migrateOperationsEntity(release, "PENDING_APPROVAL", metadata); migrateOperationsEntity(approval, "PENDING_APPROVAL", metadata); @@ -3794,7 +3794,7 @@ function setupOperations() { rejectEvent: "全局版本回滚独立审批驳回", object: `${release.id} → ${release.previousStableVersion}`, evidence: ["回滚审批意见", "审批人身份", "四眼规则校验", "影响租户清单"], - defaultApproveComment: "同意在受控窗口执行回滚", + defaultApproveComment: "同意在已安排的时间窗口执行回滚", defaultRejectComment: "回滚依据不足", successMessage: (actor, passed) => `${actor} 已${passed ? "批准" : "驳回"}全局回滚`, successTitle: (passed) => (passed ? "回滚审批通过" : "回滚审批驳回"), @@ -3807,7 +3807,7 @@ function setupOperations() { rollbackApproval?.status !== "ROLLBACK_APPROVED" || !isIndependentApproval(rollbackApproval) ) { - showToast("全局版本回滚必须先完成职责分离的独立审批", "回滚执行被阻断"); + showToast("全局版本回滚必须先由另一名审批人批准", "当前不能执行回滚"); return; } const metadata = addOperationsAudit({ @@ -3846,7 +3846,7 @@ function setupOperations() { saveOperationsStore(); renderOperations(); renderAudit(); - showToast(`${pending.length} 所待发送学校已进入原型队列,未发生真实网络发送`, "交付队列已启动"); + showToast(`${pending.length} 所待发送学校已进入原型队列,没有发出网络请求`, "交付队列已启动"); }); document.getElementById("deliveryTable").addEventListener("click", (event) => { const button = @@ -3949,7 +3949,7 @@ function setupGlobalActions() { const deliveryTodos = operationsStore.deliveries.filter((delivery) => ["PENDING", "SENDING", "FAILED", "RETRYING"].includes(delivery.status)); openInfoModal( "OPERATIONS NOTIFICATIONS", - "真实运营待办", + "运营待办", `
${openIssues .map( @@ -3963,7 +3963,7 @@ function setupGlobalActions() { : "" } ${deliveryTodos.length ? `` : ""} - ${!openIssues.length && !pendingApproval && !deliveryTodos.length ? `当前没有运营待办问题、审批和交付均已闭环` : ""} + ${!openIssues.length && !pendingApproval && !deliveryTodos.length ? `当前没有运营待办问题、审批和交付均已处理完成` : ""}
`, ); }); diff --git a/admin-tools/demo/index.html b/admin-tools/demo/index.html index f817f2b..844b72d 100644 --- a/admin-tools/demo/index.html +++ b/admin-tools/demo/index.html @@ -5,7 +5,7 @@ 产教数据中台 · 厂商运营中心 @@ -104,9 +104,9 @@
-
DATA OPERATIONS CONTROL PLANE
+
DATA OPERATIONS

招聘数据生产运行总览

-

统一管理商业招聘平台、公共就业平台和校内业务系统,从采集到交付全链路可追溯。

+

集中查看商业招聘平台、公共就业平台和校内业务系统的数据,每批数据都保留采集、处理和交付记录。

-
静态原型只模拟并持久化交付状态,不会向学校网络、接口或业务系统真实发送数据。
+
静态原型只记录交付状态,不会向学校网络、接口或业务系统发送数据。
@@ -252,8 +252,8 @@
SOURCE REGISTRY
-

统一数据源注册中心

-

商业招聘平台、公共就业平台、活动聚合平台和校内系统使用同一套资产、版本和运行模型。

+

数据源管理

+

商业招聘平台、公共就业平台、招聘活动和校内系统都按数据源、版本和运行记录管理。

@@ -291,7 +291,7 @@
COLLECTION ORCHESTRATION

采集任务编排中心

-

按来源、地域、行业和岗位族编排任务,支持分片、限速、失败隔离、断点续采和版本化原始留存。

+

按来源、地域、行业和岗位族创建采集任务,支持分片、限速、失败隔离、断点续采,并保存每次原始数据版本。

@@ -329,8 +329,8 @@
DATA RECORD EXPLORER
-

采集数据浏览与追溯

-

按数据层、来源、地区和关键词检索岗位明细,向下追溯源端记录、原始快照、采集任务与内容哈希。

+

采集数据与来源记录

+

按数据层、来源、地区和关键词检索岗位明细,并查看对应的源端记录、原始快照、采集任务与内容哈希。

@@ -394,8 +394,8 @@
- - + +
@@ -406,7 +406,7 @@
DATA EXCHANGE

数据导入与交付中心

-

支持标准文件导入、Schema 预检、字段映射、质量干跑和带清单、校验和、质量报告的版本化导出。

+

支持标准文件导入、Schema 预检、字段对应、发布前质量检查,以及带清单、校验和与质量报告的数据导出。

下载导入样例 @@ -436,7 +436,7 @@
-
版本交付

构建数据交付包

可复核、可回滚
+
版本交付

生成数据交付包

可查看检查记录,可回滚
@@ -467,7 +467,7 @@
QUALITY & NORMALIZATION

数据质量与岗位归一

-

执行结构、完整性、唯一性、时效性和业务规则校验,将多来源岗位映射到统一岗位与技能体系。

+

检查结构、完整性、唯一性、时效性和业务规则,并把不同来源的岗位名称和技能名称对齐。

@@ -478,7 +478,7 @@
94.7综合质量 -
生产发布阈值 ≥ 90当前批次仍需修复重放复核质量分达标不等于门禁通过,稳定版本继续保持不变
+
生产发布阈值 ≥ 90当前批次仍需修复重放复核仅质量分达标还不能发布,当前稳定版本保持不变
完整性97.8% @@ -504,8 +504,8 @@
AUDIT & DELIVERY
-

全链路审计与生产交付

-

记录来源、采集任务、代码版本、原始快照、处理规则、发布审批和租户交付,实现问题可定位、版本可回滚。

+

审计记录与生产交付

+

记录来源、采集任务、代码版本、原始快照、处理规则、发布审批和租户交付。出现问题时可查到相关记录,也可回滚版本。

@@ -516,7 +516,7 @@
今日审计事件2,846全部已签名
数据版本128保留 36 个月
-
可追踪任务100%原始快照已绑定
+
带追踪编号的任务100%已关联原始快照
交付租户36范围策略有效
@@ -577,7 +577,7 @@
DATA RECORD

采集记录详情

-

查看业务字段和全链路来源证据。

+

查看业务字段、来源和处理记录。

` : `
- 当前角色只读该节点由${safeText(node.owner)}负责,切换对应角色后可办理已解锁动作。 + 当前角色只读该节点由${safeText(node.owner)}负责;切换到对应角色后,可办理满足前置条件的动作。
`; document.getElementById("loopNodeDetail").innerHTML = `
@@ -1691,7 +1691,7 @@ function renderClosedLoopAction(action, nodes) { `; } @@ -2164,9 +2164,9 @@ const reports = [ { label: "现代服务类", value: 69 }, ], actions: [ - { priority: "P0", title: "推动11个专业完成高优技能缺口响应", detail: "由教务处牵头,4月底前形成课程调整或实训项目方案。" }, + { priority: "P0", title: "推动11个专业处理高优技能缺口", detail: "由教务处牵头,4月底前提交课程调整或实训项目方案。" }, { priority: "P1", title: "建设工业视觉与云原生两类校企共享实训", detail: "优先对接大华、数梦工场等已表达合作意向的企业。" }, - { priority: "P1", title: "建立企业需求季度确认机制", detail: "区分互联网招聘信号与合作企业正式确认需求,提升决策可信度。" }, + { priority: "P1", title: "每季度请企业确认一次需求", detail: "把互联网招聘信息与合作企业确认的需求分开,避免混用。" }, ], }, { @@ -2195,7 +2195,7 @@ const reports = [ ], findings: [ { title: "Java/Spring能力供需匹配良好", detail: "市场需求强度92%,课程覆盖86%,可继续保持项目化教学。", value: "差值6" }, - { title: "Docker/K8s形成明显技能缺口", detail: "市场需求81%,课程覆盖仅32%,缺口达到49个百分点。", value: "-49" }, + { title: "Docker/K8s技能缺口明显", detail: "市场需求81%,课程覆盖仅32%,相差49个百分点。", value: "-49" }, { title: "AI辅助开发进入企业基础要求", detail: "69%的重点岗位提出相关要求,当前课程覆盖仅28%。", value: "-41" }, ], bars: [ @@ -2208,7 +2208,7 @@ const reports = [ actions: [ { priority: "P0", title: "强化云原生与容器化实训模块", detail: "在综合实训中覆盖Docker、Kubernetes、CI/CD和可观测性。" }, { priority: "P1", title: "将AI辅助开发纳入软件工程实践", detail: "增加代码生成、测试辅助、安全审查和人工复核规范。" }, - { priority: "P1", title: "联合企业建设真实交付项目", detail: "引入数梦工场、海康威视的工程任务和企业导师评价。" }, + { priority: "P1", title: "联合企业建设交付项目", detail: "引入数梦工场、海康威视的工程任务和企业导师评价。" }, ], }, { @@ -2227,7 +2227,7 @@ const reports = [ author: "信息工程学院", roles: ["校级管理者", "学院负责人"], summary: - "学院6个专业平均匹配度80.4分,软件技术、物联网应用技术表现较好。当前需要跨专业统筹云平台、数据工程和AI应用三类共享能力建设。", + "学院6个专业平均匹配度80.4分,软件技术、物联网应用技术表现较好。云平台、数据工程和 AI 应用课程可由多个专业共用。", metrics: [ { label: "学院匹配度", value: "80.4", note: "较上期 +5.1" }, { label: "覆盖专业", value: "6", note: "2个高匹配专业" }, @@ -2235,8 +2235,8 @@ const reports = [ { label: "合作企业", value: "38", note: "本学期新增6家" }, ], findings: [ - { title: "共享技术底座课程重复建设", detail: "数据库、Linux和软件工程内容在多个专业重复,可建设学院共享模块。", value: "6专业" }, - { title: "云平台能力成为共同短板", detail: "云部署、容器和运维能力在5个专业中均出现覆盖不足。", value: "5专业" }, + { title: "基础技术课程重复开设", detail: "数据库、Linux 和软件工程内容在多个专业重复,可由学院统一开设共用模块。", value: "6专业" }, + { title: "5个专业都缺云平台课程内容", detail: "云部署、容器和运维内容在5个专业中均覆盖不足。", value: "5专业" }, { title: "企业项目集中度偏高", detail: "前5家企业承担了61%的项目,需要扩展中型技术企业伙伴。", value: "61%" }, ], bars: [ @@ -2247,8 +2247,8 @@ const reports = [ { label: "计算机网络", value: 75 }, ], actions: [ - { priority: "P0", title: "建立学院共享工程实践课程群", detail: "统一云平台、数据库、DevOps基础能力,按专业配置差异化项目。" }, - { priority: "P1", title: "扩展8家中型技术企业合作", detail: "降低项目来源集中度,为不同专业提供多样化真实任务。" }, + { priority: "P0", title: "开设学院共用工程实践课程", detail: "云平台、数据库和 DevOps 基础内容由学院共用,各专业再安排不同项目。" }, + { priority: "P1", title: "扩展8家中型技术企业合作", detail: "减少项目对少数企业的依赖,为不同专业提供更多企业任务。" }, { priority: "P1", title: "建立跨专业学生项目团队", detail: "围绕智能物联场景组织软件、数据和网络方向联合实训。" }, ], }, @@ -2268,7 +2268,7 @@ const reports = [ author: "产教融合中心", roles: ["校级管理者"], summary: - "杭州区域人才需求持续向智能制造、云计算、跨境电商和数字内容方向集中。全校识别23项重点技能缺口,其中8项需要在本学期形成明确响应。", + "杭州区域人才需求持续向智能制造、云计算、跨境电商和数字内容方向集中。全校有23项重点技能缺口,其中8项需要在本学期安排课程或项目调整。", metrics: [ { label: "重点缺口", value: "23", note: "8项高优" }, { label: "关联专业", value: "11", note: "覆盖5个学院" }, @@ -2330,7 +2330,7 @@ const reports = [ { label: "现代服务类", value: 88 }, ], actions: [ - { priority: "P1", title: "将真实项目成果纳入就业推荐材料", detail: "强化学生技能证据,提升企业对岗位胜任力的判断效率。" }, + { priority: "P1", title: "将企业项目成果纳入就业推荐材料", detail: "用学生作品和企业评价说明其岗位能力。" }, { priority: "P1", title: "建立分专业薪资预期指导", detail: "使用分位数而非平均数,为学生提供地域和岗位差异说明。" }, { priority: "P2", title: "持续核验企业薪资数据完整性", detail: "对缺失和区间过宽的薪资记录降低统计权重。" }, ], @@ -2372,7 +2372,7 @@ const reports = [ ], actions: [ { priority: "P0", title: "补齐就业薪资缺失记录", detail: "由就业处在本期正式材料发布前完成字段确认。" }, - { priority: "P1", title: "审核218个新增岗位名称", detail: "优先处理需求量前50的岗位,并沉淀别名规则。" }, + { priority: "P1", title: "审核218个新增岗位名称", detail: "先处理需求量前50的岗位,并把确认后的别名加入规则表。" }, { priority: "P2", title: "增加数据包服务期自动提醒", detail: "基础数据包到期前30天通知厂商和学校管理员。" }, ], }, @@ -2450,7 +2450,7 @@ const reports = [ { label: "AI内容生产", value: 75 }, ], actions: [ - { priority: "P0", title: "重构跨境电商平台运营课程", detail: "增加真实店铺、海外投放和合规履约任务。" }, + { priority: "P0", title: "重构跨境电商平台运营课程", detail: "增加企业店铺运营、海外投放和合规履约任务。" }, { priority: "P1", title: "增加AI营销内容生产工作流", detail: "纳入AI文案、图片、视频辅助生产与人工审核。" }, ], }, @@ -2487,7 +2487,7 @@ const reports = [ { label: "文化创意类", value: 68 }, ], actions: [ - { priority: "P0", title: "建立周期性分析机制", detail: "从年度人工报告转向季度数据快照和任务跟踪。" }, + { priority: "P0", title: "每季度更新一次分析", detail: "用季度数据快照和任务进展替代一年一次的人工报告。" }, { priority: "P1", title: "完善岗位分类与技能词典", detail: "提高跨数据源岗位匹配和趋势比较的稳定性。" }, ], }, @@ -2505,7 +2505,7 @@ const professionReportCatalog = [ ["新能源汽车技术", "智能制造学院", 83.1, "三电检测与智能诊断"], ["汽车检测与维修技术", "智能制造学院", 74.9, "新能源汽车售后与诊断"], ["跨境电子商务", "商贸旅游学院", 81.2, "海外投放与合规履约"], - ["国际商务", "商贸旅游学院", 73.6, "数字贸易与供应链协同"], + ["国际商务", "商贸旅游学院", 73.6, "数字贸易与供应链协作"], ["市场营销", "商贸旅游学院", 72.8, "数据营销与用户增长"], ["现代物流管理", "商贸旅游学院", 78.1, "智慧物流与仓配优化"], ["酒店管理与数字化运营", "商贸旅游学院", 71.5, "收益管理与数字化服务"], @@ -2545,7 +2545,7 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { updated: `2026-03-${String(18 - (index % 8)).padStart(2, "0")}`, author: college, roles: ["校级管理者"], - summary: `${name}专业供需匹配度${score}分。当前培养基础总体稳定,${focus}是下一阶段专业建设和校企协同的重点方向。`, + summary: `${name}专业供需匹配度${score}分。当前课程基础总体稳定,下一阶段应优先补充${focus}相关课程和企业项目。`, metrics: [ { label: "专业匹配度", value: String(score), note: score >= 80 ? "高匹配" : score >= 74 ? "保持关注" : "需要改进" }, { label: "对口岗位", value: demand.toLocaleString("zh-CN"), note: "近90天有效样本" }, @@ -2554,8 +2554,8 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { ], findings: [ { title: `${focus}需求持续增长`, detail: `重点企业正在将相关能力纳入岗位要求,近90天需求信号保持上升。`, value: `+${16 + (index % 23)}%` }, - { title: "课程实践与企业任务仍有差距", detail: "现有课程具备基础知识覆盖,但真实场景、工具链和交付评价需要加强。", value: `-${gap}` }, - { title: "校企合作具备扩展条件", detail: `已识别${companyCount}家高匹配企业,可围绕项目实训和企业导师形成合作。`, value: `${companyCount}家` }, + { title: "课程实践与企业任务仍有差距", detail: "现有课程已覆盖基础知识,但企业场景、工具链和交付评价练习仍然不足。", value: `-${gap}` }, + { title: "可以联系更多合作企业", detail: `已有${companyCount}家企业与该专业较匹配,可讨论项目实训和企业导师安排。`, value: `${companyCount}家` }, ], bars: [ { label: "专业基础能力", value: Math.min(95, coverage + 8) }, @@ -2565,9 +2565,9 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { { label: "企业项目交付", value: Math.max(50, coverage - 12) }, ], actions: [ - { priority: "P0", title: `强化${focus}教学模块`, detail: "引入企业真实任务,明确工具链、过程产物和验收标准。" }, + { priority: "P0", title: `强化${focus}教学模块`, detail: "引入企业任务,明确使用的工具、过程产物和验收标准。" }, { priority: "P1", title: "邀请企业导师参与课程评审", detail: `优先对接已识别的${companyCount}家潜力企业,核验岗位技能与课程映射。` }, - { priority: "P1", title: "建立学生能力证据档案", detail: "将项目作品、企业评价和技能达成情况纳入就业推荐材料。" }, + { priority: "P1", title: "整理学生项目材料", detail: "把项目作品、企业评价和技能考核结果放入就业推荐材料。" }, ], }); }); @@ -2593,7 +2593,7 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { updated: `2026-03-${18 - index}`, author: name, roles: ["校级管理者"], - summary: `${name}整体供需表现保持稳定,${focus}是跨专业共享能力建设的主要方向。`, + summary: `${name}整体供需表现稳定。多个专业都需要${focus}相关课程,可由学院统一开设部分内容。`, metrics: [ { label: "学院匹配度", value: String(76.8 + index * 1.3), note: "较上期持续提升" }, { label: "覆盖专业", value: scope.replace("个专业", ""), note: "全部纳入分析" }, @@ -2601,9 +2601,9 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { { label: "合作企业", value: String(26 + index * 7), note: "持续扩展" }, ], findings: [ - { title: `${focus}形成共同需求`, detail: "多个专业出现相近技能缺口,适合建设学院共享课程或实训平台。", value: "高关联" }, + { title: `多个专业都需要${focus}`, detail: "多个专业的技能缺口相近,适合共用学院课程或实训环境。", value: "高关联" }, { title: "企业项目分布仍需优化", detail: "建议降低头部企业集中度,引入更多中型和专精特新企业。", value: "待改善" }, - { title: "建议执行进入跟踪阶段", detail: "重点事项已明确负责人和周期,可纳入学院改进任务闭环。", value: "可执行" }, + { title: "建议可以开始执行", detail: "重点事项已有负责人和期限,可加入学院任务清单继续跟进。", value: "可执行" }, ], bars: [ { label: "专业匹配", value: 80 + index }, @@ -2612,9 +2612,9 @@ professionReportCatalog.forEach(([name, college, score, focus], index) => { { label: "项目实践", value: 70 + index * 2 }, ], actions: [ - { priority: "P0", title: `建设${focus}共享模块`, detail: "明确学院统一底座和各专业差异化应用场景。" }, - { priority: "P1", title: "形成企业合作伙伴分层清单", detail: "区分课程共建、项目实训、实习就业和企业导师资源。" }, - { priority: "P1", title: "按月跟踪专业改进任务", detail: "对逾期、未响应和缺少证据的任务进行校院协同督办。" }, + { priority: "P0", title: `建设${focus}共享模块`, detail: "列出学院共用内容,以及各专业需要单独设置的练习。" }, + { priority: "P1", title: "按合作类型整理企业名单", detail: "分别列出可参与课程共建、项目实训、实习就业和企业导师工作的企业。" }, + { priority: "P1", title: "按月检查专业改进任务", detail: "校级和学院共同跟进逾期、未响应或缺少材料的任务。" }, ], }); }); @@ -2634,7 +2634,7 @@ const reportDataProfiles = { }, college: { label: "学院专业建设分析", - topics: ["专业结构对比", "共享能力分析", "培养成效验证", "企业协同机会"], + topics: ["专业结构对比", "共用课程分析", "培养结果检查", "企业合作机会"], dependencies: [ { sourceId: "regional-jobs", requirement: "required", purpose: "学院相关岗位与技能趋势" }, { sourceId: "salary-company", requirement: "optional", purpose: "专业群薪资和企业结构参考" }, @@ -2646,14 +2646,14 @@ const reportDataProfiles = { }, profession: { label: "专业人才需求分析", - topics: ["岗位技能需求", "课程能力映射", "学生达成验证", "企业需求复核"], + topics: ["岗位技能需求", "课程技能对应", "学生学习结果", "企业需求复核"], dependencies: [ { sourceId: "regional-jobs", requirement: "required", purpose: "对口岗位、技能频次与需求变化" }, { sourceId: "salary-company", requirement: "optional", purpose: "区域同岗位薪资竞争力" }, { sourceId: "internship", requirement: "optional", purpose: "学生实践岗位与企业评价" }, { sourceId: "employment", requirement: "optional", purpose: "毕业去向和岗位匹配验证" }, { sourceId: "curriculum", requirement: "required", purpose: "课程标准、学时与技能覆盖" }, - { sourceId: "enterprise-demand", requirement: "required", purpose: "真实企业需求与合作意向确认" }, + { sourceId: "enterprise-demand", requirement: "required", purpose: "企业确认的人才需求与合作意向" }, ], }, industry: { @@ -2716,7 +2716,7 @@ const dataGapCatalog = [ levelLabel: "需补数", title: "就业薪资与缺失原因未完整提供", drawerTitle: "就业系统薪资字段缺失", - drawerLevel: "阻断发布", + drawerLevel: "当前不能发布", amount: "86 条记录 · 当前字段完整率 91.2%", affected: "86 条记录 · 电子商务专业 41 条、现代服务类专业 45 条", fields: ["employment_salary", "salary_period", "missing_reason"], @@ -2856,7 +2856,7 @@ function applyRole(role, options = {}) { document.getElementById("dataPageTitle").textContent = isDataAdministrator ? "学校数据运维中心" : "数据资产与质量"; document.getElementById("dataPageDescription").textContent = isDataAdministrator ? "管理学校数据源、初次导入、增量更新、字段契约、质量问题、版本与审计。" - : "区分厂商基础数据包、学校自有数据与企业授权数据,所有分析结论均可追溯。"; + : "区分厂商基础数据包、学校自有数据与企业授权数据,每项分析结论都注明数据来源。"; document.getElementById("syncAllButtonText").textContent = isDataAdministrator ? "新建更新任务" : "同步全部数据"; document.getElementById("schoolNav").hidden = isPlatformRole; @@ -2888,8 +2888,8 @@ function applyRole(role, options = {}) { }; if (role === "企业导师") { - collaborationHeading.textContent = "企业协同工作台"; - collaborationDescription.textContent = "提交真实岗位与技能需求,参与课程共建并评价学生项目成果。"; + collaborationHeading.textContent = "企业合作工作台"; + collaborationDescription.textContent = "提交岗位与技能需求,参与课程共建并评价学生项目成果。"; demandButton.innerHTML = `${svgIcon("file")}提交企业需求`; projectButton.innerHTML = `${svgIcon("course")}发起共建项目`; renderCollaborationStats([ @@ -2899,24 +2899,24 @@ function applyRole(role, options = {}) { { label: "参与学生", value: "86", unit: "人", note: "企业评价 4.7 / 5" }, ]); } else if (role === "学院负责人" || role === "专业负责人") { - collaborationHeading.textContent = "学院校企协同"; + collaborationHeading.textContent = "学院校企合作"; collaborationDescription.textContent = "围绕本院专业对接企业需求,推进课程共建、实训与企业导师协作。"; demandButton.innerHTML = `${svgIcon("file")}邀请企业调研`; - projectButton.innerHTML = `${svgIcon("course")}新建协同项目`; + projectButton.innerHTML = `${svgIcon("course")}新建合作项目`; renderCollaborationStats([ { label: "本院合作企业", value: "38", unit: "家", note: "本学期新增 6 家" }, - { label: "本院协同项目", value: "8", unit: "个", note: "3 个进行中" }, + { label: "本院合作项目", value: "8", unit: "个", note: "3 个进行中" }, { label: "企业导师", value: "21", unit: "人", note: "覆盖 6 个专业" }, { label: "学生参与", value: "386", unit: "人次", note: "满意度 94%" }, ]); } else { - collaborationHeading.textContent = "校企协同中心"; - collaborationDescription.textContent = "把产业需求转化为可执行的课程、项目与人才共育计划。"; + collaborationHeading.textContent = "校企合作"; + collaborationDescription.textContent = "根据企业需求安排课程共建、合作项目和人才培养计划。"; demandButton.innerHTML = `${svgIcon("file")}发起需求调研`; - projectButton.innerHTML = `${svgIcon("course")}新建协同项目`; + projectButton.innerHTML = `${svgIcon("course")}新建合作项目`; renderCollaborationStats([ { label: "在库合作企业", value: "126", unit: "家", note: "本学期新增 18 家" }, - { label: "本学期协同项目", value: "24", unit: "个", note: "8 个进行中" }, + { label: "本学期合作项目", value: "24", unit: "个", note: "8 个进行中" }, { label: "企业导师", value: "68", unit: "人", note: "覆盖 17 个专业" }, { label: "学生参与", value: "1,284", unit: "人次", note: "满意度 92%" }, ]); @@ -3238,7 +3238,7 @@ function renderProfessionJobsView(data) {
- ${professionEvidenceNote("证据 PRO-JOB-301", `岗位流向基于区域招聘基础包去重岗位、学校近三届就业去向及合作企业确认记录。互联网岗位反映需求信号,不等于实际录用人数。`)} + ${professionEvidenceNote("证据 PRO-JOB-301", `岗位流向使用区域招聘基础包中的去重岗位、学校近三届就业去向及合作企业确认记录计算。互联网岗位反映需求信号,不等于实际录用人数。`)} `; } @@ -3280,7 +3280,7 @@ function renderProfessionSalaryView(data) {
影响因素

技能证据与起薪

- +14%企业真实项目经历 + +14%企业项目经历 +9%高质量作品集 +7%企业导师评价
@@ -3567,7 +3567,7 @@ function renderLineageTopicNode(topic, index) {
${String(index + 1).padStart(2, "0")} ${topic} - 统一口径计算 · 保留证据定位 + 按同一统计口径计算 · 可查看数据来源
`; } @@ -3641,7 +3641,7 @@ function renderReportLineageCanvas(report) { return `
${renderLineageStage("数据资产", `${visibleDependencies.length} / ${profile.dependencies.length} 项`, "sources", sourceNodes)} - ${lineageConnector("形成指标")} + ${lineageConnector("计算指标")} ${renderLineageStage("指标 / 分析主题", `${profile.topics.length} 类`, "topics", topicNodes)} ${lineageConnector("生成报告")} ${renderLineageStage("目标报告", "1 份", "reports", renderLineageReportNode(report, readableIds))} @@ -3667,10 +3667,10 @@ function renderSourceLineageCanvas(source) { return `
${renderLineageStage("选中数据", "1 项", "sources", renderLineageSourceNode(source, null, true))} - ${lineageConnector("支撑分析")} - ${renderLineageStage("可形成的分析", `${topics.length} 类`, "topics", topics.map(renderLineageTopicNode).join(""))} - ${lineageConnector("支撑报告")} - ${renderLineageStage("可形成的报告", `${visibleReports.length} 份`, "reports", reportNodes)} + ${lineageConnector("用于分析")} + ${renderLineageStage("可做的分析", `${topics.length} 类`, "topics", topics.map(renderLineageTopicNode).join(""))} + ${lineageConnector("用于报告")} + ${renderLineageStage("使用该数据的报告", `${visibleReports.length} 份`, "reports", reportNodes)}
`; } @@ -3698,7 +3698,7 @@ function renderLineageSummary(report, source) { const gaps = gapsForSource(source.id); summary.innerHTML = [ lineageSummaryCard("当前数据", source.categoryLabel, source.version), - lineageSummaryCard("支撑报告", `${sourceReports.length} 份`, `${reportsGroupedByType(sourceReports).size} 类报告`), + lineageSummaryCard("使用该数据的报告", `${sourceReports.length} 份`, `${reportsGroupedByType(sourceReports).size} 类报告`), lineageSummaryCard("当前质量", source.quality, `${source.records} 条有效记录`), lineageSummaryCard("数据缺口", `${gaps.length} 项`, gaps.length ? "已定位责任人与时限" : "当前无数据缺口", gaps.length ? "warning" : "ready"), ].join(""); @@ -3761,7 +3761,7 @@ function renderDataReportLineage() { button.setAttribute("aria-pressed", String(selected)); }); document.getElementById("dataLineageSelectorLabel").textContent = mode === "report" ? "选择报告" : "选择数据"; - selector.setAttribute("aria-label", mode === "report" ? "选择要追溯的报告" : "选择要反查的数据"); + selector.setAttribute("aria-label", mode === "report" ? "选择报告查看所需数据" : "选择数据查看使用它的报告"); selector.innerHTML = mode === "report" ? reports @@ -3841,7 +3841,7 @@ function renderDataOpsOverview(source) {
本次更新内容 ${source.changeSummary} -

更新采用暂存校验机制,未通过质量门槛的数据进入隔离区,不会覆盖当前已发布版本。

+

更新数据先放入暂存区检查;不满足最低质量要求的数据进入隔离区,不会覆盖当前已发布版本。

@@ -3880,7 +3880,7 @@ function renderDataOpsRequirements(source) {
01准备文件或连接支持标准模板导入,也可按更新频率配置 API、数据库视图或 SFTP。 02字段映射与样本预检确认主键、必填字段、代码字典和敏感字段处理规则。 - 03暂存与质量校验先写入暂存区,阻断性错误不覆盖生产版本。 + 03暂存与质量校验先写入暂存区,发现严重错误时不更新生产版本。 04审批发布与留痕数据管理员确认质量和授权后,生成不可变版本并进入分析。
@@ -3893,7 +3893,7 @@ function renderDataOpsRequirements(source) {
学校 / 租户包与数据版本交付状态记录数回执SHA-256 回执最近动作操作
- + @@ -3925,7 +3925,7 @@ function renderDataOpsHistory(source) {

失败处理策略

-

网络失败从检查点自动重试 3 次;数据错误进入隔离区;主键冲突、授权缺失和 Schema 不兼容将整批阻断。历史已发布版本不原地覆盖。

+

网络失败从检查点自动重试 3 次;数据错误进入隔离区;出现主键冲突、授权缺失或 Schema 不兼容时,整批数据不发布。历史已发布版本不直接覆盖。

`; } @@ -3966,7 +3966,7 @@ function renderDataOpsUsage() {
SHA校验${safeText(e.receipt.receivedSha256 || e.receipt.expectedSha256)}交付包记录数${e.receipt.receivedRecords.toLocaleString("zh-CN")} / ${e.receipt.expectedRecords.toLocaleString("zh-CN")}分析快照${e.snapshot.id} · ${e.snapshot.checkedRecords.toLocaleString("zh-CN")}条
-

业务支撑关系

+

业务使用情况

报告${e.report?.id || "待生成"} 项目${e.project?.id || "待创建"} @@ -4069,7 +4069,7 @@ function updateDataOpsDrawer() { if (dataOpsState.context === "batch") { document.getElementById("dataOpsKicker").textContent = "DATA UPDATE CENTER"; document.getElementById("dataOpsTitle").textContent = "数据更新任务中心"; - document.getElementById("dataOpsDescription").textContent = "先确认业务截止日期、变更内容和质量门槛,再创建可追踪的更新任务。"; + document.getElementById("dataOpsDescription").textContent = "先确认业务截止日期、变更内容和最低质量要求,再创建带编号的更新任务。"; content.innerHTML = `
${dataOpsStat("待更新", "2 个来源", "1个自动调度 · 1个人工导入")}${dataOpsStat("运行正常", "4 个来源", "最近24小时无失败")}${dataOpsStat("隔离记录", "86 条", "未进入生产版本")}
@@ -4106,7 +4106,7 @@ function updateDataOpsDrawer() { if (dataOpsState.context === "authorization") { document.getElementById("dataOpsKicker").textContent = "DATA AUTHORIZATION"; document.getElementById("dataOpsTitle").textContent = "数据权属与授权中心"; - document.getElementById("dataOpsDescription").textContent = "统一管理用途、可见范围、服务期限、撤权和审计要求。"; + document.getElementById("dataOpsDescription").textContent = "设置数据用途、可见范围、服务期限、撤权方式和操作记录要求。"; content.innerHTML = renderAuthorizationOverview(); footer.innerHTML = ``; return; @@ -4195,7 +4195,7 @@ function openWorkspaceDetail(kind, value = "") { description: `${task.profession} · 来源:${task.source}`, content: `
${workspaceMetric("负责人", task.owner, "主责")}${workspaceMetric("截止日期", task.due, task.statusText)}${workspaceMetric("当前进度", `${task.progress}%`, "自动汇总")}
-

任务目标

将分析建议转化为课程、项目或校企协同调整,并以正式方案、企业确认和学生达成证据作为验收依据。

+

任务目标

根据分析建议调整课程、项目或企业合作安排,并用正式方案、企业确认和学生考核结果验收。

进展记录

${loopTask ? loopTask.progressLogs.map((item) => `${safeText(item.detail)}${safeText(item.operator)} · ${safeText(item.at)} · 进度 ${item.progress}%`).join("") : `完成现状与差距复核李雯 · 2026-03-18 16:20企业导师已确认技能清单陈凯 · 2026-03-20 10:42课程调整方案进入教研室评审系统 · 今天 08:30`}

验收要求

课程或项目方案${loopTask && closedLoopState.entities.evidences.length ? "已提交" : "必需"}企业确认回执${closedLoopState.entities.evaluation ? closedLoopState.entities.evaluation.result : "必需"}校级验收${loopTask?.status || "待执行"}
${loopTask ? `` : ""}
`, primary: loopTask ? "关闭详情" : "提交阶段进展", @@ -4223,7 +4223,7 @@ function openWorkspaceDetail(kind, value = "") { description: `${partner.industry} · 综合匹配度 ${partner.match}%`, content: `

推荐依据

${partner.reason}

${partner.tags.map((tag) => `${tag}`).join("")}
-

对接安排

`, +

对接安排

`, primary: "创建对接事项", }; }, @@ -4238,14 +4238,14 @@ function openWorkspaceDetail(kind, value = "") { kicker: "ORGANIZATION SCOPE", title: "组织与数据范围", description: "根据账号角色切换组织,数据权限同步变化。", - content: `

权限说明

组织切换只改变业务范围,不改变底层租户隔离。平台运营人员无法默认查看学校明文业务数据。

`, + content: `

权限说明

切换组织只改变可查看的业务范围,不改变租户隔离。平台运营人员默认不能查看学校明细数据。

`, primary: "确认当前范围", }), templates: () => ({ kicker: "REPORT TEMPLATE LIBRARY", title: "报告模板库", - description: "按不同决策场景统一报告结构、证据和审批流程。", - content: `
校级报告全校产教供需分析总报告学校事实、区域基准、专业结构、行动清单42页 · 已启用
学院报告学院专业建设分析报告专业对比、共享能力、企业合作与任务跟踪36页 · 已启用
专业报告专业人才需求分析报告岗位、技能、薪资、课程映射和企业推荐24—30页 · 已启用
数据质量数据资产质量与口径报告来源、权属、版本、质量规则、限制和审计19页 · 已启用
`, + description: "按报告用途设置章节、数据说明和审批步骤。", + content: `
校级报告全校产教供需分析总报告学校数据、区域基准、专业结构、任务清单42页 · 已启用
学院报告学院专业建设分析报告专业对比、共用课程、企业合作与任务跟踪36页 · 已启用
专业报告专业人才需求分析报告岗位、技能、薪资、课程对应和企业推荐24—30页 · 已启用
数据质量数据资产质量与口径报告来源、权属、版本、质量规则、限制和审计19页 · 已启用
`, primary: "新建模板版本", }), compare: () => ({ @@ -4323,7 +4323,7 @@ function renderSources(filter = "all") { 数据提供方${source.provider} 权属与授权${source.rights} 覆盖范围${source.coverage} - 更新机制${source.frequency} + 更新频率${source.frequency}
有效记录${source.records} @@ -4473,14 +4473,14 @@ function renderReportCenter() { const roleReports = reportsForCurrentRole(); const role = document.getElementById("roleSelect")?.value || "校级管理者"; const descriptions = { - 校级管理者: "统一管理校级、学院、专业、产业与数据质量报告,支持在线阅读和版本追溯。", - 学院负责人: "查看本院、所属专业及相关数据质量报告,将分析结论转化为专业建设行动。", + 校级管理者: "查看和管理校级、学院、专业、产业与数据质量报告,并保留各版本。", + 学院负责人: "查看本院、所属专业及相关数据质量报告,并根据分析结论安排专业建设任务。", 专业负责人: "查看本专业报告、提交业务流程报告审核并追踪审批历史;校级批准与发布由校级管理者执行。", 就业老师: "查看校级与数据质量报告,登记就业侧使用反馈;不能审批校级业务报告。", - 校级技术管理员: "查看数据质量、版本、口径和授权报告,确保进入分析的每个数据版本均可追溯。", + 校级技术管理员: "查看数据质量、版本、口径和授权报告,并检查每个分析版本的数据来源和处理记录。", }; document.getElementById("reportCenterDescription").textContent = - descriptions[role] || "统一管理分析报告,支持在线阅读和版本追溯。"; + descriptions[role] || "查看和管理分析报告,并保留各版本。"; document.getElementById("reportTotalCount").textContent = roleReports.length; document.getElementById("reportNewCount").textContent = roleReports.filter((item) => item.periodKey === "current").length; document.getElementById("reportReviewCount").textContent = roleReports.filter((item) => item.status === "待审核").length; @@ -4516,8 +4516,8 @@ function renderReportDocument(report, options = {}) {
${report.typeLabel} · ${report.period}

${report.title}

-

${report.scope}。报告基于统一数据快照生成,结论均保留来源、样本量与统计口径。

- STANDARD REPORT · 数据、口径与结论全链路可追溯 +

${report.scope}。报告使用同一数据快照生成,每项结论都注明来源、样本量和统计口径。

+ STANDARD REPORT · 可查看数据来源、统计口径和结论依据
编制单位${report.author} @@ -4546,16 +4546,16 @@ function renderReportDocument(report, options = {}) { ${window.ReportVisuals.renderExecutiveCharts(report, { interactive })}
综合解读 -

本期${evidence.scoreLabel}为${evidence.score.toFixed(1)}分,高于区域可比均值${(evidence.score - evidence.benchmark.regional).toFixed(1)}分,高于同类院校均值${(evidence.score - evidence.benchmark.peer).toFixed(1)}分。该判断建立在${evidence.benchmark.sampleText}及统一数据快照之上;所有低样本指标已降权,不将互联网招聘数量直接解释为人才缺口人数。

+

本期${evidence.scoreLabel}为${evidence.score.toFixed(1)}分,高于区域可比均值${(evidence.score - evidence.benchmark.regional).toFixed(1)}分,高于同类院校均值${(evidence.score - evidence.benchmark.peer).toFixed(1)}分。计算使用${evidence.benchmark.sampleText}和同一数据快照;低样本指标已降低权重,互联网招聘数量不直接当作人才缺口人数。

- ${reportSectionHeading(2, "INSTITUTION PROFILE", report.type === "profession" ? "专业与学校事实画像" : report.type === "college" ? "学院与学校事实画像" : "学校现状与事实画像")} + ${reportSectionHeading(2, "INSTITUTION PROFILE", report.type === "profession" ? "专业与学校现状" : report.type === "college" ? "学院与学校现状" : "学校现状")} ${window.ReportVisuals.renderProfileEvidence(report, { interactive })}
学校现状判断 -

学校现状以学籍、教务、人事、实习就业和校企合作台账为事实底座。当前全校专业、课程和企业合作规模能够支撑常规人才培养,但真实项目实训、企业导师评价与课程技能映射仍需进一步覆盖。每项现状指标均可展开查看来源系统、更新时间、责任部门和计算口径。

+

学校现状数据来自学籍、教务、人事、实习就业和校企合作台账。当前全校专业、课程和企业合作规模能够满足常规人才培养需要,但企业项目实训、企业导师评价和课程技能对应关系仍不完整。每项指标都可查看来源系统、更新时间、责任部门和计算口径。

@@ -4580,7 +4580,7 @@ function renderReportDocument(report, options = {}) {
结论交叉验证规则 - 外部需求趋势+校内培养事实+企业确认信号→业务负责人复核 + 外部岗位变化+校内培养数据+企业确认需求→业务负责人复核
@@ -4616,12 +4616,12 @@ function renderReportDocument(report, options = {}) {
结构性结论 -

高需求但课程覆盖不足的能力位于象限图左上区域,应优先进入专业建设清单;高需求且覆盖充分的能力应转向学生达成和企业评价验证。趋势图显示培养响应仍滞后于外部需求,建议以真实项目和企业验收缩短响应周期,而不是简单增加课程名称。

+

高需求但课程覆盖不足的能力位于象限图左上区域,应优先加入专业建设清单;高需求且覆盖充分的能力需要检查学生掌握情况和企业评价。趋势图显示课程调整仍慢于岗位需求变化,建议增加企业项目和企业验收,不要只增加课程名称。

- ${reportSectionHeading(5, "DATA EVIDENCE", "证据链、样本与数据来源")} + ${reportSectionHeading(5, "DATA EVIDENCE", "样本与数据来源")} ${window.ReportVisuals.renderEvidenceLedger(report)}
@@ -4630,8 +4630,8 @@ function renderReportDocument(report, options = {}) {
01数据采集

采集近90天岗位、校内主数据、课程标准、实习就业回执和合作企业确认记录,保留权属与授权标签。

02清洗归一

按岗位ID、企业、发布时间去重;专业依据教育部专业代码归一;技能使用版本化词典映射。

-
03基准构建

仅纳入同层次、同区域且有效样本达到100条的院校;同类院校按专业结构、规模和产业方向匹配。

-
04交叉验证

外部需求、校内事实与企业确认至少两类证据方向一致才形成中高置信结论,AI文本须人工审核。

+
03选择对比样本

只纳入同层次、同区域且有效样本达到100条的院校;同类院校按专业结构、规模和产业方向选择。

+
04相互核对

外部岗位、校内数据和企业确认中至少两类结果一致,才列为较可靠结论;AI草拟文字必须人工审核。

校验项门槛失败处理
主键唯一性100%整批阻断,下载冲突明细
主键唯一性100%整批不发布,可下载冲突明细
必填完整性≥ 95%进入隔离区,修复后重试
代码与日期合法性≥ 98%错误记录不进入分析
综合质量${source.threshold}低于阈值不得发布
@@ -4647,7 +4647,7 @@ function renderReportDocument(report, options = {}) {
- 本报告用于专业建设和校企协同决策参考。AI负责结构化归纳和文本草拟,不修改原始数据,不隐藏相反证据。业务负责人需结合政策、办学定位和资源约束审核,不直接替代招生、专业撤并或课程调整的正式决策程序。 + 本报告用于讨论专业建设和校企合作。AI只整理数据和草拟文字,不修改原始数据,也不删除相反结果。业务负责人仍需结合政策、办学定位和资源情况审核;报告不能替代招生、专业撤并或课程调整的正式决策程序。
@@ -4673,7 +4673,7 @@ function renderReportDocument(report, options = {}) {
责任确认5个工作日内 - 方案与资源形成可验收产物 + 方案与资源提交可按验收要求检查的成果 阶段复核按月更新证据 @@ -4720,7 +4720,7 @@ function openReportReader(reportId) { ["profile", "学校现状"], ["findings", "关键发现"], ["analysis", "供需结构"], - ["evidence", "证据链"], + ["evidence", "数据来源"], ["method", "指标口径"], ["actions", "行动建议"], ]; @@ -4975,10 +4975,10 @@ function setupWorkspaceDetails() { } const productTourSteps = [ - { view: "dashboard", selector: ".quality-strip", title: "可信数据底座", description: "先确认数据来源、更新状态和质量门槛,所有分析只引用已验收版本。" }, - { view: "dashboard", selector: ".ai-panel", title: "发现关键变化", description: "AI将岗位、技能和专业变化归纳为可解释的决策简报,并保留证据定位。" }, + { view: "dashboard", selector: ".quality-strip", title: "先核对数据", description: "先看数据来自哪里、何时更新、是否通过检查;分析只使用已验收版本。" }, + { view: "dashboard", selector: ".ai-panel", title: "查看关键变化", description: "系统整理岗位、技能和专业变化,每条结论都可打开查看数据来源。" }, { view: "profession", selector: ".profile-banner", title: "定位专业差距", description: "从岗位、技能、薪资和课程映射判断专业优势与结构性缺口。" }, - { view: "collaboration", selector: ".collab-stats", title: "连接企业协同", description: "把企业需求转化为课程共建、真实项目、企业导师和实习就业合作。" }, + { view: "collaboration", selector: ".collab-stats", title: "安排企业合作", description: "把企业需求写入课程共建、企业项目、企业导师和实习就业计划。" }, { view: "actions", selector: ".action-overview", title: "跟踪改进成效", description: "每项建议都有负责人、截止日期、进展证据和下一周期效果复核。" }, { view: "data", selector: ".source-summary-grid", title: "管理数据资产", description: "厂商、学校和企业三类数据分权维护,支持初次导入、增量更新、版本和审计。" }, { view: "reports", selector: ".featured-report-grid", title: "完成正式交付", description: "在线报告、材料包和展示大屏使用同一数据快照,适用于决策、汇报与报送。" }, @@ -5268,7 +5268,7 @@ function setupReportCenterInteractions() { const task = { id: `TSK-REPORT-${Date.now()}`, title, - source: `报告建议 · ${report?.version || "当前版本"} · 证据链已关联`, + source: `报告建议 · ${report?.version || "当前版本"} · 已关联数据来源`, profession: report?.type === "profession" ? report.scope.split("·").pop().trim() : "全校专业", owner: "待确认", due: "2026-04-30", @@ -5357,7 +5357,7 @@ const platformActionTemplates = { - +
导入要求与发布门槛
@@ -5458,7 +5458,7 @@ const platformActionTemplates = { permission: { kicker: "ROLE PERMISSION", title: "角色与权限模板", - description: "统一配置学校、学院、企业和平台运营角色权限。", + description: "分别设置学校、学院、企业和平台运营人员的权限。", confirm: "进入配置", content: `
7 套权限模板采用租户隔离、角色权限和数据范围三层控制,最近修改已通过审计复核。
`, }, @@ -5472,7 +5472,7 @@ const platformActionTemplates = { audit: { kicker: "AUDIT LOG", title: "平台审计日志", - description: "追溯数据导入、权限变更、租户操作和系统任务。", + description: "查看数据导入、权限变更、租户操作和系统任务记录。", confirm: "查看完整日志", content: `
今日记录 286 条关键操作数据操作68条,权限操作12条,系统任务201条,安全事件5条,全部保留操作者和时间戳。
`, }, @@ -5553,7 +5553,7 @@ function setupAnalysis() { "读取本期分析快照…", "归一并匹配产业岗位…", "计算专业技能覆盖差距…", - "生成可解释决策洞察…", + "整理分析结果和建议…", ]; openModal(modal); progress.style.width = "0"; @@ -5635,7 +5635,7 @@ function configureFormModal(type) { task: { kicker: "ACTION FORM", title: "创建改进任务", - description: "将分析洞察转化为可追踪、可验证的行动。", + description: "把分析结果写成有负责人、截止日期和验收要求的任务。", label: "任务名称", value: "强化云原生与容器化实训内容", scopeLabel: "关联专业", @@ -5651,16 +5651,16 @@ function configureFormModal(type) { }, project: { kicker: "COLLABORATION PROJECT", - title: "新建协同项目", + title: "新建合作项目", description: "连接专业团队与企业伙伴,共同推进人才培养项目。", label: "项目名称", - value: "企业真实项目进课堂", + value: "企业项目进课堂", scopeLabel: "牵头专业", scopeOptions: ["软件技术", "机电一体化技术", "电子商务"], priorityLabel: "项目类型", priorityOptions: ["企业项目进课堂", "课程共建", "实训基地", "企业导师"], goalLabel: "共建目标与验收方式", - goal: "围绕企业真实任务共同设计教学项目、过程评价和成果验收,保留企业任务书与导师评价证据。", + goal: "围绕企业任务共同设计教学项目、过程评价和成果验收,并保存企业任务书与导师评价。", ownerLabel: "校内负责人", owner: "王健 · 产教融合中心", dueLabel: "计划启动时间", @@ -5688,15 +5688,15 @@ function configureFormModal(type) { configs.demand = { kicker: "ENTERPRISE DEMAND", title: "提交企业人才需求", - description: "提交真实岗位、技能与共育需求,供学校专业团队确认响应。", + description: "提交岗位、技能与共育需求,供学校专业团队确认是否承接。", label: "需求名称", value: "边缘计算软件测试人才共育需求", scopeLabel: "关联专业", scopeOptions: ["软件技术", "物联网应用技术", "计算机网络技术"], priorityLabel: "合作方式", - priorityOptions: ["人才共育", "真实项目", "课程共建", "实习就业"], + priorityOptions: ["人才共育", "企业项目", "课程共建", "实习就业"], goalLabel: "企业需求说明", - goal: "提交真实岗位、技能、计划人数和合作方式,并由企业联系人确认数据授权用途与有效期。", + goal: "填写岗位、技能、计划人数和合作方式,并由企业联系人确认数据用途与有效期。", ownerLabel: "企业联系人", owner: "陈凯 · 企业人才发展部", dueLabel: "期望响应时间", @@ -5707,15 +5707,15 @@ function configureFormModal(type) { configs.project = { kicker: "CO-CREATION PROJECT", title: "发起校企共建项目", - description: "邀请学校共同设计企业真实项目、课程内容和评价标准。", + description: "邀请学校共同设计企业项目、课程内容和评价标准。", label: "项目名称", value: "智能物联边缘计算综合实训", scopeLabel: "面向专业", scopeOptions: ["物联网应用技术", "软件技术", "计算机网络技术"], priorityLabel: "项目类型", - priorityOptions: ["企业真实项目", "课程共建", "企业导师", "实训基地"], + priorityOptions: ["企业项目", "课程共建", "企业导师", "实训基地"], goalLabel: "企业任务与验收要求", - goal: "基于边缘计算测试场景设计实训任务,由企业导师参与中期评审,并依据测试报告、代码质量和协作过程验收。", + goal: "按边缘计算测试场景设计实训任务,由企业导师参加中期评审,并检查测试报告、代码质量和协作过程。", ownerLabel: "企业负责人", owner: "陈凯 · 企业人才发展部", dueLabel: "建议启动时间", @@ -5816,7 +5816,7 @@ function setupForms() { closeModal(document.getElementById("formModal")); const messages = { task: "改进任务已创建,并通知专业负责人", - project: "协同项目草案已创建,可继续邀请企业伙伴", + project: "合作项目草案已创建,可继续邀请企业伙伴", demand: "企业需求调研已创建,共有126家在库企业可发送", }; showToast(messages[type] || "内容已保存"); @@ -6007,7 +6007,7 @@ function init() { addClosedLoopAudit( "LEGACY_NEXT_CYCLE_MIGRATED", closedLoopState.entities.demand.id, - `旧版复核 ${legacyReview.id || "RVW-旧记录"} 已转换为真实的新周期实体。`, + `旧版复核 ${legacyReview.id || "RVW-旧记录"} 已转换为可继续办理的新周期记录。`, "流程状态迁移器", "系统", ); diff --git a/demo/index.html b/demo/index.html index 35e63cc..4cc6b03 100644 --- a/demo/index.html +++ b/demo/index.html @@ -5,9 +5,9 @@ - 产教融智 · 供需分析与协同平台 + 产教融智 · 供需分析与校企合作 @@ -58,14 +58,14 @@ - 专业洞察 + 专业分析 32
- 协同改进完成率 + 改进任务完成率 本学期
68%
@@ -455,7 +455,7 @@
- 结论综合基础数据包、校级数据与企业确认数据,所有引用均可追溯 + 结论使用基础数据包、校级数据与企业确认数据,每条引用都注明来源
@@ -517,11 +517,11 @@ - -
+ +
-
PROGRAM INSIGHT
+
PROGRAM ANALYSIS

软件技术

- -
+ +
COLLABORATION HUB
-

校企协同中心

-

把产业需求转化为可执行的课程、项目与人才共育计划。

+

校企合作

+

根据企业需求安排课程共建、合作项目和人才培养计划。

在库合作企业126家↑ 18
-
本学期协同项目24个8 个进行中
+
本学期合作项目24个8 个进行中
企业导师68人覆盖 17 个专业
学生参与1,284人次满意度 92%
@@ -672,7 +672,7 @@
- 协同进度 + 项目进度

本学期重点项目

@@ -713,8 +713,8 @@
ACTION TRACKER
-

改进任务闭环

-

从数据洞察到责任落实,持续追踪专业建设行动与实际成效。

+

改进任务进展

+

查看每项专业建设任务的负责人、进度和实际效果。

@@ -907,7 +907,7 @@
- 数据快照 SNP-2026-03-22-0830 · 质量评分 92.6 · 全链路可追溯 + 数据快照 SNP-2026-03-22-0830 · 质量评分 92.6 · 可查看来源与处理记录 从产业信号到专业改进,让每项决策都有证据
@@ -1413,7 +1413,7 @@

创建改进任务

-

将分析洞察转化为可追踪的行动。

+

把分析结果写成有负责人和截止日期的任务。