780 lines
18 KiB
Vue
780 lines
18 KiB
Vue
<template>
|
||
<div class="demo-home">
|
||
<section class="toolbar-meta">
|
||
<span class="snapshot-time">数据截至:{{ displayDashboard.snapshotTime || '暂无实时数据' }}</span>
|
||
<el-button text :icon="Refresh" :loading="dashboardLoading" @click="loadDashboard">刷新</el-button>
|
||
</section>
|
||
|
||
<section class="hero-grid">
|
||
<article v-for="item in heroEntries" :key="item.title" class="entry-card">
|
||
<div class="entry-main">
|
||
<div class="entry-icon">
|
||
<el-icon><component :is="item.icon" /></el-icon>
|
||
</div>
|
||
<div>
|
||
<h2>{{ item.title }}</h2>
|
||
<p>{{ item.desc }}</p>
|
||
<span class="status-pill" :class="`pill-${item.type}`">{{ item.status }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="entry-actions">
|
||
<el-button type="danger" :disabled="!item.path" @click="goFeature(item.path)">进入功能</el-button>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section class="content-grid">
|
||
<article class="panel progress-panel">
|
||
<div class="panel-title">
|
||
<h2>选 用 育 留 案例沉淀 流程进度</h2>
|
||
</div>
|
||
<div class="stage-track">
|
||
<div v-for="stage in stages" :key="stage.name" class="stage-item" :class="stage.state">
|
||
<div class="stage-node">
|
||
<el-icon v-if="stage.state === 'done'"><Check /></el-icon>
|
||
<span v-else>{{ stage.step }}</span>
|
||
</div>
|
||
<div class="stage-copy">
|
||
<strong>{{ stage.name }}</strong>
|
||
<span>{{ stage.desc }}</span>
|
||
<span class="status-pill" :class="`pill-${stage.tagType}`">{{ stage.label }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="panel risk-panel">
|
||
<div class="panel-title">
|
||
<h2>验收待办与风险</h2>
|
||
</div>
|
||
<ul class="risk-list">
|
||
<li v-for="risk in risks" :key="risk.name">
|
||
<div class="risk-icon">
|
||
<el-icon><component :is="risk.icon" /></el-icon>
|
||
</div>
|
||
<span class="risk-name">{{ risk.name }}</span>
|
||
<span class="risk-owner">负责人:{{ risk.owner }}</span>
|
||
<span class="status-pill risk-status" :class="`pill-${risk.type}`">{{ risk.status }}</span>
|
||
</li>
|
||
</ul>
|
||
</article>
|
||
</section>
|
||
|
||
<section class="bottom-grid">
|
||
<article class="panel record-panel">
|
||
<div class="panel-title compact">
|
||
<h2>最近训练记录</h2>
|
||
</div>
|
||
<el-table :data="records" size="small" class="record-table" empty-text="暂无训练记录">
|
||
<el-table-column prop="name" label="人员" min-width="92" />
|
||
<el-table-column prop="scene" label="场景" min-width="118" />
|
||
<el-table-column prop="score" label="得分" width="68" />
|
||
<el-table-column label="状态" width="88">
|
||
<template #default="{ row }">
|
||
<span class="status-dot" :class="row.state"></span>
|
||
{{ row.status }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="time" label="时间" width="112" />
|
||
</el-table>
|
||
<button type="button" class="panel-link" @click="goFeature('/train/practice')">
|
||
查看更多 <el-icon><ArrowRight /></el-icon>
|
||
</button>
|
||
</article>
|
||
|
||
<article class="panel pipeline-panel">
|
||
<div class="panel-title compact">
|
||
<h2>案例沉淀 Pipeline</h2>
|
||
</div>
|
||
<div class="pipeline-steps">
|
||
<div v-for="(step, index) in pipeline" :key="step.name" class="pipeline-step">
|
||
<div class="pipeline-icon">
|
||
<el-icon><component :is="step.icon" /></el-icon>
|
||
</div>
|
||
<strong>{{ step.name }}</strong>
|
||
<span>{{ step.count }}</span>
|
||
<el-icon v-if="index < pipeline.length - 1" class="pipeline-arrow"><ArrowRight /></el-icon>
|
||
</div>
|
||
</div>
|
||
<div class="pipeline-summary">
|
||
<span>今日新增:{{ pipelineSummary.todayNew }}</span>
|
||
<span>待审核:{{ pipelineSummary.pending }}</span>
|
||
<span>已入库:{{ pipelineSummary.completed }}</span>
|
||
</div>
|
||
<button type="button" class="panel-link" @click="goFeature('/knowledge/cases')">
|
||
进入案例沉淀 <el-icon><ArrowRight /></el-icon>
|
||
</button>
|
||
</article>
|
||
|
||
<article class="panel metrics-panel">
|
||
<div class="panel-title compact">
|
||
<h2>验收指标</h2>
|
||
</div>
|
||
<div class="metric-grid">
|
||
<div v-for="metric in metrics" :key="metric.label" class="metric-card">
|
||
<el-icon><component :is="metric.icon" /></el-icon>
|
||
<div>
|
||
<span>{{ metric.label }}</span>
|
||
<strong>{{ metric.value }}</strong>
|
||
<small>{{ metric.target }}</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="panel-link" @click="goFeature('/competency/growth')">
|
||
查看指标详情 <el-icon><ArrowRight /></el-icon>
|
||
</button>
|
||
</article>
|
||
</section>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup name="Index" lang="ts">
|
||
import {
|
||
ArrowRight,
|
||
Check,
|
||
Cpu,
|
||
DataLine,
|
||
DocumentChecked,
|
||
Finished,
|
||
FolderChecked,
|
||
Headset,
|
||
Histogram,
|
||
Microphone,
|
||
Notebook,
|
||
Operation,
|
||
Reading,
|
||
Refresh,
|
||
Switch,
|
||
Tickets,
|
||
TrendCharts,
|
||
UserFilled
|
||
} from '@element-plus/icons-vue';
|
||
import { computed, onMounted, ref } from 'vue';
|
||
import { useRouter } from 'vue-router';
|
||
import { getDashboardOverview, type DashboardMetric, type DashboardOverview, type DashboardRisk } from '@/api/aihr/dashboard';
|
||
|
||
const router = useRouter();
|
||
|
||
const emptyDashboard: DashboardOverview = {
|
||
snapshotTime: '',
|
||
heroEntries: [],
|
||
stages: [
|
||
{ step: 1, name: '选:AI面试', desc: '题目与评估', label: '可试用', state: 'done', tagType: 'success' },
|
||
{ step: 2, name: '用:岗位适配', desc: '组织快照', label: '待同步', state: 'idle', tagType: 'info' },
|
||
{ step: 3, name: '育:三角色对练', desc: '实战陪练', label: '待跑通', state: 'active', tagType: 'danger' },
|
||
{ step: 4, name: '留:成长追踪', desc: '能力画像', label: '待积累', state: 'idle', tagType: 'info' },
|
||
{ step: 5, name: '案例沉淀', desc: '知识与复用', label: '待入库', state: 'idle', tagType: 'info' }
|
||
],
|
||
risks: [
|
||
{ name: '住宅 SOP 素材', owner: '培训组', status: '0/5', type: 'danger' },
|
||
{ name: '方言 ASR', owner: '技术组', status: '未配置', type: 'warning' },
|
||
{ name: '候选资料审核', owner: 'HR组', status: '无待审', type: 'success' },
|
||
{ name: '移动训练复盘', owner: '主管', status: '无待复盘', type: 'success' }
|
||
],
|
||
records: [],
|
||
pipeline: [
|
||
{ name: '语音上传', count: '0 条', state: 'todo' },
|
||
{ name: 'ASR 转写', count: '0 条', state: 'todo' },
|
||
{ name: 'AI 整理', count: '0 条', state: 'todo' },
|
||
{ name: '审核入库', count: '0 条', state: 'todo' },
|
||
{ name: '培训复用', count: '0 条', state: 'todo' }
|
||
],
|
||
pipelineSummary: { todayNew: '0 条', pending: '0 条', completed: '0 条' },
|
||
metrics: [
|
||
{ label: '端到端路径', value: '0 条', target: 'L0 目标 >= 1 条', type: 'danger' },
|
||
{ label: 'SOP已入库', value: '0 份', target: 'B1 目标 >= 5 流程', type: 'danger' },
|
||
{ label: '训练记录', value: '0 条', target: '育:至少 1 类场景', type: 'danger' },
|
||
{ label: '试点人数', value: '0 人', target: 'D1 目标 >= 20 人', type: 'danger' }
|
||
]
|
||
};
|
||
|
||
const dashboard = ref<DashboardOverview | null>(null);
|
||
const dashboardLoading = ref(false);
|
||
const displayDashboard = computed(() => dashboard.value ?? emptyDashboard);
|
||
|
||
const baseHeroEntries = [
|
||
{
|
||
key: 'interview',
|
||
title: 'AI面试出题',
|
||
desc: '基于岗位画像与 JD,一键生成面试题目',
|
||
status: '可试用',
|
||
type: 'success',
|
||
icon: DocumentChecked,
|
||
path: '/recruit/interview'
|
||
},
|
||
{
|
||
key: 'practice',
|
||
title: '三角色对练',
|
||
desc: '简历生成 + 面试对象 + 结果评估闭环',
|
||
status: '待跑通',
|
||
type: 'warning',
|
||
icon: UserFilled,
|
||
path: '/train/practice'
|
||
},
|
||
{
|
||
key: 'case',
|
||
title: '案例语音整理',
|
||
desc: '语音上传,AI 整理为结构化案例',
|
||
status: '待入库',
|
||
type: 'warning',
|
||
icon: Microphone,
|
||
path: '/knowledge/cases'
|
||
},
|
||
{
|
||
key: 'sop',
|
||
title: 'SOP知识库',
|
||
desc: '知识库检索 + RAG问答,支持员工赋能',
|
||
status: '待入库',
|
||
type: 'warning',
|
||
icon: Reading,
|
||
path: '/knowledge/sop'
|
||
}
|
||
];
|
||
|
||
const goFeature = (path?: string) => {
|
||
if (!path) return;
|
||
router.push(path);
|
||
};
|
||
|
||
const heroEntries = computed(() => {
|
||
const statusMap = new Map(displayDashboard.value.heroEntries.map((item) => [item.key, item]));
|
||
return baseHeroEntries.map((item) => ({ ...item, ...(statusMap.get(item.key) ?? {}) }));
|
||
});
|
||
|
||
const stages = computed(() => displayDashboard.value.stages);
|
||
const records = computed(() => displayDashboard.value.records);
|
||
const pipelineSummary = computed(() => displayDashboard.value.pipelineSummary);
|
||
|
||
const pipelineIcons = [FolderChecked, Histogram, Cpu, Tickets, Notebook];
|
||
const pipeline = computed(() =>
|
||
displayDashboard.value.pipeline.map((step, index) => ({
|
||
...step,
|
||
icon: pipelineIcons[index] ?? FolderChecked
|
||
}))
|
||
);
|
||
|
||
const risks = computed(() => displayDashboard.value.risks.map((risk) => ({ ...risk, icon: riskIcon(risk) })));
|
||
const metrics = computed(() => displayDashboard.value.metrics.map((metric) => ({ ...metric, icon: metricIcon(metric) })));
|
||
|
||
const riskIcon = (risk: DashboardRisk) => {
|
||
if (risk.name.includes('SOP')) return Tickets;
|
||
if (risk.name.includes('ASR')) return Headset;
|
||
if (risk.name.includes('审核')) return Finished;
|
||
return Notebook;
|
||
};
|
||
|
||
const metricIcon = (metric: DashboardMetric) => {
|
||
if (metric.label.includes('路径')) return Switch;
|
||
if (metric.label.includes('SOP')) return Operation;
|
||
if (metric.label.includes('训练')) return TrendCharts;
|
||
return DataLine;
|
||
};
|
||
|
||
const loadDashboard = async () => {
|
||
dashboardLoading.value = true;
|
||
try {
|
||
const { data } = await getDashboardOverview();
|
||
dashboard.value = data;
|
||
} catch {
|
||
dashboard.value = null;
|
||
} finally {
|
||
dashboardLoading.value = false;
|
||
}
|
||
};
|
||
|
||
onMounted(loadDashboard);
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.demo-home {
|
||
min-height: calc(100vh - 84px);
|
||
padding: 22px;
|
||
background: #f5f7fb;
|
||
color: #162033;
|
||
}
|
||
|
||
.toolbar-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 12px;
|
||
margin-bottom: 12px;
|
||
color: #657184;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.status-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: fit-content;
|
||
min-height: 24px;
|
||
padding: 0 10px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
line-height: 24px;
|
||
font-weight: 700;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.pill-danger {
|
||
color: #c80f1f;
|
||
background: #ffe8e9;
|
||
}
|
||
|
||
.pill-success {
|
||
color: #15844a;
|
||
background: #e5f8ee;
|
||
}
|
||
|
||
.pill-warning {
|
||
color: #c46b00;
|
||
background: #fff2dc;
|
||
}
|
||
|
||
.pill-primary {
|
||
color: #1467bd;
|
||
background: #e7f2ff;
|
||
}
|
||
|
||
.pill-info {
|
||
color: #64748b;
|
||
background: #eef2f7;
|
||
}
|
||
|
||
.hero-grid,
|
||
.content-grid,
|
||
.bottom-grid {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
|
||
.hero-grid {
|
||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.content-grid {
|
||
grid-template-columns: minmax(0, 1.25fr) minmax(360px, 0.75fr);
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.bottom-grid {
|
||
grid-template-columns: minmax(350px, 1fr) minmax(420px, 1.1fr) minmax(330px, 0.9fr);
|
||
}
|
||
|
||
.panel,
|
||
.entry-card {
|
||
border: 1px solid #e4e9f2;
|
||
border-radius: 8px;
|
||
background: #fff;
|
||
box-shadow: 0 10px 24px rgba(21, 30, 45, 0.04);
|
||
}
|
||
|
||
.entry-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: 188px;
|
||
padding: 22px 22px 20px;
|
||
}
|
||
|
||
.entry-main {
|
||
display: flex;
|
||
gap: 16px;
|
||
align-items: flex-start;
|
||
|
||
h2 {
|
||
margin: 2px 0 8px;
|
||
font-size: 18px;
|
||
line-height: 1.25;
|
||
font-weight: 700;
|
||
}
|
||
|
||
p {
|
||
min-height: 40px;
|
||
margin: 0 0 12px;
|
||
color: #3f4b5f;
|
||
font-size: 13px;
|
||
line-height: 1.55;
|
||
}
|
||
}
|
||
|
||
.entry-icon {
|
||
display: grid;
|
||
width: 58px;
|
||
height: 58px;
|
||
flex: 0 0 58px;
|
||
place-items: center;
|
||
border-radius: 8px;
|
||
color: #fff;
|
||
background: linear-gradient(135deg, #ff6b72, #d90f20);
|
||
font-size: 32px;
|
||
box-shadow: 0 10px 20px rgba(216, 15, 32, 0.22);
|
||
}
|
||
|
||
.entry-actions {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 12px;
|
||
margin-top: 22px;
|
||
|
||
.el-button {
|
||
margin: 0;
|
||
}
|
||
}
|
||
|
||
.panel {
|
||
padding: 18px;
|
||
}
|
||
|
||
.panel-title {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 18px;
|
||
|
||
&.compact {
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
h2 {
|
||
margin: 0;
|
||
font-size: 17px;
|
||
line-height: 1.35;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
.stage-track {
|
||
display: grid;
|
||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||
gap: 12px;
|
||
}
|
||
|
||
.stage-item {
|
||
position: relative;
|
||
display: grid;
|
||
justify-items: center;
|
||
gap: 12px;
|
||
min-height: 150px;
|
||
text-align: center;
|
||
|
||
&:not(:last-child)::after {
|
||
position: absolute;
|
||
top: 22px;
|
||
right: -50%;
|
||
width: 100%;
|
||
height: 0;
|
||
border-top: 2px dashed #c7ced8;
|
||
content: '';
|
||
}
|
||
|
||
&.done:not(:last-child)::after {
|
||
border-color: #31b367;
|
||
}
|
||
|
||
&.active:not(:last-child)::after {
|
||
border-color: #d70f20;
|
||
}
|
||
}
|
||
|
||
.stage-node {
|
||
z-index: 1;
|
||
display: grid;
|
||
width: 48px;
|
||
height: 48px;
|
||
place-items: center;
|
||
border: 2px solid #d3d9e3;
|
||
border-radius: 50%;
|
||
background: #fff;
|
||
color: #69758a;
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.stage-item.done .stage-node {
|
||
border-color: #31b367;
|
||
color: #fff;
|
||
background: #31b367;
|
||
}
|
||
|
||
.stage-item.active .stage-node {
|
||
border-color: #d70f20;
|
||
color: #fff;
|
||
background: #d70f20;
|
||
}
|
||
|
||
.stage-copy {
|
||
display: grid;
|
||
justify-items: center;
|
||
gap: 8px;
|
||
|
||
strong {
|
||
font-size: 14px;
|
||
}
|
||
|
||
span {
|
||
min-height: 34px;
|
||
color: #303b4c;
|
||
font-size: 13px;
|
||
line-height: 1.35;
|
||
}
|
||
}
|
||
|
||
.risk-list {
|
||
display: grid;
|
||
gap: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
list-style: none;
|
||
|
||
li {
|
||
display: grid;
|
||
grid-template-columns: 34px minmax(110px, 1fr) minmax(120px, 0.8fr) 82px;
|
||
align-items: center;
|
||
gap: 12px;
|
||
min-height: 43px;
|
||
border-bottom: 1px solid #edf0f5;
|
||
|
||
&:last-child {
|
||
border-bottom: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.risk-icon {
|
||
color: #5d6878;
|
||
font-size: 22px;
|
||
}
|
||
|
||
.risk-name {
|
||
font-weight: 700;
|
||
}
|
||
|
||
.risk-owner {
|
||
color: #637085;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.record-panel {
|
||
:deep(.el-table__inner-wrapper::before) {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.record-table {
|
||
border: 1px solid #edf0f5;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.status-dot {
|
||
display: inline-block;
|
||
width: 6px;
|
||
height: 6px;
|
||
margin-right: 6px;
|
||
border-radius: 50%;
|
||
vertical-align: middle;
|
||
|
||
&.done {
|
||
background: #31b367;
|
||
}
|
||
|
||
&.active {
|
||
background: #e6a23c;
|
||
}
|
||
|
||
&.danger {
|
||
background: #d70f20;
|
||
}
|
||
}
|
||
|
||
.pipeline-steps {
|
||
display: grid;
|
||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||
gap: 12px;
|
||
padding: 8px 0 18px;
|
||
}
|
||
|
||
.pipeline-step {
|
||
position: relative;
|
||
display: grid;
|
||
justify-items: center;
|
||
gap: 8px;
|
||
text-align: center;
|
||
|
||
strong {
|
||
font-size: 13px;
|
||
}
|
||
|
||
span {
|
||
color: #0f7be8;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
.pipeline-icon {
|
||
display: grid;
|
||
width: 56px;
|
||
height: 56px;
|
||
place-items: center;
|
||
border: 1px solid #dce2ec;
|
||
border-radius: 50%;
|
||
background: #f8fafc;
|
||
color: #1d2b3f;
|
||
font-size: 30px;
|
||
}
|
||
|
||
.pipeline-arrow {
|
||
position: absolute;
|
||
top: 22px;
|
||
right: -18px;
|
||
color: #aab3c2;
|
||
}
|
||
|
||
.pipeline-summary {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px 16px;
|
||
padding-top: 14px;
|
||
border-top: 1px solid #edf0f5;
|
||
color: #526178;
|
||
|
||
span {
|
||
position: relative;
|
||
|
||
&:not(:last-child)::after {
|
||
position: absolute;
|
||
top: 3px;
|
||
right: -9px;
|
||
width: 1px;
|
||
height: 12px;
|
||
background: #cbd3df;
|
||
content: '';
|
||
}
|
||
}
|
||
}
|
||
|
||
.metric-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
gap: 8px;
|
||
}
|
||
|
||
.metric-card {
|
||
display: grid;
|
||
grid-template-columns: 44px minmax(0, 1fr);
|
||
align-items: center;
|
||
gap: 10px;
|
||
min-height: 86px;
|
||
padding: 12px;
|
||
border: 1px solid #e5eaf3;
|
||
border-radius: 8px;
|
||
|
||
.el-icon {
|
||
color: #d70f20;
|
||
font-size: 34px;
|
||
}
|
||
|
||
span,
|
||
small {
|
||
display: block;
|
||
color: #5f6c80;
|
||
font-size: 12px;
|
||
}
|
||
|
||
strong {
|
||
display: block;
|
||
margin: 2px 0;
|
||
color: #142033;
|
||
font-size: 24px;
|
||
line-height: 1.1;
|
||
}
|
||
}
|
||
|
||
.panel-link {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 4px;
|
||
margin-top: 14px;
|
||
margin-left: auto;
|
||
padding: 0;
|
||
border: 0;
|
||
background: transparent;
|
||
color: #d70f20;
|
||
cursor: pointer;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
@media (max-width: 1360px) {
|
||
.hero-grid {
|
||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||
}
|
||
|
||
.content-grid,
|
||
.bottom-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.demo-home {
|
||
padding: 14px;
|
||
}
|
||
|
||
.page-heading {
|
||
align-items: flex-start;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.hero-grid,
|
||
.stage-track,
|
||
.pipeline-steps,
|
||
.metric-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.stage-item {
|
||
justify-items: start;
|
||
grid-template-columns: 48px minmax(0, 1fr);
|
||
min-height: auto;
|
||
text-align: left;
|
||
|
||
&::after {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.stage-copy {
|
||
justify-items: start;
|
||
}
|
||
|
||
.risk-list li {
|
||
grid-template-columns: 28px minmax(0, 1fr);
|
||
}
|
||
|
||
.risk-owner,
|
||
.risk-status {
|
||
grid-column: 2;
|
||
}
|
||
|
||
.pipeline-step {
|
||
grid-template-columns: 56px minmax(0, 1fr);
|
||
justify-items: start;
|
||
text-align: left;
|
||
}
|
||
|
||
.pipeline-arrow {
|
||
display: none;
|
||
}
|
||
|
||
.pipeline-summary span::after {
|
||
display: none;
|
||
}
|
||
}
|
||
</style>
|