From a6b18b78e645b29c46cd4a4556a762944616a5fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Sat, 5 Sep 2026 21:58:55 +0800 Subject: [PATCH] =?UTF-8?q?task-261(admin.html=E8=A7=82=E6=84=9F=E5=AF=B9?= =?UTF-8?q?=E9=BD=90):=20=E6=95=B0=E5=AD=97=E4=BA=BA=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E9=A1=B5=E5=AF=B9=E9=BD=90=EF=BC=88=E7=8A=B6=E6=80=81/?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E2=98=85/=E6=96=87=E4=BB=B6=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F/MD5=E6=88=AA=E6=96=AD/=E6=93=8D=E4=BD=9C=E7=9F=A9?= =?UTF-8?q?=E9=98=B5/=E4=B8=8A=E4=BC=A0=E6=96=87=E6=A1=88/=E5=88=A0?= =?UTF-8?q?=E9=99=A4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecordsDigitalHumanVersionPage.vue | 96 +++++++++++++------ .../src/pages/records/digitalhuman-api.ts | 5 + .../src/pages/records/digitalhuman-format.ts | 9 ++ admin-frontend-vue/tests/task-261.test.ts | 65 +++++++++++++ 4 files changed, 146 insertions(+), 29 deletions(-) create mode 100644 admin-frontend-vue/src/pages/records/digitalhuman-format.ts create mode 100644 admin-frontend-vue/tests/task-261.test.ts diff --git a/admin-frontend-vue/src/pages/records/RecordsDigitalHumanVersionPage.vue b/admin-frontend-vue/src/pages/records/RecordsDigitalHumanVersionPage.vue index fd8989f1..a6a8f7c0 100644 --- a/admin-frontend-vue/src/pages/records/RecordsDigitalHumanVersionPage.vue +++ b/admin-frontend-vue/src/pages/records/RecordsDigitalHumanVersionPage.vue @@ -1,11 +1,22 @@ @@ -107,36 +139,41 @@ onMounted(load) - + - + - - + + - - + + + + + - - - - + - + @@ -172,4 +209,5 @@ onMounted(load) .page-heading { display: flex; justify-content: space-between; align-items: flex-start; } .actions { display: flex; align-items: center; gap: 10px; } .dim { color: var(--el-text-color-secondary); font-size: 12px; } +.star { color: #e6a23c; font-weight: 700; } diff --git a/admin-frontend-vue/src/pages/records/digitalhuman-api.ts b/admin-frontend-vue/src/pages/records/digitalhuman-api.ts index 32e9405f..0570d273 100644 --- a/admin-frontend-vue/src/pages/records/digitalhuman-api.ts +++ b/admin-frontend-vue/src/pages/records/digitalhuman-api.ts @@ -29,3 +29,8 @@ export async function releaseDigitalHumanVersion(version: string): Promise export async function setLatestDigitalHumanVersion(version: string): Promise { await http.post(`${DIGITAL_HUMAN_VERSIONS_ENDPOINT}/${encodeURIComponent(version)}/set-latest`) } + +/** 删除数字人版本:DELETE /{version}。 */ +export async function deleteDigitalHumanVersion(version: string): Promise { + await http.delete(`${DIGITAL_HUMAN_VERSIONS_ENDPOINT}/${encodeURIComponent(version)}`) +} diff --git a/admin-frontend-vue/src/pages/records/digitalhuman-format.ts b/admin-frontend-vue/src/pages/records/digitalhuman-format.ts new file mode 100644 index 00000000..461cafe7 --- /dev/null +++ b/admin-frontend-vue/src/pages/records/digitalhuman-format.ts @@ -0,0 +1,9 @@ +/** 数字人版本展示格式化(module 13 task 261):MD5 截断展示;纯逻辑。 */ + +/** MD5 前 len 位(默认 12,对齐 admin)展示;空值回空串。 */ +export function md5Short(md5: string | null | undefined, len = 12): string { + const text = typeof md5 === 'string' ? md5.trim() : '' + if (!text) return '' + const max = typeof len === 'number' && Number.isFinite(len) && len >= 1 ? Math.floor(len) : 12 + return text.length <= max ? text : `${text.slice(0, max)}…` +} diff --git a/admin-frontend-vue/tests/task-261.test.ts b/admin-frontend-vue/tests/task-261.test.ts new file mode 100644 index 00000000..b6dbc58d --- /dev/null +++ b/admin-frontend-vue/tests/task-261.test.ts @@ -0,0 +1,65 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { readSource } from './helpers.ts' +import { digitalHumanStatusDisplay, latestBadgeText } from '../src/pages/records/digitalhuman-status-display.ts' +import { canReleaseDigitalHumanVersion } from '../src/pages/records/digitalhuman-release.ts' +import { canSetLatestDigitalHumanVersion } from '../src/pages/records/digitalhuman-latest.ts' +import { md5Short } from '../src/pages/records/digitalhuman-format.ts' + +// module 13 task 261:数字人版本页对齐 admin panel-digital-human-version(状态/最新★/大小/MD5截断/操作矩阵/上传文案)。 + +test('test_task_261_dh_normal_primary_path', () => { + // 正常主路径:状态映射与发布/设最新判定。 + assert.deepEqual(digitalHumanStatusDisplay('DRAFT'), { text: '草稿', tag: 'info' }) + assert.deepEqual(digitalHumanStatusDisplay('RELEASED'), { text: '已发布', tag: 'success' }) + assert.equal(canReleaseDigitalHumanVersion('DRAFT'), true) + assert.equal(canSetLatestDigitalHumanVersion('RELEASED'), true) + assert.equal(canSetLatestDigitalHumanVersion('DRAFT'), false) +}) + +test('test_task_261_dh_normal_variant_input', () => { + assert.equal(md5Short('a'.repeat(12)), 'a'.repeat(12), '恰好 12 位原样') + assert.equal(md5Short('a'.repeat(20)), `${'a'.repeat(12)}…`, '超长截 12 位并省略') + assert.equal(md5Short(''), '') + assert.equal(md5Short(null), '') +}) + +test('test_task_261_dh_normal_repeated_operation_is_idempotent', () => { + assert.equal(digitalHumanStatusDisplay('draft').text, '草稿') + assert.equal(digitalHumanStatusDisplay('draft').text, '草稿') +}) + +test('test_task_261_dh_boundary_empty_input', () => { + assert.equal(latestBadgeText(true), '最新') + assert.equal(latestBadgeText(false), '') + assert.equal(digitalHumanStatusDisplay('').text, '草稿', '未知状态归一草稿') +}) + +test('test_task_261_dh_boundary_single_item', () => { + const page = readSource('src/pages/records/RecordsDigitalHumanVersionPage.vue') + assert.match(page, /formatFileSize/, '文件大小走共享格式化') + assert.match(page, /md5Short/, 'MD5 截断展示') + assert.match(page, /canReleaseDigitalHumanVersion/, '发布按钮按状态显隐') +}) + +test('test_task_261_dh_boundary_limit_or_missing_field', () => { + // 边界上限:文件大小格式化(复用了版本页 formatFileSize)。 + const fmt = readSource('src/pages/records/version-format.ts') + assert.match(fmt, /formatFileSize/) +}) + +test('test_task_261_dh_invalid_input_rejected', () => { + // 异常:删除需二次确认;删除走后端 DELETE;删除失败有兜底。 + const page = readSource('src/pages/records/RecordsDigitalHumanVersionPage.vue') + assert.match(page, /此操作不可恢复/, '删除需危险二次确认') + assert.match(page, /删除失败/, '删除失败有兜底文案') + const api = readSource('src/pages/records/digitalhuman-api.ts') + assert.match(api, /http\.delete/, '删除调用 DELETE 适配') +}) + +test('test_task_261_dh_dependency_failure_returns_actionable_message', () => { + // 依赖失败:上传成功文案含“请在列表中点击发布”。 + const page = readSource('src/pages/records/RecordsDigitalHumanVersionPage.vue') + assert.match(page, /上传成功!版本:/, '上传成功文案需含版本') + assert.match(page, /请在列表中点击“发布”按钮/, '上传成功引导发布') +})