From 6640f734bf30ce1b2bd3dc23708efefb5cc4753e Mon Sep 17 00:00:00 2001 From: MaDaLei Date: Tue, 14 Apr 2026 16:56:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=A2=84=E7=BA=A6?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=8F=8A=E5=A4=9A=E9=A1=B9UI/=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.config.json | 2 +- src/App.vue | 3 +- src/api/index.js | 6 + src/assets/global.css | 354 ++++--- src/components/AppIcon.vue | 53 +- src/components/TabBar.vue | 73 +- src/composables/useNavigator.js | 7 +- src/manifest.json | 7 +- src/pages.json | 5 +- src/pages/_template/PageStarter.vue | 2 +- src/pages/appointment/AppointmentDetail.vue | 202 ++++ src/pages/home/Home.vue | 827 +++++++-------- src/pages/login/Login.vue | 482 ++++++--- src/pages/mine/Mine.vue | 350 ++++--- src/pages/mine/MyOrders.vue | 28 +- src/pages/mine/MyReports.vue | 17 +- src/pages/mine/Profile.vue | 15 +- src/pages/mine/ServiceType.vue | 60 +- src/pages/mine/Staff.vue | 145 ++- src/pages/mine/Store.vue | 15 +- src/pages/report-view/reportView.vue | 1048 +++++++++++++------ src/pages/report/Report.vue | 514 +++++---- src/utils/globalState.js | 8 +- src/utils/reportPosterDraw.js | 362 ++++--- 24 files changed, 2885 insertions(+), 1700 deletions(-) create mode 100644 src/pages/appointment/AppointmentDetail.vue diff --git a/project.config.json b/project.config.json index 8b4a6d2..7963307 100644 --- a/project.config.json +++ b/project.config.json @@ -20,6 +20,6 @@ "ignore": [], "include": [] }, - "appid": "wx4fe9ae1e083c1c4f", + "appid": "wx8ca2dfa89af72edf", "editorSetting": {} } \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 765b0fe..66f9b6a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -41,7 +41,8 @@ page { margin: 0; padding: 0; box-sizing: border-box; - background: #f5f5f5; + background: #fafaf8; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #1a1a1a; } diff --git a/src/api/index.js b/src/api/index.js index eaf0dae..6e867f5 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -43,6 +43,9 @@ export const sendSms = (phone) => post('/sms/send', { phone }) // 登录 export const login = (phone, code) => post('/user/login', { phone, code }) +/** 微信小程序:getPhoneNumber 返回的 detail.code */ +export const wxPhoneLogin = (phoneCode) => post('/user/wx-phone-login', { phoneCode }) + // 注册老板 export const registerBoss = (data) => post('/user/register-boss', data) @@ -52,6 +55,9 @@ export const registerStaff = (data) => post('/user/register-staff', data) // 预约列表 export const getAppointmentList = (userId, storeId) => get('/appointment/list', { userId, storeId }) +// 预约详情 +export const getAppointmentDetail = (id) => get('/appointment/detail', { id }) + // 创建预约 export const createAppointment = (data) => post('/appointment/create', data) diff --git a/src/assets/global.css b/src/assets/global.css index 9393e20..8976866 100644 --- a/src/assets/global.css +++ b/src/assets/global.css @@ -1,133 +1,181 @@ /* ============================================================ - 宠伴生活馆 - 全局样式 + 宠伴生活馆 — 设计系统 v2 · 简约 · 温暖 · 专业 ============================================================ */ +:root { + --c-bg: #fafaf8; + --c-surface: #ffffff; + --c-surface-alt: #f5f5f2; + --c-border: #ebebea; + --c-border-light: #f0f0ee; + --c-text: #1a1a1a; + --c-text-2: #666660; + --c-text-3: #999993; + --c-text-4: #bbbbb5; + --c-brand: #2db96d; + --c-brand-light: #eaf8f0; + --c-brand-dark: #1e9a55; + --c-orange: #f5913e; + --c-orange-light: #fef5ec; + --c-red: #e5534b; + --c-shadow-sm: 0 1px 3px rgba(0,0,0,0.04); + --c-shadow: 0 2px 8px rgba(0,0,0,0.05); + --c-shadow-lg: 0 8px 24px rgba(0,0,0,0.06); + --radius-sm: 8px; + --radius: 12px; + --radius-lg: 16px; + --radius-xl: 20px; + --font: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + page { margin: 0; padding: 0; box-sizing: border-box; - background: linear-gradient(180deg, #f7f9fc 0%, #f3f6fa 100%); - font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, sans-serif; - color: #1f2937; + background: var(--c-bg); + font-family: var(--font); + color: var(--c-text); font-size: 15px; -webkit-font-smoothing: antialiased; } /* ---- 输入框 ---- */ .van-field { - background: #ffffff !important; - border: 1px solid #dfe5ee !important; - border-radius: 12px !important; - padding: 10px 14px !important; + background: var(--c-surface-alt) !important; + border: 1.5px solid transparent !important; + border-radius: var(--radius) !important; + padding: 11px 14px !important; font-size: 15px !important; - color: #1f2937 !important; + color: var(--c-text) !important; min-height: 44px !important; width: 100% !important; box-sizing: border-box !important; - transition: border-color 0.2s, box-shadow 0.2s; + transition: border-color 0.2s, background 0.2s; } .van-field:focus { - border-color: #22c55e !important; - box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.14) !important; + border-color: var(--c-brand) !important; + background: var(--c-surface) !important; } -.van-field::placeholder { color: #9aa4b2 !important; } +.van-field::placeholder { color: var(--c-text-4) !important; } -/* ---- 按钮 ---- */ +/* ---- 按钮 ---- + * 微信小程序原生 button 默认白底,会盖住 class 背景;且仅写 var(--c-brand) 在部分基础库下可能不生效, + * 导致「白底 + 白字」。此处用实色 + button 元素选择器强制覆盖。 */ .van-button { - border-radius: 12px !important; + border-radius: var(--radius) !important; font-size: 15px !important; - height: 44px !important; - line-height: 44px !important; + height: 46px !important; + line-height: 46px !important; font-weight: 600 !important; display: inline-flex !important; align-items: center !important; justify-content: center !important; + transition: opacity 0.15s, transform 0.15s; + box-sizing: border-box !important; } -.van-button--primary { - background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%) !important; - border: 1px solid #16a34a !important; - color: #fff !important; - box-shadow: 0 8px 20px rgba(34, 197, 94, 0.28) !important; -} -.van-button--primary:active { transform: translateY(1px); } -.van-button--block { width: 100% !important; margin-top: 12px !important; } -.van-button--small { - height: 34px !important; - line-height: 34px !important; - font-size: 13px !important; - padding: 0 14px !important; - border-radius: 8px !important; - background: #07c160 !important; - border: 1px solid #07c160 !important; - color: #fff !important; - flex-shrink: 0; -} -.van-button[disabled] { - background: #c8e8d8 !important; - border-color: #c8e8d8 !important; - color: #fff !important; +.van-button:active { opacity: 0.85; transform: scale(0.98); } +.van-button--primary, +button.van-button--primary { + background-color: #2db96d !important; + background: #2db96d !important; + border: none !important; + color: #ffffff !important; box-shadow: none !important; } -button::after { border: none !important; } +.van-button--block { width: 100% !important; margin-top: 12px !important; } -/* ---- 单元格组(卡片化) ---- */ +/* 小号按钮仅尺寸;主色需同时加 .van-button--primary,避免非主色按钮被设成白字 */ +.van-button--small { + height: 34px !important; + min-height: 34px !important; + line-height: 34px !important; + font-size: 13px !important; + padding: 0 16px !important; + border-radius: var(--radius-sm) !important; + flex-shrink: 0; +} +.van-button--small.van-button--primary, +button.van-button--small.van-button--primary { + background-color: #2db96d !important; + background: #2db96d !important; + color: #ffffff !important; + border: none !important; +} +/* 小号默认(取消等):浅底深字,保证对比度 */ +.van-button--small:not(.van-button--primary), +button.van-button--small:not(.van-button--primary) { + background-color: #f5f5f2 !important; + background: #f5f5f2 !important; + color: #1a1a1a !important; + border: 1px solid #ebebea !important; +} + +.van-button[disabled] { + background: var(--c-border) !important; + color: var(--c-text-4) !important; + box-shadow: none !important; +} +button::after { + border: none !important; +} + +/* ---- 单元格组 ---- */ .van-cell-group { - background: #fff !important; - border-radius: 18px !important; + background: var(--c-surface) !important; + border-radius: var(--radius-lg) !important; overflow: hidden; margin: 0 !important; - border: 1px solid #e7edf5; - box-shadow: 0 6px 20px rgba(15, 23, 42, 0.04); + border: none; + box-shadow: var(--c-shadow-sm); } .van-cell { padding: 14px 16px !important; - background: #fff !important; + background: var(--c-surface) !important; font-size: 15px !important; min-height: 48px !important; } .van-cell::after { left: 16px !important; right: 16px !important; - border-color: #eef2f7 !important; + border-color: var(--c-border-light) !important; } -.van-cell--link:active { background: #fafafa !important; } -.van-cell__title { color: #111827 !important; font-size: 15px !important; } -.van-cell__value { color: #6b7280 !important; font-size: 14px !important; } -.van-cell__arrow { color: #c3ccd8 !important; font-size: 16px !important; margin-left: 4px; } -.van-cell__icon { margin-right: 10px !important; } +.van-cell--link:active { background: var(--c-surface-alt) !important; } +.van-cell__title { color: var(--c-text) !important; font-size: 15px !important; } +.van-cell__value { color: var(--c-text-2) !important; font-size: 14px !important; } /* ---- 标签 ---- */ .van-tag { border-radius: 6px !important; font-size: 12px !important; padding: 2px 8px !important; + font-weight: 500; } -.van-tag--warning { background: #fff3e8 !important; color: #ff6b35 !important; } -.van-tag--primary { background: #e8f7ef !important; color: #07c160 !important; } -.van-tag--success { background: #f0f0f0 !important; color: #888 !important; } -.van-tag--default { background: #f5f5f5 !important; color: #999 !important; } +.van-tag--warning { background: var(--c-orange-light) !important; color: var(--c-orange) !important; } +.van-tag--primary { background: var(--c-brand-light) !important; color: var(--c-brand) !important; } +.van-tag--success { background: var(--c-surface-alt) !important; color: var(--c-text-3) !important; } +.van-tag--default { background: var(--c-surface-alt) !important; color: var(--c-text-4) !important; } -/* ---- 通用卡片容器 ---- */ +/* ---- 卡片 ---- */ .card-section { - background: #fff; - border-radius: 16px; + background: var(--c-surface); + border-radius: var(--radius-lg); overflow: hidden; margin: 0 16px; } -/* ---- 通用弹窗 ---- */ +/* ---- 弹窗 ---- */ .popup-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; - background: rgba(0,0,0,0.5); + background: rgba(0,0,0,0.35); z-index: 200; display: flex; align-items: flex-end; justify-content: center; } .popup-content { - background: #fff; - border-radius: 20px 20px 0 0; + background: var(--c-surface); + border-radius: var(--radius-xl) var(--radius-xl) 0 0; width: 100%; max-height: 85vh; display: flex; @@ -137,80 +185,57 @@ button::after { border: none !important; } display: flex; justify-content: space-between; align-items: center; - padding: 18px 20px 14px; - border-bottom: 1px solid #f0f0f0; + padding: 20px 20px 16px; flex-shrink: 0; } -.popup-title { font-size: 17px; font-weight: 600; color: #1a1a1a; } -.popup-close { font-size: 20px; color: #bbb; } -.popup-body { padding: 16px 20px; overflow-y: auto; flex: 1; } -.popup-footer { padding: 8px 20px max(env(safe-area-inset-bottom), 20px); flex-shrink: 0; } +.popup-title { font-size: 17px; font-weight: 700; color: var(--c-text); } +.popup-close { font-size: 20px; color: var(--c-text-4); } +.popup-body { padding: 0 20px 20px; overflow-y: auto; flex: 1; } +.popup-footer { padding: 12px 20px max(env(safe-area-inset-bottom), 20px); flex-shrink: 0; border-top: 1px solid var(--c-border-light); } /* ---- 字段标签 ---- */ .field-label { - font-size: 14px; - color: #666; - margin-bottom: 8px; + font-size: 13px; + color: var(--c-text-2); + margin-bottom: 6px; margin-top: 14px; - font-weight: 500; + font-weight: 600; + letter-spacing: 0.2px; } .field-label:first-child { margin-top: 0; } -/* ---- 表单卡片(用于登录/注册页) ---- */ +/* ---- 表单卡片 ---- */ .form-card { - background: #fff; - border-radius: 22px; + background: var(--c-surface); + border-radius: var(--radius-xl); padding: 28px 24px; - border: 1px solid #e8edf4; - box-shadow: 0 14px 40px rgba(15, 23, 42, 0.12); + box-shadow: var(--c-shadow); +} +.form-card > input.van-field { display: block; } +.form-card > input.van-field + input.van-field, +.form-card > input.van-field + .sms-field { + margin-top: 12px; } -/* ---- 主色调 ---- */ -:root { - --space-8: 8px; - --space-12: 12px; - --space-16: 16px; - --space-24: 24px; - --pet-green: #16a34a; - --pet-green-light: #e8f7ef; - --pet-orange: #f97316; - --pet-orange-light: #fff7ed; - --pet-bg: #f5f7fb; - --pet-text: #111827; - --pet-subtext: #6b7280; - --pet-border: #e5ebf3; - --pet-card-shadow: 0 8px 24px rgba(15, 23, 42, 0.06); -} - -/* Dark mode tokens (预埋,按需启用) */ -@media (prefers-color-scheme: dark) { - :root { - --pet-bg: #0f172a; - --pet-text: #e5e7eb; - --pet-subtext: #94a3b8; - --pet-border: #334155; - } -} - -/* ---- 通用 TabBar 样式(顶部状态栏) ---- */ +/* ---- Tabs ---- */ .van-tabs { display: flex; - background: #fff; - border-bottom: 1px solid #f0f0f0; + background: var(--c-surface); padding: 0 16px; } .van-tabs__tab { flex: 1; text-align: center; - padding: 12px 0; - font-size: 15px; - color: #999; + padding: 13px 0; + font-size: 14px; + color: var(--c-text-3); cursor: pointer; position: relative; + font-weight: 500; } .van-tabs__tab.active { - color: #07c160; - font-weight: 600; + color: var(--c-text); + font-weight: 700; } .van-tabs__tab.active::after { content: ''; @@ -218,103 +243,84 @@ button::after { border: none !important; } bottom: 0; left: 50%; transform: translateX(-50%); - width: 40px; - height: 3px; - background: #07c160; + width: 20px; + height: 2.5px; + background: var(--c-brand); border-radius: 2px; } -/* ---- 通用页面头部 ---- */ +/* ---- 导航头 ---- */ [class*='-nav'] { - border-bottom-left-radius: 16px; - border-bottom-right-radius: 16px; + border-bottom-left-radius: var(--radius-lg); + border-bottom-right-radius: var(--radius-lg); box-sizing: border-box; } .nav-title { - letter-spacing: 0.3px; + font-size: 17px; + font-weight: 700; + color: #fff; + letter-spacing: 0.2px; } .nav-back { - font-weight: 700; - width: 28px; - height: 28px; - border-radius: 8px; + width: 32px; + height: 32px; + border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; - transition: transform 0.16s ease, background-color 0.16s ease, opacity 0.16s ease; + transition: opacity 0.15s; -webkit-tap-highlight-color: transparent; } -.nav-back:active { - transform: scale(0.94); - opacity: 0.9; - background: rgba(255, 255, 255, 0.15); +.nav-back:active { opacity: 0.7; } +.nav-gradient { + background-color: #2db96d !important; + background: #2db96d !important; } -/* ---- 空状态统一 ---- */ +/* ---- 空状态 ---- */ .empty { margin: 24px 16px; - padding: 22px 16px; - background: #ffffff; - border: 1px solid var(--pet-border); - border-radius: 14px; - color: var(--pet-subtext); + padding: 32px 16px; + background: var(--c-surface); + border-radius: var(--radius-lg); + color: var(--c-text-3); text-align: center; + font-size: 14px; } -/* ---- 页面布局工具类 ---- */ +/* ---- 页面布局 ---- */ .page-shell { min-height: 100vh; - background: var(--pet-bg); + background: var(--c-bg); padding-bottom: 120rpx; } -.page-section { - margin: var(--space-16); -} -.section-gap { - margin-top: var(--space-12); -} +.page-section { margin: 16px; } +.section-gap { margin-top: 12px; } -/* ---- 常用内容间距 ---- */ +/* ---- 文本 ---- */ .module-title { font-size: 12px; - color: #94a3b8; + color: var(--c-text-3); font-weight: 700; - margin-bottom: var(--space-8); + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: 8px; } .form-field-wrap { - padding: 6px var(--space-16) var(--space-12); + padding: 6px 16px 12px; } +.text-title { font-size: 18px; font-weight: 700; color: var(--c-text); } +.text-body { font-size: 14px; color: var(--c-text); line-height: 1.6; } +.text-sub { font-size: 12px; color: var(--c-text-3); } -/* ---- 文本层级工具类 ---- */ -.text-title { - font-size: 18px; - font-weight: 700; - color: var(--pet-text); -} -.text-body { - font-size: 14px; - color: var(--pet-text); - line-height: 1.5; -} -.text-sub { - font-size: 12px; - color: var(--pet-subtext); -} - -/* ---- 导航头工具类 ---- */ -.nav-gradient { - background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%); - box-shadow: 0 8px 20px rgba(34, 197, 94, 0.25); -} - -/* ---- 微交互:统一点击反馈 ---- */ +/* ---- 微交互 ---- */ .van-button, .order-item, .gallery-item, .menu-card, .card-section, .user-card { - transition: transform 0.16s ease, box-shadow 0.2s ease, opacity 0.16s ease; + transition: transform 0.12s ease, opacity 0.12s ease; -webkit-tap-highlight-color: transparent; } .van-button:active, @@ -323,6 +329,6 @@ button::after { border: none !important; } .menu-card:active, .card-section:active, .user-card:active { - transform: translateY(1px) scale(0.995); - opacity: 0.97; + transform: scale(0.98); + opacity: 0.9; } diff --git a/src/components/AppIcon.vue b/src/components/AppIcon.vue index 2e397d4..6e4113f 100644 --- a/src/components/AppIcon.vue +++ b/src/components/AppIcon.vue @@ -1,17 +1,6 @@ diff --git a/src/components/TabBar.vue b/src/components/TabBar.vue index b79e027..11a5374 100644 --- a/src/components/TabBar.vue +++ b/src/components/TabBar.vue @@ -1,22 +1,16 @@ @@ -24,11 +18,14 @@ + + diff --git a/src/pages/home/Home.vue b/src/pages/home/Home.vue index adfffb4..910f979 100644 --- a/src/pages/home/Home.vue +++ b/src/pages/home/Home.vue @@ -1,160 +1,169 @@