From c6e1d94510808df0586d5f5f7c3d90159a6b7cf8 Mon Sep 17 00:00:00 2001 From: wangziqi Date: Mon, 10 Aug 2026 10:05:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20CI=20=E6=97=B6?= =?UTF-8?q?=E5=8C=BA=E6=B5=8B=E8=AF=95=E5=A4=B1=E8=B4=A5=20+=20=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=AE=89=E5=85=A8=E5=8D=87=E7=BA=A7=20+=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BE=9D=E8=B5=96=E6=A3=80=E6=9F=A5=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix(server): getCourseClock 固定 UTC+8(Asia/Shanghai),与 attendance-settlement 保持一致, 修复 CI(UTC 容器)下 attendance.lesson-session.spec.ts 失败 - chore(deps): @ant-design/x 2.9.0 / @ant-design/x-markdown 2.9.0 / mermaid 11.16.1; 直接依赖 dompurify 3.4.13(修复生产依赖 audit 漏洞,mermaid/x-markdown 复用同一份) - ci: 新增 dependency-check workflow(生产依赖 moderate+ / 全局 critical 失败,outdated 报告) --- .gitea/workflows/dependency-check.yml | 44 ++++ apps/admin/package.json | 7 +- apps/server/src/attendance/attendance-time.ts | 4 +- package-lock.json | 214 +++++++++--------- package.json | 3 +- 5 files changed, 154 insertions(+), 118 deletions(-) create mode 100644 .gitea/workflows/dependency-check.yml diff --git a/.gitea/workflows/dependency-check.yml b/.gitea/workflows/dependency-check.yml new file mode 100644 index 0000000..a6b047b --- /dev/null +++ b/.gitea/workflows/dependency-check.yml @@ -0,0 +1,44 @@ +name: Dependency Check + +# 依赖安全检查:生产依赖 moderate+ 或全局 critical 漏洞即失败; +# npm outdated 作为信息输出,不阻断。 +# 注意:npmmirror 未实现 audit 接口,audit 必须显式指定官方 registry。 + +env: + NPM_CONFIG_REGISTRY: https://registry.npmmirror.com + NPM_CONFIG_AUDIT: "false" + NPM_CONFIG_FUND: "false" + NPM_CONFIG_REPLACE_REGISTRY_HOST: always + CI: "true" + +on: + pull_request: + branches: [main] + schedule: + - cron: '30 2 * * 1' # 每周一 02:30 复查已发布的新漏洞 + workflow_dispatch: + +jobs: + check: + runs-on: ubuntu-latest + container: node:22.22.0-bookworm + timeout-minutes: 20 + + steps: + - name: Checkout + uses: https://gitee.com/mirrors_actions/checkout@v4 + with: + github-server-url: https://git.gongxue100.com + fetch-depth: 1 + + - name: Install dependencies + run: npm ci + + - name: Audit production dependencies (moderate+) + run: npm audit --registry=https://registry.npmjs.org --omit=dev --audit-level=moderate + + - name: Audit all dependencies (critical only) + run: npm audit --registry=https://registry.npmjs.org --audit-level=critical + + - name: Outdated report (informational) + run: npm outdated --registry=https://registry.npmjs.org || true diff --git a/apps/admin/package.json b/apps/admin/package.json index 90b7684..f1ca3a4 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -14,9 +14,9 @@ }, "dependencies": { "@ant-design/icons": "^6.1.1", - "@ant-design/x": "^2.8.0", + "@ant-design/x": "^2.9.0", "@ant-design/x-card": "^2.9.0", - "@ant-design/x-markdown": "^2.8.0", + "@ant-design/x-markdown": "^2.9.0", "@ant-design/x-sdk": "^2.8.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -26,10 +26,11 @@ "antd": "^6.3.6", "axios": "^1.15.1", "dayjs": "^1.11.20", + "dompurify": "^3.4.13", "echarts": "^6.0.0", "fast-deep-equal": "^3.1.3", "file-saver": "^2.0.5", - "mermaid": "^11.16.0", + "mermaid": "^11.16.1", "react": "^19.2.5", "react-dom": "^19.2.5", "react-router": "^8.3.0", diff --git a/apps/server/src/attendance/attendance-time.ts b/apps/server/src/attendance/attendance-time.ts index ac5fa79..24e457c 100644 --- a/apps/server/src/attendance/attendance-time.ts +++ b/apps/server/src/attendance/attendance-time.ts @@ -6,7 +6,9 @@ export function toMinutes(time: string): number { } export function getCourseClock(date: Date): { date: string; minutes: number } { - const d = dayjs(date); + // Asia/Shanghai 无夏令时,固定 UTC+8(与 attendance-settlement 保持一致), + // 避免依赖服务器进程时区导致「课程是否已开始」判断漂移。 + const d = dayjs(date).utcOffset(8); return { date: d.format('YYYY-MM-DD'), minutes: d.hour() * 60 + d.minute(), diff --git a/package-lock.json b/package-lock.json index 4316f36..77e8baa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ "version": "0.0.0", "dependencies": { "@ant-design/icons": "^6.1.1", - "@ant-design/x": "^2.8.0", + "@ant-design/x": "^2.9.0", "@ant-design/x-card": "^2.9.0", - "@ant-design/x-markdown": "^2.8.0", + "@ant-design/x-markdown": "^2.9.0", "@ant-design/x-sdk": "^2.8.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -33,10 +33,11 @@ "antd": "^6.3.6", "axios": "^1.15.1", "dayjs": "^1.11.20", + "dompurify": "^3.4.13", "echarts": "^6.0.0", "fast-deep-equal": "^3.1.3", "file-saver": "^2.0.5", - "mermaid": "^11.16.0", + "mermaid": "^11.16.1", "react": "^19.2.5", "react-dom": "^19.2.5", "react-router": "^8.3.0", @@ -65,6 +66,103 @@ "vitest": "^4.1.10" } }, + "apps/admin/node_modules/@ant-design/x": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/@ant-design/x/-/x-2.9.0.tgz", + "integrity": "sha512-m3N2nprrPG/D0n93B/fBFhjpvSaJAb2IDF6w0rX0ycYXSGxtgrJQvqSI33Jhx6gxUHj495zdIzqA1NMFld9iQA==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^8.0.0", + "@ant-design/cssinjs": "^2.0.1", + "@ant-design/cssinjs-utils": "^2.0.2", + "@ant-design/fast-color": "^3.0.0", + "@ant-design/icons": "^6.0.0", + "@babel/runtime": "^7.25.6", + "@rc-component/motion": "^1.1.6", + "@rc-component/resize-observer": "^1.0.1", + "@rc-component/util": "^1.4.0", + "clsx": "^2.1.1", + "lodash.throttle": "^4.1.1", + "mermaid": "^11.12.1", + "react-syntax-highlighter": "^16.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "antd": "^6.1.1", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "apps/admin/node_modules/@ant-design/x-markdown": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/@ant-design/x-markdown/-/x-markdown-2.9.0.tgz", + "integrity": "sha512-IwYUky9Fi3y86wouFQ3rjx/DyKFUm/eAidiU/leVD0u6hAfN4INDWltWuZqe1FRRwOE7DJdSxweDyD6+/B6oQg==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1", + "dompurify": "^3.2.6", + "html-react-parser": "^5.2.13", + "katex": "^0.16.22", + "marked": "^15.0.12" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "apps/admin/node_modules/dompurify": { + "version": "3.4.13", + "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.13.tgz", + "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "apps/admin/node_modules/mermaid": { + "version": "11.16.1", + "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.16.1.tgz", + "integrity": "sha512-TQsq6u22fAn3rek5VOubrhKPo1g5hwC3FXUN9hiyupTckcYiGuuKGkNQrKYwGJkXUxZdojwRG46gsSCFZMDp4g==", + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.2", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.2.0", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.33.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.20", + "dompurify": "^3.3.3", + "es-toolkit": "^1.45.1", + "katex": "^0.16.45", + "khroma": "^2.1.0", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" + } + }, + "apps/admin/node_modules/mermaid/node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmmirror.com/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "apps/admin/node_modules/react-router": { "version": "8.3.0", "resolved": "https://registry.npmmirror.com/react-router/-/react-router-8.3.0.tgz", @@ -553,36 +651,6 @@ "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@ant-design/x": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@ant-design/x/-/x-2.8.0.tgz", - "integrity": "sha512-z0ncy8i3sy8fnFS1iETTQfP2Os1kzOl5OPdljT5ZFSCDsZp+VYFt9jHHMacBnkEftKNzkmG1BLSwvBTS1aWxiw==", - "license": "MIT", - "dependencies": { - "@ant-design/colors": "^8.0.0", - "@ant-design/cssinjs": "^2.0.1", - "@ant-design/cssinjs-utils": "^2.0.2", - "@ant-design/fast-color": "^3.0.0", - "@ant-design/icons": "^6.0.0", - "@babel/runtime": "^7.25.6", - "@rc-component/motion": "^1.1.6", - "@rc-component/resize-observer": "^1.0.1", - "@rc-component/util": "^1.4.0", - "clsx": "^2.1.1", - "lodash.throttle": "^4.1.1", - "mermaid": "^11.12.1", - "react-syntax-highlighter": "^16.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ant-design" - }, - "peerDependencies": { - "antd": "^6.1.1", - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, "node_modules/@ant-design/x-card": { "version": "2.9.0", "resolved": "https://registry.npmmirror.com/@ant-design/x-card/-/x-card-2.9.0.tgz", @@ -599,23 +667,6 @@ "react-dom": ">=18.0.0" } }, - "node_modules/@ant-design/x-markdown": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@ant-design/x-markdown/-/x-markdown-2.8.0.tgz", - "integrity": "sha512-QRS0s81ykVt8RLqf9nGHJmP/y8hNQgQZdu7+7x+EMS5VuPBeQw74IpIUNchVLQy/P60VoNpkw+YTalyJtyLPPw==", - "license": "MIT", - "dependencies": { - "clsx": "^2.1.1", - "dompurify": "^3.2.6", - "html-react-parser": "^5.2.13", - "katex": "^0.16.22", - "marked": "^15.0.12" - }, - "peerDependencies": { - "react": ">=18.0.0", - "react-dom": ">=18.0.0" - } - }, "node_modules/@ant-design/x-sdk": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@ant-design/x-sdk/-/x-sdk-2.8.0.tgz", @@ -10085,15 +10136,6 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/dompurify": { - "version": "3.4.12", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz", - "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/domutils": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", @@ -14394,60 +14436,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mermaid": { - "version": "11.16.0", - "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.16.0.tgz", - "integrity": "sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==", - "license": "MIT", - "dependencies": { - "@braintree/sanitize-url": "^7.1.2", - "@iconify/utils": "^3.0.2", - "@mermaid-js/parser": "^1.2.0", - "@types/d3": "^7.4.3", - "@upsetjs/venn.js": "^2.0.0", - "cytoscape": "^3.33.3", - "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.2.0", - "d3": "^7.9.0", - "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.14", - "dayjs": "^1.11.20", - "dompurify": "^3.3.3", - "es-toolkit": "^1.45.1", - "katex": "^0.16.45", - "khroma": "^2.1.0", - "marked": "^16.3.0", - "roughjs": "^4.6.6", - "stylis": "^4.3.6", - "ts-dedent": "^2.2.0", - "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" - } - }, - "node_modules/mermaid/node_modules/marked": { - "version": "16.4.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", - "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/mermaid/node_modules/uuid": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", - "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", diff --git a/package.json b/package.json index be80561..0730eac 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ }, "minimatch@10.2.5": { "brace-expansion": "^5.0.9" - } + }, + "dompurify": "^3.4.13" } }