feat ui设计稿

This commit is contained in:
Ironsp
2026-09-30 15:55:36 +08:00
parent ce8210fb3f
commit 9ab6253c81
102 changed files with 4855 additions and 2359 deletions

View File

@@ -6,21 +6,22 @@
2. **每完成一项立即打 `[x]`**(开发结束标记),不得批量补标。
3. **之后只做未完成(`[ ]`/`[~]`/`[!]`)的部分**,已完成项不再重做,除非回归失败。
4. 每个模块收尾必须过 `pnpm build`(vue-tsc 零错误)才算可打 `[x]`。
5. 当前约束:**无蓝湖设计稿、无接口文档** → 阶段二/接口细节 `[!]` 阻塞中;页面代码按 PRD + 原型降级开发(结构/交互先行,视觉参数用 `styles/variables.less` 近似值,接口用 store 层 mock 临时实现并集中标注 `// TODO(api)`,文档到位后仅替换 api 层)。
5. 当前约束:**无接口文档** → 接口细节 `[!]` 阻塞中;页面代码按 PRD + 原型降级开发(结构/交互先行,视觉参数用 `styles/variables.less` 近似值,接口用 store 层 mock 临时实现并集中标注 `// TODO(api)`,文档到位后仅替换 api 层)。
6. 蓝湖设计稿已到位(2026-09-30):pid `b0052b6c-4eaa-4709-b2d1-32cf4c1fe53b`,共 55 张设计图(因 UI 失误全部命名为「首页」,已按标注图层文字 + 像素取证完成「设计图 → 路由」映射);阶段二与「蓝湖视觉补齐」已完成。
## 阶段总览
| 阶段 | 内容 | 状态 |
| --- | --- | --- |
| 阶段一 | PRD 生成(`docs/PRD.md`) | [x] |
| 阶段二 | 蓝湖 MCP 设计稿读取(标注参数/切图) | [!] 无设计稿,阻塞 |
| 阶段二 | 蓝湖 MCP 设计稿读取(标注参数/切图) | [x](55 张标注已落盘 `specs/*.ann.txt`;`lanhu_get_design_overview/export_design_assets` 因 `UnsupportedCoordinates` 不可用,切图改由 2× 封面按标注坐标裁剪) |
| 阶段三 | 页面结构规划(`docs/page-architecture.md`) | [x] |
| 阶段四 | 页面代码生成 + 组件拆分 | [x] |
| 阶段五 | API + Store 逻辑层 | [x] |
| 阶段六 | 公共组件提取 | [x] |
| 阶段七 | 自动验证与修正(`pnpm build` 零错误) | [x] |
| 补齐 | 接口文档落地后替换 mock api 层 | [!] 无接口文档,阻塞 |
| 补齐 | 蓝湖到位后校准视觉(色值/间距/字号/切图) | [!] 无设计稿,阻塞 |
| 补齐 | 蓝湖到位后校准视觉(色值/间距/字号/切图) | [x] |
## P0 基础工程(全模块前置)
@@ -146,7 +147,8 @@
- [x] 阶段六:全局扫描,跨页面重复 UI 上移 components/,更新 components/index.ts barrel
- [x] 阶段七:逐页对照 PRD/原型自检(布局/交互/字段/组件拆分/规范合规:无 as any、页面不直接 import api)
- [x] `pnpm build`(vue-tsc)全量零错误
- [ ] 蓝湖到位后:校准 variables.less 色值/字号/间距,替换切图,逐页对照设计稿修正 → 补打 [x]
- [x] 蓝湖到位后:校准 variables.less 色值/字号/间距,替换切图,逐页对照设计稿修正(主色 `#276fff→#1f67ef`、内容强调 `#024fff`、灰阶对齐 `#1f2937/#4b5563/#6b7280/#9ca3af`、危险 `#ef4444`、成功 `#16a34a`、顶栏 `#f4f5f9`+`#d8d8d8`、页脚 `#0c1321`;AppHeader/AppFooter 按设计重写;10 个模块页面视觉按标注补齐,`<script>` 逻辑块零改动;26 条路由 QA 无横向溢出/无同色不可见文字;`pnpm build` 零错误)
- [ ] 仍无设计稿的 5 个路由(保持现状,待补设计后再次校准):`/project` 列表、`/cases/:id` 案例详情、`/finance/invoices` 发票申请、`/profile/favorites` 收藏列表、`/profile/hotline` 专属客服热线
- [ ] 接口文档到位后:逐 api 文件替换 `// TODO(api)` 为真实路径/入参出参,走真实联调 → 补打 [x]
## 完成度速查
@@ -166,5 +168,5 @@
| M10 profile | [x] |
| 阶段六 公共组件提取 | [x] |
| 阶段七 验证修正 | [x] |
| 蓝湖视觉补齐 | [!] |
| 蓝湖视觉补齐 | [x] |
| 接口联调补齐 | [!] |

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

View File

@@ -6,7 +6,7 @@ const siteStore = useSiteStore()
const quickLinks = [
{ label: '首页', path: '/' },
{ label: '案例库', path: '/cases' },
{ label: '需求池', path: '/demand' },
{ label: '需求提报', path: '/demand' },
{ label: '下载 APP', path: '/' },
{ label: '消息中心', path: '/message' },
]
@@ -25,19 +25,11 @@ const coreBusiness = [
<div class="app-footer__inner container">
<div class="app-footer__about">
<div class="app-footer__brand">
<!-- TODO(蓝湖): 替换 logo 切图 -->
<img src="@/assets/vue.svg" class="app-footer__logo" alt="虫子智造 logo">
<span class="app-footer__name">虫子智造</span>
</div>
<p class="app-footer__desc">
研发智造一体化自营平台,打通研发‑仿真‑设计‑PCB‑SMT‑整机装配‑售后迭代全链路,为科技企业、硬件厂商、创客团队提供软硬一体化定制与量产落地服务。平台自营不开放第三方服务商入驻,对项目质量全权兜底。
</p>
<p class="app-footer__legal">
©2026 虫子智造 研发智造一体化平台 版权所有|自营研发生产平台,所有项目源码、图纸受平台知识产权保护,禁止盗用、复制、二次分发
</p>
<p class="app-footer__legal">
{{ siteStore.siteInfo.icp }} | {{ siteStore.siteInfo.police }}
</p>
</div>
<div class="app-footer__col">
@@ -75,19 +67,29 @@ const coreBusiness = [
<span class="app-footer__contact">工作时间:{{ siteStore.siteInfo.workTime }}</span>
</div>
</div>
<div class="app-footer__bottom">
<p class="app-footer__legal">
©2026 虫子智造 研发智造一体化平台 版权所有|自营研发生产平台,所有项目源码、图纸受平台知识产权保护,禁止盗用、复制、二次分发
</p>
<p class="app-footer__legal">
{{ siteStore.siteInfo.icp }} | {{ siteStore.siteInfo.police }}
</p>
</div>
</footer>
</template>
<style lang="less" scoped>
.app-footer {
background: @heading-color;
color: @text-color-secondary;
background: @footer-bg;
color: @white;
&__inner {
.flex(row, space-between, flex-start);
gap: @spacing-xl;
padding-top: @spacing-xxl;
padding-bottom: @spacing-xxl;
padding-left: @footer-inset;
padding-right: @footer-inset;
}
&__about {
@@ -96,26 +98,19 @@ const coreBusiness = [
&__brand {
.flex(row, flex-start);
gap: @spacing-sm;
margin-bottom: @spacing-base;
}
&__logo {
width: 28px;
height: 28px;
}
&__name {
font-size: @font-size-lg;
font-weight: 600;
font-size: @font-size-title;
font-weight: 500;
color: @white;
}
&__desc,
&__legal {
&__desc {
margin-top: @spacing-sm;
font-size: @font-size-sm;
line-height: 1.6;
line-height: 1.8;
}
&__col {
@@ -125,22 +120,37 @@ const coreBusiness = [
&__title {
margin-bottom: @spacing-sm;
font-size: @font-size-base;
font-size: @font-size-title;
font-weight: 500;
color: @white;
}
&__link {
font-size: @font-size-sm;
line-height: 1.5;
cursor: pointer;
transition: color 0.2s;
&:hover {
color: @primary-color;
color: @primary-light;
}
}
&__contact {
font-size: @font-size-sm;
line-height: 1.8;
}
// 版权 / 备案:设计稿为页脚底部居中两行
&__bottom {
padding: @spacing-xxl @footer-inset;
text-align: center;
}
&__legal {
font-size: @font-size-sm;
line-height: 1.8;
color: @white;
}
}
</style>

View File

@@ -11,7 +11,7 @@ interface NavItem {
const navItems: NavItem[] = [
{ label: '首页', path: '/' },
{ label: '案例库', path: '/cases' },
{ label: '需求池', path: '/demand' },
{ label: '需求提报', path: '/demand' },
{ label: '项目中心', path: '/project' },
{ label: '合同中心', path: '/contract' },
{ label: '财务中心', path: '/finance' },
@@ -28,8 +28,6 @@ onMounted(() => void messageStore.fetchUnreadCount())
<header class="app-header">
<div class="app-header__inner container">
<RouterLink to="/" class="app-header__logo">
<!-- TODO(蓝湖): 替换 logo 切图 -->
<img src="@/assets/vue.svg" class="app-header__logo-icon" alt="虫子智造 logo">
<span class="app-header__logo-text">虫子智造</span>
</RouterLink>
@@ -45,10 +43,12 @@ onMounted(() => void messageStore.fetchUnreadCount())
</nav>
<div class="app-header__actions">
<RouterLink to="/demand" class="app-header__action app-header__action--primary">
快速提报
<RouterLink to="/demand" class="app-header__action">
<img src="@/assets/icons/quick-report.png" class="app-header__action-icon" alt="">
快捷提报
</RouterLink>
<RouterLink to="/service" class="app-header__action app-header__action--success">
<RouterLink to="/service" class="app-header__action">
<img src="@/assets/icons/online-service.png" class="app-header__action-icon" alt="">
在线客服
</RouterLink>
<RouterLink to="/message" class="app-header__bell" aria-label="消息中心">
@@ -69,8 +69,8 @@ onMounted(() => void messageStore.fetchUnreadCount())
top: 0;
z-index: 100;
height: @header-height;
background: @white;
box-shadow: @shadow-base;
background: @header-bg;
border-bottom: 1px solid @header-border;
&__inner {
.flex(row, space-between);
@@ -79,12 +79,6 @@ onMounted(() => void messageStore.fetchUnreadCount())
&__logo {
.flex(row, flex-start);
gap: @spacing-sm;
&-icon {
width: 32px;
height: 32px;
}
&-text {
font-size: @font-size-xl;
@@ -95,16 +89,38 @@ onMounted(() => void messageStore.fetchUnreadCount())
&__nav {
.flex(row, center);
gap: @spacing-lg;
gap: @header-nav-gap;
height: 100%;
@media (max-width: 1280px) {
gap: 32px;
}
&-item {
position: relative;
.flex(row, center);
height: 100%;
font-size: @font-size-base;
color: @text-color;
font-weight: 500;
color: @black;
transition: color 0.2s;
&:hover,
&.router-link-active {
color: @primary-color;
color: @primary-strong;
}
// 激活项底部短横线(设计 29×2px × 0.77,距顶栏底边 11px × 0.77)
&.router-link-active::after {
content: '';
position: absolute;
left: 50%;
bottom: 9px;
width: 22px;
height: 2px;
border-radius: 1px;
background: @primary-color;
transform: translateX(-50%);
}
}
}
@@ -116,23 +132,23 @@ onMounted(() => void messageStore.fetchUnreadCount())
&__action {
.flex(row, center);
gap: @spacing-xs;
height: 28px;
padding: 0 @spacing-base;
border-radius: @radius-round;
padding: 0 @spacing-sm;
border-radius: @radius-sm;
background: @primary-color;
color: @white;
font-size: @font-size-sm;
font-weight: 500;
transition: opacity 0.2s;
&:hover {
opacity: 0.88;
}
&--primary {
background: linear-gradient(90deg, @warning-color, @danger-color);
}
&--success {
background: linear-gradient(90deg, #22b14c, @success-color);
&-icon {
width: 16px;
height: 16px;
}
}

View File

@@ -68,8 +68,10 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
<style lang="less" scoped>
.case-card {
overflow: hidden;
border: 1px solid @cases-card-border;
border-radius: @radius-base;
background: @white;
box-shadow: @cases-card-shadow;
cursor: pointer;
transition: box-shadow 0.2s, transform 0.2s;
@@ -80,10 +82,8 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
&__cover {
position: relative;
margin: @spacing-sm @spacing-sm 0;
border-radius: @radius-base;
aspect-ratio: 396 / 138; // 设计04 封面 396×137.8,通栏无留白
overflow: hidden;
aspect-ratio: 16 / 5;
}
&__img {
@@ -92,21 +92,21 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
object-fit: cover;
&--placeholder {
background: linear-gradient(135deg, @primary-light, @bg-color);
background: @primary-strong; // 设计04 封面占位实底 rgba(2,79,255)
}
}
&__tag {
position: absolute;
top: 10px;
left: 10px;
height: 24px;
padding: 0 10px;
border-radius: @radius-round;
background: @primary-color;
top: 6px;
left: 14px;
height: 19px; // 设计15 标签 24 × 0.77
padding: 0 6px;
border-radius: @radius-sm;
background: @primary-strong;
color: @white;
font-size: @font-size-sm;
line-height: 24px;
font-size: 11px; // 设计 10 → 7.7,取可读下限 11
line-height: 19px;
&--hardware {
background: @tag-hardware;
@@ -160,13 +160,13 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
}
&__body {
padding: @spacing-sm @spacing-base @spacing-base;
padding: 13px 16px 11px; // 上 17 / 左 20 / 下 14 × 0.77
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
font-size: 12px; // 设计 16 × 0.77 ≈ 12.3
font-weight: 500;
color: @cases-text;
.ellipsis();
}
@@ -175,9 +175,9 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 6px @spacing-sm;
margin-top: @spacing-sm;
font-size: @font-size-sm;
font-size: 11px; // 设计 10 → 7.7,取可读下限 11
line-height: 1.5;
color: @heading-color;
color: @cases-text;
li {
/* 值可能较长(如「完成时间:2026/11/30」),换行而非截断,避免丢信息 */
@@ -186,16 +186,16 @@ const meta = computed<Array<{ label: string; value: string }>>(() => [
}
&__label {
color: @text-color-secondary;
color: inherit; // 设计04 标签与值同色 rgba(51,51,51)
}
&__more {
display: block;
width: fit-content;
margin: @spacing-base 0 0 auto;
color: @primary-color;
font-size: @font-size-base;
font-weight: 500;
margin: 11px 0 0 auto; // 设计 14 × 0.77
color: @primary-strong; // 设计04 实取 rgba(2,79,255)
font-size: 11px; // 设计 12 → 9.2,取可读下限 11
font-weight: 400;
}
}
</style>

View File

@@ -58,72 +58,92 @@ function onCancel(): void {
</template>
<style lang="less" scoped>
// 设计 24(取消绑定确认)/ 29(注销风险提示):白卡 ~840 设计px、无蒙层压暗、
// 底部两枚等宽整行按钮(次级 #EEF0F3 / 主色或危险色)
.confirm-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: rgba(0, 0, 0, 0.45);
background: transparent;
&__panel {
width: 400px;
width: 660px; // 设计 840 × 0.77
max-width: calc(100vw - 32px);
padding: @spacing-lg;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
}
// 蓝条 + 标题 15 设计px w700(与个人中心各弹窗一致)
&__title {
position: relative;
margin-bottom: @spacing-base;
font-size: @font-size-lg;
font-weight: 600;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__body {
margin-bottom: @spacing-lg;
font-size: @font-size-base;
font-size: 11px; // 设计 29 条目 13 → 11
color: @text-color;
line-height: 1.6;
line-height: 1.7;
}
// 设计 24:两枚等宽整行按钮铺满卡宽
&__footer {
.flex(row, flex-end);
.flex(row, flex-start);
gap: @spacing-sm;
}
&__btn {
height: 34px;
flex: 1;
height: 36px;
padding: 0 @spacing-base;
border: 1px solid @border-color-dark;
border-radius: @radius-base;
background: @white;
border: none;
border-radius: @profile-radius;
background: @profile-quiet-btn;
color: @text-color;
font-size: @font-size-base;
font-size: 12px;
font-weight: 500;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
// 设计 24 主按钮 #024FFF / 设计 29 危险按钮 #EF4444
&--confirm {
border-color: @primary-color;
background: @primary-color;
background: @primary-strong;
color: @white;
&:hover {
background: @primary-hover;
background: darken(@primary-strong, 6%);
color: @white;
}
&.is-danger {
border-color: @danger-color;
background: @danger-color;
&:hover {
background: fade(@danger-color, 85%);
background: darken(@danger-color, 6%);
}
}
}

View File

@@ -45,13 +45,14 @@ const emit = defineEmits<{
.flex(column, flex-start);
gap: @spacing-sm;
// 设计稿(06/07 附件条):实底 #EDEDED 灰条、无描边
&__item {
.flex(row, space-between);
gap: @spacing-base;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
padding: @spacing-base;
border: none;
border-radius: @radius-sm;
background: @demand-upload-bg;
}
&__info {

View File

@@ -71,50 +71,54 @@ const emit = defineEmits<{
<style lang="less" scoped>
.filter-panel {
padding: @spacing-base @spacing-lg;
border-radius: @radius-lg;
padding: 24px 36px; // 设计04 搜索卡左右内缩 47 × 0.77
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
&__bar {
.flex(row, flex-start);
gap: @spacing-sm;
gap: 18px; // 按钮间距 24 × 0.77
}
&__input {
width: 240px;
height: 34px;
flex: 1;
max-width: 456px; // 设计输入框 592 × 0.77
margin-right: 28px; // 与按钮总距 60 × 0.77(叠加 bar gap 18)
height: 38px; // 设计 49 × 0.77
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border: 1px solid @cases-input-border;
border-radius: @radius-sm;
background: @white;
color: @cases-text;
font-size: 15px; // 设计 20 × 0.77
outline: none;
transition: border-color 0.2s;
&::placeholder {
color: @cases-input-border;
}
&:focus {
border-color: @primary-color;
border-color: @cases-accent;
}
}
&__btn {
height: 34px;
min-width: 77px; // 设计 100 × 0.77
height: 38px; // 设计 49 × 0.77
padding: 0 @spacing-base;
border: 1px solid @border-color-dark;
border-radius: @radius-base;
background: @white;
color: @text-color;
font-size: @font-size-base;
border-radius: @radius-sm;
background: @cases-accent; // 设计 重置/搜索 均为 rgba(7,92,255)
color: @white;
font-size: 15px; // 设计 20 × 0.77
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
background: @primary-hover;
}
&--primary {
border-color: @primary-color;
background: @primary-color;
background: @cases-accent;
color: @white;
&:hover {
@@ -127,29 +131,36 @@ const emit = defineEmits<{
&__chips {
.flex(row, flex-start, center);
flex-wrap: wrap;
gap: @spacing-sm;
gap: 11px 10px; // 行距 14 / 列距 13 × 0.77
margin-top: @spacing-base;
font-size: @font-size-sm;
padding: 12px 18px 16px; // 「已选条件」面板内边距 16/24/21 × 0.77
border-radius: @radius-base;
background: @chips-panel-bg;
font-size: 15px; // 设计 20 × 0.77
}
&__chips-label {
color: @cases-text; // 设计04 标题 rgba(51,51,51)
font-weight: 500;
}
&__chip {
height: 26px;
height: 25px; // 设计 32 × 0.77
padding: 0 @spacing-sm;
border: 1px solid @primary-light;
border-radius: @radius-round;
background: @primary-light;
color: @primary-color;
font-size: @font-size-sm;
background: @white;
color: @cases-accent; // 设计 chips 文字 rgba(7,92,255)
font-size: 11px; // 设计 14 → 10.8,取可读下限 11
font-weight: 500;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-hover;
}
&--clear {
border-color: @border-color;
background: @white;
color: @text-color-secondary;
background: transparent;
color: @primary-strong; // 设计15「清空」为纯文字蓝链
}
}

View File

@@ -67,30 +67,30 @@ function go(page: number): void {
<style lang="less" scoped>
.pagination {
.flex(row, center);
gap: @spacing-xs;
padding: @spacing-base 0;
gap: @spacing-xs; // 盒间距 6 × 0.77 ≈ 5
padding: 12px 0; // 网格 → 分页 36 × 0.77(叠加主栏 gap 18)
&__btn {
.flex(row, center);
min-width: 32px;
height: 32px;
padding: 0 @spacing-xs;
min-width: 20px; // 设计15 页码盒 26 × 0.77
height: 25px; // 设计 32 × 0.77
padding: 0 3px;
border: 1px solid @border-color;
border-radius: @radius-sm;
background: @white;
color: @text-color;
font-size: @font-size-base;
color: @text-color-secondary; // 设计15 实取 rgba(107,114,128)
font-size: 11px; // 设计 12 → 9.2,取可读下限 11
transition: all 0.2s;
&:hover:not(:disabled):not(.is-ellipsis) {
border-color: @primary-color;
color: @primary-color;
border-color: @primary-strong;
color: @primary-strong;
}
&.is-active {
border-color: @primary-color;
background: @primary-color;
color: @white;
border-color: @cases-page-active-bg;
background: @cases-page-active-bg;
color: @primary-strong; // 设计15 当前页文字 rgba(2,79,255)
}
&.is-ellipsis {

View File

@@ -36,20 +36,25 @@ const levelIndex = computed(() => (level.value === 'strong' ? 3 : level.value ==
</template>
<style lang="less" scoped>
// 设计稿(54/55):满宽强度条(弱=首段红,余段浅灰轨道)+ 右端灰色强度文字 + 下方红色提示
.pwd-strength {
.flex(column, flex-start);
gap: @spacing-xs;
display: grid;
grid-template-columns: 1fr auto;
column-gap: @spacing-sm;
row-gap: 9px;
align-items: center;
&__bars {
.flex(row, center);
gap: 4px;
gap: 8px;
}
// 设计稿轨道实取 #EDEFF2,条高 5 设计px ≈ 4px
&__bar {
width: 56px;
flex: 1;
height: 4px;
border-radius: @radius-round;
background: @border-color;
border-radius: 2px;
background: @auth-track;
&.is-on.is-weak {
background: @danger-color;
@@ -64,24 +69,17 @@ const levelIndex = computed(() => (level.value === 'strong' ? 3 : level.value ==
}
}
// 设计稿强度文字为 11 设计px 中性灰(「弱」实取 rgba(156,163,175))
&__label {
font-size: @font-size-sm;
&.is-weak {
color: @danger-color;
}
&.is-medium {
color: @warning-color;
}
&.is-strong {
color: @success-color;
}
justify-self: end;
font-size: 11px;
color: @text-color-disabled;
}
&__tip {
font-size: @font-size-sm;
grid-column: 1 / -1;
margin: 0;
font-size: 11px;
color: @danger-color;
}
}

View File

@@ -57,7 +57,7 @@ onMounted(() => {
</div>
<p class="qr-panel__status text-secondary">
<template v-if="!expired">
二维码将在 <strong class="qr-panel__count">{{ countdownText }}</strong> 后失效(过期可点击二维码刷新)
<span class="qr-panel__countdown">二维码将在 <strong class="qr-panel__count">{{ countdownText }}</strong> 后失效</span>(过期可点击二维码刷新)
</template>
<template v-else>
二维码已过期,请点击刷新
@@ -67,25 +67,22 @@ onMounted(() => {
</template>
<style lang="less" scoped>
// 扫码面板(设计 39:灰色二维码占位块 + 红色倒计时胶囊 + 灰色小字提示)
.qr-panel {
.flex(column, center);
gap: @spacing-sm;
gap: 17px; // 二维码 → 倒计时(设计 22 × 0.77)
&__box {
.flex(column, center);
gap: @spacing-xs;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @white;
border: none;
border-radius: @radius-sm;
background: @contract-qr-bg;
cursor: pointer;
transition: border-color 0.2s;
&:hover {
border-color: @primary-color;
}
transition: background 0.2s;
&.is-expired {
background: @bg-color;
background: @bg-color-light;
color: @text-color-secondary;
}
}
@@ -98,12 +95,28 @@ onMounted(() => {
&__tip {
font-size: @font-size-sm;
color: @text-color-secondary;
color: @text-color;
text-align: center;
}
// 状态行:胶囊(倒计时)+ 下方灰色提示,整体居中
&__status {
font-size: @font-size-sm;
display: flex;
flex-direction: column;
align-items: center;
gap: @spacing-sm;
font-size: 11px; // 设计 13/11 → 可读下限
color: @text-color-disabled;
}
&__countdown {
display: inline-flex;
align-items: center;
padding: 8px 16px; // 胶囊高 42 设计 × 0.77
border-radius: @radius-round;
background: fade(@danger-color, 8%);
color: @danger-color; // 设计 39 实取 @danger-color
line-height: 1.4;
}
&__count {

View File

@@ -37,32 +37,40 @@ function onGetCode(): void {
.flex(row, stretch);
gap: @spacing-sm;
// 设计稿(02/54/55):验证码输入框与普通输入框同规格 40 设计px ≈ 32px、13 设计px 字号
&__input {
flex: 1;
min-width: 0;
height: 40px;
padding: 0 @spacing-base;
height: 32px;
padding: 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
}
// 设计稿:「获取验证码」为白底蓝描边蓝字小按钮(#024FFF)
&__btn {
flex-shrink: 0;
width: 132px;
height: 40px;
border: 1px solid @primary-color;
border-radius: @radius-base;
min-width: 96px;
height: 32px;
padding: 0 @spacing-sm;
border: 1px solid @primary-strong;
border-radius: 6px;
background: @white;
color: @primary-color;
font-size: @font-size-sm;
color: @primary-strong;
font-size: 11px;
transition: all 0.2s;
&:hover:not(:disabled) {

View File

@@ -14,12 +14,13 @@ withDefaults(defineProps<Props>(), { variant: 'info' })
</template>
<style lang="less" scoped>
// 设计稿(项目中心 09 付款计划徽标):约 57×22 设计px、圆角 4 设计px、11px 字、浅底彩色字
.status-tag {
display: inline-block;
padding: 2px @spacing-sm;
padding: 3px 10px;
border-radius: @radius-sm;
font-size: @font-size-sm;
line-height: 1.5;
font-size: 11px;
line-height: 16px;
white-space: nowrap;
&--primary {
@@ -28,13 +29,13 @@ withDefaults(defineProps<Props>(), { variant: 'info' })
}
&--success {
background: fade(@success-color, 12%);
background: @tag-success-bg;
color: @success-color;
}
&--warning {
background: fade(@warning-color, 12%);
color: @warning-color;
background: @tag-warning-bg;
color: @tag-warning-text;
}
&--danger {
@@ -43,7 +44,7 @@ withDefaults(defineProps<Props>(), { variant: 'info' })
}
&--info {
background: @bg-color;
background: @tag-info-bg;
color: @text-color-secondary;
}
}

View File

@@ -28,59 +28,55 @@ defineProps<Props>()
</template>
<style lang="less" scoped>
// 设计稿(06/07 三步表单):白卡上竖排「大号蓝色序号 + 区块标题」,无连接线/分隔线/阴影
.step-form {
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
box-shadow: none;
&__header {
.flex(row, center);
gap: @spacing-sm;
.flex(column, flex-start, baseline);
gap: @spacing-base;
margin-bottom: @spacing-lg;
padding-bottom: @spacing-base;
border-bottom: 1px solid @border-color;
padding-bottom: 0;
border-bottom: none;
}
&__step {
.flex(row, center);
.flex(row, baseline);
gap: @spacing-xs;
&.is-active .step-form__dot {
background: @primary-color;
color: @white;
}
&.is-done .step-form__dot {
border-color: @primary-color;
color: @primary-color;
}
&.is-active .step-form__label {
color: @primary-color;
font-weight: 600;
}
}
// 设计稿序号:48 设计px ≈ 37px、#024FFF、与内容列对齐(列宽 46px)
&__dot {
.flex(row, center);
width: 24px;
height: 24px;
border: 1px solid @border-color-dark;
border-radius: @radius-round;
font-size: @font-size-sm;
color: @text-color-secondary;
flex-shrink: 0;
width: 46px;
border: none;
border-radius: 0;
background: transparent;
font-size: 37px;
font-weight: 500;
line-height: 1;
color: @demand-accent;
text-align: left;
}
// 设计稿区块标题:28 设计px ≈ 22px、500、rgba(51,51,51)
&__label {
font-size: @font-size-base;
color: @text-color;
font-size: @font-size-title;
font-weight: 500;
color: @demand-heading;
}
// 设计稿无步骤连接线
&__line {
flex: 1;
height: 1px;
background: @border-color;
display: none;
}
&__body {
// 内容列与序号后的标题对齐(序号列 46px)
margin-left: 46px;
}
}
</style>

View File

@@ -63,20 +63,21 @@ function onDrop(event: DragEvent): void {
</template>
<style lang="less" scoped>
// 设计稿(06/07 附件条):实底 #EDEDED 灰条、无描边、90 设计px ≈ 69px 高
.upload-area {
.flex(column, center);
gap: @spacing-xs;
padding: @spacing-lg;
border: 1px dashed @border-color-dark;
border-radius: @radius-base;
background: @bg-color-light;
min-height: 69px;
padding: @spacing-base;
border: none;
border-radius: @radius-sm;
background: @demand-upload-bg;
cursor: pointer;
transition: border-color 0.2s, background 0.2s;
transition: background 0.2s;
&:hover,
&.is-dragging {
border-color: @primary-color;
background: @primary-light;
background: darken(@demand-upload-bg, 5%);
}
&.is-disabled {
@@ -85,8 +86,8 @@ function onDrop(event: DragEvent): void {
}
&__icon {
font-size: @font-size-xl;
color: @primary-color;
font-size: @font-size-lg;
color: @text-color-disabled;
}
&__hint {

View File

@@ -14,7 +14,7 @@ body {
body {
color: @text-color;
font-family: 'PingFang SC', 'Microsoft YaHei', -apple-system, 'Helvetica Neue', Arial, sans-serif;
font-family: 'PingFang SC', 'Source Han Sans SC', 'Microsoft YaHei', -apple-system, 'Helvetica Neue', Arial, sans-serif;
font-size: @font-size-base;
line-height: 1.5;
background-color: @bg-color;

View File

@@ -1,29 +1,37 @@
// ★ less 变量唯一来源(颜色/间距/字号/圆角)
// 注:蓝湖设计稿到位前为原型近似值,到位后按标注精确校准
// 注:下列色值已按蓝湖设计稿(lanhu pid=b0052b6c)标注实测校准,
// 换算约定:设计画布内容宽 1780px → 应用内容宽 1368px(.container 1400 − 2×16),
// 即 设计px × 0.77 ≈ CSS px;小字号(设计 ≤12px)按可读下限不跟缩。
// 品牌色(按案例库设计稿标注校准)
@primary-color: #276fff;
// 品牌色(设计稿实测:填充按钮/下划线 #1F67EF,内容强调 #024FFF)
@primary-color: #1f67ef;
@primary-strong: #024fff;
@primary-hover: #598bff;
@primary-light: #eaf1ff;
// 功能色
@success-color: #34c724;
// 功能色(设计稿实测:危险 #EF4444、成功 #16A34A)
@success-color: #16a34a;
@warning-color: #ff8f1f;
@danger-color: #f54a45;
@danger-color: #ef4444;
@info-color: #8a94a6;
// 文字色
@heading-color: #1f2733;
@text-color: #525e71;
@text-color-secondary: #8a94a6;
@text-color-disabled: #b8c0cc;
// 文字色(设计稿灰阶:#1F2937 / #4B5563 / #6B7280 / #9CA3AF)
@heading-color: #1f2937;
@text-color: #4b5563;
@text-color-secondary: #6b7280;
@text-color-disabled: #9ca3af;
// 背景 / 边框
// 背景 / 边框(设计稿实测:页面 #F4F6F8、顶栏 #F4F5F9、顶栏下边线 #D8D8D8、页脚 #0C1321)
@bg-color: #f5f6f8;
@bg-color-light: #fafbfc;
@border-color: #e4e7ec;
@border-color-dark: #cdd3dd;
@white: #ffffff;
@black: #000000;
@header-bg: #f4f5f9;
@header-border: #d8d8d8;
@footer-bg: #0c1321;
// 圆角
@radius-sm: 4px;
@@ -50,27 +58,44 @@
// 布局(容器宽度按设计稿标注校准:设计稿为约 1400 宽的整幅版面)
@container-width: 1400px;
@header-height: 64px;
@header-nav-gap: 72px; // 顶栏导航项间距(设计 94px × 0.77;≤1280 视口降为 32px)
@footer-height: 240px;
@footer-inset: 65px; // 页脚内容左右内缩(设计 85px × 0.77,页脚比正文更窄)
// 阴影
@shadow-base: 0 2px 8px rgba(31, 39, 51, 0.08);
@shadow-lg: 0 4px 16px rgba(31, 39, 51, 0.12);
// 案例库(按设计稿标注校准;筛选面板 / 案例卡片专用)
@filter-selected-bg: #e6f7ff; // 业务类型选中行底色
@pill-bg: #f2f2f2; // 胶囊选项默认底色
@pill-selected-bg: #d4e2ff; // 胶囊选项选中底色
@chips-panel-bg: #eff6ff; // 「已选条件」区底色
@input-bg: #f3f4f6; // 搜索框 / 日期区间底色
@tag-hardware: #82b43b; // 业务标签:硬件电路
// 案例库(蓝湖设计稿 04/08/15;筛选面板 / 案例卡片 / 分页专用)
// ⚠️ 换算约定:设计画布内容宽 1780px → 应用内容宽 1368px,即 设计px × 0.77 ≈ CSS px;
// 小字号(设计 ≤12px)按可读下限 11px 不跟缩。下列色值均为设计稿取色实测。
@filter-selected-bg: #e7eeff; // 业务类型选中行底色(设计15 实取 rgba(231,238,255))
@pill-bg: #ededed; // 胶囊选项默认底色(设计04 实取 rgba(237,237,237))
@pill-selected-bg: #075cff; // 胶囊选项选中底色(设计04 实取 rgba(7,92,255))
@chips-panel-bg: #eaf1ff; // 「已选条件」区底色(设计04 实取 rgba(234,241,255))
@input-bg: #ededed; // 日期区间胶囊底色(设计04 实取 rgba(237,237,237))
@tag-hardware: #4caf50; // 业务标签:硬件电路(设计15 实取 #4CAF50)
@tag-iot: #5720ba; // 业务标签:物联网全案
@tag-manufacturing: #ff8f1f; // 业务标签:生产制造
@tag-other: #8a94a6; // 业务标签:其他
// 需求提报(按需求提报设计稿标注校准)
@demand-selected-bg: #dee8fc; // 业务类型卡片 / 预算胶囊选中底色
@demand-accent: #2563eb; // 业务类型选中描边与右上角圆点
@demand-secondary-bg: #e6e6e6; // 底部「保存草稿 / 重置」按钮底色
@cases-accent: #075cff; // 搜索/重置按钮、已选 chip 文字(设计04/08 实取 rgba(7,92,255))
@cases-confirm: #2563eb; // 底部「确定筛选」按钮底色(设计04 实取)
@cases-hero-title: #121212; // 「成功案例库」主标题(设计04 实取 18,18,18)
@cases-filter-title: #222222; // 「筛选条件」标题(设计04 实取 34,34,34)
@cases-text: #333333; // 筛选项 / 卡片正文(设计04 实取 51,51,51)
@cases-muted: #666666; // 次级文字:计数 / 页面标语(设计04 实取 102,102,102)
@cases-input-border: #999999; // 搜索框描边·占位文字 / 复选框描边(设计04 实取 153,153,153)
@cases-icon: #797979; // 搜索图标(设计04 实取 121,121,121)
@cases-reset-bg: #f0f0f0; // 底部「重置」按钮底色(设计04 实取 239.82→240)
@cases-card-border: #e1dfdf; // 案例卡片描边(设计04 实取 224.6,222.7,222.7)
@cases-card-shadow: 0 4px 10px rgba(0, 0, 0, 0.08); // 案例卡片常驻阴影(设计04 实取)
@cases-page-active-bg: #e0e9fa; // 分页当前页底色(设计15 实取 ≈ rgba(2,79,255,.12) 叠白)
// 需求提报(按需求提报设计稿 06/07 标注实测校准)
@demand-selected-bg: #024fff; // 业务类型卡片 / 预算胶囊选中底色(设计稿实取 rgba(2,79,255))
@demand-accent: #024fff; // 业务类型选中描边·右上圆点 / 步骤序号(设计稿强调色 #024FFF)
@demand-secondary-bg: #075cff; // 底部「保存草稿 / 重置 / 立即提报」按钮底色(设计稿实取 rgba(7,92,255))
// 项目中心(按项目中心设计稿标注校准)
@project-table-head-bg: #e8e8e8; // 表头底色(设计稿实取 (232,232,232))
@@ -79,11 +104,11 @@
// 项目详情(按 docs/prototype/项目中心-演示.html 设计稿校准)
// ⚠️ 换算系数:设计画布内容宽 1776px → 应用内容宽 1368px(.container 1400 − 2×16),
// 即 设计px × 0.77 ≈ CSS px。下列数值 = 设计稿实测值 × 0.77 后取整。
@project-accent: #2563eb; // 竖条 / 状态文字 / 进度条 / 激活页签 / 里程碑进行中(设计稿实取 rgba(37,99,235,1))
@project-track: #e8e8e8; // 进度条轨道(设计稿实取)
@milestone-done: #34c724; // 里程碑已完成圆点
@milestone-idle: #cecece; // 里程碑待开始圆环 + 连接线(设计稿实取)
@team-avatar-bg: #54bcbd; // 团队头像底色(设计稿实取)
@project-accent: #024fff; // 竖条 / 状态文字 / 进度条 / 激活页签 / 里程碑进行中(蓝湖设计稿实取 #024FFF)
@project-track: #edeff2; // 进度条轨道(蓝湖设计 13 实取 #EDEFF2)
@milestone-done: #22c55e; // 里程碑已完成圆点 + 已完成段连接线(蓝湖设计 13 实取 #22C55E)
@milestone-idle: #d6d9de; // 里程碑待开始圆环描边(蓝湖设计 13 实取)
@team-avatar-bg: #1f67ef; // 团队头像底色(蓝湖设计 13 实取 #1F67EF)
// 收银台 / 确认支付(按「支付」设计稿标注校准)
// ⚠️ 换算系数:设计稿 250px 宽 ≈ 375 视口(缩放 1.5×),下列数值 = 设计稿实测值 × 1.5 后取整。
@@ -102,13 +127,136 @@
// 项目详情 → 合同财务(付款计划卡 / 发票·合同文件行)
// 来源 docs/prototype/项目中心-演示.html 第 1 帧(与 @project-accent 同源,换算同为 设计px × 0.77)。
// ⚠️ 小字号例外:设计 12px/10px 折算后是 9/8px(不可读),按可读下限取 12/11px,不跟缩。
@finance-card-width: 508px; // 计划卡定宽(设计 660px),竖排左对齐
@finance-card-radius: 12px; // 计划卡圆角(设计 15px ≈ @radius-lg)
@finance-card-shadow: 0 0 2px rgba(0, 0, 0, 0.4); // 计划卡阴影(设计 0 0 3px rgba(0,0,0,.4)),设计稿无描边
@finance-meta-color: #6c6c6c; // 字段行「账单号:/ 关联项目:」(设计实取 (108,108,108))
@finance-row-bg: #f8fafc; // 发票/合同文件行底色(设计实取 (248,250,252),无描边无圆角)
@finance-paid: #22c55e; // 已支付:徽标实底 + 金额文字
@finance-pending: #f59e0b; // 待支付:徽标实底 + 「立即支付」按钮底色(设计实取)
@finance-pending-amount: #f6ab29; // 待支付:金额文字(设计实取,比徽标略暖)
@finance-idle: #9a9a9a; // 未到期:徽标实底 + 金额文字(设计实取)
@finance-card-width: 285px; // 计划卡定宽(蓝湖设计 09 实测 x70..440 = 370 设计px × 0.77),竖排左对齐
@finance-card-radius: 10px; // 计划卡圆角(蓝湖设计 09 实测 ≈13 设计px × 0.77)
@finance-meta-color: #6b7280; // 字段行「账单号:/ 关联项目:」(蓝湖设计 09 (107,114,128))
@finance-row-bg: #f7f8fa; // 项目文件行底色(蓝湖设计 09/10/11 实取 #F7F8FA)
@finance-paid: #16a34a; // 已支付:徽标文字 + 金额(蓝湖设计 09 (22,163,74))
@finance-pending: #f59e0b; // 待支付:「立即支付」按钮底色 + 金额(蓝湖设计 09 实取)
@finance-pending-amount: #f59e0b; // 待支付:金额文字(蓝湖设计 09 (245,158,11))
@finance-idle: #b3bfc4; // 未到期:金额文字(蓝湖设计 09 (179,185,196))
@finance-cta-hover: #e08d05; // 「立即支付」hover(与收银台 CTA 同色系)
// 首页 / 业务详情(蓝湖设计稿:03·05 首页,53 业务详情)
// ⚠️ 换算约定同上:设计px × 0.77 ≈ CSS px;设计 ≤12px 小字号按可读下限取 12/11px。
@home-ink: #121212; // 栏目标题 / 卡片标题 / 分类标签文字(设计实取 #121212)
@home-welcome: #2c2c2c; // 首页欢迎语与副文案(设计实取 #2C2C2C)
@home-body: #333333; // 详情页标题/标签、案例元信息(设计实取 #333333)
@home-paragraph: #222222; // 详情页富文本正文(设计实取 #222222)
@home-breadcrumb: #666666; // 详情页面包屑(设计实取 #666666)
@home-card-border: #ebebeb; // 首页仪表盘(欢迎卡/快捷入口卡)描边(设计实取)
@home-section-border: #e2e2e2; // 首页大区块卡(业务服务/案例库精选)描边(设计实取)
@home-case-border: #e0dede; // 案例卡片描边(设计实取 rgba(224,222,222))
@home-business-border: #999999; // 业务卡片未选中描边(设计实取 #999999)
@home-ring: #c6c2c2; // 业务卡片右上圆环·未选中 / 快捷入口「更多」箭头(设计实取)
@home-tab-active: #085dff; // 案例分类激活文字(设计实取 #085DFF,下划线仍用 @primary-color)
@home-banner-dot: #8d96ae; // 首页头图轮播指示条/点(设计实取 rgba(141,150,174))
@home-banner-bg: #f3f4f8; // 首页头图底色(设计实取,轮播无图时兜底)
@home-quick-blue: #a5d0ff; // 快捷入口·工单需求池(cyan,设计实取)
@home-quick-purple: #dbc9fe; // 快捷入口·案例库管理(purple,设计实取)
@home-quick-green: #c4f0be; // 快捷入口·客服工作台(green,设计实取)
@home-quick-peach: #ffcbbe; // 快捷入口·合同台账(blue tone,设计稿实取浅橙)
@home-quick-pink: #ffcadb; // 快捷入口·财务台账(amber tone,设计稿实取浅粉)
@home-detail-hero-bg: linear-gradient(115deg, #e2ebf7 0%, #cfe7fd 55%, #b6dfff 100%); // 业务详情头图底(设计实取采样渐变)
@home-detail-logo-bg: #d9e5ff; // 业务详情头像块底色(设计实取 rgba(217.8,229.4,255))
@home-service-web: #ae7eff; // 服务类型·Web应用 圆形底(设计实取)
@home-service-mp: #00b240; // 服务类型·小程序 圆形底(设计实取)
@home-service-app: #fd9a83; // 服务类型·APP 圆形底(设计实取)
@home-service-dev: #80e561; // 服务类型·二次开发 圆形底(设计实取)
@home-service-pc: #0081e3; // 服务类型·桌面工具 圆形底(设计实取)
// 需求提报 / 登录注册(蓝湖设计稿)
// 设计稿索引:06·07 需求提报,02·51 登录,54 注册,55 找回密码
// ⚠️ 换算约定同上:设计px × 0.77 ≈ CSS px;设计 ≤12px 小字号按可读下限取 11/12px。
@demand-ink: #121212; // 需求提报页主标题 / 卡片标题 / 输入值(设计实取 rgba(18,18,18))
@demand-heading: #333333; // 区块标题(01/02/03 旁)/ 表单标签 / 底部提示(设计实取 rgba(51,51,51))
@demand-subtitle: #666666; // 页面副标题「填写您的需求信息…」(设计实取 rgba(102,102,102))
@demand-line: #999999; // 输入框·胶囊·卡片描边 + 占位文案(设计实取 rgba(153,153,153))
@demand-upload-bg: #ededed; // 附件上传区 / 文件行底色(设计实取 rgba(236.8,236.8,236.8)≈#EDEDED)
@demand-radio-idle: #c7c2c2; // 业务类型未选中单选圈描边(设计实取 rgba(198.8,194.4,194.4))
@auth-gradient-from: #505be8; // 登录/注册左侧品牌渐变起点(设计实取采样)
@auth-gradient-to: #8b3fe8; // 登录/注册左侧品牌渐变终点(设计实取采样)
@auth-track: #edeff2; // 密码强度条轨道底色(设计实取 #EDEFF2)
// 项目中心(蓝湖设计稿)
// 蓝湖设计 09(合同财务)/10(售后信息)/11(项目文件)/12(申请售后)/13(项目进度)像素实取。
// 换算约定同上:设计px × 0.77 ≈ CSS px;设计 ≤12px 小字号按可读下限取 11/12px。
@project-divider: #f0f1f3; // 页签下分割线 / 计划卡描边 / 表单底栏分隔线(设计 (240,241,243))
@project-breadcrumb: #666666; // 详情页·申请售后页面包屑文字(设计 (102,102,102))
@project-logo-bg: #f2f4f6; // 详情头像方块「</>」底色(设计 09 实取 ≈#F1F3F5)
@project-banner-bg: #fdeeee; // 售后工单提示横幅底色(设计 10 实取 #FDEEEE)
@project-banner-title: #d93025; // 横幅标题红(设计 10 (217,48,37))
@project-apply: #e3464b; // 「申请售后」按钮底色(设计 10 实取 #E3464B)
@project-quiet-btn: #eef0f3; // 浅灰按钮底:上传文档 / 取消 / 重置(设计 10·12 实取)
@tag-success-bg: #e7f7ec; // 徽标底:已支付 / 成功(设计 09 实取)
@tag-warning-bg: #fef3e2; // 徽标底:待支付(设计 09 实取)
@tag-warning-text: #d97706; // 徽标字:待支付(设计 09 (217,119,6))
@tag-info-bg: #f3f4f6; // 徽标底:未支付 / 中性(设计 09 实取)
@milestone-line: #eeeff2; // 里程碑未完成连接线(设计 13 实取)
// 合同中心(蓝湖设计稿)
// 设计索引:41 顶部横幅+搜索栏,46/47 表格+分页,40/44/52 合同详情,45 面包屑,39 签署。
// ⚠️ 换算约定同上:设计px × 0.77 ≈ CSS px;设计 ≤12px 小字号按可读下限取 11px,不跟缩。
@contract-accent: #075cff; // 列表:搜索/重置按钮、当前页码、「详情」链接(设计 46 实取 rgb(7,92,255))
@contract-muted: #666666; // 面包屑 / 顶部横幅副标语 / 分页箭头(设计 45·46 实取 #666666)
@contract-head-text: #222222; // 表头文字(设计 46 实取 #222222)
@contract-cell-text: #333333; // 表格正文(设计 46 实取 #333333)
@contract-line: #999999; // 表格边框·行分隔线·分页描边与页码(设计 46 实取 #999999)
@contract-table-head-bg: #ededed; // 表头底色(设计 46 实取 (237,237,237))
@contract-placeholder: #b3b9c4; // 搜索框占位文字(设计 41 实取 (179,185,196))
@contract-reset-bg: #eef0f3; // 搜索行「重置」按钮底色(设计 41 实取)
@contract-qr-bg: #d6d6d6; // 签署页二维码占位底色(设计 39 实取 #D6D6D6)
// 财务中心(蓝湖设计稿)
// 设计索引:37 财务概览,30 账单明细,31 账单详情,33·34 扫码支付,32 支付结果,35·36 发票抬头。
// ⚠️ 换算约定:设计画布内容宽 1780 → 应用内容宽 1368(.container 1400 − 2×16),设计px × 0.77;
// 字号 = 设计px × 0.77,≤14 设计px 折算不足 11px 时按可读下限取 11px(15/16 → 12,18 → 14,20 → 15,22 → 17,26 → 20,34 → 26,38 → 29)。
// 复用同值既有 token:表格/卡片分隔线 @project-divider(#f0f1f3)、占位文字 @contract-placeholder(#b3b9c4)、
// 「重置」按钮底 @project-quiet-btn(#eef0f3)、二维码占位底 @contract-qr-bg(#d6d6d6)。
@finance-hero-gradient: linear-gradient(115deg, #024fff 0%, #4b4ff3 55%, #7e75ec 100%); // 概览「累计消费总额」卡渐变(设计 37 实取采样 #034FFF→#7E75EC)
@finance-chart-bar: #4a90c4; // 概览月度账单柱条(设计 37 实取采样)
@finance-chart-grid: #edeef2; // 概览图表网格线(设计 37 实取 rgba(237,239,242))
@finance-table-head-bg: #f1f3f5; // 账单表头底色(设计 30 实取)
@finance-field-bg: #f3f4f6; // 搜索框底色(设计 30 实取 #F3F4F6)
@finance-page-active: #d5e2fe; // 分页当前页底色(设计 30/35 实取 #C5D7FE/#D5E2FE)
@finance-summary-cta: #ffb754; // 底部汇总条「立即支付」按钮(设计 30 实取采样)
@finance-result-circle: #7ed321; // 支付结果大圆勾底色(设计 32 实取采样)
@finance-safe-bg: #d2eedc; // 扫码支付「已通过安全验证」横幅底(设计 33 实取采样)
// 消息中心 / 在线客服(蓝湖设计稿)
// 设计索引:43 消息中心列表,42 通知详情,38 在线客服聊天。
// ⚠️ 换算约定同上:设计px × 0.77 ≈ CSS px;设计 ≤14px 小字号按可读下限取 11px。
// 复用同值既有 token:行分割线/聊天卡描边 @project-divider(#f0f1f3)、灰字 #9ca3af=@text-color-disabled、
// 搜索框底 @finance-field-bg(#f3f4f6)、「重置」底 @contract-reset-bg(#eef0f3)、占位字 @contract-placeholder(#b3b9c4)、
// 附件/输入框底 #f7f8fa=@finance-row-bg、聊天消息区底 #fafbfc=@bg-color-light、未读徽标红=@danger-color、
// 强调蓝(搜索/返回/发送/气泡/头像)#024fff=@primary-strong、分页激活底 #e1eafa≈@cases-page-active-bg。
@message-icon-bg: #3b82f6; // 消息行类型图标圆底(设计 43 实取 #3B82F6)
@service-user-avatar: #8d99ae; // 客服聊天·右侧用户头像底(设计 38 实取 #8D99AE)
// 个人中心(蓝湖设计稿)
// 设计索引:14 布局+专属客服热线,28 账号安全列表,22~29 安全类弹窗,20 地址管理,17 资质列表,
// 18 意见反馈,16 帮助中心,19 关于我们。
// ⚠️ 换算约定同上:设计px × 0.77 ≈ CSS px;字号 = round(设计px × 0.77),≤14 设计px 按可读下限取 11px
// (11/12/13/14 → 11,15/16 → 12,19/20 → 15,24 → 18)。
// 复用同值既有 token:页面底 @bg-color、强调蓝 #024fff=@primary-strong、卡片描边 #f0f1f3≈@project-divider、
// 成功绿底徽标 #e7f7ec≈@tag-success-bg、次级按钮底 #eef0f3≈@project-quiet-btn、文字灰阶 @text-color* 系列。
@profile-nav-active-bg: #e7eeff; // 左侧菜单选中项底色(设计 28 实取 rgba(231,238,255))
@profile-card-border: #f0f1f3; // 列表卡 / 分组卡描边(设计 28 实取 (240,241,243))
@profile-line: #e5e7eb; // 按钮描边 / 分隔线(设计 28 注销按钮描边实取 (229,231,235))
@profile-input-border: #dde1e7; // 输入框描边(设计 22 实取 (221,225,231))
@profile-radius: 6px; // 输入框 / 小按钮 / 菜单选中项圆角(设计 8px × 0.77)
@profile-hotline-bg: #d6e4fb; // 专属客服热线卡底色(设计 14 实取 rgba(214,228,251))
@profile-icon-pwd: #c7d2fe; // 账号安全「修改密码」图标块底(设计 28 实取)
@profile-icon-phone: #fdebeb; // 账号安全「绑定手机」图标块底(设计 28 实取)
@profile-icon-email: #fee2e2; // 账号安全「绑定邮箱」图标块底(设计 28 实取)
@profile-user-from: #5459e8; // 用户卡渐变起点(设计 14 左上角实取)
@profile-user-to: #d2bdf3; // 用户卡渐变终点(设计 14 右下角实取)
@profile-user-avatar: #8976ed; // 用户卡头像圆底(设计 14 实取)
@profile-page-active-bg: #d1e0fe; // 分页当前页底色(设计 20 实取 #D1E0FE)
@profile-quiet-btn: #eef0f3; // 弹窗次级(取消)按钮底色(设计 24 实取 rgba(238,240,243))
// 合同中心(蓝湖设计稿)· 补充
@contract-ink: #121212; // 页面最深标题色(设计实取 #121212)
// 财务中心(蓝湖设计稿)· 补充
@finance-pay-bg: #f7f8f9; // 扫码支付页底色(设计实取 #f7f8f9)

View File

@@ -309,15 +309,15 @@ function clearChips(): void {
<style lang="less" scoped>
.case-filter {
flex-shrink: 0;
width: 300px;
padding: @spacing-lg 0 @spacing-base;
width: 397px; // 设计04 面板 516 × 0.77
padding: 12px 0 40px; // 顶 15 × 0.77 / 底 50 × 0.77
border-radius: @radius-base;
background: @white;
&__head,
&__group,
&__actions {
padding: 0 @spacing-base;
padding: 0 38px 0 27px; // 内容左 35 × 0.77 / 右 50 × 0.77
}
&__head {
@@ -325,13 +325,13 @@ function clearChips(): void {
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
font-size: 22px; // 设计 28 × 0.77
font-weight: 500;
color: @cases-filter-title;
}
&__link {
color: @primary-color;
color: @primary-strong;
font-size: @font-size-base;
&:hover {
@@ -343,25 +343,30 @@ function clearChips(): void {
margin-top: @spacing-lg;
}
// 标题 → 第一组(设计 11 × 0.77)
&__head + &__group {
margin-top: 9px;
}
&__group-title {
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
font-size: 18px; // 设计 24 × 0.77
font-weight: 500;
color: @cases-text;
}
/* 业务类型:整行可点,选中整行铺满底色 */
&__rows {
margin-top: @spacing-sm;
margin-top: 14px; // 设计 19 × 0.77
}
&__row {
.flex(row, flex-start, center);
gap: @spacing-sm;
gap: 9px; // 设计 12 × 0.77
width: 100%;
height: 36px;
padding: 0 @spacing-base;
color: @text-color;
font-size: @font-size-base;
height: 38px; // 行距 50 × 0.77
padding: 0;
color: @cases-text;
font-size: 15px; // 设计 20 × 0.77
text-align: left;
transition: background 0.2s;
@@ -371,7 +376,7 @@ function clearChips(): void {
&.is-active {
background: @filter-selected-bg;
color: @primary-color;
color: @primary-strong;
font-weight: 600;
}
}
@@ -379,22 +384,22 @@ function clearChips(): void {
&__box {
position: relative;
flex-shrink: 0;
width: 14px;
height: 14px;
border: 1px solid @border-color-dark;
width: 12px; // 设计 16 × 0.77
height: 12px;
border: 1px solid @cases-input-border;
border-radius: 2px;
.case-filter__row.is-active & {
border-color: @primary-color;
background: @primary-color;
border-color: @primary-strong;
background: @primary-strong;
&::after {
content: '';
position: absolute;
top: 1px;
left: 4px;
left: 3px;
width: 4px;
height: 7px;
height: 6px;
border: solid @white;
border-width: 0 1.5px 1.5px 0;
transform: rotate(45deg);
@@ -408,51 +413,55 @@ function clearChips(): void {
}
&__row-count {
color: @text-color-secondary;
color: @cases-muted;
font-weight: 400;
}
// 选中行的计数随行文字变蓝、加粗(设计15)
.case-filter__row.is-active &__row-count {
color: inherit;
font-weight: inherit;
}
/* 胶囊选项(两列;minmax(0,1fr) 防止内部长内容(日期区间)把列撑宽) */
&__pills {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: @spacing-sm;
margin-top: @spacing-sm;
gap: 18px 25px; // 行距 24 × 0.77 / 列距 33 × 0.77
margin-top: 15px; // 设计 21 × 0.77
}
&__pill {
height: 34px;
height: 41px; // 设计 53 × 0.77
padding: 0 @spacing-sm;
border-radius: @radius-round;
border-radius: @radius-base;
background: @pill-bg;
color: @text-color;
font-size: @font-size-base;
color: @cases-text;
font-size: 15px; // 设计 20 × 0.77
.ellipsis();
transition: all 0.2s;
&:hover {
color: @primary-color;
}
&.is-active {
background: @primary-color;
color: @white;
color: @primary-strong;
}
&.is-active,
&.is-light {
background: @pill-selected-bg;
color: @primary-color;
font-weight: 600;
color: @white;
font-weight: 500;
}
}
&__date {
grid-column: 1 / -1;
display: flex;
justify-content: center;
width: 100%;
min-width: 0;
height: 34px;
height: 41px;
padding: 0 @spacing-sm;
border-radius: @radius-round;
border-radius: @radius-base;
background: @input-bg;
box-shadow: none;
@@ -471,18 +480,18 @@ function clearChips(): void {
flex: 0 1 auto;
width: 76px;
background: transparent;
color: @text-color;
font-size: @font-size-sm;
color: @cases-text;
font-size: 15px;
&::placeholder {
color: @text-color-secondary;
color: @cases-text;
}
}
:deep(.el-range-separator) {
color: @text-color-secondary;
font-size: @font-size-sm;
line-height: 34px;
color: @cases-text;
font-size: 15px;
line-height: 41px;
}
&.is-focus {
@@ -492,8 +501,8 @@ function clearChips(): void {
/* 已选条件 */
&__selected {
margin-top: @spacing-lg;
padding: @spacing-base;
margin: 18px 38px 0 27px; // 上距 23 × 0.77,左右与内容对齐(50/35 × 0.77)
padding: 12px 18px 16px; // 设计 16/24/21 × 0.77
border-radius: @radius-base;
background: @chips-panel-bg;
}
@@ -503,31 +512,32 @@ function clearChips(): void {
}
&__selected-title {
color: @primary-color;
font-size: @font-size-base;
font-weight: 600;
color: @cases-text;
font-size: 15px; // 设计 20 × 0.77
font-weight: 500;
}
&__selected-empty {
margin-top: @spacing-sm;
color: @text-color-secondary;
color: @cases-muted;
font-size: @font-size-sm;
}
&__chips {
.flex(row, flex-start, center);
flex-wrap: wrap;
gap: @spacing-sm;
margin-top: @spacing-sm;
gap: 11px 10px; // 行距 14 × 0.77 / 列距 13 × 0.77
margin-top: 12px; // 设计 16 × 0.77
}
&__chip {
height: 26px;
height: 25px; // 设计 32 × 0.77
padding: 0 @spacing-sm;
border-radius: @radius-round;
background: @white;
color: @primary-color;
font-size: @font-size-sm;
color: @cases-accent;
font-size: 11px; // 设计 14 → 10.8,取可读下限 11
font-weight: 500;
transition: color 0.2s;
&:hover {
@@ -538,36 +548,37 @@ function clearChips(): void {
/* 底部操作 */
&__actions {
.flex(row, flex-start, center);
gap: @spacing-sm;
margin-top: @spacing-base;
gap: 10px; // 设计 13 × 0.77
margin-top: 23px; // 设计 30 × 0.77
}
&__reset {
width: 88px;
height: 36px;
width: 104px; // 设计 135 × 0.77
height: 23px; // 设计 30 × 0.77
border-radius: @radius-round;
background: @pill-bg;
color: @text-color;
font-size: @font-size-base;
transition: color 0.2s;
background: @cases-reset-bg;
color: @black;
font-size: 11px; // 设计 14 → 10.8,取可读下限 11
font-weight: 400;
transition: filter 0.2s;
&:hover {
color: @primary-color;
filter: brightness(0.96);
}
}
&__confirm {
flex: 1;
height: 36px;
height: 23px;
border-radius: @radius-round;
background: @primary-color;
background: @cases-confirm;
color: @white;
font-size: @font-size-base;
font-weight: 600;
font-size: 11px;
font-weight: 400;
transition: background 0.2s;
&:hover {
background: @primary-hover;
background: @cases-accent;
}
}
}

View File

@@ -41,16 +41,16 @@ const emit = defineEmits<{
<style lang="less" scoped>
.cases-grid {
&__total {
font-size: 24px;
font-weight: 600;
font-size: 15px; // 设计15 计数 20 × 0.77
font-weight: 700;
color: @heading-color;
}
&__list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: @spacing-base;
margin-top: @spacing-base;
gap: 18px 22px; // 设计04 行距 23 / 列距 28 × 0.77
margin-top: 12px; // 设计15 计数 → 卡片 15 × 0.77
}
&__empty {

View File

@@ -60,65 +60,68 @@ const keyword = computed<string>({
<style lang="less" scoped>
.case-search {
.flex(row, flex-start, center);
gap: @spacing-sm;
padding: @spacing-base @spacing-lg;
gap: 18px; // 按钮间距 24 × 0.77
padding: 30px 36px; // 卡片 128 高、输入 49 高:上下 40 × 0.77 / 左右 47 × 0.77
border-radius: @radius-base;
background: @white;
&__field {
position: relative;
flex: 1;
max-width: 520px;
max-width: 456px; // 设计输入框 592 × 0.77
margin-right: 28px; // 与按钮总间距 60 × 0.77(叠加 bar gap 18)
}
&__icon {
position: absolute;
top: 50%;
left: 12px;
width: 16px;
height: 16px;
right: 16px; // 设计放大镜在输入框右侧
left: auto;
width: 20px; // 设计 27 × 0.77
height: 20px;
transform: translateY(-50%);
fill: none;
stroke: @text-color-secondary;
stroke: @cases-icon;
stroke-width: 1.8;
}
&__input {
width: 100%;
height: 36px;
padding: 0 @spacing-base 0 36px;
border: 1px solid transparent;
border-radius: @radius-base;
background: @input-bg;
color: @text-color;
font-size: @font-size-base;
height: 38px; // 设计 49 × 0.77
padding: 0 44px 0 16px;
border: 1px solid @cases-input-border;
border-radius: @radius-sm;
background: @white;
color: @cases-text;
font-size: 15px; // 设计 20 × 0.77
outline: none;
transition: border-color 0.2s;
&::placeholder {
color: @text-color-secondary;
color: @cases-input-border; // 设计占位 @cases-input-border
}
&:focus {
border-color: @primary-color;
border-color: @cases-accent;
}
}
&__btn {
height: 36px;
padding: 0 @spacing-lg;
border-radius: @radius-base;
background: @pill-bg;
color: @text-color;
font-size: @font-size-base;
min-width: 77px; // 设计 100 × 0.77
height: 38px; // 设计 49 × 0.77
padding: 0 @spacing-base;
border-radius: @radius-sm;
background: @cases-accent; // 设计 重置/搜索 均为 rgba(7,92,255)
color: @white;
font-size: 15px; // 设计 20 × 0.77
transition: all 0.2s;
&:hover {
color: @primary-color;
background: @primary-hover;
}
&--primary {
background: @primary-color;
background: @cases-accent;
color: @white;
&:hover {

View File

@@ -111,23 +111,24 @@ onMounted(() => {
<style lang="less" scoped>
.cases {
padding-bottom: @spacing-xxl;
padding-bottom: 60px; // 设计04 正文 → 页脚 78 × 0.77
&__hero {
padding: @spacing-lg 0;
padding: 25px 0 33px; // 标题上 32 / 标语下 43 × 0.77
background: @white;
}
&__title {
font-size: @font-size-xxl;
font-weight: 600;
color: @heading-color;
font-size: @font-size-xxl; // 设计 36 × 0.77 ≈ 28
font-weight: 700;
color: @cases-hero-title;
}
&__slogan {
margin-top: @spacing-xs;
font-size: @font-size-base;
color: @text-color-secondary;
margin-top: 12px; // 设计 15 × 0.77
font-size: 18.5px; // 设计 24 × 0.77
font-weight: 500;
color: @cases-muted;
}
&__body {
@@ -139,7 +140,7 @@ onMounted(() => {
&__main {
.flex(column, flex-start);
flex: 1;
gap: @spacing-base;
gap: 18px; // 设计04 搜索卡 → 卡片网格 23 × 0.77
min-width: 0;
}

View File

@@ -63,17 +63,17 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
关联项目
</h3>
<div class="contract-info__related-body">
<div class="contract-info__field">
<span class="contract-info__label text-secondary">
项目名称
<button class="contract-info__link" @click="emit('viewProject')">查看详情</button>
</span>
<span class="contract-info__value">{{ contract.relatedProjectName }}</span>
</div>
<div class="contract-info__field">
<span class="contract-info__label text-secondary">项目编号</span>
<span class="contract-info__value">{{ contract.projectNo }}</span>
</div>
<div class="contract-info__field">
<span class="contract-info__label text-secondary">项目名称</span>
<span class="contract-info__value">{{ contract.relatedProjectName }}</span>
</div>
<button class="contract-info__link" @click="emit('viewProject')">
查看详情
</button>
</div>
</div>
@@ -112,60 +112,90 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
</template>
<style lang="less" scoped>
// 合同详情信息区(设计 40:灰底页面直排、标签 + 灰底值框、蓝竖条区块标题)
.contract-info {
.flex(column, flex-start);
gap: @spacing-lg;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
.flex(column, flex-start, stretch);
gap: 24px;
&__grid {
&__grid,
&__related-body {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: @spacing-base @spacing-xl;
column-gap: 46px; // 列间距 60 设计 × 0.77
row-gap: 15px; // 行间距 20 设计 × 0.77
}
&__field {
.flex(row, flex-start, center);
gap: @spacing-sm;
.flex(column, flex-start, stretch);
gap: 6px; // 标签 → 值框(设计 8 × 0.77)
min-width: 0;
}
&__label {
flex-shrink: 0;
width: 70px;
font-size: @font-size-sm;
font-size: 11px; // 设计 13 → 可读下限
font-weight: 500;
line-height: 1.4;
color: @heading-color; // 设计 @heading-color(覆盖 .text-secondary)
}
// 值框:设计 40 实取 #F3F4F6 底 + 浅描边,高 38 设计 × 0.77
&__value {
font-size: @font-size-base;
color: @heading-color;
width: 100%;
height: 29px;
padding: 0 10px;
border: 1px solid @border-color;
border-radius: @radius-sm;
background: @input-bg;
font-size: 11px;
line-height: 27px;
color: @text-color; // 设计 @text-color
.ellipsis();
}
// 合同状态(StatusTag)同样入灰底值框,去彩色胶囊
&__field :deep(.status-tag) {
width: 100%;
height: 29px;
padding: 0 10px;
border: 1px solid @border-color;
border-radius: @radius-sm;
background: @input-bg;
font-size: 11px;
line-height: 27px;
color: @text-color;
}
// 区块标题:蓝色竖条(设计 40 实取 4×17 设计px #024FFF)+ 15 设计px 半粗
&__section-title {
margin-bottom: @spacing-base;
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 10px;
margin-bottom: 14px; // 设计 18 × 0.77
font-size: @font-size-sm; // 12px = 设计 15 × 0.77
font-weight: 700;
line-height: 16px;
color: @heading-color;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
width: 4px;
height: 15px;
border-radius: @radius-round;
background: @primary-strong;
transform: translateY(-50%);
}
}
&__related,
&__files-section {
padding-top: @spacing-base;
border-top: 1px solid @border-color;
}
&__related-body {
.flex(row, flex-start, center);
flex-wrap: wrap;
gap: @spacing-base;
margin-top: 6px; // 区块间距合计 30(设计 40 × 0.77)
}
&__link {
font-size: @font-size-base;
color: @primary-color;
font-size: 11px; // 设计 10 → 可读下限
font-weight: 500;
color: @primary-strong;
transition: opacity 0.2s;
&:hover {
@@ -173,34 +203,44 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
}
}
// 设计 40:「项目名称 查看详情」同一行内联
&__label &__link {
margin-left: 3px;
}
&__files {
.flex(column, flex-start);
.flex(column, flex-start, stretch);
gap: @spacing-sm;
}
// 文件行:设计 40 浅灰通栏底(#F7F8FA),无描边
&__file {
.flex(row, space-between);
gap: @spacing-base;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
min-height: 42px; // 通栏高 54 设计 × 0.77
padding: 7px 16px;
border: none;
border-radius: @radius-base;
background: @bg-color-light;
background: @finance-row-bg;
}
&__file-info {
.flex(column, flex-start);
.flex(column, flex-start, stretch);
gap: 2px;
min-width: 0;
}
&__file-name {
font-size: @font-size-base;
color: @heading-color;
font-size: 11px;
line-height: 1.3;
color: @heading-color; // 设计 @heading-color
.ellipsis();
}
&__file-meta {
font-size: @font-size-sm;
font-size: 11px; // 设计 11 → 可读下限
line-height: 1.3;
color: @text-color-disabled; // 设计 @text-color-disabled
}
&__file-actions {

View File

@@ -23,20 +23,20 @@ const emit = defineEmits<{ refresh: [] }>()
</template>
<style lang="less" scoped>
// 签署卡(设计 39:白底圆角卡、二维码直接置于卡面、右侧四步指引)
.sign-panel {
.flex(row, flex-start, stretch);
gap: @spacing-lg;
padding: @spacing-xl;
.flex(row, flex-start, flex-start);
gap: 48px; // 二维码区 → 步骤区(设计 63 × 0.77)
padding: 28px 32px; // 卡内边距(设计 37/40 × 0.77)
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
&__left {
.flex(row, center);
flex-shrink: 0;
padding: @spacing-lg;
border-radius: @radius-base;
background: @bg-color-light;
padding: 0;
background: transparent;
border-radius: 0;
}
&__right {

View File

@@ -81,32 +81,44 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
<style lang="less" scoped>
.contract-table {
overflow-x: auto;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
.scrollbar();
// 表格本体(设计 46:外框 1px #999、灰表头、横分隔线、无竖线、无卡面——卡面在页面层)
&__grid {
width: 100%;
border: 1px solid @contract-line;
border-collapse: collapse;
font-size: @font-size-base;
table-layout: fixed;
font-size: 15px; // 设计 20 × 0.77
th,
td {
padding: @spacing-base;
text-align: left;
border-bottom: 1px solid @border-color;
padding: 8px 10px;
border-bottom: 1px solid @contract-line;
vertical-align: middle;
white-space: nowrap;
font-size: 15px; // 设计 20 × 0.77
}
// 长名称列按设计稿换行显示(设计首行双行文本)
td.contract-table__name {
white-space: normal;
word-break: break-all;
}
th {
background: @bg-color-light;
color: @heading-color;
font-weight: 600;
height: 49px; // 设计 64 × 0.77
padding-top: 0;
padding-bottom: 0;
background: @contract-table-head-bg;
color: @contract-head-text;
font-weight: 400; // 设计 400
text-align: center; // 表头居中(设计实测)
}
td {
color: @text-color;
height: 75px; // 行高 97 设计 × 0.77
color: @contract-cell-text;
}
tbody tr:last-child td {
@@ -116,12 +128,23 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
tbody tr:hover td {
background: @bg-color-light;
}
// 列宽按设计稿栅格比例微调(10 列合计 100%,日期/编号列留足 nowrap 宽度)
th:nth-child(1) { width: 11%; }
th:nth-child(2) { width: 9%; }
th:nth-child(3) { width: 10%; }
th:nth-child(4) { width: 9%; }
th:nth-child(5) { width: 10%; }
th:nth-child(6) { width: 11%; }
th:nth-child(7) { width: 7%; }
th:nth-child(8) { width: 11%; }
th:nth-child(9) { width: 11%; }
th:nth-child(10) { width: 11%; }
}
// 长名称列继承正文灰(设计 46 单元格统一 #333333)
&__name {
max-width: 200px;
color: @heading-color;
.ellipsis();
color: @contract-cell-text;
}
&__actions {
@@ -130,8 +153,8 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
}
&__btn {
font-size: @font-size-base;
color: @primary-color;
font-size: 13px;
color: @contract-accent;
transition: opacity 0.2s;
&:hover {
@@ -143,16 +166,25 @@ const SIGN_VARIANTS: Record<SignStatus, 'primary' | 'success' | 'warning' | 'dan
padding: 0 @spacing-sm;
border: none;
border-radius: @radius-sm;
background: @primary-color;
background: @contract-accent;
color: @white;
&:hover {
background: @primary-hover;
background: @primary-color;
opacity: 1;
}
}
}
// 设计 46 状态列为纯文字,不使用彩色胶囊
:deep(.status-tag) {
padding: 0;
border-radius: 0;
background: transparent;
color: inherit;
font-size: inherit;
}
&__empty {
padding: @spacing-xl 0;
text-align: center;

View File

@@ -36,41 +36,45 @@ const steps = [
</template>
<style lang="less" scoped>
// 四步签署指引(设计 39:小蓝圆序号 + 14/12 设计px 标题与说明,步距 63 设计px)
.sign-steps {
.flex(column, flex-start);
gap: @spacing-lg;
.flex(column, flex-start, stretch);
gap: 17px; // 步骤间距(设计 22 × 0.77)
&__item {
.flex(row, flex-start);
gap: @spacing-base;
.flex(row, flex-start, flex-start);
gap: 11px; // 序号 → 文字(设计 14 × 0.77)
}
&__index {
.flex(row, center);
flex-shrink: 0;
width: 32px;
height: 32px;
width: 16px; // 序号圆(设计 21 × 0.77)
height: 16px;
border-radius: @radius-round;
background: @primary-light;
color: @primary-color;
font-size: @font-size-base;
font-weight: 600;
background: @primary-strong;
color: @white;
font-size: 11px; // 设计 12 → 可读下限
font-weight: 700;
line-height: 1;
}
&__body {
.flex(column, flex-start);
gap: @spacing-xs;
.flex(column, flex-start, stretch);
gap: 5px; // 标题 → 说明(设计 6 × 0.77)
min-width: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
font-size: 11px; // 设计 14 → 可读下限
font-weight: 700;
line-height: 1.4;
color: @heading-color;
}
&__desc {
font-size: @font-size-base;
line-height: 1.6;
font-size: 11px; // 设计 12 → 可读下限
line-height: 1.5;
}
}
</style>

View File

@@ -46,6 +46,7 @@ onMounted(load)
<template>
<div class="contract-detail">
<div class="container">
<nav class="contract-detail__breadcrumb text-secondary">
<RouterLink to="/contract" class="link">
合同中心
@@ -72,21 +73,47 @@ onMounted(load)
</AppButton>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.contract-detail {
.flex(column, flex-start);
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
// 内容列(面包屑 → 信息卡 → 返回):区块间距 24(设计 26~30 × 0.77)
.container {
.flex(column, flex-start, stretch);
gap: @spacing-lg;
}
// 面包屑(设计 45:24 设计px × 0.77、#666666、字重 500)
&__breadcrumb {
font-size: @font-size-base;
font-size: 18px;
font-weight: 500;
color: @contract-muted;
}
&__footer {
.flex(row, flex-start);
.flex(row, flex-end);
width: 100%;
// 「返回」按钮(设计 40/39:#024FFF 实底、白字、小圆角)
:deep(.app-button) {
height: 30px;
padding: 0 24px; // 按钮宽约 90 设计 × 0.77
border: none;
border-radius: @radius-sm;
background: @primary-strong;
color: @white;
font-size: 11px; // 设计 13 → 可读下限
}
:deep(.app-button:hover) {
border-color: transparent;
background: @primary-color;
color: @white;
}
}
&__empty {

View File

@@ -43,15 +43,21 @@ onMounted(() => {
<template>
<div class="contract">
<header class="contract__head">
<!-- 顶部横幅:白底通栏 + 标题/副标语(设计 41 横幅区、46 标题规格) -->
<div class="contract__head">
<div class="container">
<h1 class="contract__title">
合同中心
</h1>
<p class="contract__slogan text-secondary">
项目电子合同在线签署、归档与查询管理
</p>
</header>
</div>
</div>
<div class="container">
<!-- 内容白卡:搜索行 + 表格 + 分页(设计 46/47 卡片) -->
<div class="contract__card">
<FilterPanel
v-model:keyword="keyword"
keyword-placeholder="合同名称/合同编号搜索"
@@ -72,24 +78,159 @@ onMounted(() => {
@page-change="onPageChange"
/>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.contract {
.flex(column, flex-start);
gap: @spacing-base;
padding-top: @spacing-xl;
padding-bottom: @spacing-xxl;
// 横幅:设计 41/46 实测 y72..251(179 设计px → 138 CSS)白底通栏
&__head {
padding: 25px 0 33px;
background: @white;
// 标题/副标语相对内容区左缩进 42 设计px × 0.77 ≈ 32(容器自带 16)
.container {
padding-left: 48px;
}
}
&__title {
font-size: @font-size-xxl;
font-weight: 600;
color: @heading-color;
font-size: @font-size-xxl; // 28px = 设计 36 × 0.77
font-weight: 700;
line-height: 1.4;
color: @home-ink; // 复用同值 token(横幅标题设计实取 @contract-ink)
}
&__slogan {
margin-top: @spacing-xs;
font-size: @font-size-base;
margin-top: 12px; // 设计 15 × 0.77
font-size: 18px; // 设计 24 × 0.77
font-weight: 500;
line-height: 1.5;
color: @contract-muted;
}
}
// 内容白卡(设计 46:x70..1850 圆角白卡,无阴影)——显式 .contract 前缀抬高覆写优先级
.contract .contract__card {
margin-top: 15px; // 横幅底 → 卡片顶:设计 20 × 0.77
padding: 40px 48px 44px; // 卡片内缩:设计 51/64/59 × 0.77
border-radius: @radius-lg;
background: @white;
// 搜索行并入卡片:去掉 FilterPanel 自带的卡面,按设计 41 重排控件
:deep(.filter-panel) {
margin-bottom: 30px; // 搜索行 → 表格:设计 39 × 0.77
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
:deep(.filter-panel__body) {
margin-top: 0;
}
:deep(.filter-panel__bar) {
gap: 6px;
}
:deep(.filter-panel__input) {
flex: 1;
width: auto;
height: 30px; // 设计 38 × 0.77
border-color: transparent;
background: @input-bg;
font-size: 11px; // 设计 13 → 可读下限
}
:deep(.filter-panel__input::placeholder) {
color: @contract-placeholder;
}
:deep(.filter-panel__input:focus) {
border-color: @primary-strong;
}
// 设计 41 按钮序为「重置 | 搜索」,组件内 DOM 序相反,用 order 对齐
:deep(.filter-panel__btn) {
order: 1;
height: 30px;
padding: 0 16px;
border: none;
background: @contract-reset-bg;
color: @text-color;
font-size: 11px; // 设计 12 → 可读下限
}
:deep(.filter-panel__btn:hover) {
border-color: transparent;
color: @text-color;
}
:deep(.filter-panel__btn--primary) {
order: 2;
background: @primary-strong;
color: @white;
}
:deep(.filter-panel__btn--primary:hover) {
background: @primary-color;
color: @white;
}
// 分页(设计 46:右对齐、方角小页码、当前页实底蓝)
:deep(.pagination) {
justify-content: flex-end;
gap: 8px; // 设计 10 × 0.77
padding: 0;
margin-top: 22px; // 表格底 → 分页:设计 28 × 0.77
}
:deep(.pagination__btn) {
min-width: 31px; // 设计 40 × 0.77
height: 20px; // 设计 26 × 0.77
padding: 0 4px;
border: 1px solid @contract-line;
border-radius: 0;
background: @white;
color: @contract-line;
font-size: 11px; // 设计 14 → 可读下限
}
:deep(.pagination__btn:hover:not(:disabled):not(.is-ellipsis)) {
border-color: @contract-accent;
color: @contract-accent;
}
:deep(.pagination__btn.is-active) {
border-color: @contract-accent;
background: @contract-accent;
color: @white;
}
:deep(.pagination__btn.is-ellipsis) {
border-color: transparent;
background: transparent;
color: @contract-muted;
}
// 首尾「上一页/下一页」:设计为无框纯文字
:deep(.pagination__btn:first-child),
:deep(.pagination__btn:last-child) {
min-width: auto;
padding: 0 2px;
border: none;
background: transparent;
color: @contract-muted;
font-size: 12px;
}
:deep(.pagination__btn:first-child:disabled),
:deep(.pagination__btn:last-child:disabled) {
opacity: 1;
}
}
</style>

View File

@@ -35,6 +35,7 @@ onMounted(load)
<template>
<div class="contract-sign">
<div class="container">
<nav class="contract-sign__breadcrumb text-secondary">
<RouterLink to="/contract" class="link">
合同中心
@@ -58,21 +59,52 @@ onMounted(load)
</AppButton>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.contract-sign {
.flex(column, flex-start);
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
// 内容列(面包屑 → 签署卡 → 返回):面包屑 → 卡片 12(设计 16 × 0.77)
.container {
.flex(column, flex-start, stretch);
gap: 12px;
}
// 面包屑(设计 39:12 设计px → 可读下限 11、#9CA3AF,当前项 #4B5563 加粗)
&__breadcrumb {
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
font-weight: 500;
}
}
&__footer {
.flex(row, flex-start);
.flex(row, flex-end);
width: 100%;
margin-top: 19px; // 卡片底 → 按钮:设计 40 × 0.77(另计容器 12)
// 「返回」按钮(设计 39:#024FFF 实底、白字、小圆角)
:deep(.app-button) {
height: 30px;
padding: 0 24px; // 按钮宽约 98 设计 × 0.77
border: none;
border-radius: @radius-sm;
background: @primary-strong;
color: @white;
font-size: 11px; // 设计 13 → 可读下限
}
:deep(.app-button:hover) {
border-color: transparent;
background: @primary-color;
color: @white;
}
}
}
</style>

View File

@@ -64,15 +64,19 @@ const emit = defineEmits<{
&__inner {
.flex(row, space-between, center);
height: 72px;
// 覆盖 .container 内缩:左 = 容器16 + 卡左内边距49 + 序号列46 = 111(对齐内容列),右 = 16 + 40
gap: @spacing-base;
padding-left: 111px;
padding-right: 56px;
}
&__tip {
.flex(row, flex-start, center);
gap: @spacing-sm;
min-width: 0;
font-size: @font-size-base;
color: @text-color;
font-size: 15px;
font-weight: 500;
color: @demand-heading;
}
&__info {
@@ -80,28 +84,32 @@ const emit = defineEmits<{
flex-shrink: 0;
width: 16px;
height: 16px;
border: 1px solid @primary-color;
border: 1px solid @demand-accent;
border-radius: 50%;
font-size: 11px;
font-style: normal;
font-weight: 600;
color: @primary-color;
color: @demand-accent;
}
&__actions {
.flex(row, flex-end, center);
gap: @spacing-base;
// 设计稿按钮 232×63 设计px ≈ 179×48,间距 47 设计px ≈ 36px
gap: 36px;
flex-shrink: 0;
}
// 设计稿三个按钮均为实底蓝 #075CFF + 白字
&__btn {
height: 36px;
padding: 0 @spacing-lg;
width: 179px;
height: 48px;
padding: 0;
border: none;
border-radius: @radius-round;
border-radius: @radius-base;
background: @demand-secondary-bg;
font-size: @font-size-base;
color: @heading-color;
font-size: 15px;
font-weight: 500;
color: @white;
cursor: pointer;
transition: background 0.2s, opacity 0.2s;
@@ -115,13 +123,13 @@ const emit = defineEmits<{
}
&--primary {
// 设计稿按钮宽度(247px @1400 版面)由 min-width 兜住,短文案也不塌
min-width: 240px;
background: @primary-color;
// 设计稿三个按钮等宽(232 设计px ≈ 179px),主按钮不额外加宽
min-width: 179px;
background: @demand-secondary-bg;
color: @white;
&:hover:not(:disabled) {
background: @primary-hover;
background: darken(@demand-secondary-bg, 6%);
}
}
}

View File

@@ -208,41 +208,41 @@ function onDownload(file: DemandAttachment): void {
<style lang="less" scoped>
.demand-attach {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
gap: 11px;
&__head {
.flex(row, flex-start, center);
gap: @spacing-sm;
gap: 15px;
}
&__label {
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
font-size: 15px;
font-weight: 500;
color: @demand-heading;
}
&__hint {
flex: 1;
min-width: 0;
font-size: @font-size-sm;
color: @text-color-secondary;
color: @demand-line;
}
&__pick {
flex-shrink: 0;
height: 28px;
padding: 0 @spacing-base;
border: 1px solid @border-color-dark;
border: 1px solid @demand-line;
border-radius: @radius-sm;
background: @white;
font-size: @font-size-sm;
color: @text-color;
color: @demand-line;
cursor: pointer;
transition: border-color 0.2s, color 0.2s;
&:hover:not(:disabled) {
border-color: @primary-color;
color: @primary-color;
border-color: @demand-accent;
color: @demand-accent;
}
&:disabled {
@@ -257,18 +257,21 @@ function onDownload(file: DemandAttachment): void {
&__list {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
// 设计稿:两条 90 设计px 灰条,间距 20 设计px ≈ 15px
gap: 15px;
margin: 0;
padding: 0;
list-style: none;
}
// 设计稿附件条:实底 #EDEDED、无描边、90 设计px ≈ 69px 高
&__item {
.flex(row, flex-start, center);
gap: @spacing-sm;
padding: @spacing-sm @spacing-base;
gap: @spacing-base;
min-height: 69px;
padding: @spacing-base;
border-radius: @radius-sm;
background: @bg-color-light;
background: @demand-upload-bg;
}
&__badge {
@@ -290,8 +293,8 @@ function onDownload(file: DemandAttachment): void {
}
&__name {
font-size: @font-size-base;
color: @heading-color;
font-size: 15px;
color: @demand-ink;
.ellipsis();
}

View File

@@ -57,19 +57,19 @@ const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
}
&__grid {
// auto-fill(不是 auto-fit):条目不足 5 个时保留空轨道,卡片尺寸与设计稿一致(约 251px),
// auto-fill(不是 auto-fit):条目不足 5 个时保留空轨道,卡片尺寸与设计稿一致(303 设计px ≈ 233px),
// 不会被拉伸变形;满 5 个时正好落在设计稿的 5 列上。
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: @spacing-base;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 14px;
}
&__card {
position: relative;
.flex(column, flex-start, stretch);
gap: @spacing-xs;
padding: @spacing-base;
border: 1px solid @border-color;
gap: 2px;
padding: 12px 12px 8px;
border: 1px solid @demand-line;
border-radius: @radius-base;
background: @white;
text-align: left;
@@ -80,53 +80,61 @@ const emit = defineEmits<{ 'update:modelValue': [value: string] }>()
border-color: @demand-accent;
}
// 选中:整卡蓝底(设计稿实取 #024FFF),文字反白
&.is-active {
border-color: @demand-accent;
border-color: @demand-selected-bg;
background: @demand-selected-bg;
}
}
/** 右上角选中标记:未选为空心圈,选中为实心蓝点 */
/** 右上角选中标记(设计稿 30 设计px ≈ 23px):未选空心圈,选中为白环 + 蓝缝 + 白点 */
&__check {
position: absolute;
top: 12px;
right: 12px;
width: 16px;
height: 16px;
border: 1px solid @border-color-dark;
top: 22px;
right: 19px;
width: 23px;
height: 23px;
border: 1px solid @demand-radio-idle;
border-radius: 50%;
background: @white;
transition: background 0.2s, border-color 0.2s, box-shadow 0.2s;
transition: border-color 0.2s, box-shadow 0.2s;
}
&__card.is-active &__check {
border-color: @demand-accent;
background: @demand-accent;
border-color: @white;
background: @white;
box-shadow: inset 0 0 0 3px @demand-selected-bg;
}
&__icon {
margin-bottom: @spacing-xs;
margin-bottom: 25px;
}
/** 后端 Logo:与内联 SVG 同尺寸,保证两种来源视觉一致 */
&__logo {
width: 40px;
height: 40px;
margin-bottom: @spacing-xs;
margin-bottom: 25px;
object-fit: contain;
}
&__name {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
font-size: @font-size-title;
font-weight: 500;
color: @demand-ink;
}
&__desc {
font-size: @font-size-sm;
color: @text-color-secondary;
line-height: 1.5;
font-weight: 500;
color: @demand-ink;
line-height: 1.45;
}
// 选中卡内文字反白(设计稿:标题/描述均为白色)
&__card.is-active &__name,
&__card.is-active &__desc {
color: @white;
}
}
</style>

View File

@@ -81,25 +81,37 @@ function onRemark(event: Event): void {
&__row {
.flex(row, flex-start, stretch);
gap: @spacing-base;
// 设计稿:两个 503 设计px 输入框(≈387px),间距 73 设计px ≈ 56px,整行不占满
gap: 56px;
}
&__field {
.flex(column, flex-start, stretch);
flex: 1 1 50%;
gap: @spacing-sm;
gap: 10px;
min-width: 0;
}
// 行内两列(用户名称 / 用户手机号)定宽;补充备注整行铺满
&__row &__field {
flex: 0 0 387px;
}
&__label {
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
font-size: 15px;
font-weight: 500;
color: @demand-heading;
}
&__input {
.text-control();
height: 36px;
height: 38px;
font-size: 15px;
border-color: @demand-line;
color: @demand-ink;
&::placeholder {
color: @demand-line;
}
}
&__area {
@@ -109,10 +121,17 @@ function onRemark(event: Event): void {
&__textarea {
.text-control();
min-height: 132px;
padding: @spacing-sm @spacing-base 24px;
min-height: 208px;
padding: 10px 14px 24px;
font-size: 15px;
border-color: @demand-line;
color: @demand-ink;
line-height: 1.7;
resize: vertical;
&::placeholder {
color: @demand-line;
}
}
&__count {

View File

@@ -198,24 +198,29 @@ function onBudgetManualBlur(event: Event): void {
&__field {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
gap: 10px;
min-width: 0;
}
&__row {
.flex(row, flex-start, stretch);
gap: @spacing-base;
// 设计稿:预算列 892 设计px + 间距 61 设计px + 周期列 652 设计px(1605 总宽)
gap: @spacing-xxl;
.demand-info__field {
flex: 1 1 50%;
width: 50%;
flex: 687 1 0;
width: auto;
}
.demand-info__field:last-child {
flex: 502 1 0;
}
}
&__label {
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
font-size: 15px;
font-weight: 500;
color: @demand-heading;
}
&__required {
@@ -225,7 +230,15 @@ function onBudgetManualBlur(event: Event): void {
&__input {
.text-control();
height: 36px;
// 设计稿:49 设计px 高 ≈ 38px,20 设计px 字号 ≈ 15px,描边/占位 rgba(153,153,153)
height: 38px;
font-size: 15px;
border-color: @demand-line;
color: @demand-ink;
&::placeholder {
color: @demand-line;
}
}
&__area {
@@ -235,10 +248,18 @@ function onBudgetManualBlur(event: Event): void {
&__textarea {
.text-control();
min-height: 132px;
padding: @spacing-sm @spacing-base 24px;
// 设计稿:270 设计px 高 ≈ 208px,占位内缩 18/10 设计px ≈ 14/8px
min-height: 208px;
padding: 10px 14px 24px;
font-size: 15px;
border-color: @demand-line;
color: @demand-ink;
line-height: 1.7;
resize: vertical;
&::placeholder {
color: @demand-line;
}
}
&__count {
@@ -251,21 +272,22 @@ function onBudgetManualBlur(event: Event): void {
&__budgets {
.flex(row, flex-start, stretch);
gap: @spacing-base;
// 设计稿:5 个 165 设计px 胶囊、间距 17 设计px ≈ 13px
gap: 13px;
}
/** 预算控件外观:4 个胶囊按钮 + 第 5 个手填输入框共用同一套规格 */
&__budget {
flex: 1;
min-width: 0;
height: 36px;
height: 38px;
padding: 0 @spacing-sm;
border: 1px solid @border-color;
border: 1px solid @demand-line;
border-radius: @radius-sm;
background: @white;
font-size: @font-size-base;
font-size: 15px;
font-family: inherit;
color: @text-color;
color: @demand-line;
text-align: center;
cursor: pointer;
transition: all 0.2s;
@@ -279,7 +301,7 @@ function onBudgetManualBlur(event: Event): void {
&.is-active {
border-color: @demand-accent;
background: @demand-selected-bg;
color: @demand-accent;
color: @white;
font-weight: 600;
}
}
@@ -290,7 +312,7 @@ function onBudgetManualBlur(event: Event): void {
&::placeholder {
font-weight: 400;
color: @text-color-secondary;
color: @demand-line;
}
}
}

View File

@@ -123,6 +123,8 @@ onMounted(() => {
padding-top: @spacing-lg;
// 固定底条 72px + 呼吸间距,避免遮住 ③ 卡片
padding-bottom: 104px;
// 设计稿:导航下方 179 设计px(≈138px)白色通栏横幅,其下为页面底色
background: linear-gradient(to bottom, @white 0, @white 138px, @bg-color 138px);
&.is-loading {
.demand {
@@ -133,54 +135,76 @@ onMounted(() => {
}
.demand {
// 设计稿:页头下与首块间距 ≈ 20px
// 设计稿:标题距横幅顶 32 设计px、副标题行距 15 设计px、横幅下留白 50 设计px
&__head {
.flex(column, flex-start, stretch);
gap: @spacing-xs;
margin-bottom: @spacing-base;
gap: 11px;
margin-bottom: 50px;
}
&__title {
font-size: @font-size-xxl;
font-weight: 600;
color: @heading-color;
font-weight: 700;
line-height: 1.45;
color: @demand-ink;
}
&__subtitle {
font-size: @font-size-base;
color: @text-color-secondary;
font-size: 18px;
font-weight: 500;
color: @demand-subtitle;
}
// 设计稿三段内容位于同一张白色大卡内:三张卡无缝拼接呈现同一张卡的观感
&__card {
padding: @spacing-lg;
border-radius: @radius-base;
padding: 24px 40px 24px 49px;
border-radius: 0;
background: @white;
// 设计稿块间距 18px
// 三卡相连,不再留块间距
& + & {
margin-top: 18px;
margin-top: 0;
}
&:first-of-type {
padding-top: 37px;
border-radius: @radius-base @radius-base 0 0;
}
&:last-of-type {
padding-bottom: 40px;
border-radius: 0 0 @radius-base @radius-base;
}
}
// 区块标题:序号落在卡左内边距列(x=134 设计px),标题文字对齐内容列(x=194)
&__section {
.flex(row, flex-start, center);
gap: @spacing-sm;
margin-bottom: @spacing-base;
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
.flex(row, flex-start, baseline);
gap: @spacing-xs;
margin-bottom: 16px;
font-size: @font-size-title;
font-weight: 500;
color: @demand-heading;
}
/** 区块序号:实心蓝圆 + 白色数字 */
// 内容列(卡片栅格 / 表单)与区块标题文字对齐到 x=194 设计列(60 设计px ≈ 46px)
&__section + * {
margin-left: 46px;
}
// ① 段标题到卡片栅格的间距更大(56 设计px ≈ 43px)
&__card:first-of-type &__section {
margin-bottom: 40px;
}
/** 区块序号:设计稿 48 设计px 蓝色数字(01/02/03) */
&__index {
.flex(row, center, center);
width: 18px;
height: 18px;
border-radius: 50%;
background: @primary-color;
font-size: @font-size-sm;
font-weight: 600;
color: @white;
flex-shrink: 0;
width: 42px;
font-size: 37px;
font-weight: 500;
line-height: 1;
color: @demand-accent;
}
&__required {

View File

@@ -79,7 +79,14 @@ onMounted(() => {
</div>
<div class="bill-detail__field">
<span class="bill-detail__label text-secondary">订单金额</span>
<span class="bill-detail__value bill-detail__value--amount">¥{{ formatMoney(currentBill.amount) }}</span>
<!-- 设计 31:金额随状态取色——已支付红 / 待支付橙 / 未到期深灰 -->
<span
class="bill-detail__value bill-detail__value--amount"
:class="{
'is-pending': currentBill.status === '待支付',
'is-idle': currentBill.status === '未到期' || currentBill.status === '已取消',
}"
>¥{{ formatMoney(currentBill.amount) }}</span>
</div>
</div>
@@ -143,17 +150,28 @@ onMounted(() => {
<style lang="less" scoped>
.bill-detail {
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 31:面包屑 13 设计px → 11px,前缀灰、当前页深灰
&__breadcrumb {
margin-bottom: @spacing-base;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
// 设计 31:白卡居中(对应设计三张窄卡的中轴布局),圆角 8、柔阴影
&__card {
padding: @spacing-lg;
border-radius: @radius-lg;
max-width: 440px;
margin: 0 auto;
padding: @spacing-base 20px 20px;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
@@ -164,69 +182,114 @@ onMounted(() => {
}
&__card-title {
font-size: @font-size-lg;
font-weight: 600;
font-size: 12px;
font-weight: 700;
color: @heading-color;
}
// 状态徽标压成设计稿的深色粗体状态词
:deep(.status-tag) {
padding: 0;
background: transparent;
color: @heading-color;
font-size: 12px;
font-weight: 700;
}
// 字段行:标签左(灰 11px)、值右(深色粗体)——设计 31 左右分栏
&__fields {
.flex(column, flex-start);
gap: @spacing-sm;
.flex(column, flex-start, stretch);
gap: 12px;
}
&__field {
.flex(row, flex-start, center);
.flex(row, space-between, center);
gap: @spacing-base;
font-size: @font-size-base;
font-size: 11px;
}
&__label {
width: 80px;
flex-shrink: 0;
font-size: 11px;
}
&__value {
color: @heading-color;
&--amount {
font-weight: 600;
text-align: right;
word-break: break-all;
// 设计 31:付款金额 已支付 #EF4444 / 待支付 #F59E0B / 未到期深灰,18 设计px → 14px 粗体
&--amount {
font-size: 14px;
font-weight: 700;
color: @danger-color;
}
&.is-pending {
color: @finance-pending;
}
&.is-idle {
color: @heading-color;
}
}
&__pay {
margin-top: @spacing-lg;
margin-top: @spacing-base;
}
&__pay-info {
margin-top: @spacing-lg;
margin-top: @spacing-base;
padding-top: @spacing-base;
border-top: 1px solid @border-color;
border-top: 1px solid @project-divider;
}
&__sub-title {
margin-bottom: @spacing-sm;
font-size: @font-size-base;
font-weight: 600;
margin-bottom: 12px;
font-size: 11px;
font-weight: 700;
color: @heading-color;
}
&__tip {
margin-top: @spacing-lg;
padding: @spacing-base;
border-radius: @radius-base;
margin-top: @spacing-base;
padding: 12px;
border-radius: @radius-sm;
background: @bg-color;
font-size: @font-size-base;
font-size: 11px;
}
&__empty {
padding: @spacing-xl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
&__back {
margin-top: @spacing-lg;
max-width: 440px;
margin: @spacing-base auto 0;
}
// 设计 31/32:按钮蓝底 #024FFF(返回/立即支付同色)
:deep(.app-button--primary) {
background: @primary-strong;
&:hover {
background: @primary-color;
}
}
&__back :deep(.app-button--default) {
border-color: @primary-strong;
background: @primary-strong;
color: @white;
&:hover {
border-color: @primary-color;
background: @primary-color;
color: @white;
}
}
}
</style>

View File

@@ -75,6 +75,8 @@ onMounted(() => {
<span>账单明细</span>
</nav>
<!-- 设计 30:状态分段 Tab 与搜索栏同排共处一张白卡 -->
<div class="bills__toolbar">
<div class="bills__tabs">
<button
v-for="tab in STATUS_TABS"
@@ -93,7 +95,9 @@ onMounted(() => {
@search="onSearch"
@reset="onReset"
/>
</div>
<div class="bills__board">
<BillTable
:bills="list"
:selected-ids="selectedIds"
@@ -102,12 +106,6 @@ onMounted(() => {
@pay="onPay"
/>
<BillSummaryBar
:bills="list"
:selected-ids="selectedIds"
@batch-pay="onBatchPay"
/>
<PaginationBar
:page="query.page"
:page-size="query.pageSize"
@@ -115,44 +113,170 @@ onMounted(() => {
@page-change="onPageChange"
/>
</div>
<BillSummaryBar
:bills="list"
:selected-ids="selectedIds"
@batch-pay="onBatchPay"
/>
</div>
</template>
<style lang="less" scoped>
.bills {
.flex(column, flex-start);
align-items: stretch;
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 30:面包屑 13 设计px → 11px,前缀灰、当前页深灰
&__breadcrumb {
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
&__tabs {
.flex(row, flex-start);
// 顶部工具条:Tab 分段组 + 搜索栏(一张白卡)
&__toolbar {
.flex(row, flex-start, center);
gap: @spacing-base;
padding: 10px @spacing-base;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
:deep(.filter-panel) {
flex: 1;
min-width: 0;
padding: 0;
background: transparent;
box-shadow: none;
border-radius: 0;
}
:deep(.filter-panel__body) {
margin-top: 0;
}
:deep(.filter-panel__bar) {
gap: @spacing-sm;
}
&__tab {
height: 34px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @white;
color: @text-color;
font-size: @font-size-base;
transition: all 0.2s;
:deep(.filter-panel__input) {
order: 1;
flex: 1;
width: auto;
height: 26px;
border: none;
border-radius: @radius-sm;
background: @finance-field-bg;
font-size: 11px;
&::placeholder {
color: @contract-placeholder;
}
}
// 设计顺序:… 重置 搜索(FilterPanel 模板为搜索在前,用 order 调序)
:deep(.filter-panel__btn--primary) {
order: 3;
height: 26px;
padding: 0 14px;
border: none;
background: @primary-strong;
font-size: 11px;
&:hover {
border-color: @primary-color;
color: @primary-color;
background: @primary-color;
}
}
:deep(.filter-panel__btn:not(.filter-panel__btn--primary)) {
order: 2;
height: 26px;
padding: 0 14px;
border: none;
background: @project-quiet-btn;
color: @text-color;
font-size: 11px;
&:hover {
border: none;
background: @border-color;
color: @text-color;
}
}
}
// 状态 Tab:描边分段组,选中实底 #024FFF(设计 30)
&__tabs {
.flex(row, flex-start);
gap: 0;
border: 1px solid @border-color;
border-radius: @radius-sm;
overflow: hidden;
flex-shrink: 0;
}
&__tab {
height: 26px;
padding: 0 14px;
border: none;
border-right: 1px solid @border-color;
border-radius: 0;
background: @white;
color: @text-color;
font-size: 11px;
transition: all 0.2s;
&:last-child {
border-right: none;
}
&:hover {
color: @primary-strong;
}
&.is-active {
border-color: @primary-color;
background: @primary-color;
border-right-color: @primary-strong;
background: @primary-strong;
color: @white;
}
}
// 表格 + 分页共处白卡(设计 30:分页在卡片内右下角)
&__board {
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
overflow: hidden;
}
// 分页:右对齐小方格,选中浅蓝底蓝字(设计 30/35)
.pagination {
justify-content: flex-end;
padding: 12px @spacing-base @spacing-base;
}
:deep(.pagination__btn) {
min-width: 24px;
height: 24px;
border-color: @border-color;
border-radius: @radius-sm;
color: @text-color-secondary;
font-size: 11px;
&.is-active {
border-color: @primary-strong;
background: @finance-page-active;
color: @primary-strong;
}
}
}
</style>

View File

@@ -34,17 +34,22 @@ function onBatchPay(): void {
</script>
<template>
<!-- 设计 30:整幅白条——左「已选择 N 笔订单」+ 统计,右「合计:¥ 金额 + 立即支付」 -->
<div class="bill-summary">
<div class="bill-summary__left">
<span class="bill-summary__selected">
已选择<strong>{{ selectedBills.length }}</strong>笔订单
</span>
<div class="bill-summary__stats">
<span class="bill-summary__stat">总笔数:<strong>{{ totalCount }}</strong></span>
<span class="bill-summary__stat">总金额:<strong>¥{{ formatMoney(totalAmount) }}</strong></span>
<span class="bill-summary__stat">待支付:<strong>{{ pendingCount }}</strong></span>
</div>
</div>
<div class="bill-summary__right">
<span class="bill-summary__selected">
已选择{{ selectedBills.length }}笔订单 · 合计:¥{{ formatMoney(selectedAmount) }}
</span>
<span class="bill-summary__label">合计:</span>
<span class="bill-summary__amount">¥{{ formatMoney(selectedAmount) }}</span>
<AppButton
type="primary"
:disabled="!canPay"
@@ -59,30 +64,73 @@ function onBatchPay(): void {
<style lang="less" scoped>
.bill-summary {
.flex(row, space-between, center);
padding: @spacing-base @spacing-lg;
border-radius: @radius-lg;
gap: @spacing-base;
margin: 0 -16px;
padding: 10px @spacing-base;
border-radius: 0;
background: @white;
box-shadow: @shadow-base;
&__left {
.flex(row, flex-start, center);
gap: @spacing-lg;
min-width: 0;
}
&__selected {
font-size: 11px;
color: @text-color;
white-space: nowrap;
strong {
margin: 0 2px;
color: @danger-color;
font-weight: 700;
}
}
&__stats {
.flex(row, flex-start);
.flex(row, flex-start, center);
gap: @spacing-lg;
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
strong {
color: @heading-color;
font-weight: 600;
}
}
&__right {
.flex(row, flex-end, center);
gap: @spacing-base;
gap: 6px;
flex-shrink: 0;
}
&__selected {
font-size: @font-size-base;
&__label {
font-size: 11px;
color: @text-color;
}
// 合计金额:设计 30 实取 20 设计px → 15px 粗体红
&__amount {
margin-right: @spacing-sm;
font-size: 15px;
font-weight: 700;
color: @danger-color;
white-space: nowrap;
}
// 「立即支付」:设计 30 实取橙色按钮
:deep(.app-button--primary) {
height: 28px;
padding: 0 14px;
background: @finance-summary-cta;
color: @white;
font-size: 11px;
&:hover {
background: @warning-color;
}
}
}
</style>

View File

@@ -118,31 +118,33 @@ const STATUS_VARIANTS: Record<BillStatus, 'warning' | 'success' | 'info' | 'dang
</template>
<style lang="less" scoped>
// 设计 30:表格贴满白卡(外层 .bills__board 提供卡底),全网格浅灰线 + 浅灰表头
.bill-table {
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
overflow-x: auto;
&__table {
width: 100%;
border-collapse: collapse;
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
th,
td {
padding: @spacing-sm @spacing-sm;
padding: 11px 10px;
text-align: left;
white-space: nowrap;
border-bottom: 1px solid @border-color;
border: 1px solid @project-divider;
}
th {
background: @bg-color-light;
color: @text-color-secondary;
font-weight: 500;
background: @finance-table-head-bg;
color: @text-color;
font-weight: 600;
text-align: center;
}
tbody tr:hover {
@@ -150,28 +152,54 @@ const STATUS_VARIANTS: Record<BillStatus, 'warning' | 'success' | 'info' | 'dang
}
}
&__check {
width: 40px;
// 列对齐按设计 30:序号/账单号/流水号/金额/状态/操作居中,名称类左对齐
&__table th:nth-child(1),
&__table th:nth-child(2),
&__table td:nth-child(1),
&__table td:nth-child(2),
&__table th:nth-child(4),
&__table td:nth-child(4),
&__table th:nth-child(5),
&__table td:nth-child(5),
&__table th:nth-child(7),
&__table td:nth-child(7),
&__table th:nth-child(8),
&__table td:nth-child(8),
&__table th:nth-child(9),
&__table td:nth-child(9) {
text-align: center;
}
&__check {
width: 44px;
text-align: center;
input {
width: 14px;
height: 14px;
accent-color: @primary-strong;
vertical-align: middle;
}
}
// 金额列与正文同色(设计 30 实取 #4B5563 常规字重)
&__amount {
color: @heading-color;
font-weight: 600;
color: @text-color;
font-weight: 400;
}
&__ops {
.flex(row, flex-start);
gap: @spacing-sm;
.flex(row, center, center);
gap: 12px;
}
&__link {
color: @primary-color;
font-size: @font-size-base;
color: @primary-strong;
font-size: 11px;
transition: color 0.2s;
&:hover {
color: @primary-hover;
color: @primary-color;
}
}
@@ -179,5 +207,14 @@ const STATUS_VARIANTS: Record<BillStatus, 'warning' | 'success' | 'info' | 'dang
text-align: center;
padding: @spacing-xl 0;
}
// 状态列按设计 30 为纯文字(去底色徽标)
:deep(.status-tag) {
padding: 0;
background: transparent;
color: @text-color;
font-size: 11px;
line-height: 1.5;
}
}
</style>

View File

@@ -39,6 +39,25 @@ function percentOf(value: number): number {
业务类型分布
</h3>
<div class="finance-chart__body">
<!-- 设计 37:横向网格线 + 等宽柱条(柱高按占比换算) -->
<div class="finance-chart__plot">
<div class="finance-chart__grid" aria-hidden="true">
<i class="finance-chart__line" />
<i class="finance-chart__line" />
<i class="finance-chart__line" />
<i class="finance-chart__line" />
<i class="finance-chart__line" />
</div>
<div class="finance-chart__bars">
<span
v-for="item in distribution"
:key="item.name"
class="finance-chart__bar"
:style="{ height: `${Math.max(percentOf(item.value), 6)}%` }"
/>
</div>
</div>
<!-- 数据源色环:设计稿为柱状图,此处仅保留绑定(隐藏)以免游离变量 -->
<div class="finance-chart__pie" :style="{ background: gradient }" />
<ul class="finance-chart__legend">
<li
@@ -59,52 +78,100 @@ function percentOf(value: number): number {
</template>
<style lang="less" scoped>
// 设计 37:白卡 + 蓝色竖条标题(15 设计px → 12px/700)+ 柱状图 + 横排图例
.finance-chart {
padding: @spacing-lg;
border-radius: @radius-lg;
padding: 20px @spacing-lg @spacing-lg;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
&__title {
position: relative;
padding-left: 10px;
margin-bottom: @spacing-base;
font-size: @font-size-lg;
font-weight: 600;
font-size: 12px;
font-weight: 700;
color: @heading-color;
&::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 4px;
height: 14px;
border-radius: @radius-round;
background: @primary-strong;
transform: translateY(-50%);
}
}
&__body {
.flex(row, center, center);
gap: @spacing-xl;
.flex(column, center, center);
gap: @spacing-base;
}
&__plot {
position: relative;
width: 100%;
height: 184px;
}
&__grid {
.flex(column, space-between);
position: absolute;
inset: 0;
}
&__line {
display: block;
width: 100%;
height: 1px;
background: @finance-chart-grid;
}
&__bars {
.flex(row, space-around, flex-end);
position: absolute;
inset: 0;
padding: 0 60px;
}
&__bar {
display: block;
width: 40px;
border-radius: 2px 2px 0 0;
background: @finance-chart-bar;
}
// 设计稿无色环:绑定保留但不参与展示
&__pie {
width: 180px;
height: 180px;
border-radius: @radius-round;
flex-shrink: 0;
display: none;
}
&__legend {
.flex(column, flex-start);
gap: @spacing-base;
.flex(row, center, center);
gap: @spacing-lg;
list-style: none;
padding: 0;
}
&__legend-item {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: @font-size-base;
color: @text-color;
gap: 6px;
font-size: 11px;
color: @text-color-secondary;
}
&__dot {
width: 10px;
height: 10px;
width: 8px;
height: 8px;
border-radius: @radius-round;
flex-shrink: 0;
}
&__name {
min-width: 72px;
min-width: 0;
}
&__value {

View File

@@ -63,33 +63,39 @@ const emit = defineEmits<{
</template>
<style lang="less" scoped>
// 设计 37:整卡为蓝紫渐变(累计消费总额白字),右上角白色操作链接
.finance-overview {
.flex(row, space-between, center);
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
.flex(column, flex-start, stretch);
flex: 1 1 500px;
min-width: 0;
padding: 14px @spacing-lg 16px;
border-radius: @radius-base;
background: @finance-hero-gradient;
box-shadow: @shadow-base;
&__main {
.flex(column, flex-start);
gap: @spacing-sm;
.flex(column, flex-start, flex-start);
gap: 6px;
}
&__label {
font-size: @font-size-base;
color: @white;
font-size: 11px;
}
&__amount {
font-size: 36px;
font-weight: 600;
color: @heading-color;
line-height: 1.2;
color: @white;
font-size: 29px;
font-weight: 700;
line-height: 1.15;
}
&__meta {
.flex(row, flex-start, center);
gap: @spacing-base;
font-size: @font-size-base;
margin-top: 4px;
font-size: 11px;
color: fade(@white, 85%);
}
&__periods {
@@ -98,38 +104,52 @@ const emit = defineEmits<{
}
&__period {
height: 28px;
height: 22px;
padding: 0 @spacing-sm;
border: 1px solid @border-color;
border: 1px solid fade(@white, 45%);
border-radius: @radius-sm;
background: @white;
color: @text-color;
font-size: @font-size-sm;
background: fade(@white, 16%);
color: @white;
font-size: 11px;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
border-color: @white;
background: fade(@white, 30%);
color: @white;
}
}
&__month {
font-size: @font-size-sm;
font-size: 11px;
color: fade(@white, 85%);
}
// 待支付小徽标压到渐变上:半透明白底 + 白字
:deep(.status-tag) {
background: fade(@white, 20%);
color: @white;
font-size: 11px;
}
// 操作链接置顶右对齐(对应设计右上角「2026年账单 ›」位置)
&__actions {
.flex(row, flex-start);
order: -1;
align-self: stretch;
.flex(row, flex-end, center);
gap: @spacing-base;
margin-bottom: 4px;
}
&__action {
font-size: @font-size-base;
color: @primary-color;
font-size: 11px;
color: fade(@white, 92%);
cursor: pointer;
transition: color 0.2s;
&:hover {
color: @primary-hover;
color: @white;
text-decoration: underline;
}
}
}

View File

@@ -16,23 +16,10 @@ const emit = defineEmits<{
</script>
<template>
<!-- 设计 35/36:一行一张宽卡——左上默认徽标、右上操作按钮,下方三栏字段 -->
<div class="invoice-title-card">
<div class="invoice-title-card__head">
<span class="invoice-title-card__label text-secondary">发票抬头</span>
<StatusTag
:label="invoiceTitle.type"
:variant="invoiceTitle.type === '企业单位' ? 'primary' : 'info'"
/>
<div class="invoice-title-card__top">
<StatusTag v-if="invoiceTitle.isDefault" label="默认" variant="success" />
</div>
<p class="invoice-title-card__title">
{{ invoiceTitle.title }}
</p>
<div class="invoice-title-card__tax">
<span class="invoice-title-card__label text-secondary">税号</span>
<span class="invoice-title-card__tax-no">{{ invoiceTitle.taxNo }}</span>
</div>
<div class="invoice-title-card__actions">
<button
class="invoice-title-card__btn"
@@ -40,71 +27,73 @@ const emit = defineEmits<{
>
{{ invoiceTitle.isDefault ? '取消默认' : '设为默认' }}
</button>
<button class="invoice-title-card__btn" @click="emit('edit', invoiceTitle)">
编辑
</button>
<button class="invoice-title-card__btn is-danger" @click="emit('delete', invoiceTitle.id)">
删除
</button>
<button class="invoice-title-card__btn" @click="emit('edit', invoiceTitle)">
编辑
</button>
</div>
</div>
<div class="invoice-title-card__cols">
<div class="invoice-title-card__col">
<StatusTag
:label="invoiceTitle.type"
:variant="invoiceTitle.type === '企业单位' ? 'primary' : 'info'"
/>
</div>
<div class="invoice-title-card__col">
<span class="invoice-title-card__label text-secondary">发票抬头</span>
<p class="invoice-title-card__title">
{{ invoiceTitle.title }}
</p>
</div>
<div class="invoice-title-card__col">
<span class="invoice-title-card__label text-secondary">税号</span>
<span class="invoice-title-card__tax-no">{{ invoiceTitle.taxNo }}</span>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.invoice-title-card {
padding: @spacing-base;
border: 1px solid @border-color;
display: flex;
flex-direction: column;
gap: 16px;
padding: 14px 20px;
border: none;
border-radius: @radius-base;
background: @white;
.flex(column, flex-start);
gap: @spacing-sm;
box-shadow: @shadow-base;
&__head {
.flex(row, flex-start, center);
gap: @spacing-sm;
}
&__label {
font-size: @font-size-sm;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
word-break: break-all;
}
&__tax {
.flex(row, flex-start, center);
gap: @spacing-sm;
}
&__tax-no {
font-size: @font-size-base;
color: @text-color;
word-break: break-all;
// 顶行:默认徽标居左、操作按钮居右(设计 35 同一行)
&__top {
.flex(row, space-between, center);
min-height: 24px;
}
&__actions {
.flex(row, flex-start);
.flex(row, flex-end, center);
gap: @spacing-sm;
margin-top: @spacing-xs;
}
// 描边小按钮:浅灰边白底 11px(设计 35 实取)
&__btn {
height: 28px;
padding: 0 @spacing-sm;
border: 1px solid @border-color-dark;
height: 24px;
padding: 0 10px;
border: 1px solid @border-color;
border-radius: @radius-sm;
background: @white;
color: @text-color;
font-size: @font-size-sm;
font-size: 11px;
cursor: pointer;
transition: all 0.2s;
&:hover:not(:disabled) {
border-color: @primary-color;
color: @primary-color;
border-color: @primary-strong;
color: @primary-strong;
}
&.is-danger:hover:not(:disabled) {
@@ -112,5 +101,49 @@ const emit = defineEmits<{
color: @danger-color;
}
}
// 三栏字段:列起点按设计 35(x97 / x579 / x1061,卡内 0 / 371 / 742 CSS)
&__cols {
display: grid;
grid-template-columns: minmax(0, 371px) minmax(0, 371px) minmax(0, 1fr);
gap: @spacing-base;
}
&__col {
.flex(column, flex-start, flex-start);
gap: 6px;
min-width: 0;
}
// 标签 11 设计px → 11px 灰;值 14 设计px → 11px 粗体深色
&__label {
font-size: 11px;
}
&__title,
&__tax-no {
font-size: 11px;
font-weight: 700;
color: @heading-color;
word-break: break-all;
}
// 抬头类型值:去掉徽标底色,按设计为纯文字
:deep(.status-tag) {
padding: 0;
background: transparent;
color: @heading-color;
font-size: 11px;
font-weight: 700;
align-self: flex-start;
}
// 「默认」徽标:设计 35 为实底蓝底白字小胶囊
:deep(.status-tag--success) {
padding: 2px 8px;
background: @primary-strong;
color: @white;
font-weight: 500;
}
}
</style>

View File

@@ -53,8 +53,7 @@ const qrSvg = computed(() => {
qr.addData(props.content)
qr.make()
return qr.createSvgTag({ cellSize: 4, margin: 2, scalable: true })
}
catch {
} catch {
return ''
}
})
@@ -98,12 +97,8 @@ function onBoxClick(): void {
<Teleport to="body">
<div v-if="visible" class="wx-qr" @click.self="close">
<div class="wx-qr__panel">
<h3 class="wx-qr__title">
微信扫码支付
</h3>
<p class="wx-qr__amount">
¥{{ formatMoney(amount) }}
</p>
<h3 class="wx-qr__title">微信扫码支付</h3>
<p class="wx-qr__amount">¥{{ formatMoney(amount) }}</p>
<div
class="wx-qr__box"
@@ -115,25 +110,21 @@ function onBoxClick(): void {
<div v-else class="wx-qr__mask">
<span class="wx-qr__mask-icon">⟳</span>
<span class="wx-qr__mask-text">
{{ expired ? '二维码已过期' : '二维码生成中' }}<br>点击刷新
{{ expired ? '二维码已过期' : '二维码生成中' }}<br />点击刷新
</span>
</div>
</div>
<p class="wx-qr__status">
<template v-if="!expired">
请使用手机微信 <strong>[扫一扫]</strong> 扫描上方二维码,
二维码 <strong class="wx-qr__count">{{ countdownText }}</strong> 后失效
</template>
<template v-else>
二维码已过期,请点击二维码或下方按钮刷新
请使用手机微信 <strong>[扫一扫]</strong> 扫描上方二维码, 二维码
<strong class="wx-qr__count">{{ countdownText }}</strong> 后失效
</template>
<template v-else> 二维码已过期,请点击二维码或下方按钮刷新 </template>
</p>
<div class="wx-qr__actions">
<button class="wx-qr__btn" @click="refresh">
刷新二维码
</button>
<button class="wx-qr__btn" @click="refresh">刷新二维码</button>
<button class="wx-qr__btn wx-qr__btn--cta" @click="onPaid">
我已完成支付
</button>

View File

@@ -36,14 +36,13 @@ onMounted(() => {
</p>
</header>
<div class="finance__top">
<FinanceOverview
:stats="stats"
@period-change="onPeriodChange"
@export="onExport"
/>
<FinanceChart :distribution="stats?.distribution ?? []" />
<div class="finance__entries">
<RouterLink to="/finance/invoices" class="finance__entry">
<span class="finance__entry-icon">🧾</span>
@@ -59,52 +58,77 @@ onMounted(() => {
</button>
</div>
</div>
<FinanceChart :distribution="stats?.distribution ?? []" />
</div>
</template>
<style lang="less" scoped>
.finance {
.flex(column, flex-start);
align-items: stretch;
gap: @spacing-base;
padding-top: @spacing-xl;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: 40px @spacing-base @spacing-xxl;
// 设计 37:页头标题 22 设计px × 0.77 ≈ 17px 加粗,副标语 13 设计px → 11px 居中
&__title {
font-size: @font-size-xxl;
font-weight: 600;
font-size: 17px;
font-weight: 700;
color: @heading-color;
}
&__slogan {
margin-top: @spacing-xs;
font-size: @font-size-base;
font-size: 11px;
text-align: center;
}
// 顶部行:左「累计消费」渐变卡 + 右快捷入口白卡(设计 37 同排并列)
&__top {
.flex(row, flex-start, stretch);
gap: @spacing-base;
flex-wrap: wrap;
}
&__entries {
.flex(row, flex-start);
.flex(row, space-around, center);
flex: 0 0 500px;
gap: @spacing-base;
padding: @spacing-base @spacing-lg;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
&__entry {
.flex(row, center, center);
.flex(column, center, center);
gap: @spacing-sm;
width: 200px;
height: 72px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @white;
width: auto;
height: auto;
border: none;
border-radius: 0;
background: transparent;
color: @text-color;
font-size: @font-size-lg;
font-size: 11px;
cursor: pointer;
transition: all 0.2s;
transition: color 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
border: none;
color: @primary-strong;
}
}
&__entry-icon {
font-size: @font-size-xl;
.flex(row, center, center);
width: 36px;
height: 36px;
border-radius: @radius-base;
background: @bg-color;
font-size: 18px;
}
}
</style>

View File

@@ -146,24 +146,52 @@ onMounted(() => {
<style lang="less" scoped>
.invoice-titles {
.flex(column, flex-start);
align-items: stretch;
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 35/36:面包屑 13 设计px → 11px,前缀灰、当前页深灰
&__breadcrumb {
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
// 顶部「发票管理」白卡条(设计 35:蓝竖条标题 + 右侧按钮组)
&__head {
.flex(row, space-between, center);
flex-wrap: wrap;
gap: @spacing-base;
padding: 14px 20px;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
&__title {
font-size: @font-size-xl;
font-weight: 600;
position: relative;
padding-left: 10px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
&::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 4px;
height: 14px;
border-radius: @radius-round;
background: @primary-strong;
transform: translateY(-50%);
}
}
&__filters {
@@ -172,36 +200,51 @@ onMounted(() => {
}
&__filter {
height: 34px;
padding: 0 @spacing-base;
height: 26px;
padding: 0 14px;
border: 1px solid @border-color;
border-radius: @radius-base;
border-radius: @radius-sm;
background: @white;
color: @text-color;
font-size: @font-size-base;
font-size: 11px;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
border-color: @primary-strong;
color: @primary-strong;
}
&.is-active {
border-color: @primary-color;
background: @primary-color;
border-color: @primary-strong;
background: @primary-strong;
color: @white;
}
}
// 「+ 新增抬头」:设计 35 实底 #024FFF 小按钮
:deep(.app-button--primary) {
height: 26px;
padding: 0 12px;
border-radius: @radius-sm;
background: @primary-strong;
font-size: 11px;
&:hover {
background: @primary-color;
}
}
// 抬头卡纵排铺满(设计 35 一行一张)
&__grid {
.flex(row, flex-start);
flex-wrap: wrap;
display: flex;
flex-direction: column;
gap: @spacing-base;
}
&__empty {
padding: @spacing-xl 0;
font-size: @font-size-base;
font-size: 11px;
text-align: center;
}
}
</style>

View File

@@ -213,12 +213,21 @@ onMounted(() => {
<style lang="less" scoped>
.invoices {
.flex(column, flex-start);
align-items: stretch;
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 与财务中心其他页一致:面包屑 11px、前缀灰当前页深灰
&__breadcrumb {
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
&__title-card {
@@ -230,7 +239,7 @@ onMounted(() => {
}
&__title-main {
.flex(column, flex-start);
.flex(column, flex-start, stretch);
gap: @spacing-xs;
}

View File

@@ -52,12 +52,12 @@ onMounted(() => {
<h2 class="pay-result__title">
支付成功
</h2>
<p class="pay-result__amount">
付款金额 ¥{{ formatMoney(result.amount) }}
</p>
<p class="pay-result__count text-secondary">
共{{ result.bills.length }}个订单
</p>
<p class="pay-result__amount">
付款金额 ¥{{ formatMoney(result.amount) }}
</p>
</div>
</div>
@@ -109,130 +109,171 @@ onMounted(() => {
<style lang="less" scoped>
.pay-result {
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 32:面包屑 13 设计px → 11px,前缀灰、当前页深灰
&__breadcrumb {
margin-bottom: @spacing-base;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
// 设计 32:内容为居中窄列,直接坐在页面底色上(无外层大卡)
&__card {
padding: @spacing-xl @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
width: 300px;
max-width: 100%;
margin: 0 auto;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
// 头部:大绿圆勾 + 标题 + 「共 N 个订单 / 付款金额」同一行
&__head {
.flex(row, flex-start, center);
gap: @spacing-base;
padding-bottom: @spacing-lg;
border-bottom: 1px solid @border-color;
.flex(column, center, center);
gap: 12px;
padding-bottom: 16px;
border-bottom: 1px solid @project-divider;
}
&__check {
.flex(row, center);
width: 56px;
height: 56px;
width: 76px;
height: 76px;
border-radius: @radius-round;
background: fade(@success-color, 12%);
color: @success-color;
font-size: 32px;
font-weight: 600;
background: @finance-result-circle;
color: @white;
font-size: 42px;
font-weight: 400;
line-height: 1;
flex-shrink: 0;
}
&__head-text {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: baseline;
gap: 6px;
}
&__title {
font-size: @font-size-xl;
font-weight: 600;
flex-basis: 100%;
text-align: center;
font-size: 17px;
font-weight: 700;
color: @heading-color;
}
&__amount {
margin-top: @spacing-xs;
font-size: @font-size-lg;
font-size: 14px;
color: @danger-color;
font-weight: 600;
font-weight: 700;
}
&__count {
margin-top: @spacing-xs;
font-size: @font-size-base;
font-size: 11px;
}
// 支付信息:标签左灰、值右粗(设计 32 竖排行)
&__grid {
.flex(row, flex-start, flex-start);
gap: @spacing-xxl;
margin-top: @spacing-lg;
.flex(column, flex-start, stretch);
gap: 14px;
margin-top: 16px;
}
&__grid-item {
.flex(column, flex-start);
gap: @spacing-xs;
.flex(row, space-between, center);
gap: @spacing-base;
}
&__grid-label {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-secondary;
}
&__grid-value {
font-size: @font-size-base;
font-size: 11px;
font-weight: 700;
color: @heading-color;
text-align: right;
word-break: break-all;
}
&__bills {
margin-top: @spacing-lg;
padding-top: @spacing-base;
border-top: 1px solid @border-color;
margin-top: 16px;
}
&__sub-title {
margin-bottom: @spacing-sm;
font-size: @font-size-base;
font-weight: 600;
margin-bottom: 8px;
font-size: 11px;
font-weight: 700;
color: @heading-color;
}
// 已支付订单行卡:白底圆角(设计 32 实取)
&__bill-list {
.flex(column, flex-start);
gap: @spacing-sm;
.flex(column, flex-start, stretch);
gap: 6px;
list-style: none;
padding: 0;
margin: 0;
}
&__bill {
.flex(row, flex-start, center);
gap: @spacing-base;
padding: @spacing-sm;
border-radius: @radius-sm;
background: @bg-color-light;
font-size: @font-size-base;
gap: 8px;
padding: 10px;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @text-color;
}
&__bill-name {
color: @heading-color;
font-weight: 700;
}
&__bill-no {
flex: 1;
font-size: 11px;
color: @text-color-disabled;
}
&__bill-amount {
font-weight: 600;
font-weight: 700;
color: @heading-color;
white-space: nowrap;
}
// 返回按钮右对齐(设计 32 在列右下)
&__footer {
margin-top: @spacing-lg;
display: flex;
justify-content: flex-end;
margin-top: 16px;
}
:deep(.app-button--primary) {
background: @primary-strong;
&:hover {
background: @primary-color;
}
}
&__empty {
padding: @spacing-xl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
}
</style>

View File

@@ -74,29 +74,42 @@ onMounted(() => {
<span>扫码支付</span>
</nav>
<div class="pay__body">
<section class="pay__left card">
<QrCodePanel
:expires-in="payment?.qrExpiresInSeconds ?? 300"
@refresh="onRefresh"
/>
<p class="pay__safe text-secondary">
安全提示:本页面已通过安全验证,请勿向他人泄露付款码
<!-- 设计 33/34:单张大白卡——左(渠道说明 + 切换)/ 中(金额 + 二维码)/ 右(步骤 + 订单明细 + 安全提示) -->
<div class="pay__body card">
<section class="pay__left">
<div class="pay__left-top">
<p class="pay__method">
{{ methodLabel }} · 请使用手机微信 <strong>[扫一扫]</strong> 扫描下方二维码完成支付
</p>
<AppButton @click="dialogVisible = true">
<AppButton class="pay__switch" @click="dialogVisible = true">
切换支付方式
</AppButton>
</section>
</div>
<section class="pay__right card">
<div class="pay__amount-block">
<p class="pay__amount-label text-secondary">
支付金额
</p>
<p class="pay__amount">¥{{ formatMoney(payment?.amount ?? currentBill?.amount ?? 0) }}</p>
<p class="pay__method">
{{ methodLabel }} · 请使用手机微信 <strong>[扫一扫]</strong> 扫描下方二维码完成支付
</p>
</div>
<QrCodePanel
:expires-in="payment?.qrExpiresInSeconds ?? 300"
@refresh="onRefresh"
/>
</section>
<section class="pay__right">
<div class="pay__steps">
<h4 class="pay__sub-title">
扫码支付操作步骤
</h4>
<ol class="pay__step-list">
<li v-for="(step, index) in steps" :key="step" class="pay__step">
<span class="pay__step-index">{{ index + 1 }}</span>
<span>{{ step }}</span>
</li>
</ol>
</div>
<div class="pay__detail">
@@ -123,18 +136,13 @@ onMounted(() => {
</ul>
</div>
<div class="pay__steps">
<h4 class="pay__sub-title">
扫码支付操作步骤
</h4>
<ol class="pay__step-list">
<li v-for="(step, index) in steps" :key="step" class="pay__step">
<span class="pay__step-index">{{ index + 1 }}</span>
<span>{{ step }}</span>
</li>
</ol>
<p class="pay__safe">
安全提示:本页面已通过安全验证,请勿向他人泄露付款码
</p>
</section>
</div>
<!-- 设计 33:操作按钮在大卡右下方 -->
<div class="pay__footer">
<AppButton type="primary" size="lg" @click="onPaid">
完成支付
@@ -143,8 +151,6 @@ onMounted(() => {
返回
</AppButton>
</div>
</section>
</div>
<PayMethodDialog
v-model:visible="dialogVisible"
@@ -156,136 +162,224 @@ onMounted(() => {
<style lang="less" scoped>
.pay {
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
width: 100%;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 33:面包屑 13 设计px → 11px,前缀灰、当前页深灰
&__breadcrumb {
margin-bottom: @spacing-base;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-disabled;
> span:last-child {
color: @text-color;
}
}
// 设计 33:整页单张大白卡,左中右三区
&__body {
.flex(row, flex-start);
gap: @spacing-base;
align-items: flex-start;
.flex(row, flex-start, flex-start);
gap: 24px;
padding: 24px 32px;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
&__left {
.flex(column, center, center);
gap: @spacing-base;
width: 320px;
flex-shrink: 0;
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
}
&__safe {
font-size: @font-size-sm;
text-align: center;
line-height: 1.6;
}
&__right {
flex: 1;
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
min-width: 0;
gap: @spacing-base;
}
// 左区顶行:渠道说明靠左、切换支付方式胶囊靠右(设计 33 右上角)
&__left-top {
.flex(row, space-between, center);
align-self: stretch;
gap: @spacing-base;
}
&__method {
font-size: 12px;
color: @text-color;
strong {
color: @primary-strong;
}
}
&__switch {
flex-shrink: 0;
}
:deep(.pay__switch.app-button--default) {
height: 24px;
padding: 0 10px;
border: 1px solid fade(@primary-strong, 30%);
background: fade(@primary-strong, 10%);
color: @primary-strong;
font-size: 11px;
&:hover {
border-color: @primary-strong;
background: fade(@primary-strong, 18%);
color: @primary-strong;
}
}
// 中区:支付金额标签 15 设计px → 12px,金额 34 设计px → 26px 粗体红
&__amount-block {
padding-bottom: @spacing-base;
border-bottom: 1px solid @border-color;
text-align: center;
}
&__amount-label {
font-size: @font-size-base;
font-size: 12px;
color: @text-color;
}
&__amount {
margin: @spacing-xs 0;
font-size: 32px;
font-weight: 600;
margin-top: 4px;
font-size: 26px;
font-weight: 700;
color: @danger-color;
line-height: 1.2;
}
&__method {
font-size: @font-size-base;
color: @text-color;
strong {
color: @primary-color;
}
// 二维码占位(QrCodePanel 内部压成设计稿的灰色方块)
:deep(.qr-panel__box) {
border: none;
background: @contract-qr-bg;
border-radius: @radius-base;
}
&__detail,
&__steps {
margin-top: @spacing-base;
// 倒计时行 → 浅红胶囊(设计 33「二维码将在 04:32 后失效」)
:deep(.qr-panel__status) {
font-size: 11px;
color: @danger-color;
background: fade(@danger-color, 8%);
border-radius: @radius-round;
padding: 5px 14px;
}
:deep(.qr-panel__count) {
color: @danger-color;
font-weight: 700;
}
// 右区:步骤 + 订单明细 + 安全提示(设计 33 右列 400 设计px ≈ 310px)
&__right {
flex: 0 0 310px;
display: flex;
flex-direction: column;
gap: @spacing-base;
}
&__sub-title {
margin-bottom: @spacing-sm;
font-size: @font-size-base;
font-weight: 600;
margin-bottom: 12px;
font-size: 15px;
font-weight: 700;
color: @heading-color;
// 「订单明细」小节按设计 33 降为 13 设计px → 11px
}
&__detail-list {
.flex(column, flex-start);
gap: @spacing-sm;
&__detail &__sub-title {
font-size: 11px;
}
&__detail-item {
.flex(row, flex-start, center);
gap: @spacing-base;
font-size: @font-size-base;
color: @heading-color;
}
&__detail-label {
width: 72px;
flex-shrink: 0;
}
&__detail-amount {
font-weight: 600;
color: @danger-color;
&__steps &__sub-title {
font-size: 15px;
}
// 三步指引:序号实底蓝圆 024FFF,步骤文字 14 设计px → 11px
&__step-list {
.flex(column, flex-start);
gap: @spacing-sm;
.flex(column, flex-start, stretch);
gap: 12px;
padding-left: 0;
list-style: none;
}
&__step {
.flex(row, flex-start, center);
.flex(row, flex-start, flex-start);
gap: @spacing-sm;
font-size: @font-size-base;
font-size: 11px;
line-height: 1.7;
color: @text-color;
}
&__step-index {
.flex(row, center);
width: 22px;
height: 22px;
width: 16px;
height: 16px;
margin-top: 1px;
border-radius: @radius-round;
background: @primary-light;
color: @primary-color;
font-size: @font-size-sm;
background: @primary-strong;
color: @white;
font-size: 11px;
font-weight: 700;
flex-shrink: 0;
}
&__footer {
// 订单明细:浅灰底板 + 白底行卡(设计 33 实取 #F7F8F9 / #FFFFFF)
&__detail-list {
.flex(column, flex-start, stretch);
gap: 6px;
margin: 0;
padding: 6px;
list-style: none;
border-radius: 6px;
background: @bg-color;
}
&__detail-item {
.flex(row, flex-start, center);
gap: @spacing-sm;
padding: 8px 10px;
border-radius: @radius-sm;
background: @white;
font-size: 11px;
color: @heading-color;
}
&__detail-label {
width: 56px;
flex-shrink: 0;
font-size: 11px;
}
&__detail-amount {
margin-left: auto;
font-weight: 700;
color: @danger-color;
}
// 安全提示横幅:浅绿底 + 绿字(设计 33 实取 #D2EEDC / #16A34A)
&__safe {
padding: 8px 12px;
border-radius: @radius-sm;
background: @finance-safe-bg;
color: @success-color;
font-size: 11px;
font-weight: 600;
line-height: 1.6;
}
// 卡下操作区:右对齐(设计 33 返回按钮在卡右下)
&__footer {
.flex(row, flex-end, center);
gap: @spacing-base;
margin-top: @spacing-lg;
padding-top: @spacing-base;
border-top: 1px solid @border-color;
margin-top: @spacing-base;
}
:deep(.app-button--primary) {
background: @primary-strong;
&:hover {
background: @primary-color;
}
}
}
</style>

View File

@@ -161,7 +161,7 @@ function onClose(): void {
z-index: 1000;
.flex(row, center);
padding: @spacing-base;
background: rgba(0, 0, 0, 0.45);
background: fade(@black, 45%);
&__panel {
.flex(column, flex-start, stretch);
@@ -248,28 +248,29 @@ function onClose(): void {
box-shadow: @shadow-base;
}
// tone 底色与首页快捷入口一致(按蓝湖设计稿采样)
&--purple {
background: #f0eaff;
background: @home-quick-purple;
}
&--green {
background: #e7f8ec;
background: @home-quick-green;
}
&--blue {
background: @primary-light;
background: @home-quick-peach;
}
&--amber {
background: #fff3e0;
background: @home-quick-pink;
}
&--red {
background: #ffeceb;
background: fade(@danger-color, 15%);
}
&--cyan {
background: #e4f6fa;
background: @home-quick-blue;
}
}

View File

@@ -78,6 +78,16 @@ onBeforeUnmount(stop)
>
›
</button>
<!-- 设计稿底部居中的指示条(长条=当前,圆点=其余) -->
<div class="home-banner__dots">
<span
v-for="(slide, index) in slides"
:key="`dot-${slide.id ?? index}`"
class="home-banner__dot"
:class="{ 'is-active': index === current }"
/>
</div>
</template>
</section>
</template>
@@ -85,11 +95,10 @@ onBeforeUnmount(stop)
<style lang="less" scoped>
.home-banner {
position: relative;
height: 240px;
// 设计稿头图通栏 1920×661 设计px → 高 509 CSS,紧贴顶栏无圆角
height: 509px;
overflow: hidden;
border-radius: @radius-lg;
background: @bg-color;
box-shadow: @shadow-base;
background: @home-banner-bg;
&__img {
display: block;
@@ -105,7 +114,7 @@ onBeforeUnmount(stop)
height: 32px;
transform: translateY(-50%);
border-radius: @radius-round;
background: rgba(31, 39, 51, 0.35);
background: fade(@black, 35%);
color: @white;
font-size: @font-size-xl;
line-height: 1;
@@ -124,5 +133,29 @@ onBeforeUnmount(stop)
&:hover &__arrow {
opacity: 1;
}
&__dots {
position: absolute;
bottom: 48px;
left: 50%;
transform: translateX(-50%);
.flex(row, center, center);
gap: 10px;
}
&__dot {
width: 4px;
height: 4px;
border-radius: @radius-round;
background: @home-banner-dot;
transition: width 0.2s;
// 当前页:设计稿 44×5 设计px 长条
&.is-active {
width: 34px;
height: 4px;
border-radius: @radius-round;
}
}
}
</style>

View File

@@ -30,10 +30,12 @@ defineProps<Props>()
<!-- TODO(蓝湖): 替换业务图标切图 -->
{{ line.name.slice(0, 2) }}
</span>
<!-- 设计稿卡片右上角选择圆环 -->
<span class="home-business__check" aria-hidden="true" />
</div>
<h4 class="home-business__name">
{{ line.name }}
</h4>
</div>
<p class="home-business__desc">
{{ line.desc }}
</p>
@@ -45,15 +47,25 @@ defineProps<Props>()
<style lang="less" scoped>
.home-business {
// 设计稿区块卡 1680×400 设计px:白底 + #E2E2E2 描边(内容区内左右缩 50 设计px)
max-width: 1294px;
margin-right: auto;
margin-left: auto;
padding: 34px 54px 40px;
border: 1px solid @home-section-border;
border-radius: @radius-lg;
background: @white;
&__head {
.flex(row, space-between);
margin-bottom: @spacing-base;
margin-bottom: 36px;
}
&__title {
font-size: @font-size-xl;
font-weight: 600;
color: @heading-color;
// 设计稿栏目标题 36 设计px / 700 / #121212
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__slogan {
@@ -63,111 +75,128 @@ defineProps<Props>()
&__grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: @spacing-base;
// 设计稿卡片间距 22 设计px ≈ 17 CSS
gap: 17px;
}
&__card {
.flex(column, flex-start);
gap: @spacing-base;
padding: @spacing-lg;
border-radius: @radius-lg;
background: @primary-light;
box-shadow: @shadow-base;
gap: 0;
// 设计稿业务卡 368×206 设计px:白底 / #999 描边 / 小圆角
padding: 22px 16px 6px;
border: 1px solid @home-business-border;
border-radius: @radius-base;
background: @white;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
box-shadow: @shadow-lg;
box-shadow: @shadow-base;
transform: translateY(-2px);
}
}
&__card-head {
.flex(row, flex-start);
gap: @spacing-sm;
.flex(row, space-between, flex-start);
width: 100%;
}
&__icon {
.flex(row, center);
flex-shrink: 0;
width: 40px;
height: 40px;
width: 44px;
height: 44px;
border-radius: @radius-base;
background: @white;
color: @primary-color;
font-size: @font-size-base;
background: transparent;
color: @primary-strong;
font-size: @font-size-lg;
font-weight: 600;
}
// 右上角选择圆环(31 设计px ≈ 24 CSS)
&__check {
position: relative;
flex-shrink: 0;
width: 24px;
height: 24px;
border: 1px solid @home-ring;
border-radius: @radius-round;
&::after {
content: '';
position: absolute;
inset: 0;
width: 14px;
height: 14px;
margin: auto;
border-radius: @radius-round;
background: @white;
opacity: 0;
}
}
&__name {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
margin-top: 16px;
// 设计稿卡片标题 28 设计px / 500 / #121212
font-size: @font-size-title;
font-weight: 500;
color: @home-ink;
}
&__desc {
min-height: 40px;
margin-top: 4px;
font-size: @font-size-sm;
color: @text-color-secondary;
font-weight: 500;
color: @home-ink;
.multi-ellipsis(2);
}
&__more {
align-self: flex-end;
margin-top: auto;
font-size: @font-size-sm;
color: @text-color-secondary;
transition: color 0.2s;
}
// 四类业务各自的主题色(与设计稿一致:卡片浅色底 + 同色系图标/文案)
// 设计稿:首张「互联网软件」为 #024FFF 选中实底 + 白字白环;其余白底描边
&__card--internet {
background: #e8f0ff;
border-color: @primary-strong;
background: @primary-strong;
.home-business__icon {
color: #3370ff;
color: @white;
}
.home-business__check {
border-color: @white;
&::after {
opacity: 1;
}
}
.home-business__name,
.home-business__desc,
.home-business__more {
color: #598bff;
color: @white;
}
}
&__card--hardware {
background: #e7f8ec;
.home-business__icon {
color: #22b14c;
}
.home-business__desc,
.home-business__more {
color: #34c724;
color: @tag-hardware;
}
}
&__card--iot {
background: #f0eaff;
.home-business__icon {
color: #7c4dff;
}
.home-business__desc,
.home-business__more {
color: #9a7bff;
color: @tag-iot;
}
}
&__card--manufacturing {
background: #fff2e4;
.home-business__icon {
color: #ff8f1f;
}
.home-business__desc,
.home-business__more {
color: #ffa94d;
color: @tag-manufacturing;
}
}
}

View File

@@ -85,71 +85,99 @@ function switchCategory(value: BusinessType | 'all'): void {
<style lang="less" scoped>
.home-cases {
// 设计稿区块卡 1680×446 设计px:白底 + #E2E2E2 描边(内容区内左右缩 50 设计px)
max-width: 1294px;
margin-right: auto;
margin-left: auto;
padding: 32px 54px 44px;
border: 1px solid @home-section-border;
border-radius: @radius-lg;
background: @white;
&__head {
.flex(row, space-between);
gap: @spacing-base;
margin-bottom: @spacing-base;
.flex(row, flex-start);
gap: 20px;
margin-bottom: 36px;
}
&__title {
font-size: @font-size-xl;
font-weight: 600;
color: @heading-color;
// 设计稿栏目标题 36 设计px / 700 / #121212
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__tabs {
.flex(row, center);
flex: 1;
gap: @spacing-sm;
// 设计稿分类紧跟标题左侧排布(间距 36 设计px ≈ 28)
gap: 28px;
}
&__tab {
height: 30px;
padding: 0 @spacing-base;
border-radius: @radius-round;
background: @white;
color: @text-color;
position: relative;
height: auto;
padding: 0;
border: 0;
background: transparent;
// 设计稿分类 16 设计px / 500 / #121212(激活 #085DFF + 下划线)
color: @home-ink;
font-size: @font-size-sm;
transition: all 0.2s;
font-weight: 500;
transition: color 0.2s;
&.is-active {
background: transparent;
color: @home-tab-active;
// 设计稿激活下划线 29×2 设计px(#1F67EF)
&::after {
content: '';
position: absolute;
right: 0;
bottom: -6px;
left: 0;
height: 2px;
background: @primary-color;
color: @white;
}
}
}
&__more {
font-size: @font-size-base;
margin-left: auto;
font-size: @font-size-sm;
}
&__grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: @spacing-base;
// 设计稿案例卡间距 24 设计px ≈ 18 CSS
gap: 18px;
}
&__card {
overflow: hidden;
border-radius: @radius-lg;
// 设计稿案例卡 368×248 设计px:白底 + #E0DEDE 描边 + 0 4 10 黑 8% 投影
border: 1px solid @home-case-border;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
box-shadow: 0 4px 10px fade(@black, 8%);
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
box-shadow: @shadow-lg;
box-shadow: 0 6px 14px fade(@black, 12%);
transform: translateY(-2px);
.home-cases__view {
background: @primary-color;
color: @white;
color: @primary-color;
}
}
}
&__cover {
position: relative;
height: 130px;
// 设计稿封面区 128 设计px 高 ≈ 99 CSS
height: 100px;
overflow: hidden;
}
@@ -171,43 +199,46 @@ function switchCategory(value: BusinessType | 'all'): void {
border-radius: @radius-sm;
background: @primary-color;
color: @white;
font-size: @font-size-sm;
font-size: 11px;
&--hardware {
background: #22b14c;
background: @tag-hardware;
}
&--iot {
background: #7c4dff;
background: @tag-iot;
}
&--manufacturing {
background: #ff8f1f;
background: @tag-manufacturing;
}
&--other {
background: @text-color-secondary;
background: @tag-other;
}
}
&__body {
padding: @spacing-base;
padding: 12px 15px 6px;
}
&__name {
margin-bottom: @spacing-sm;
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
margin-bottom: 8px;
// 设计稿案例名 16 设计px / 500 / #333333
font-size: @font-size-sm;
font-weight: 500;
color: @home-body;
.multi-ellipsis(1);
}
&__meta {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4px @spacing-sm;
font-size: @font-size-sm;
color: @text-color-secondary;
// 设计稿元信息 10 设计px → 可读下限 11px / #333333
gap: 3px @spacing-sm;
font-size: 11px;
line-height: 1.5;
color: @home-body;
li {
.ellipsis();
@@ -217,13 +248,13 @@ function switchCategory(value: BusinessType | 'all'): void {
&__view {
display: block;
width: fit-content;
margin: @spacing-base 0 0 auto;
padding: 2px @spacing-base;
border: 1px solid @primary-color;
border-radius: @radius-sm;
color: @primary-color;
margin: 10px 0 0 auto;
padding: 0;
border: 0;
// 设计稿「查看详情>」12 设计px / #024FFF(无按钮描边)
color: @primary-strong;
font-size: @font-size-sm;
transition: all 0.2s;
transition: color 0.2s;
}
}
</style>

View File

@@ -87,14 +87,16 @@ function onMore(): void {
<style lang="less" scoped>
.home-quick {
position: relative;
.flex(column, flex-start, stretch);
flex-shrink: 0;
width: 320px;
gap: @spacing-base;
padding: @spacing-lg;
// 设计稿右卡 722×245 设计px → 556 宽;白底 + 浅灰描边
width: 556px;
gap: 0;
padding: 14px 31px 21px;
border: 1px solid @home-card-border;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
&__head {
.flex(row, flex-start);
@@ -102,25 +104,28 @@ function onMore(): void {
}
&__head-icon {
color: @heading-color;
font-size: @font-size-lg;
color: @home-ink;
font-size: @font-size-xl;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
// 设计稿卡内标题 36 设计px / 700 / #121212
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__list {
.flex(row, space-between, flex-start);
gap: @spacing-sm;
.flex(row, flex-start, flex-start);
// 设计稿入口间距 127 设计px(图标 90 + 间隙 37)≈ 70 + 28
gap: 28px;
margin-top: 16px;
}
&__item {
.flex(column, flex-start, center);
gap: @spacing-sm;
flex: 1;
gap: 8px;
flex: none;
transition: transform 0.2s;
&:hover {
@@ -130,55 +135,63 @@ function onMore(): void {
&__icon {
.flex(row, center);
width: 44px;
height: 44px;
// 设计稿图标块 90×90 设计px ≈ 70 CSS
width: 70px;
height: 70px;
border-radius: @radius-base;
font-size: @font-size-xl;
font-size: 28px;
// 底色按设计稿采样(tone → 设计稿色)
&--amber {
background: #fff3e0;
background: @home-quick-pink;
}
&--blue {
background: @primary-light;
background: @home-quick-peach;
}
&--green {
background: #e7f8ec;
background: @home-quick-green;
}
&--purple {
background: #f0eaff;
background: @home-quick-purple;
}
&--red {
background: #ffeceb;
background: fade(@danger-color, 15%);
}
&--cyan {
background: #e4f6fa;
background: @home-quick-blue;
}
}
&__img {
width: 24px;
height: 24px;
width: 32px;
height: 32px;
object-fit: contain;
}
&__label {
font-size: @font-size-sm;
color: @text-color;
// 设计稿入口文字 18 设计px / 500 / #121212
font-size: @font-size-base;
font-weight: 500;
color: @home-ink;
text-align: center;
}
&__more {
align-self: flex-end;
// 设计稿「更多」箭头位于卡片右侧垂直居中
position: absolute;
top: 50%;
right: 31px;
padding: 0;
border: 0;
transform: translateY(-50%);
background: transparent;
font-size: @font-size-sm;
color: @text-color-secondary;
color: @home-ring;
cursor: pointer;
}
}

View File

@@ -29,11 +29,11 @@ defineProps<Props>()
<style lang="less" scoped>
.home-contents {
&__block {
margin-bottom: @spacing-lg;
padding: @spacing-lg @spacing-xl;
// 设计稿区块卡 1780×593 设计px:白底、无描边投影
margin-bottom: @spacing-base;
padding: 24px 32px 32px;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
&:last-child {
margin-bottom: 0;
@@ -41,30 +41,18 @@ defineProps<Props>()
}
&__title {
position: relative;
margin-bottom: @spacing-base;
padding-left: @spacing-sm;
font-size: @font-size-xl;
font-weight: 600;
color: @heading-color;
&::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 3px;
height: 16px;
border-radius: @radius-round;
background: @primary-color;
transform: translateY(-50%);
}
// 设计稿栏目标题 36 设计px / 700 / #121212(无竖条)
margin-bottom: 36px;
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__rich {
// 设计稿正文 16 设计px / #222222
font-size: @font-size-sm;
line-height: 1.9;
color: @text-color;
line-height: 1.8;
color: @home-paragraph;
word-break: break-word;
:deep(p) {
@@ -85,7 +73,8 @@ defineProps<Props>()
:deep(video) {
display: block;
max-width: 100%;
margin: 0 auto @spacing-base;
// 设计稿视频/图片通栏贴卡内边距,圆角与卡片呼应
margin: 0 auto @spacing-lg;
border-radius: @radius-base;
}
@@ -96,7 +85,7 @@ defineProps<Props>()
margin: @spacing-base 0 @spacing-sm;
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
color: @home-ink;
}
:deep(table) {

View File

@@ -44,54 +44,65 @@ function isImageIcon(icon?: string): boolean {
<style lang="less" scoped>
.home-service-types {
margin-bottom: @spacing-lg;
padding: @spacing-lg @spacing-xl;
// 设计稿区块卡 1780×287 设计px:白底、无描边投影
margin-bottom: @spacing-base;
padding: 18px 32px 24px;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
&__title {
position: relative;
margin-bottom: @spacing-lg;
padding-left: @spacing-sm;
font-size: @font-size-xl;
font-weight: 600;
color: @heading-color;
&::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 3px;
height: 16px;
border-radius: @radius-round;
background: @primary-color;
transform: translateY(-50%);
}
// 设计稿栏目标题 36 设计px / 700 / #121212(无竖条)
margin-bottom: 40px;
font-size: @font-size-xxl;
font-weight: 700;
color: @home-ink;
}
&__list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
gap: @spacing-lg @spacing-base;
.flex(row, flex-start);
gap: 0;
}
&__item {
.flex(column, center);
gap: @spacing-sm;
// 设计稿条目横向间距 182 设计px → 定宽 140 居中
width: 140px;
// 设计稿圆底(550..618)与文字(665)之间 41 设计px ≈ 32 CSS
gap: 32px;
}
&__icon {
.flex(row, center);
width: 56px;
height: 56px;
border-radius: @radius-base;
// 设计稿为 60 设计px 彩色圆底 + 白色图形
width: 52px;
height: 52px;
border-radius: @radius-round;
background: @primary-light;
color: @primary-color;
font-size: @font-size-lg;
color: @white;
font-size: @font-size-xl;
font-weight: 600;
overflow: hidden;
// 每类业务圆底色按设计稿采样(顺序:Web应用/小程序/APP/二次开发/桌面工具)
.home-service-types__item:nth-child(1) & {
background: @home-service-web;
}
.home-service-types__item:nth-child(2) & {
background: @home-service-mp;
}
.home-service-types__item:nth-child(3) & {
background: @home-service-app;
}
.home-service-types__item:nth-child(4) & {
background: @home-service-dev;
}
.home-service-types__item:nth-child(5) & {
background: @home-service-pc;
}
}
&__img {
@@ -101,8 +112,9 @@ function isImageIcon(icon?: string): boolean {
}
&__label {
// 设计稿条目文字 16 设计px / #333333
font-size: @font-size-sm;
color: @text-color;
color: @home-body;
text-align: center;
.ellipsis();
}

View File

@@ -31,26 +31,33 @@ const items = [
<style lang="less" scoped>
.home-stats {
.flex(row, flex-end);
gap: @spacing-base;
// 设计稿方块间距 30 设计px ≈ 23 CSS
gap: 23px;
&__item {
.flex(column, center, center);
gap: @spacing-xs;
min-width: 84px;
padding: @spacing-base;
border-radius: @radius-lg;
background: rgba(255, 255, 255, 0.92);
gap: 0;
// 设计稿统计方块 112×112 设计px → 86×86 CSS,#024FFF 实底
width: 86px;
height: 86px;
min-width: 86px;
padding: 0;
border-radius: @radius-sm;
background: @primary-strong;
}
&__value {
font-size: @font-size-xxl;
font-weight: 600;
color: @primary-color;
// 设计稿数字 48 设计px / 500 / 白
font-size: 37px;
font-weight: 500;
line-height: 1.2;
color: @white;
}
&__label {
font-size: @font-size-sm;
color: @text-color-secondary;
font-weight: 500;
color: @white;
}
}
</style>

View File

@@ -37,23 +37,26 @@ const greeting = computed(() => {
&__greeting {
.flex(row, flex-start);
gap: @spacing-sm;
font-size: @font-size-xxl;
font-weight: 600;
color: @white;
// 设计稿「中午好」52 设计px / 700 / #2C2C2C
font-size: 40px;
font-weight: 700;
color: @home-welcome;
}
&__wave {
.flex(row, center);
width: 32px;
height: 32px;
width: 36px;
height: 36px;
border-radius: @radius-round;
background: rgba(255, 255, 255, 0.25);
background: fade(@black, 4%);
font-size: @font-size-lg;
}
&__summary {
font-size: @font-size-lg;
color: rgba(255, 255, 255, 0.9);
// 设计稿副文案 24 设计px / 400 / #2C2C2C
font-size: 18px;
font-weight: 400;
color: @home-welcome;
}
}
</style>

View File

@@ -73,44 +73,55 @@ onMounted(load)
padding-bottom: @spacing-xxl;
&__breadcrumb {
margin-bottom: @spacing-base;
font-size: @font-size-base;
margin-bottom: 36px;
// 设计稿面包屑 24 设计px / 500 / #666666
font-size: 18px;
font-weight: 500;
color: @home-breadcrumb;
.link {
color: @home-breadcrumb;
}
}
// 设计稿头图卡 1780×219 设计px:浅蓝渐变底、左上图标块 + 标题 + 副标题
&__hero {
.flex(row, flex-start);
gap: @spacing-base;
margin-bottom: @spacing-xl;
padding: @spacing-xl;
.flex(column, flex-start);
gap: 18px;
margin-bottom: @spacing-base;
padding: 19px 22px 24px;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
background: @home-detail-hero-bg;
}
&__logo {
.flex(row, center);
width: 56px;
height: 56px;
width: 62px;
height: 62px;
border-radius: @radius-lg;
background: @primary-light;
color: @primary-color;
background: @home-detail-logo-bg;
color: @primary-strong;
font-size: @font-size-xl;
font-weight: 600;
}
&__intro {
.flex(column, flex-start);
gap: @spacing-xs;
gap: 6px;
}
&__name {
font-size: @font-size-xxl;
// 设计稿详情标题 26 设计px / #333333
font-size: @font-size-xl;
font-weight: 600;
color: @heading-color;
color: @home-body;
}
&__slogan {
font-size: @font-size-base;
// 设计稿副标题 14 设计px → 可读下限 11px / #333333
font-size: 11px;
font-weight: 400;
color: @home-body;
}
&__cta {

View File

@@ -27,9 +27,8 @@ onMounted(() => {
<template>
<div class="home">
<div class="container">
<!-- 设计稿头图为通栏(0..1920),故不包 .container -->
<HomeBanner :banners="banners" />
</div>
<div class="container home__dashboard">
<section class="home__dashboard-main">
@@ -55,23 +54,30 @@ onMounted(() => {
<style lang="less" scoped>
.home {
.flex(column, flex-start);
gap: @spacing-xl;
padding-top: @spacing-xl;
// 设计稿区块间距 19~20 设计px ≈ 16 CSS;头图紧贴顶栏
gap: @spacing-base;
padding-top: 0;
padding-bottom: @spacing-xxl;
&__dashboard {
.flex(row, space-between, stretch);
gap: @spacing-base;
// 设计稿左右卡间距 36 设计px ≈ 28 CSS
gap: 28px;
// 设计稿区块行 1680 设计px 宽(内容区内左右各缩 50 设计px)≈ 1294 CSS
max-width: 1326px;
margin-right: auto;
margin-left: auto;
}
&__dashboard-main {
.flex(row, space-between, center);
flex: 1;
gap: @spacing-lg;
padding: @spacing-xl;
// 设计稿欢迎卡(120,754,922,245):白底 + 浅灰描边,内边距 61/106/66/73 设计px
padding: 46px 56px 46px 82px;
border: 1px solid @home-card-border;
border-radius: @radius-lg;
background: linear-gradient(120deg, @primary-color, #6a5cff);
box-shadow: @shadow-base;
background: @white;
}
}
</style>

View File

@@ -54,7 +54,7 @@ const localAgree = computed({
</div>
<label class="login-form__agree">
<input v-model="localAgree" type="checkbox">
<span>已阅读并同意《用户协议》和《隐私政策》</span>
<span>已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<button class="login-form__submit" type="submit">
登 录
@@ -65,55 +65,64 @@ const localAgree = computed({
<style lang="less" scoped>
.login-form {
.flex(column, flex-start);
gap: @spacing-base;
gap: @spacing-lg;
&__field {
width: 100%;
}
// 设计稿:输入框 40 设计px ≈ 32px 高、13 设计px 字号(可读下限 11px)、白底浅描边
&__input {
width: 100%;
height: 44px;
padding: 0 @spacing-base;
height: 32px;
padding: 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @text-color-secondary;
color: @heading-color;
}
}
&__agree {
.flex(row, flex-start);
gap: @spacing-xs;
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
margin-top: 2px;
accent-color: @primary-color;
margin-top: 1px;
accent-color: @primary-strong;
}
// 设计稿:《用户协议》《隐私政策》为强调蓝,其余为次级灰
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计稿:登录按钮 44 设计px ≈ 34px 高、#024FFF 实底
&__submit {
width: 100%;
height: 44px;
height: 34px;
border: none;
border-radius: @radius-base;
background: @primary-color;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: @font-size-lg;
font-size: 12px;
font-weight: 500;
letter-spacing: 2px;
cursor: pointer;
transition: background 0.2s;

View File

@@ -73,7 +73,7 @@ function onSubmit(): void {
</div>
<label class="sms-login__agree">
<input v-model="localAgree" type="checkbox">
<span>已阅读并同意《用户协议》和《隐私政策》</span>
<span>已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<button class="sms-login__submit" type="submit">
登 录
@@ -84,55 +84,64 @@ function onSubmit(): void {
<style lang="less" scoped>
.sms-login {
.flex(column, flex-start);
gap: @spacing-base;
gap: @spacing-lg;
&__field {
width: 100%;
}
// 设计稿:输入框 40 设计px ≈ 32px 高、13 设计px 字号(可读下限 11px)、白底浅描边
&__input {
width: 100%;
height: 44px;
padding: 0 @spacing-base;
height: 32px;
padding: 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @text-color-secondary;
color: @heading-color;
}
}
&__agree {
.flex(row, flex-start);
gap: @spacing-xs;
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
margin-top: 2px;
accent-color: @primary-color;
margin-top: 1px;
accent-color: @primary-strong;
}
// 设计稿:《用户协议》《隐私政策》为强调蓝,其余为次级灰
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计稿:登录按钮 44 设计px ≈ 34px 高、#024FFF 实底
&__submit {
width: 100%;
height: 44px;
height: 34px;
border: none;
border-radius: @radius-base;
background: @primary-color;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: @font-size-lg;
font-size: 12px;
font-weight: 500;
letter-spacing: 2px;
cursor: pointer;
transition: background 0.2s;

View File

@@ -89,13 +89,7 @@ async function onGetCode(target: string): Promise<void> {
<main class="auth-page__main">
<div class="auth-page__card">
<div class="auth-page__tabs">
<button
class="auth-page__tab"
:class="{ 'is-active': activeTab === 'account' }"
@click="activeTab = 'account'"
>
账号密码登录
</button>
<!-- 设计稿 Tab 顺序:手机验证码登录在前、账号密码登录在后 -->
<button
class="auth-page__tab"
:class="{ 'is-active': activeTab === 'sms' }"
@@ -103,6 +97,13 @@ async function onGetCode(target: string): Promise<void> {
>
手机验证码登录
</button>
<button
class="auth-page__tab"
:class="{ 'is-active': activeTab === 'account' }"
@click="activeTab = 'account'"
>
账号密码登录
</button>
</div>
<LoginForm
@@ -131,48 +132,59 @@ async function onGetCode(target: string): Promise<void> {
<style lang="less" scoped>
.auth-page {
position: relative;
display: flex;
min-height: 100vh;
background: @bg-color;
// 设计稿:右侧表单区为纯白底,无卡片描边/阴影
background: @white;
&__brand {
flex: 0 0 44%;
.flex(row, center, center);
background: linear-gradient(135deg, @primary-color 0%, #1b4fd8 100%);
// 设计稿:左侧品牌渐变面板约占 786/1920 ≈ 41%
flex: 0 0 41%;
.flex(row, flex-start, stretch);
background: linear-gradient(135deg, @auth-gradient-from 0%, @auth-gradient-to 100%);
color: @white;
}
&__brand-inner {
.flex(column, flex-start);
gap: @spacing-lg;
padding: @spacing-xxl;
.flex(column, space-between, flex-start);
width: 100%;
// 设计稿:文字列起点 x=257 ≈ 面板宽 32.7%;主标距顶 ≈ 28%、标语底边距底 ≈ 30%
padding: 26vh 48px 30vh 32%;
}
&__logo {
font-size: 32px;
font-size: 31px;
font-weight: 700;
letter-spacing: 2px;
line-height: 1.4;
line-height: 1.45;
// 设计稿文本框 432 设计px:定宽让 11 字在「虫子智造研发 / 一体化平台」处折行
max-width: 200px;
}
&__slogan {
font-size: @font-size-xl;
opacity: 0.85;
letter-spacing: 6px;
font-size: 17px;
font-weight: 600;
letter-spacing: 8px;
}
// 设计稿:「游客模式」为右上角白底上的深色纯文本,无边框
&__guest {
margin-top: @spacing-xl;
padding: @spacing-sm @spacing-base;
border: 1px solid rgba(255, 255, 255, 0.6);
border-radius: @radius-base;
color: @white;
font-size: @font-size-base;
position: absolute;
top: 18px;
right: 16px;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
color: @heading-color;
font-size: 11px;
text-decoration: none;
transition: background 0.2s;
transition: color 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.15);
background: transparent;
color: @primary-strong;
}
}
@@ -184,46 +196,48 @@ async function onGetCode(target: string): Promise<void> {
&__card {
.flex(column, flex-start);
gap: @spacing-lg;
// 设计稿:表单列宽 688 设计px ≈ 530px,标题/Tab/输入/按钮纵向节奏 ≈ 41px
gap: 41px;
width: 100%;
max-width: 420px;
padding: @spacing-xl @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
max-width: 530px;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
&__tabs {
.flex(row, center);
gap: @spacing-lg;
border-bottom: 1px solid @border-color;
// 设计稿:Tab 左对齐于表单列,仅激活项带 2px 蓝色下划线(无整行分隔线)
.flex(row, flex-start);
gap: @spacing-sm;
border-bottom: none;
}
&__tab {
padding: @spacing-sm 0;
padding: 0 0 4px;
border: none;
border-bottom: 2px solid transparent;
background: transparent;
font-size: @font-size-lg;
color: @text-color-secondary;
font-size: 11px;
color: @text-color;
cursor: pointer;
transition: all 0.2s;
&.is-active {
border-bottom-color: @primary-color;
color: @primary-color;
border-bottom-color: @primary-strong;
color: @primary-strong;
font-weight: 600;
}
}
&__switch {
text-align: center;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-secondary;
}
&__link {
color: @primary-color;
color: @primary-strong;
&:hover {
color: @primary-hover;

View File

@@ -103,7 +103,7 @@ onBeforeUnmount(() => {
>
<label class="auth-page__agree">
<input v-model="agree" type="checkbox">
<span>已阅读并同意《用户协议》和《隐私政策》</span>
<span>已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<button class="auth-page__submit" type="submit">
注 册
@@ -120,48 +120,59 @@ onBeforeUnmount(() => {
<style lang="less" scoped>
.auth-page {
position: relative;
display: flex;
min-height: 100vh;
background: @bg-color;
// 设计稿:右侧表单区为纯白底,无卡片描边/阴影
background: @white;
&__brand {
flex: 0 0 44%;
.flex(row, center, center);
background: linear-gradient(135deg, @primary-color 0%, #1b4fd8 100%);
// 设计稿:左侧品牌渐变面板约占 786/1920 ≈ 41%
flex: 0 0 41%;
.flex(row, flex-start, stretch);
background: linear-gradient(135deg, @auth-gradient-from 0%, @auth-gradient-to 100%);
color: @white;
}
&__brand-inner {
.flex(column, flex-start);
gap: @spacing-lg;
padding: @spacing-xxl;
.flex(column, space-between, flex-start);
width: 100%;
// 设计稿:文字列起点 x=257 ≈ 面板宽 32.7%;主标距顶 ≈ 28%、标语底边距底 ≈ 30%
padding: 26vh 48px 30vh 32%;
}
&__logo {
font-size: 32px;
font-size: 31px;
font-weight: 700;
letter-spacing: 2px;
line-height: 1.4;
line-height: 1.45;
// 设计稿文本框 432 设计px:定宽让 11 字在「虫子智造研发 / 一体化平台」处折行
max-width: 200px;
}
&__slogan {
font-size: @font-size-xl;
opacity: 0.85;
letter-spacing: 6px;
font-size: 17px;
font-weight: 600;
letter-spacing: 8px;
}
// 设计稿:「游客模式」为右上角白底上的深色纯文本,无边框
&__guest {
margin-top: @spacing-xl;
padding: @spacing-sm @spacing-base;
border: 1px solid rgba(255, 255, 255, 0.6);
border-radius: @radius-base;
color: @white;
font-size: @font-size-base;
position: absolute;
top: 18px;
right: 16px;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
color: @heading-color;
font-size: 11px;
text-decoration: none;
transition: background 0.2s;
transition: color 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.15);
background: transparent;
color: @primary-strong;
}
}
@@ -173,76 +184,89 @@ onBeforeUnmount(() => {
&__card {
.flex(column, flex-start);
gap: @spacing-base;
// 设计稿:表单列宽 688 设计px ≈ 530px,标题/输入/按钮纵向节奏 ≈ 41px
gap: 41px;
width: 100%;
max-width: 420px;
padding: @spacing-xl @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
max-width: 530px;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
// 设计稿:标题(34 设计px ≈ 26px)到首个输入框 ≈ 62px
&__title {
font-size: @font-size-xl;
font-weight: 600;
margin-bottom: 21px;
font-size: 26px;
font-weight: 700;
color: @heading-color;
}
&__form {
.flex(column, flex-start);
gap: @spacing-base;
gap: @spacing-lg;
width: 100%;
}
// 设置密码 → 密码强度条 ≈ 9px,强度条 → 提示 ≈ 9px(组件内)
&__pwd-wrap {
.flex(column, flex-start);
gap: @spacing-xs;
gap: 9px;
width: 100%;
}
// 设计稿:输入框 40 设计px ≈ 32px 高、13 设计px 字号(可读下限 11px)、白底浅描边
&__input {
width: 100%;
height: 44px;
padding: 0 @spacing-base;
height: 32px;
padding: 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @text-color-secondary;
color: @heading-color;
}
}
&__agree {
.flex(row, flex-start);
gap: @spacing-xs;
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
margin-top: 2px;
accent-color: @primary-color;
margin-top: 1px;
accent-color: @primary-strong;
}
// 设计稿:《用户协议》《隐私政策》为强调蓝,其余为次级灰
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计稿:注册按钮 44 设计px ≈ 34px 高、#024FFF 实底
&__submit {
width: 100%;
height: 44px;
height: 34px;
border: none;
border-radius: @radius-base;
background: @primary-color;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: @font-size-lg;
font-size: 12px;
font-weight: 500;
letter-spacing: 2px;
cursor: pointer;
transition: background 0.2s;
@@ -252,14 +276,16 @@ onBeforeUnmount(() => {
}
}
// 设计稿:按钮 → 底部切换链接仅约 13px
&__switch {
margin-top: -26px;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-secondary;
}
&__link {
color: @primary-color;
color: @primary-strong;
&:hover {
color: @primary-hover;

View File

@@ -118,7 +118,7 @@ onBeforeUnmount(() => {
>
<label class="auth-page__agree">
<input v-model="agree" type="checkbox">
<span>已阅读并同意《用户协议》和《隐私政策》</span>
<span>已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<button class="auth-page__submit" type="submit">
确认修改
@@ -135,48 +135,59 @@ onBeforeUnmount(() => {
<style lang="less" scoped>
.auth-page {
position: relative;
display: flex;
min-height: 100vh;
background: @bg-color;
// 设计稿:右侧表单区为纯白底,无卡片描边/阴影
background: @white;
&__brand {
flex: 0 0 44%;
.flex(row, center, center);
background: linear-gradient(135deg, @primary-color 0%, #1b4fd8 100%);
// 设计稿:左侧品牌渐变面板约占 786/1920 ≈ 41%
flex: 0 0 41%;
.flex(row, flex-start, stretch);
background: linear-gradient(135deg, @auth-gradient-from 0%, @auth-gradient-to 100%);
color: @white;
}
&__brand-inner {
.flex(column, flex-start);
gap: @spacing-lg;
padding: @spacing-xxl;
.flex(column, space-between, flex-start);
width: 100%;
// 设计稿:文字列起点 x=257 ≈ 面板宽 32.7%;主标距顶 ≈ 28%、标语底边距底 ≈ 30%
padding: 26vh 48px 30vh 32%;
}
&__logo {
font-size: 32px;
font-size: 31px;
font-weight: 700;
letter-spacing: 2px;
line-height: 1.4;
line-height: 1.45;
// 设计稿文本框 432 设计px:定宽让 11 字在「虫子智造研发 / 一体化平台」处折行
max-width: 200px;
}
&__slogan {
font-size: @font-size-xl;
opacity: 0.85;
letter-spacing: 6px;
font-size: 17px;
font-weight: 600;
letter-spacing: 8px;
}
// 设计稿:「游客模式」为右上角白底上的深色纯文本,无边框
&__guest {
margin-top: @spacing-xl;
padding: @spacing-sm @spacing-base;
border: 1px solid rgba(255, 255, 255, 0.6);
border-radius: @radius-base;
color: @white;
font-size: @font-size-base;
position: absolute;
top: 18px;
right: 16px;
margin: 0;
padding: 0;
border: none;
border-radius: 0;
color: @heading-color;
font-size: 11px;
text-decoration: none;
transition: background 0.2s;
transition: color 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.15);
background: transparent;
color: @primary-strong;
}
}
@@ -188,70 +199,82 @@ onBeforeUnmount(() => {
&__card {
.flex(column, flex-start);
gap: @spacing-base;
// 设计稿:表单列宽 688 设计px ≈ 530px,标题/输入/按钮纵向节奏 ≈ 41px
gap: 41px;
width: 100%;
max-width: 420px;
padding: @spacing-xl @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
max-width: 530px;
padding: 0;
border-radius: 0;
background: transparent;
box-shadow: none;
}
// 设计稿:标题(34 设计px ≈ 26px)到首个输入框 ≈ 62px
&__title {
font-size: @font-size-xl;
font-weight: 600;
margin-bottom: 21px;
font-size: 26px;
font-weight: 700;
color: @heading-color;
}
&__form {
.flex(column, flex-start);
gap: @spacing-base;
gap: @spacing-lg;
width: 100%;
}
// 设计稿:输入框 40 设计px ≈ 32px 高、13 设计px 字号(可读下限 11px)、白底浅描边
&__input {
width: 100%;
height: 44px;
padding: 0 @spacing-base;
height: 32px;
padding: 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
border-radius: 6px;
background: @white;
font-size: 11px;
color: @heading-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @text-color-secondary;
color: @heading-color;
}
}
&__agree {
.flex(row, flex-start);
gap: @spacing-xs;
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
margin-top: 2px;
accent-color: @primary-color;
margin-top: 1px;
accent-color: @primary-strong;
}
// 设计稿:《用户协议》《隐私政策》为强调蓝,其余为次级灰
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计稿:确认修改按钮 44 设计px ≈ 34px 高、#024FFF 实底
&__submit {
width: 100%;
height: 44px;
height: 34px;
border: none;
border-radius: @radius-base;
background: @primary-color;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: @font-size-lg;
font-size: 12px;
font-weight: 500;
letter-spacing: 2px;
cursor: pointer;
transition: background 0.2s;
@@ -261,14 +284,16 @@ onBeforeUnmount(() => {
}
}
// 设计稿:按钮 → 底部切换链接仅约 13px
&__switch {
margin-top: -26px;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
color: @text-color-secondary;
}
&__link {
color: @primary-color;
color: @primary-strong;
&:hover {
color: @primary-hover;

View File

@@ -41,10 +41,10 @@ const emojiMap: Record<MessageType, string> = {
<style lang="less" scoped>
.message-item {
position: relative; // 未读徽标相对行定位(压图标右上角)
.flex(row, flex-start);
gap: @spacing-base;
padding: @spacing-base;
border-radius: @radius-base;
gap: @spacing-base; // 图标→标题 22 × 0.77
padding: 14px 17px; // 行内边距 23/22 × 0.77
background: @white;
cursor: pointer;
transition: background 0.2s;
@@ -53,17 +53,24 @@ const emojiMap: Record<MessageType, string> = {
background: @bg-color-light;
}
// 类型图标圆:设计 43 直径 40 × 0.77,实取 #3B82F6
&__emoji {
flex-shrink: 0;
font-size: @font-size-xl;
line-height: 1.4;
.flex(row, center);
width: 31px;
height: 31px;
border-radius: @radius-round;
background: @message-icon-bg;
font-size: 15px;
line-height: 1;
}
&__body {
.flex(column, flex-start);
gap: @spacing-xs;
.flex(column, flex-start, stretch);
gap: 5px; // 标题→摘要 6 × 0.77
flex: 1;
min-width: 0;
margin-top: 6px; // 标题比图标顶下移 9 × 0.77
}
&__head {
@@ -72,27 +79,33 @@ const emojiMap: Record<MessageType, string> = {
width: 100%;
}
// 设计 43:标题 14 → 可读下限 11 / 600 / #1F2937(所有行均半粗)
&__title {
font-size: @font-size-lg;
font-size: 11px;
font-weight: 600;
color: @heading-color;
.ellipsis();
}
&__time {
flex-shrink: 0;
font-size: @font-size-sm;
font-size: 11px; // 设计 12 → 可读下限 11
color: @text-color-disabled; // 设计 43 时间 @text-color-disabled(覆盖 text-secondary)
}
// 设计 43:摘要 12 → 可读下限 11 / #6B7280(text-secondary)
&__summary {
font-size: @font-size-base;
font-size: 11px;
.ellipsis();
}
// 未读徽标:设计 43 红圆压图标右上(≈ 直径 20 × 0.77)
&__dot {
flex-shrink: 0;
align-self: center;
width: 8px;
height: 8px;
position: absolute;
top: 12px;
left: 42px;
width: 15px;
height: 15px;
border-radius: @radius-round;
background: @danger-color;
}

View File

@@ -29,16 +29,22 @@ const emit = defineEmits<{ view: [id: string] }>()
<style lang="less" scoped>
.message-list {
.flex(column, flex-start);
gap: @spacing-sm;
padding: @spacing-sm;
border-radius: @radius-lg;
background: @bg-color;
.flex(column, flex-start, stretch);
gap: 0; // 行紧排,行间以分割线分隔(设计 43)
padding: 0;
border-radius: @radius-base;
background: @white; // 设计 43 列表卡白底直压页面灰底
overflow: hidden; // 悬停底色收敛在卡圆角内
// 行分割线:设计 43 实取 #F0F1F3(矩形 1/2,跨满卡内容宽)
.message-item + .message-item {
border-top: 1px solid @project-divider;
}
&__empty {
padding: @spacing-xxl 0;
padding: 40px 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px; // 设计 43 空态文字 → 可读下限 11
}
}
</style>

View File

@@ -46,50 +46,52 @@ function countOf(value: MessageType | 'all', counts: Counts): number {
<style lang="less" scoped>
.message-tabs {
.flex(row, flex-start);
gap: @spacing-sm;
padding: @spacing-sm @spacing-base;
border-radius: @radius-lg;
.flex(column, flex-start, stretch);
padding: 18px 0; // 卡上内边距 24 × 0.77
min-height: 338px; // 设计左卡高 439 × 0.77
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
box-shadow: none; // 设计 43:白卡直压页面底色,无阴影无描边
&__tab {
.flex(row, center);
gap: @spacing-xs;
height: 32px;
padding: 0 @spacing-base;
border-radius: @radius-round;
.flex(row, space-between);
gap: @spacing-sm;
height: 32px; // 分类行间距 41 × 0.77
padding: 0 18px 0 25px; // 左 33 / 右 23 × 0.77
border-radius: 0;
background: transparent;
color: @text-color;
font-size: @font-size-base;
color: @text-color; // 设计 43 未选中 @text-color
font-size: 11px; // 设计 13 → 可读下限 11
font-weight: 400;
transition: all 0.2s;
&:hover {
color: @primary-color;
color: @primary-strong;
}
&.is-active {
background: @primary-light;
color: @primary-color;
background: transparent; // 设计 43 选中无胶囊底
color: @primary-strong; // 设计 43 选中 @primary-strong
font-weight: 600;
}
}
&__count {
min-width: 18px;
height: 18px;
padding: 0 5px;
min-width: 15px; // 徽标直径 20 × 0.77
height: 15px;
padding: 0 4px;
border-radius: @radius-round;
background: @bg-color;
color: @text-color-secondary;
font-size: @font-size-sm;
line-height: 18px;
background: @danger-color; // 设计 43 红底 ≈ #F54343
color: @white;
font-size: 11px; // 设计 10 → 可读下限 11
line-height: 15px;
text-align: center;
}
.is-active &__count {
background: @primary-color;
background: @danger-color; // 设计 43 选中项徽标仍为红底
color: @white;
font-weight: 600;
}
}
</style>

View File

@@ -101,84 +101,113 @@ onMounted(load)
<style lang="less" scoped>
.message-detail {
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-lg @spacing-base @spacing-xxl;
// 设计 42:面包屑 12 → 11,#9CA3AF;末段「消息详情」#4B5563 / 500
&__breadcrumb {
margin-bottom: @spacing-base;
font-size: @font-size-base;
display: flex;
align-items: center;
gap: 4px;
margin-bottom: 12px; // 面包屑→卡片 15 × 0.77
font-size: 11px;
color: @text-color-disabled;
.link {
color: @text-color-disabled;
}
span:last-child {
color: @text-color;
font-weight: 500;
}
}
// 设计 42:白卡直压页面灰底,无阴影
&__card {
padding: @spacing-xl;
padding: 32px 36px 34px; // 卡内边距 42/48/44 × 0.77
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
box-shadow: none;
}
// 设计 42:主标题 20 → 15 / 700 / 居中 / #1F2937
&__title {
font-size: @font-size-xl;
font-weight: 600;
font-size: 15px;
font-weight: 700;
color: @heading-color;
text-align: center;
}
// 设计 42:发布时间 12 → 11 / #9CA3AF / 居中
&__time {
margin-top: @spacing-sm;
font-size: @font-size-sm;
margin-top: 11px; // 14 × 0.77
font-size: 11px;
color: @text-color-disabled;
text-align: center;
}
// 设计 42:富文本 13 → 11 / #4B5563 / 居中 / 行高 24.7 × 0.77
&__content {
margin-top: @spacing-lg;
padding: @spacing-base;
border-radius: @radius-base;
background: @bg-color-light;
margin-top: 24px; // 时间→正文 32 × 0.77
background: transparent;
color: @text-color;
font-size: @font-size-base;
line-height: 1.8;
font-size: 11px;
line-height: 1.9;
text-align: center;
white-space: pre-wrap;
word-break: break-word;
}
&__attachments {
margin-top: @spacing-lg;
margin-top: 20px; // 正文→附件 26 × 0.77
&-title {
margin-bottom: @spacing-sm;
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
margin-bottom: 8px;
font-size: 11px;
font-weight: 400;
color: @text-color-disabled;
}
}
&__file-list {
.flex(column, flex-start);
.flex(column, flex-start, stretch);
gap: @spacing-sm;
}
// 附件行:设计 42 实取底 #F7F8FA、圆角小卡、无描边
&__file {
.flex(row, space-between);
gap: @spacing-base;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
align-items: center;
width: fit-content;
max-width: 100%;
padding: 10px 14px; // 附件盒 13/15 × 0.77
border: none;
border-radius: 6px;
background: @finance-row-bg;
list-style: none;
}
&__file-info {
.flex(column, flex-start);
gap: 2px;
.flex(column, flex-start, flex-start);
gap: 3px;
min-width: 0;
}
// 设计 42:文件名 12 → 11 / 700 / #1F2937
&__file-name {
font-size: @font-size-base;
font-size: 11px;
font-weight: 700;
color: @heading-color;
.ellipsis();
}
// 设计 42:大小 12 → 11 / #9CA3AF
&__file-meta {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-disabled;
}
&__file-actions {
@@ -188,24 +217,40 @@ onMounted(load)
}
&__file-btn {
font-size: @font-size-sm;
color: @primary-color;
transition: opacity 0.2s;
font-size: 11px;
color: @text-color-secondary;
transition: color 0.2s;
&:hover {
opacity: 0.75;
color: @primary-strong;
}
}
// 返回:设计 42 右下角 #024FFF 小按钮
&__actions {
.flex(row, flex-start);
margin-top: @spacing-lg;
.flex(row, flex-end);
margin-top: 32px; // 附件→返回 43 × 0.77
.app-button {
height: 24px; // 31 × 0.77
padding: 0 16px;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: 11px; // 13 → 可读下限 11
font-weight: 500;
&:hover {
background: @primary-strong;
color: @white;
}
}
}
&__empty {
padding: @spacing-xxl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
}
</style>

View File

@@ -55,73 +55,201 @@ onMounted(() => {
<template>
<div class="message">
<header class="message__head">
<div class="message__head-text">
<h1 class="message__title">
消息中心
</h1>
</header>
<p class="message__subtitle text-secondary">
统一接收项目进度、售后工单、账单待办等站内消息,重要业务动态实时提醒
</p>
</div>
<div class="message__body">
<MessageTabs
class="message__tabs"
:active="query.type"
:counts="tabCounts"
@tab-change="onTabChange"
/>
<div class="message__main">
<div class="message__toolbar">
<FilterPanel
class="message__filter"
v-model:keyword="keyword"
keyword-placeholder="搜索消息标题、内容"
@search="onSearch"
@reset="onReset"
/>
<AppButton
class="message__mark-read"
type="default"
:disabled="unreadCount === 0"
@click="onMarkAllRead"
>
全部已读
</AppButton>
</header>
<MessageTabs
:active="query.type"
:counts="tabCounts"
@tab-change="onTabChange"
/>
<FilterPanel
v-model:keyword="keyword"
keyword-placeholder="搜索消息标题、内容"
@search="onSearch"
@reset="onReset"
/>
</div>
<MessageList :messages="list" @view="onView" />
<PaginationBar
class="message__pagination"
:page="query.page"
:page-size="query.pageSize"
:total="total"
@page-change="onPageChange"
/>
</div>
</div>
</div>
</template>
<style lang="less" scoped>
.message {
.flex(column, flex-start);
.flex(column, flex-start, stretch);
gap: @spacing-base;
padding-top: @spacing-xl;
padding-bottom: @spacing-xxl;
max-width: @container-width;
margin: 0 auto;
padding: @spacing-xl @spacing-base @spacing-xxl;
&__head {
.flex(row, space-between);
gap: @spacing-base;
}
&__head-text {
.flex(column, flex-start);
gap: @spacing-xs;
min-width: 0;
.flex(row, flex-start);
margin-bottom: -10px; // 标题→副标题净距 8 × 0.77(叠加父级 gap 16)
}
// 设计 43:标题 22 × 0.77,700,#1F2937
&__title {
font-size: @font-size-xxl;
font-weight: 600;
font-size: 17px;
font-weight: 700;
color: @heading-color;
}
// 设计 43:副标题整行居中,13 → 可读下限 11,#6B7280(text-secondary)
&__subtitle {
font-size: @font-size-base;
text-align: center;
font-size: 11px;
}
&__body {
.flex(row, flex-start);
gap: 26px; // 左右栏间距 34 × 0.77
align-items: flex-start;
}
&__tabs {
flex-shrink: 0;
width: 156px; // 左分类卡宽 202 × 0.77
}
&__main {
.flex(column, flex-start, stretch);
gap: 15px; // 卡片纵向间距 19 × 0.77
flex: 1;
min-width: 0;
}
// 搜索行白卡:设计 43 x243..1897 / y370..435,输入与「全部已读」同卡
&__toolbar {
.flex(row, flex-start);
align-items: center;
gap: 11px;
padding: 10px 17px; // 卡内边距 22/16 × 0.77
border-radius: @radius-base;
background: @white;
}
& .message__filter {
flex: 1;
min-width: 0;
padding: 0;
background: transparent;
}
// 「全部已读」:设计 43 白底浅描边 12 → 11 / 500 #4B5563
& .message__mark-read {
flex-shrink: 0;
height: 26px; // 34 × 0.77
padding: 0 16px;
border: 1px solid @border-color;
border-radius: 6px;
background: @white;
color: @text-color;
font-size: 11px;
font-weight: 500;
&:hover:not(:disabled) {
border-color: @primary-color;
background: @white;
color: @primary-color;
}
}
& .message__pagination {
justify-content: flex-end;
align-self: stretch;
padding: 0;
}
// FilterPanel 内部按设计 43 覆写(灰底输入框 / 灰重置 / 蓝搜索,重置在前)
.message__filter {
:deep(.filter-panel__bar) {
gap: 6px;
}
:deep(.filter-panel__body) {
margin-top: 0;
}
:deep(.filter-panel__input) {
order: 0;
flex: 0 1 349px; // 输入框宽 453 × 0.77
max-width: 349px;
height: 29px; // 38 × 0.77
margin-right: 2px; // 叠加 bar gap 6 ≈ 输入→按钮 8 × 0.77
padding: 0 10px;
border: none;
border-radius: 6px;
background: @finance-field-bg; // 设计 43 实取 @input-bg
color: @text-color;
font-size: 11px; // 设计 13 → 可读下限 11
&::placeholder {
color: @contract-placeholder; // 设计 43 实取 #B3B9C4
}
&:focus {
border: none;
}
}
:deep(.filter-panel__btn) {
order: 1;
min-width: 46px; // 重置 57 × 0.77
height: 29px;
padding: 0 12px;
border: none;
border-radius: 6px;
background: @contract-reset-bg; // 设计 43 重置底 #EEF0F3
color: @text-color;
font-size: 11px;
font-weight: 500;
&:hover {
background: @contract-reset-bg;
color: @text-color;
}
}
:deep(.filter-panel__btn--primary) {
order: 2;
background: @primary-strong; // 设计 43 搜索底 @primary-strong
color: @white;
&:hover {
background: @primary-strong;
color: @white;
}
}
}
}
</style>

View File

@@ -15,6 +15,7 @@ import AboutPanel from './cpns/AboutPanel.vue'
</template>
<style lang="less" scoped>
// 设计 19(关于我们):面板内标题蓝条,正文各区块平铺
.about-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -22,16 +23,27 @@ import AboutPanel from './cpns/AboutPanel.vue'
&__head {
width: 100%;
padding: @spacing-base @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
}
</style>

View File

@@ -83,10 +83,10 @@ onMounted(() => {
</h3>
<StatusTag v-if="address.isDefault" label="默认" variant="success" />
</div>
<ul class="address-card__meta text-secondary">
<li>联系方式:{{ address.phone }}</li>
<li>所在地区:{{ address.region }}</li>
<li>详细地址:{{ address.detailAddress }}</li>
<ul class="address-card__meta">
<li><span>联系方式:</span>{{ address.phone }}</li>
<li><span>所在地区:</span>{{ address.region }}</li>
<li><span>详细地址:</span>{{ address.detailAddress }}</li>
</ul>
<div class="address-card__actions">
<button
@@ -143,6 +143,7 @@ onMounted(() => {
</template>
<style lang="less" scoped>
// 设计 20(地址管理):标题蓝条、整行白卡描边、字段标签灰/值深、白底描边小按钮、分页靠右
.address-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -151,21 +152,33 @@ onMounted(() => {
&__head {
.flex(row, space-between, center);
width: 100%;
padding: @spacing-base @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
// 设计 20:列表整行铺满(单列),分页靠右
&__grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: 1fr;
gap: @spacing-base;
width: 100%;
}
@@ -174,66 +187,133 @@ onMounted(() => {
grid-column: 1 / -1;
padding: @spacing-xxl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
:deep(.pagination) {
justify-content: flex-end;
padding: 0;
}
:deep(.pagination__btn.is-active) {
border-color: @profile-page-active-bg;
background: @profile-page-active-bg;
color: @primary-strong;
}
// 顶部「+ 新增地址」:小号蓝底按钮(设计 20 实取 #024FFF)
.app-button--primary {
height: 24px;
padding: 0 10px;
border: none;
border-radius: @profile-radius;
background: @primary-strong;
color: @white;
font-size: 11px;
font-weight: 500;
&:hover {
border: none;
background: darken(@primary-strong, 6%);
}
}
}
.address-card {
.flex(column, flex-start);
gap: @spacing-sm;
padding: @spacing-base @spacing-lg;
border-radius: @radius-lg;
.flex(row, flex-start, center);
gap: @spacing-lg;
padding: @spacing-base;
border: 1px solid @profile-card-border;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
&__head {
.flex(row, space-between, center);
gap: @spacing-sm;
.flex(row, flex-start, center);
gap: @spacing-xs;
flex-shrink: 0;
flex-direction: column-reverse; // 设计 20:「默认」标签在上、姓名在下
align-items: flex-start;
}
// 设计 20:字段值 13 设计px w600 深灰
&__name {
font-size: @font-size-lg;
font-size: 11px;
font-weight: 600;
color: @heading-color;
}
// 设计 20:标签 11 设计px 灰、值 13 设计px w600 深;整行横向排布
&__meta {
.flex(column, flex-start);
gap: @spacing-xs;
.flex(row, flex-start);
gap: @spacing-xl;
flex: 1;
min-width: 0;
list-style: none;
font-size: @font-size-base;
font-size: 11px;
li {
flex: 1;
min-width: 0;
color: @heading-color;
font-weight: 600;
.ellipsis();
}
span {
display: block;
margin-bottom: @spacing-xs;
color: @text-color-secondary;
font-weight: 400;
}
}
&__actions {
.flex(row, center);
gap: @spacing-base;
margin-top: auto;
padding-top: @spacing-sm;
border-top: 1px solid @border-color;
width: 100%;
gap: @spacing-sm;
flex-shrink: 0;
width: auto;
margin-top: 0;
padding-top: 0;
border-top: none;
}
// 设计 20:操作按钮 = 白底灰描边、12 设计px w500 灰字
&__btn {
font-size: @font-size-base;
color: @primary-color;
transition: opacity 0.2s;
height: 24px;
padding: 0 10px;
border: 1px solid @profile-line;
border-radius: @profile-radius;
background: @white;
color: @text-color;
font-size: 11px;
font-weight: 500;
transition: all 0.2s;
&:hover:not(:disabled) {
opacity: 0.75;
border-color: @primary-strong;
color: @primary-strong;
opacity: 1;
}
&--muted {
color: @text-color-disabled;
color: @text-color;
cursor: not-allowed;
opacity: 0.6;
}
&--danger {
color: @danger-color;
color: @text-color;
}
}
}
// 「默认」标签:设计 20 实取蓝底 #024FFF 白字
.address-card .status-tag {
padding: 2px 8px;
background: @primary-strong;
color: @white;
font-size: 11px;
font-weight: 500;
}
</style>

View File

@@ -82,35 +82,36 @@ const advantages = [
</template>
<style lang="less" scoped>
// 设计 19(关于我们):区块标题 14 设计px w700、正文 13 设计px 灰、平铺无卡片底
.about-panel {
.flex(column, flex-start);
gap: @spacing-base;
gap: @spacing-lg;
&__section {
.flex(column, flex-start);
gap: @spacing-sm;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
background: transparent;
box-shadow: none;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
font-size: 11px; // 设计 14 → 11
font-weight: 700;
color: @heading-color;
}
&__text {
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
line-height: 1.8;
line-height: 1.9;
}
// 设计 19:优势项为「标题 + 描述」同排平铺,标题亦为灰色加粗
&__advantages {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: @spacing-base;
grid-template-columns: 1fr;
gap: @spacing-sm;
width: 100%;
margin: 0;
padding: 0;
@@ -118,21 +119,22 @@ const advantages = [
}
&__advantage {
.flex(column, flex-start);
gap: @spacing-xs;
padding: @spacing-base;
border-radius: @radius-base;
background: @bg-color-light;
.flex(row, flex-start);
gap: @spacing-sm;
padding: 0;
background: transparent;
}
&__advantage-title {
font-size: @font-size-base;
font-weight: 600;
color: @primary-color;
flex-shrink: 0;
font-size: 11px;
font-weight: 700;
color: @text-color;
}
&__advantage-desc {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color;
line-height: 1.7;
}
@@ -142,18 +144,19 @@ const advantages = [
margin: 0;
padding: 0;
list-style: none;
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
span {
color: @text-color-secondary;
color: @text-color;
}
}
&__link {
color: @primary-color;
color: @text-color;
&:hover {
color: @primary-strong;
text-decoration: underline;
}
}

View File

@@ -123,28 +123,47 @@ function onSave(): void {
</template>
<style lang="less" scoped>
// 与个人中心其它弹窗同规格(设计 22~27):白卡 700px、蓝条标题、白底描边输入、等宽双按钮
.address-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: rgba(0, 0, 0, 0.45);
background: transparent;
overflow-y: auto;
&__panel {
width: 480px;
width: 700px;
max-width: calc(100vw - 32px);
padding: @spacing-lg;
max-height: calc(100vh - 48px);
overflow-y: auto;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
.flex(column, flex-start);
gap: @spacing-base;
.scrollbar();
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__field {
@@ -154,41 +173,77 @@ function onSave(): void {
}
&__label {
font-size: @font-size-base;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
&__input,
&__textarea {
width: 100%;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
}
&__input {
height: 40px;
height: 32px;
}
&__textarea {
padding: @spacing-sm @spacing-base;
padding: 8px 12px;
line-height: 1.6;
resize: vertical;
}
&__footer {
.flex(row, flex-end);
.flex(row, flex-start);
gap: @spacing-sm;
width: 100%;
}
.app-button {
flex: 1;
height: 36px;
font-size: 12px;
font-weight: 500;
border-radius: @profile-radius;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
.app-button--default {
border: none;
background: @profile-quiet-btn;
color: @text-color;
&:hover {
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
}
}
</style>

View File

@@ -132,7 +132,7 @@ function onSubmit(): void {
<label v-if="!isIdentity" class="bind-dialog__agree">
<input v-model="agree" type="checkbox">
<span>我已阅读并同意《用户协议》和《隐私政策》</span>
<span>我已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<div class="bind-dialog__footer">
@@ -149,35 +149,68 @@ function onSubmit(): void {
</template>
<style lang="less" scoped>
// 设计 23~27(绑定/换绑/身份验证弹窗):与修改密码弹窗同规格 —— 白卡 700px、蓝条标题、
// 白底描边输入、底部等宽双按钮;设计稿无蒙层压暗,遮罩透明。
.bind-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: rgba(0, 0, 0, 0.45);
background: transparent;
overflow-y: auto;
&__panel {
width: 440px;
width: 700px; // 设计 900 × 0.77
max-width: calc(100vw - 32px);
padding: @spacing-lg;
max-height: calc(100vh - 48px);
overflow-y: auto;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
.flex(column, flex-start);
gap: @spacing-base;
.scrollbar();
}
// 设计 22~26:蓝条 + 标题 15 设计px w700 深灰
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
// 设计 23:身份验证标题为纯蓝字 14 设计px(无蓝条)
&__title:has(+ .bind-dialog__desc) {
padding-left: 0;
font-size: 11px;
color: @primary-strong;
&::before {
display: none;
}
}
// 设计 23:说明为纯灰字(非底色块)
&__desc {
padding: @spacing-sm @spacing-base;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-sm;
padding: 0;
background: transparent;
color: @text-color-secondary;
font-size: 11px;
line-height: 1.6;
}
@@ -188,42 +221,85 @@ function onSubmit(): void {
}
&__label {
font-size: @font-size-base;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
&__input {
width: 100%;
height: 40px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
height: 32px;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
}
&__agree {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: @font-size-sm;
color: @text-color;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
accent-color: @primary-color;
accent-color: @primary-strong;
}
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计 24/25/26:底部等宽双按钮,次级 #EEF0F3、主色 #024FFF
&__footer {
.flex(row, flex-end);
.flex(row, flex-start);
gap: @spacing-sm;
width: 100%;
}
.app-button {
flex: 1;
height: 36px;
font-size: 12px;
font-weight: 500;
border-radius: @profile-radius;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
.app-button--default {
border: none;
background: @profile-quiet-btn;
color: @text-color;
&:hover {
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
}
}
</style>

View File

@@ -103,7 +103,7 @@ function onSubmit(): void {
<label class="change-pwd-dialog__agree">
<input v-model="agree" type="checkbox">
<span>我已阅读并同意《用户协议》和《隐私政策》</span>
<span>我已阅读并同意<em>《用户协议》</em>和<em>《隐私政策》</em></span>
</label>
<div class="change-pwd-dialog__footer">
@@ -120,28 +120,49 @@ function onSubmit(): void {
</template>
<style lang="less" scoped>
// 设计 22(修改密码弹窗):白卡 900×~540 设计px、蓝条标题、白底描边输入 40 设计px、
// 整行蓝色主按钮;设计稿无蒙层压暗(页面原样可见),故遮罩透明。
.change-pwd-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: rgba(0, 0, 0, 0.45);
background: transparent;
overflow-y: auto;
&__panel {
width: 440px;
width: 700px; // 设计 900 × 0.77
max-width: calc(100vw - 32px);
padding: @spacing-lg;
max-height: calc(100vh - 48px);
overflow-y: auto;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
.flex(column, flex-start);
gap: @spacing-base;
.scrollbar();
}
// 设计 22:蓝条(#024FFF 4×20 设计px)+ 标题 15 设计px w700
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__field {
@@ -150,28 +171,37 @@ function onSubmit(): void {
width: 100%;
}
// 设计 22:标签 13 设计px w500 深灰
&__label {
font-size: @font-size-base;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
// 设计 22:白底、#DDE1E7 描边、40 设计px ≈ 32px 高、13 设计px 字
&__input {
width: 100%;
height: 40px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
height: 32px;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
&:read-only {
color: @text-color-secondary;
color: @text-color;
cursor: not-allowed;
}
}
@@ -179,19 +209,55 @@ function onSubmit(): void {
&__agree {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: @font-size-sm;
color: @text-color;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
accent-color: @primary-color;
accent-color: @primary-strong;
}
em {
font-style: normal;
color: @primary-strong;
}
}
// 设计 24:底部两枚等宽整行按钮 —— 次级 #EEF0F3 灰底、主色 #024FFF
&__footer {
.flex(row, flex-end);
.flex(row, flex-start);
gap: @spacing-sm;
width: 100%;
}
.app-button {
flex: 1;
height: 36px;
font-size: 12px;
font-weight: 500;
border-radius: @profile-radius;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
.app-button--default {
border: none;
background: @profile-quiet-btn;
color: @text-color;
&:hover {
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
}
}
</style>

View File

@@ -114,13 +114,14 @@ function onReset(): void {
</template>
<style lang="less" scoped>
// 设计 18(意见反馈表单):表单直接铺在白面板上(无内嵌卡)、标签 13 设计px w500、
// 白底 #DDE1E7 描边输入、计数灰字、附件区白底描边
.feedback-form {
.flex(column, flex-start);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
background: transparent;
box-shadow: none;
&__field {
.flex(column, flex-start);
@@ -129,7 +130,8 @@ function onReset(): void {
}
&__label {
font-size: @font-size-base;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
@@ -138,52 +140,51 @@ function onReset(): void {
color: @danger-color;
}
&__input {
&__input,
&__textarea {
width: 100%;
height: 40px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
}
&__input {
height: 32px; // 设计 40 × 0.77
}
&__textarea {
width: 100%;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
padding: 8px 12px;
line-height: 1.6;
outline: none;
transition: border-color 0.2s;
resize: vertical;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
}
}
// 设计 18:字数统计 11 设计px 灰字
&__counter {
align-self: flex-end;
font-size: @font-size-sm;
color: @text-color-disabled;
font-size: 11px;
}
&__tip {
padding: @spacing-sm @spacing-base;
border-radius: @radius-base;
border-radius: @profile-radius;
background: @primary-light;
color: @primary-color;
font-size: @font-size-sm;
color: @primary-strong;
font-size: 11px;
line-height: 1.6;
}
@@ -191,5 +192,40 @@ function onReset(): void {
.flex(row, flex-start);
gap: @spacing-sm;
}
// 附件区:设计 18 白底 + #DDE1E7 描边
:deep(.upload-area) {
min-height: 56px;
border: 1px solid @profile-input-border;
background: @white;
&:hover,
&.is-dragging {
background: @bg-color-light;
}
}
:deep(.upload-area__hint) {
color: @text-color-disabled;
font-size: 11px;
}
.app-button {
height: 32px;
padding: 0 16px;
border-radius: @profile-radius;
font-size: 12px;
font-weight: 500;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
}
</style>

View File

@@ -42,26 +42,25 @@ defineProps<Props>()
</template>
<style lang="less" scoped>
// 设计 16(帮助中心 FAQ):分类标题居中 14 设计px w700、Q 加粗深灰、A 13 设计px 灰,
// 无卡片底色/描边,平铺在面板上
.help-faq {
.flex(column, flex-start);
gap: @spacing-base;
&__group {
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
overflow: hidden;
background: transparent;
}
&__summary {
.flex(row, flex-start, center);
padding: @spacing-base @spacing-xl;
font-size: @font-size-lg;
font-weight: 600;
.flex(row, center, center);
justify-content: center;
padding: 0;
font-size: 11px; // 设计 14 → 11
font-weight: 700;
color: @heading-color;
cursor: pointer;
list-style: none;
transition: background 0.2s;
user-select: none;
&::-webkit-details-marker {
@@ -69,52 +68,46 @@ defineProps<Props>()
}
&::after {
content: '▾';
margin-left: auto;
font-size: @font-size-base;
color: @text-color-secondary;
transition: transform 0.2s;
content: none;
}
&:hover {
background: @bg-color-light;
background: transparent;
color: @primary-strong;
}
}
&__group[open] > .help-faq__summary::after {
transform: rotate(180deg);
}
&__list {
.flex(column, flex-start);
gap: @spacing-base;
gap: 6px;
margin: 0;
padding: 0 @spacing-xl @spacing-lg;
padding: @spacing-sm 0 0;
list-style: none;
border-top: 1px solid @border-color;
border-top: none;
}
&__item {
.flex(column, flex-start);
gap: @spacing-xs;
padding-top: @spacing-base;
padding-top: 0;
}
&__q {
font-size: @font-size-base;
font-weight: 600;
font-size: 11px;
font-weight: 700;
color: @heading-color;
}
&__a {
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
line-height: 1.7;
}
&__empty {
padding: @spacing-xxl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
}
</style>

View File

@@ -22,42 +22,65 @@ const WORK_TIME = '工作日 8:00-12:00 14:00-18:00'
</template>
<style lang="less" scoped>
// 设计 14(专属客服热线):面板内整行浅蓝卡(#D6E4FB)、蓝色圆形图标、
// 标题 19 设计px w700、号码 24 设计px 蓝色 w700、时间 12 设计px 灰
.hotline-panel {
.flex(row, center);
padding: @spacing-xxl 0;
.flex(row, flex-start);
padding: 0;
&__card {
.flex(column, center);
gap: @spacing-base;
width: 480px;
display: grid;
grid-template-columns: auto 1fr;
grid-template-areas:
'icon title'
'icon number'
'icon time';
column-gap: @spacing-base;
align-content: center;
width: 100%;
max-width: 100%;
padding: @spacing-xxl @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
text-align: center;
padding: @spacing-lg;
border-radius: @radius-base;
background: @profile-hotline-bg;
text-align: left;
align-items: center;
}
// 设计 14 实取:#024FFF 蓝色圆底(直径约 64 设计px)
&__icon {
font-size: @font-size-xxl * 2;
.flex(row, center);
grid-area: icon;
flex-shrink: 0;
width: 49px;
height: 49px;
margin: 0;
border-radius: @radius-round;
background: @primary-strong;
font-size: @font-size-lg;
line-height: 1;
}
&__title {
font-size: @font-size-xl;
font-weight: 600;
grid-area: title;
align-self: end;
font-size: 15px; // 设计 19 → 15
font-weight: 700;
color: @heading-color;
}
&__number {
font-size: @font-size-xxl + @spacing-sm;
grid-area: number;
font-size: 18px; // 设计 24 → 18
font-weight: 700;
color: @primary-color;
line-height: 1.2;
color: @primary-strong;
line-height: 1.3;
}
&__time {
font-size: @font-size-base;
grid-area: time;
align-self: start;
color: @text-color-secondary;
font-size: 11px; // 设计 12 → 11
}
}
</style>

View File

@@ -22,11 +22,11 @@ const menus: MenuItem[] = [
<ul class="profile-sider__menu">
<li v-for="item in menus" :key="item.to">
<RouterLink :to="item.to" class="profile-sider__item">
<span class="profile-sider__icon">{{ item.icon }}</span>
<span class="profile-sider__label">{{ item.label }}</span>
</RouterLink>
</li>
</ul>
<div class="profile-sider__footer">
<RouterLink
to="/profile/hotline"
@@ -47,50 +47,50 @@ const menus: MenuItem[] = [
&__menu {
.flex(column, flex-start);
gap: 2px;
gap: 0;
list-style: none;
}
// 设计 14/28:纯文字菜单,选中项浅蓝底 + 蓝色加粗,行距 36 × 0.77 ≈ 28
&__item {
.flex(row, flex-start);
gap: @spacing-sm;
height: 44px;
padding: 0 @spacing-base;
border-radius: @radius-base;
.flex(row, flex-start, center);
height: 28px;
padding: 0 @spacing-sm;
border-radius: @profile-radius;
color: @text-color;
font-size: @font-size-base;
font-size: 11px;
line-height: 1;
transition: all 0.2s;
&:hover {
background: @primary-light;
color: @primary-color;
color: @primary-strong;
}
&.router-link-active {
background: @primary-light;
color: @primary-color;
background: @profile-nav-active-bg;
color: @primary-strong;
font-weight: 600;
}
}
&__icon {
font-size: @font-size-lg;
line-height: 1;
&__label {
white-space: nowrap;
}
&__footer {
padding: @spacing-base;
border-top: 1px solid @border-color;
text-align: center;
padding: @spacing-sm @spacing-sm 0;
border-top: 1px solid @project-divider;
}
&__hotline {
font-size: @font-size-sm;
display: inline-block;
font-size: 11px;
color: @text-color-secondary;
transition: color 0.2s;
&:hover {
color: @primary-color;
color: @primary-strong;
}
}
}

View File

@@ -50,63 +50,68 @@ function save(): void {
</template>
<style lang="less" scoped>
// 设计 14:左列紫渐变用户卡(渐变实取 #5459E8 → #D2BDF3),内容居中
.profile-user-card {
.flex(row, flex-start);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
.flex(column, center);
gap: @spacing-xs; // 设计 14:头像与文字块间距约 4px
padding: @spacing-base @spacing-sm; // 设计:上 20 / 下 25 设计px ≈ 16
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
background: linear-gradient(170deg, @profile-user-from 0%, @profile-user-to 100%);
&__avatar {
.flex(row, center);
flex-shrink: 0;
width: 64px;
height: 64px;
width: 42px; // 设计 54 × 0.77
height: 42px;
border-radius: @radius-round;
background: linear-gradient(135deg, @primary-color, @primary-hover);
background: @profile-user-avatar;
color: @white;
font-size: @font-size-xxl;
font-size: @font-size-lg;
font-weight: 600;
}
&__info {
.flex(column, flex-start);
.flex(column, center);
gap: @spacing-xs;
min-width: 0;
width: 100%;
text-align: center;
}
// 卡内为深色底:名称/号码一律白字(设计 14 实取 #FFFFFF)
&__name {
width: 240px;
height: 34px;
padding: 0 @spacing-sm;
width: 100%;
height: 16px; // 设计 19 × 0.77
padding: 0 @spacing-xs;
border: 1px solid transparent;
border-radius: @radius-base;
border-radius: @profile-radius;
background: transparent;
font-size: @font-size-xl;
font-size: 11px;
font-weight: 600;
color: @heading-color;
color: @white;
text-align: center;
outline: none;
transition: all 0.2s;
&:hover {
border-color: @border-color;
border-color: fade(@white, 55%);
}
&:focus {
border-color: @primary-color;
background: @bg-color-light;
border-color: @white;
background: fade(@white, 12%);
}
&::placeholder {
font-size: @font-size-lg;
font-size: 11px;
font-weight: 400;
color: @text-color-disabled;
color: fade(@white, 75%);
}
}
&__phone {
font-size: @font-size-base;
font-size: 11px;
color: @white;
}
}
</style>

View File

@@ -59,13 +59,14 @@ const STATUS_VARIANTS: Record<QualificationStatus, 'success' | 'warning' | 'dang
</template>
<style lang="less" scoped>
// 设计 17(资质列表行):白卡灰描边、字段标签灰/值深 w600、状态为纯文字、白底描边操作按钮
.qual-card {
.flex(column, flex-start);
gap: @spacing-sm;
padding: @spacing-base;
border-radius: @radius-lg;
border: 1px solid @profile-card-border;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
&__head {
.flex(row, space-between, flex-start);
@@ -73,7 +74,7 @@ const STATUS_VARIANTS: Record<QualificationStatus, 'success' | 'warning' | 'dang
}
&__name {
font-size: @font-size-lg;
font-size: 11px; // 设计 13 → 11
font-weight: 600;
color: @heading-color;
.multi-ellipsis(2);
@@ -83,42 +84,77 @@ const STATUS_VARIANTS: Record<QualificationStatus, 'success' | 'warning' | 'dang
.flex(column, flex-start);
gap: @spacing-xs;
list-style: none;
font-size: @font-size-base;
color: @text-color;
font-size: 11px;
color: @heading-color;
li {
.ellipsis();
font-weight: 600;
}
span {
color: @text-color-secondary;
font-weight: 400;
}
}
&__actions {
.flex(row, center);
gap: @spacing-base;
gap: @spacing-sm;
margin-top: auto;
padding-top: @spacing-sm;
border-top: 1px solid @border-color;
border-top: 1px solid @profile-card-border;
width: 100%;
}
// 设计 17:操作按钮 = 白底灰描边、12 设计px w500 灰字
&__btn {
font-size: @font-size-base;
color: @primary-color;
transition: opacity 0.2s;
height: 24px;
padding: 0 10px;
border: 1px solid @profile-line;
border-radius: @profile-radius;
background: @white;
color: @text-color;
font-size: 11px;
font-weight: 500;
transition: all 0.2s;
&:hover {
opacity: 0.75;
border-color: @primary-strong;
color: @primary-strong;
opacity: 1;
}
&--danger {
color: @danger-color;
color: @text-color;
}
&--warning {
color: @warning-color;
color: @text-color;
}
}
}
// 设计 17:状态为纯文字(已认证/审核中深灰、未通过红),无底色胶囊
.qual-card .status-tag {
padding: 0;
background: transparent;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
&--success {
background: transparent;
color: @heading-color;
}
&--warning {
background: transparent;
color: @heading-color;
}
&--danger {
background: transparent;
color: @danger-color;
}
}
</style>

View File

@@ -184,20 +184,21 @@ function onSave(): void {
</template>
<style lang="less" scoped>
// 与个人中心其它弹窗同规格(设计 22~27):白卡 700px、蓝条标题、白底描边输入、等宽双按钮
.qual-dialog {
position: fixed;
inset: 0;
z-index: 1000;
.flex(row, center);
background: rgba(0, 0, 0, 0.45);
background: transparent;
overflow-y: auto;
&__panel {
width: 520px;
width: 700px;
max-width: calc(100vw - 32px);
max-height: calc(100vh - 48px);
overflow-y: auto;
padding: @spacing-lg;
padding: @spacing-base;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-lg;
@@ -207,9 +208,23 @@ function onSave(): void {
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__field {
@@ -219,25 +234,30 @@ function onSave(): void {
}
&__label {
font-size: @font-size-base;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
&__input {
width: 100%;
height: 40px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
font-size: @font-size-base;
height: 32px;
padding: 0 12px;
border: 1px solid @profile-input-border;
border-radius: @profile-radius;
background: @white;
font-size: 11px;
color: @text-color;
outline: none;
transition: border-color 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border-color: @primary-strong;
}
&::placeholder {
color: @heading-color;
}
}
@@ -248,17 +268,47 @@ function onSave(): void {
&__sep {
flex-shrink: 0;
font-size: @font-size-sm;
font-size: 11px;
}
&__hint {
font-size: @font-size-sm;
font-size: 11px;
}
&__footer {
.flex(row, flex-end);
.flex(row, flex-start);
gap: @spacing-sm;
width: 100%;
}
.app-button {
flex: 1;
height: 36px;
font-size: 12px;
font-weight: 500;
border-radius: @profile-radius;
}
.app-button--primary {
border-color: @primary-strong;
background: @primary-strong;
&:hover {
border-color: darken(@primary-strong, 6%);
background: darken(@primary-strong, 6%);
}
}
.app-button--default {
border: none;
background: @profile-quiet-btn;
color: @text-color;
&:hover {
border: none;
background: darken(@profile-quiet-btn, 4%);
color: @text-color;
}
}
}
</style>

View File

@@ -42,13 +42,14 @@ const risks = [
<div class="security-panel">
<!-- 修改密码 -->
<section class="security-panel__row">
<span class="security-panel__icon security-panel__icon--pwd" aria-hidden="true" />
<div class="security-panel__main">
<h3 class="security-panel__title">
修改密码
</h3>
<p class="security-panel__status">
<span class="security-panel__badge security-panel__badge--ok">已设置</span>
<span class="security-panel__note text-secondary">上次修改:{{ profile?.passwordModifiedAt }}</span>
<span class="security-panel__note">上次修改:{{ profile?.passwordModifiedAt }}</span>
</p>
</div>
<AppButton type="default" @click="emit('changePassword')">
@@ -58,6 +59,7 @@ const risks = [
<!-- 绑定手机 -->
<section class="security-panel__row">
<span class="security-panel__icon security-panel__icon--phone" aria-hidden="true" />
<div class="security-panel__main">
<h3 class="security-panel__title">
绑定手机
@@ -65,7 +67,7 @@ const risks = [
<p class="security-panel__status">
<span class="security-panel__badge security-panel__badge--ok">已绑定 {{ profile?.phone }}</span>
</p>
<p class="security-panel__note text-secondary">
<p class="security-panel__note">
注:换绑新手机号之后,可以用新的手机号及当前密码登录
</p>
</div>
@@ -76,6 +78,7 @@ const risks = [
<!-- 绑定邮箱 -->
<section class="security-panel__row">
<span class="security-panel__icon security-panel__icon--email" aria-hidden="true" />
<div class="security-panel__main">
<h3 class="security-panel__title">
绑定邮箱
@@ -115,7 +118,7 @@ const risks = [
</h3>
<div class="security-panel__block">
<h4 class="security-panel__block-title">
<h4 class="security-panel__block-title security-panel__block-title--ok">
注销条件
</h4>
<ul class="security-panel__checks">
@@ -126,7 +129,7 @@ const risks = [
</div>
<div class="security-panel__block">
<h4 class="security-panel__block-title">
<h4 class="security-panel__block-title security-panel__block-title--risk">
注销风险提示
</h4>
<ol class="security-panel__risks">
@@ -138,7 +141,7 @@ const risks = [
<label class="security-panel__agree">
<input v-model="agree" type="checkbox">
<span>已阅读并同意《账号注销协议》</span>
<span>已阅读并同意<em>《账号注销协议》</em></span>
</label>
<AppButton
@@ -154,25 +157,47 @@ const risks = [
</template>
<style lang="less" scoped>
// 设计 28:白卡行 + 浅灰描边、图标块 44×44 设计px、标题 14 设计px w600、副文 11 设计px
.security-panel {
.flex(column, flex-start);
gap: @spacing-base;
&__row {
.flex(row, space-between, flex-start);
.flex(row, flex-start, center);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
padding: @spacing-base;
border: 1px solid @profile-card-border;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
// 设计 28 实取图标块底色:#C7D2FE / #FDEBEB / #FEE2E2
&__icon {
flex-shrink: 0;
width: 34px; // 设计 44 × 0.77
height: 34px;
border-radius: @radius-base;
&--pwd {
background: @profile-icon-pwd;
}
&--phone {
background: @profile-icon-phone;
}
&--email {
background: @profile-icon-email;
}
}
&__main {
flex: 1;
min-width: 0;
}
&__title {
font-size: @font-size-lg;
font-size: 11px; // 设计 14 → 10.8,取可读下限 11
font-weight: 600;
color: @heading-color;
}
@@ -181,26 +206,29 @@ const risks = [
.flex(row, flex-start, center);
flex-wrap: wrap;
gap: @spacing-sm;
margin-top: @spacing-sm;
font-size: @font-size-base;
margin-top: @spacing-xs;
font-size: 11px;
}
// 设计 28:已设置/已绑定 = 浅绿底绿字胶囊,未绑定 = 纯灰字
&__badge {
padding: 2px @spacing-sm;
padding: 2px 8px;
border-radius: @radius-sm;
background: @bg-color;
background: transparent;
color: @text-color-secondary;
font-size: @font-size-sm;
font-size: 11px;
font-weight: 500;
&--ok {
background: fade(@success-color, 12%);
background: @tag-success-bg;
color: @success-color;
}
}
&__note {
margin-top: @spacing-xs;
font-size: @font-size-sm;
color: @text-color-disabled;
font-size: 11px;
line-height: 1.6;
}
@@ -210,18 +238,48 @@ const risks = [
flex-shrink: 0;
}
// 行内操作按钮:白底灰描边小按钮(设计 20/17 操作按钮同规格)
.app-button {
height: 28px;
padding: 0 12px;
border: 1px solid @profile-line;
border-radius: @profile-radius;
background: @white;
color: @text-color;
font-size: 11px;
font-weight: 500;
&:hover:not(:disabled) {
border-color: @primary-strong;
color: @primary-strong;
background: @white;
}
}
.app-button--text {
border-color: transparent;
background: transparent;
color: @text-color;
&:hover:not(:disabled) {
border-color: transparent;
background: transparent;
color: @primary-strong;
}
}
&__danger {
.flex(column, flex-start);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
border: 1px solid fade(@danger-color, 35%);
border-radius: @radius-lg;
padding: @spacing-lg;
border: 1px solid @profile-card-border;
border-radius: @radius-base;
background: @white;
}
&__danger-title {
font-size: @font-size-lg;
font-weight: 600;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @danger-color;
}
@@ -230,10 +288,18 @@ const risks = [
gap: @spacing-sm;
}
// 设计 29:注销条件标题绿、注销风险提示标题红
&__block-title {
font-size: @font-size-base;
font-size: 11px;
font-weight: 600;
color: @heading-color;
&--ok {
color: @success-color;
}
&--risk {
color: @danger-color;
}
}
&__checks {
@@ -243,7 +309,7 @@ const risks = [
}
&__check {
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
}
@@ -255,10 +321,10 @@ const risks = [
&__risks {
margin: 0;
padding-left: @spacing-lg;
padding-left: @spacing-base;
.flex(column, flex-start);
gap: @spacing-xs;
font-size: @font-size-base;
font-size: 11px;
color: @text-color;
line-height: 1.6;
}
@@ -266,25 +332,40 @@ const risks = [
&__agree {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: @font-size-base;
color: @text-color;
font-size: 11px;
color: @text-color-secondary;
cursor: pointer;
input {
accent-color: @danger-color;
accent-color: @primary-strong;
}
em {
font-style: normal;
color: @primary-strong;
}
}
// AppButton 根元素可被父级 scoped 命中:danger 描边按钮
// 注销账号:白底灰描边整行按钮(设计 28 实取文字 #9CA3AF、15 设计px)
&__delete-btn {
border-color: @danger-color !important;
color: @danger-color !important;
width: 100%;
height: 36px;
border: 1px solid @profile-line !important;
background: @white !important;
color: @text-color-disabled !important;
font-size: 12px;
font-weight: 500;
&:hover:not(:disabled) {
background: fade(@danger-color, 8%) !important;
border-color: @danger-color !important;
background: @white !important;
color: @danger-color !important;
}
&:disabled {
opacity: 1;
cursor: not-allowed;
}
}
}
</style>

View File

@@ -96,6 +96,7 @@ onMounted(() => {
</template>
<style lang="less" scoped>
// 收藏列表无独立设计稿:与个人中心面板一致 —— 分类条平铺在白面板上,选中态用主色 token
.favorites-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -106,33 +107,42 @@ onMounted(() => {
flex-wrap: wrap;
gap: @spacing-sm;
width: 100%;
padding: @spacing-base @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__cat {
height: 32px;
height: 28px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border: 1px solid @profile-line;
border-radius: @radius-round;
background: @white;
color: @text-color;
font-size: @font-size-sm;
font-size: 11px;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
color: @primary-color;
border-color: @primary-strong;
color: @primary-strong;
}
&.is-active {
border-color: @primary-color;
background: @primary-light;
color: @primary-color;
border-color: @primary-strong;
background: @profile-nav-active-bg;
color: @primary-strong;
font-weight: 600;
}
}
// 分页与地址/资质页保持同一激活态(设计 20 实取 #D1E0FE + #024FFF 字)
:deep(.pagination) {
justify-content: flex-end;
padding: 0;
}
:deep(.pagination__btn.is-active) {
border-color: @profile-page-active-bg;
background: @profile-page-active-bg;
color: @primary-strong;
}
}
</style>

View File

@@ -58,6 +58,7 @@ function onPreview(file: FileInfo): void {
</template>
<style lang="less" scoped>
// 设计 18(意见反馈):面板内标题蓝条 + 副文案,表单直接铺在面板上
.feedback-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -67,20 +68,31 @@ function onPreview(file: FileInfo): void {
.flex(column, flex-start);
gap: @spacing-xs;
width: 100%;
padding: @spacing-base @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__sub {
font-size: @font-size-base;
font-size: 11px;
}
}
</style>

View File

@@ -28,6 +28,7 @@ onMounted(() => {
</template>
<style lang="less" scoped>
// 设计 16(帮助中心):面板内标题蓝条 + 副文案,FAQ 平铺在面板上
.help-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -37,20 +38,31 @@ onMounted(() => {
.flex(column, flex-start);
gap: @spacing-xs;
width: 100%;
padding: @spacing-base @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__sub {
font-size: @font-size-base;
font-size: 11px;
}
}
</style>

View File

@@ -21,10 +21,9 @@ onMounted(() => {
<template>
<div class="profile">
<div class="profile__container">
<ProfileUserCard :profile="profile" @save-nickname="onSaveNickname" />
<div class="profile__body">
<aside class="profile__aside">
<ProfileUserCard :profile="profile" @save-nickname="onSaveNickname" />
<ProfileSider />
</aside>
<main class="profile__main">
@@ -44,30 +43,32 @@ onMounted(() => {
width: @container-width;
max-width: calc(100% - @spacing-xl);
margin: 0 auto;
padding-top: @spacing-xl;
padding-top: @spacing-lg;
}
&__body {
.flex(row, flex-start);
gap: @spacing-base;
margin-top: @spacing-base;
align-items: flex-start;
}
// 左列(设计14):紫渐变用户卡 + 菜单,直接坐在页面底色上,无外层白卡
&__aside {
width: 220px;
width: 114px; // 设计 148 × 0.77
flex-shrink: 0;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
overflow: hidden;
}
&__main {
flex: 1;
min-width: 0;
.flex(column, flex-start);
gap: @spacing-base;
}
// 右侧内容面板(设计14/28):整块白卡,内缩 16px 承载各页面
&__main {
flex: 1;
min-width: 0;
min-height: 400px;
padding: @spacing-base;
border-radius: @radius-base;
background: @white;
box-shadow: @shadow-base;
}
}
</style>

View File

@@ -112,6 +112,7 @@ onMounted(() => {
</template>
<style lang="less" scoped>
// 设计 17(资质列表):标题蓝条、整行白卡单列、分页靠右
.qual-page {
.flex(column, flex-start);
gap: @spacing-base;
@@ -120,21 +121,32 @@ onMounted(() => {
&__head {
.flex(row, space-between, center);
width: 100%;
padding: @spacing-base @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
padding: 0;
}
&__title {
font-size: @font-size-lg;
font-weight: 600;
position: relative;
padding-left: 12px;
font-size: 12px; // 设计 15 → 12
font-weight: 700;
color: @heading-color;
line-height: 20px;
&::before {
content: '';
position: absolute;
left: 0;
top: 3px;
width: 3px;
height: 14px;
border-radius: 2px;
background: @primary-strong;
}
}
&__grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: 1fr;
gap: @spacing-base;
width: 100%;
}
@@ -143,7 +155,35 @@ onMounted(() => {
grid-column: 1 / -1;
padding: @spacing-xxl 0;
text-align: center;
font-size: @font-size-base;
font-size: 11px;
}
:deep(.pagination) {
justify-content: flex-end;
padding: 0;
}
:deep(.pagination__btn.is-active) {
border-color: @profile-page-active-bg;
background: @profile-page-active-bg;
color: @primary-strong;
}
// 顶部「+ 新增资质」:小号蓝底按钮(设计 17 实取 #024FFF)
.app-button--primary {
height: 24px;
padding: 0 10px;
border: none;
border-radius: @profile-radius;
background: @primary-strong;
color: @white;
font-size: 11px;
font-weight: 500;
&:hover {
border: none;
background: darken(@primary-strong, 6%);
}
}
}
</style>

View File

@@ -187,6 +187,15 @@ onMounted(() => {
<template>
<div class="container after-sales">
<!-- 设计 12:页面顶部面包屑(与项目详情页同款) -->
<nav class="after-sales__breadcrumb">
<RouterLink to="/project" class="link">
项目中心
</RouterLink>
<span> &gt; </span>
<span>项目详情</span>
</nav>
<header class="after-sales__header">
<h1 class="after-sales__title">
申请售后
@@ -235,7 +244,7 @@ onMounted(() => {
<select
id="after-sales-project"
v-model="selectedProjectId"
class="after-sales__select"
class="after-sales__select after-sales__select--filled"
>
<option value="">
请选择项目
@@ -258,13 +267,13 @@ onMounted(() => {
rows="5"
placeholder="请详细描述您的问题..."
/>
<span class="after-sales__count text-secondary">{{ descriptionCount }}字</span>
<span class="after-sales__count">{{ descriptionCount }}字</span>
</div>
<div class="after-sales__field">
<div class="after-sales__field-head">
<label class="after-sales__label">附件上传</label>
<span class="after-sales__field-hint text-secondary">支持图片/文档/压缩包,大小不超过1G</span>
<span class="after-sales__field-hint">支持图片/文档/压缩包,大小不超过1G</span>
<AppButton
class="after-sales__upload-btn"
size="sm"
@@ -307,13 +316,13 @@ onMounted(() => {
rows="4"
placeholder="其他需要说明的事项..."
/>
<span class="after-sales__count text-secondary">{{ remarkCount }}字</span>
<span class="after-sales__count">{{ remarkCount }}字</span>
</div>
</section>
<!-- 底部操作条(设计稿:左侧提示 + 右侧 取消 / 重置 / 申请售后) -->
<footer class="after-sales__footer">
<p class="after-sales__footer-tip text-secondary">
<p class="after-sales__footer-tip">
<span class="after-sales__footer-icon" aria-hidden="true">i</span>
提交后我们的专业顾问将在一个工作日内与您联系,为您提供一对一服务
</p>
@@ -338,92 +347,131 @@ onMounted(() => {
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
// 设计 12:整页白底(蓝湖实测页面底 #FFFFFF)
background: @white;
// 面包屑(设计 24px × 0.77 ≈ 18px,#666666,字重 500)
&__breadcrumb {
font-size: 18px;
font-weight: 500;
color: @project-breadcrumb;
}
&__header {
.flex(column, flex-start, stretch);
gap: @spacing-xs;
padding: @spacing-sm 0 @spacing-base;
gap: 6px;
padding: 16px 0 0;
}
// 设计 12:主标题 22 设计px × 0.77 ≈ 17px / 700
&__title {
font-size: @font-size-title;
font-weight: 600;
font-size: 17px;
font-weight: 700;
color: @heading-color;
}
// 设计 12:副标题 13 设计px × 0.77 ≈ 11px、整行居中
&__subtitle {
font-size: @font-size-sm;
font-size: 11px;
text-align: center;
}
// ── 三段卡片(设计稿:白底圆角 + 序号圆标标题) ──
// ── 三段卡片(设计 12:白底 + 1px #F0F1F3 描边 + 圆角,无阴影) ──
&__card {
.flex(column, flex-start, stretch);
gap: @spacing-lg;
padding: @spacing-lg @spacing-xl;
gap: @spacing-base;
padding: 20px 24px;
border: 1px solid @project-divider;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
box-sizing: border-box;
}
// 设计 12:卡片标题 15 设计px × 0.77 ≈ 12px / 700 + 圆形序号
&__card-title {
.flex(row, flex-start, center);
gap: @spacing-sm;
font-size: @font-size-lg;
font-weight: 600;
gap: 12px;
font-size: 12px;
font-weight: 700;
color: @heading-color;
}
// 设计 12:序号圆 ≈26 设计px × 0.77、蓝底白字 12px / 700
&__step {
.flex(row, center);
width: 26px;
height: 26px;
width: 20px;
height: 20px;
border-radius: @radius-round;
background: @primary-color;
background: @project-accent;
color: @white;
font-size: @font-size-sm;
font-weight: 600;
font-size: 12px;
font-weight: 700;
line-height: 1;
}
&__field {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
gap: 4px;
position: relative;
}
// 设计 12:标签与提示同行,间距 14 设计px × 0.77
&__field-head {
.flex(row, flex-start, center);
gap: @spacing-sm;
gap: 11px;
}
// 设计 12:提示 11 设计px #9CA3AF
&__field-hint {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-disabled;
}
// 「上传文件」推到行尾
// 「上传文件」推到行尾(设计 12:浅灰底按钮)
&__upload-btn {
margin-left: auto;
}
&__label {
font-size: @font-size-base;
font-weight: 600;
color: @heading-color;
&__field-head :deep(.after-sales__upload-btn) {
height: 28px;
border: none;
border-radius: 6px;
background: @project-quiet-btn;
color: @text-color;
font-size: 12px;
&:hover {
border-color: transparent;
background: @project-quiet-btn;
color: @text-color;
}
}
// 设计 12:字段标签整行**居中**,13 设计px × 0.77 ≈ 11px / 500
&__label {
font-size: 11px;
font-weight: 500;
color: @heading-color;
text-align: center;
}
// 设计 12:星号与标签同色同字重(标注层整串同色)
&__required {
margin-left: 2px;
color: @danger-color;
font-weight: 400;
color: inherit;
font-weight: inherit;
}
// 设计 12:「售后类型」白底描边,「项目名称」灰底只读态(--filled)
&__select {
width: 100%;
height: 40px;
padding: 0 36px 0 @spacing-base;
height: 36px;
padding: 0 36px 0 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background-color: @bg-color-light;
border-radius: 6px;
background-color: @white;
color: @text-color;
font-size: @font-size-base;
font-size: 11px;
appearance: none;
outline: none;
cursor: pointer;
@@ -434,57 +482,77 @@ onMounted(() => {
background-size: 12px 12px;
transition: border-color 0.2s;
&::placeholder {
color: @text-color-disabled;
}
&:focus {
border-color: @primary-color;
}
// 设计 12:项目名称 = 灰底填充(#F3F4F6),无描边
&--filled {
border-color: transparent;
background-color: @input-bg;
}
}
// 「项目名称」与「售后类型」共用同一个下拉样式(见上方 &__select)
&__textarea {
width: 100%;
padding: @spacing-sm @spacing-base;
height: 104px;
padding: 10px 12px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
border-radius: 6px;
background: @white;
color: @text-color;
font-size: @font-size-base;
font-size: 11px;
line-height: 1.6;
resize: vertical;
outline: none;
box-sizing: border-box;
transition: border-color 0.2s;
&::placeholder {
color: @text-color-disabled;
}
&:focus {
border-color: @primary-color;
}
}
// 设计 12:字数统计在文本域**内部右下角**
&__count {
align-self: flex-end;
font-size: @font-size-sm;
position: absolute;
right: 12px;
bottom: 8px;
font-size: 11px;
color: @text-color-disabled;
}
&__file-input {
display: none;
}
// ── 底部固定操作条 ──
// ── 底部固定操作条(设计 12:顶部分隔线 #F0F1F3、白底、左提示右三键) ──
&__footer {
position: sticky;
bottom: 0;
z-index: 10;
.flex(row, space-between, center);
gap: @spacing-base;
margin-top: @spacing-sm;
padding: @spacing-base @spacing-xl;
border-top: 1px solid @border-color;
margin-top: 8px;
padding: 12px 0;
border-top: 1px solid @project-divider;
background: @white;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
}
&__footer-tip {
.flex(row, flex-start, center);
gap: @spacing-xs;
font-size: @font-size-sm;
gap: 6px;
font-size: 12px;
color: @text-color;
}
&__footer-icon {
@@ -501,8 +569,71 @@ onMounted(() => {
&__footer-actions {
.flex(row, flex-end, center);
gap: @spacing-sm;
gap: 12px;
flex-shrink: 0;
// 设计 12:取消 / 重置 = 浅灰底灰字,申请售后 = #024FFF 蓝底白字
:deep(.app-button) {
height: 32px;
border-radius: 6px;
font-size: 11px;
}
:deep(.app-button--default) {
border: none;
background: @project-quiet-btn;
color: @text-color;
&:hover {
border-color: transparent;
background: @project-quiet-btn;
color: @text-color;
}
}
:deep(.app-button--primary) {
background: @project-accent;
&:hover {
background: @primary-color;
}
}
}
// 设计 12:附件行 = #F7F8FA 圆角行、灰字操作(公共 FileList,仅本页覆写外观)
:deep(.file-list) {
gap: 12px;
}
:deep(.file-list__item) {
padding: 6px 14px;
border: none;
border-radius: 6px;
background: @finance-row-bg;
}
:deep(.file-list__name) {
font-size: 11px;
line-height: 15px;
}
:deep(.file-list__meta) {
font-size: 11px;
line-height: 15px;
color: @text-color-disabled;
}
:deep(.file-list__actions) {
gap: 12px;
}
:deep(.file-list__btn) {
font-size: 12px;
color: @text-color-secondary;
}
:deep(.file-list__btn--danger) {
color: @danger-color;
}
}
</style>

View File

@@ -76,12 +76,8 @@ function onDeleteFile(): void {
<!-- 规则 3:已完成 + 已提交售后 → 工单横幅 + 售后信息 + 取消售后 -->
<template v-else-if="hasTicket && afterSales">
<!-- 设计 10:整宽浅红提示横幅,只有标题 + 说明两行,无图标 -->
<div class="project-after-sales__banner">
<span class="project-after-sales__banner-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="currentColor">
<path d="M6 2h7l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Zm7 1.6V8h4.4L13 3.6ZM8 12.2h8v1.6H8v-1.6Zm0 3.6h8v1.6H8v-1.6Z" />
</svg>
</span>
<div class="project-after-sales__banner-text">
<h3 class="project-after-sales__banner-title">
售后工单处理中
@@ -113,7 +109,7 @@ function onDeleteFile(): void {
<div class="project-after-sales__field">
<div class="project-after-sales__field-head">
<span class="project-after-sales__label">附件上传</span>
<span class="project-after-sales__field-hint text-secondary">支持图片/文档/压缩包,大小不超过1G</span>
<span class="project-after-sales__field-hint">支持图片/文档/压缩包,大小不超过1G</span>
</div>
<FileList
v-if="afterSales.attachments.length > 0"
@@ -146,7 +142,7 @@ function onDeleteFile(): void {
</div>
<div class="project-after-sales__actions">
<button
class="project-after-sales__btn project-after-sales__btn--primary"
class="project-after-sales__btn project-after-sales__btn--apply"
@click="emit('apply')"
>
申请售后
@@ -159,29 +155,17 @@ function onDeleteFile(): void {
<style lang="less" scoped>
.project-after-sales {
.flex(column, flex-start, stretch);
gap: @spacing-lg;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
gap: @spacing-base;
// 设计 10:售后信息区块直接落在白底页面上,无外层卡片
padding: 0;
// ── 顶部工单横幅:浅红底 + 红色图标块(设计稿) ──
// ── 顶部工单横幅:浅红底、无图标块(设计 10 实取 #FDEEEE) ──
&__banner {
.flex(row, flex-start, center);
gap: @spacing-base;
padding: @spacing-base @spacing-lg;
border-radius: @radius-base;
background: fade(@danger-color, 8%);
}
&__banner-icon {
.flex(row, center);
flex-shrink: 0;
width: 44px;
height: 44px;
border-radius: @radius-base;
background: @danger-color;
color: @white;
margin-bottom: 16px;
padding: 12px 20px;
border-radius: 6px;
background: @project-banner-bg;
}
&__banner-text {
@@ -190,59 +174,72 @@ function onDeleteFile(): void {
min-width: 0;
}
// 设计 10:标题 17 设计px × 0.77 ≈ 13px / 700 红
&__banner-title {
font-size: @font-size-lg;
font-weight: 600;
color: @heading-color;
line-height: 1.2;
font-size: 13px;
font-weight: 700;
color: @project-banner-title;
line-height: 1.3;
}
// 设计 10:说明 13 设计px × 0.77 ≈ 11px #4B5563
&__banner-desc {
font-size: @font-size-sm;
color: @text-color-secondary;
font-size: 11px;
color: @text-color;
}
// ── 「售后信息」区块标题:竖条 + 15px 缩进(与其它页签一致) ──
// ── 「售后信息」区块标题:竖条 + 缩进(与其它页签一致) ──
&__title {
.section-title();
margin-top: 0;
padding-left: 9px;
font-size: 12px;
font-weight: 700;
margin-top: @spacing-xs;
&::before {
width: 3px;
height: 15px;
}
}
&__field {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
gap: 6px;
}
// 设计 10:标签与提示同行,间距 14 设计px × 0.77
&__field-head {
.flex(row, flex-start, baseline);
gap: @spacing-sm;
gap: 11px;
}
// 设计 10:提示 11 设计px #9CA3AF
&__field-hint {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-disabled;
}
// 设计 10:字段标签 13 设计px × 0.77 ≈ 11px / 500
&__label {
font-size: @font-size-base;
font-weight: 600;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
// 只读展示(设计稿里是灰底带边框的框,不是输入控件)
// 只读展示(设计 10:灰底圆角实底框,无描边)
&__readonly {
min-height: 40px;
padding: 0 @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
min-height: 36px;
padding: 0 12px;
border: none;
border-radius: 6px;
background: @input-bg;
color: @text-color;
font-size: @font-size-base;
line-height: 40px;
font-size: 11px;
line-height: 36px;
&--block {
min-height: 96px;
padding: @spacing-sm @spacing-base;
min-height: 104px;
padding: 12px;
line-height: 1.7;
white-space: pre-wrap;
word-break: break-word;
@@ -263,18 +260,22 @@ function onDeleteFile(): void {
font-size: @font-size-base;
}
// 设计 10:按钮组贴右,间距 34 设计px × 0.77
&__actions {
.flex(row, flex-end, center);
gap: @spacing-sm;
gap: 24px;
margin-top: 8px;
}
// 设计 10:高 ≈36 设计px × 0.77、圆角 ≈8 设计px、文字 15 设计px × 0.77
&__btn {
height: 36px;
padding: 0 @spacing-lg;
border-radius: @radius-base;
font-size: @font-size-base;
height: 28px;
padding: 0 14px;
border-radius: 6px;
font-size: 12px;
transition: all 0.2s;
// 「取消售后」= 品牌蓝(设计 10 实取 #1F67EF)
&--primary {
border: none;
background: @primary-color;
@@ -284,6 +285,53 @@ function onDeleteFile(): void {
background: @primary-hover;
}
}
// 「申请售后」= 红(设计 10 实取 #E3464B)
&--apply {
border: none;
background: @project-apply;
color: @white;
&:hover {
background: fade(@project-apply, 88%);
}
}
}
// 设计 10:附件行 = #F7F8FA 圆角行、灰字操作(公共 FileList,仅本页覆写外观)
:deep(.file-list) {
gap: 12px;
}
:deep(.file-list__item) {
padding: 6px 14px;
border: none;
border-radius: 6px;
background: @finance-row-bg;
}
:deep(.file-list__name) {
font-size: 11px;
line-height: 15px;
}
:deep(.file-list__meta) {
font-size: 11px;
line-height: 15px;
color: @text-color-disabled;
}
:deep(.file-list__actions) {
gap: 12px;
}
:deep(.file-list__btn) {
font-size: 12px;
color: @text-color-secondary;
}
:deep(.file-list__btn--danger) {
color: @danger-color;
}
}
</style>

View File

@@ -30,7 +30,7 @@ const emit = defineEmits<{
>
<div class="project-files__info">
<span class="project-files__name" :title="file.name">{{ file.name }}</span>
<span class="project-files__meta text-secondary">
<span class="project-files__meta">
{{ formatFileSize(file.size) }} · {{ file.uploadTime }}
</span>
</div>
@@ -60,27 +60,36 @@ const emit = defineEmits<{
.project-files {
.flex(column, flex-start, stretch);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
// 设计 11:项目文件区块直接落在白底页面上,无卡片
padding: 0;
&__title {
.section-title();
// 设计 11:竖条 4×20 设计px、文字 15 设计px/700
padding-left: 9px;
font-size: 12px;
font-weight: 700;
&::before {
width: 3px;
height: 15px;
}
}
&__list {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
// 设计 11:行间距 15 设计px × 0.77
gap: 12px;
}
// 设计 11:整行通铺 #F7F8FA 浅底、圆角 ≈8 设计px,无描边
&__item {
.flex(row, space-between);
gap: @spacing-base;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
padding: 6px 16px;
border: none;
border-radius: 6px;
background: @finance-row-bg;
}
&__info {
@@ -89,25 +98,31 @@ const emit = defineEmits<{
min-width: 0;
}
// 设计 11:文件名 13 设计px、副行 11 设计px #9CA3AF
&__name {
font-size: @font-size-base;
font-size: 11px;
line-height: 15px;
color: @heading-color;
.ellipsis();
}
&__meta {
font-size: @font-size-sm;
font-size: 11px;
line-height: 15px;
color: @text-color-disabled;
}
&__actions {
.flex(row, center);
gap: @spacing-sm;
// 设计 11:「预览 / 下载」间距 14 设计px × 0.77
gap: 12px;
flex-shrink: 0;
}
// 设计 11:行内操作是灰色纯文字(非蓝色),删除保持警示红
&__btn {
font-size: @font-size-sm;
color: @primary-color;
font-size: 12px;
color: @text-color-secondary;
transition: opacity 0.2s;
&:hover {

View File

@@ -122,26 +122,9 @@ function fileMeta(file: FileInfo): string {
</div>
<div class="project-finance__file-actions">
<button class="project-finance__act" type="button" @click="emit('preview', file)">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M1.5 8s2.4-4.5 6.5-4.5S14.5 8 14.5 8s-2.4 4.5-6.5 4.5S1.5 8 1.5 8Z"
stroke="currentColor"
stroke-width="1.2"
/>
<circle cx="8" cy="8" r="1.8" stroke="currentColor" stroke-width="1.2" />
</svg>
预览
</button>
<button class="project-finance__act" type="button" @click="emit('download', file)">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M8 2v8m0 0 3-3m-3 3L5 7M3 13h10"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
下载
</button>
</div>
@@ -168,26 +151,9 @@ function fileMeta(file: FileInfo): string {
</div>
<div class="project-finance__file-actions">
<button class="project-finance__act" type="button" @click="emit('preview', contractFile)">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M1.5 8s2.4-4.5 6.5-4.5S14.5 8 14.5 8s-2.4 4.5-6.5 4.5S1.5 8 1.5 8Z"
stroke="currentColor"
stroke-width="1.2"
/>
<circle cx="8" cy="8" r="1.8" stroke="currentColor" stroke-width="1.2" />
</svg>
预览
</button>
<button class="project-finance__act" type="button" @click="emit('download', contractFile)">
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
<path
d="M8 2v8m0 0 3-3m-3 3L5 7M3 13h10"
stroke="currentColor"
stroke-width="1.2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
下载
</button>
</div>
@@ -202,14 +168,20 @@ function fileMeta(file: FileInfo): string {
.project-finance {
.flex(column, flex-start, stretch);
gap: @spacing-base;
padding: @spacing-lg @spacing-xl;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
// 设计 09:合同财务区块直接落在白底页面上,无外层卡片
padding: 0;
// 区块标题:与「项目进度/项目文件/售后信息」同款(16px/600 + 左侧蓝色竖条)
// 区块标题:与「项目进度/项目文件/售后信息」同款(12px/700 + 左侧蓝色竖条)
&__title {
.section-title();
padding-left: 9px;
font-size: 12px;
font-weight: 700;
&::before {
width: 3px;
height: 15px;
}
}
// 只读回落态(后端未重启、响应无 bills)的说明行
@@ -222,23 +194,26 @@ function fileMeta(file: FileInfo): string {
// 设计稿:卡片**竖排单列、定宽左对齐**(不是横排多列网格)
&__plans {
.flex(column, flex-start, flex-start);
gap: @spacing-sm;
// 设计 09:卡片间距 13 设计px × 0.77
gap: 10px;
}
// 设计 09:白底 + 1px #F0F1F3 描边、圆角 ≈13 设计px,定宽竖排
&__plan {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
width: @finance-card-width;
padding: 12px;
padding: 14px 15px;
border: 1px solid @project-divider;
border-radius: @finance-card-radius;
background: @white;
// 设计稿用阴影立卡片、**不描边**;阴影比页面默认更淡,只做「浮起」暗示
box-shadow: @finance-card-shadow;
box-sizing: border-box;
// 三态配色(徽标实底白字 + 金额同色)
// 三态配色(浅底徽标 + 同色系金额)
&.is-paid {
.project-finance__badge {
background: @finance-paid;
background: @tag-success-bg;
color: @finance-paid;
}
.project-finance__amount {
@@ -248,7 +223,8 @@ function fileMeta(file: FileInfo): string {
&.is-pending {
.project-finance__badge {
background: @finance-pending;
background: @tag-warning-bg;
color: @tag-warning-text;
}
.project-finance__amount {
@@ -258,7 +234,8 @@ function fileMeta(file: FileInfo): string {
&.is-idle {
.project-finance__badge {
background: @finance-idle;
background: @tag-info-bg;
color: @text-color-secondary;
}
.project-finance__amount {
@@ -272,27 +249,27 @@ function fileMeta(file: FileInfo): string {
gap: @spacing-sm;
}
// 设计 09:期次标题 14 设计px × 0.77 ≈ 11px / 700
&__plan-name {
font-size: @font-size-base;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.8px;
color: @heading-color;
.ellipsis();
}
// 状态徽标:实底白字的小圆角块(设计 48×22 / 圆角 4 / 10 设计px 字号)
// 状态徽标:浅底彩色字(设计 09:约 57×22 设计px、圆角 4 设计px、11px 字)
&__badge {
.flex(row, center, center);
flex-shrink: 0;
padding: 2px @spacing-sm;
padding: 3px 10px;
border-radius: @radius-sm;
font-size: 11px;
line-height: 16px;
color: @white;
white-space: nowrap;
}
&__plan-body {
.flex(row, space-between, flex-start);
.flex(row, space-between, center);
gap: @spacing-base;
}
@@ -303,29 +280,30 @@ function fileMeta(file: FileInfo): string {
}
&__field {
font-size: @font-size-sm;
line-height: 17px;
font-size: 11px;
line-height: 16px;
color: @finance-meta-color;
.ellipsis();
}
// 金额:设计稿在卡片**右侧**、字号最大且随状态变色(不是左下角恒定深色)
// 金额:设计稿在卡片**右侧**、字号最大且随状态变色(20 设计px × 0.77 ≈ 15px)
&__amount {
flex-shrink: 0;
font-size: @font-size-xl;
font-size: 15px;
font-weight: 700;
line-height: 28px;
line-height: 22px;
white-space: nowrap;
}
// 「立即支付」:设计稿是卡内**满宽**金色胶囊(不是右下角的小蓝按钮)
// 「立即支付」:设计稿是卡内**满宽**金色按钮,通铺到卡片左右下缘
&__pay {
height: 22px;
height: 28px;
margin: 0 -15px -14px;
border: none;
border-radius: @radius-round;
border-radius: 0 0 @finance-card-radius @finance-card-radius;
background: @finance-pending;
color: @white;
font-size: @font-size-sm;
font-size: 12px;
cursor: pointer;
transition: background 0.2s;
@@ -338,17 +316,18 @@ function fileMeta(file: FileInfo): string {
&__files {
.flex(column, flex-start, stretch);
gap: @spacing-sm;
gap: 12px;
margin: 0;
padding: 0;
list-style: none;
}
// 设计稿:整行通铺浅灰底、无描边无圆角(区别于卡片)
// 设计稿:整行通铺 #F7F8FA 浅底、圆角 ≈8 设计px(区别于卡片)
&__file {
.flex(row, space-between, center);
gap: @spacing-sm;
padding: @spacing-sm @spacing-base;
padding: 6px 14px;
border-radius: 6px;
background: @finance-row-bg;
}
@@ -357,9 +336,9 @@ function fileMeta(file: FileInfo): string {
.flex(row, center, center);
flex-shrink: 0;
width: 34px;
height: 34px;
height: 20px;
border-radius: @radius-sm;
font-size: 10px;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.2px;
}
@@ -372,27 +351,30 @@ function fileMeta(file: FileInfo): string {
}
&__file-name {
font-size: @font-size-base;
font-size: 11px;
line-height: 15px;
color: @heading-color;
.ellipsis();
}
&__file-meta {
font-size: @font-size-sm;
color: @text-color-secondary;
font-size: 11px;
line-height: 15px;
color: @text-color-disabled;
}
&__file-actions {
.flex(row, flex-end, center);
gap: @spacing-base;
gap: 12px;
flex-shrink: 0;
}
// 设计 09:行内操作是灰色纯文字(非蓝色)
&__act {
.flex(row, center, center);
gap: 4px;
font-size: @font-size-sm;
color: @text-color;
font-size: 12px;
color: @text-color-secondary;
cursor: pointer;
transition: color 0.2s;

View File

@@ -67,56 +67,57 @@ function businessTypeText(project: Project): string {
<style lang="less" scoped>
.project-info-card {
.flex(row, flex-start, center);
gap: @spacing-base;
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
gap: 14px;
// 设计 09:标识 + 文字 + 右侧状态直接排在白底页面上,无卡片底/阴影/内边距
padding: 0;
&__logo {
.flex(row, center, center);
flex-shrink: 0;
width: 56px;
height: 56px;
border-radius: 14px;
background: @white;
box-shadow: @shadow-base;
// 设计 09:方块 ≈56 设计px × 0.77,浅灰底、圆角 ≈12 设计px × 0.77
width: 44px;
height: 44px;
border-radius: 12px;
background: @project-logo-bg;
}
// 设计 09:方块内只有蓝色「</>」文字,无描边徽标框
&__logo-badge {
.flex(row, center, center);
width: 34px;
height: 34px;
border: 2px solid @project-accent;
border-radius: 10px;
width: auto;
height: auto;
border: none;
border-radius: 0;
color: @project-accent;
font-family: Consolas, Menlo, 'Courier New', monospace;
font-size: @font-size-base;
font-weight: 700;
letter-spacing: -1px;
font-family: inherit;
font-size: 15px;
font-weight: 400;
letter-spacing: 0;
}
&__main {
.flex(column, flex-start, stretch);
flex: 1;
min-width: 0;
gap: @spacing-sm;
gap: 6px;
}
// 设计 09:主标题 19 设计px × 0.77 ≈ 15px / 700
&__name {
font-size: @font-size-title;
font-weight: 600;
font-size: 15px;
font-weight: 700;
line-height: 1.2;
color: @heading-color;
.ellipsis();
}
// 设计稿:三个字段是**单行**「标签:值」,等距排布
// 设计稿:三个字段是**单行**「标签:值」,等距排布(11px 小字号不跟缩)
&__meta {
.flex(row, flex-start, center);
flex-wrap: wrap;
gap: @spacing-lg;
font-size: @font-size-sm;
gap: 20px;
font-size: 11px;
font-weight: 500;
color: @heading-color;
}
@@ -128,12 +129,14 @@ function businessTypeText(project: Project): string {
&__label {
color: @text-color-secondary;
font-style: normal;
font-weight: 400;
}
// 设计 09:右侧状态是纯文字,16 设计px × 0.77 ≈ 12px / 700
&__status {
flex-shrink: 0;
font-size: @font-size-title;
font-weight: 600;
font-size: 12px;
font-weight: 700;
&.is-active {
color: @project-accent;

View File

@@ -50,7 +50,7 @@ function linkDone(index: number): boolean {
</span>
<span class="project-milestones__name">{{ node.name }}</span>
<!-- 设计稿:已完成节点显示完成时间,其余显示状态文案 -->
<span class="project-milestones__sub text-secondary">{{ node.time || node.status }}</span>
<span class="project-milestones__sub">{{ node.time || node.status }}</span>
</li>
</ol>
@@ -61,25 +61,32 @@ function linkDone(index: number): boolean {
</template>
<style lang="less" scoped>
// 节点列宽 = 设计稿相邻节点中心距(237 设计px × 0.77 ≈ 182px)
@milestone-node-width: 182px;
@milestone-dot-size: 32px;
// 节点列宽 = 设计稿相邻节点中心距(356 设计px × 0.77 ≈ 274px)
@milestone-node-width: 274px;
@milestone-dot-size: 18px;
.project-milestones {
.flex(column, flex-start, stretch);
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
// 设计 13:里程碑区块直接落在白底页面上,无卡片
padding: 0;
&__title {
.section-title();
// 设计 13:竖条 4×20 设计px、文字 15 设计px/700
padding-left: 9px;
font-size: 12px;
font-weight: 700;
&::before {
width: 3px;
height: 15px;
}
}
// 设计稿:轨迹从卡片左侧正文位起、**固定节距**左对齐(不铺满整宽)
// 设计稿:轨迹从容器左缘起、**固定节距**左对齐(不铺满整宽)
&__track {
.flex(row, flex-start, flex-start);
margin-top: @spacing-lg;
margin-top: 16px;
padding-bottom: @spacing-xs;
overflow-x: auto;
.scrollbar();
@@ -99,7 +106,7 @@ function linkDone(index: number): boolean {
left: calc(50% + @milestone-dot-size / 2);
width: calc(100% - @milestone-dot-size);
height: 2px;
background: @milestone-idle;
background: @milestone-line;
}
&.is-link-done:not(:last-child)::after {
@@ -113,12 +120,15 @@ function linkDone(index: number): boolean {
z-index: 1;
width: @milestone-dot-size;
height: @milestone-dot-size;
border: 2px solid @milestone-idle;
border: 3px solid @milestone-idle;
border-radius: @radius-round;
background: @white;
box-sizing: border-box;
// 设计 13:已完成圆点略小(20 设计px)、实心绿
.is-done & {
width: 16px;
height: 16px;
border-color: @milestone-done;
background: @milestone-done;
}
@@ -130,39 +140,40 @@ function linkDone(index: number): boolean {
}
&__check {
width: 16px;
height: 16px;
width: 10px;
height: 10px;
}
&__name {
margin-top: @spacing-sm;
max-width: 100%;
font-size: @font-size-base;
font-weight: 600;
font-size: 12px;
font-weight: 400;
text-align: center;
color: @text-color-secondary;
color: @text-color;
.multi-ellipsis(2);
.is-done & {
color: @milestone-done;
color: @success-color;
}
.is-active & {
color: @project-accent;
font-weight: 600;
}
}
&__sub {
margin-top: @spacing-xs;
max-width: 100%;
font-size: @font-size-sm;
font-size: 11px;
text-align: center;
color: @text-color-disabled;
.multi-ellipsis(2);
}
&__empty {
margin-top: @spacing-base;
padding-left: 21px;
font-size: @font-size-base;
}
}

View File

@@ -37,8 +37,8 @@ function clampPercent(value: number): number {
</div>
<div class="project-progress__range">
<span class="text-secondary">开始时间:{{ props.startTime || '—' }}</span>
<span class="text-secondary">结束时间:{{ props.endTime || '—' }}</span>
<span>开始时间:{{ props.startTime || '—' }}</span>
<span>结束时间:{{ props.endTime || '—' }}</span>
</div>
</section>
</template>
@@ -46,36 +46,43 @@ function clampPercent(value: number): number {
<style lang="less" scoped>
.project-progress {
.flex(column, flex-start, stretch);
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
// 设计 13:开发进度区块直接落在白底页面上,无卡片
padding: 0;
&__title {
.section-title();
// 设计 13:竖条 4×20 设计px、文字 15 设计px/700,条→文间距 8 设计px
padding-left: 9px;
font-size: 12px;
font-weight: 700;
&::before {
width: 3px;
height: 15px;
}
}
// 设计稿:正文块相对标题再右缩进一级(设计 27 设计px × 0.77 ≈ 21px)
// 设计 13:正文与容器左缘对齐(只有标题被竖条顶出一级)
&__head {
.flex(row, space-between, center);
margin-top: @spacing-base;
padding-left: 21px;
margin-top: 20px;
}
&__label {
font-size: @font-size-sm;
font-size: 12px;
}
// 设计 13:「65%」20 设计px × 0.77 ≈ 15px / 700
&__percent {
font-size: @font-size-title;
font-weight: 600;
font-size: 15px;
font-weight: 700;
color: @project-accent;
}
&__track {
position: relative;
height: 5px;
margin: @spacing-base 0 0 21px;
margin: 12px 0 0;
border-radius: @radius-round;
background: @project-track;
}
@@ -87,11 +94,12 @@ function clampPercent(value: number): number {
transition: width 0.3s;
}
// 设计 13:末端白底蓝环圆点 ≈15 设计px × 0.77
&__knob {
position: absolute;
top: 50%;
width: 16px;
height: 16px;
width: 12px;
height: 12px;
border: 2px solid @project-accent;
border-radius: @radius-round;
background: @white;
@@ -101,8 +109,10 @@ function clampPercent(value: number): number {
&__range {
.flex(row, space-between, center);
margin-top: @spacing-lg;
font-size: @font-size-sm;
margin-top: 10px;
font-size: 11px;
// 设计 13:起止时间 (156,163,175)
color: @text-color-disabled;
}
}
</style>

View File

@@ -22,7 +22,7 @@ defineProps<Props>()
>
<span class="project-team__avatar">{{ member.avatarChar }}</span>
<span class="project-team__name">{{ member.name || '—' }}</span>
<span class="project-team__role text-secondary">{{ member.role }}</span>
<span class="project-team__role">{{ member.role }}</span>
</li>
</ul>
@@ -33,27 +33,33 @@ defineProps<Props>()
</template>
<style lang="less" scoped>
// 设计稿实测:头像直径 90 设计px、相邻头像中心距 183 设计px → ×0.77 得 69px / 141px
@team-avatar-size: 68px;
@team-avatar-gap: 72px;
// 设计稿实测:头像直径 64 设计px、相邻头像中心距 99 设计px → ×0.77 得 49px / 76px(取整 48 / 间距 28)
@team-avatar-size: 48px;
@team-avatar-gap: 28px;
.project-team {
.flex(column, flex-start, stretch);
padding: @spacing-lg;
border-radius: @radius-lg;
background: @white;
box-shadow: @shadow-base;
// 设计 13:项目团队区块直接落在白底页面上,无卡片
padding: 0;
&__title {
.section-title();
// 设计 13:竖条 4×20 设计px、文字 15 设计px/700
padding-left: 9px;
font-size: 12px;
font-weight: 700;
&::before {
width: 3px;
height: 15px;
}
}
&__list {
.flex(row, flex-start, flex-start);
flex-wrap: wrap;
gap: @spacing-base @team-avatar-gap;
margin-top: @spacing-lg;
padding-left: 18px;
margin-top: 16px;
}
&__item {
@@ -61,6 +67,7 @@ defineProps<Props>()
width: @team-avatar-size;
}
// 设计 13:头像 = 品牌蓝实底圆 + 白色单字(16 设计px × 0.77 ≈ 12px)
&__avatar {
.flex(row, center, center);
width: @team-avatar-size;
@@ -68,14 +75,15 @@ defineProps<Props>()
border-radius: @radius-round;
background: @team-avatar-bg;
color: @white;
font-size: @font-size-title;
font-weight: 500;
font-size: 12px;
font-weight: 400;
}
// 设计 13:姓名 16 设计px/600,角色 12 设计px #9CA3AF
&__name {
margin-top: @spacing-sm;
margin-top: 16px;
max-width: 100%;
font-size: @font-size-lg;
font-size: 12px;
font-weight: 600;
color: @heading-color;
text-align: center;
@@ -85,14 +93,14 @@ defineProps<Props>()
&__role {
margin-top: @spacing-xs;
max-width: 100%;
font-size: @font-size-sm;
font-size: 12px;
text-align: center;
color: @text-color-disabled;
.ellipsis();
}
&__empty {
margin-top: @spacing-base;
padding-left: 18px;
font-size: @font-size-base;
}
}

View File

@@ -211,26 +211,33 @@ onMounted(load)
gap: @spacing-base;
padding-top: @spacing-lg;
padding-bottom: @spacing-xxl;
// 设计 09/10/11/13:详情内容区是整片白底、无卡片(蓝湖实测页面底 #FFFFFF)
background: @white;
// 面包屑(设计 24px × 0.77 ≈ 18px,#666666,字重 500)
&__breadcrumb {
font-size: @font-size-sm;
font-size: 18px;
font-weight: 500;
color: @project-breadcrumb;
}
// 设计稿:页签无白底容器,仅一行文字 + 激活项 2px 下划线;相邻间距实测 ≈50px
// 设计稿:页签无白底容器,仅一行文字 + 激活项下划线,下缘 1px 通栏分割线;
// 首个页签文字与内容区左缘对齐(间距 = 86 设计px 节距 − 文字宽 ≈ 22px)
&__tabs {
.flex(row, flex-start, center);
gap: 50px;
padding: 0 @spacing-base;
gap: 22px;
border-bottom: 1px solid @project-divider;
}
&__tab {
position: relative;
padding: 0 0 @spacing-sm;
padding: 0 0 16px;
border: none;
background: transparent;
color: @text-color;
font-size: @font-size-base;
line-height: 20px;
font-size: 11px;
font-weight: 400;
line-height: 14px;
transition: color 0.2s;
&:hover {
@@ -245,6 +252,7 @@ onMounted(load)
&.is-active {
color: @project-accent;
font-weight: 600;
&::after {
content: '';

View File

@@ -31,49 +31,55 @@ const emit = defineEmits<{ download: [] }>()
<style lang="less" scoped>
.chat-file-card {
.flex(row, center);
gap: @spacing-sm;
min-width: 220px;
gap: 8px; // 图标→文件名 11 × 0.77
min-width: 181px; // 设计 38 文件卡宽 235 × 0.77
max-width: 320px;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
padding: 10px 12px; // 卡内边距 13/15 × 0.77
border: 1px solid @project-divider; // 设计 38 卡描边 ≈ @project-divider
border-radius: 6px;
background: @white;
&__icon {
font-size: @font-size-xl;
flex-shrink: 0;
font-size: 14px;
line-height: 1;
}
&__info {
.flex(column, flex-start);
gap: 2px;
.flex(column, flex-start, flex-start);
gap: 4px;
flex: 1;
min-width: 0;
}
// 设计 38:文件名 12 → 11 / 700 / #1F2937
&__name {
font-size: @font-size-base;
font-size: 11px;
font-weight: 700;
color: @heading-color;
.ellipsis();
}
// 设计 38:大小 12 → 11 / #9CA3AF
&__size {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-disabled;
}
&__download {
flex-shrink: 0;
height: 26px;
padding: 0 @spacing-sm;
border: 1px solid @primary-color;
border-radius: @radius-sm;
height: 22px;
padding: 0 8px;
border: 1px solid @border-color;
border-radius: 4px;
background: @white;
color: @primary-color;
font-size: @font-size-sm;
color: @text-color-secondary;
font-size: 11px;
transition: all 0.2s;
&:hover {
background: @primary-light;
border-color: @primary-strong;
color: @primary-strong;
}
}
}

View File

@@ -86,42 +86,49 @@ function onFileChange(event: Event): void {
<style lang="less" scoped>
.chat-input {
.flex(column, flex-start);
gap: @spacing-sm;
padding: @spacing-base;
border-top: 1px solid @border-color;
.flex(column, flex-start, stretch);
gap: 16px; // 输入框→提示行 23 × 0.77
padding: 12px 16px 24px; // 上 13 / 左右 21 / 下 36 × 0.77
border-top: 1px solid @project-divider; // 设计 38 分割线 @project-divider
background: @white;
// 设计 38:文本域灰底无描边,占位文案 #1F2937(13 → 11)
&__textarea {
width: 100%;
padding: @spacing-sm @spacing-base;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @bg-color-light;
color: @text-color;
font-size: @font-size-base;
height: 57px; // 文本域高 74 × 0.77(覆盖 rows 固有高)
padding: 11px 10px;
border: none;
border-radius: 6px;
background: @finance-row-bg; // 设计 38 实取 @finance-row-bg
color: @heading-color;
font-size: 11px;
line-height: 1.6;
resize: none;
outline: none;
transition: border-color 0.2s;
transition: background 0.2s;
box-sizing: border-box;
&:focus {
border-color: @primary-color;
border: none;
background: @finance-row-bg;
}
&::placeholder {
color: @text-color-disabled;
color: @heading-color; // 设计 38 占位即标注 @heading-color
}
}
&__bar {
.flex(row, space-between);
gap: @spacing-base;
align-items: center;
width: 100%;
}
// 设计 38:提示 11 / #9CA3AF(覆盖 text-secondary)
&__hint {
font-size: @font-size-sm;
font-size: 11px;
color: @text-color-disabled;
}
&__actions {
@@ -131,22 +138,38 @@ function onFileChange(event: Event): void {
&__attach {
.flex(row, center);
width: 32px;
height: 32px;
border: 1px solid @border-color;
border-radius: @radius-base;
background: @white;
font-size: @font-size-lg;
width: 28px;
height: 28px;
border: none;
border-radius: @radius-sm;
background: transparent;
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
&:hover {
border-color: @primary-color;
background: @bg-color-light;
}
}
&__file {
display: none;
}
// 「发送」:设计 38 #024FFF 小按钮(12 → 11 / 500)
.app-button {
height: 24px; // 31 × 0.77
padding: 0 14px;
border-radius: 6px;
background: @primary-strong;
color: @white;
font-size: 11px;
font-weight: 500;
&:hover {
background: @primary-strong;
color: @white;
}
}
}
</style>

View File

@@ -38,70 +38,84 @@ const emit = defineEmits<{ download: [] }>()
<style lang="less" scoped>
.chat-message-item {
.flex(row, flex-start);
gap: @spacing-sm;
.flex(row, flex-start, flex-start); // 头像与气泡顶对齐(设计 38)
gap: 9px; // 头像→气泡 12 × 0.77
// 设计 38:头像直径 36 × 0.77;客服 #024FFF,用户 #8D99AE
&__avatar {
flex-shrink: 0;
.flex(row, center);
width: 36px;
height: 36px;
width: 28px;
height: 28px;
border-radius: @radius-round;
background: @primary-light;
color: @primary-color;
font-size: @font-size-base;
font-weight: 600;
background: @primary-strong;
color: @white;
font-size: 12px; // 16 → 12
font-weight: 400;
&--user {
background: fade(@success-color, 15%);
color: @success-color;
background: @service-user-avatar;
color: @white;
}
}
&__main {
.flex(column, flex-start);
gap: @spacing-xs;
max-width: 70%;
.flex(column, flex-start, flex-start);
gap: 4px;
max-width: 320px; // 气泡最宽 ≈ 设计 410 × 0.77
}
// 设计 38:客服气泡白底轻影;13 → 11 / #1F2937
&__bubble {
position: relative;
padding: @spacing-sm @spacing-base;
border-radius: @radius-base;
padding: 9px 12px; // 内边距 12/15 × 0.77
border-radius: 8px;
background: @white;
box-shadow: @shadow-base;
color: @text-color;
font-size: @font-size-base;
line-height: 1.7;
color: @heading-color;
font-size: 11px;
line-height: 1.75;
white-space: pre-wrap;
word-break: break-word;
}
&__time {
font-size: @font-size-sm;
// 文件消息:文件卡自身成卡,气泡去内边距/底色/影(设计 38 单层卡)
&__bubble:has(.chat-file-card) {
padding: 0;
background: transparent;
box-shadow: none;
}
// 设计 38:消息时间 11 / #9CA3AF
&__time {
font-size: 11px;
color: @text-color-disabled;
}
// 设计 38:「未读」挂在文件卡左下外侧,10 → 11 / #9CA3AF,无底色
&__unread {
position: absolute;
top: -8px;
right: -6px;
padding: 0 6px;
border-radius: @radius-round;
background: @danger-color;
color: @white;
font-size: @font-size-sm;
line-height: 16px;
top: 100%;
left: 0;
margin-top: 6px;
padding: 0;
background: transparent;
color: @text-color-disabled;
font-size: 11px;
font-weight: 400;
line-height: 1.3;
}
&--user {
.flex(row, flex-end);
.flex(row, flex-end, flex-start);
.chat-message-item__main {
align-items: flex-end;
}
// 设计 38:我方气泡 #024FFF 白字
.chat-message-item__bubble {
background: @primary-color;
background: @primary-strong;
color: @white;
}
}

Some files were not shown because too many files have changed in this diff Show More