diff --git a/apps/admin-web/src/App.vue b/apps/admin-web/src/App.vue index 36efd85..2b107d3 100644 --- a/apps/admin-web/src/App.vue +++ b/apps/admin-web/src/App.vue @@ -15,6 +15,8 @@ import ActivitiesView from './views/ActivitiesView.vue'; import ContentView from './views/ContentView.vue'; import NotificationDeliveriesView from './views/NotificationDeliveriesView.vue'; import StatisticsView from './views/StatisticsView.vue'; +import DashboardView from './views/DashboardView.vue'; +import AdminIcon from './components/AdminIcon.vue'; const auth = useAuthStore(); const form = reactive({ username: '', password: '' }); @@ -23,6 +25,7 @@ const submitting = ref(false); const showPassword = ref(false); const message = ref(''); const activeView = ref< + | 'dashboard' | 'applications' | 'beneficiaries' | 'cases' @@ -33,7 +36,7 @@ const activeView = ref< | 'content' | 'notifications' | 'statistics' ->('applications'); +>('dashboard'); onMounted(() => auth.restore()); @@ -136,13 +139,21 @@ async function logout(): Promise {
乐活公益管理平台
-

Phase 6:内容审核、站内消息与微信订阅通知

+

仅限授权人员访问,关键业务操作均记录审计。

@@ -230,7 +241,11 @@ async function logout(): Promise {
- + + diff --git a/apps/admin-web/src/components/AdminIcon.vue b/apps/admin-web/src/components/AdminIcon.vue new file mode 100644 index 0000000..ef5bfc0 --- /dev/null +++ b/apps/admin-web/src/components/AdminIcon.vue @@ -0,0 +1,30 @@ + + + diff --git a/apps/admin-web/src/styles.css b/apps/admin-web/src/styles.css index e16ac5d..612d91a 100644 --- a/apps/admin-web/src/styles.css +++ b/apps/admin-web/src/styles.css @@ -1,5 +1,12 @@ :root { - --color-primary: #ff6b35; + --primitive-orange-500: #ff6b35; + --primitive-orange-600: #e95a28; + --primitive-navy-900: #202c38; + --primitive-navy-800: #293746; + --primitive-gray-50: #f5f7f9; + --primitive-gray-200: #e4e8ec; + --primitive-white: #fff; + --color-primary: var(--primitive-orange-500); --color-primary-hover: #e95a28; --color-primary-soft: #fff1eb; --color-text: #1f2329; @@ -8,10 +15,10 @@ --color-success: #237a2b; --color-warning: #8a5a00; --color-info: #145ea8; - --color-surface: #fff; - --color-background: #f5f5f5; - --color-border: #d9dce1; - --color-sidebar: #263342; + --color-surface: var(--primitive-white); + --color-background: var(--primitive-gray-50); + --color-border: var(--primitive-gray-200); + --color-sidebar: var(--primitive-navy-900); --focus-ring: 0 0 0 3px rgb(255 107 53 / 28%); color: var(--color-text); background: var(--color-background); @@ -211,6 +218,7 @@ input[aria-invalid='true'] { overflow-y: auto; } .nav-item { + display: flex; width: 100%; min-height: 48px; padding: 10px 14px; @@ -219,6 +227,15 @@ input[aria-invalid='true'] { color: #e8edf2; background: transparent; text-align: left; + align-items: center; + gap: 12px; +} +.admin-icon { + width: 19px; + height: 19px; + flex: 0 0 auto; + fill: currentColor; + opacity: 0.9; } .nav-item--active { color: #fff; @@ -246,6 +263,234 @@ input[aria-invalid='true'] { font-size: 13px; line-height: 1.6; } +.page-kicker { + margin: 0 0 6px !important; + color: var(--color-primary) !important; + font-size: 13px; + font-weight: 700; + letter-spacing: 0.08em; +} +.dashboard-summary .summary-card { + border: 0; + border-top: 3px solid var(--color-primary); + box-shadow: 0 5px 18px rgb(28 39 51 / 7%); +} +.dashboard-summary .summary-card:nth-child(2) { + border-color: #378fe8; +} +.dashboard-summary .summary-card:nth-child(3) { + border-color: #42af57; +} +.dashboard-summary .summary-card:nth-child(4) { + border-color: #ffb13b; +} +.dashboard-charts { + display: grid; + margin-bottom: 20px; + grid-template-columns: minmax(0, 1.4fr) minmax(320px, 0.8fr); + gap: 20px; +} +.chart-panel { + min-height: 360px; +} +.panel-heading { + display: flex; + margin-bottom: 20px; + align-items: flex-start; + justify-content: space-between; + gap: 20px; +} +.panel-heading h2 { + margin: 0 0 5px; +} +.panel-heading p, +.panel-heading > span { + margin: 0; + color: var(--color-text-secondary); + font-size: 13px; +} +.bar-chart { + display: flex; + height: 220px; + padding: 18px 10px 0; + align-items: stretch; + justify-content: space-around; + gap: 10px; + border-bottom: 1px solid var(--color-border); + background: repeating-linear-gradient( + to bottom, + #eef1f4 0, + #eef1f4 1px, + transparent 1px, + transparent 55px + ); +} +.bar-column { + display: flex; + min-width: 36px; + flex: 1; + flex-direction: column; + align-items: center; + justify-content: flex-end; + gap: 8px; +} +.bar-values { + display: flex; + width: 100%; + height: 180px; + align-items: flex-end; + justify-content: center; + gap: 5px; +} +.bar { + display: block; + width: min(18px, 35%); + min-height: 5px; + border-radius: 4px 4px 0 0; +} +.bar--application { + background: #4b98ee; +} +.bar--completed { + background: #ff7848; +} +.bar-column small { + color: var(--color-text-secondary); +} +.chart-legend { + display: flex; + margin-top: 18px; + justify-content: center; + gap: 24px; + color: var(--color-text-secondary); + font-size: 13px; +} +.legend-dot { + display: inline-block; + width: 9px; + height: 9px; + margin-right: 7px; + border-radius: 50%; +} +.legend-dot--blue { + background: #4b98ee; +} +.legend-dot--orange { + background: #ff7848; +} +.distribution-list { + display: grid; + gap: 19px; +} +.distribution-list > div > div { + display: flex; + margin-bottom: 7px; + justify-content: space-between; + font-size: 14px; +} +.distribution-list progress { + width: 100%; + height: 8px; + overflow: hidden; + border: 0; + border-radius: 10px; + accent-color: var(--color-primary); +} +.quick-panel { + margin-bottom: 28px; +} +.quick-actions { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 14px; +} +.quick-actions button { + display: flex; + min-height: 76px; + padding: 14px; + align-items: center; + gap: 12px; + border: 1px solid var(--color-border); + border-radius: 12px; + color: var(--color-text); + background: #fff; + text-align: left; +} +.quick-actions b { + display: grid; + width: 38px; + height: 38px; + place-items: center; + border-radius: 10px; + color: #fff; + background: var(--color-primary); +} +.quick-actions .blue { + background: #378fe8; +} +.quick-actions .green { + background: #42af57; +} +.quick-actions .gold { + background: #e8a22c; +} +.muted-text { + color: var(--color-text-secondary); +} +.case-stepper { + display: grid; + margin-bottom: 20px; + padding: 24px 32px; + grid-template-columns: repeat(5, 1fr); + border: 1px solid var(--color-border); + border-radius: 14px; + background: #fff; +} +.case-stepper div { + position: relative; + display: flex; + align-items: center; + flex-direction: column; + gap: 8px; + color: var(--color-text-secondary); + font-size: 13px; +} +.case-stepper div:not(:last-child)::after { + position: absolute; + z-index: 0; + top: 14px; + left: calc(50% + 20px); + width: calc(100% - 40px); + height: 2px; + content: ''; + background: #dde2e6; +} +.case-stepper i { + position: relative; + z-index: 1; + display: grid; + width: 30px; + height: 30px; + place-items: center; + border: 2px solid #cbd2d8; + border-radius: 50%; + color: #7c858d; + background: #fff; + font-style: normal; + font-weight: 700; +} +.case-stepper .done { + color: #268948; + font-weight: 600; +} +.case-stepper .done i { + border-color: #3daf5c; + color: #fff; + background: #3daf5c; +} +.case-stepper .done:not(:last-child)::after { + background: #78ca8d; +} .admin-main { min-width: 0; } @@ -742,6 +987,12 @@ button.summary-card:hover { .summary-grid { grid-template-columns: 1fr 1fr; } + .dashboard-charts { + grid-template-columns: 1fr; + } + .quick-actions { + grid-template-columns: 1fr 1fr; + } } @media (max-width: 760px) { @@ -789,6 +1040,9 @@ button.summary-card:hover { .summary-grid { grid-template-columns: 1fr; } + .quick-actions { + grid-template-columns: 1fr; + } } @media (prefers-reduced-motion: reduce) { diff --git a/apps/admin-web/src/views/DashboardView.vue b/apps/admin-web/src/views/DashboardView.vue new file mode 100644 index 0000000..c7a3019 --- /dev/null +++ b/apps/admin-web/src/views/DashboardView.vue @@ -0,0 +1,146 @@ + + + diff --git a/apps/admin-web/src/views/ServiceCasesView.vue b/apps/admin-web/src/views/ServiceCasesView.vue index d044b35..72dcb38 100644 --- a/apps/admin-web/src/views/ServiceCasesView.vue +++ b/apps/admin-web/src/views/ServiceCasesView.vue @@ -318,6 +318,25 @@ onMounted(() => load()); 仅可将以下信息用于已分配的公益服务;查看、指派和记录操作均会留痕。

{{ message }}

+
+
1已建单
+
+ 2已指派 +
+
+ 3服务中 +
+
+ 4服务完成 +
+
+ 5进入回访 +
+

服务计划

diff --git a/apps/miniprogram/miniprogram/app.wxss b/apps/miniprogram/miniprogram/app.wxss index 0d94a84..f1bcf6f 100644 --- a/apps/miniprogram/miniprogram/app.wxss +++ b/apps/miniprogram/miniprogram/app.wxss @@ -1,5 +1,15 @@ page { - /* 乐活公益公众端设计令牌:暖、可信、适老。 */ + /* Primitive → semantic → component tokens. */ + --primitive-orange-500: #ff6b35; + --primitive-orange-600: #e85220; + --primitive-orange-50: #fff5ef; + --primitive-green-500: #34ad50; + --primitive-blue-500: #2f91ed; + --primitive-gray-950: #1f2429; + --primitive-gray-600: #687078; + --primitive-gray-200: #e8ebee; + --primitive-gray-50: #f6f7f8; + --primitive-white: #ffffff; --color-primary: #f05a28; --color-primary-pressed: #d94718; --color-primary-soft: #fff0e8; @@ -12,16 +22,18 @@ page { --color-warning: #b76e00; --color-warning-soft: #fff6dd; --color-danger: #b42318; - --color-text: #24211f; - --color-text-secondary: #6e6862; + --color-text: var(--primitive-gray-950); + --color-text-secondary: var(--primitive-gray-600); --color-text-tertiary: #918a83; - --color-border: #e9e3dd; - --color-background: #f7f5f2; - --color-surface: #ffffff; + --color-border: var(--primitive-gray-200); + --color-divider: #f0f1f2; + --color-background: var(--primitive-gray-50); + --color-surface: var(--primitive-white); --radius-sm: 16rpx; --radius-md: 24rpx; --radius-lg: 32rpx; --shadow-card: 0 10rpx 32rpx rgba(91, 62, 45, 0.07); + --shadow-hero: 0 16rpx 38rpx rgba(231, 79, 29, 0.22); min-height: 100%; color: var(--color-text); background: var(--color-background); diff --git a/apps/miniprogram/miniprogram/assets/images/brand-child-care.jpg b/apps/miniprogram/miniprogram/assets/images/brand-child-care.jpg new file mode 100644 index 0000000..2c758db Binary files /dev/null and b/apps/miniprogram/miniprogram/assets/images/brand-child-care.jpg differ diff --git a/apps/miniprogram/miniprogram/assets/images/brand-disability-support.jpg b/apps/miniprogram/miniprogram/assets/images/brand-disability-support.jpg new file mode 100644 index 0000000..3a71690 Binary files /dev/null and b/apps/miniprogram/miniprogram/assets/images/brand-disability-support.jpg differ diff --git a/apps/miniprogram/miniprogram/assets/images/brand-elder-care.jpg b/apps/miniprogram/miniprogram/assets/images/brand-elder-care.jpg new file mode 100644 index 0000000..6512465 Binary files /dev/null and b/apps/miniprogram/miniprogram/assets/images/brand-elder-care.jpg differ diff --git a/apps/miniprogram/miniprogram/assets/images/brand-women-support.jpg b/apps/miniprogram/miniprogram/assets/images/brand-women-support.jpg new file mode 100644 index 0000000..6070d1d Binary files /dev/null and b/apps/miniprogram/miniprogram/assets/images/brand-women-support.jpg differ diff --git a/apps/miniprogram/miniprogram/constants/future-capabilities.ts b/apps/miniprogram/miniprogram/constants/future-capabilities.ts new file mode 100644 index 0000000..40a8340 --- /dev/null +++ b/apps/miniprogram/miniprogram/constants/future-capabilities.ts @@ -0,0 +1,13 @@ +/** + * 后续能力只在此登记扩展边界,不注册页面、不展示入口,也不产生模拟数据。 + * 接入时必须完成独立产品评审、接口契约、权限、审计与迁移设计。 + */ +export const FUTURE_CAPABILITIES = { + donation: { enabled: false, route: '' }, + recurringDonation: { enabled: false, route: '' }, + donationRecords: { enabled: false, route: '' }, + materialOrders: { enabled: false, route: '' }, + volunteerLearning: { enabled: false, route: '' }, + volunteerCredentials: { enabled: false, route: '' }, + volunteerTeams: { enabled: false, route: '' }, +} as const; diff --git a/apps/miniprogram/miniprogram/custom-tab-bar/index.ts b/apps/miniprogram/miniprogram/custom-tab-bar/index.ts index f8c98ff..a46d07a 100644 --- a/apps/miniprogram/miniprogram/custom-tab-bar/index.ts +++ b/apps/miniprogram/miniprogram/custom-tab-bar/index.ts @@ -2,10 +2,10 @@ Component({ data: { selected: 0, tabs: [ - { pagePath: '/pages/index/index', text: '首页', icon: '⌂' }, - { pagePath: '/pages/service-hub/service-hub', text: '服务', icon: '♡' }, - { pagePath: '/pages/public-welfare/public-welfare', text: '公益', icon: '◎' }, - { pagePath: '/pages/profile/profile', text: '我的', icon: '○' }, + { pagePath: '/pages/index/index', text: '首页', icon: 'home' }, + { pagePath: '/pages/service-hub/service-hub', text: '服务', icon: 'service' }, + { pagePath: '/pages/public-welfare/public-welfare', text: '发现', icon: 'discover' }, + { pagePath: '/pages/profile/profile', text: '我的', icon: 'profile' }, ], }, lifetimes: { diff --git a/apps/miniprogram/miniprogram/custom-tab-bar/index.wxml b/apps/miniprogram/miniprogram/custom-tab-bar/index.wxml index 395842f..428a3df 100644 --- a/apps/miniprogram/miniprogram/custom-tab-bar/index.wxml +++ b/apps/miniprogram/miniprogram/custom-tab-bar/index.wxml @@ -1,7 +1,7 @@ diff --git a/apps/miniprogram/miniprogram/custom-tab-bar/index.wxss b/apps/miniprogram/miniprogram/custom-tab-bar/index.wxss index ff82d75..9afa970 100644 --- a/apps/miniprogram/miniprogram/custom-tab-bar/index.wxss +++ b/apps/miniprogram/miniprogram/custom-tab-bar/index.wxss @@ -1,45 +1,117 @@ .tab-bar { position: fixed; - z-index: 100; + z-index: 90; right: 0; bottom: 0; left: 0; - padding-bottom: env(safe-area-inset-bottom); - background: rgba(255, 255, 255, 0.98); - border-top: 2rpx solid #eee8e2; - box-shadow: 0 -8rpx 28rpx rgba(74, 55, 43, 0.06); + padding: 0 20rpx env(safe-area-inset-bottom); } .tab-bar__inner { - display: flex; - height: 112rpx; - align-items: stretch; + display: grid; + height: 106rpx; + padding: 8rpx 10rpx 4rpx; + grid-template-columns: repeat(4, 1fr); + border: 2rpx solid #eceff1; + border-bottom: 0; + border-radius: 28rpx 28rpx 0 0; + background: rgba(255, 255, 255, 0.97); + box-shadow: 0 -8rpx 30rpx rgba(31, 36, 41, 0.08); + box-sizing: border-box; } .tab { display: flex; min-width: 0; margin: 0; - padding: 10rpx 4rpx 8rpx; - flex: 1; + padding: 4rpx; flex-direction: column; align-items: center; justify-content: center; - color: #77716b; + gap: 5rpx; + color: #7b8288; background: transparent; - font-size: 23rpx; + font-size: 21rpx; line-height: 1; } -.tab__icon { - height: 40rpx; - font-size: 38rpx; - font-weight: 700; - line-height: 40rpx; -} -.tab__text { - margin-top: 7rpx; -} .tab--active { color: #f05a28; -} -.tab--active .tab__text { font-weight: 700; } +.tab__icon { + position: relative; + width: 38rpx; + height: 38rpx; + color: currentColor; +} +.tab__icon::before, +.tab__icon::after, +.tab__icon-core { + position: absolute; + box-sizing: border-box; + content: ''; +} +.tab__icon--home::before { + left: 6rpx; + bottom: 4rpx; + width: 27rpx; + height: 24rpx; + border: 4rpx solid currentColor; + border-top: 0; + border-radius: 3rpx; +} +.tab__icon--home::after { + left: 6rpx; + top: 4rpx; + width: 26rpx; + height: 26rpx; + border-top: 4rpx solid currentColor; + border-left: 4rpx solid currentColor; + transform: rotate(45deg); +} +.tab__icon--service::before { + left: 2rpx; + top: 10rpx; + width: 34rpx; + height: 22rpx; + border: 4rpx solid currentColor; + border-radius: 18rpx 18rpx 9rpx 9rpx; + transform: rotate(-10deg); +} +.tab__icon--service::after { + left: 9rpx; + top: 0; + width: 20rpx; + height: 17rpx; + border: 4rpx solid currentColor; + border-bottom: 0; + border-radius: 15rpx 15rpx 0 0; +} +.tab__icon--discover::before { + inset: 3rpx; + border: 4rpx solid currentColor; + border-radius: 50%; +} +.tab__icon--discover::after { + left: 15rpx; + top: 9rpx; + width: 9rpx; + height: 18rpx; + border-radius: 8rpx 8rpx 2rpx 2rpx; + background: currentColor; + transform: rotate(35deg); +} +.tab__icon--profile::before { + left: 12rpx; + top: 2rpx; + width: 15rpx; + height: 15rpx; + border: 4rpx solid currentColor; + border-radius: 50%; +} +.tab__icon--profile::after { + left: 5rpx; + bottom: 1rpx; + width: 29rpx; + height: 18rpx; + border: 4rpx solid currentColor; + border-radius: 18rpx 18rpx 4rpx 4rpx; +} diff --git a/apps/miniprogram/miniprogram/pages/application-form/application-form.wxml b/apps/miniprogram/miniprogram/pages/application-form/application-form.wxml index d094786..b08d7d8 100644 --- a/apps/miniprogram/miniprogram/pages/application-form/application-form.wxml +++ b/apps/miniprogram/miniprogram/pages/application-form/application-form.wxml @@ -20,8 +20,7 @@ - 需要什么帮助? - 请选择最接近的一项,工作人员后续会进一步了解。 + 请选择需要的服务类型我们会认真了解并及时回应 diff --git a/apps/miniprogram/miniprogram/pages/application-form/application-form.wxss b/apps/miniprogram/miniprogram/pages/application-form/application-form.wxss index 31ca8a1..d36a975 100644 --- a/apps/miniprogram/miniprogram/pages/application-form/application-form.wxss +++ b/apps/miniprogram/miniprogram/pages/application-form/application-form.wxss @@ -235,3 +235,36 @@ transition: none; } } +.application-banner { + display: flex; + min-height: 126rpx; + margin: -32rpx -32rpx 24rpx; + padding: 28rpx 30rpx; + flex-direction: column; + justify-content: center; + border-radius: 30rpx 30rpx 16rpx 16rpx; + color: #e84e1e; + background: linear-gradient(120deg, #fff0e7, #fff8f3); + font-weight: 800; +} +.application-banner text:last-child { + margin-top: 7rpx; + color: #7b6257; + font-size: 24rpx; + font-weight: 400; +} +.selection-photo { + width: 148rpx; + height: 104rpx; + flex: 0 0 auto; + border-radius: 18rpx; + object-fit: cover; +} +.selection-photo--fallback { + display: flex; + align-items: center; + justify-content: center; + color: #7c6d65; + background: #f4f1ee; + font-size: 22rpx; +} diff --git a/apps/miniprogram/miniprogram/pages/index/index.ts b/apps/miniprogram/miniprogram/pages/index/index.ts index 4af3f1c..6f081b8 100644 --- a/apps/miniprogram/miniprogram/pages/index/index.ts +++ b/apps/miniprogram/miniprogram/pages/index/index.ts @@ -9,12 +9,10 @@ Page({ title: MINI_PROGRAM_TITLE, canCollaborate: false, serviceCategories: [ - { code: 'OLD_AGE', label: '关爱老人', icon: '人', tone: 'orange' }, - { code: 'WOMEN_CHILDREN', label: '妇女帮扶', icon: '爱', tone: 'rose' }, - { code: 'WOMEN_CHILDREN', label: '儿童关爱', icon: '苗', tone: 'green' }, - { code: 'DISABILITY', label: '残障帮扶', icon: '助', tone: 'blue' }, - { code: 'DIFFICULT_FAMILY', label: '生活困难', icon: '家', tone: 'gold' }, - { code: 'OTHER', label: '其他服务', icon: '心', tone: 'purple' }, + { code: 'OLD_AGE', label: '关爱老人', symbol: '老', tone: 'orange' }, + { code: 'WOMEN_CHILDREN', label: '困境儿童', symbol: '童', tone: 'green' }, + { code: 'WOMEN_CHILDREN', label: '妇女帮扶', symbol: '女', tone: 'rose' }, + { code: 'DISABILITY', label: '残障救助', symbol: '助', tone: 'blue' }, ], }, @@ -90,4 +88,7 @@ Page({ viewNotifications() { void wx.navigateTo({ url: '/pages/notifications/notifications' }); }, + apply() { + void wx.navigateTo({ url: '/pages/application-form/application-form?mode=SELF' }); + }, }); diff --git a/apps/miniprogram/miniprogram/pages/index/index.wxml b/apps/miniprogram/miniprogram/pages/index/index.wxml index 0ff70bc..8f8db62 100644 --- a/apps/miniprogram/miniprogram/pages/index/index.wxml +++ b/apps/miniprogram/miniprogram/pages/index/index.wxml @@ -1,37 +1,41 @@ - - - 乐活公益 ♡ - 用爱连接,让爱传递 - 有需要,告诉我们;想帮忙,也欢迎加入。 - 公益服务隐私保护专人跟进 + + + 乐活公益用爱连接 · 让爱传递 - 正在安全登录,请稍候… - 暂时无法登录{{message}} + + + 用爱连接 让爱传递 + 乐于助人 · 助人为乐 · 服务社会 + + + + 正在安全登录,请稍候… + 暂时无法登录{{message}} - - - + + + + + + - + - 我们能帮什么六类暖心服务 - - + 公益项目 + + + 便捷入口 + + + + - - 一起参与公益每份行动都有温度 - - - - - - - 乐活动态内容均经审核发布 - - 紧急情况请先求助公共服务如遇危及生命安全的情况,请及时联系 110 或 120。 diff --git a/apps/miniprogram/miniprogram/pages/index/index.wxss b/apps/miniprogram/miniprogram/pages/index/index.wxss index 0deeae1..6cc42b2 100644 --- a/apps/miniprogram/miniprogram/pages/index/index.wxss +++ b/apps/miniprogram/miniprogram/pages/index/index.wxss @@ -1,293 +1,282 @@ .home-page { - padding-top: 20rpx; + padding-top: 18rpx; +} +.brand-row { + display: flex; + align-items: center; + gap: 18rpx; + padding: 4rpx 8rpx 24rpx; +} +.brand-logo { + position: relative; + width: 68rpx; + height: 68rpx; + border-radius: 22rpx; + background: linear-gradient(145deg, #ff9d26, #ff5726); + transform: rotate(-8deg); +} +.brand-logo::after { + position: absolute; + right: 11rpx; + bottom: 10rpx; + width: 24rpx; + height: 37rpx; + border-radius: 20rpx 20rpx 4rpx 20rpx; + content: ''; + background: #fff; + transform: rotate(35deg); +} +.brand-name, +.brand-slogan { + display: block; +} +.brand-name { + font-size: 38rpx; + font-weight: 800; + letter-spacing: 4rpx; +} +.brand-slogan { + margin-top: 2rpx; + color: var(--color-text-secondary); + font-size: 22rpx; + letter-spacing: 5rpx; } .home-hero { position: relative; - margin-bottom: 24rpx; - padding: 40rpx 34rpx 34rpx; + min-height: 232rpx; + padding: 40rpx 34rpx; overflow: hidden; - border-radius: 36rpx; + border-radius: 30rpx; color: #fff; - background: linear-gradient(135deg, #ff7845 0%, #f05225 100%); - box-shadow: 0 16rpx 36rpx rgba(224, 75, 25, 0.22); + background: linear-gradient(125deg, #ff7b3e 0%, #ff5d23 55%, #ff8e4e 100%); + box-shadow: var(--shadow-hero); + box-sizing: border-box; } -.hero-orb { +.hero-glow { position: absolute; - border: 3rpx solid rgba(255, 255, 255, 0.25); + border: 3rpx solid rgba(255, 255, 255, 0.22); border-radius: 50%; } -.hero-orb--one { +.hero-glow--one { width: 180rpx; height: 180rpx; - right: -54rpx; - top: 30rpx; + right: -35rpx; + top: 20rpx; } -.hero-orb--two { - width: 90rpx; - height: 90rpx; - right: 92rpx; - bottom: -32rpx; +.hero-glow--two { + width: 100rpx; + height: 100rpx; + right: 110rpx; + bottom: -38rpx; } -.hero-brand, .hero-title, .hero-copy { position: relative; z-index: 1; display: block; } -.hero-brand { - font-size: 27rpx; - font-weight: 700; -} .hero-title { - margin-top: 18rpx; - font-size: 46rpx; - font-weight: 700; + font-size: 42rpx; + font-weight: 800; letter-spacing: 2rpx; } .hero-copy { - margin-top: 12rpx; - font-size: 28rpx; + margin-top: 10rpx; + font-size: 24rpx; + opacity: 0.92; } -.hero-trust { +.hero-action { position: relative; z-index: 1; display: flex; - margin-top: 28rpx; + width: max-content; + min-height: 58rpx; + margin: 24rpx 0 0; + padding: 8rpx 22rpx; + align-items: center; gap: 12rpx; -} -.hero-trust text { - padding: 7rpx 14rpx; border-radius: 999rpx; - background: rgba(255, 255, 255, 0.18); + color: #df4c1b; + background: #fff; + font-size: 25rpx; + font-weight: 700; +} +.quick-grid { + display: grid; + margin-top: 24rpx; + padding: 26rpx 8rpx 18rpx; + grid-template-columns: repeat(4, 1fr); + gap: 28rpx 10rpx; + border: 2rpx solid var(--color-border); + border-radius: 28rpx; + background: #fff; + box-shadow: var(--shadow-card); +} +.quick-item { + display: flex; + min-width: 0; + margin: 0; + padding: 0; + flex-direction: column; + align-items: center; + gap: 12rpx; + color: var(--color-text); + background: transparent; + font-size: 23rpx; + line-height: 1.25; +} +.quick-icon { + display: flex; + width: 68rpx; + height: 68rpx; + align-items: center; + justify-content: center; + border-radius: 24rpx; + color: #fff; + font-size: 26rpx; + font-weight: 800; + box-shadow: 0 8rpx 18rpx rgba(20, 30, 40, 0.1); +} +.quick-icon--orange, +.list-mark--orange { + background: linear-gradient(145deg, #ff8b4d, #ff5e2b); +} +.quick-icon--green, +.list-mark--green { + background: linear-gradient(145deg, #62ca58, #36ad43); +} +.quick-icon--rose { + background: linear-gradient(145deg, #ff8292, #ef556f); +} +.quick-icon--blue, +.list-mark--blue { + background: linear-gradient(145deg, #55aaf5, #2887e5); +} +.quick-icon--gold { + background: linear-gradient(145deg, #ffbd57, #f2942e); +} +.notice-strip { + display: grid; + width: 100%; + min-height: 70rpx; + margin: 20rpx 0 0; + padding: 12rpx 18rpx; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 14rpx; + border-radius: 18rpx; + color: var(--color-text-secondary); + background: #fff; + text-align: left; font-size: 23rpx; } -.primary-actions { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 18rpx; +.notice-badge { + color: var(--color-primary); + font-weight: 800; } -.primary-action { - position: relative; - display: flex; - min-height: 190rpx; +.notice-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.section-heading { + margin-top: 32rpx; +} +.section-link { + min-height: 52rpx; margin: 0; - padding: 26rpx 22rpx; - flex-direction: column; - align-items: flex-start; - color: #5e2715; - border: 2rpx solid #ffd2bd; - border-radius: 30rpx; + padding: 4rpx 0 4rpx 20rpx; + color: var(--color-text-secondary); + background: transparent; + font-size: 24rpx; +} +.feature-project { + width: 100%; + margin: 0; + padding: 0; + overflow: hidden; + border: 2rpx solid var(--color-border); + border-radius: 26rpx; + background: #fff; + text-align: left; + box-shadow: var(--shadow-card); +} +.feature-project image { + width: 100%; + height: 260rpx; + display: block; +} +.feature-project__body { + padding: 22rpx 24rpx; +} +.feature-project__title, +.feature-project__copy { + display: block; +} +.feature-project__title { + color: var(--color-text); + font-size: 31rpx; + font-weight: 800; +} +.feature-project__copy { + margin-top: 10rpx; + color: var(--color-text-secondary); + font-size: 25rpx; + line-height: 1.6; +} +.feature-project__meta { + display: flex; + margin-top: 18rpx; + justify-content: space-between; + color: var(--color-primary); + font-size: 23rpx; + font-weight: 700; +} +.service-list { + padding: 0 24rpx; + border: 2rpx solid var(--color-border); + border-radius: 26rpx; + background: #fff; + box-shadow: var(--shadow-card); +} +.service-list button { + display: grid; + width: 100%; + min-height: 112rpx; + margin: 0; + padding: 18rpx 0; + grid-template-columns: 58rpx 1fr auto; + align-items: center; + gap: 18rpx; + border-bottom: 2rpx solid var(--color-divider); + color: var(--color-text); + background: transparent; text-align: left; } -.primary-action--warm { - background: #fff2ea; +.service-list button:last-child { + border-bottom: 0; } -.primary-action--green { - color: #185f37; - border-color: #cdebd9; - background: #edf9f1; -} -.primary-action__icon { +.list-mark { display: flex; - width: 58rpx; - height: 58rpx; + width: 56rpx; + height: 56rpx; align-items: center; justify-content: center; border-radius: 18rpx; color: #fff; - background: #f05a28; - font-size: 35rpx; -} -.primary-action--green .primary-action__icon { - background: #35a864; -} -.primary-action__title, -.primary-action__copy { - display: block; -} -.primary-action__title { - margin-top: 18rpx; - font-size: 33rpx; - font-weight: 700; -} -.primary-action__copy { - margin-top: 6rpx; - color: #755447; font-size: 24rpx; - line-height: 1.5; + font-weight: 800; } -.primary-action--green .primary-action__copy { - color: #52705f; -} -.primary-action__arrow { - position: absolute; - right: 18rpx; - top: 20rpx; - font-size: 36rpx; -} -.progress-banner { - display: flex; - width: 100%; - min-height: 104rpx; - margin: 20rpx 0 0; - padding: 20rpx 26rpx; - align-items: center; - justify-content: space-between; - color: #235f91; - border-radius: 24rpx; - background: #edf6fd; - text-align: left; -} -.progress-banner__label, -.progress-banner__copy { +.list-title, +.list-copy { display: block; } -.progress-banner__label { +.list-title { + font-size: 28rpx; font-weight: 700; } -.progress-banner__copy { - margin-top: 4rpx; - color: #607b91; - font-size: 24rpx; -} -.progress-banner__arrow { - font-size: 26rpx; - font-weight: 700; -} -.service-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 16rpx; -} -.service-item { - display: flex; - min-height: 142rpx; - margin: 0; - padding: 20rpx 8rpx; - flex-direction: column; - align-items: center; - justify-content: center; - border: 2rpx solid #eee7e1; - border-radius: 26rpx; - background: #fff; -} -.service-item__icon { - display: flex; - width: 58rpx; - height: 58rpx; - align-items: center; - justify-content: center; - border-radius: 20rpx; - color: #fff; - background: #f47745; - font-size: 30rpx; -} -.service-item--green .service-item__icon { - background: #46a956; -} -.service-item--blue .service-item__icon { - background: #378fd6; -} -.service-item--purple .service-item__icon { - background: #8564cf; -} -.service-item--gold .service-item__icon { - background: #e69a31; -} -.service-item--rose .service-item__icon { - background: #e96878; -} -.service-item__label { - margin-top: 12rpx; - font-size: 26rpx; - font-weight: 600; -} -.participation-card { - padding: 0 26rpx; - border: 2rpx solid var(--color-border); - border-radius: 30rpx; - background: #fff; - box-shadow: var(--shadow-card); -} -.participation-item { - display: grid; - width: 100%; - min-height: 122rpx; - margin: 0; - padding: 20rpx 0; - grid-template-columns: 64rpx 1fr auto; - align-items: center; - gap: 18rpx; - color: var(--color-text); - border-bottom: 2rpx solid #f0ece8; - background: transparent; - text-align: left; -} -.participation-item:last-child { - border-bottom: 0; -} -.participation-item__icon { - display: flex; - width: 62rpx; - height: 62rpx; - align-items: center; - justify-content: center; - border-radius: 20rpx; - color: #fff; - font-size: 32rpx; -} -.orange { - background: #f47745; -} -.blue { - background: #378fd6; -} -.green { - background: #38a862; -} -.participation-item__title, -.participation-item__copy { - display: block; -} -.participation-item__title { - font-weight: 700; -} -.participation-item__copy { +.list-copy { margin-top: 4rpx; color: var(--color-text-secondary); - font-size: 25rpx; -} -.content-links { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16rpx; -} -.content-links button { - display: flex; - min-height: 96rpx; - margin: 0; - padding: 20rpx 24rpx; - align-items: center; - justify-content: space-between; - color: #544d47; - border: 2rpx solid var(--color-border); - border-radius: 24rpx; - background: #fff; - font-weight: 600; -} -.safety-note { - display: flex; - margin-top: 30rpx; - padding: 24rpx; - flex-direction: column; - color: #735818; - border-radius: 22rpx; - background: #fff7df; - font-size: 26rpx; - line-height: 1.65; -} -.safety-note__title { - margin-bottom: 5rpx; - font-weight: 700; + font-size: 23rpx; } diff --git a/apps/miniprogram/miniprogram/pages/profile/profile.wxml b/apps/miniprogram/miniprogram/pages/profile/profile.wxml index 5610a9e..84d6afa 100644 --- a/apps/miniprogram/miniprogram/pages/profile/profile.wxml +++ b/apps/miniprogram/miniprogram/pages/profile/profile.wxml @@ -2,7 +2,7 @@ 暂时无法打开个人中心{{error}} - 乐{{user.displayName || '乐活用户'}}账号已安全登录{{isVolunteer ? '认证志愿者' : '公益伙伴'}} + 乐{{user.displayName || '乐活用户'}}账号已安全登录{{isVolunteer ? '认证志愿者' : '公益伙伴'}}隐私保护最少采集服务可查进度留痕消息可达及时通知 我的服务 diff --git a/apps/miniprogram/miniprogram/pages/profile/profile.wxss b/apps/miniprogram/miniprogram/pages/profile/profile.wxss index 87097d8..e4df36c 100644 --- a/apps/miniprogram/miniprogram/pages/profile/profile.wxss +++ b/apps/miniprogram/miniprogram/pages/profile/profile.wxss @@ -4,8 +4,8 @@ .profile-hero { position: relative; display: flex; - min-height: 170rpx; - padding: 32rpx; + min-height: 280rpx; + padding: 32rpx 32rpx 120rpx; align-items: center; gap: 22rpx; border-radius: 34rpx; @@ -13,6 +13,35 @@ background: linear-gradient(135deg, #39aa61, #24934d); box-shadow: 0 14rpx 32rpx rgba(35, 139, 70, 0.18); } +.profile-trust { + position: absolute; + right: 24rpx; + bottom: 22rpx; + left: 24rpx; + display: grid; + padding-top: 20rpx; + grid-template-columns: repeat(3, 1fr); + border-top: 2rpx solid rgba(255, 255, 255, 0.24); + text-align: center; +} +.profile-trust view { + border-right: 2rpx solid rgba(255, 255, 255, 0.22); +} +.profile-trust view:last-child { + border-right: 0; +} +.profile-trust strong, +.profile-trust text { + display: block; +} +.profile-trust strong { + font-size: 25rpx; +} +.profile-trust text { + margin-top: 3rpx; + font-size: 20rpx; + opacity: 0.8; +} .avatar { display: flex; width: 92rpx; diff --git a/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxml b/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxml index d6a2294..cd8d891 100644 --- a/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxml +++ b/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxml @@ -1 +1 @@ -项目暂时无法查看{{message}}♡{{project.statusLabel}}{{project.name}}{{project.summary}}项目周期{{project.startDate}} 至 {{project.endDate}}项目介绍{{project.content}}参与说明查看项目关联活动,选择适合的时间报名参与。平台暂不提供公开募捐交易。 +项目暂时无法查看{{message}}{{project.name}}{{project.statusLabel}}{{project.summary}}服务对象{{project.targetPeople || '以项目说明为准'}}活动数量{{project.activityCount}}服务工单{{project.serviceCaseCount}}项目周期{{project.startDate}} 至 {{project.endDate}}项目介绍{{project.content}}参与说明查看项目关联活动,选择适合的时间报名参与;提交后可在志愿者中心查询审核与签到状态。 diff --git a/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxss b/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxss index d75f166..7684058 100644 --- a/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxss +++ b/apps/miniprogram/miniprogram/pages/project-detail/project-detail.wxss @@ -83,3 +83,43 @@ line-height: 1.8; white-space: pre-wrap; } +.project-visual { + display: block; + width: 100%; + height: 360rpx; + border-radius: 28rpx 28rpx 0 0; +} +.project-title-row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 20rpx; +} +.project-facts { + display: grid; + margin: 26rpx 0; + padding: 22rpx 0; + grid-template-columns: repeat(3, 1fr); + border-top: 2rpx solid var(--color-divider); + border-bottom: 2rpx solid var(--color-divider); + text-align: center; +} +.project-facts view { + border-right: 2rpx solid var(--color-divider); +} +.project-facts view:last-child { + border-right: 0; +} +.project-facts text, +.project-facts strong { + display: block; +} +.project-facts text { + color: var(--color-text-secondary); + font-size: 22rpx; +} +.project-facts strong { + margin-top: 6rpx; + color: var(--color-primary); + font-size: 28rpx; +} diff --git a/docs/07_UI_UX.md b/docs/07_UI_UX.md index 926d9b6..6fedeea 100644 --- a/docs/07_UI_UX.md +++ b/docs/07_UI_UX.md @@ -157,3 +157,13 @@ P2:5. 公益项目 6. 公益活动 7. 我要做公益 - 全局使用 16/24/32rpx 级圆角、低强度暖灰阴影、至少约 96rpx 的主按钮/主要点击高度和系统字体;不使用闪烁、强动画、玻璃拟态或科技大屏视觉。 - 项目、活动和志愿者页面只展示 API 返回的真实事实;封面缺失时使用轻量公益图形占位,不生成虚构人物、捐赠额、服务人数或活动成果。 - 参考图中的公开捐赠交易、证书、培训和团队入口不属于当前 V1 已实现能力,不在公众端显示;项目详情明确不提供公开募捐交易。 + +--- + +## 12. 参考界面全端还原范围(2026-08-13) + +- 小程序端采用参考图的品牌头、暖橙主视觉、四列服务入口、公告、项目大卡、绿色个人中心、图文服务选择、项目事实卡和统一底部导航。 +- 管理端采用深色固定侧栏、浅灰工作区、真实 KPI、月度趋势、服务类型分布、快捷入口、标准筛选表格和工单横向步骤条。 +- 生成的人物图片均为虚构品牌场景素材,仅作服务类别与项目视觉,不作为真实服务对象、服务现场或项目成果证据;素材已压缩进入小程序本地包。 +- 捐赠支付、自动捐赠、捐赠记录/金额、物资订单、志愿者培训/证书/团队不展示入口;代码只保留禁用的集中能力登记和组件/导航扩展边界。 +- 图片中的金额、满意度、捐赠人数等示例值不得复制;所有运行时数字必须来自已批准接口,缺少事实时使用明确空状态。 diff --git a/docs/10_TASK_STATE.md b/docs/10_TASK_STATE.md index 2bf890f..0115612 100644 --- a/docs/10_TASK_STATE.md +++ b/docs/10_TASK_STATE.md @@ -4,6 +4,20 @@ ## 当前阶段 +2026-08-13 + +任务:参考图小程序端与管理端视觉全量还原(延期能力仅预留)。 + +完成:建立 primitive→semantic→component 三层设计令牌;按参考图重建小程序品牌首页、八宫格服务入口、公告、项目图文卡、正式底部导航、图文服务申请、项目详情事实区和绿色个人中心;保留既有真实申请、项目、活动、志愿报名、协作任务、消息和内容业务流程。管理端新增深色图标侧栏、工作概览、真实 KPI、月度申请/完成趋势、服务类型分布、快捷入口和工单横向状态步骤条,并沿用既有脱敏表格、筛选、详情、权限和审计逻辑。新增四张虚构公益品牌场景素材并压缩用于本地包,不作为真实成果证据。 + +范围:按用户确认,爱心捐赠及支付、每月自动捐赠、捐赠记录/金额统计、物资订单、志愿者培训/证书/团队不进入当前版本,不显示入口、不建立 API/表;新增集中禁用能力清单与稳定导航/组件边界供后期开发。新增 D-017,未改变技术栈、数据库、认证、状态机或 V1 业务范围。 + +验证:格式检查、Lint、27 个单元测试、34 个真实 MySQL 集成测试和全仓生产构建通过;8 个 migration 在隔离 `lehuo_test` 库无待执行项。首次全仓类型检查发现管理端步骤条使用了申请状态名称而非工单状态名称,已改为 `ASSIGNED/IN_SERVICE/SERVICE_COMPLETED` 并完成最终重跑。 + +遗留问题:真实微信 AppID/AppSecret、合法 HTTPS 域名和微信环境联调继续按用户安排后期提供;延期能力仍需未来独立评审。视觉真机验收需微信开发者工具环境。 + +--- + `PHASE_7_IMPLEMENTATION_COMPLETE - 外部发布验收待执行` ## 当前版本目标 diff --git a/docs/11_DECISIONS.md b/docs/11_DECISIONS.md index 8abb2ac..1f56600 100644 --- a/docs/11_DECISIONS.md +++ b/docs/11_DECISIONS.md @@ -195,6 +195,20 @@ V1 统计直接从业务事实表计算,不建立可人工覆盖的统计表 --- +## D-017 参考界面还原与延期能力扩展边界 + +状态:ACCEPTED + +决定: +小程序端和管理端以 2026-08-10 已确认参考图作为当前视觉基准,在不改变 V1 业务状态机、权限、数据口径和隐私边界的前提下完整还原其信息层级、色彩、卡片、导航、表格、图表和详情结构。界面统计只使用现有事实接口,不展示虚构人数、金额、满意度或成果。 + +爱心捐赠及微信/支付宝/银行卡支付、每月自动捐赠、捐赠记录与金额统计、物资订单、志愿者培训、证书和团队不进入当前版本,不注册页面或可操作入口,不新增数据库/API;通过集中能力清单、稳定模块边界和可扩展导航结构预留后续接入点,后续启用仍须独立产品、权限、审计、支付合规和迁移评审。 + +原因: +满足已批准视觉目标,同时避免用不可用入口或模拟数据冒充已交付功能,并防止支付、订单和志愿者扩展模块未经合规及架构评审进入 V1。 + +--- + ## 待确认建议 Codex 若有会改变已批准架构的建议,只能写在这里,不得直接实施: