项目中心
This commit is contained in:
108
src/views/project/cpns/ProjectProgress.vue
Normal file
108
src/views/project/cpns/ProjectProgress.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
/** 总体进度百分比(后端 `projectStage.developmentProgress`;未立项为 0) */
|
||||
progress: number
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
/** 进度条填充宽度(夹到 0~100,避免脏数据把条撑出容器) */
|
||||
function clampPercent(value: number): number {
|
||||
if (!Number.isFinite(value)) return 0
|
||||
return Math.min(100, Math.max(0, Math.round(value)))
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="project-progress">
|
||||
<h2 class="project-progress__title">
|
||||
开发进度
|
||||
</h2>
|
||||
|
||||
<div class="project-progress__head">
|
||||
<span class="project-progress__label text-secondary">总体进度</span>
|
||||
<span class="project-progress__percent">{{ clampPercent(props.progress) }}%</span>
|
||||
</div>
|
||||
|
||||
<!-- 设计稿:轨道通栏,蓝色填充,末端一个白底蓝环圆点(进度为 0 时不画圆点) -->
|
||||
<div class="project-progress__track">
|
||||
<div class="project-progress__fill" :style="{ width: `${clampPercent(props.progress)}%` }" />
|
||||
<span
|
||||
v-if="clampPercent(props.progress) > 0"
|
||||
class="project-progress__knob"
|
||||
:style="{ left: `${clampPercent(props.progress)}%` }"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="project-progress__range">
|
||||
<span class="text-secondary">开始时间:{{ props.startTime || '—' }}</span>
|
||||
<span class="text-secondary">结束时间:{{ props.endTime || '—' }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.project-progress {
|
||||
.flex(column, flex-start, stretch);
|
||||
padding: @spacing-lg;
|
||||
border-radius: @radius-lg;
|
||||
background: @white;
|
||||
box-shadow: @shadow-base;
|
||||
|
||||
&__title {
|
||||
.section-title();
|
||||
}
|
||||
|
||||
// 设计稿:正文块相对标题再右缩进一级(设计 27 设计px × 0.77 ≈ 21px)
|
||||
&__head {
|
||||
.flex(row, space-between, center);
|
||||
margin-top: @spacing-base;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
&__percent {
|
||||
font-size: @font-size-title;
|
||||
font-weight: 600;
|
||||
color: @project-accent;
|
||||
}
|
||||
|
||||
&__track {
|
||||
position: relative;
|
||||
height: 5px;
|
||||
margin: @spacing-base 0 0 21px;
|
||||
border-radius: @radius-round;
|
||||
background: @project-track;
|
||||
}
|
||||
|
||||
&__fill {
|
||||
height: 100%;
|
||||
border-radius: @radius-round;
|
||||
background: @project-accent;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
&__knob {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid @project-accent;
|
||||
border-radius: @radius-round;
|
||||
background: @white;
|
||||
transform: translate(-50%, -50%);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&__range {
|
||||
.flex(row, space-between, center);
|
||||
margin-top: @spacing-lg;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user