release: align H5 demo UI and login
This commit is contained in:
@@ -6,6 +6,9 @@ export const authService = {
|
||||
wechatLogin(payload: { code: string }) {
|
||||
return post('/auth/wechat/login', payload, { idempotencyKey: payload.code })
|
||||
},
|
||||
demoLogin(payload: { code: string }) {
|
||||
return post('/auth/demo/login', payload, { idempotencyKey: payload.code })
|
||||
},
|
||||
bindPhone(payload: Record<string, any>) {
|
||||
return post('/auth/phone/bind', payload, { idempotencyKey: payload.phoneCode || payload.encryptedData })
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="page-layout">
|
||||
<van-nav-bar
|
||||
class="page-layout__nav"
|
||||
:title="title"
|
||||
left-arrow
|
||||
fixed
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<van-tabbar route fixed placeholder class="tab-layout__bar">
|
||||
<van-tabbar-item to="/home" icon="wap-home-o">首页</van-tabbar-item>
|
||||
<van-tabbar-item to="/discover" icon="friends-o">找对象</van-tabbar-item>
|
||||
<van-tabbar-item to="/messages" icon="chat-o">消息</van-tabbar-item>
|
||||
<van-tabbar-item to="/activity" icon="flag-o">活动</van-tabbar-item>
|
||||
<van-tabbar-item to="/mine" icon="user-o">我的</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
@@ -17,8 +18,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// 固定 4 项 TabBar,顺序与 miniapp/app.json 一致。
|
||||
const cached = ['HomePage', 'DiscoverPage', 'ActivityPage', 'MinePage']
|
||||
// 固定 5 项 TabBar,顺序与 miniapp/app.json 一致。
|
||||
const cached = ['HomePage', 'DiscoverPage', 'MessagesPage', 'ActivityPage', 'MinePage']
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -31,5 +32,7 @@ const cached = ['HomePage', 'DiscoverPage', 'ActivityPage', 'MinePage']
|
||||
}
|
||||
.tab-layout__bar {
|
||||
border-top: 1px solid var(--mini-border);
|
||||
background: var(--mini-surface);
|
||||
box-shadow: 0 -8px 24px rgba(28, 30, 88, 0.08);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="home__brand-slogan">公益婚恋服务平台</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home__notice" @click="router.push('/notifications')">
|
||||
<div class="home__notice" @click="router.push('/messages')">
|
||||
<van-icon name="bell" size="18" />
|
||||
<span>通知</span>
|
||||
</div>
|
||||
@@ -44,7 +44,7 @@
|
||||
<van-swipe v-if="banners.length" :autoplay="4500" indicator-color="#FF4F91" class="home__swipe">
|
||||
<van-swipe-item v-for="b in banners" :key="b.id">
|
||||
<div class="home__banner-card" @click="onBannerTap(b)">
|
||||
<div class="home__banner-cover">{{ (b.title || '善').slice(0, 1) }}</div>
|
||||
<img class="home__banner-image" :src="b.imageFileId || '/assets/brand/home-hero-v2.jpg'" alt="" />
|
||||
<div class="home__banner-copy">
|
||||
<div class="home__banner-kicker">公益 · 本地 · 真实 · 安全</div>
|
||||
<div class="home__banner-title">{{ b.title }}</div>
|
||||
@@ -54,7 +54,7 @@
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
<div v-else class="home__banner-card">
|
||||
<div class="home__banner-cover">缘</div>
|
||||
<img class="home__banner-image" src="/assets/brand/home-hero-v2.jpg" alt="" />
|
||||
<div class="home__banner-copy">
|
||||
<div class="home__banner-kicker">公益 · 本地 · 真实 · 安全</div>
|
||||
<div class="home__banner-title">在丹阳,遇见更好的你</div>
|
||||
@@ -73,7 +73,7 @@
|
||||
:class="{ 'home__entry--disabled': !e.enabled }"
|
||||
@click="onEntryTap(e)"
|
||||
>
|
||||
<div class="home__entry-icon" :class="`tone-${toneOf(e.code)}`">{{ (e.label || '善').slice(0, 1) }}</div>
|
||||
<div class="home__entry-icon" :class="`tone-${toneOf(e.code)}`"><img :src="iconOf(e.code)" :alt="e.label" /></div>
|
||||
<div class="home__entry-label">{{ e.label }}</div>
|
||||
<div class="home__entry-sub">{{ subOf(e.code) }}</div>
|
||||
</div>
|
||||
@@ -121,7 +121,7 @@
|
||||
class="home__mini"
|
||||
@click="onServiceTap(s.type)"
|
||||
>
|
||||
<div class="home__mini-cover" :class="`tone-${toneOf(s.type)}`">{{ (s.title || '善').slice(0, 1) }}</div>
|
||||
<img class="home__mini-cover" :src="coverOf(s.type)" alt="" />
|
||||
<div class="home__mini-title">{{ s.title }}</div>
|
||||
<div class="home__mini-sub">{{ s.ctaText }}</div>
|
||||
</div>
|
||||
@@ -137,7 +137,7 @@
|
||||
class="home__act"
|
||||
@click="router.push({ path: '/activity/detail', query: { id: a.id } })"
|
||||
>
|
||||
<div class="home__act-cover">{{ (a.title || '活').slice(0, 1) }}</div>
|
||||
<img class="home__act-cover" :src="a.coverFileId || '/assets/covers/activity-default.jpg'" alt="" />
|
||||
<div class="home__act-info">
|
||||
<div class="home__act-tag">公益活动</div>
|
||||
<div class="home__act-title">{{ a.title }}</div>
|
||||
@@ -150,7 +150,7 @@
|
||||
<!-- 善缘服务站 -->
|
||||
<UiSectionHeader title="善缘服务站" />
|
||||
<div v-if="serviceLocation" class="home__station" @click="router.push('/service-station')">
|
||||
<div class="home__station-icon">站</div>
|
||||
<img class="home__station-icon" src="/assets/covers/station-default.jpg" alt="" />
|
||||
<div class="home__station-info">
|
||||
<div class="home__station-name">{{ serviceLocation.name }}</div>
|
||||
<div class="home__station-desc">
|
||||
@@ -175,7 +175,7 @@
|
||||
class="home__article"
|
||||
@click="router.push({ path: '/content/detail', query: { id: art.id } })"
|
||||
>
|
||||
<div class="home__article-cover">{{ (art.title || '课').slice(0, 1) }}</div>
|
||||
<img class="home__article-cover" :src="art.coverFileId || '/assets/covers/classroom-default.jpg'" alt="" />
|
||||
<div class="home__article-main">
|
||||
<div class="home__article-title">{{ art.title }}</div>
|
||||
<div class="home__article-meta">善缘课堂 · 公益内容</div>
|
||||
@@ -188,7 +188,7 @@
|
||||
<!-- 善缘安全提醒 -->
|
||||
<UiSectionHeader title="善缘安全提醒" />
|
||||
<div class="home__safety" @click="router.push('/anti-fraud')">
|
||||
<div class="home__safety-icon">盾</div>
|
||||
<img class="home__safety-icon" src="/assets/covers/anti-fraud-default.jpg" alt="" />
|
||||
<div class="home__safety-text">{{ safetyNotice.text }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -247,6 +247,16 @@ const ENTRY_SUBS: Record<string, string> = {
|
||||
anti_fraud: '守护真爱',
|
||||
service_station: '就在身边',
|
||||
}
|
||||
const ENTRY_ICONS: Record<string, string> = {
|
||||
find_object: '/assets/icons/home/find-object.png',
|
||||
matchmaker: '/assets/icons/home/matchmaker.png',
|
||||
activities: '/assets/icons/home/activity.png',
|
||||
counseling: '/assets/icons/home/counseling.png',
|
||||
classroom: '/assets/icons/home/classroom.png',
|
||||
premarital: '/assets/icons/home/premarital.png',
|
||||
anti_fraud: '/assets/icons/home/anti-fraud.png',
|
||||
service_station: '/assets/icons/home/service-station.png',
|
||||
}
|
||||
/** 固定 8 入口默认值(服务端未返回时兜底;顺序不可变更) */
|
||||
const DEFAULT_ENTRIES = [
|
||||
{ code: 'find_object', label: '找对象', enabled: true },
|
||||
@@ -327,6 +337,15 @@ function toneOf(code: string): string {
|
||||
function subOf(code: string): string {
|
||||
return ENTRY_SUBS[code] || ''
|
||||
}
|
||||
function iconOf(code: string): string {
|
||||
return ENTRY_ICONS[code] || ENTRY_ICONS.find_object
|
||||
}
|
||||
function coverOf(type: string): string {
|
||||
if (type === 'counseling') return '/assets/covers/counseling-default.jpg'
|
||||
if (type === 'premarital') return '/assets/covers/classroom-default.jpg'
|
||||
if (type === 'service_station') return '/assets/covers/station-default.jpg'
|
||||
return '/assets/covers/counseling-default.jpg'
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -454,7 +473,7 @@ onMounted(load)
|
||||
|
||||
/* 品牌区 */
|
||||
.home__hero {
|
||||
background: var(--mini-brand-gradient);
|
||||
background: var(--mini-gradient-night);
|
||||
padding: 16px 16px 0;
|
||||
border-bottom-left-radius: 20px;
|
||||
border-bottom-right-radius: 20px;
|
||||
@@ -550,19 +569,17 @@ onMounted(load)
|
||||
height: 150px;
|
||||
border-radius: var(--mini-radius);
|
||||
overflow: hidden;
|
||||
background: linear-gradient(135deg, #2a3a86 0%, #4b2a6b 100%);
|
||||
background: var(--mini-gradient-night);
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.home__banner-cover {
|
||||
.home__banner-image {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 72px;
|
||||
font-weight: 700;
|
||||
color: rgba(255, 255, 255, 0.14);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
opacity: .9;
|
||||
}
|
||||
.home__banner-copy {
|
||||
position: relative;
|
||||
@@ -617,6 +634,11 @@ onMounted(load)
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.home__entry-icon img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.home__entry-label {
|
||||
font-size: 12px;
|
||||
color: var(--mini-text-strong);
|
||||
@@ -655,6 +677,7 @@ onMounted(load)
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
margin-bottom: 6px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.home__mini-title {
|
||||
font-size: 13px;
|
||||
@@ -714,7 +737,8 @@ onMounted(load)
|
||||
}
|
||||
.home__act-cover {
|
||||
height: 84px;
|
||||
background: linear-gradient(135deg, #6a5acd 0%, #8367c7 100%);
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -754,7 +778,7 @@ onMounted(load)
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(135deg, #2fb36d 0%, #1f8a52 100%);
|
||||
object-fit: cover;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -796,7 +820,7 @@ onMounted(load)
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(135deg, #f5a623 0%, #e08b00 100%);
|
||||
object-fit: cover;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -830,7 +854,7 @@ onMounted(load)
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 8px;
|
||||
background: var(--mini-accent-pink);
|
||||
object-fit: cover;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<PageLayout title="通知">
|
||||
<PageLayout :title="pageTitle">
|
||||
<div class="notif">
|
||||
<div class="notif__bar">
|
||||
<span class="notif__count">{{ unreadCount > 0 ? `${unreadCount} 条未读` : '暂无未读' }}</span>
|
||||
@@ -44,7 +44,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { notificationService } from '@/api/services'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { formatDateTime } from '@/utils/datetime'
|
||||
@@ -55,6 +56,8 @@ import UiErrorState from '@/components/UiErrorState.vue'
|
||||
import UiTag from '@/components/UiTag.vue'
|
||||
|
||||
const appStore = useAppStore()
|
||||
const route = useRoute()
|
||||
const pageTitle = computed(() => route.path === '/messages' ? '消息' : '通知')
|
||||
|
||||
const TYPE_TEXT: Record<string, string> = {
|
||||
system: '系统通知',
|
||||
|
||||
@@ -30,6 +30,7 @@ export const routes: RouteRecordRaw[] = [
|
||||
{ path: '', redirect: '/home' },
|
||||
{ path: 'home', name: 'HomePage', component: () => import('@/pages/home/HomePage.vue') },
|
||||
{ path: 'discover', name: 'DiscoverPage', component: () => import('@/pages/discover/DiscoverPage.vue') },
|
||||
{ path: 'messages', name: 'MessagesPage', component: () => import('@/pages/settings/NotificationsPage.vue') },
|
||||
{ path: 'activity', name: 'ActivityPage', component: () => import('@/pages/activity/ActivityPage.vue') },
|
||||
{ path: 'mine', name: 'MinePage', component: () => import('@/pages/mine/MinePage.vue') },
|
||||
],
|
||||
|
||||
@@ -28,7 +28,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
* 无需微信环境即可切换到预置演示用户(见实施计划 D2 / 登录策略)。
|
||||
*/
|
||||
async function loginByDemoCode(code: string) {
|
||||
const data = await authService.wechatLogin({ code })
|
||||
const data = await authService.demoLogin({ code })
|
||||
applyTokens(data)
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -20,6 +20,36 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
button,
|
||||
.van-button,
|
||||
.van-tabbar-item,
|
||||
.van-cell,
|
||||
.van-nav-bar {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.van-nav-bar {
|
||||
background: var(--mini-night-start);
|
||||
color: var(--mini-text-on-night);
|
||||
}
|
||||
|
||||
.van-nav-bar .van-nav-bar__title,
|
||||
.van-nav-bar .van-icon,
|
||||
.van-nav-bar .van-nav-bar__text {
|
||||
color: var(--mini-text-on-night);
|
||||
}
|
||||
|
||||
.van-button--primary {
|
||||
background: var(--mini-gradient-brand-solid);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.van-button--plain.van-button--primary {
|
||||
color: var(--mini-tabbar-active);
|
||||
background: transparent;
|
||||
border-color: var(--mini-tabbar-active);
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
--mini-night-start: #172a72;
|
||||
--mini-night-end: #25104f;
|
||||
--mini-brand-gradient: linear-gradient(135deg, #172a72 0%, #25104f 100%);
|
||||
--mini-gradient-night: linear-gradient(160deg, #172a72 0%, #25104f 100%);
|
||||
--mini-gradient-brand-solid: linear-gradient(135deg, #c24c50 0%, #b8434a 100%);
|
||||
|
||||
/* 强调粉 / 主色 */
|
||||
--mini-accent-pink: #ff4f91;
|
||||
@@ -37,4 +39,10 @@
|
||||
--mini-radius-lg: 16px;
|
||||
--mini-shadow: 0 4px 16px rgba(23, 42, 114, 0.08);
|
||||
--mini-shadow-strong: 0 8px 28px rgba(23, 42, 114, 0.14);
|
||||
--mini-glass: rgba(255, 255, 255, 0.1);
|
||||
--mini-glass-strong: rgba(255, 255, 255, 0.16);
|
||||
--mini-hairline: rgba(255, 255, 255, 0.16);
|
||||
--mini-text-on-night: #fff;
|
||||
--mini-text-on-night-muted: rgba(255, 255, 255, 0.72);
|
||||
--mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.4) 56%, rgba(255, 79, 145, 0.12) 100%);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user