diff --git a/scripts/extract-vue-styles.mjs b/scripts/extract-vue-styles.mjs
new file mode 100644
index 0000000..a4799c2
--- /dev/null
+++ b/scripts/extract-vue-styles.mjs
@@ -0,0 +1,68 @@
+import fs from 'node:fs'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src')
+
+function walk(dir, files = []) {
+ for (const name of fs.readdirSync(dir)) {
+ const full = path.join(dir, name)
+ if (fs.statSync(full).isDirectory())
+ walk(full, files)
+ else if (name.endsWith('.vue'))
+ files.push(full)
+ }
+ return files
+}
+
+function extractVue(vuePath) {
+ const content = fs.readFileSync(vuePath, 'utf8')
+ const base = path.basename(vuePath, '.vue')
+ const dir = path.dirname(vuePath)
+ const scssPath = path.join(dir, `${base}.scss`)
+
+ const patterns = [
+ {
+ regex: /`,
+ },
+ {
+ regex: /`,
+ },
+ {
+ regex: /`,
+ },
+ {
+ regex: /`,
+ },
+ ]
+
+ for (const { regex, replacement } of patterns) {
+ const match = content.match(regex)
+ if (!match)
+ continue
+
+ const styleBody = match[1].trimEnd()
+ if (styleBody.includes(`@import './${base}.scss'`))
+ return false
+
+ fs.writeFileSync(scssPath, `${styleBody}\n`, 'utf8')
+ const next = content.replace(regex, replacement())
+ fs.writeFileSync(vuePath, next, 'utf8')
+ return true
+ }
+
+ return false
+}
+
+const vueFiles = walk(root)
+let count = 0
+for (const file of vueFiles) {
+ if (extractVue(file))
+ count += 1
+}
+
+console.log(`Extracted styles from ${count} Vue files.`)
diff --git a/src/App.scss b/src/App.scss
new file mode 100644
index 0000000..8958c3c
--- /dev/null
+++ b/src/App.scss
@@ -0,0 +1,6 @@
+@import '@/styles/fonts.scss';
+
+page {
+ font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', sans-serif;
+ background-color: #ffffff;
+}
diff --git a/src/App.vue b/src/App.vue
index dc0a09c..600ba39 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -5,10 +5,5 @@ onLaunch(() => {})
diff --git a/src/components/AppFooter.scss b/src/components/AppFooter.scss
new file mode 100644
index 0000000..e8326a3
--- /dev/null
+++ b/src/components/AppFooter.scss
@@ -0,0 +1,12 @@
+.footer{
+ position: absolute;
+ bottom: 1rem;
+ left: 50%;
+ transform: translateX(-50%);
+ color: #888;
+}
+.uni-helper-github__image {
+ display: inline-block;
+ height: 1em;
+ width: 1em;
+}
diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue
index 61049b6..469d7f8 100644
--- a/src/components/AppFooter.vue
+++ b/src/components/AppFooter.vue
@@ -18,17 +18,6 @@ function handleClickGithub() {
-
diff --git a/src/components/AppLogos.scss b/src/components/AppLogos.scss
new file mode 100644
index 0000000..3703b1f
--- /dev/null
+++ b/src/components/AppLogos.scss
@@ -0,0 +1,34 @@
+.container {
+ display: inline-flex;
+ font-size: 1.5rem;
+ font-weight: 300;
+ &:hover {
+ .link-bar {
+ transform: rotate(135deg);
+ }
+ }
+}
+.uni-helper-logo {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ .uni-helper-logo__image {
+ display: inline-block;
+ height: 4.5rem;
+ width: 4.5rem;
+ }
+ .uni-helper-logo__label {
+ margin-top: -0.5rem;
+ }
+ .green {
+ color: #22c55e;
+ };
+ .purple {
+ color: #a855f7;
+ }
+}
+.link-bar {
+ color: #9ca3af;
+ margin: auto 1em;
+ transition: all 500ms cubic-bezier(0.4, 0, 0.2, 1);
+}
diff --git a/src/components/AppLogos.vue b/src/components/AppLogos.vue
index 8779ca6..4acd6bf 100644
--- a/src/components/AppLogos.vue
+++ b/src/components/AppLogos.vue
@@ -22,38 +22,5 @@
diff --git a/src/components/AppTabBar.scss b/src/components/AppTabBar.scss
new file mode 100644
index 0000000..4b9fc41
--- /dev/null
+++ b/src/components/AppTabBar.scss
@@ -0,0 +1,38 @@
+@import '@/styles/variables.scss';
+
+.app-tab-bar {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+ padding: 12rpx 0 calc(12rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.app-tab-bar__item {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+}
+
+.app-tab-bar__icon {
+ width: 44rpx;
+ height: 44rpx;
+}
+
+.app-tab-bar__label {
+ margin-top: 6rpx;
+ font-size: 20rpx;
+ color: $color-text-secondary;
+
+ &--active {
+ color: $color-primary;
+ font-weight: 500;
+ }
+}
diff --git a/src/components/AppTabBar.vue b/src/components/AppTabBar.vue
index d8b16ad..4349286 100644
--- a/src/components/AppTabBar.vue
+++ b/src/components/AppTabBar.vue
@@ -48,42 +48,5 @@ function handleSwitch(path: string, key: TabKey) {
diff --git a/src/components/InputEntry.scss b/src/components/InputEntry.scss
new file mode 100644
index 0000000..484dba8
--- /dev/null
+++ b/src/components/InputEntry.scss
@@ -0,0 +1,16 @@
+.input-box {
+ margin: 1rem;
+ padding: 0.5rem;
+ border-bottom: 1px solid gray;
+}
+.popup {
+ position: fixed;
+ top: 2rem;
+ left: 0px;
+ right: 0px;
+ .popup_label {
+ padding: 0.5rem 2rem;
+ background: gray;
+ border-radius: 8px;
+ }
+}
diff --git a/src/components/InputEntry.vue b/src/components/InputEntry.vue
index b63a59a..92a40a0 100644
--- a/src/components/InputEntry.vue
+++ b/src/components/InputEntry.vue
@@ -33,20 +33,5 @@ function handleClick() {
diff --git a/src/constants/bill-list.ts b/src/constants/bill-list.ts
new file mode 100644
index 0000000..9ba6ac9
--- /dev/null
+++ b/src/constants/bill-list.ts
@@ -0,0 +1,49 @@
+import { PROJECT_CENTER_LIST } from '@/constants/project-center'
+import { getProjectDetail } from '@/constants/project-detail'
+import type { BillItem, BillListSummary } from '@/types/bill'
+
+const PAID_BILL_META: Record = {
+ '1-1': {
+ paidAt: '2026-01-21 15:00:00',
+ paidMethod: 'wechat',
+ transactionNo: 'T20260819153035678K2M001',
+ },
+}
+
+function buildBillList(): BillItem[] {
+ const bills: BillItem[] = []
+
+ PROJECT_CENTER_LIST.forEach((project) => {
+ const detail = getProjectDetail(project.id)
+ if (!detail)
+ return
+
+ detail.paymentPlans.forEach((plan) => {
+ const metaKey = `${project.id}-${plan.id}`
+ const paidMeta = PAID_BILL_META[metaKey]
+
+ bills.push({
+ ...plan,
+ projectId: project.id,
+ billNo: plan.id === '1' && project.id === '1' ? '20260813ZZ251245' : plan.billNo,
+ transactionNo: paidMeta?.transactionNo || plan.transactionNo,
+ paidAt: paidMeta?.paidAt,
+ paidMethod: paidMeta?.paidMethod,
+ })
+ })
+ })
+
+ return bills
+}
+
+export const BILL_LIST: BillItem[] = buildBillList()
+
+export const BILL_LIST_SUMMARY: BillListSummary = {
+ totalCount: 10,
+ totalAmount: '40.0万',
+ pendingCount: 3,
+}
+
+export function getBill(projectId: string, planId: string): BillItem | null {
+ return BILL_LIST.find(bill => bill.projectId === projectId && bill.id === planId) || null
+}
diff --git a/src/constants/personal-center.ts b/src/constants/personal-center.ts
new file mode 100644
index 0000000..2f6b2ef
--- /dev/null
+++ b/src/constants/personal-center.ts
@@ -0,0 +1,37 @@
+import type { PersonalCenterMenuItem, PersonalCenterProfile } from '@/types/personal-center'
+import avatarIcon from '@/static/icon/avatar.png'
+import iconAbout from '@/static/icon/about.png'
+import iconAddress from '@/static/icon/address.png'
+import iconContractList from '@/static/icon/contract-list.png'
+import iconFavorites from '@/static/icon/favorites.png'
+import iconFeedback from '@/static/icon/feedback.png'
+import iconFinance from '@/static/icon/finance.png'
+import iconHelp from '@/static/icon/help.png'
+import iconInvoice from '@/static/icon/invoice.png'
+import iconMessagePush from '@/static/icon/message-push.png'
+import iconQualification from '@/static/icon/qualification.png'
+import iconSecurity from '@/static/icon/security.png'
+import iconServiceHotline from '@/static/icon/service-hotline.png'
+
+export const PERSONAL_CENTER_PROFILE: PersonalCenterProfile = {
+ nickname: '这里是昵称',
+ phone: '13589898989',
+ avatar: avatarIcon,
+}
+
+export const PERSONAL_CENTER_MENU: PersonalCenterMenuItem[] = [
+ { key: 'security', label: '账号安全', icon: iconSecurity },
+ { key: 'message-push', label: '消息推送', icon: iconMessagePush },
+ { key: 'feedback', label: '意见反馈', icon: iconFeedback },
+ { key: 'contract-list', label: '合同列表', icon: iconContractList },
+ { key: 'finance', label: '财务管理', icon: iconFinance, path: '/pages/project-center/bill-list/index' },
+ { key: 'invoice', label: '发票列表', icon: iconInvoice },
+ { key: 'address', label: '地址管理', icon: iconAddress },
+ { key: 'favorites', label: '收藏列表', icon: iconFavorites, path: '/pages/case-library/favorites/index' },
+ { key: 'qualification', label: '资质列表', icon: iconQualification },
+ { key: 'help', label: '帮助中心', icon: iconHelp },
+ { key: 'about', label: '关于我们', icon: iconAbout },
+ { key: 'service-hotline', label: '专属客服热线', icon: iconServiceHotline },
+]
+
+export const PERSONAL_CENTER_SERVICE_HOTLINE = '400-000-0000'
diff --git a/src/constants/project-detail.ts b/src/constants/project-detail.ts
index 6341e98..0d1dea0 100644
--- a/src/constants/project-detail.ts
+++ b/src/constants/project-detail.ts
@@ -47,6 +47,48 @@ const DEFAULT_FILES = [
{ id: '3', name: '参考图.png', icon: '/static/icons/PNG.png' },
]
+const DEFAULT_PAYMENT_PLANS = [
+ {
+ id: '1',
+ title: '第一期·预付款',
+ ratio: '比例33%',
+ status: 'paid' as const,
+ transactionNo: '202608131104121251',
+ billNo: '202608131104121251',
+ relatedProject: '社区康养智慧系统',
+ amount: 20100,
+ },
+ {
+ id: '2',
+ title: '第二期·进度款',
+ ratio: '比例33%',
+ status: 'pending' as const,
+ transactionNo: '202608131104121252',
+ billNo: '202608131104121252',
+ relatedProject: '社区康养智慧系统',
+ amount: 20100,
+ },
+ {
+ id: '3',
+ title: '第三期·尾款',
+ ratio: '比例34%',
+ status: 'not_due' as const,
+ transactionNo: '202608131104121253',
+ billNo: '202608131104121253',
+ relatedProject: '社区康养智慧系统',
+ amount: 20100,
+ },
+]
+
+const DEFAULT_AFTER_SALES = {
+ processing: true,
+ bannerTitle: '售后工单处理中',
+ bannerDesc: '工程师正在处理您的修改需求,请耐心等待',
+ type: 'bug问题',
+ description: '具体请看清单',
+ attachments: DEFAULT_FILES.map(file => ({ ...file, id: `as-${file.id}` })),
+}
+
function buildDetail(item: typeof PROJECT_CENTER_LIST[number]): ProjectDetail {
const progress = item.progress ?? 0
@@ -57,8 +99,19 @@ function buildDetail(item: typeof PROJECT_CENTER_LIST[number]): ProjectDetail {
steps: DEFAULT_STEPS.map(step => ({ ...step })),
team: DEFAULT_TEAM.map(member => ({ ...member })),
files: DEFAULT_FILES.map(file => ({ ...file })),
- financeSummary: '合同金额已确认,当前处于开发阶段付款节点,发票与回款记录可在后台查看。',
- afterSalesSummary: '项目交付后将提供一年免费运维服务,支持 7×24 小时远程技术支持与故障响应。',
+ paymentPlans: DEFAULT_PAYMENT_PLANS.map(plan => ({ ...plan })),
+ paymentPlanFiles: DEFAULT_FILES.map((file, index) => ({
+ ...file,
+ id: `pay-${index + 1}`,
+ })),
+ contractFiles: DEFAULT_FILES.map((file, index) => ({
+ ...file,
+ id: `contract-${index + 1}`,
+ })),
+ afterSales: {
+ ...DEFAULT_AFTER_SALES,
+ attachments: DEFAULT_AFTER_SALES.attachments.map(file => ({ ...file })),
+ },
progress,
}
}
@@ -70,3 +123,17 @@ const PROJECT_DETAIL_MAP: Record = Object.fromEntries(
export function getProjectDetail(id: string): ProjectDetail | null {
return PROJECT_DETAIL_MAP[id] || null
}
+
+export function getPaymentPlan(projectId: string, planId: string) {
+ const detail = getProjectDetail(projectId)
+ if (!detail)
+ return null
+
+ return detail.paymentPlans.find(plan => plan.id === planId) || null
+}
+
+export const PAYMENT_PLAN_STATUS_LABEL: Record = {
+ paid: '已支付',
+ pending: '待支付',
+ not_due: '未到期',
+}
diff --git a/src/pages.json b/src/pages.json
index 3772666..0aae421 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -115,6 +115,36 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/project-center/payment/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/project-center/payment-success/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/project-center/bill-list/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/project-center/bill-detail/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/project-center/after-sales-apply/index",
+ "style": {
+ "navigationStyle": "custom"
+ }
+ },
{
"path": "pages/personal-center/index",
"style": {
diff --git a/src/pages/Login/splash/index.scss b/src/pages/Login/splash/index.scss
new file mode 100644
index 0000000..1772f78
--- /dev/null
+++ b/src/pages/Login/splash/index.scss
@@ -0,0 +1,53 @@
+@import '@/styles/variables.scss';
+
+.splash {
+ position: relative;
+ width: 100vw;
+ height: 100vh;
+ overflow: hidden;
+ background: linear-gradient(180deg, $color-splash-gradient-start 0%, $color-splash-gradient-end 100%);
+}
+
+.splash__bg-circle {
+ position: absolute;
+ top: 50%;
+ right: -120rpx;
+ width: 520rpx;
+ height: 520rpx;
+ border-radius: 50%;
+ background: $color-splash-circle;
+ transform: translateY(-50%);
+}
+
+.splash__content {
+ position: relative;
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding-top: 38vh;
+}
+
+.splash__logo {
+ width: 160rpx;
+ height: 160rpx;
+}
+
+.splash__title {
+ margin-top: 40rpx;
+ font-family: 'Alimama FangYuanTi VF-Bold', 'Alimama FangYuanTi VF', sans-serif;
+ font-size: 61.07rpx;
+ font-weight: 700;
+ font-variation-settings: 'wght' 700, 'BEVL' 100;
+ color: $color-text-primary;
+ letter-spacing: 2rpx;
+}
+
+.splash__subtitle {
+ margin-top: 16rpx;
+ font-family: 'PingFangSC-Regular', 'PingFang SC', sans-serif;
+ font-size: 22.9rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+ letter-spacing: 1rpx;
+}
diff --git a/src/pages/Login/splash/index.vue b/src/pages/Login/splash/index.vue
index 348ca75..2d493eb 100644
--- a/src/pages/Login/splash/index.vue
+++ b/src/pages/Login/splash/index.vue
@@ -33,57 +33,5 @@ onMounted(() => {
diff --git a/src/pages/Login/user-agreement/index.scss b/src/pages/Login/user-agreement/index.scss
new file mode 100644
index 0000000..01db819
--- /dev/null
+++ b/src/pages/Login/user-agreement/index.scss
@@ -0,0 +1,86 @@
+@import '@/styles/variables.scss';
+
+.user-agreement-page {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ background: $color-bg-page;
+}
+
+.user-agreement-page__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: calc(env(safe-area-inset-top) + 20rpx) 32rpx 20rpx;
+ background: $color-bg-page;
+ border-bottom: 1rpx solid #f0f0f0;
+}
+
+.user-agreement-page__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.user-agreement-page__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.user-agreement-page__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.user-agreement-page__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.user-agreement-page__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.user-agreement-page__content {
+ padding: 32rpx 40rpx calc(40rpx + env(safe-area-inset-bottom));
+}
+
+.user-agreement-page__doc-title {
+ display: block;
+ margin-bottom: 24rpx;
+ font-size: 36rpx;
+ font-weight: 700;
+ line-height: 1.5;
+ color: $color-text-primary;
+}
+
+.user-agreement-page__date {
+ display: block;
+ margin-bottom: 8rpx;
+ font-size: 28rpx;
+ line-height: 1.6;
+ color: $color-text-primary;
+}
+
+.user-agreement-page__section-title {
+ display: block;
+ margin-top: 40rpx;
+ margin-bottom: 16rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ line-height: 1.5;
+ color: $color-text-primary;
+}
+
+.user-agreement-page__paragraph {
+ display: block;
+ margin-bottom: 16rpx;
+ font-size: 28rpx;
+ line-height: 1.8;
+ color: $color-text-primary;
+ text-align: justify;
+}
diff --git a/src/pages/Login/user-agreement/index.vue b/src/pages/Login/user-agreement/index.vue
index d07c69d..92cd5ab 100644
--- a/src/pages/Login/user-agreement/index.vue
+++ b/src/pages/Login/user-agreement/index.vue
@@ -70,90 +70,5 @@ function handleBack() {
diff --git a/src/pages/Login/user-forgot-password/components/CodeInput.scss b/src/pages/Login/user-forgot-password/components/CodeInput.scss
new file mode 100644
index 0000000..dd27f8f
--- /dev/null
+++ b/src/pages/Login/user-forgot-password/components/CodeInput.scss
@@ -0,0 +1,47 @@
+@import '@/styles/variables.scss';
+
+.code-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 16rpx 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.code-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.code-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
+
+.code-input__btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ height: 64rpx;
+ padding: 0 24rpx;
+ background: $color-primary;
+ border-radius: 32rpx;
+
+ &--disabled {
+ opacity: 0.6;
+ }
+}
+
+.code-input__btn-text {
+ font-size: 24rpx;
+ font-weight: 500;
+ color: #ffffff;
+ white-space: nowrap;
+}
diff --git a/src/pages/Login/user-forgot-password/components/CodeInput.vue b/src/pages/Login/user-forgot-password/components/CodeInput.vue
index 3ddc55e..a45f64c 100644
--- a/src/pages/Login/user-forgot-password/components/CodeInput.vue
+++ b/src/pages/Login/user-forgot-password/components/CodeInput.vue
@@ -61,51 +61,5 @@ function handleGetCode() {
diff --git a/src/pages/Login/user-forgot-password/components/ForgotInput.scss b/src/pages/Login/user-forgot-password/components/ForgotInput.scss
new file mode 100644
index 0000000..b16322c
--- /dev/null
+++ b/src/pages/Login/user-forgot-password/components/ForgotInput.scss
@@ -0,0 +1,25 @@
+@import '@/styles/variables.scss';
+
+.forgot-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.forgot-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.forgot-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
diff --git a/src/pages/Login/user-forgot-password/components/ForgotInput.vue b/src/pages/Login/user-forgot-password/components/ForgotInput.vue
index 755527e..3087ee8 100644
--- a/src/pages/Login/user-forgot-password/components/ForgotInput.vue
+++ b/src/pages/Login/user-forgot-password/components/ForgotInput.vue
@@ -34,29 +34,5 @@ function onInput(e: { detail: { value: string } }) {
diff --git a/src/pages/Login/user-forgot-password/components/PasswordField.scss b/src/pages/Login/user-forgot-password/components/PasswordField.scss
new file mode 100644
index 0000000..f946fab
--- /dev/null
+++ b/src/pages/Login/user-forgot-password/components/PasswordField.scss
@@ -0,0 +1,32 @@
+@import '@/styles/variables.scss';
+
+.password-field {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.password-field__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.password-field__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
+
+.password-field__eye {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-left: 16rpx;
+}
diff --git a/src/pages/Login/user-forgot-password/components/PasswordField.vue b/src/pages/Login/user-forgot-password/components/PasswordField.vue
index efb43e6..ba12cce 100644
--- a/src/pages/Login/user-forgot-password/components/PasswordField.vue
+++ b/src/pages/Login/user-forgot-password/components/PasswordField.vue
@@ -47,36 +47,5 @@ function toggleVisible() {
diff --git a/src/pages/Login/user-forgot-password/index.scss b/src/pages/Login/user-forgot-password/index.scss
new file mode 100644
index 0000000..e55f9f0
--- /dev/null
+++ b/src/pages/Login/user-forgot-password/index.scss
@@ -0,0 +1,127 @@
+@import '@/styles/variables.scss';
+
+.forgot-page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ padding: 0 64rpx;
+ background: $color-bg-page;
+}
+
+.forgot-page__header {
+ padding-top: 120rpx;
+ text-align: center;
+}
+
+.forgot-page__title {
+ display: block;
+ font-size: 56rpx;
+ font-weight: 700;
+ color: $color-text-primary;
+ letter-spacing: 2rpx;
+}
+
+.forgot-page__subtitle {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 28rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+}
+
+.forgot-page__form {
+ width: 100%;
+ margin-top: 80rpx;
+ box-sizing: border-box;
+}
+
+.forgot-page__field {
+ width: 100%;
+ margin-top: 24rpx;
+ box-sizing: border-box;
+}
+
+.forgot-page__agreement {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 32rpx;
+}
+
+.forgot-page__checkbox {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+ margin-top: 4rpx;
+ margin-right: 12rpx;
+ border: 2rpx solid #cccccc;
+ border-radius: 50%;
+ transition: all 0.2s;
+
+ &--checked {
+ background: $color-primary;
+ border-color: $color-primary;
+ }
+}
+
+.forgot-page__checkmark {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #ffffff;
+ line-height: 1;
+}
+
+.forgot-page__agreement-text {
+ flex: 1;
+ font-size: 24rpx;
+ line-height: 1.6;
+}
+
+.forgot-page__agreement-normal {
+ color: $color-text-secondary;
+}
+
+.forgot-page__agreement-link {
+ color: $color-text-link;
+}
+
+.forgot-page__submit {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 96rpx;
+ margin-top: 48rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ border: none;
+ border-radius: 48rpx;
+ line-height: 96rpx;
+
+ &::after {
+ border: none;
+ }
+}
+
+.forgot-page__footer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-top: auto;
+ padding: 60rpx 0 calc(60rpx + env(safe-area-inset-bottom));
+}
+
+.forgot-page__footer-normal {
+ font-size: 28rpx;
+ color: $color-text-secondary;
+}
+
+.forgot-page__footer-link {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ color: $color-text-link;
+}
diff --git a/src/pages/Login/user-forgot-password/index.vue b/src/pages/Login/user-forgot-password/index.vue
index 2b3eeb8..73c13ae 100644
--- a/src/pages/Login/user-forgot-password/index.vue
+++ b/src/pages/Login/user-forgot-password/index.vue
@@ -143,131 +143,5 @@ function handleUserAgreement() {
diff --git a/src/pages/Login/user-login/components/LoginInput.scss b/src/pages/Login/user-login/components/LoginInput.scss
new file mode 100644
index 0000000..f954a4c
--- /dev/null
+++ b/src/pages/Login/user-login/components/LoginInput.scss
@@ -0,0 +1,32 @@
+@import '@/styles/variables.scss';
+
+.login-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.login-input__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.login-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.login-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
diff --git a/src/pages/Login/user-login/components/LoginInput.vue b/src/pages/Login/user-login/components/LoginInput.vue
index c4f8574..f0554ce 100644
--- a/src/pages/Login/user-login/components/LoginInput.vue
+++ b/src/pages/Login/user-login/components/LoginInput.vue
@@ -42,36 +42,5 @@ function onInput(e: { detail: { value: string } }) {
diff --git a/src/pages/Login/user-login/index.scss b/src/pages/Login/user-login/index.scss
new file mode 100644
index 0000000..6409e9d
--- /dev/null
+++ b/src/pages/Login/user-login/index.scss
@@ -0,0 +1,188 @@
+@import '@/styles/variables.scss';
+
+.login-page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ padding: 0 64rpx;
+ background: $color-bg-page;
+}
+
+.login-page__header {
+ padding-top: 120rpx;
+ text-align: center;
+}
+
+.login-page__title {
+ display: block;
+ font-size: 56rpx;
+ font-weight: 700;
+ color: $color-text-primary;
+ letter-spacing: 2rpx;
+}
+
+.login-page__subtitle {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 28rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+}
+
+.login-page__form {
+ width: 100%;
+ margin-top: 80rpx;
+ box-sizing: border-box;
+}
+
+.login-page__password-group {
+ margin-top: 24rpx;
+}
+
+.login-page__forgot {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.login-page__agreement {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 32rpx;
+}
+
+.login-page__checkbox {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+ margin-top: 4rpx;
+ margin-right: 12rpx;
+ border: 2rpx solid #cccccc;
+ border-radius: 50%;
+ transition: all 0.2s;
+
+ &--checked {
+ background: $color-primary;
+ border-color: $color-primary;
+ }
+}
+
+.login-page__checkmark {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #ffffff;
+ line-height: 1;
+}
+
+.login-page__agreement-text {
+ flex: 1;
+ font-size: 24rpx;
+ line-height: 1.6;
+}
+
+.login-page__agreement-normal {
+ color: $color-text-secondary;
+}
+
+.login-page__agreement-link {
+ color: $color-text-link;
+}
+
+.login-page__submit {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 96rpx;
+ margin-top: 48rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ border: none;
+ border-radius: 48rpx;
+ line-height: 96rpx;
+
+ &::after {
+ border: none;
+ }
+}
+
+.login-page__other {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 60rpx 0;
+}
+
+.login-page__divider {
+ display: flex;
+ align-items: center;
+ width: 100%;
+}
+
+.login-page__divider-line {
+ flex: 1;
+ height: 1rpx;
+ background: #e8e8e8;
+}
+
+.login-page__divider-text {
+ padding: 0 24rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+ white-space: nowrap;
+}
+
+.login-page__sms {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: fit-content;
+ margin-top: 48rpx;
+}
+
+.login-page__sms-icon-wrap {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 96rpx;
+ height: 96rpx;
+ background: #B6CDFF;
+ border-radius: 50%;
+}
+
+.login-page__sms-icon {
+ width: 48rpx;
+ height: 48rpx;
+}
+
+.login-page__sms-text {
+ margin-top: 16rpx;
+ font-size: 24rpx;
+ color: #999999;
+}
+
+.login-page__footer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-bottom: calc(60rpx + env(safe-area-inset-bottom));
+}
+
+.login-page__footer-normal {
+ font-size: 28rpx;
+ color: $color-text-secondary;
+}
+
+.login-page__footer-link {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ color: $color-text-link;
+}
diff --git a/src/pages/Login/user-login/index.vue b/src/pages/Login/user-login/index.vue
index 77161fc..d3e4215 100644
--- a/src/pages/Login/user-login/index.vue
+++ b/src/pages/Login/user-login/index.vue
@@ -172,192 +172,5 @@ function handleUserAgreement() {
diff --git a/src/pages/Login/user-register-success/index.scss b/src/pages/Login/user-register-success/index.scss
new file mode 100644
index 0000000..664e8bd
--- /dev/null
+++ b/src/pages/Login/user-register-success/index.scss
@@ -0,0 +1,36 @@
+@import '@/styles/variables.scss';
+
+.result-page {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 100vh;
+ background: $color-bg-page;
+}
+
+.result-page__content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 0 64rpx;
+}
+
+.result-page__icon {
+ width: 160rpx;
+ height: 160rpx;
+}
+
+.result-page__title {
+ margin-top: 48rpx;
+ font-size: 40rpx;
+ font-weight: 700;
+ color: $color-text-primary;
+ letter-spacing: 1rpx;
+}
+
+.result-page__subtitle {
+ margin-top: 24rpx;
+ font-size: 28rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+}
diff --git a/src/pages/Login/user-register-success/index.vue b/src/pages/Login/user-register-success/index.vue
index dd8c19f..aa799d8 100644
--- a/src/pages/Login/user-register-success/index.vue
+++ b/src/pages/Login/user-register-success/index.vue
@@ -8,11 +8,19 @@ import {
} from '@/types/result-page'
const pageType = ref('register')
+const projectId = ref('')
const countdown = ref(RESULT_REDIRECT_DELAY / 1000)
let timer: ReturnType | null = null
const pageConfig = computed(() => RESULT_PAGE_CONFIG[pageType.value])
+const redirectUrl = computed(() => {
+ if (pageType.value === 'afterSalesSuccess' && projectId.value) {
+ return `${pageConfig.value.redirectUrl}?id=${encodeURIComponent(projectId.value)}&tab=aftersales`
+ }
+ return pageConfig.value.redirectUrl
+})
+
const title = computed(() => pageConfig.value.title)
const subtitle = computed(() => `${countdown.value}秒后自动跳转至${pageConfig.value.subtitleTarget}`)
@@ -29,6 +37,13 @@ onLoad((options) => {
}
if (type === 'submitSuccess') {
pageType.value = 'submitSuccess'
+ return
+ }
+ if (type === 'afterSalesSuccess') {
+ pageType.value = 'afterSalesSuccess'
+ const id = options?.id
+ if (id)
+ projectId.value = decodeURIComponent(String(id))
}
})
@@ -41,7 +56,7 @@ onMounted(() => {
timer = null
}
uni.redirectTo({
- url: pageConfig.value.redirectUrl,
+ url: redirectUrl.value,
})
}
}, 1000)
@@ -74,40 +89,5 @@ onUnmounted(() => {
diff --git a/src/pages/Login/user-register/components/CodeInput.scss b/src/pages/Login/user-register/components/CodeInput.scss
new file mode 100644
index 0000000..9641dc9
--- /dev/null
+++ b/src/pages/Login/user-register/components/CodeInput.scss
@@ -0,0 +1,54 @@
+@import '@/styles/variables.scss';
+
+.code-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 16rpx 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.code-input__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.code-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.code-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
+
+.code-input__btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ height: 64rpx;
+ padding: 0 24rpx;
+ background: $color-primary;
+ border-radius: 32rpx;
+
+ &--disabled {
+ opacity: 0.6;
+ }
+}
+
+.code-input__btn-text {
+ font-size: 24rpx;
+ font-weight: 500;
+ color: #ffffff;
+ white-space: nowrap;
+}
diff --git a/src/pages/Login/user-register/components/CodeInput.vue b/src/pages/Login/user-register/components/CodeInput.vue
index 1556e8f..4d009e6 100644
--- a/src/pages/Login/user-register/components/CodeInput.vue
+++ b/src/pages/Login/user-register/components/CodeInput.vue
@@ -66,58 +66,5 @@ function handleGetCode() {
diff --git a/src/pages/Login/user-register/components/PasswordField.scss b/src/pages/Login/user-register/components/PasswordField.scss
new file mode 100644
index 0000000..d1f1b01
--- /dev/null
+++ b/src/pages/Login/user-register/components/PasswordField.scss
@@ -0,0 +1,39 @@
+@import '@/styles/variables.scss';
+
+.password-field {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.password-field__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.password-field__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.password-field__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
+
+.password-field__eye {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-left: 16rpx;
+}
diff --git a/src/pages/Login/user-register/components/PasswordField.vue b/src/pages/Login/user-register/components/PasswordField.vue
index cd4dcb6..b5dd833 100644
--- a/src/pages/Login/user-register/components/PasswordField.vue
+++ b/src/pages/Login/user-register/components/PasswordField.vue
@@ -52,43 +52,5 @@ function toggleVisible() {
diff --git a/src/pages/Login/user-register/components/PasswordStrength.scss b/src/pages/Login/user-register/components/PasswordStrength.scss
new file mode 100644
index 0000000..8a8ce49
--- /dev/null
+++ b/src/pages/Login/user-register/components/PasswordStrength.scss
@@ -0,0 +1,59 @@
+.password-strength {
+ width: 100%;
+ margin-top: 16rpx;
+}
+
+.password-strength__row {
+ display: flex;
+ align-items: center;
+}
+
+.password-strength__bars {
+ display: flex;
+ flex: 1;
+ gap: 12rpx;
+}
+
+.password-strength__bar {
+ flex: 1;
+ height: 8rpx;
+ background: #e8e8e8;
+ border-radius: 4rpx;
+}
+
+.password-strength__label {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ font-size: 24rpx;
+ font-weight: 500;
+}
+
+.password-strength__error {
+ display: flex;
+ align-items: center;
+ margin-top: 12rpx;
+}
+
+.password-strength__error-icon {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 28rpx;
+ height: 28rpx;
+ margin-right: 8rpx;
+ // background: #ff4d4f;
+ border-radius: 6rpx;
+}
+
+.password-strength__error-mark {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #ffffff;
+ line-height: 1;
+}
+
+.password-strength__error-text {
+ font-size: 24rpx;
+ color: #ff4d4f;
+}
diff --git a/src/pages/Login/user-register/components/PasswordStrength.vue b/src/pages/Login/user-register/components/PasswordStrength.vue
index 194c0cc..34a7258 100644
--- a/src/pages/Login/user-register/components/PasswordStrength.vue
+++ b/src/pages/Login/user-register/components/PasswordStrength.vue
@@ -57,63 +57,5 @@ const showIndicator = computed(() => props.password.length > 0)
diff --git a/src/pages/Login/user-register/components/RegisterInput.scss b/src/pages/Login/user-register/components/RegisterInput.scss
new file mode 100644
index 0000000..24b0c47
--- /dev/null
+++ b/src/pages/Login/user-register/components/RegisterInput.scss
@@ -0,0 +1,32 @@
+@import '@/styles/variables.scss';
+
+.register-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.register-input__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.register-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.register-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
diff --git a/src/pages/Login/user-register/components/RegisterInput.vue b/src/pages/Login/user-register/components/RegisterInput.vue
index 62d7361..7bd1e7a 100644
--- a/src/pages/Login/user-register/components/RegisterInput.vue
+++ b/src/pages/Login/user-register/components/RegisterInput.vue
@@ -42,36 +42,5 @@ function onInput(e: { detail: { value: string } }) {
diff --git a/src/pages/Login/user-register/index.scss b/src/pages/Login/user-register/index.scss
new file mode 100644
index 0000000..8cecafc
--- /dev/null
+++ b/src/pages/Login/user-register/index.scss
@@ -0,0 +1,131 @@
+@import '@/styles/variables.scss';
+
+.register-page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ padding: 0 64rpx;
+ background: $color-bg-page;
+}
+
+.register-page__header {
+ padding-top: 120rpx;
+ text-align: center;
+}
+
+.register-page__title {
+ display: block;
+ font-size: 56rpx;
+ font-weight: 700;
+ color: $color-text-primary;
+ letter-spacing: 2rpx;
+}
+
+.register-page__subtitle {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 28rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+}
+
+.register-page__form {
+ width: 100%;
+ margin-top: 80rpx;
+ box-sizing: border-box;
+}
+
+.register-page__field {
+ width: 100%;
+ margin-top: 24rpx;
+ box-sizing: border-box;
+
+ &:first-child {
+ margin-top: 0;
+ }
+}
+
+.register-page__agreement {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 32rpx;
+}
+
+.register-page__checkbox {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+ margin-top: 4rpx;
+ margin-right: 12rpx;
+ border: 2rpx solid #cccccc;
+ border-radius: 50%;
+ transition: all 0.2s;
+
+ &--checked {
+ background: $color-primary;
+ border-color: $color-primary;
+ }
+}
+
+.register-page__checkmark {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #ffffff;
+ line-height: 1;
+}
+
+.register-page__agreement-text {
+ flex: 1;
+ font-size: 24rpx;
+ line-height: 1.6;
+}
+
+.register-page__agreement-normal {
+ color: $color-text-secondary;
+}
+
+.register-page__agreement-link {
+ color: $color-text-link;
+}
+
+.register-page__submit {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 96rpx;
+ margin-top: 48rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ border: none;
+ border-radius: 48rpx;
+ line-height: 96rpx;
+
+ &::after {
+ border: none;
+ }
+}
+
+.register-page__footer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-top: auto;
+ padding: 60rpx 0 calc(60rpx + env(safe-area-inset-bottom));
+}
+
+.register-page__footer-normal {
+ font-size: 28rpx;
+ color: $color-text-secondary;
+}
+
+.register-page__footer-link {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ color: $color-text-link;
+}
diff --git a/src/pages/Login/user-register/index.vue b/src/pages/Login/user-register/index.vue
index 621882f..7e1a595 100644
--- a/src/pages/Login/user-register/index.vue
+++ b/src/pages/Login/user-register/index.vue
@@ -151,135 +151,5 @@ function handleUserAgreement() {
diff --git a/src/pages/Login/user-sms-login/components/CodeInput.scss b/src/pages/Login/user-sms-login/components/CodeInput.scss
new file mode 100644
index 0000000..9641dc9
--- /dev/null
+++ b/src/pages/Login/user-sms-login/components/CodeInput.scss
@@ -0,0 +1,54 @@
+@import '@/styles/variables.scss';
+
+.code-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 16rpx 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.code-input__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.code-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.code-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
+
+.code-input__btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ height: 64rpx;
+ padding: 0 24rpx;
+ background: $color-primary;
+ border-radius: 32rpx;
+
+ &--disabled {
+ opacity: 0.6;
+ }
+}
+
+.code-input__btn-text {
+ font-size: 24rpx;
+ font-weight: 500;
+ color: #ffffff;
+ white-space: nowrap;
+}
diff --git a/src/pages/Login/user-sms-login/components/CodeInput.vue b/src/pages/Login/user-sms-login/components/CodeInput.vue
index 1556e8f..4d009e6 100644
--- a/src/pages/Login/user-sms-login/components/CodeInput.vue
+++ b/src/pages/Login/user-sms-login/components/CodeInput.vue
@@ -66,58 +66,5 @@ function handleGetCode() {
diff --git a/src/pages/Login/user-sms-login/components/LoginInput.scss b/src/pages/Login/user-sms-login/components/LoginInput.scss
new file mode 100644
index 0000000..f954a4c
--- /dev/null
+++ b/src/pages/Login/user-sms-login/components/LoginInput.scss
@@ -0,0 +1,32 @@
+@import '@/styles/variables.scss';
+
+.login-input {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 96rpx;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+ background: $color-bg-input;
+ border-radius: 48rpx;
+}
+
+.login-input__icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+ margin-right: 20rpx;
+}
+
+.login-input__field {
+ flex: 1;
+ height: 96rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+ background: transparent;
+}
+
+.login-input__placeholder {
+ font-size: 30rpx;
+ color: $color-text-placeholder;
+}
diff --git a/src/pages/Login/user-sms-login/components/LoginInput.vue b/src/pages/Login/user-sms-login/components/LoginInput.vue
index c4f8574..f0554ce 100644
--- a/src/pages/Login/user-sms-login/components/LoginInput.vue
+++ b/src/pages/Login/user-sms-login/components/LoginInput.vue
@@ -42,36 +42,5 @@ function onInput(e: { detail: { value: string } }) {
diff --git a/src/pages/Login/user-sms-login/index.scss b/src/pages/Login/user-sms-login/index.scss
new file mode 100644
index 0000000..f5dada1
--- /dev/null
+++ b/src/pages/Login/user-sms-login/index.scss
@@ -0,0 +1,181 @@
+@import '@/styles/variables.scss';
+
+.sms-login-page {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ padding: 0 64rpx;
+ background: $color-bg-page;
+}
+
+.sms-login-page__header {
+ padding-top: 120rpx;
+ text-align: center;
+}
+
+.sms-login-page__title {
+ display: block;
+ font-size: 56rpx;
+ font-weight: 700;
+ color: $color-text-primary;
+ letter-spacing: 2rpx;
+}
+
+.sms-login-page__subtitle {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 28rpx;
+ font-weight: 400;
+ color: $color-text-secondary;
+}
+
+.sms-login-page__form {
+ width: 100%;
+ margin-top: 80rpx;
+ box-sizing: border-box;
+}
+
+.sms-login-page__code-group {
+ margin-top: 24rpx;
+}
+
+.sms-login-page__agreement {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 32rpx;
+}
+
+.sms-login-page__checkbox {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+ margin-top: 4rpx;
+ margin-right: 12rpx;
+ border: 2rpx solid #cccccc;
+ border-radius: 50%;
+ transition: all 0.2s;
+
+ &--checked {
+ background: $color-primary;
+ border-color: $color-primary;
+ }
+}
+
+.sms-login-page__checkmark {
+ font-size: 20rpx;
+ font-weight: 700;
+ color: #ffffff;
+ line-height: 1;
+}
+
+.sms-login-page__agreement-text {
+ flex: 1;
+ font-size: 24rpx;
+ line-height: 1.6;
+}
+
+.sms-login-page__agreement-normal {
+ color: $color-text-secondary;
+}
+
+.sms-login-page__agreement-link {
+ color: $color-text-link;
+}
+
+.sms-login-page__submit {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 96rpx;
+ margin-top: 48rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ border: none;
+ border-radius: 48rpx;
+ line-height: 96rpx;
+
+ &::after {
+ border: none;
+ }
+}
+
+.sms-login-page__other {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 60rpx 0;
+}
+
+.sms-login-page__divider {
+ display: flex;
+ align-items: center;
+ width: 100%;
+}
+
+.sms-login-page__divider-line {
+ flex: 1;
+ height: 1rpx;
+ background: #e8e8e8;
+}
+
+.sms-login-page__divider-text {
+ padding: 0 24rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+ white-space: nowrap;
+}
+
+.sms-login-page__password {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: fit-content;
+ margin-top: 48rpx;
+}
+
+.sms-login-page__password-icon-wrap {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 96rpx;
+ height: 96rpx;
+ background: #B6CDFF;
+ border-radius: 50%;
+}
+
+.sms-login-page__password-icon {
+ width: 48rpx;
+ height: 48rpx;
+}
+
+.sms-login-page__password-text {
+ margin-top: 16rpx;
+ font-size: 24rpx;
+ color: #999999;
+}
+
+.sms-login-page__footer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-bottom: calc(60rpx + env(safe-area-inset-bottom));
+}
+
+.sms-login-page__footer-normal {
+ font-size: 28rpx;
+ color: $color-text-secondary;
+}
+
+.sms-login-page__footer-link {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ color: $color-text-link;
+}
diff --git a/src/pages/Login/user-sms-login/index.vue b/src/pages/Login/user-sms-login/index.vue
index 9714164..c4b4818 100644
--- a/src/pages/Login/user-sms-login/index.vue
+++ b/src/pages/Login/user-sms-login/index.vue
@@ -154,185 +154,5 @@ function handleUserAgreement() {
diff --git a/src/pages/case-library/components/CaseCard.scss b/src/pages/case-library/components/CaseCard.scss
new file mode 100644
index 0000000..b640642
--- /dev/null
+++ b/src/pages/case-library/components/CaseCard.scss
@@ -0,0 +1,87 @@
+@import '@/styles/variables.scss';
+
+.case-card {
+ padding: 0 0 28rpx;
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ overflow: hidden;
+}
+
+.case-card__cover-wrap {
+ position: relative;
+ height: 320rpx;
+ overflow: hidden;
+}
+
+.case-card__cover {
+ width: 100%;
+ height: 100%;
+}
+
+.case-card__tag {
+ position: absolute;
+ top: 20rpx;
+ left: 20rpx;
+ padding: 6rpx 16rpx;
+ font-size: 22rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 8rpx;
+}
+
+.case-card__favorite {
+ position: absolute;
+ top: 20rpx;
+ right: 20rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 56rpx;
+ height: 56rpx;
+ background: rgba(255, 255, 255, 0.92);
+ border-radius: 50%;
+}
+
+.case-card__favorite-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.case-card__title {
+ display: block;
+ padding: 24rpx 24rpx 0;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-card__meta {
+ padding: 20rpx 24rpx 0;
+}
+
+.case-card__meta-row {
+ display: flex;
+ margin-bottom: 16rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.case-card__meta-item {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.case-card__meta-label {
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.case-card__meta-value {
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ color: $color-text-primary;
+}
diff --git a/src/pages/case-library/components/CaseCard.vue b/src/pages/case-library/components/CaseCard.vue
index 9e7747e..c9605fe 100644
--- a/src/pages/case-library/components/CaseCard.vue
+++ b/src/pages/case-library/components/CaseCard.vue
@@ -95,91 +95,5 @@ const emit = defineEmits<{
diff --git a/src/pages/case-library/components/CaseFilterPanel.scss b/src/pages/case-library/components/CaseFilterPanel.scss
new file mode 100644
index 0000000..3183099
--- /dev/null
+++ b/src/pages/case-library/components/CaseFilterPanel.scss
@@ -0,0 +1,213 @@
+@import '@/styles/variables.scss';
+
+.case-filter-panel {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 300;
+}
+
+.case-filter-panel__mask {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: rgba(0, 0, 0, 0.45);
+}
+
+.case-filter-panel__sheet {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: flex;
+ flex-direction: column;
+ max-height: 78vh;
+ background: $color-bg-page;
+ border-radius: 24rpx 24rpx 0 0;
+}
+
+.case-filter-panel__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: 28rpx 32rpx 20rpx;
+}
+
+.case-filter-panel__title-wrap,
+.case-filter-panel__reset {
+ display: flex;
+ align-items: center;
+}
+
+.case-filter-panel__title-icon {
+ width: 28rpx;
+ height: 28rpx;
+ margin-right: 10rpx;
+}
+
+.case-filter-panel__title {
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-filter-panel__reset-icon {
+ margin-right: 6rpx;
+ font-size: 28rpx;
+ color: $color-primary;
+}
+
+.case-filter-panel__reset-text {
+ font-size: 26rpx;
+ color: $color-primary;
+}
+
+.case-filter-panel__body {
+ flex: 1;
+ min-height: 0;
+ padding: 0 32rpx;
+ box-sizing: border-box;
+}
+
+.case-filter-panel__section {
+ margin-bottom: 28rpx;
+}
+
+.case-filter-panel__section-title {
+ display: block;
+ margin-bottom: 20rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-filter-panel__chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16rpx;
+}
+
+.case-filter-panel__chip {
+ padding: 14rpx 24rpx;
+ font-size: 24rpx;
+ color: $color-text-primary;
+ background: $color-bg-section;
+ border-radius: 999rpx;
+
+ &--active {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+}
+
+.case-filter-panel__date-row {
+ display: flex;
+ align-items: center;
+ margin-top: 20rpx;
+}
+
+.case-filter-panel__date-field {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 220rpx;
+ height: 72rpx;
+ padding: 0 20rpx;
+ background: $color-bg-section;
+ border-radius: 999rpx;
+}
+
+.case-filter-panel__date-placeholder {
+ color: $color-text-placeholder;
+}
+
+.case-filter-panel__date-separator {
+ margin: 0 16rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.case-filter-panel__selected {
+ flex-shrink: 0;
+ margin: 0 32rpx 20rpx;
+ padding: 20rpx 24rpx;
+ background: $color-bg-section;
+ border-radius: 16rpx;
+}
+
+.case-filter-panel__selected-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16rpx;
+}
+
+.case-filter-panel__selected-title {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.case-filter-panel__selected-clear {
+ font-size: 24rpx;
+ color: $color-primary;
+}
+
+.case-filter-panel__selected-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12rpx;
+}
+
+.case-filter-panel__tag {
+ display: flex;
+ align-items: center;
+ padding: 8rpx 16rpx;
+ background: $color-primary-light;
+ border-radius: 999rpx;
+}
+
+.case-filter-panel__tag-text {
+ font-size: 22rpx;
+ color: $color-primary;
+}
+
+.case-filter-panel__tag-close {
+ margin-left: 8rpx;
+ font-size: 24rpx;
+ line-height: 1;
+ color: $color-primary;
+}
+
+.case-filter-panel__footer {
+ display: flex;
+ gap: 20rpx;
+ flex-shrink: 0;
+ padding: 16rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
+}
+
+.case-filter-panel__btn {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ border-radius: 44rpx;
+
+ &--cancel {
+ color: $color-primary;
+ background: #ffffff;
+ border: 2rpx solid $color-primary;
+ }
+
+ &--confirm {
+ color: #ffffff;
+ background: $color-primary;
+ }
+}
diff --git a/src/pages/case-library/components/CaseFilterPanel.vue b/src/pages/case-library/components/CaseFilterPanel.vue
index 8a95a7e..a1e4058 100644
--- a/src/pages/case-library/components/CaseFilterPanel.vue
+++ b/src/pages/case-library/components/CaseFilterPanel.vue
@@ -312,217 +312,5 @@ function handleConfirm() {
diff --git a/src/pages/case-library/components/LoadMoreFooter.scss b/src/pages/case-library/components/LoadMoreFooter.scss
new file mode 100644
index 0000000..bb31e81
--- /dev/null
+++ b/src/pages/case-library/components/LoadMoreFooter.scss
@@ -0,0 +1,39 @@
+@import '@/styles/variables.scss';
+
+.load-more-footer {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 32rpx 0 16rpx;
+}
+
+.load-more-footer__loading {
+ display: flex;
+ align-items: center;
+}
+
+.load-more-footer__spinner {
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+ border: 4rpx solid #d6e4ff;
+ border-top-color: $color-primary;
+ border-radius: 50%;
+ animation: load-more-spin 0.8s linear infinite;
+}
+
+.load-more-footer__text,
+.load-more-footer__finished {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+@keyframes load-more-spin {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/pages/case-library/components/LoadMoreFooter.vue b/src/pages/case-library/components/LoadMoreFooter.vue
index b6784ba..bce5776 100644
--- a/src/pages/case-library/components/LoadMoreFooter.vue
+++ b/src/pages/case-library/components/LoadMoreFooter.vue
@@ -41,43 +41,5 @@ const emit = defineEmits<{
diff --git a/src/pages/case-library/detail/index.scss b/src/pages/case-library/detail/index.scss
new file mode 100644
index 0000000..fe6b40d
--- /dev/null
+++ b/src/pages/case-library/detail/index.scss
@@ -0,0 +1,181 @@
+@import '@/styles/variables.scss';
+
+.case-detail {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.case-detail__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+}
+
+.case-detail__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.case-detail__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.case-detail__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-detail__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.case-detail__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.case-detail__content {
+ padding: 24rpx 24rpx calc(32rpx + env(safe-area-inset-bottom));
+}
+
+.case-detail__hero {
+ padding: 32rpx 28rpx;
+ background: linear-gradient(135deg, #eef4ff 0%, #ffffff 60%);
+ border-radius: 20rpx;
+}
+
+.case-detail__tag {
+ display: inline-block;
+ padding: 6rpx 16rpx;
+ font-size: 22rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 8rpx;
+}
+
+.case-detail__title {
+ display: block;
+ margin-top: 20rpx;
+ font-size: 36rpx;
+ font-weight: 600;
+ line-height: 1.4;
+ color: $color-text-primary;
+}
+
+.case-detail__section {
+ margin-top: 24rpx;
+ padding: 28rpx 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &--last {
+ margin-bottom: 0;
+ }
+}
+
+.case-detail__section-title {
+ display: block;
+ margin-bottom: 24rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-detail__overview {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.case-detail__overview-item {
+ display: flex;
+ flex-direction: column;
+ width: 33.33%;
+ margin-bottom: 24rpx;
+}
+
+.case-detail__overview-label {
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.case-detail__overview-value {
+ margin-top: 8rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.case-detail__image-placeholder {
+ height: 280rpx;
+ margin-bottom: 24rpx;
+ background: #e8eaed;
+ border-radius: 12rpx;
+}
+
+.case-detail__paragraph {
+ display: block;
+ font-size: 28rpx;
+ line-height: 1.8;
+ color: $color-text-primary;
+}
+
+.case-detail__attachments {
+ margin-top: 24rpx;
+ white-space: nowrap;
+}
+
+.case-detail__attachments-inner {
+ display: inline-flex;
+ gap: 20rpx;
+ padding: 10rpx 10rpx 0 0;
+}
+
+.case-detail__attachment {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 160rpx;
+ padding: 20rpx 16rpx;
+ background: $color-bg-section;
+ border-radius: 12rpx;
+}
+
+.case-detail__attachment-remove {
+ position: absolute;
+ top: -10rpx;
+ right: -10rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.case-detail__attachment-remove-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.case-detail__attachment-icon {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.case-detail__attachment-name {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+ word-break: break-all;
+}
diff --git a/src/pages/case-library/detail/index.vue b/src/pages/case-library/detail/index.vue
index 0b56a02..3bc5b73 100644
--- a/src/pages/case-library/detail/index.vue
+++ b/src/pages/case-library/detail/index.vue
@@ -161,185 +161,5 @@ function handleBack() {
diff --git a/src/pages/case-library/favorites/index.scss b/src/pages/case-library/favorites/index.scss
new file mode 100644
index 0000000..d5d8ad0
--- /dev/null
+++ b/src/pages/case-library/favorites/index.scss
@@ -0,0 +1,172 @@
+@import '@/styles/variables.scss';
+
+.case-favorites {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-section;
+}
+
+.case-favorites__header {
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 24rpx 0;
+ background: $color-bg-page;
+}
+
+.case-favorites__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-bottom: 28rpx;
+}
+
+.case-favorites__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.case-favorites__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.case-favorites__title {
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.case-favorites__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.case-favorites__search-row {
+ display: flex;
+ align-items: center;
+}
+
+.case-favorites__search {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ height: 72rpx;
+ padding: 0 24rpx;
+ background: $color-bg-section;
+ border-radius: 36rpx;
+}
+
+.case-favorites__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.case-favorites__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.case-favorites__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.case-favorites__favorite-btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 72rpx;
+ height: 72rpx;
+ margin-left: 16rpx;
+}
+
+.case-favorites__favorite-btn-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.case-favorites__tabs {
+ margin-top: 24rpx;
+ white-space: nowrap;
+}
+
+.case-favorites__tabs-inner {
+ display: inline-flex;
+ gap: 32rpx;
+ padding-right: 24rpx;
+}
+
+.case-favorites__tab {
+ flex-shrink: 0;
+ padding-bottom: 12rpx;
+ font-size: 28rpx;
+ color: $color-text-secondary;
+
+ &--active {
+ font-weight: 600;
+ color: $color-text-primary;
+ border-bottom: 4rpx solid $color-primary;
+ }
+}
+
+.case-favorites__quick-filters {
+ display: flex;
+ align-items: center;
+ gap: 24rpx;
+ margin-top: 20rpx;
+}
+
+.case-favorites__quick-filter {
+ display: flex;
+ align-items: center;
+ gap: 4rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.case-favorites__quick-filter-arrow {
+ font-size: 20rpx;
+ color: $color-text-secondary;
+}
+
+.case-favorites__filter {
+ display: flex;
+ align-items: center;
+ margin-left: auto;
+}
+
+.case-favorites__filter-icon {
+ width: 28rpx;
+ height: 28rpx;
+ margin-left: 8rpx;
+}
+
+.case-favorites__filter-text {
+ font-size: 26rpx;
+ color: #666666;
+}
+
+.case-favorites__toolbar {
+ padding: 20rpx 0 24rpx;
+}
+
+.case-favorites__count {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.case-favorites__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.case-favorites__list {
+ padding: 0 24rpx calc(32rpx + env(safe-area-inset-bottom));
+}
diff --git a/src/pages/case-library/favorites/index.vue b/src/pages/case-library/favorites/index.vue
index 6b39b6d..2dbe229 100644
--- a/src/pages/case-library/favorites/index.vue
+++ b/src/pages/case-library/favorites/index.vue
@@ -291,176 +291,5 @@ function showTimePicker() {
diff --git a/src/pages/case-library/index.scss b/src/pages/case-library/index.scss
new file mode 100644
index 0000000..281ee19
--- /dev/null
+++ b/src/pages/case-library/index.scss
@@ -0,0 +1,132 @@
+@import '@/styles/variables.scss';
+
+.case-library {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-section;
+}
+
+.case-library__header {
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 24rpx 0;
+ background: $color-bg-page;
+}
+
+.case-library__title {
+ display: block;
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+ text-align: center;
+}
+
+.case-library__search-row {
+ display: flex;
+ align-items: center;
+ margin-top: 24rpx;
+}
+
+.case-library__search {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ height: 72rpx;
+ padding: 0 24rpx;
+ background: $color-bg-section;
+ border-radius: 36rpx;
+}
+
+.case-library__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.case-library__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.case-library__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.case-library__favorite-btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 72rpx;
+ height: 72rpx;
+ margin-left: 16rpx;
+}
+
+.case-library__favorite-btn-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.case-library__tabs {
+ margin-top: 24rpx;
+ white-space: nowrap;
+}
+
+.case-library__tabs-inner {
+ display: inline-flex;
+ gap: 32rpx;
+ padding-right: 24rpx;
+}
+
+.case-library__tab {
+ flex-shrink: 0;
+ padding-bottom: 12rpx;
+ font-size: 28rpx;
+ color: $color-text-secondary;
+
+ &--active {
+ font-weight: 600;
+ color: $color-text-primary;
+ border-bottom: 4rpx solid $color-primary;
+ }
+}
+
+.case-library__toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20rpx 0 24rpx;
+}
+
+.case-library__count {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.case-library__filter {
+ display: flex;
+ align-items: center;
+}
+
+.case-library__filter-icon {
+ width: 28rpx;
+ height: 28rpx;
+ margin-right: 8rpx;
+}
+
+.case-library__filter-text {
+ font-size: 26rpx;
+ color: #666666;
+}
+
+.case-library__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.case-library__list {
+ padding: 0 24rpx calc(140rpx + env(safe-area-inset-bottom));
+}
diff --git a/src/pages/case-library/index.vue b/src/pages/case-library/index.vue
index 07ba4c2..4fe105d 100644
--- a/src/pages/case-library/index.vue
+++ b/src/pages/case-library/index.vue
@@ -209,136 +209,5 @@ function handleCaseTap(id: string) {
diff --git a/src/pages/home-index/business-detail/index.scss b/src/pages/home-index/business-detail/index.scss
new file mode 100644
index 0000000..21a757a
--- /dev/null
+++ b/src/pages/home-index/business-detail/index.scss
@@ -0,0 +1,192 @@
+@import '@/styles/variables.scss';
+
+.business-detail {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.business-detail__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 12rpx;
+ background: $color-bg-page;
+}
+
+.business-detail__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.business-detail__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.business-detail__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.business-detail__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.business-detail__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.business-detail__hero {
+ position: relative;
+ margin: 20rpx 24rpx 0;
+ overflow: hidden;
+ border-radius: 20rpx;
+}
+
+.business-detail__hero-bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.business-detail__hero-inner {
+ position: relative;
+ z-index: 1;
+ padding: 24rpx 24rpx 28rpx;
+}
+
+.business-detail__hero-icon {
+ width: 96rpx;
+ height: 96rpx;
+}
+
+.business-detail__hero-title {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.business-detail__hero-subtitle {
+ display: block;
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ line-height: 1.5;
+ color: #333333;
+}
+
+.business-detail__section {
+ margin: 20rpx 24rpx 0;
+ padding: 28rpx 24rpx 32rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.business-detail__section-title {
+ display: block;
+ margin-bottom: 28rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.business-detail__type-row {
+ display: flex;
+ justify-content: space-between;
+}
+
+.business-detail__type-item {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+}
+
+.business-detail__type-icon {
+ width: 91rpx;
+ height: 91rpx;
+}
+
+.business-detail__type-label {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+}
+
+.business-detail__video {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 360rpx;
+ overflow: hidden;
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
+ border-radius: 16rpx;
+}
+
+.business-detail__video-play {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 80rpx;
+ height: 80rpx;
+ background: rgba(255, 255, 255, 0.25);
+ border-radius: 50%;
+}
+
+.business-detail__video-play-icon {
+ margin-left: 6rpx;
+ font-size: 32rpx;
+ color: #ffffff;
+}
+
+.business-detail__content {
+ margin-top: 28rpx;
+}
+
+.business-detail__paragraph {
+ display: block;
+ margin-bottom: 16rpx;
+ font-size: 28rpx;
+ line-height: 1.8;
+ color: $color-text-primary;
+
+ &--title {
+ margin-top: 8rpx;
+ margin-bottom: 12rpx;
+ font-weight: 600;
+ }
+}
+
+.business-detail__footer {
+ flex-shrink: 0;
+ padding: 16rpx 32rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.business-detail__submit-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 44rpx;
+}
diff --git a/src/pages/home-index/business-detail/index.vue b/src/pages/home-index/business-detail/index.vue
index 6ef4aeb..9c72922 100644
--- a/src/pages/home-index/business-detail/index.vue
+++ b/src/pages/home-index/business-detail/index.vue
@@ -140,196 +140,5 @@ function handleSubmit() {
diff --git a/src/pages/home-index/components/HomeFloatingActions.scss b/src/pages/home-index/components/HomeFloatingActions.scss
new file mode 100644
index 0000000..20a1990
--- /dev/null
+++ b/src/pages/home-index/components/HomeFloatingActions.scss
@@ -0,0 +1,60 @@
+@import '@/styles/variables.scss';
+
+.home-floating-actions {
+ position: fixed;
+ right: 24rpx;
+ bottom: calc(160rpx + env(safe-area-inset-bottom));
+ z-index: 120;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 20rpx;
+}
+
+.home-floating-actions__item {
+ display: flex;
+ align-items: center;
+ height: 72rpx;
+ padding: 0 28rpx 0 12rpx;
+ background: #ffffff;
+ border-radius: 999rpx;
+ box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
+}
+
+.home-floating-actions__icon {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 48rpx;
+ height: 48rpx;
+ border-radius: 50%;
+
+ &--submit {
+ background: #22c55e;
+ }
+
+ &--service {
+ background: #e8f0ff;
+ }
+}
+
+.home-floating-actions__plus {
+ font-size: 32rpx;
+ font-weight: 500;
+ line-height: 1;
+ color: #ffffff;
+}
+
+.home-floating-actions__service-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.home-floating-actions__label {
+ margin-left: 16rpx;
+ font-size: 26rpx;
+ font-weight: 500;
+ color: $color-text-primary;
+ white-space: nowrap;
+}
diff --git a/src/pages/home-index/components/HomeFloatingActions.vue b/src/pages/home-index/components/HomeFloatingActions.vue
index 8a0c876..9ef44be 100644
--- a/src/pages/home-index/components/HomeFloatingActions.vue
+++ b/src/pages/home-index/components/HomeFloatingActions.vue
@@ -47,65 +47,5 @@ function handleCustomerService() {
diff --git a/src/pages/home-index/components/ProjectCard.scss b/src/pages/home-index/components/ProjectCard.scss
new file mode 100644
index 0000000..37ed3a9
--- /dev/null
+++ b/src/pages/home-index/components/ProjectCard.scss
@@ -0,0 +1,123 @@
+@import '@/styles/variables.scss';
+
+.project-card {
+ position: relative;
+ margin-top: 20rpx;
+ overflow: hidden;
+ border-radius: 20rpx;
+}
+
+.project-card__bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.project-card__inner {
+ position: relative;
+ z-index: 1;
+ padding: 28rpx;
+}
+
+.project-card__header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.project-card__title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-card__status {
+ flex-shrink: 0;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.project-card__meta {
+ display: flex;
+ align-items: center;
+ margin-top: 16rpx;
+}
+
+.project-card__meta-info {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: space-between;
+ min-width: 0;
+ margin-left: 12rpx;
+}
+
+.project-card__tag {
+ flex-shrink: 0;
+ padding: 4rpx 12rpx;
+ font-size: 20rpx;
+ border-radius: 6rpx;
+ font-weight: 500;
+ width: 100rpx;
+ text-align: center;
+ height: 20rpx;
+ line-height: 20rpx;
+
+ &--orange {
+ color: #875045;
+ background: #FFF1EA;
+ }
+}
+
+.project-card__no {
+ flex: 1;
+ min-width: 0;
+ font-size: 22rpx;
+ color: #666666;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.project-card__progress-value {
+ flex-shrink: 0;
+ margin-left: 12rpx;
+ font-size: 24rpx;
+ color: #666666;
+}
+
+.project-card__progress-bar {
+ height: 12rpx;
+ margin-top: 24rpx;
+ overflow: hidden;
+ background: #eef2ff;
+ border-radius: 6rpx;
+}
+
+.project-card__progress-fill {
+ height: 100%;
+ background: $color-primary;
+ border-radius: 6rpx;
+}
+
+.project-card__footer {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 20rpx;
+}
+
+.project-card__time {
+ font-size: 22rpx;
+ color: #666666;
+}
+
+.project-card__detail {
+ font-size: 24rpx;
+ color: #666666;
+}
diff --git a/src/pages/home-index/components/ProjectCard.vue b/src/pages/home-index/components/ProjectCard.vue
index 9f4126d..ad4d018 100644
--- a/src/pages/home-index/components/ProjectCard.vue
+++ b/src/pages/home-index/components/ProjectCard.vue
@@ -61,127 +61,5 @@ defineProps<{
diff --git a/src/pages/home-index/components/QuickEntryEditor.scss b/src/pages/home-index/components/QuickEntryEditor.scss
new file mode 100644
index 0000000..eb042c1
--- /dev/null
+++ b/src/pages/home-index/components/QuickEntryEditor.scss
@@ -0,0 +1,137 @@
+@import '@/styles/variables.scss';
+
+.quick-entry-editor {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 200;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 40rpx;
+ box-sizing: border-box;
+}
+
+.quick-entry-editor__mask {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: rgba(0, 0, 0, 0.45);
+}
+
+.quick-entry-editor__panel {
+ position: relative;
+ z-index: 1;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ max-height: 80vh;
+ overflow: hidden;
+ background: $color-bg-page;
+ border-radius: 24rpx;
+ box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.12);
+}
+
+.quick-entry-editor__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: 32rpx 32rpx 24rpx;
+}
+
+.quick-entry-editor__title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.quick-entry-editor__close {
+ width: 48rpx;
+ font-size: 40rpx;
+ line-height: 1;
+ color: $color-text-secondary;
+ text-align: right;
+}
+
+.quick-entry-editor__body {
+ flex: 1;
+ max-height: calc(80vh - 100rpx);
+ padding: 0 24rpx 32rpx;
+ box-sizing: border-box;
+}
+
+.quick-entry-editor__section-title {
+ display: block;
+ margin: 32rpx 8rpx 24rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.quick-entry-editor__grid {
+ display: flex;
+ flex-wrap: wrap;
+
+ &--pinned {
+ justify-content: space-between;
+ padding: 0 8rpx;
+ }
+
+ &--other {
+ row-gap: 28rpx;
+ padding: 0 8rpx;
+ }
+}
+
+.quick-entry-editor__item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 20%;
+}
+
+.quick-entry-editor__icon-wrap {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 88rpx;
+ height: 88rpx;
+}
+
+.quick-entry-editor__icon {
+ width: 72rpx;
+ height: 72rpx;
+}
+
+.quick-entry-editor__badge {
+ position: absolute;
+ top: -4rpx;
+ right: -4rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+ background: #c8cdd4;
+ border-radius: 50%;
+}
+
+.quick-entry-editor__badge-text {
+ font-size: 22rpx;
+ font-weight: 600;
+ line-height: 1;
+ color: #ffffff;
+}
+
+.quick-entry-editor__label {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+}
diff --git a/src/pages/home-index/components/QuickEntryEditor.vue b/src/pages/home-index/components/QuickEntryEditor.vue
index a42d2c4..432ec7f 100644
--- a/src/pages/home-index/components/QuickEntryEditor.vue
+++ b/src/pages/home-index/components/QuickEntryEditor.vue
@@ -104,141 +104,5 @@ const emit = defineEmits<{
diff --git a/src/pages/home-index/components/ServiceCard.scss b/src/pages/home-index/components/ServiceCard.scss
new file mode 100644
index 0000000..d7066fd
--- /dev/null
+++ b/src/pages/home-index/components/ServiceCard.scss
@@ -0,0 +1,75 @@
+.service-card {
+ position: relative;
+ display: flex;
+ height: 240rpx;
+ padding: 28rpx 24rpx 24rpx;
+ overflow: hidden;
+ border-radius: 20rpx;
+ box-sizing: border-box;
+
+ &--with-illus {
+ overflow: visible;
+ }
+
+ &--blue {
+ background: linear-gradient(180deg, #D3E1FC 0%, #FFFFFF 100%);
+ }
+
+ &--green {
+ background: linear-gradient( 180deg, #B7EDEA 0%, #FFFFFF 100%);
+ }
+
+ &--pink {
+ background: linear-gradient( 180deg, #FFECE1 0%, #FFFFFF 100%);
+ }
+
+ &--orange {
+ background: linear-gradient( 180deg, #F7D3C6 0%, #FFFFFF 100%);
+ }
+
+ &--clickable {
+ cursor: pointer;
+ }
+}
+
+.service-card__illus {
+ position: absolute;
+ top: -36rpx;
+ right: -10rpx;
+ z-index: 2;
+ width: 152rpx;
+ height: 152rpx;
+ pointer-events: none;
+}
+
+.service-card__content {
+ position: relative;
+ z-index: 1;
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ width: 100%;
+}
+
+.service-card__title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #1a1a1a;
+}
+
+.service-card__desc {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ line-height: 1.45;
+ color: #666666;
+}
+
+.service-card--with-illus .service-card__desc {
+ margin-top: 28rpx;
+}
+
+.service-card__link {
+ margin-top: auto;
+ font-size: 22rpx;
+ color: #2563EB;
+}
diff --git a/src/pages/home-index/components/ServiceCard.vue b/src/pages/home-index/components/ServiceCard.vue
index 0e3d0b3..58ed937 100644
--- a/src/pages/home-index/components/ServiceCard.vue
+++ b/src/pages/home-index/components/ServiceCard.vue
@@ -46,79 +46,5 @@ function handleTap() {
diff --git a/src/pages/home-index/index.scss b/src/pages/home-index/index.scss
new file mode 100644
index 0000000..5de53c2
--- /dev/null
+++ b/src/pages/home-index/index.scss
@@ -0,0 +1,270 @@
+@import '@/styles/variables.scss';
+
+.home {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.home__header {
+ position: relative;
+ flex-shrink: 0;
+ overflow: hidden;
+ background: $color-home-header;
+ height: 360rpx;
+}
+
+.home__header-bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.home__header-inner {
+ position: relative;
+ z-index: 1;
+ padding: calc(var(--status-bar-height, 44px) + 16rpx) 32rpx 48rpx;
+}
+
+.home__header-top {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top:85rpx
+}
+
+.home__brand {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ min-width: 0;
+}
+
+.home__logo {
+ flex-shrink: 0;
+ width: 76.34rpx;
+ height: 76.34rpx;
+ padding: 8rpx;
+ border-radius: 12rpx;
+ box-sizing: border-box;
+}
+
+.home__brand-name {
+ margin-left: 16rpx;
+ font-size: 26rpx;
+ font-weight: 500;
+ color: #ffffff;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.home__message-btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+ margin-left: 16rpx;
+ border-radius: 16rpx;
+}
+
+.home__message-icon {
+ width: 57.25rpx;
+ height: 57.25rpx;
+}
+
+.home__greeting-row {
+ display: flex;
+ align-items: center;
+ margin-top: 30rpx;
+}
+
+.home__greeting {
+ font-size: 52rpx;
+ font-weight: 700;
+ color: #ffffff;
+}
+
+.home__hi-badge {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 45.8rpx;
+ height: 45.8rpx;
+ margin-left: 16rpx;
+ border-radius: 50%;
+}
+
+.home__hi-text {
+ font-size: 22rpx;
+ font-weight: 600;
+ color: #ffffff;
+ text-transform: lowercase;
+}
+
+.home__subtitle {
+ display: block;
+ margin-top: 12rpx;
+ font-size: 26rpx;
+ color: rgba(255, 255, 255, 0.85);
+}
+
+.home__body {
+ flex: 1;
+ background: transparent;
+}
+
+.home__content {
+ min-height: 100%;
+ margin-top: 24rpx;
+ padding: 20rpx 20rpx calc(140rpx + env(safe-area-inset-bottom));
+}
+
+.home__section {
+ margin-bottom: 20rpx;
+ height: 600rpx;
+ width: 711.83rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ padding-top: 20rpx
+}
+
+.home__sections {
+ margin-bottom: 20rpx;
+ height: 210rpx;
+ width: 711.83rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ padding-top: 20rpx
+}
+
+.home__sectionss {
+ margin-bottom: 20rpx;
+ width: 711.83rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ padding-top: 20rpx
+}
+
+.home__section--last {
+ margin-bottom: 0;
+}
+
+.home__section-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 24rpx;
+}
+
+.home__section-title {
+ font-size: 32rpx;
+ font-weight: 500;
+ color: $color-text-primary;
+ margin-left: 30rpx;
+ // margin-top: 20rpx;
+}
+
+.home__section-action {
+ font-size: 26rpx;
+ color: #666666 ;
+ margin-right: 20rpx;
+}
+
+.home__service-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20rpx;
+ margin-top: 24rpx;
+ padding: 24rpx 20rpx 0;
+ overflow: visible;
+}
+
+.home__quick-row {
+ display: flex;
+ justify-content: space-between;
+}
+
+.home__quick-item {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+}
+
+.home__quick-icon {
+ width: 60rpx;
+ height: 60rpx;
+}
+
+.home__quick-label {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+}
+
+.home__stats-row {
+ display: flex;
+ gap: 20rpx;
+ padding: 0 20rpx;
+}
+
+.home__stat-card {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 32rpx 24rpx;
+ border-radius: 16rpx;
+ text-align: center;
+
+ &--blue {
+ background: linear-gradient(180deg, #D3E1FC 0%, #FFFFFF 100%);
+ }
+
+ &--orange {
+ background: linear-gradient(180deg, #FFECE1 0%, #FFFFFF 100%);
+ }
+}
+
+.home__stat-value {
+ display: flex;
+ align-items: baseline;
+ justify-content: center;
+}
+
+.home__stat-num {
+ font-size: 56rpx;
+ font-weight: 700;
+ line-height: 1;
+ color: $color-text-primary;
+}
+
+.home__stat-unit {
+ margin-left: 4rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: $color-text-primary;
+}
+
+.home__stat-label {
+ margin-top: 12rpx;
+ font-size: 24rpx;
+ color: #333333;
+}
+
+.home__recent-title {
+ display: block;
+ margin-top: 32rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
diff --git a/src/pages/home-index/index.vue b/src/pages/home-index/index.vue
index 9646111..114f0e5 100644
--- a/src/pages/home-index/index.vue
+++ b/src/pages/home-index/index.vue
@@ -244,274 +244,5 @@ const projects: ProjectItem[] = [
diff --git a/src/pages/home-index/requirement-submit/index.scss b/src/pages/home-index/requirement-submit/index.scss
new file mode 100644
index 0000000..a28fb4c
--- /dev/null
+++ b/src/pages/home-index/requirement-submit/index.scss
@@ -0,0 +1,353 @@
+@import '@/styles/variables.scss';
+
+.requirement-submit {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.requirement-submit__navbar {
+ position: relative;
+ z-index: 30;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 12rpx;
+ background: $color-bg-page;
+}
+
+.requirement-submit__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.requirement-submit__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.requirement-submit__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.requirement-submit__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.requirement-submit__scroll {
+ flex: 1;
+ height: 0;
+ padding: 20rpx 24rpx;
+ box-sizing: border-box;
+}
+
+.requirement-submit__card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 20rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &--dropdown {
+ position: relative;
+ z-index: 20;
+ overflow: visible;
+ }
+}
+
+.requirement-submit__field {
+ margin-bottom: 28rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.requirement-submit__label {
+ display: block;
+ margin-bottom: 16rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: $color-text-primary;
+}
+
+.requirement-submit__required {
+ color: #ff4d4f;
+}
+
+.requirement-submit__hint {
+ display: block;
+ margin-bottom: 16rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.requirement-submit__input {
+ width: 100%;
+ font-size: 28rpx;
+ color: $color-text-primary;
+
+ &--box {
+ height: 80rpx;
+ padding: 0 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-sizing: border-box;
+ }
+
+ &--cycle {
+ flex: 1;
+ }
+}
+
+.requirement-submit__placeholder {
+ color: $color-text-placeholder;
+}
+
+.requirement-submit__select-wrap {
+ position: relative;
+ z-index: 20;
+}
+
+.requirement-submit__select {
+ display: flex;
+ align-items: center;
+ height: 80rpx;
+ padding: 0 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+}
+
+.requirement-submit__select-text {
+ flex: 1;
+ font-size: 28rpx;
+ color: $color-text-primary;
+
+ &--placeholder {
+ color: $color-text-placeholder;
+ }
+}
+
+.requirement-submit__select-arrow {
+ flex-shrink: 0;
+ margin-left: 12rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+ transition: transform 0.2s ease;
+
+ &--open {
+ transform: rotate(180deg);
+ }
+}
+
+.requirement-submit__dropdown {
+ position: absolute;
+ top: calc(100% + 8rpx);
+ right: 0;
+ left: 0;
+ z-index: 21;
+ overflow: hidden;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
+}
+
+.requirement-submit__dropdown-item {
+ padding: 24rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &--active {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+}
+
+.requirement-submit__dropdown-mask {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 10;
+ background: transparent;
+}
+
+.requirement-submit__textarea-wrap {
+ position: relative;
+ padding: 20rpx 24rpx 48rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+}
+
+.requirement-submit__textarea {
+ width: 100%;
+ min-height: 180rpx;
+ font-size: 28rpx;
+ line-height: 1.6;
+ color: $color-text-primary;
+
+ &--remark {
+ min-height: 140rpx;
+ padding: 20rpx 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-sizing: border-box;
+ }
+}
+
+.requirement-submit__counter {
+ position: absolute;
+ right: 24rpx;
+ bottom: 16rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.requirement-submit__budget-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16rpx;
+}
+
+.requirement-submit__budget-item {
+ padding: 14rpx 28rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+
+ &--active {
+ color: $color-primary;
+ background: $color-primary-light;
+ border-color: $color-primary-light;
+ }
+}
+
+.requirement-submit__cycle-row {
+ display: flex;
+ align-items: center;
+}
+
+.requirement-submit__cycle-unit {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+}
+
+.requirement-submit__attachment-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+}
+
+.requirement-submit__attachment-item {
+ position: relative;
+ width: 120rpx;
+ height: 120rpx;
+}
+
+.requirement-submit__attachment-thumb {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ background: #f8f9fb;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+}
+
+.requirement-submit__attachment-icon {
+ width: 72rpx;
+ height: 72rpx;
+}
+
+.requirement-submit__attachment-remove {
+ position: absolute;
+ top: -10rpx;
+ right: -10rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.requirement-submit__attachment-remove-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.requirement-submit__attachment-add {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 120rpx;
+ height: 120rpx;
+ background: #f8f9fb;
+ border: 1rpx dashed #d8dde6;
+ border-radius: 12rpx;
+}
+
+.requirement-submit__attachment-add-icon {
+ font-size: 40rpx;
+ line-height: 1;
+ color: $color-text-secondary;
+}
+
+.requirement-submit__attachment-add-text {
+ margin-top: 8rpx;
+ font-size: 20rpx;
+ color: $color-text-secondary;
+}
+
+.requirement-submit__footer {
+ display: flex;
+ gap: 16rpx;
+ flex-shrink: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.requirement-submit__footer-btn {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+ height: 80rpx;
+ font-size: 28rpx;
+ border-radius: 12rpx;
+
+ &--outline {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+
+ &--primary {
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ }
+}
diff --git a/src/pages/home-index/requirement-submit/index.vue b/src/pages/home-index/requirement-submit/index.vue
index 4b836f8..7d2568e 100644
--- a/src/pages/home-index/requirement-submit/index.vue
+++ b/src/pages/home-index/requirement-submit/index.vue
@@ -350,357 +350,5 @@ function handleSubmit() {
diff --git a/src/pages/index.scss b/src/pages/index.scss
new file mode 100644
index 0000000..e69ae43
--- /dev/null
+++ b/src/pages/index.scss
@@ -0,0 +1,4 @@
+.root-container {
+ padding: 5rem 2.5rem;
+ text-align: center;
+}
diff --git a/src/pages/index.vue b/src/pages/index.vue
index 553811e..834e10c 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -12,9 +12,6 @@ import InputEntry from '@/components/InputEntry.vue'
-
diff --git a/src/pages/message-center/components/MessageItem.scss b/src/pages/message-center/components/MessageItem.scss
new file mode 100644
index 0000000..4b074f7
--- /dev/null
+++ b/src/pages/message-center/components/MessageItem.scss
@@ -0,0 +1,63 @@
+@import '@/styles/variables.scss';
+
+.message-item {
+ display: flex;
+ align-items: flex-start;
+ width: 100%;
+ box-sizing: border-box;
+ padding: 24rpx 32rpx;
+ background: $color-bg-page;
+
+ &:last-child {
+ border-bottom: none;
+ }
+}
+
+.message-item__icon-wrap {
+ flex-shrink: 0;
+ margin-right: 24rpx;
+}
+
+.message-item__icon {
+ width: 88rpx;
+ height: 88rpx;
+}
+
+.message-item__content {
+ flex: 1;
+ min-width: 0;
+ padding-top: 4rpx;
+}
+
+.message-item__row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.message-item__title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.message-item__time {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.message-item__preview {
+ margin-top: 8rpx;
+ min-height: 78rpx;
+ font-size: 26rpx;
+ line-height: 1.5;
+ color: $color-text-secondary;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
diff --git a/src/pages/message-center/components/MessageItem.vue b/src/pages/message-center/components/MessageItem.vue
index 412b1d6..8814e63 100644
--- a/src/pages/message-center/components/MessageItem.vue
+++ b/src/pages/message-center/components/MessageItem.vue
@@ -40,67 +40,5 @@ const emit = defineEmits<{
diff --git a/src/pages/message-center/customer-service/components/ChatMessage.scss b/src/pages/message-center/customer-service/components/ChatMessage.scss
new file mode 100644
index 0000000..13c1101
--- /dev/null
+++ b/src/pages/message-center/customer-service/components/ChatMessage.scss
@@ -0,0 +1,75 @@
+@import '@/styles/variables.scss';
+
+.chat-message {
+ display: flex;
+ align-items: flex-start;
+ margin-bottom: 32rpx;
+
+ &--user {
+ flex-direction: row-reverse;
+
+ .chat-message__body {
+ align-items: flex-end;
+ }
+
+ .chat-message__nickname {
+ text-align: right;
+ }
+ }
+
+ &--service {
+ flex-direction: row;
+
+ .chat-message__body {
+ align-items: flex-start;
+ }
+ }
+}
+
+.chat-message__avatar {
+ flex-shrink: 0;
+ width: 72rpx;
+ height: 72rpx;
+ border-radius: 50%;
+ background: #fff7e6;
+}
+
+.chat-message__body {
+ display: flex;
+ flex-direction: column;
+ max-width: calc(100% - 96rpx);
+ margin: 0 16rpx;
+}
+
+.chat-message__nickname {
+ margin-bottom: 8rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.chat-message__bubble {
+ padding: 20rpx 24rpx;
+ border-radius: 16rpx;
+
+ &--user {
+ background: $color-primary;
+ }
+
+ &--service {
+ background: #f2f3f5;
+ }
+}
+
+.chat-message__text {
+ font-size: 28rpx;
+ line-height: 1.5;
+ word-break: break-all;
+
+ .chat-message__bubble--user & {
+ color: #ffffff;
+ }
+
+ .chat-message__bubble--service & {
+ color: $color-text-primary;
+ }
+}
diff --git a/src/pages/message-center/customer-service/components/ChatMessage.vue b/src/pages/message-center/customer-service/components/ChatMessage.vue
index a7deba4..2f23fd0 100644
--- a/src/pages/message-center/customer-service/components/ChatMessage.vue
+++ b/src/pages/message-center/customer-service/components/ChatMessage.vue
@@ -34,79 +34,5 @@ defineProps<{
diff --git a/src/pages/message-center/customer-service/index.scss b/src/pages/message-center/customer-service/index.scss
new file mode 100644
index 0000000..4b37cdd
--- /dev/null
+++ b/src/pages/message-center/customer-service/index.scss
@@ -0,0 +1,129 @@
+@import '@/styles/variables.scss';
+
+.customer-service {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-page;
+}
+
+.customer-service__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+ border-bottom: 1rpx solid #f0f0f0;
+}
+
+.customer-service__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.customer-service__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.customer-service__title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.customer-service__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.customer-service__scroll {
+ flex: 1;
+ min-height: 0;
+ background: $color-bg-page;
+}
+
+.customer-service__messages {
+ padding: 24rpx 24rpx 32rpx;
+}
+
+.customer-service__footer {
+ flex-shrink: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.customer-service__input-row {
+ display: flex;
+ align-items: center;
+ gap: 16rpx;
+}
+
+.customer-service__tool-btn {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.customer-service__tool-icon {
+ width: 48rpx;
+ height: 48rpx;
+}
+
+.customer-service__input {
+ flex: 1;
+ height: 72rpx;
+ padding: 0 24rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+ background: #f2f3f5;
+ border-radius: 36rpx;
+}
+
+.customer-service__placeholder {
+ color: $color-text-placeholder;
+}
+
+.customer-service__panel {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-around;
+ min-height: 400rpx;
+ margin-top: 24rpx;
+ padding: 40rpx 24rpx 48rpx;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.customer-service__panel-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.customer-service__panel-icon-wrap {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 112rpx;
+ height: 112rpx;
+}
+
+.customer-service__panel-icon {
+ width: 112rpx;
+ height: 112rpx;
+}
+
+.customer-service__panel-label {
+ margin-top: 12rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
diff --git a/src/pages/message-center/customer-service/index.vue b/src/pages/message-center/customer-service/index.vue
index 18d95b3..9ba7714 100644
--- a/src/pages/message-center/customer-service/index.vue
+++ b/src/pages/message-center/customer-service/index.vue
@@ -167,133 +167,5 @@ function handleAttachment(type: 'camera' | 'photo' | 'file') {
diff --git a/src/pages/message-center/index.scss b/src/pages/message-center/index.scss
new file mode 100644
index 0000000..04fdc6a
--- /dev/null
+++ b/src/pages/message-center/index.scss
@@ -0,0 +1,43 @@
+@import '@/styles/variables.scss';
+
+.message-center {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-page;
+}
+
+.message-center__header {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 32rpx 28rpx;
+ background: $color-bg-page;
+}
+
+.message-center__title {
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.message-center__read-all {
+ position: absolute;
+ right: 32rpx;
+ bottom: 28rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.message-center__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.message-center__list {
+ width: 100%;
+ padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
+}
diff --git a/src/pages/message-center/index.vue b/src/pages/message-center/index.vue
index 1a00305..b4dfcf6 100644
--- a/src/pages/message-center/index.vue
+++ b/src/pages/message-center/index.vue
@@ -76,47 +76,5 @@ function handleMessageTap(item: MessageItem) {
diff --git a/src/pages/message-center/status-notification/components/StatusNotificationItem.scss b/src/pages/message-center/status-notification/components/StatusNotificationItem.scss
new file mode 100644
index 0000000..1525db0
--- /dev/null
+++ b/src/pages/message-center/status-notification/components/StatusNotificationItem.scss
@@ -0,0 +1,61 @@
+@import '@/styles/variables.scss';
+
+.status-notification-item {
+ display: flex;
+ align-items: flex-start;
+ width: 100%;
+ box-sizing: border-box;
+ padding: 24rpx 32rpx;
+ background: $color-bg-page;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+}
+
+.status-notification-item__icon {
+ flex-shrink: 0;
+ width: 88rpx;
+ height: 88rpx;
+ margin-right: 24rpx;
+}
+
+.status-notification-item__content {
+ flex: 1;
+ min-width: 0;
+ padding-top: 4rpx;
+}
+
+.status-notification-item__row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.status-notification-item__title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.status-notification-item__time {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.status-notification-item__preview {
+ margin-top: 8rpx;
+ min-height: 78rpx;
+ font-size: 26rpx;
+ line-height: 1.5;
+ color: $color-text-secondary;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
diff --git a/src/pages/message-center/status-notification/components/StatusNotificationItem.vue b/src/pages/message-center/status-notification/components/StatusNotificationItem.vue
index 007be45..bc4beaa 100644
--- a/src/pages/message-center/status-notification/components/StatusNotificationItem.vue
+++ b/src/pages/message-center/status-notification/components/StatusNotificationItem.vue
@@ -32,65 +32,5 @@ defineProps<{
diff --git a/src/pages/message-center/status-notification/index.scss b/src/pages/message-center/status-notification/index.scss
new file mode 100644
index 0000000..e63ad40
--- /dev/null
+++ b/src/pages/message-center/status-notification/index.scss
@@ -0,0 +1,87 @@
+@import '@/styles/variables.scss';
+
+.status-notification {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-page;
+}
+
+.status-notification__header {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 32rpx 28rpx;
+ background: $color-bg-page;
+}
+
+.status-notification__back {
+ position: absolute;
+ left: 32rpx;
+ bottom: 28rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.status-notification__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.status-notification__title {
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.status-notification__read-all {
+ position: absolute;
+ right: 32rpx;
+ bottom: 28rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.status-notification__search {
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ height: 72rpx;
+ margin: 0 32rpx 16rpx;
+ padding: 0 24rpx;
+ background: $color-bg-section;
+ border-radius: 36rpx;
+}
+
+.status-notification__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.status-notification__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.status-notification__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.status-notification__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.status-notification__list {
+ width: 100%;
+ padding-bottom: env(safe-area-inset-bottom);
+}
diff --git a/src/pages/message-center/status-notification/index.vue b/src/pages/message-center/status-notification/index.vue
index 280d618..a7a851a 100644
--- a/src/pages/message-center/status-notification/index.vue
+++ b/src/pages/message-center/status-notification/index.vue
@@ -92,91 +92,5 @@ function handleReadAll() {
diff --git a/src/pages/message-center/system-notification/index.scss b/src/pages/message-center/system-notification/index.scss
new file mode 100644
index 0000000..f471e4e
--- /dev/null
+++ b/src/pages/message-center/system-notification/index.scss
@@ -0,0 +1,87 @@
+@import '@/styles/variables.scss';
+
+.system-notification {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-page;
+}
+
+.system-notification__header {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 32rpx 28rpx;
+ background: $color-bg-page;
+}
+
+.system-notification__back {
+ position: absolute;
+ left: 32rpx;
+ bottom: 28rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.system-notification__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.system-notification__title {
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.system-notification__read-all {
+ position: absolute;
+ right: 32rpx;
+ bottom: 28rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.system-notification__search {
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ height: 72rpx;
+ margin: 0 32rpx 16rpx;
+ padding: 0 24rpx;
+ background: $color-bg-section;
+ border-radius: 36rpx;
+}
+
+.system-notification__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.system-notification__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.system-notification__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.system-notification__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.system-notification__list {
+ width: 100%;
+ padding-bottom: env(safe-area-inset-bottom);
+}
diff --git a/src/pages/message-center/system-notification/index.vue b/src/pages/message-center/system-notification/index.vue
index 93a3860..e6c9d3a 100644
--- a/src/pages/message-center/system-notification/index.vue
+++ b/src/pages/message-center/system-notification/index.vue
@@ -92,91 +92,5 @@ function handleReadAll() {
diff --git a/src/pages/personal-center/index.scss b/src/pages/personal-center/index.scss
new file mode 100644
index 0000000..d149875
--- /dev/null
+++ b/src/pages/personal-center/index.scss
@@ -0,0 +1,93 @@
+@import '@/styles/variables.scss';
+
+.personal-center {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-section;
+}
+
+.personal-center__header {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ padding: calc(var(--status-bar-height, 44px) + 48rpx) 32rpx 40rpx;
+}
+
+.personal-center__avatar {
+ flex-shrink: 0;
+ width: 120rpx;
+ height: 120rpx;
+ border-radius: 50%;
+ background: $color-bg-page;
+}
+
+.personal-center__profile {
+ flex: 1;
+ min-width: 0;
+ margin-left: 24rpx;
+}
+
+.personal-center__nickname-row {
+ display: flex;
+ align-items: center;
+}
+
+.personal-center__nickname {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.personal-center__edit-icon {
+ width: 28rpx;
+ height: 28rpx;
+ margin-left: 12rpx;
+}
+
+.personal-center__phone {
+ display: block;
+ margin-top: 12rpx;
+ font-size: 28rpx;
+ color: $color-text-secondary;
+}
+
+.personal-center__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.personal-center__menu-card {
+ margin: 0 24rpx;
+ padding: 8rpx 0 calc(140rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.personal-center__menu-item {
+ display: flex;
+ align-items: center;
+ min-height: 96rpx;
+ padding: 0 28rpx;
+}
+
+.personal-center__menu-icon {
+ flex-shrink: 0;
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.personal-center__menu-label {
+ flex: 1;
+ margin-left: 20rpx;
+ font-size: 30rpx;
+ color: $color-text-primary;
+}
+
+.personal-center__menu-arrow {
+ flex-shrink: 0;
+ font-size: 36rpx;
+ line-height: 1;
+ color: $color-text-placeholder;
+}
diff --git a/src/pages/personal-center/index.vue b/src/pages/personal-center/index.vue
index 484e593..170d302 100644
--- a/src/pages/personal-center/index.vue
+++ b/src/pages/personal-center/index.vue
@@ -1,41 +1,99 @@
-
-
- 个人中心
-
-
- 功能开发中
-
+
+
+
+
+
+
+
diff --git a/src/pages/project-center/after-sales-apply/index.scss b/src/pages/project-center/after-sales-apply/index.scss
new file mode 100644
index 0000000..07f5abf
--- /dev/null
+++ b/src/pages/project-center/after-sales-apply/index.scss
@@ -0,0 +1,328 @@
+@import '@/styles/variables.scss';
+
+.after-sales-apply {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.after-sales-apply__navbar {
+ position: relative;
+ z-index: 30;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 12rpx;
+ background: $color-bg-page;
+}
+
+.after-sales-apply__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.after-sales-apply__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.after-sales-apply__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.after-sales-apply__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.after-sales-apply__scroll {
+ flex: 1;
+ height: 0;
+ padding: 20rpx 24rpx;
+ box-sizing: border-box;
+}
+
+.after-sales-apply__card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 20rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &--dropdown {
+ position: relative;
+ z-index: 20;
+ overflow: visible;
+ }
+}
+
+.after-sales-apply__field {
+ margin-bottom: 28rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.after-sales-apply__label-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16rpx;
+}
+
+.after-sales-apply__label {
+ display: block;
+ margin-bottom: 16rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: $color-text-primary;
+
+ &--inline {
+ display: inline;
+ margin-bottom: 0;
+ }
+}
+
+.after-sales-apply__required {
+ color: #ff4d4f;
+}
+
+.after-sales-apply__hint {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.after-sales-apply__input {
+ width: 100%;
+ font-size: 28rpx;
+ color: $color-text-primary;
+
+ &--box {
+ height: 80rpx;
+ padding: 0 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-sizing: border-box;
+ }
+}
+
+.after-sales-apply__placeholder {
+ color: $color-text-placeholder;
+}
+
+.after-sales-apply__select-wrap {
+ position: relative;
+ z-index: 20;
+}
+
+.after-sales-apply__select {
+ display: flex;
+ align-items: center;
+ height: 80rpx;
+ padding: 0 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+}
+
+.after-sales-apply__select-text {
+ flex: 1;
+ font-size: 28rpx;
+ color: $color-text-primary;
+
+ &--placeholder {
+ color: $color-text-placeholder;
+ }
+}
+
+.after-sales-apply__select-arrow {
+ flex-shrink: 0;
+ margin-left: 12rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+ transition: transform 0.2s ease;
+
+ &--open {
+ transform: rotate(180deg);
+ }
+}
+
+.after-sales-apply__dropdown {
+ position: absolute;
+ top: calc(100% + 8rpx);
+ right: 0;
+ left: 0;
+ z-index: 21;
+ overflow: hidden;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
+}
+
+.after-sales-apply__dropdown-item {
+ padding: 24rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+ border-bottom: 1rpx solid #f0f0f0;
+
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &--active {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+}
+
+.after-sales-apply__dropdown-mask {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 10;
+ background: transparent;
+}
+
+.after-sales-apply__textarea-wrap {
+ position: relative;
+ padding: 20rpx 24rpx 48rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+}
+
+.after-sales-apply__textarea {
+ width: 100%;
+ min-height: 180rpx;
+ font-size: 28rpx;
+ line-height: 1.6;
+ color: $color-text-primary;
+
+ &--remark {
+ min-height: 140rpx;
+ padding: 20rpx 24rpx;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ border-radius: 12rpx;
+ box-sizing: border-box;
+ }
+}
+
+.after-sales-apply__counter {
+ position: absolute;
+ right: 24rpx;
+ bottom: 16rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.after-sales-apply__attachment-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+ padding: 10rpx 10rpx 0 0;
+}
+
+.after-sales-apply__attachment-item {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 160rpx;
+ padding: 20rpx 16rpx;
+ background: $color-bg-section;
+ border-radius: 12rpx;
+}
+
+.after-sales-apply__attachment-remove {
+ position: absolute;
+ top: -10rpx;
+ right: -10rpx;
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.after-sales-apply__attachment-remove-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.after-sales-apply__attachment-icon {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.after-sales-apply__attachment-name {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+ word-break: break-all;
+}
+
+.after-sales-apply__attachment-add {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 160rpx;
+ height: 160rpx;
+ background: #f8f9fb;
+ border: 1rpx dashed #d8dde6;
+ border-radius: 12rpx;
+}
+
+.after-sales-apply__attachment-add-icon {
+ font-size: 40rpx;
+ line-height: 1;
+ color: $color-text-secondary;
+}
+
+.after-sales-apply__attachment-add-text {
+ margin-top: 8rpx;
+ font-size: 20rpx;
+ color: $color-text-secondary;
+}
+
+.after-sales-apply__footer {
+ display: flex;
+ gap: 20rpx;
+ flex-shrink: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.after-sales-apply__footer-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 30rpx;
+ border-radius: 12rpx;
+
+ &--outline {
+ flex: 0.8;
+ color: $color-primary;
+ background: $color-bg-page;
+ border: 1rpx solid $color-primary;
+ }
+
+ &--primary {
+ flex: 1.2;
+ font-weight: 600;
+ color: #ffffff;
+ background: $color-primary;
+ }
+}
diff --git a/src/pages/project-center/after-sales-apply/index.vue b/src/pages/project-center/after-sales-apply/index.vue
new file mode 100644
index 0000000..6fdb44a
--- /dev/null
+++ b/src/pages/project-center/after-sales-apply/index.vue
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+ 申请售后
+
+
+
+
+
+
+
+
+ 业务类型
+ *
+
+
+
+
+
+ {{ businessType || '选择下方推荐的服务或手动输入服务名称' }}
+
+
+ ▾
+
+
+
+
+ {{ option }}
+
+
+
+
+
+
+
+
+
+ 项目名称
+ *
+
+
+
+
+
+
+
+ 核心需求描述
+ *
+
+
+
+
+
+ {{ descLength }}/500字
+
+
+
+
+
+
+ 用户名称
+
+
+
+
+
+
+ 用户手机号
+
+
+
+
+
+
+
+ 附件上传
+
+
+ 支持图片/文档/压缩包
+
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
+ +
+
+
+ 添加附件
+
+
+
+
+
+
+
+
+
+ 补充备注
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/project-center/bill-detail/index.scss b/src/pages/project-center/bill-detail/index.scss
new file mode 100644
index 0000000..375003b
--- /dev/null
+++ b/src/pages/project-center/bill-detail/index.scss
@@ -0,0 +1,148 @@
+@import '@/styles/variables.scss';
+
+.bill-detail {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.bill-detail__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+}
+
+.bill-detail__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.bill-detail__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.bill-detail__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-detail__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.bill-detail__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.bill-detail__content {
+ padding: 24rpx 24rpx calc(32rpx + env(safe-area-inset-bottom));
+}
+
+.bill-detail__hero {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 24rpx 0 40rpx;
+}
+
+.bill-detail__icon {
+ width: 120rpx;
+ height: 120rpx;
+}
+
+.bill-detail__status {
+ margin-top: 28rpx;
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-detail__amount {
+ margin-top: 16rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.bill-detail__card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.bill-detail__card-title {
+ display: block;
+ margin-bottom: 24rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-detail__info-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ margin-top: 20rpx;
+
+ &:first-of-type {
+ margin-top: 0;
+ }
+}
+
+.bill-detail__info-label {
+ flex-shrink: 0;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.bill-detail__info-value {
+ flex: 1;
+ margin-left: 24rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+ text-align: right;
+ word-break: break-all;
+}
+
+.bill-detail__order-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.bill-detail__order-title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-detail__order-amount {
+ flex-shrink: 0;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-detail__order-meta {
+ display: block;
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
diff --git a/src/pages/project-center/bill-detail/index.vue b/src/pages/project-center/bill-detail/index.vue
new file mode 100644
index 0000000..1ab494c
--- /dev/null
+++ b/src/pages/project-center/bill-detail/index.vue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+ 账单明细
+
+
+
+
+
+
+
+
+
+ 已支付
+
+
+ 付款金额:{{ formatAmount(bill.amount) }}
+
+
+
+
+
+ 支付信息
+
+
+
+ 支付方式
+
+
+ {{ paymentMethodLabel }}
+
+
+
+
+ 支付时间
+
+
+ {{ paymentTime }}
+
+
+
+
+ 交易流水号
+
+
+ {{ bill.transactionNo }}
+
+
+
+
+
+
+ 已支付订单
+
+
+
+ {{ bill.title }} {{ bill.ratio }}
+
+
+ {{ formatAmount(bill.amount) }}
+
+
+
+ 账单号:{{ bill.billNo }}
+
+
+ 关联项目:{{ bill.relatedProject }}
+
+
+
+
+
+
+
+
diff --git a/src/pages/project-center/bill-list/index.scss b/src/pages/project-center/bill-list/index.scss
new file mode 100644
index 0000000..2e897c7
--- /dev/null
+++ b/src/pages/project-center/bill-list/index.scss
@@ -0,0 +1,185 @@
+@import '@/styles/variables.scss';
+
+.bill-list {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.bill-list__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+}
+
+.bill-list__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.bill-list__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.bill-list__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-list__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.bill-list__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.bill-list__content {
+ padding: 24rpx 24rpx calc(32rpx + env(safe-area-inset-bottom));
+}
+
+.bill-list__summary {
+ display: flex;
+ padding: 28rpx 16rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.bill-list__summary-item {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+}
+
+.bill-list__summary-value {
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-list__summary-label {
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.bill-list__search {
+ display: flex;
+ align-items: center;
+ height: 72rpx;
+ margin-top: 24rpx;
+ padding: 0 24rpx;
+ background: $color-bg-page;
+ border-radius: 36rpx;
+}
+
+.bill-list__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.bill-list__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.bill-list__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.bill-list__card {
+ padding: 28rpx 24rpx;
+ margin-top: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.bill-list__card-header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.bill-list__card-title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-list__tag {
+ flex-shrink: 0;
+ padding: 4rpx 12rpx;
+ font-size: 20rpx;
+ border-radius: 6rpx;
+
+ &--paid {
+ color: #ffffff;
+ background: $color-primary;
+ }
+
+ &--pending {
+ color: #ffffff;
+ background: #ff9a3d;
+ }
+
+ &--not_due {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+}
+
+.bill-list__card-body {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-top: 20rpx;
+}
+
+.bill-list__card-meta {
+ flex: 1;
+ min-width: 0;
+ padding-right: 16rpx;
+}
+
+.bill-list__card-row {
+ display: block;
+ font-size: 22rpx;
+ line-height: 1.6;
+ color: #666666;
+}
+
+.bill-list__card-amount {
+ flex-shrink: 0;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.bill-list__pay-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 80rpx;
+ margin-top: 24rpx;
+ font-size: 28rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 12rpx;
+}
diff --git a/src/pages/project-center/bill-list/index.vue b/src/pages/project-center/bill-list/index.vue
new file mode 100644
index 0000000..09e7287
--- /dev/null
+++ b/src/pages/project-center/bill-list/index.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+
+
+ 账单明细
+
+
+
+
+
+
+
+
+
+ {{ BILL_LIST_SUMMARY.totalCount }}
+
+
+ 总笔数
+
+
+
+
+ ¥ {{ BILL_LIST_SUMMARY.totalAmount }}
+
+
+ 总金额
+
+
+
+
+ {{ BILL_LIST_SUMMARY.pendingCount }}
+
+
+ 待支付
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 交易流水号:{{ item.transactionNo }}
+
+
+ 账单号:{{ item.billNo }}
+
+
+ 关联项目:{{ item.relatedProject }}
+
+
+
+ {{ formatAmount(item.amount) }}
+
+
+
+ 立即支付
+
+
+
+
+
+
+
+
diff --git a/src/pages/project-center/components/ProjectCenterCard.scss b/src/pages/project-center/components/ProjectCenterCard.scss
new file mode 100644
index 0000000..48f5f6f
--- /dev/null
+++ b/src/pages/project-center/components/ProjectCenterCard.scss
@@ -0,0 +1,104 @@
+@import '@/styles/variables.scss';
+
+.project-center-card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+ margin-top: 20rpx;
+}
+
+.project-center-card__header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.project-center-card__title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-center-card__status {
+ flex-shrink: 0;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.project-center-card__meta {
+ display: flex;
+ align-items: center;
+ margin-top: 16rpx;
+}
+
+.project-center-card__tag {
+ flex-shrink: 0;
+ padding: 4rpx 12rpx;
+ font-size: 20rpx;
+ color: $color-primary;
+ background: $color-primary-light;
+ border-radius: 6rpx;
+}
+
+.project-center-card__no {
+ flex: 1;
+ min-width: 0;
+ margin-left: 12rpx;
+ font-size: 22rpx;
+ color: #666666;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.project-center-card__progress {
+ display: flex;
+ align-items: center;
+ margin-top: 24rpx;
+}
+
+.project-center-card__progress-bar {
+ flex: 1;
+ height: 12rpx;
+ overflow: hidden;
+ background: #eef2ff;
+ border-radius: 6rpx;
+}
+
+.project-center-card__progress-fill {
+ height: 100%;
+ background: $color-primary;
+ border-radius: 6rpx;
+}
+
+.project-center-card__progress-value {
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ font-size: 24rpx;
+ color: #666666;
+}
+
+.project-center-card__footer {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 20rpx;
+
+ &--simple {
+ justify-content: flex-end;
+ margin-top: 24rpx;
+ }
+}
+
+.project-center-card__time {
+ font-size: 22rpx;
+ color: #666666;
+}
+
+.project-center-card__detail {
+ font-size: 24rpx;
+ color: #666666;
+}
diff --git a/src/pages/project-center/components/ProjectCenterCard.vue b/src/pages/project-center/components/ProjectCenterCard.vue
index 684f2c6..d499285 100644
--- a/src/pages/project-center/components/ProjectCenterCard.vue
+++ b/src/pages/project-center/components/ProjectCenterCard.vue
@@ -66,108 +66,5 @@ const emit = defineEmits<{
diff --git a/src/pages/project-center/detail/index.scss b/src/pages/project-center/detail/index.scss
new file mode 100644
index 0000000..8ac68ea
--- /dev/null
+++ b/src/pages/project-center/detail/index.scss
@@ -0,0 +1,605 @@
+@import '@/styles/variables.scss';
+
+.project-detail {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.project-detail__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+}
+
+.project-detail__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.project-detail__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.project-detail__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-detail__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.project-detail__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.project-detail__content {
+ padding: 24rpx 24rpx calc(32rpx + env(safe-area-inset-bottom));
+}
+
+.project-detail__hero {
+ position: relative;
+ overflow: hidden;
+ border-radius: 20rpx;
+}
+
+.project-detail__hero-bg {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.project-detail__hero-inner {
+ position: relative;
+ z-index: 1;
+ padding: 28rpx 24rpx;
+}
+
+.project-detail__hero-top {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.project-detail__tag {
+ padding: 4rpx 12rpx;
+ font-size: 20rpx;
+ color: $color-primary;
+ background: $color-primary-light;
+ border-radius: 6rpx;
+}
+
+.project-detail__hero-status {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+}
+
+.project-detail__status {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__progress-text {
+ margin-top: 4rpx;
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__title {
+ display: block;
+ margin-top: 20rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-detail__no {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 22rpx;
+ color: #666666;
+}
+
+.project-detail__tabs {
+ display: flex;
+ margin-top: 24rpx;
+}
+
+.project-detail__tab {
+ flex: 1;
+ padding-bottom: 12rpx;
+ font-size: 28rpx;
+ text-align: center;
+ color: $color-text-secondary;
+
+ &--active {
+ font-weight: 600;
+ color: $color-text-primary;
+ border-bottom: 4rpx solid $color-primary;
+ }
+}
+
+.project-detail__panel {
+ margin-top: 24rpx;
+ padding: 28rpx 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.project-detail__panel-title {
+ display: block;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-detail__dev-progress {
+ padding-bottom: 8rpx;
+}
+
+.project-detail__overall {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 24rpx;
+}
+
+.project-detail__overall-label {
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__overall-value {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-primary;
+}
+
+.project-detail__slider {
+ margin-top: 20rpx;
+}
+
+.project-detail__slider-track {
+ position: relative;
+ height: 8rpx;
+ background: #e8eaef;
+ border-radius: 4rpx;
+}
+
+.project-detail__slider-fill {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: $color-primary;
+ border-radius: 4rpx;
+}
+
+.project-detail__slider-thumb {
+ position: absolute;
+ top: 50%;
+ width: 24rpx;
+ height: 24rpx;
+ margin-left: -12rpx;
+ background: $color-bg-page;
+ border: 4rpx solid $color-primary;
+ border-radius: 50%;
+ transform: translateY(-50%);
+}
+
+.project-detail__dates {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 20rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__timeline {
+ margin-top: 32rpx;
+ padding-top: 8rpx;
+}
+
+.project-detail__timeline-heading {
+ display: block;
+ margin-bottom: 24rpx;
+}
+
+.project-detail__timeline-item {
+ display: flex;
+ min-height: 96rpx;
+}
+
+.project-detail__timeline-left {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 48rpx;
+ margin-right: 20rpx;
+}
+
+.project-detail__timeline-dot {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 40rpx;
+ height: 40rpx;
+ border-radius: 50%;
+
+ &--done {
+ background: $color-primary;
+ }
+
+ &--active {
+ background: $color-primary;
+ }
+
+ &--pending {
+ background: $color-bg-page;
+ border: 2rpx solid #d8dde6;
+ }
+}
+
+.project-detail__timeline-check {
+ font-size: 22rpx;
+ color: #ffffff;
+}
+
+.project-detail__timeline-index {
+ font-size: 22rpx;
+ color: #ffffff;
+
+ .project-detail__timeline-dot--pending & {
+ color: $color-text-secondary;
+ }
+}
+
+.project-detail__timeline-line {
+ flex: 1;
+ width: 2rpx;
+ min-height: 40rpx;
+ margin-top: 8rpx;
+ background: #e8eaef;
+
+ &--done {
+ background: $color-primary;
+ }
+}
+
+.project-detail__timeline-body {
+ flex: 1;
+ padding-bottom: 28rpx;
+}
+
+.project-detail__timeline-title {
+ display: block;
+ font-size: 28rpx;
+ color: $color-text-primary;
+}
+
+.project-detail__timeline-time,
+.project-detail__timeline-status {
+ display: block;
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__timeline-status--active {
+ color: $color-primary;
+}
+
+.project-detail__team {
+ margin-top: 32rpx;
+ padding-top: 28rpx;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.project-detail__team-scroll {
+ margin-top: 24rpx;
+ white-space: nowrap;
+}
+
+.project-detail__team-inner {
+ display: inline-flex;
+ gap: 32rpx;
+}
+
+.project-detail__member {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 140rpx;
+}
+
+.project-detail__avatar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 96rpx;
+ height: 96rpx;
+ font-size: 28rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 50%;
+}
+
+.project-detail__member-name {
+ margin-top: 12rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.project-detail__member-role {
+ margin-top: 6rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__files {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+ padding: 10rpx 10rpx 0 0;
+}
+
+.project-detail__file {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 160rpx;
+ padding: 20rpx 16rpx;
+ background: $color-bg-section;
+ border-radius: 12rpx;
+}
+
+.project-detail__file-remove {
+ position: absolute;
+ top: -10rpx;
+ right: -10rpx;
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.project-detail__file-remove-icon {
+ width: 32rpx;
+ height: 32rpx;
+}
+
+.project-detail__file-icon {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.project-detail__file-name {
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-primary;
+ text-align: center;
+ word-break: break-all;
+}
+
+.project-detail__panel--section {
+ margin-top: 24rpx;
+}
+
+.project-detail__finance,
+.project-detail__aftersales {
+ margin-top: 24rpx;
+}
+
+.project-detail__payment-card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+}
+
+.project-detail__payment-header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.project-detail__payment-title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-detail__payment-tag {
+ flex-shrink: 0;
+ padding: 4rpx 12rpx;
+ font-size: 20rpx;
+ border-radius: 6rpx;
+
+ &--paid,
+ &--pending {
+ color: #ffffff;
+ background: $color-primary;
+ }
+
+ &--not_due {
+ color: $color-primary;
+ background: $color-primary-light;
+ }
+}
+
+.project-detail__payment-body {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ margin-top: 20rpx;
+}
+
+.project-detail__payment-meta {
+ flex: 1;
+ min-width: 0;
+ padding-right: 16rpx;
+}
+
+.project-detail__payment-row {
+ display: block;
+ font-size: 22rpx;
+ line-height: 1.6;
+ color: #666666;
+}
+
+.project-detail__payment-amount {
+ flex-shrink: 0;
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-detail__payment-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 80rpx;
+ margin-top: 24rpx;
+ font-size: 28rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 12rpx;
+}
+
+.project-detail__aftersales-banner {
+ display: flex;
+ align-items: center;
+ padding: 24rpx;
+ margin-bottom: 24rpx;
+ background: #FF7D29;
+ border-radius: 20rpx;
+}
+
+.project-detail__aftersales-banner-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 72rpx;
+ height: 72rpx;
+ margin-right: 20rpx;
+ border-radius: 50%;
+}
+
+.project-detail__aftersales-banner-icon-img {
+ width: 59.16rpx;
+ height: 59.16rpx;
+}
+
+.project-detail__aftersales-banner-text {
+ flex: 1;
+ min-width: 0;
+}
+
+.project-detail__aftersales-banner-title {
+ display: block;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #ffffff;
+}
+
+.project-detail__aftersales-banner-desc {
+ display: block;
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ line-height: 1.5;
+ color: rgba(255, 255, 255, 0.92);
+}
+
+.project-detail__info-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ margin-top: 24rpx;
+}
+
+.project-detail__info-label {
+ flex-shrink: 0;
+ font-size: 26rpx;
+ color: #333333;
+ font-weight: 500;
+}
+
+.project-detail__info-value {
+ flex: 1;
+ margin-left: 24rpx;
+ font-size: 26rpx;
+ color: #999999;
+ text-align: right;
+}
+
+.project-detail__files--with-add {
+ align-items: flex-start;
+}
+
+.project-detail__file-add {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 160rpx;
+ height: 160rpx;
+ background: $color-bg-section;
+ border: 1rpx dashed #d8dde6;
+ border-radius: 12rpx;
+}
+
+.project-detail__file-add-icon {
+ font-size: 40rpx;
+ line-height: 1;
+ color: $color-text-secondary;
+}
+
+.project-detail__file-add-text {
+ margin-top: 8rpx;
+ font-size: 20rpx;
+ color: $color-text-secondary;
+}
+
+.project-detail__aftersales-actions {
+ margin-top: 32rpx;
+}
+
+.project-detail__btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 30rpx;
+ border-radius: 12rpx;
+
+ &--primary {
+ color: #ffffff;
+ background: $color-primary;
+ }
+
+ &--outline {
+ margin-top: 20rpx;
+ color: $color-text-primary;
+ background: $color-bg-page;
+ border: 1rpx solid #e8eaef;
+ }
+}
diff --git a/src/pages/project-center/detail/index.vue b/src/pages/project-center/detail/index.vue
index 4de49bf..45a1887 100644
--- a/src/pages/project-center/detail/index.vue
+++ b/src/pages/project-center/detail/index.vue
@@ -1,7 +1,9 @@
@@ -97,23 +137,17 @@ function handleSelectTab(key: ProjectDetailTab) {
-
-
-
- {{ tab.label }}
-
+
+
+ {{ tab.label }}
-
+
-
- {{ detail.financeSummary }}
-
+
+
+
+
+
+ 交易流水号:{{ plan.transactionNo }}
+
+
+ 账单号:{{ plan.billNo }}
+
+
+ 关联项目:{{ plan.relatedProject }}
+
+
+
+ {{ formatAmount(plan.amount) }}
+
+
+
+ 立即支付
+
+
+
+
+
+ 付款计划
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
+
+
+
+ 合同文件
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
-
- {{ detail.afterSalesSummary }}
-
+
+
+
+
+
+
+ {{ detail.afterSales.bannerTitle }}
+
+
+ {{ detail.afterSales.bannerDesc }}
+
+
+
+
+
+
+ 售后信息
+
+
+
+ 售后类型
+
+
+ {{ detail.afterSales.type }}
+
+
+
+
+ 问题描述
+
+
+ {{ detail.afterSales.description }}
+
+
+
+
+
+
+ 附件
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+
+
+ +
+
+
+ 添加附件
+
+
+
+
+
+
+
+ 申请售后
+
+
+ 取消售后
+
+
@@ -289,415 +512,5 @@ function handleSelectTab(key: ProjectDetailTab) {
diff --git a/src/pages/project-center/index.scss b/src/pages/project-center/index.scss
new file mode 100644
index 0000000..634f436
--- /dev/null
+++ b/src/pages/project-center/index.scss
@@ -0,0 +1,111 @@
+@import '@/styles/variables.scss';
+
+.project-center {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ background: $color-bg-section;
+}
+
+.project-center__header {
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 60rpx) 24rpx 0;
+ background: $color-bg-page;
+}
+
+.project-center__title {
+ display: block;
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+ text-align: center;
+}
+
+.project-center__search {
+ display: flex;
+ align-items: center;
+ height: 72rpx;
+ margin-top: 24rpx;
+ padding: 0 24rpx;
+ background: $color-bg-section;
+ border-radius: 36rpx;
+}
+
+.project-center__search-icon {
+ flex-shrink: 0;
+ width: 32rpx;
+ height: 32rpx;
+ margin-right: 12rpx;
+}
+
+.project-center__search-input {
+ flex: 1;
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.project-center__search-placeholder {
+ color: $color-text-placeholder;
+}
+
+.project-center__tabs {
+ margin-top: 24rpx;
+ white-space: nowrap;
+}
+
+.project-center__tabs-inner {
+ display: inline-flex;
+ gap: 32rpx;
+ padding-right: 24rpx;
+}
+
+.project-center__tab {
+ flex-shrink: 0;
+ padding-bottom: 12rpx;
+ font-size: 28rpx;
+ color: $color-text-secondary;
+
+ &--active {
+ font-weight: 600;
+ color: $color-text-primary;
+ border-bottom: 4rpx solid $color-primary;
+ }
+}
+
+.project-center__toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20rpx 0 24rpx;
+}
+
+.project-center__count {
+ font-size: 24rpx;
+ color: $color-text-secondary;
+}
+
+.project-center__filter {
+ display: flex;
+ align-items: center;
+}
+
+.project-center__filter-icon {
+ width: 28rpx;
+ height: 28rpx;
+ margin-right: 8rpx;
+}
+
+.project-center__filter-text {
+ font-size: 26rpx;
+ color: #666666;
+}
+
+.project-center__scroll {
+ flex: 1;
+ min-height: 0;
+}
+
+.project-center__list {
+ padding: 0 24rpx calc(140rpx + env(safe-area-inset-bottom));
+}
diff --git a/src/pages/project-center/index.vue b/src/pages/project-center/index.vue
index 92d63e8..f0499b1 100644
--- a/src/pages/project-center/index.vue
+++ b/src/pages/project-center/index.vue
@@ -145,115 +145,5 @@ function handleViewDetail(id: string) {
diff --git a/src/pages/project-center/payment-success/index.scss b/src/pages/project-center/payment-success/index.scss
new file mode 100644
index 0000000..bbe6515
--- /dev/null
+++ b/src/pages/project-center/payment-success/index.scss
@@ -0,0 +1,136 @@
+@import '@/styles/variables.scss';
+
+.payment-success {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.payment-success__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.payment-success__content {
+ padding: calc(var(--status-bar-height, 44px) + 48rpx) 24rpx calc(140rpx + env(safe-area-inset-bottom));
+}
+
+.payment-success__hero {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 24rpx 0 40rpx;
+}
+
+.payment-success__icon {
+ width: 209.92rpx;
+ height: 209.92rpx;
+}
+
+.payment-success__title {
+ margin-top: 28rpx;
+ font-size: 36rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.payment-success__subtitle {
+ margin-top: 16rpx;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.payment-success__card {
+ padding: 28rpx 24rpx;
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.payment-success__card-title {
+ display: block;
+ margin-bottom: 24rpx;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.payment-success__info-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ margin-top: 20rpx;
+
+ &:first-of-type {
+ margin-top: 0;
+ }
+}
+
+.payment-success__info-label {
+ flex-shrink: 0;
+ font-size: 26rpx;
+ color: $color-text-secondary;
+}
+
+.payment-success__info-value {
+ flex: 1;
+ margin-left: 24rpx;
+ font-size: 26rpx;
+ color: $color-text-primary;
+ text-align: right;
+ word-break: break-all;
+}
+
+.payment-success__order-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.payment-success__order-title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.payment-success__order-amount {
+ flex-shrink: 0;
+ font-size: 28rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.payment-success__order-meta {
+ display: block;
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.payment-success__footer {
+ display: flex;
+ gap: 20rpx;
+ flex-shrink: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.payment-success__btn {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 28rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 12rpx;
+}
diff --git a/src/pages/project-center/payment-success/index.vue b/src/pages/project-center/payment-success/index.vue
new file mode 100644
index 0000000..5c07784
--- /dev/null
+++ b/src/pages/project-center/payment-success/index.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+ 支付成功
+
+
+ 共1个订单,付款金额:{{ formatAmount(plan.amount) }}
+
+
+
+
+
+ 支付信息
+
+
+
+ 支付方式
+
+
+ {{ paymentMethodLabel }}
+
+
+
+
+ 支付时间
+
+
+ {{ paymentTime }}
+
+
+
+
+ 交易流水号
+
+
+ {{ transactionNo }}
+
+
+
+
+
+
+ 已支付订单
+
+
+
+ {{ plan.title }} {{ plan.ratio }}
+
+
+ {{ formatAmount(plan.amount) }}
+
+
+
+ 账单号:{{ plan.billNo }}
+
+
+ 关联项目:{{ plan.relatedProject }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/project-center/payment/index.scss b/src/pages/project-center/payment/index.scss
new file mode 100644
index 0000000..2a3e6fe
--- /dev/null
+++ b/src/pages/project-center/payment/index.scss
@@ -0,0 +1,191 @@
+@import '@/styles/variables.scss';
+
+.project-payment {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ background: $color-bg-section;
+}
+
+.project-payment__navbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-shrink: 0;
+ padding: calc(var(--status-bar-height, 44px) + 12rpx) 24rpx 20rpx;
+ background: $color-bg-page;
+}
+
+.project-payment__back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.project-payment__back-icon {
+ width: 40rpx;
+ height: 40rpx;
+}
+
+.project-payment__navbar-title {
+ font-size: 34rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-payment__navbar-placeholder {
+ width: 64rpx;
+ height: 64rpx;
+}
+
+.project-payment__scroll {
+ flex: 1;
+ height: 0;
+}
+
+.project-payment__content {
+ padding: 24rpx 24rpx calc(140rpx + env(safe-area-inset-bottom));
+}
+
+.project-payment__card {
+ margin-bottom: 24rpx;
+ background: $color-bg-page;
+ border-radius: 20rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.project-payment__card-inner {
+ padding: 28rpx 24rpx;
+}
+
+.project-payment__card-title {
+ display: block;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: $color-text-primary;
+}
+
+.project-payment__order-row {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ margin-top: 24rpx;
+}
+
+.project-payment__order-title {
+ flex: 1;
+ padding-right: 16rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+}
+
+.project-payment__order-amount {
+ flex-shrink: 0;
+ font-size: 28rpx;
+ color: $color-text-primary;
+}
+
+.project-payment__order-meta {
+ display: block;
+ margin-top: 12rpx;
+ font-size: 22rpx;
+ color: $color-text-secondary;
+}
+
+.project-payment__order-divider {
+ height: 1rpx;
+ margin-top: 24rpx;
+ background: #f0f0f0;
+}
+
+.project-payment__order-summary {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-top: 24rpx;
+}
+
+.project-payment__order-summary-label {
+ font-size: 26rpx;
+ color: $color-text-primary;
+}
+
+.project-payment__order-summary-amount {
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ff4d4f;
+}
+
+.project-payment__method {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 28rpx 0;
+
+ &:first-of-type {
+ margin-top: 8rpx;
+ }
+
+ & + & {
+ border-top: 1rpx solid #f0f0f0;
+ }
+}
+
+.project-payment__method-left {
+ display: flex;
+ align-items: center;
+}
+
+.project-payment__method-icon {
+ width: 48rpx;
+ height: 48rpx;
+}
+
+.project-payment__method-label {
+ margin-left: 16rpx;
+ font-size: 28rpx;
+ color: $color-text-primary;
+}
+
+.project-payment__radio {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 36rpx;
+ height: 36rpx;
+ border: 2rpx solid #d8dde6;
+ border-radius: 50%;
+
+ &--active {
+ background: $color-primary;
+ border-color: $color-primary;
+ }
+}
+
+.project-payment__radio-check {
+ font-size: 20rpx;
+ color: #ffffff;
+}
+
+.project-payment__footer {
+ flex-shrink: 0;
+ padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom));
+ background: $color-bg-page;
+ border-top: 1rpx solid #f0f0f0;
+}
+
+.project-payment__confirm-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 88rpx;
+ font-size: 30rpx;
+ color: #ffffff;
+ background: $color-primary;
+ border-radius: 12rpx;
+}
diff --git a/src/pages/project-center/payment/index.vue b/src/pages/project-center/payment/index.vue
new file mode 100644
index 0000000..bfe2018
--- /dev/null
+++ b/src/pages/project-center/payment/index.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+ 确认支付
+
+
+
+
+
+
+
+
+
+ 订单明细
+
+
+
+ {{ plan.title }} {{ plan.ratio }}
+
+
+ {{ formatAmount(plan.amount) }}
+
+
+
+ 账单号:{{ plan.billNo }}
+
+
+ 关联项目:{{ plan.relatedProject }}
+
+
+
+
+ 已选 1笔订单,合计
+
+
+ {{ formatAmount(plan.amount) }}
+
+
+
+
+
+
+
+
+ 选择支付方式
+
+
+
+
+
+ {{ method.label }}
+
+
+
+
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/static/icon/about.png b/src/static/icon/about.png
new file mode 100644
index 0000000..4b9eee9
Binary files /dev/null and b/src/static/icon/about.png differ
diff --git a/src/static/icon/address.png b/src/static/icon/address.png
new file mode 100644
index 0000000..a2bc118
Binary files /dev/null and b/src/static/icon/address.png differ
diff --git a/src/static/icon/avatar.png b/src/static/icon/avatar.png
new file mode 100644
index 0000000..70fb545
Binary files /dev/null and b/src/static/icon/avatar.png differ
diff --git a/src/static/icon/contract-list.png b/src/static/icon/contract-list.png
new file mode 100644
index 0000000..535d62e
Binary files /dev/null and b/src/static/icon/contract-list.png differ
diff --git a/src/static/icon/edit.svg b/src/static/icon/edit.svg
new file mode 100644
index 0000000..f415496
--- /dev/null
+++ b/src/static/icon/edit.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/static/icon/favorites.png b/src/static/icon/favorites.png
new file mode 100644
index 0000000..1bc87c5
Binary files /dev/null and b/src/static/icon/favorites.png differ
diff --git a/src/static/icon/feedback.png b/src/static/icon/feedback.png
new file mode 100644
index 0000000..0ad9001
Binary files /dev/null and b/src/static/icon/feedback.png differ
diff --git a/src/static/icon/finance.png b/src/static/icon/finance.png
new file mode 100644
index 0000000..e1510ba
Binary files /dev/null and b/src/static/icon/finance.png differ
diff --git a/src/static/icon/help.png b/src/static/icon/help.png
new file mode 100644
index 0000000..5b4eb1c
Binary files /dev/null and b/src/static/icon/help.png differ
diff --git a/src/static/icon/invoice.png b/src/static/icon/invoice.png
new file mode 100644
index 0000000..f84d256
Binary files /dev/null and b/src/static/icon/invoice.png differ
diff --git a/src/static/icon/message-push.png b/src/static/icon/message-push.png
new file mode 100644
index 0000000..39c22df
Binary files /dev/null and b/src/static/icon/message-push.png differ
diff --git a/src/static/icon/qualification.png b/src/static/icon/qualification.png
new file mode 100644
index 0000000..0ec7754
Binary files /dev/null and b/src/static/icon/qualification.png differ
diff --git a/src/static/icon/security.png b/src/static/icon/security.png
new file mode 100644
index 0000000..6ff9666
Binary files /dev/null and b/src/static/icon/security.png differ
diff --git a/src/static/icon/service-hotline.png b/src/static/icon/service-hotline.png
new file mode 100644
index 0000000..e4da45c
Binary files /dev/null and b/src/static/icon/service-hotline.png differ
diff --git a/src/static/icons/售后.png b/src/static/icons/售后.png
new file mode 100644
index 0000000..6e4d9b4
Binary files /dev/null and b/src/static/icons/售后.png differ
diff --git a/src/static/icons/微信.png b/src/static/icons/微信.png
new file mode 100644
index 0000000..7becf15
Binary files /dev/null and b/src/static/icons/微信.png differ
diff --git a/src/static/icons/支付宝.png b/src/static/icons/支付宝.png
new file mode 100644
index 0000000..2f4b50c
Binary files /dev/null and b/src/static/icons/支付宝.png differ
diff --git a/src/types/bill.ts b/src/types/bill.ts
new file mode 100644
index 0000000..8f7694f
--- /dev/null
+++ b/src/types/bill.ts
@@ -0,0 +1,15 @@
+import type { PaymentPlanItem, PaymentPlanStatus } from '@/types/project-detail'
+
+export interface BillItem extends PaymentPlanItem {
+ projectId: string
+ paidAt?: string
+ paidMethod?: 'wechat' | 'alipay'
+}
+
+export interface BillListSummary {
+ totalCount: number
+ totalAmount: string
+ pendingCount: number
+}
+
+export type BillDetailStatus = PaymentPlanStatus
diff --git a/src/types/personal-center.ts b/src/types/personal-center.ts
new file mode 100644
index 0000000..e53d242
--- /dev/null
+++ b/src/types/personal-center.ts
@@ -0,0 +1,26 @@
+export type PersonalCenterMenuKey =
+ | 'security'
+ | 'message-push'
+ | 'feedback'
+ | 'contract-list'
+ | 'finance'
+ | 'invoice'
+ | 'address'
+ | 'favorites'
+ | 'qualification'
+ | 'help'
+ | 'about'
+ | 'service-hotline'
+
+export interface PersonalCenterMenuItem {
+ key: PersonalCenterMenuKey
+ label: string
+ icon: string
+ path?: string
+}
+
+export interface PersonalCenterProfile {
+ nickname: string
+ phone: string
+ avatar: string
+}
diff --git a/src/types/project-detail.ts b/src/types/project-detail.ts
index 3ef77eb..8258071 100644
--- a/src/types/project-detail.ts
+++ b/src/types/project-detail.ts
@@ -4,6 +4,8 @@ export type ProjectDetailTab = 'progress' | 'files' | 'finance' | 'aftersales'
export type ProjectProgressStepStatus = 'done' | 'active' | 'pending'
+export type PaymentPlanStatus = 'paid' | 'pending' | 'not_due'
+
export interface ProjectProgressStep {
id: string
title: string
@@ -24,12 +26,34 @@ export interface ProjectFileItem {
icon: string
}
+export interface PaymentPlanItem {
+ id: string
+ title: string
+ ratio: string
+ status: PaymentPlanStatus
+ transactionNo: string
+ billNo: string
+ relatedProject: string
+ amount: number
+}
+
+export interface AfterSalesDetail {
+ processing: boolean
+ bannerTitle: string
+ bannerDesc: string
+ type: string
+ description: string
+ attachments: ProjectFileItem[]
+}
+
export interface ProjectDetail extends ProjectCenterItem {
progressStartTime: string
progressEndTime: string
steps: ProjectProgressStep[]
team: ProjectTeamMember[]
files: ProjectFileItem[]
- financeSummary: string
- afterSalesSummary: string
+ paymentPlans: PaymentPlanItem[]
+ paymentPlanFiles: ProjectFileItem[]
+ contractFiles: ProjectFileItem[]
+ afterSales: AfterSalesDetail
}
diff --git a/src/types/result-page.ts b/src/types/result-page.ts
index 347f7a2..e9860a7 100644
--- a/src/types/result-page.ts
+++ b/src/types/result-page.ts
@@ -1,4 +1,4 @@
-export type ResultPageType = 'register' | 'resetPassword' | 'loginFailed' | 'submitSuccess'
+export type ResultPageType = 'register' | 'resetPassword' | 'loginFailed' | 'submitSuccess' | 'afterSalesSuccess'
export interface ResultPageConfig {
title: string
@@ -32,6 +32,12 @@ export const RESULT_PAGE_CONFIG: Record = {
icon: '/static/icons/icon-register-success.png',
redirectUrl: '/pages/home-index/index',
},
+ afterSalesSuccess: {
+ title: '申请成功',
+ subtitleTarget: '售后详情',
+ icon: '/static/icons/icon-register-success.png',
+ redirectUrl: '/pages/project-center/detail/index',
+ },
}
export const RESULT_PAGE_ROUTE = '/pages/Login/user-register-success/index'
diff --git a/src/utils/navigate-result.ts b/src/utils/navigate-result.ts
index f08263f..52fd0de 100644
--- a/src/utils/navigate-result.ts
+++ b/src/utils/navigate-result.ts
@@ -3,8 +3,13 @@ import {
type ResultPageType,
} from '@/types/result-page'
-export function navigateToResultPage(type: ResultPageType) {
- const url = `${RESULT_PAGE_ROUTE}?type=${type}`
+export function navigateToResultPage(type: ResultPageType, params?: Record) {
+ const pairs = [`type=${encodeURIComponent(type)}`]
+ if (params) {
+ for (const [key, value] of Object.entries(params))
+ pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
+ }
+ const url = `${RESULT_PAGE_ROUTE}?${pairs.join('&')}`
uni.redirectTo({
url,