12312
This commit is contained in:
+78
-93
@@ -1,39 +1,30 @@
|
||||
<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"></text>
|
||||
</view>
|
||||
<text class="nav-title">商户折扣</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-area">
|
||||
<view class="search-bar">
|
||||
<text class="search-icon"></text>
|
||||
<u-icon name="search" color="#8e8e93" size="36"></u-icon>
|
||||
<input class="search-input" v-model="keyword" placeholder="请搜索商户名" confirm-type="search" @confirm="onSearch" />
|
||||
<view class="search-btn" @click="onSearch">搜索</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商户列表 -->
|
||||
<view class="list-area">
|
||||
<view class="merchant-card" v-for="item in list" :key="item.id" @click="goDetail(item)">
|
||||
<scroll-view class="list-area" scroll-y @scrolltolower="loadMore" :lower-threshold="100">
|
||||
<view class="merchant-card" v-for="item in list" :key="item.shopId" @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"></text>
|
||||
<text class="distance-text">{{ item.distance }}km</text>
|
||||
<view class="card-distance" v-if="item.distance !== null">
|
||||
<u-icon name="map" color="#999999" size="24"></u-icon>
|
||||
<text class="distance-text">{{ item.distance < 1 ? Math.round(item.distance * 1000) + 'm' : Math.round(item.distance) + 'km' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="loadStatus" :loading-text="'加载中...'" :loadmore-text="'上拉加载更多'" :nomore-text="'没有更多了'" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -41,87 +32,85 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44,
|
||||
keyword: '',
|
||||
list: [
|
||||
{
|
||||
id: 1,
|
||||
name: '万达影城(怀化市鹤城区万...',
|
||||
category: '影城',
|
||||
address: '怀化市鹤城区万达广场 C 区501',
|
||||
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_merchant1.png',
|
||||
distance: '1.4'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '绝味鸭脖(绝味怀化万达...',
|
||||
category: '商超',
|
||||
address: '怀化市鹤城区万达广场 C 区501',
|
||||
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_merchant2.png',
|
||||
distance: '1.4'
|
||||
}
|
||||
]
|
||||
list: [],
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
loading: false,
|
||||
lng: '',
|
||||
lat: '',
|
||||
loadStatus: 'loadmore'
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
const loc = uni.getStorageSync('lng') && uni.getStorageSync('lat')
|
||||
? { lng: uni.getStorageSync('lng'), lat: uni.getStorageSync('lat') }
|
||||
: null
|
||||
if (loc) {
|
||||
this.lng = loc.lng
|
||||
this.lat = loc.lat
|
||||
}
|
||||
this.loadList()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
loadList() {
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
this.loadStatus = 'loading'
|
||||
const params = {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
keyword: this.keyword,
|
||||
typeId: 2
|
||||
}
|
||||
if (this.lng) params.lng = this.lng
|
||||
if (this.lat) params.lat = this.lat
|
||||
this.$u.api.getStoreList(params).then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
const list = res.data.list || []
|
||||
if (this.pageNo === 1) {
|
||||
this.list = list
|
||||
} else {
|
||||
this.list = this.list.concat(list)
|
||||
}
|
||||
this.total = res.data.total || 0
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
if (this.list.length === 0) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else if (this.list.length >= this.total) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else {
|
||||
this.loadStatus = 'loadmore'
|
||||
}
|
||||
})
|
||||
},
|
||||
loadMore() {
|
||||
if (this.list.length < this.total && !this.loading) {
|
||||
this.pageNo++
|
||||
this.loadList()
|
||||
}
|
||||
},
|
||||
goDetail(item) {
|
||||
uni.navigateTo({ url: '/pages/venue/detail?id=' + item.id })
|
||||
uni.navigateTo({ url: '/pages/venue/detail?id=' + item.shopId })
|
||||
},
|
||||
onSearch() {
|
||||
// TODO: 调用搜索接口
|
||||
this.pageNo = 1
|
||||
this.list = []
|
||||
this.loadList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
page {
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
background-color: #ffffff;
|
||||
@@ -139,11 +128,6 @@ export default {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
font-size: 18px;
|
||||
color: #8e8e93;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
@@ -160,7 +144,9 @@ export default {
|
||||
}
|
||||
|
||||
.list-area {
|
||||
padding: 12px;
|
||||
width: 702rpx;
|
||||
margin-left: 24rpx;
|
||||
margin-top: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
@@ -195,6 +181,10 @@ export default {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
.card-category {
|
||||
@@ -220,11 +210,6 @@ export default {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.distance-icon {
|
||||
font-size: 12px;
|
||||
color: #727272;
|
||||
}
|
||||
|
||||
.distance-text {
|
||||
font-size: 12px;
|
||||
color: #727272;
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
|
||||
+2
-1
@@ -18,8 +18,9 @@
|
||||
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
|
||||
+31
-6
@@ -7,7 +7,7 @@
|
||||
|
||||
<!-- 金刚区 -->
|
||||
<view class="king-area">
|
||||
<view class="king-item" v-for="(item, index) in kingList" :key="index" @click="goPage(item.url)">
|
||||
<view class="king-item" v-for="(item, index) in kingList" :key="index" @click="item.isRights ? goRights() : goPage(item.url)">
|
||||
<image class="king-icon" :src="item.icon" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
@@ -39,7 +39,7 @@
|
||||
kingList: [
|
||||
{ icon: 'https://aliyunoss.hn12301.net/hhrs/hhrs_wlcg.png', url: '/pages/venue/venue' },
|
||||
{ icon: 'https://aliyunoss.hn12301.net/hhrs/hhrs_shzk.png', url: '/pages/discount/discount' },
|
||||
{ icon: 'https://aliyunoss.hn12301.net/hhrs/hhrs_qyb.png', url: '/pages/rights/rights' },
|
||||
{ icon: 'https://aliyunoss.hn12301.net/hhrs/hhrs_qyb.png', url: '/pages/rights/rights', isRights: true },
|
||||
{ icon: 'https://aliyunoss.hn12301.net/hhrs/hhrs_zjmd.png', url: '/pages/winners/winners' }
|
||||
],
|
||||
guideList: [
|
||||
@@ -58,10 +58,35 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad() {},
|
||||
methods: {
|
||||
onLoad() {
|
||||
this.getLocation()
|
||||
},
|
||||
methods: {
|
||||
getLocation() {
|
||||
import('@/common/location.js').then(module => {
|
||||
module.default.getLocation().then(({ lng, lat }) => {
|
||||
console.log('定位成功:', lng, lat)
|
||||
}).catch(err => {
|
||||
console.log('定位失败:', err)
|
||||
})
|
||||
})
|
||||
},
|
||||
goPage(url) {
|
||||
uni.navigateTo({ url })
|
||||
},
|
||||
goRights() {
|
||||
const phone = uni.getStorageSync('phone')
|
||||
if (!phone) {
|
||||
uni.navigateTo({ url: '/pages/index/login?redirect=rights' })
|
||||
return
|
||||
}
|
||||
const isAuth = uni.getStorageSync('isAuth')
|
||||
const hasWin = uni.getStorageSync('hasWin')
|
||||
let status = 'auth'
|
||||
if (isAuth) {
|
||||
status = hasWin ? 'info' : 'noWin'
|
||||
}
|
||||
uni.navigateTo({ url: `/pages/rights/rights?status=${status}` })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,9 +94,9 @@
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 120rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.banner-img {
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 标题区 -->
|
||||
<view class="title-area">
|
||||
<text class="title">手机号登录</text>
|
||||
<text class="subtitle">请使用真实手机号登录</text>
|
||||
</view>
|
||||
|
||||
<!-- 表单区 -->
|
||||
<view class="form-area">
|
||||
<view class="input-item">
|
||||
<input class="input-field" type="number" maxlength="11" v-model="phone" placeholder="请输入手机号码" />
|
||||
</view>
|
||||
<view class="input-item code-row">
|
||||
<input class="input-field" type="number" maxlength="4" v-model="code" placeholder="请输入验证码" />
|
||||
<text class="code-btn" :class="{ disabled: countdown > 0 }" @click="sendCode">
|
||||
{{ countdown > 0 ? countdown + '秒后重新获取' : '获取验证码' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<view class="login-btn" @click="onLogin">立即登录</view>
|
||||
|
||||
<!-- 协议区 -->
|
||||
<view class="agreement-area" @click="agreed = !agreed">
|
||||
<view class="checkbox" :class="{ checked: agreed }">
|
||||
<text class="check-icon" v-if="agreed">✓</text>
|
||||
</view>
|
||||
<text class="agreement-text">我已阅读并同意</text>
|
||||
<text class="agreement-link">《用户协议》</text>
|
||||
<text class="agreement-text">和</text>
|
||||
<text class="agreement-link">《隐私协议》</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
phone: '',
|
||||
code: '',
|
||||
countdown: 0,
|
||||
timer: null,
|
||||
agreed: true,
|
||||
redirect: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.redirect = options.redirect || ''
|
||||
},
|
||||
onUnload() {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendCode() {
|
||||
if (this.countdown > 0) return
|
||||
if (!this.phone || !/^1\d{10}$/.test(this.phone)) {
|
||||
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.$u.api.sendLoginVerifyCode({ smsType: 'CIB_LOGIN', mobile: this.phone }).then(res => {
|
||||
if (res.errcode === 0) {
|
||||
uni.showToast({ title: '验证码已发送', icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: res.errmsg || '发送失败', icon: 'none' })
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.showToast({ title: '发送失败', icon: 'none' })
|
||||
})
|
||||
this.countdown = 60
|
||||
this.timer = setInterval(() => {
|
||||
this.countdown--
|
||||
if (this.countdown <= 0) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
onLogin() {
|
||||
if (!this.phone || !/^1\d{10}$/.test(this.phone)) {
|
||||
uni.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!this.code || this.code.length < 4) {
|
||||
uni.showToast({ title: '请输入4位验证码', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!this.agreed) {
|
||||
uni.showToast({ title: '请同意用户协议和隐私协议', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.$u.api.checkerLogin({ password: '1232321', mobile: this.phone, verifyCode: this.code }).then(res => {
|
||||
if (res.errcode === 0) {
|
||||
uni.setStorageSync('token', res.data.token)
|
||||
uni.setStorageSync('phone', this.phone)
|
||||
this.$u.api.getEligibility({ phone: this.phone, identityNo: '', name: '' }).then(eRes => {
|
||||
if (eRes.errcode === 0) {
|
||||
uni.setStorageSync('isAuth', eRes.data.isAuth)
|
||||
uni.setStorageSync('hasWin', eRes.data.hasWin)
|
||||
uni.setStorageSync('cardNumber', eRes.data.cardNumber)
|
||||
uni.setStorageSync('expiresTime', eRes.data.expiresTime)
|
||||
}
|
||||
}).finally(() => {
|
||||
if (this.redirect === 'rights') {
|
||||
const isAuth = uni.getStorageSync('isAuth')
|
||||
const hasWin = uni.getStorageSync('hasWin')
|
||||
let status = 'auth'
|
||||
if (isAuth) {
|
||||
status = hasWin ? 'info' : 'noWin'
|
||||
}
|
||||
uni.redirectTo({ url: `/pages/rights/rights?status=${status}` })
|
||||
} else {
|
||||
uni.navigateBack()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showToast({ title: res.errmsg || '登录失败', icon: 'none' })
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.showToast({ title: '登录失败', icon: 'none' })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
height: 100vh;
|
||||
background-color: #ffffff;
|
||||
padding: 0 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 标题区 */
|
||||
.title-area {
|
||||
margin-top: 160rpx;
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 44rpx;
|
||||
font-weight: bold;
|
||||
color: #1a1a1a;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 表单区 */
|
||||
.form-area {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
height: 96rpx;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.code-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.code-row .input-field {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.code-btn {
|
||||
font-size: 26rpx;
|
||||
color: #0088FF;
|
||||
padding: 0 24rpx;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.code-btn.disabled {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
/* 登录按钮 */
|
||||
.login-btn {
|
||||
height: 96rpx;
|
||||
line-height: 96rpx;
|
||||
text-align: center;
|
||||
background-color: #0088FF;
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 协议区 */
|
||||
.agreement-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border: 2rpx solid #0088FF;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.checkbox.checked {
|
||||
background-color: #0088FF;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
font-size: 20rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.agreement-text {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.agreement-link {
|
||||
font-size: 24rpx;
|
||||
color: #0088FF;
|
||||
}
|
||||
</style>
|
||||
+47
-51
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="nav-header">
|
||||
<text class="nav-title">我的</text>
|
||||
<!-- 未登录 -->
|
||||
<view class="user-section" v-if="!isLogin" @click="goLogin">
|
||||
<view class="user-info">
|
||||
<image class="user-avatar" src="https://aliyunoss.hn12301.net/hhrs/hhrs_wd_tx.png" mode="aspectFill" />
|
||||
<text class="login-hint">点击登录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<view class="user-section">
|
||||
<!-- 已登录 -->
|
||||
<view class="user-section" v-else>
|
||||
<view class="user-info">
|
||||
<image class="user-avatar" src="https://aliyunoss.hn12301.net/hhrs/hhrs_avatar.png" mode="aspectFill" />
|
||||
<image class="user-avatar" src="https://aliyunoss.hn12301.net/hhrs/hhrs_wd_tx.png" mode="aspectFill" />
|
||||
<view class="user-detail">
|
||||
<text class="user-name">王东林</text>
|
||||
<text class="user-phone">186****9010</text>
|
||||
<text class="user-phone">{{ maskPhone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="logout-btn" @click="onLogout">退出登录</view>
|
||||
@@ -22,24 +22,24 @@
|
||||
<!-- 菜单列表 -->
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="goWinners">
|
||||
<text class="menu-icon icon-ticket"></text>
|
||||
<image class="menu-icon" src="https://aliyunoss.hn12301.net/hhrs/hhrs_wd_zjcx.png" mode="aspectFit" />
|
||||
<text class="menu-label">用户中奖查询</text>
|
||||
<text class="menu-arrow"></text>
|
||||
<u-icon name="arrow-right" color="#cccccc" size="28"></u-icon>
|
||||
</view>
|
||||
<view class="menu-item" @click="goGuide">
|
||||
<text class="menu-icon icon-book"></text>
|
||||
<image class="menu-icon" src="https://aliyunoss.hn12301.net/hhrs/hhrs_wd_syzn.png" mode="aspectFit" />
|
||||
<text class="menu-label">使用指南</text>
|
||||
<text class="menu-arrow"></text>
|
||||
<u-icon name="arrow-right" color="#cccccc" size="28"></u-icon>
|
||||
</view>
|
||||
<view class="menu-item" @click="goService">
|
||||
<text class="menu-icon icon-headset"></text>
|
||||
<image class="menu-icon" src="https://aliyunoss.hn12301.net/hhrs/hhrs_wd_lxkf.png" mode="aspectFit" />
|
||||
<text class="menu-label">联系客服</text>
|
||||
<text class="menu-arrow"></text>
|
||||
<u-icon name="arrow-right" color="#cccccc" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部 TabBar -->
|
||||
<tab-bar :current="1" />
|
||||
<!-- <tab-bar :current="1" /> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -50,14 +50,24 @@ export default {
|
||||
components: { tabBar },
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44
|
||||
isLogin: false,
|
||||
phone: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
computed: {
|
||||
maskPhone() {
|
||||
if (!this.phone || this.phone.length < 7) return this.phone
|
||||
return this.phone.substring(0, 3) + '****' + this.phone.substring(7)
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.phone = uni.getStorageSync('phone') || ''
|
||||
this.isLogin = !!this.phone
|
||||
},
|
||||
methods: {
|
||||
goLogin() {
|
||||
uni.navigateTo({ url: '/pages/index/login' })
|
||||
},
|
||||
onLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
@@ -65,6 +75,9 @@ export default {
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('phone')
|
||||
this.isLogin = false
|
||||
this.phone = ''
|
||||
uni.showToast({ title: '已退出登录', icon: 'success' })
|
||||
}
|
||||
}
|
||||
@@ -82,32 +95,13 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
page {
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
|
||||
.nav-bar {
|
||||
background-color: #ffffff;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-header {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #1a1818;
|
||||
}
|
||||
|
||||
/* 用户信息 */
|
||||
.user-section {
|
||||
@@ -118,6 +112,13 @@ export default {
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.login-hint {
|
||||
font-size: 16px;
|
||||
color: #1a1818;
|
||||
font-weight: 500;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -173,10 +174,8 @@ export default {
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
font-size: 18px;
|
||||
color: #0088ff;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
@@ -186,8 +185,5 @@ export default {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
+165
-136
@@ -1,70 +1,75 @@
|
||||
<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"></text>
|
||||
</view>
|
||||
<text class="nav-title">权益详情</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 门店信息卡片 -->
|
||||
<view class="store-card">
|
||||
<image class="store-img" :src="store.image" mode="aspectFill" />
|
||||
<view class="store-info">
|
||||
<text class="store-name">{{ store.name }}</text>
|
||||
<text class="store-category">{{ store.category }}</text>
|
||||
<text class="store-hours">营业时间:{{ store.hours }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地址行 -->
|
||||
<view class="address-row">
|
||||
<text class="address-text">{{ store.address }}</text>
|
||||
<view class="distance-row">
|
||||
<text class="distance-icon"></text>
|
||||
<text class="distance-text">{{ store.distance }}km</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 选择预约日期 -->
|
||||
<view class="date-section">
|
||||
<view class="section-title">
|
||||
<text class="section-icon">!</text>
|
||||
<text class="section-title-text">选择预约日期</text>
|
||||
</view>
|
||||
<view class="date-list">
|
||||
<view
|
||||
v-for="(item, index) in dateList"
|
||||
:key="index"
|
||||
class="date-card"
|
||||
:class="{ active: selectedDate === index }"
|
||||
@click="selectDate(index)"
|
||||
>
|
||||
<text class="date-weekday">{{ item.weekday }}</text>
|
||||
<text class="date-day">{{ item.day }}</text>
|
||||
<text class="date-stock">{{ item.stock }}</text>
|
||||
<view v-if="detail">
|
||||
<!-- 门店信息卡片 -->
|
||||
<view class="store-card">
|
||||
<image class="store-img" :src="detail.shopImage" mode="aspectFill" />
|
||||
<view class="store-info">
|
||||
<text class="store-name">{{ detail.shopName }}</text>
|
||||
<text class="store-category">{{ detail.category }}</text>
|
||||
<text class="store-hours">营业时间:{{ detail.businessTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="date-tip">该日期无需选择场次,直接预约即可!仅可预约近 3 日内时段</text>
|
||||
</view>
|
||||
|
||||
<!-- 商户优惠 -->
|
||||
<view class="discount-section">
|
||||
<view class="section-title">
|
||||
<text class="discount-tag-icon"></text>
|
||||
<text class="discount-title">商户优惠</text>
|
||||
<!-- 地址行 -->
|
||||
<view class="address-row">
|
||||
<text class="address-text">{{ detail.address }}</text>
|
||||
<view class="distance-row" v-if="detail.distance !== null">
|
||||
<u-icon name="map" color="#999999" size="24"></u-icon>
|
||||
<text class="distance-text">{{ detail.distance < 1 ? Math.round(detail.distance * 1000) + 'm' : Math.round(detail.distance) + 'km' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="discount-list">
|
||||
<text class="discount-item" v-for="(item, index) in store.discounts" :key="index">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部预约按钮 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="book-btn" @click="onBook">立即预约</view>
|
||||
<!-- 选择预约日期 -->
|
||||
<view class="date-section">
|
||||
<view class="section-title">
|
||||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_xzyyrq.png" style="width: 30rpx;height: 30rpx;"></image>
|
||||
<text class="section-title-text">选择预约日期</text>
|
||||
</view>
|
||||
<view class="date-list">
|
||||
<view
|
||||
v-for="(item, index) in detail.dates"
|
||||
:key="index"
|
||||
class="date-card"
|
||||
:class="{ active: selectedDate === index, disabled: item.disabled }"
|
||||
@click="!item.disabled && selectDate(index)"
|
||||
>
|
||||
<text class="date-weekday">{{ item.weekday }}</text>
|
||||
<text class="date-day">{{ item.day }}</text>
|
||||
<text class="date-stock">{{ item.stock }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 时段选择 -->
|
||||
<view class="time-slot-section" v-if="detail.dates[selectedDate] && detail.dates[selectedDate].timeSlots">
|
||||
<text class="section-title-text" style="margin-top:16px;">选择时段</text>
|
||||
<view class="time-slot-list">
|
||||
<view v-for="(slot, idx) in detail.dates[selectedDate].timeSlots" :key="slot.id"
|
||||
class="time-slot-card" :class="{ active: selectedTimeSlot === idx }"
|
||||
@click="selectTimeSlot(idx)">
|
||||
<text class="slot-name">{{ slot.name }}</text>
|
||||
<text class="slot-time">{{ slot.time }}</text>
|
||||
<text class="slot-stock">{{ slot.stock }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="date-tip" v-if="detail.isAppointment">仅可预约近 {{ detail.appointmentDays }} 日内时段</text>
|
||||
</view>
|
||||
|
||||
<!-- 使用说明 -->
|
||||
<view class="discount-section">
|
||||
<view class="section-title">
|
||||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_qysm.png" style="width: 30rpx;height: 30rpx;"></image>
|
||||
<text class="discount-title">权益说明</text>
|
||||
</view>
|
||||
<view class="discount-list">
|
||||
<text class="discount-item">{{ detail.cardInstruction }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部预约按钮 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="book-btn" @click="onBook">立即预约</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -73,102 +78,72 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44,
|
||||
ruleId: '',
|
||||
detail: null,
|
||||
selectedDate: 0,
|
||||
store: {
|
||||
id: 1,
|
||||
name: '怀化黄岩白马风景区',
|
||||
category: '景区',
|
||||
hours: '08:00~12:00',
|
||||
address: '怀化市鹤城区万达广场 C 区501',
|
||||
distance: '1.4',
|
||||
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_venue1.png',
|
||||
discounts: [
|
||||
'用本人 62 开头社保卡凭电子社保码,可享景区免费入园权益',
|
||||
'仅限社保卡持卡人本人使用,非持卡人核销后会扣除使用次数且无法入园',
|
||||
'电子社保码截图无效,需在核销时打开电子社保卡页面。电子社保卡可在云闪付-湖南社保卡,或者微信-湖南智慧人社公众号'
|
||||
]
|
||||
},
|
||||
dateList: [
|
||||
{ weekday: '明天', day: '7月14日', stock: '无限库存' },
|
||||
{ weekday: '周三', day: '7月15日', stock: '无限库存' },
|
||||
{ weekday: '周四', day: '7月16日', stock: '无限库存' }
|
||||
]
|
||||
selectedTimeSlot: null
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
if (options.id) {
|
||||
this.ruleId = options.id
|
||||
this.loadDetail(options.id)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
selectDate(index) {
|
||||
this.selectedDate = index
|
||||
this.selectedTimeSlot = null
|
||||
},
|
||||
selectTimeSlot(index) {
|
||||
this.selectedTimeSlot = index
|
||||
},
|
||||
onBook() {
|
||||
if (!this.detail) return
|
||||
const date = this.detail.dates[this.selectedDate]
|
||||
if (date.disabled) {
|
||||
uni.showToast({ title: date.reason || '该日期不可预约', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (this.detail.isAppointment && this.detail.dates[this.selectedDate].timeSlots && this.selectedTimeSlot === null) {
|
||||
uni.showToast({ title: '请选择时段', icon: 'none' })
|
||||
return
|
||||
}
|
||||
// TODO: 调用预约接口
|
||||
uni.showToast({ title: '预约成功', icon: 'success' })
|
||||
},
|
||||
loadDetail(id) {
|
||||
// TODO: 调用接口
|
||||
loadDetail(ruleId) {
|
||||
const loc = uni.getStorageSync('lng') && uni.getStorageSync('lat')
|
||||
? { lng: uni.getStorageSync('lng'), lat: uni.getStorageSync('lat') }
|
||||
: null
|
||||
const params = { ruleId: ruleId }
|
||||
if (loc) {
|
||||
params.lng = loc.lng
|
||||
params.lat = loc.lat
|
||||
}
|
||||
this.$u.api.getRightsDetail(params).then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
this.detail = res.data
|
||||
const firstAvailable = res.data.dates.findIndex(d => !d.disabled)
|
||||
this.selectedDate = firstAvailable >= 0 ? firstAvailable : 0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background-color: #f2f2f7;
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
page {
|
||||
background-color: #f2f2f7;
|
||||
padding-top: 24rpx;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
/* 门店卡片 */
|
||||
.store-card {
|
||||
display: flex;
|
||||
background-color: #ffffff;
|
||||
margin: 12px;
|
||||
margin:0rpx 12px 12px 12px;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
gap: 12px;
|
||||
@@ -231,11 +206,6 @@ export default {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.distance-icon {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.distance-text {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
@@ -295,6 +265,11 @@ export default {
|
||||
border-color: #0088ff;
|
||||
}
|
||||
|
||||
.date-card.disabled {
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.date-weekday {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
@@ -330,6 +305,60 @@ export default {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.time-slot-section {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.time-slot-list {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.time-slot-card {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12px 8px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 8px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.time-slot-card.active {
|
||||
background-color: #0088ff;
|
||||
border-color: #0088ff;
|
||||
}
|
||||
|
||||
.slot-name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1a1818;
|
||||
}
|
||||
|
||||
.time-slot-card.active .slot-name {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.slot-time {
|
||||
font-size: 11px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.time-slot-card.active .slot-time {
|
||||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
.slot-stock {
|
||||
font-size: 11px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.time-slot-card.active .slot-stock {
|
||||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
/* 商户优惠 */
|
||||
.discount-section {
|
||||
background-color: #ffffff;
|
||||
|
||||
+765
-525
File diff suppressed because it is too large
Load Diff
+30
-81
@@ -1,42 +1,32 @@
|
||||
<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"></text>
|
||||
</view>
|
||||
<text class="nav-title">门店详情</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="page" v-if="store">
|
||||
<!-- 门店信息卡片 -->
|
||||
<view class="store-card">
|
||||
<image class="store-img" :src="store.image" mode="aspectFill" />
|
||||
<view class="store-info">
|
||||
<text class="store-name">{{ store.name }}</text>
|
||||
<text class="store-category">{{ store.category }}</text>
|
||||
<text class="store-hours">营业时间:{{ store.hours }}</text>
|
||||
<text class="store-hours">营业时间:{{ store.businessTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 地址行 -->
|
||||
<view class="address-row">
|
||||
<text class="address-text">{{ store.address }}</text>
|
||||
<view class="distance-row">
|
||||
<text class="distance-icon"></text>
|
||||
<text class="distance-text">{{ store.distance }}km</text>
|
||||
<view class="distance-row" v-if="store.distance !== null">
|
||||
<u-icon name="map" color="#999999" size="24"></u-icon>
|
||||
<text class="distance-text">{{ store.distance < 1 ? Math.round(store.distance * 1000) + 'm' : Math.round(store.distance) + 'km' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商户优惠 -->
|
||||
<view class="discount-section">
|
||||
<view class="section-title">
|
||||
<text class="discount-tag-icon"></text>
|
||||
<image src="https://aliyunoss.hn12301.net/hhrs/hhrs_qysm.png" style="width: 30rpx;height: 30rpx;"></image>
|
||||
<text class="discount-title">商户优惠</text>
|
||||
</view>
|
||||
<view class="discount-list">
|
||||
<text class="discount-item" v-for="(item, index) in store.discounts" :key="index">{{ item }}</text>
|
||||
<text class="discount-item" v-for="(item, index) in discountList" :key="index">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -46,36 +36,35 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44,
|
||||
store: {
|
||||
id: 1,
|
||||
name: '怀化黄岩白马风景区',
|
||||
category: '景区',
|
||||
hours: '08:00~12:00',
|
||||
address: '怀化市鹤城区万达广场 C 区501',
|
||||
distance: '1.4',
|
||||
image: 'https://aliyunoss.hn12301.net/hhrs/hhrs_venue1.png',
|
||||
discounts: [
|
||||
'用本人 62 开头社保卡凭电子社保码,可享景区免费入园权益',
|
||||
'仅限社保卡持卡人本人使用,非持卡人核销后会扣除使用次数且无法入园',
|
||||
'电子社保码截图无效,需在核销时打开电子社保卡页面。电子社保卡可在云闪付-湖南社保卡,或者微信-湖南智慧人社公众号'
|
||||
]
|
||||
}
|
||||
store: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
discountList() {
|
||||
if (!this.store || !this.store.merchantDiscount) return []
|
||||
return this.store.merchantDiscount.split('\n')
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
if (options.id) {
|
||||
this.loadDetail(options.id)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
loadDetail(id) {
|
||||
// TODO: 调用接口 this.$u.api.getVenueDetail({ id })
|
||||
loadDetail(shopId) {
|
||||
const loc = uni.getStorageSync('lng') && uni.getStorageSync('lat')
|
||||
? { lng: uni.getStorageSync('lng'), lat: uni.getStorageSync('lat') }
|
||||
: null
|
||||
const params = { shopId: shopId }
|
||||
if (loc) {
|
||||
params.lng = loc.lng
|
||||
params.lat = loc.lat
|
||||
}
|
||||
this.$u.api.getStoreDetail(params).then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
this.store = res.data
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,44 +72,9 @@ export default {
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
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;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 门店卡片 */
|
||||
@@ -190,11 +144,6 @@ export default {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.distance-icon {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.distance-text {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
|
||||
+73
-92
@@ -1,39 +1,30 @@
|
||||
<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"></text>
|
||||
</view>
|
||||
<text class="nav-title">文旅场馆</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-area">
|
||||
<view class="search-bar">
|
||||
<text class="search-icon"></text>
|
||||
<u-icon name="search" color="#8e8e93" size="36"></u-icon>
|
||||
<input class="search-input" v-model="keyword" placeholder="请搜索场馆名" confirm-type="search" @confirm="onSearch" />
|
||||
<view class="search-btn" @click="onSearch">搜索</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 场馆列表 -->
|
||||
<view class="list-area">
|
||||
<view class="venue-card" v-for="item in list" :key="item.id" @click="goDetail(item)">
|
||||
<scroll-view class="list-area" scroll-y @scrolltolower="loadMore" :lower-threshold="100">
|
||||
<view class="venue-card" v-for="item in list" :key="item.shopId" @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"></text>
|
||||
<text class="distance-text">{{ item.distance }}km</text>
|
||||
<view class="card-distance" v-if="item.distance !== null">
|
||||
<u-icon name="map" color="#999999" size="24"></u-icon>
|
||||
<text class="distance-text">{{ item.distance < 1 ? Math.round(item.distance * 1000) + 'm' : Math.round(item.distance) + 'km' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="loadStatus" :loading-text="'加载中...'" :loadmore-text="'上拉加载更多'" :nomore-text="'没有更多了'" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -41,87 +32,85 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44,
|
||||
keyword: '',
|
||||
list: [
|
||||
{
|
||||
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'
|
||||
}
|
||||
]
|
||||
list: [],
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
loading: false,
|
||||
lng: '',
|
||||
lat: '',
|
||||
loadStatus: 'loadmore'
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
const loc = uni.getStorageSync('lng') && uni.getStorageSync('lat')
|
||||
? { lng: uni.getStorageSync('lng'), lat: uni.getStorageSync('lat') }
|
||||
: null
|
||||
if (loc) {
|
||||
this.lng = loc.lng
|
||||
this.lat = loc.lat
|
||||
}
|
||||
this.loadList()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
loadList() {
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
this.loadStatus = 'loading'
|
||||
const params = {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
keyword: this.keyword,
|
||||
typeId: 1
|
||||
}
|
||||
if (this.lng) params.lng = this.lng
|
||||
if (this.lat) params.lat = this.lat
|
||||
this.$u.api.getStoreList(params).then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
const list = res.data.list || []
|
||||
if (this.pageNo === 1) {
|
||||
this.list = list
|
||||
} else {
|
||||
this.list = this.list.concat(list)
|
||||
}
|
||||
this.total = res.data.total || 0
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
if (this.list.length === 0) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else if (this.list.length >= this.total) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else {
|
||||
this.loadStatus = 'loadmore'
|
||||
}
|
||||
})
|
||||
},
|
||||
loadMore() {
|
||||
if (this.list.length < this.total && !this.loading) {
|
||||
this.pageNo++
|
||||
this.loadList()
|
||||
}
|
||||
},
|
||||
goDetail(item) {
|
||||
uni.navigateTo({ url: '/pages/venue/detail?id=' + item.id })
|
||||
uni.navigateTo({ url: '/pages/venue/detail?id=' + item.shopId })
|
||||
},
|
||||
onSearch() {
|
||||
// TODO: 调用搜索接口
|
||||
this.pageNo = 1
|
||||
this.list = []
|
||||
this.loadList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
page {
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
background-color: #ffffff;
|
||||
@@ -139,11 +128,6 @@ export default {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
font-size: 18px;
|
||||
color: #8e8e93;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
@@ -172,6 +156,8 @@ export default {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #f2f2f7;
|
||||
border-radius: 6px;
|
||||
width: 702rpx;
|
||||
|
||||
padding: 24px 12px;
|
||||
gap: 12px;
|
||||
box-shadow: 0 2px 3px #f2f2f7;
|
||||
@@ -220,11 +206,6 @@ export default {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.distance-icon {
|
||||
font-size: 12px;
|
||||
color: #727272;
|
||||
}
|
||||
|
||||
.distance-text {
|
||||
font-size: 12px;
|
||||
color: #727272;
|
||||
|
||||
+86
-84
@@ -1,15 +1,5 @@
|
||||
<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"></text>
|
||||
</view>
|
||||
<text class="nav-title">中奖名单</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 顶部公告区 -->
|
||||
<view class="banner-area">
|
||||
<view class="banner-header">
|
||||
@@ -41,18 +31,19 @@
|
||||
</view>
|
||||
|
||||
<!-- 中奖者表格 -->
|
||||
<view class="table-area">
|
||||
<scroll-view class="table-area" scroll-y @scrolltolower="loadMore" :lower-threshold="100">
|
||||
<view class="table-header">
|
||||
<text class="table-col col-name">姓名</text>
|
||||
<text class="table-col col-idcard">身份证</text>
|
||||
<text class="table-col col-phone">手机号码</text>
|
||||
</view>
|
||||
<view class="table-row" v-for="(item, index) in currentList" :key="index">
|
||||
<text class="table-col col-name">{{ item.name }}</text>
|
||||
<text class="table-col col-idcard">{{ item.idCard }}</text>
|
||||
<text class="table-col col-phone">{{ item.phone }}</text>
|
||||
<text class="table-col col-name">{{ item.memberName }}</text>
|
||||
<text class="table-col col-idcard">{{ item.memberIdentityNo }}</text>
|
||||
<text class="table-col col-phone">{{ item.memberPhone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-loadmore :status="loadStatus" :loading-text="'加载中...'" :loadmore-text="'上拉加载更多'" :nomore-text="'没有更多了'" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -60,21 +51,14 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 44,
|
||||
currentTab: 0,
|
||||
tabs: [
|
||||
{ name: '第一期', date: '2026.02.10' },
|
||||
{ name: '第二期', date: '2026.04.10' },
|
||||
{ name: '第三期', date: '2026.06.10' }
|
||||
],
|
||||
winnerData: {
|
||||
0: [
|
||||
{ name: '王大力分', idCard: '4306********1920', phone: '186****1212' },
|
||||
{ name: '王东林', idCard: '4306********1921', phone: '186****9010' }
|
||||
],
|
||||
1: [],
|
||||
2: []
|
||||
}
|
||||
tabs: [],
|
||||
winnerData: {},
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
loading: false,
|
||||
loadStatus: 'loadmore'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -83,63 +67,83 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 44
|
||||
this.loadDates()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
loadDates() {
|
||||
this.$u.api.getWinnerDates().then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
const dates = res.data
|
||||
this.tabs = dates.map((date, index) => ({
|
||||
name: `第${index + 1}期`,
|
||||
date: date
|
||||
}))
|
||||
const data = {}
|
||||
dates.forEach((date, index) => {
|
||||
data[index] = []
|
||||
})
|
||||
this.winnerData = data
|
||||
if (this.tabs.length > 0) {
|
||||
this.loadWinnerList(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
loadWinnerList(tabIndex) {
|
||||
if (!this.tabs[tabIndex]) return
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
this.loadStatus = 'loading'
|
||||
const drawDate = this.tabs[tabIndex].date
|
||||
this.$u.api.getWinnerList({
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
drawDate: drawDate
|
||||
}).then(res => {
|
||||
if (res.errcode === 0 && res.data) {
|
||||
const list = res.data.list || []
|
||||
if (this.pageNo === 1) {
|
||||
this.$set(this.winnerData, tabIndex, list)
|
||||
} else {
|
||||
this.winnerData[tabIndex] = this.winnerData[tabIndex].concat(list)
|
||||
}
|
||||
this.total = res.data.total || 0
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
if (this.winnerData[tabIndex].length === 0) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else if (this.winnerData[tabIndex].length >= this.total) {
|
||||
this.loadStatus = 'nomore'
|
||||
} else {
|
||||
this.loadStatus = 'loadmore'
|
||||
}
|
||||
})
|
||||
},
|
||||
loadMore() {
|
||||
if (this.winnerData[this.currentTab].length < this.total && !this.loading) {
|
||||
this.pageNo++
|
||||
this.loadWinnerList(this.currentTab)
|
||||
}
|
||||
},
|
||||
switchTab(index) {
|
||||
this.currentTab = index
|
||||
this.pageNo = 1
|
||||
if (this.winnerData[index].length === 0) {
|
||||
this.loadWinnerList(index)
|
||||
} else {
|
||||
this.loadStatus = this.winnerData[index].length >= this.total ? 'nomore' : 'loadmore'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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;
|
||||
}
|
||||
|
||||
page {
|
||||
background-color: #f2f2f7;
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
/* 顶部公告区 */
|
||||
.banner-area {
|
||||
background-color: #ffffff;
|
||||
@@ -223,7 +227,7 @@ export default {
|
||||
}
|
||||
|
||||
.tab-date {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #b1b1b1;
|
||||
line-height: 22px;
|
||||
@@ -246,13 +250,9 @@ export default {
|
||||
/* 中奖者表格 */
|
||||
.table-area {
|
||||
background-color: #ffffff;
|
||||
margin: 0 12px;
|
||||
margin-top: 12px;
|
||||
border-radius: 10px 10px 0 0;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 470px;
|
||||
width: 702rpx;
|
||||
margin: 24rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.table-header,
|
||||
@@ -266,6 +266,7 @@ export default {
|
||||
.table-header {
|
||||
color: #8e8e93;
|
||||
font-size: 14px;
|
||||
|
||||
}
|
||||
|
||||
.table-row {
|
||||
@@ -291,5 +292,6 @@ export default {
|
||||
.col-phone {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user