dev #3
@@ -48,8 +48,8 @@ assert.match(dashboardSource, /grid-template-columns:\s*minmax\(0,\s*1\.9fr\)\s*
|
|||||||
assert.match(dashboardSource, /\.training-chart\s*\{[\s\S]*?height:\s*300px;[\s\S]*?min-height:\s*300px;/, '训练统计图应保持舒展、稳定的展示高度')
|
assert.match(dashboardSource, /\.training-chart\s*\{[\s\S]*?height:\s*300px;[\s\S]*?min-height:\s*300px;/, '训练统计图应保持舒展、稳定的展示高度')
|
||||||
assert.match(dashboardSource, /\.service-table\s*\{[\s\S]*?grid-template-rows:[^;]*repeat\(4,\s*minmax\(48px,\s*1fr\)\)/, '服务状态行应随中间区域同步拉伸')
|
assert.match(dashboardSource, /\.service-table\s*\{[\s\S]*?grid-template-rows:[^;]*repeat\(4,\s*minmax\(48px,\s*1fr\)\)/, '服务状态行应随中间区域同步拉伸')
|
||||||
assert.match(dashboardSource, /\.tasks-heading\s*\{[\s\S]*?min-height:\s*32px;[\s\S]*?padding:\s*0 14px 10px;/, '训练任务标题区应适当加高')
|
assert.match(dashboardSource, /\.tasks-heading\s*\{[\s\S]*?min-height:\s*32px;[\s\S]*?padding:\s*0 14px 10px;/, '训练任务标题区应适当加高')
|
||||||
assert.match(dashboardSource, /\.tasks-table\s*\{[\s\S]*?th,\s*td\s*\{[\s\S]*?height:\s*42px;[\s\S]*?th\s*\{[\s\S]*?height:\s*36px;/, '训练任务表格行应适当加高')
|
assert.match(dashboardSource, /\.tasks-table\s*\{[\s\S]*?th,\s*td\s*\{[\s\S]*?height:\s*50px;[\s\S]*?th\s*\{[\s\S]*?height:\s*38px;/, '训练任务表格正文行应保持舒展')
|
||||||
assert.match(dashboardSource, /@media\s*\(max-height:\s*900px\)[\s\S]*?\.tasks-heading\s*\{[\s\S]*?min-height:\s*28px;[\s\S]*?padding:\s*0 12px 8px;[\s\S]*?\.tasks-table\s*\{[\s\S]*?height:\s*36px;[\s\S]*?th\s*\{[\s\S]*?height:\s*32px;/, '低高度桌面视口也应提高训练任务占比')
|
assert.match(dashboardSource, /@media\s*\(max-height:\s*900px\)[\s\S]*?\.tasks-heading\s*\{[\s\S]*?min-height:\s*28px;[\s\S]*?padding:\s*0 12px 8px;[\s\S]*?\.tasks-table\s*\{[\s\S]*?height:\s*42px;[\s\S]*?th\s*\{[\s\S]*?height:\s*34px;/, '低高度桌面视口也应保留可读的训练任务行高')
|
||||||
assert.match(dashboardSource, /class=["']user-stats-row["'][\s\S]*?用户操作分布[\s\S]*?登录时长排行[\s\S]*?最近登录用户/, '服务看板应展示三块用户统计卡片')
|
assert.match(dashboardSource, /class=["']user-stats-row["'][\s\S]*?用户操作分布[\s\S]*?登录时长排行[\s\S]*?最近登录用户/, '服务看板应展示三块用户统计卡片')
|
||||||
assert.match(dashboardSource, /class=["']duration-chart["'][\s\S]*?loginDurationChartOption/, '登录时长应使用 ECharts 图表展示')
|
assert.match(dashboardSource, /class=["']duration-chart["'][\s\S]*?loginDurationChartOption/, '登录时长应使用 ECharts 图表展示')
|
||||||
assert.match(dashboardSource, /const loginDurationChartOption[\s\S]*?type:\s*['"]bar['"][\s\S]*?formatter:\s*['"]\{c\} 小时['"]/, '登录时长应以横向柱状图展示具体小时数')
|
assert.match(dashboardSource, /const loginDurationChartOption[\s\S]*?type:\s*['"]bar['"][\s\S]*?formatter:\s*['"]\{c\} 小时['"]/, '登录时长应以横向柱状图展示具体小时数')
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ assert.match(rootPageCardBlock, /box-shadow:\s*none\s*!important;/, '页面根
|
|||||||
const trainingLogStyle = [trainingLogSource, trainingOverviewSource]
|
const trainingLogStyle = [trainingLogSource, trainingOverviewSource]
|
||||||
.flatMap((source) => parseSfc(source).descriptor.styles.map((item) => item.content))
|
.flatMap((source) => parseSfc(source).descriptor.styles.map((item) => item.content))
|
||||||
.join('\n')
|
.join('\n')
|
||||||
const businessSurfaceBlock = extractCssBlock(trainingLogStyle, '.profile-section,\n.runtime-panel')
|
const businessSurfaceBlock = extractCssBlock(trainingLogStyle, '.task-overview')
|
||||||
assert.match(
|
assert.match(
|
||||||
businessSurfaceBlock,
|
businessSurfaceBlock,
|
||||||
/background:\s*var\(--app-surface-bg\);/,
|
/background:\s*var\(--app-surface-bg\);/,
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ function updateTime() {
|
|||||||
currentDate.value = now.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-')
|
currentDate.value = now.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' }).replace(/\//g, '-')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openGuide() {
|
||||||
|
const guideUrl = router.resolve({ name: 'guide' }).href
|
||||||
|
window.open(guideUrl, '_blank', 'noopener,noreferrer')
|
||||||
|
}
|
||||||
|
|
||||||
const serverIp = ref(window.location.hostname)
|
const serverIp = ref(window.location.hostname)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -103,6 +108,19 @@ onUnmounted(() => {
|
|||||||
<span>{{ currentTime }}</span>
|
<span>{{ currentTime }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="divider document-divider"></div>
|
||||||
|
|
||||||
|
<el-tooltip content="使用文档" placement="bottom">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="documentation-btn"
|
||||||
|
aria-label="打开使用文档"
|
||||||
|
@click="openGuide"
|
||||||
|
>
|
||||||
|
<i class="fa fa-book" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
@@ -261,4 +279,50 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.documentation-btn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
background: #fff;
|
||||||
|
color: #64748b;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 17px;
|
||||||
|
transition: color 180ms ease, border-color 180ms ease, background-color 180ms ease, box-shadow 180ms ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(79, 70, 229, 0.28);
|
||||||
|
background: #eef2ff;
|
||||||
|
color: var(--primary-color);
|
||||||
|
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 3px solid rgba(79, 70, 229, 0.2);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1280px) {
|
||||||
|
.header-right {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-info .info-item:first-child {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1040px) {
|
||||||
|
.system-info,
|
||||||
|
.header-right > .divider:not(.document-divider) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import('@/views/login/LoginView.vue'),
|
component: () => import('@/views/login/LoginView.vue'),
|
||||||
meta: { title: '登录', public: true },
|
meta: { title: '登录', public: true },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/guide',
|
||||||
|
name: 'guide',
|
||||||
|
component: () => import('@/views/guide/GuideView.vue'),
|
||||||
|
meta: { title: '使用文档', skipPermission: true },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => import('@/layouts/MainLayout.vue'),
|
component: () => import('@/layouts/MainLayout.vue'),
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ const loginDurationStats: LoginDurationStat[] = [
|
|||||||
|
|
||||||
const loginDurationChartOption = computed<EChartsOption>(() => ({
|
const loginDurationChartOption = computed<EChartsOption>(() => ({
|
||||||
animationDuration: 500,
|
animationDuration: 500,
|
||||||
grid: { top: 8, right: 40, bottom: 6, left: 8, containLabel: true },
|
grid: { top: 8, right: 60, bottom: 6, left: 8, containLabel: true },
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer: { type: 'shadow' },
|
axisPointer: { type: 'shadow' },
|
||||||
@@ -261,7 +261,7 @@ const loginDurationChartOption = computed<EChartsOption>(() => ({
|
|||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
max: Math.ceil(Math.max(...loginDurationStats.map((user) => user.duration)) / 10) * 10,
|
max: Math.ceil(Math.max(...loginDurationStats.map((user) => user.duration)) * 1.15 / 10) * 10,
|
||||||
splitNumber: 4,
|
splitNumber: 4,
|
||||||
axisLabel: { color: '#94a3b8', fontSize: 11, formatter: '{value}h' },
|
axisLabel: { color: '#94a3b8', fontSize: 11, formatter: '{value}h' },
|
||||||
axisLine: { show: false },
|
axisLine: { show: false },
|
||||||
@@ -284,7 +284,7 @@ const loginDurationChartOption = computed<EChartsOption>(() => ({
|
|||||||
barMaxWidth: 18,
|
barMaxWidth: 18,
|
||||||
barCategoryGap: '34%',
|
barCategoryGap: '34%',
|
||||||
itemStyle: { color: '#4f46e5', borderRadius: [0, 4, 4, 0] },
|
itemStyle: { color: '#4f46e5', borderRadius: [0, 4, 4, 0] },
|
||||||
label: { show: true, position: 'right', distance: 8, color: '#64748b', fontSize: 11, formatter: '{c} 小时' },
|
label: { show: true, position: 'right', distance: 6, color: '#64748b', fontSize: 11, formatter: '{c} 小时' },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}))
|
}))
|
||||||
@@ -798,8 +798,8 @@ function viewTask(task: DashboardTask) {
|
|||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
height: 42px;
|
height: 50px;
|
||||||
padding: 6px 10px;
|
padding: 8px 10px;
|
||||||
border-top: 1px solid #eef2f7;
|
border-top: 1px solid #eef2f7;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@@ -807,7 +807,7 @@ function viewTask(task: DashboardTask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
height: 36px;
|
height: 38px;
|
||||||
background: #f8fafc;
|
background: #f8fafc;
|
||||||
color: #475569;
|
color: #475569;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -925,12 +925,12 @@ function viewTask(task: DashboardTask) {
|
|||||||
.tasks-table {
|
.tasks-table {
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
height: 36px;
|
height: 42px;
|
||||||
padding: 4px 8px;
|
padding: 6px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
height: 32px;
|
height: 34px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const WIZARD_STEPS = [
|
|||||||
{ id: 'upload', title: '上传文件', desc: '上传或接入待处理的源数据' },
|
{ id: 'upload', title: '上传文件', desc: '上传或接入待处理的源数据' },
|
||||||
{ id: 'preview', title: '数据预览', desc: '核对源文件与预览内容' },
|
{ id: 'preview', title: '数据预览', desc: '核对源文件与预览内容' },
|
||||||
{ id: 'generate', title: '开始生成', desc: '确认摘要并启动处理' },
|
{ id: 'generate', title: '开始生成', desc: '确认摘要并启动处理' },
|
||||||
{ id: 'results', title: '编辑与保存', desc: '检查、修改并保存结果' },
|
{ id: 'results', title: '结果编辑与保存', desc: '检查、修改并保存结果' },
|
||||||
] as const satisfies ReadonlyArray<{ id: StepId; title: string; desc: string }>
|
] as const satisfies ReadonlyArray<{ id: StepId; title: string; desc: string }>
|
||||||
const currentStep = ref(0)
|
const currentStep = ref(0)
|
||||||
const currentStepId = computed<StepId>(() => WIZARD_STEPS[currentStep.value]?.id ?? 'create')
|
const currentStepId = computed<StepId>(() => WIZARD_STEPS[currentStep.value]?.id ?? 'create')
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ function formatDateTime(value?: string) {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border: 1px solid #e4e7ed !important;
|
border: 1px solid #e4e7ed !important;
|
||||||
border-radius: 8px !important;
|
border-radius: 8px !important;
|
||||||
|
background: var(--app-surface-bg);
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
.overview-layout { width: 100%; }
|
.overview-layout { width: 100%; }
|
||||||
|
|||||||
Reference in New Issue
Block a user