feat: 完成70%全局样式与可读性优化

This commit is contained in:
rain
2026-07-31 11:27:15 +08:00
parent 96524e4d6c
commit 555aa00043
116 changed files with 1928 additions and 1169 deletions
+31
View File
@@ -0,0 +1,31 @@
<template>
<image class="app-avatar" :src="avatarSource" mode="aspectFill" />
</template>
<script setup>
import { computed } from "vue";
import { getDefaultAvatar } from "@/utils/avatar.js";
const props = defineProps({
sex: {
type: [String, Number],
default: "",
},
src: {
type: String,
default: "",
},
});
const avatarSource = computed(
() => props.src.trim() || getDefaultAvatar(props.sex),
);
</script>
<style scoped>
.app-avatar {
display: block;
width: 100%;
height: 100%;
}
</style>
+9 -7
View File
@@ -15,7 +15,7 @@
@click="handleClick"
>
<image class="app-button__skin" :src="skin" mode="aspectFit" />
<text class="app-button__label"
<text class="app-button__label app-single-line"
><slot>{{ label }}</slot></text
>
</button>
@@ -45,7 +45,7 @@ const handleClick = (event) => {
</script>
<style scoped lang="scss">
@use "../styles/adaptive-frame-profiles.scss" as adaptive;
@import "../styles/adaptive-frame-profiles.scss";
.app-button {
display: inline-grid;
@@ -70,17 +70,17 @@ const handleClick = (event) => {
.app-button--compact {
}
.app-button--compact.app-button--primary {
@include adaptive.adaptive-scroll-button(primary);
@include adaptive-scroll-button(primary);
}
.app-button--compact.app-button--secondary {
@include adaptive.adaptive-scroll-button(secondary);
@include adaptive-scroll-button(secondary);
}
.app-button--compact .app-button__skin {
display: none;
}
.app-button--compact .app-button__label {
padding: 0;
font-size: 23rpx;
font-size: clamp(14px, 23rpx, 17px);
letter-spacing: 0;
white-space: nowrap;
}
@@ -95,11 +95,13 @@ const handleClick = (event) => {
}
.app-button__label {
z-index: 1;
padding: 0 38rpx;
padding: 12rpx 38rpx;
box-sizing: border-box;
color: #fffaf0;
font-size: 29rpx;
font-size: clamp(16px, 29rpx, 20px);
font-weight: 700;
letter-spacing: 3rpx;
line-height: 1.35;
text-align: center;
}
.app-button--secondary .app-button__label {
+9 -5
View File
@@ -116,7 +116,7 @@ const cancel = () => {
</script>
<style scoped lang="scss">
@use "../styles/adaptive-frame-profiles.scss" as adaptive;
@import "../styles/adaptive-frame-profiles.scss";
.app-dialog-layer {
position: fixed;
@@ -136,7 +136,7 @@ const cancel = () => {
max-height: calc(var(--app-viewport-height, 100vh) - 80rpx - env(safe-area-inset-top) - env(safe-area-inset-bottom));
flex-direction: column;
overflow: hidden;
@include adaptive.adaptive-auth-dialog;
@include adaptive-auth-dialog;
}
.app-dialog__content {
z-index: 1;
@@ -163,13 +163,13 @@ const cancel = () => {
}
.app-dialog__eyebrow {
color: #9f170f;
font-size: 22rpx;
font-size: clamp(14px, 22rpx, 17px);
font-weight: 700;
letter-spacing: 4rpx;
}
.app-dialog__title {
color: #8f160f;
font-size: 42rpx;
font-size: clamp(22px, 42rpx, 28px);
font-weight: 700;
letter-spacing: 4rpx;
}
@@ -179,7 +179,7 @@ const cancel = () => {
.app-dialog__message {
margin-top: 22rpx;
color: #513a28;
font-size: 27rpx;
font-size: clamp(16px, 27rpx, 20px);
line-height: 1.65;
}
.app-dialog__actions {
@@ -189,6 +189,10 @@ const cancel = () => {
gap: 16rpx;
margin-top: 26rpx;
}
.app-dialog__actions :deep(.app-button__label) {
padding-right: 18rpx;
padding-left: 18rpx;
}
.app-dialog__actions--single {
display: flex;
justify-content: center;
+4 -4
View File
@@ -82,11 +82,11 @@ defineProps({
}
.app-loading--page .app-loading__copy {
margin-top: 22rpx;
font-size: 30rpx;
font-size: clamp(17px, 30rpx, 22px);
}
.app-loading--page .app-loading__description {
margin-top: 14rpx;
font-size: 24rpx;
font-size: clamp(15px, 24rpx, 18px);
}
.app-loading--section {
@@ -103,11 +103,11 @@ defineProps({
}
.app-loading--section .app-loading__copy {
margin-top: 14rpx;
font-size: 24rpx;
font-size: clamp(15px, 24rpx, 18px);
}
.app-loading--section .app-loading__description {
margin-top: 10rpx;
font-size: 22rpx;
font-size: clamp(14px, 22rpx, 17px);
}
@keyframes app-loading-seal-breathe {
0%,
+5 -2
View File
@@ -17,7 +17,7 @@
mode="aspectFit"
aria-hidden="true"
/>
<text :class="['tab-label', { active: active === item.key }]">{{
<text :class="['tab-label', 'app-single-line', { active: active === item.key }]">{{
item.label
}}</text>
</button>
@@ -77,6 +77,7 @@ const switchRoot = (item) => {
.tab-item {
display: flex;
min-width: 0;
min-height: 88rpx;
flex: 1;
flex-direction: column;
@@ -104,10 +105,12 @@ const switchRoot = (item) => {
}
.tab-label {
max-width: 100%;
color: $ink-muted;
font-size: 30rpx;
font-size: clamp(17px, 30rpx, 22px);
letter-spacing: 2rpx;
line-height: 1.2;
text-align: center;
}
.tab-label.active {
+3 -3
View File
@@ -18,7 +18,7 @@ defineProps({
</script>
<style scoped lang="scss">
@use "../styles/adaptive-frame-profiles.scss" as adaptive;
@import "../styles/adaptive-frame-profiles.scss";
.app-toast {
position: fixed;
@@ -31,7 +31,7 @@ defineProps({
min-height: 82rpx;
align-items: center;
justify-content: center;
@include adaptive.adaptive-feedback-toast;
@include adaptive-feedback-toast;
transform: translateX(-50%);
pointer-events: none;
}
@@ -39,7 +39,7 @@ defineProps({
z-index: 1;
padding: 14rpx 30rpx;
color: #5c4330;
font-size: 25rpx;
font-size: clamp(15px, 25rpx, 18px);
font-weight: 500;
line-height: 1.45;
text-align: center;
+30 -10
View File
@@ -6,16 +6,17 @@
src="/static/assets/modules/auth/opaque/a01-vnext-header-v1.png"
mode="widthFix"
/>
<image
class="auth-shell__seal"
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
/>
<view class="auth-shell__brand-lockup">
<image
class="auth-shell__seal"
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
/>
<text class="auth-shell__project-name">代代相传</text>
</view>
</view>
<view class="auth-shell__paper">
<slot />
</view>
<view class="auth-shell__paper"><slot /></view>
<slot name="overlay" />
</view>
@@ -51,13 +52,21 @@
pointer-events: none;
}
.auth-shell__seal {
.auth-shell__brand-lockup {
position: absolute;
top: calc(var(--app-safe-top) + clamp(46px, 11.5vw, 58px));
left: 50%;
display: flex;
align-items: center;
gap: 12rpx;
transform: translateX(-50%);
white-space: nowrap;
}
.auth-shell__seal {
position: static;
width: clamp(56px, 17vw, 78px);
height: clamp(67px, 20.4vw, 94px);
transform: translateX(-50%);
pointer-events: none;
}
@@ -75,4 +84,15 @@
background-size: 100% auto, 100% auto;
background-repeat: no-repeat, repeat-y;
}
.auth-shell__project-name {
color: #f8dfa6;
font-family: "STKaiti", "KaiTi", serif;
font-size: clamp(14px, 24rpx, 17px);
font-weight: 700;
letter-spacing: 4rpx;
line-height: 1;
white-space: nowrap;
}
</style>
+84 -85
View File
@@ -27,36 +27,34 @@
<view class="card-main">
<view class="card-title-row">
<text class="card-name">{{ genealogy.name }}</text>
<view class="card-side">
<text class="card-role">{{ role }}</text>
<image
class="card-chevron"
src="/static/assets/foundation/transparent/chevron-right.png"
mode="aspectFit"
/>
</view>
<image
class="card-chevron"
src="/static/assets/foundation/transparent/chevron-right.png"
mode="aspectFit"
/>
</view>
<view class="card-detail-row">
<view class="card-updated">
<text>更新于 {{ genealogy.updatedAt }}</text>
<view class="card-meta-item card-meta-item--location">
<image
class="card-meta-icon"
src="/static/assets/foundation/transparent/meta-location.png"
mode="aspectFit"
/>
<text class="card-meta">{{ genealogy.location }}</text>
</view>
<view class="card-metas">
<view class="card-meta-item">
<image
class="card-meta-icon"
src="/static/assets/foundation/transparent/meta-location.png"
mode="aspectFit"
/>
<text class="card-meta">{{ genealogy.location }}</text>
</view>
<view class="card-meta-item">
<image
class="card-meta-icon"
src="/static/assets/foundation/transparent/meta-member.png"
mode="aspectFit"
/>
<text class="card-meta">{{ genealogy.memberCount }} 位成员</text>
</view>
<view class="card-meta-item card-meta-item--members">
<image
class="card-meta-icon"
src="/static/assets/foundation/transparent/meta-member.png"
mode="aspectFit"
/>
<text class="card-meta">{{ genealogy.memberCount }} 位成员</text>
</view>
<view class="card-trailing">
<text class="card-role app-single-line">{{ role }}</text>
<text v-if="genealogy.updatedAt" class="card-updated app-single-line"
>更新于 {{ genealogy.updatedAt }}</text
>
</view>
</view>
</view>
@@ -82,13 +80,13 @@ const accessibleLabel = computed(
<style scoped lang="scss">
.genealogy-card {
--card-padding-x: 24rpx;
--card-padding-y: 18rpx;
--card-padding-y: 20rpx;
display: grid;
grid-template-columns: 72rpx minmax(0, 1fr);
min-height: 178rpx;
grid-template-columns: 68rpx minmax(0, 1fr);
min-height: 204rpx;
align-items: center;
column-gap: 22rpx;
padding: 18rpx 24rpx;
column-gap: 20rpx;
padding: 20rpx 24rpx;
box-sizing: border-box;
background: transparent;
}
@@ -114,8 +112,8 @@ const accessibleLabel = computed(
grid-column: 1;
grid-row: 1;
z-index: 2;
width: 72rpx;
height: 112rpx;
width: 68rpx;
height: 106rpx;
place-items: center;
color: #fff5df;
}
@@ -132,14 +130,14 @@ const accessibleLabel = computed(
.surname-seal-copy {
z-index: 1;
display: flex;
height: 82rpx;
height: 78rpx;
align-items: center;
justify-content: center;
}
.seal-title {
color: #fff5df;
font-family: "STKaiti", "KaiTi", serif;
font-size: 30rpx;
font-size: clamp(17px, 30rpx, 22px);
font-weight: 700;
letter-spacing: 2rpx;
line-height: 1;
@@ -165,45 +163,47 @@ const accessibleLabel = computed(
.card-title-row {
display: flex;
min-width: 0;
align-items: flex-start;
align-items: center;
justify-content: space-between;
gap: 12rpx;
}
.card-name {
min-width: 0;
flex: 1;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 37rpx;
font-size: clamp(18px, 34rpx, 23px);
font-weight: 700;
line-height: 1.25;
overflow: hidden;
overflow-wrap: anywhere;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.card-detail-row {
display: flex;
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
min-width: 0;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
margin-top: 8rpx;
}
.card-metas {
display: flex;
min-width: 0;
width: 100%;
flex-wrap: wrap;
align-items: center;
margin-top: 2rpx;
gap: 4rpx 18rpx;
column-gap: 16rpx;
row-gap: 4rpx;
margin-top: 10rpx;
}
.card-meta-item {
display: flex;
min-width: 0;
align-items: center;
margin-right: 0;
}
.card-meta-item--location {
grid-column: 1 / -1;
}
.card-meta-item--members {
grid-column: 1;
}
.card-meta-icon {
width: 46rpx;
height: 46rpx;
width: 38rpx;
height: 38rpx;
flex: 0 0 auto;
margin-right: 6rpx;
opacity: 1;
@@ -212,73 +212,72 @@ const accessibleLabel = computed(
.card-meta {
min-width: 0;
color: #62584c;
font-size: 26rpx;
font-size: clamp(15px, 24rpx, 18px);
font-weight: 500;
overflow-wrap: anywhere;
}
.card-trailing {
grid-column: 2;
display: flex;
min-width: 0;
align-items: flex-end;
justify-content: center;
row-gap: 4rpx;
flex-direction: column;
}
.card-updated {
display: flex;
width: 100%;
flex: 0 0 auto;
align-items: center;
justify-content: flex-end;
margin-top: 0;
margin-left: 0;
color: #62584c;
font-size: 24rpx;
font-size: clamp(14px, 22rpx, 17px);
font-weight: 500;
line-height: 1.35;
white-space: nowrap;
overflow-wrap: anywhere;
}
.card-side {
z-index: 1;
display: flex;
min-width: 0;
flex: 0 1 auto;
flex-direction: row;
align-items: center;
justify-content: flex-end;
margin-left: 20rpx;
}
.card-role {
min-width: 0;
color: #62584c;
font-size: 26rpx;
font-weight: 500;
overflow-wrap: anywhere;
padding: 3rpx 10rpx 4rpx;
border: 1rpx solid rgba(181, 138, 75, 0.56);
border-radius: 999rpx;
color: #7f4f16;
font-size: clamp(14px, 23rpx, 17px);
font-weight: 600;
line-height: 1.25;
white-space: nowrap;
}
.card-chevron {
width: 34rpx;
height: 34rpx;
margin-left: 14rpx;
width: 30rpx;
height: 30rpx;
margin-left: 8rpx;
}
@media screen and (max-width: 340px) {
.genealogy-card {
--card-padding-x: 18rpx;
grid-template-columns: 66rpx minmax(0, 1fr);
grid-template-columns: 62rpx minmax(0, 1fr);
column-gap: 16rpx;
min-height: 148rpx;
min-height: 176rpx;
padding-right: 18rpx;
padding-left: 18rpx;
}
.surname-seal {
width: 66rpx;
height: 100rpx;
width: 62rpx;
height: 96rpx;
}
.card-name {
font-size: 32rpx;
font-size: clamp(17px, 32rpx, 22px);
}
.card-meta {
font-size: 22rpx;
font-size: clamp(14px, 22rpx, 17px);
}
.card-updated {
display: none;
}
.card-side {
margin-left: 12rpx;
}
.card-chevron {
width: 28rpx;
height: 28rpx;
+1
View File
@@ -27,4 +27,5 @@
width: 100%;
opacity: 0.28;
}
</style>
+60 -6
View File
@@ -46,7 +46,20 @@
</button>
</view>
<text class="header-title">{{ title }}</text>
<view
class="header-project-lockup"
:class="{ 'header-project-lockup--root': root }"
>
<image
v-if="!root"
class="header-project-lockup__logo"
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
aria-hidden="true"
/>
<text class="header-project-name">代代相传</text>
</view>
<text class="header-title app-single-line">{{ title }}</text>
<view class="header-side header-side--right">
<button
@@ -65,10 +78,10 @@
</button>
<button
v-else-if="root && action"
class="header-action header-action--root"
class="header-action header-action--root app-single-line"
@click="$emit('action')"
>{{ action }}</button>
<button v-else-if="action" class="header-action" @click="$emit('action')">{{
<button v-else-if="action" class="header-action app-single-line" @click="$emit('action')">{{
action
}}</button>
<view
@@ -168,6 +181,7 @@ const handleBack = () => {
.header-side {
display: flex;
flex: 0 0 120rpx;
width: 120rpx;
min-height: 88rpx;
align-items: center;
@@ -179,6 +193,10 @@ const handleBack = () => {
.header-side--right {
justify-content: flex-end;
}
.page-header:not(.page-header--root) .header-side--right {
flex-basis: 152rpx;
width: 152rpx;
}
.header-icon-button {
display: grid;
@@ -246,9 +264,12 @@ const handleBack = () => {
border: 0;
background: transparent;
color: #ffe3a7;
font-size: 27rpx;
font-size: clamp(16px, 27rpx, 20px);
line-height: normal;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.header-action-placeholder {
width: 100%;
@@ -280,12 +301,45 @@ const handleBack = () => {
.header-back--pressed {
opacity: 0.62;
}
.header-project-lockup {
position: absolute;
top: calc(var(--status-bar-height, 0px) + 52rpx);
left: 112rpx;
z-index: 3;
display: flex;
align-items: center;
gap: 7rpx;
transform: translateY(-50%);
pointer-events: none;
}
.header-project-lockup--root {
top: calc(var(--status-bar-height, 0px) + 62rpx);
left: 116rpx;
}
.header-project-lockup__logo {
width: 34rpx;
height: 34rpx;
flex: 0 0 auto;
}
.header-project-name {
color: #ffe3a7;
font-family: "STKaiti", "KaiTi", serif;
font-size: clamp(11px, 19rpx, 14px);
font-weight: 700;
letter-spacing: 3rpx;
line-height: 1;
white-space: nowrap;
}
.header-title {
min-width: 0;
flex: 1;
overflow: hidden;
color: #fff9ed;
font-family: serif;
font-size: 35rpx;
font-size: clamp(19px, 35rpx, 24px);
font-weight: 700;
letter-spacing: 4rpx;
text-align: center;
@@ -296,7 +350,7 @@ const handleBack = () => {
.page-header--root .header-title {
color: #ffe3a7;
font-family: "STKaiti", "KaiTi", serif;
font-size: 48rpx;
font-size: clamp(24px, 48rpx, 30px);
letter-spacing: 5rpx;
transform: translateY(2rpx);
}