Files
hhrs/pages/rights/rights.vue
T
jacobxu666andClaude Sonnet 5 073dfa5c00 feat(hhrs): 新增权益包、门店详情、权益详情、我的四个H5页面
- 权益包页面支持3种状态切换:认证表单、未中奖空状态、权益信息(统计卡片+Tab+列表)
- 门店详情页展示场馆信息、营业时间、商户优惠说明
- 权益详情页含日期选择卡片和底部预约按钮
- 我的页面含用户信息、菜单列表和底部TabBar
- 新增权益相关API接口定义(getRightsInfo/getRightsDetail/doRightsAuth/doRightsBook)
- 商户折扣列表跳转统一至门店详情页

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 13:57:51 +08:00

603 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="page">
<!-- 自定义导航栏 -->
<view class="nav-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-header">
<view class="nav-back" @click="goBack">
<text class="back-icon">&#xe600;</text>
</view>
<text class="nav-title">{{ navTitle }}</text>
</view>
</view>
<!-- 状态1: 权益资格认证 -->
<view v-if="status === 'auth'" class="auth-container">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">权益资格认证</text>
</view>
<view class="form-area">
<view class="form-item">
<text class="form-label required">真实姓名</text>
<input class="form-input" v-model="form.realName" placeholder="请输入真实姓名" />
</view>
<view class="form-item">
<text class="form-label required">手机号码</text>
<text class="form-value phone-value">{{ form.phone }}</text>
</view>
<view class="form-item" @click="showIdTypePicker = true">
<text class="form-label required">证件类型</text>
<text class="form-value">{{ form.idType }}</text>
<text class="form-arrow">&#xe602;</text>
</view>
<view class="form-item">
<text class="form-label required">证件号码</text>
<input class="form-input" v-model="form.idNumber" placeholder="请输入真实证件号码" />
</view>
</view>
<view class="auth-btn" @click="onAuth">开始认证</view>
<view class="tips-section">
<view class="section-title">
<view class="title-bar"></view>
<text class="title-text">温馨提示</text>
</view>
<view class="tips-list">
<text class="tip-item">1. 请输入真实的身份信息用来进行活动权益资格认证</text>
<text class="tip-item">2. 认证通过后系统会显示出您的所获得的权益信息</text>
<text class="tip-item">3. 手机号码为您登录的手机,无法修改。若号码对,请更换登录手机。</text>
</view>
</view>
</view>
<!-- 状态2: 未中奖 -->
<view v-if="status === 'noWin'" class="empty-container">
<image class="empty-img" src="https://aliyunoss.hn12301.net/hhrs/hhrs_empty.png" mode="widthFix" />
<text class="empty-text">您暂未中奖</text>
</view>
<!-- 状态3: 权益信息 -->
<view v-if="status === 'info'">
<!-- 蓝色头部横幅 -->
<view class="banner-area">
<text class="banner-title">恭喜您!获得怀化市社保卡权益包</text>
<view class="banner-expire">
<text class="expire-icon">!</text>
<text class="expire-text">2026年12月31日</text>
<text class="expire-label">到期</text>
</view>
</view>
<!-- 权益统计卡片 -->
<view class="stats-card">
<view class="stats-item">
<text class="stats-label">总权益价值</text>
<view class="stats-value-row">
<text class="stats-currency">¥</text>
<text class="stats-number">1500</text>
<text class="stats-unit">元</text>
</view>
</view>
<view class="stats-divider"></view>
<view class="stats-item">
<text class="stats-label">剩余可用权益数</text>
<view class="stats-value-row">
<text class="stats-number-large">10</text>
<text class="stats-unit">个</text>
</view>
</view>
</view>
<!-- Tab 切换 -->
<view class="tab-bar">
<view
v-for="(tab, index) in tabs"
:key="index"
class="tab-item"
:class="{ active: currentTab === index }"
@click="switchTab(index)"
>
<text class="tab-text">{{ tab }}</text>
</view>
</view>
<!-- 搜索栏 -->
<view class="search-area">
<view class="search-bar">
<text class="search-icon">&#xe610;</text>
<input class="search-input" v-model="keyword" placeholder="搜索权益商家" />
</view>
</view>
<!-- 权益列表 -->
<view class="list-area">
<view class="rights-card" v-for="item in rightsList" :key="item.id" @click="goDetail(item)">
<image class="card-img" :src="item.image" mode="aspectFill" />
<view class="card-info">
<text class="card-name">{{ item.name }}</text>
<text class="card-category">{{ item.category }}</text>
<text class="card-address">{{ item.address }}</text>
</view>
<view class="card-distance">
<text class="distance-icon">&#xe609;</text>
<text class="distance-text">{{ item.distance }}km</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 44,
// auth | noWin | info
status: 'info',
navTitle: '权益信息',
form: {
realName: '',
phone: '18684839400',
idType: '居民身份证',
idNumber: ''
},
showIdTypePicker: false,
tabs: ['待使用', '已预约', '已使用'],
currentTab: 0,
keyword: '',
rightsList: [
{
id: 1,
name: '怀化黄岩白马风景区',
category: '景区',
address: '怀化市鹤城区万达广场 C 区501',
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_venue1.png',
distance: '1.4'
},
{
id: 2,
name: '穿岩山国家森林公园景区',
category: '景区',
address: '怀化市鹤城区万达广场 C 区501',
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_venue2.png',
distance: '1.4'
}
]
}
},
onLoad(options) {
const sysInfo = uni.getSystemInfoSync()
this.statusBarHeight = sysInfo.statusBarHeight || 44
if (options.status) {
this.status = options.status
this.updateNavTitle()
}
},
methods: {
updateNavTitle() {
const titles = { auth: '权益资格认证', noWin: '中奖名单', info: '权益信息' }
this.navTitle = titles[this.status] || '权益信息'
},
goBack() {
uni.navigateBack()
},
onAuth() {
// TODO: 调用认证接口
},
switchTab(index) {
this.currentTab = index
},
goDetail(item) {
uni.navigateTo({ url: '/pages/rights/detail?id=' + item.id })
}
}
}
</script>
<style>
.page {
min-height: 100vh;
background-color: #f2f2f7;
}
/* 导航栏 */
.nav-bar {
background-color: #ffffff;
position: sticky;
top: 0;
z-index: 100;
}
.nav-header {
height: 44px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.nav-back {
position: absolute;
left: 14px;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
font-size: 20px;
color: #1a1818;
}
.nav-title {
font-size: 16px;
font-weight: 500;
color: #1a1818;
}
/* 认证表单 */
.auth-container {
padding: 16px;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 16px;
}
.title-bar {
width: 4px;
height: 16px;
background-color: #0088ff;
border-radius: 2px;
margin-right: 8px;
}
.title-text {
font-size: 16px;
font-weight: 600;
color: #1a1818;
}
.form-area {
background-color: #ffffff;
border-radius: 8px;
padding: 0 16px;
}
.form-item {
display: flex;
align-items: center;
height: 50px;
border-bottom: 1px solid #f0f0f0;
position: relative;
}
.form-item:last-child {
border-bottom: none;
}
.form-label {
font-size: 14px;
color: #333333;
width: 80px;
flex-shrink: 0;
}
.form-label.required::before {
content: '*';
color: #ff4d4f;
margin-right: 4px;
}
.form-input {
flex: 1;
font-size: 14px;
color: #333333;
}
.form-value {
flex: 1;
font-size: 14px;
color: #333333;
}
.phone-value {
color: #999999;
}
.form-arrow {
font-size: 14px;
color: #cccccc;
}
.auth-btn {
margin: 24px 0;
background-color: #0088ff;
color: #ffffff;
text-align: center;
font-size: 16px;
font-weight: 500;
height: 48px;
line-height: 48px;
border-radius: 24px;
}
.tips-section {
margin-top: 8px;
}
.tips-list {
display: flex;
flex-direction: column;
gap: 12px;
padding: 0 4px;
}
.tip-item {
font-size: 13px;
color: #ff4d4f;
line-height: 1.6;
}
/* 未中奖空状态 */
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 160px;
}
.empty-img {
width: 200px;
}
.empty-text {
font-size: 18px;
color: #999999;
margin-top: 24px;
}
/* 权益信息 - 蓝色横幅 */
.banner-area {
background-color: #0088ff;
padding: 20px 16px 24px;
}
.banner-title {
font-size: 16px;
color: #ffffff;
font-weight: 500;
display: block;
text-align: center;
margin-bottom: 12px;
}
.banner-expire {
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.expire-icon {
width: 18px;
height: 18px;
background-color: #ffffff;
color: #0088ff;
border-radius: 50%;
text-align: center;
line-height: 18px;
font-size: 12px;
font-weight: 700;
}
.expire-text {
font-size: 16px;
color: #ffffff;
font-weight: 600;
}
.expire-label {
font-size: 14px;
color: rgba(255,255,255,0.8);
}
/* 统计卡片 */
.stats-card {
display: flex;
align-items: center;
background-color: #ffffff;
margin: -12px 12px 0;
border-radius: 8px;
padding: 16px 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
position: relative;
z-index: 1;
}
.stats-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.stats-label {
font-size: 12px;
color: #999999;
margin-bottom: 8px;
}
.stats-value-row {
display: flex;
align-items: baseline;
}
.stats-currency {
font-size: 14px;
color: #1a1818;
font-weight: 600;
}
.stats-number {
font-size: 28px;
color: #1a1818;
font-weight: 700;
}
.stats-number-large {
font-size: 28px;
color: #1a1818;
font-weight: 700;
}
.stats-unit {
font-size: 12px;
color: #999999;
margin-left: 2px;
}
.stats-divider {
width: 1px;
height: 36px;
background-color: #eeeeee;
}
/* Tab 切换 */
.tab-bar {
display: flex;
background-color: #ffffff;
margin-top: 12px;
padding: 0 16px;
}
.tab-item {
flex: 1;
text-align: center;
padding: 12px 0;
position: relative;
}
.tab-item.active::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 24px;
height: 3px;
background-color: #0088ff;
border-radius: 2px;
}
.tab-text {
font-size: 14px;
color: #999999;
}
.tab-item.active .tab-text {
color: #0088ff;
font-weight: 600;
}
/* 搜索栏 */
.search-area {
padding: 12px;
}
.search-bar {
display: flex;
align-items: center;
height: 36px;
background-color: #ffffff;
border-radius: 18px;
padding: 0 12px;
gap: 8px;
}
.search-icon {
font-size: 16px;
color: #cccccc;
}
.search-input {
flex: 1;
font-size: 14px;
color: #333333;
}
/* 权益列表 */
.list-area {
padding: 0 12px 12px;
display: flex;
flex-direction: column;
gap: 10px;
}
.rights-card {
display: flex;
align-items: flex-end;
background-color: #ffffff;
border-radius: 6px;
padding: 12px;
gap: 12px;
}
.card-img {
width: 75px;
height: 75px;
border-radius: 6px;
flex-shrink: 0;
}
.card-info {
flex: 1;
display: flex;
flex-direction: column;
}
.card-name {
font-size: 15px;
font-weight: 500;
color: #1a1818;
}
.card-category {
font-size: 13px;
color: #999999;
margin-top: 4px;
}
.card-address {
font-size: 13px;
color: #999999;
margin-top: 4px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 180px;
}
.card-distance {
display: flex;
align-items: center;
gap: 2px;
flex-shrink: 0;
}
.distance-icon {
font-size: 12px;
color: #999999;
}
.distance-text {
font-size: 12px;
color: #999999;
}
</style>