14 changed files with 2493 additions and 443 deletions
-
44api/activity.js
-
14pages.json
-
2pages/home/home.vue
-
707pages/home/home2.vue
-
13pages/user/user.vue
-
BINstatic/images/menu-hd.png
-
479subpkg/pages/activity-detail/activity-detail.vue
-
382subpkg/pages/activity-list/activity-list.vue
-
484subpkg/pages/activity-record/activity-record.vue
-
28subpkg/pages/booking-record/booking-record.vue
-
241subpkg/pages/seat-booking/seat-booking copy.vue
-
441subpkg/pages/seat-booking/seat-booking.vue
-
4utils/config.js
-
35utils/request.js
@ -0,0 +1,44 @@ |
|||||
|
import request from '../utils/request'; |
||||
|
|
||||
|
// 活动列表
|
||||
|
export function FetchActivityInfo(data) { |
||||
|
return request({ |
||||
|
url: '/api/weixin/initActivityInfo', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 报名活动
|
||||
|
export function FetchSignActivity(data) { |
||||
|
return request({ |
||||
|
url: '/api/weixin/signActivity', |
||||
|
method: 'POST', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 我的报名活动列表
|
||||
|
export function FetchMySignActivityInfo(data) { |
||||
|
return request({ |
||||
|
url: '/api/weixin/mySignActivityInfo', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 取消报名
|
||||
|
export function FetchCancelSignActivity(data) { |
||||
|
return request({ |
||||
|
url: '/api/weixin/cancelSignActivity', |
||||
|
method: 'POST', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 删除自己报名的活动
|
||||
|
export function FetchDeleteSignActivity(data) { |
||||
|
return request({ |
||||
|
url: '/api/weixin/deleteSignActivity', |
||||
|
method: 'POST', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
@ -0,0 +1,707 @@ |
|||||
|
<template> |
||||
|
<view style="padding-bottom: 20px;"> |
||||
|
<view class="top-bar"> |
||||
|
<uni-icons class="erweima-top" custom-prefix="iconfont" type="icon-erweima" size="22" color="#fff" @click="showTopImgPopup"></uni-icons> |
||||
|
<image class="top-bar-bg" src="@/static/images/mingqi-beij@2x.png" mode="aspectFill"></image> |
||||
|
<view class="library-info"> |
||||
|
<image class="avatar" src="@/static/images/logo.jpg" mode="aspectFill"></image> |
||||
|
<view class="library-name">葛店经济技术开发区图书馆</view> |
||||
|
</view> |
||||
|
<uni-icons class="search-icon" type="search" size="24" @click="onToSearch"></uni-icons> |
||||
|
</view> |
||||
|
|
||||
|
<view class="status-cards"> |
||||
|
<view class="status-card" @click="toBorrowPage(0)"> |
||||
|
<view class="status-icon icon-color1" > |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-daiban02" size="22"></uni-icons> |
||||
|
</view> |
||||
|
<view class="status-label">在借中</view> |
||||
|
</view> |
||||
|
<view class="status-card" @click="toBorrowPage(1)"> |
||||
|
<view class="status-icon icon-color4" > |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-a-zhidu4" size="22"></uni-icons> |
||||
|
</view> |
||||
|
<view class="status-label">历史借阅</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<swiper class="banner-swiper" interval="3000" circular :vertical="false" :indicator-dots="true" :autoplay="true"> |
||||
|
<swiper-item> |
||||
|
<image data-post-id="3" src="https://mmbiz.qpic.cn/mmbiz_jpg/bVyA57fUOMicbQqItawJwQlR2oCoYql1icEbuH45ibSAzZsk2T3aDbUOIdMyOOc2CzkYouok0El5u5U3LONACaeNw/640?wx_fmt=jpeg&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1#imgIndex=1"></image> |
||||
|
</swiper-item> |
||||
|
<swiper-item> |
||||
|
<image data-post-id="4" src="https://mmbiz.qpic.cn/sz_mmbiz_gif/tuyGibvSXrsqqiaNpAFJ7lbfGL5vibHtUdV5SUk1RWnlq3QqDe9liaWhdS91L0orEsFxZMiaHOFxDOzINmkiby24fYmmWstiayUgywfVia1pwMcNpBA/640?wx_fmt=gif&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1#imgIndex=3"></image> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
|
||||
|
<swiper class="menu-swiper" interval="6000" :vertical="false" :autoplay="false"> |
||||
|
<swiper-item> |
||||
|
<view class="menu-grid"> |
||||
|
<view class="menu-item" @click="onToSearch"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-ziyuan" size="22"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">书目检索</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="onToLendCar"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-z_renew_normal" size="24"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">图书续借</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="toLibraryCard"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-duzhezheng" size="26"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">电子证</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="toRanking"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-paihangbang" size="22"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">借阅排行</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="toActivityList"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-remenhuodong" size="26"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">活动报名</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="toFeedback"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-ruguanyuyue" size="26"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">预约入馆</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="onToUser"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-yonghuxinxi-gerenxinxi" size="20"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">个人中心</view> |
||||
|
</view> |
||||
|
<view class="menu-item" @click="goRegister"> |
||||
|
<view class="menu-icon"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-daohang-banzhengxuzhi" size="25"></uni-icons> |
||||
|
</view> |
||||
|
<view class="menu-label">在线办证</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
|
||||
|
<view v-if="isBindLibraryCard" class="library-card-has"> |
||||
|
<view class="section-title">我的借阅证</view> |
||||
|
|
||||
|
<swiper |
||||
|
class="card-swiper" |
||||
|
:circular="false" |
||||
|
> |
||||
|
<swiper-item v-for="item in readerCardList" :key="item.id"> |
||||
|
<view class="card-item" @click.stop="showQrcode(item.bindValue)"> |
||||
|
<image class="card-left-img" src="@/static/images/card-img2.png" mode="widthFix" /> |
||||
|
<view class="card-right-info"> |
||||
|
<text class="info-title">读者证号</text> |
||||
|
<text class="info-num">{{ formatCardNo(item.bindValue) }}</text> |
||||
|
</view> |
||||
|
<view class="default-tag" v-if="item.bindDefault">默认证</view> |
||||
|
<uni-icons class="erweima-style" custom-prefix="iconfont" type="icon-erweima" size="28"></uni-icons> |
||||
|
</view> |
||||
|
</swiper-item> |
||||
|
</swiper> |
||||
|
</view> |
||||
|
|
||||
|
<view class="library-card-section" @click="toCheckLogin" v-else> |
||||
|
<view class="section-title">借阅证</view> |
||||
|
<image class="card-icon" src="@/static/images/card-img2.png"></image> |
||||
|
<view class="card-tip">您还没有绑定读者证哦~</view> |
||||
|
<button class="bind-btn">立即绑定</button> |
||||
|
</view> |
||||
|
|
||||
|
<root-portal> |
||||
|
<uni-popup |
||||
|
ref="popup" |
||||
|
type="center" |
||||
|
:mask-click="true" |
||||
|
@maskClick="closeAllPopup" |
||||
|
> |
||||
|
<view class="qrcode-popup"> |
||||
|
<view class="qrcode-title">读者证二维码</view> |
||||
|
<w-qrcode |
||||
|
v-if="qrcodeText" |
||||
|
:value="qrcodeText" |
||||
|
:size="160" |
||||
|
foreground="#333" |
||||
|
background="#ffffff" |
||||
|
/> |
||||
|
<view class="qrcode-num" v-if="qrcodeText">{{ qrcodeText }}</view> |
||||
|
</view> |
||||
|
</uni-popup> |
||||
|
|
||||
|
<uni-popup |
||||
|
ref="erweimapopup" |
||||
|
type="center" |
||||
|
:mask-click="true" |
||||
|
@maskClick="closeErweiPopup" |
||||
|
:custom-style="popupFixedStyle" |
||||
|
> |
||||
|
<view class="qrcode-popup" style="width: auto !important;"> |
||||
|
<image |
||||
|
v-if="wecharQRCode" |
||||
|
:src="wecharQRCode" |
||||
|
style="width:200px;height:200px;" |
||||
|
mode="aspectFit" |
||||
|
:show-menu-by-longpress="true" |
||||
|
@longpress="onQRCodeLongPress" |
||||
|
></image> |
||||
|
</view> |
||||
|
</uni-popup> |
||||
|
</root-portal> |
||||
|
|
||||
|
|
||||
|
<view class="recommendation-section"> |
||||
|
<view class="section-title"> |
||||
|
<text class="left-txt">图书推荐</text> |
||||
|
<view class="more-link" @click="getMoreBoook" v-if="!(recommendedBooks.length === 0 && !isLoading)"> |
||||
|
<text style="margin-right: 5px;">查看更多</text> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-gengduo" size="12"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="recommendation-list"> |
||||
|
<uni-load-more status="loading" v-if="isLoading"></uni-load-more> |
||||
|
|
||||
|
<view v-else class="book-item" v-for="(item,index) in recommendedBooks.slice(0,3)" @click="goToBookDetail(item)" :key="index" > |
||||
|
<image |
||||
|
class="book-cover" |
||||
|
:src="item.coverUrl || '/static/images/default-book.png'" |
||||
|
@error="onImgError" |
||||
|
></image> |
||||
|
<view class="book-title">{{item.name}}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="empty" v-if="recommendedBooks.length === 0 && !isLoading"> |
||||
|
<uni-icons custom-prefix="iconfont" type="icon-kongshuju" size="80"></uni-icons> |
||||
|
<text style="margin-top: 20px;">暂无推荐书籍~</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { FetchInitScreenSetting, FetchOpenId, FetchFindAllReaderBindByOpenId} from '@/api/user'; |
||||
|
import { FetchInitScreenBookRecommend } from '@/api/book'; |
||||
|
import config from '@/utils/config'; |
||||
|
import { STORAGE_KEYS } from '@/utils/storage'; |
||||
|
|
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
isLoading: true, |
||||
|
recommendedBooks: [], |
||||
|
userInfo: {}, |
||||
|
isBindLibraryCard: false, |
||||
|
readerCardList: [], |
||||
|
baseUrl: config.baseUrl, |
||||
|
qrcodeText: '', |
||||
|
popupFixedStyle: 'position:fixed;top:0;left:0;right:0;bottom:0;', |
||||
|
wecharQRCode: null |
||||
|
}; |
||||
|
}, |
||||
|
onLoad() { |
||||
|
this.getRecommendBooks(); |
||||
|
this.getScreenSetting() |
||||
|
}, |
||||
|
onShow() { |
||||
|
this.initUserAndCheckBind(); |
||||
|
}, |
||||
|
methods:{ |
||||
|
async getScreenSetting() { |
||||
|
const res = await FetchInitScreenSetting({ libcode: config.LIB_CODE }); |
||||
|
if (res.data.wechar_qr_code && res.data.wechar_qr_code.context) { |
||||
|
// 直接使用图片url,不再转base64 |
||||
|
this.wecharQRCode = this.baseUrl + '/api/fileRelevant/getImg?imgType=1&imgId=' + res.data.wechar_qr_code.context; |
||||
|
} else { |
||||
|
this.wecharQRCode = null; |
||||
|
} |
||||
|
}, |
||||
|
showTopImgPopup() { |
||||
|
if (!this.wecharQRCode) { |
||||
|
uni.showToast({ title: '暂无图片', icon: 'none' }) |
||||
|
return |
||||
|
} |
||||
|
this.$refs.erweimapopup.open() |
||||
|
}, |
||||
|
|
||||
|
formatCardNo(cardNo) { |
||||
|
if (!cardNo) return ''; |
||||
|
const str = String(cardNo); |
||||
|
const len = str.length; |
||||
|
|
||||
|
if (len > 8) { |
||||
|
const front = str.substring(0, 2); |
||||
|
const end = str.substring(len - 2); |
||||
|
const star = '*'.repeat(len - 4); |
||||
|
return front + star + end; |
||||
|
} else { |
||||
|
return '***' + str.substring(len - 2); |
||||
|
} |
||||
|
}, |
||||
|
onImgError(e) { |
||||
|
// 图片加载失败,替换默认图 |
||||
|
e.target.src = "/static/images/default-book.png"; |
||||
|
}, |
||||
|
async initUserAndCheckBind() { |
||||
|
try { |
||||
|
let openId = uni.getStorageSync('wx_login_code'); |
||||
|
|
||||
|
if (!openId) { |
||||
|
const loginRes = await new Promise((resolve, reject) => { |
||||
|
uni.login({ |
||||
|
success: resolve, |
||||
|
fail: reject |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
if (!loginRes.code) { |
||||
|
uni.showToast({ title: '授权失败', icon: 'none' }); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const openRes = await FetchOpenId({ |
||||
|
libcode: config.LIB_CODE, |
||||
|
code: loginRes.code |
||||
|
}); |
||||
|
|
||||
|
if (openRes.code !== 200 || !openRes.data) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
openId = openRes.data; |
||||
|
uni.setStorageSync('wx_login_code', openId); |
||||
|
} |
||||
|
|
||||
|
const res = await FetchFindAllReaderBindByOpenId({ |
||||
|
libcode: config.LIB_CODE, |
||||
|
openId: openId |
||||
|
}); |
||||
|
|
||||
|
if (res.code === 200 && res.data.length > 0) { |
||||
|
this.isBindLibraryCard = true; |
||||
|
const defaultCard = res.data.find(item => item.bindDefault === true); |
||||
|
const otherCards = res.data.filter(item => !item.bindDefault); |
||||
|
this.readerCardList = defaultCard ? [defaultCard, ...otherCards] : res.data; |
||||
|
|
||||
|
uni.setStorageSync(STORAGE_KEYS.READER_CARD_LIST, this.readerCardList); |
||||
|
uni.setStorageSync(STORAGE_KEYS.CURRENT_READER_CARD, defaultCard); |
||||
|
} else { |
||||
|
this.isBindLibraryCard = false; |
||||
|
this.readerCardList = []; |
||||
|
uni.setStorageSync(STORAGE_KEYS.READER_CARD_LIST, []); |
||||
|
uni.setStorageSync(STORAGE_KEYS.CURRENT_READER_CARD, null); |
||||
|
} |
||||
|
|
||||
|
} catch (err) { |
||||
|
console.error('初始化失败:', err); |
||||
|
const list = uni.getStorageSync(STORAGE_KEYS.READER_CARD_LIST) || []; |
||||
|
const defaultCard = list.find(item => item.bindDefault === true); |
||||
|
const otherCards = list.filter(item => !item.bindDefault); |
||||
|
this.readerCardList = defaultCard ? [defaultCard, ...otherCards] : list; |
||||
|
|
||||
|
this.isBindLibraryCard = list.length > 0; |
||||
|
} |
||||
|
}, |
||||
|
async getRecommendBooks() { |
||||
|
try { |
||||
|
const res = await FetchInitScreenBookRecommend({ libcode: config.LIB_CODE }); |
||||
|
let books = res.data || []; |
||||
|
const limit = 3; |
||||
|
const displayBooks = books.slice(0, limit); |
||||
|
|
||||
|
// 不再请求下载图片,直接拼接url |
||||
|
for (let i = 0; i < displayBooks.length; i++) { |
||||
|
let item = displayBooks[i]; |
||||
|
if (item.imgPath) { |
||||
|
item.coverUrl = this.baseUrl + '/api/fileRelevant/getImg?imgType=2&imgId=' + item.imgPath; |
||||
|
} else { |
||||
|
item.coverUrl = ''; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
this.recommendedBooks = displayBooks; |
||||
|
this.isLoading = false; |
||||
|
} catch (err) { |
||||
|
console.error('获取图书推荐失败:', err); |
||||
|
this.isLoading = false; |
||||
|
} |
||||
|
}, |
||||
|
goToBookDetail(item) { |
||||
|
uni.navigateTo({ |
||||
|
url: "/subpkg/pages/book-detail/book-detail?bookData=" + encodeURIComponent(JSON.stringify(item)) + "&fromRecommend=true" |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
getMoreBoook(){ |
||||
|
uni.navigateTo({ |
||||
|
url: "/subpkg/pages/book-list/book-list" |
||||
|
}) |
||||
|
}, |
||||
|
onToSearch() { |
||||
|
uni.switchTab({ |
||||
|
url: "/pages/search/search" |
||||
|
}); |
||||
|
}, |
||||
|
onToLendCar() { |
||||
|
this.checkBindAndNavigate("/pages/lendCar/lendCar", "请您绑定读者证", true); |
||||
|
}, |
||||
|
toCheckLogin() { |
||||
|
uni.navigateTo({ |
||||
|
url: "/pages/login/login" |
||||
|
}); |
||||
|
}, |
||||
|
toRanking(){ |
||||
|
uni.navigateTo({ |
||||
|
url: "/subpkg/pages/ranking/ranking" |
||||
|
}) |
||||
|
}, |
||||
|
toActivityList(){ |
||||
|
this.checkBindAndNavigate("/subpkg/pages/activity-list/activity-list", "请您绑定读者证"); |
||||
|
}, |
||||
|
toBorrowPage(index) { |
||||
|
if (this.isBindLibraryCard) { |
||||
|
uni.setStorageSync('switch_tab_index', index); |
||||
|
uni.navigateTo({ |
||||
|
url: '/subpkg/pages/myLending/myLending' |
||||
|
}); |
||||
|
} else { |
||||
|
uni.showModal({ |
||||
|
title: '提示', |
||||
|
content: '请您绑定读者证', |
||||
|
confirmText: '去绑定', |
||||
|
cancelText: '取消', |
||||
|
success: (res) => { |
||||
|
if (res.confirm) { |
||||
|
uni.navigateTo({ url: "/pages/login/login" }); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
toBorrowCar() { |
||||
|
uni.switchTab({ |
||||
|
url: '/pages/lendCar/lendCar' |
||||
|
}); |
||||
|
}, |
||||
|
toFeedback() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/subpkg/pages/seat-booking/seat-booking' |
||||
|
}); |
||||
|
}, |
||||
|
toLibraryCard() { |
||||
|
if (this.isBindLibraryCard) { |
||||
|
uni.navigateTo({ url: '/subpkg/pages/reader-card/reader-card' }); |
||||
|
} |
||||
|
else { |
||||
|
uni.navigateTo({ url: "/pages/login/login" }); |
||||
|
} |
||||
|
}, |
||||
|
onToUser() { |
||||
|
this.checkBindAndNavigate("/pages/user/user", "请您绑定读者证", true); |
||||
|
}, |
||||
|
checkBindAndNavigate(url, message, isSwitchTab = false) { |
||||
|
if (this.isBindLibraryCard) { |
||||
|
if (isSwitchTab) { |
||||
|
uni.switchTab({ url }); |
||||
|
} else { |
||||
|
uni.navigateTo({ url }); |
||||
|
} |
||||
|
} else { |
||||
|
uni.showModal({ |
||||
|
title: '提示', |
||||
|
content: message, |
||||
|
confirmText: '去绑定', |
||||
|
cancelText: '取消', |
||||
|
success: (res) => { |
||||
|
if (res.confirm) { |
||||
|
uni.navigateTo({ url: "/pages/login/login" }); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
showQrcode(bindValue) { |
||||
|
this.qrcodeText = bindValue; |
||||
|
this.$refs.popup.open(); |
||||
|
}, |
||||
|
closeAllPopup() { |
||||
|
this.qrcodeText = ''; |
||||
|
this.$refs.popup.close(); |
||||
|
}, |
||||
|
closeErweiPopup() { |
||||
|
this.$refs.erweimapopup.close() |
||||
|
}, |
||||
|
onQRCodeLongPress() { |
||||
|
}, |
||||
|
// 【已废弃】不再使用urlToBase64 |
||||
|
goRegister() { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/register/register' |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.top-bar{ |
||||
|
.erweima-top{ |
||||
|
position: absolute; |
||||
|
left: 16px; |
||||
|
top: 15px; |
||||
|
z-index: 999; |
||||
|
} |
||||
|
.search-icon{ |
||||
|
position: absolute; |
||||
|
right: 16px; |
||||
|
top: 15px; |
||||
|
z-index: 22; |
||||
|
::v-deep .uni-icons{ |
||||
|
color: #fff !important; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.status-cards { |
||||
|
display: flex; |
||||
|
background-color: #fff; |
||||
|
margin: 10px; |
||||
|
border-radius: 8px; |
||||
|
padding: 20px 10px; |
||||
|
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05); |
||||
|
.status-card { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.status-icon { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
width: 40px; |
||||
|
height: 40px; |
||||
|
margin-bottom: 6px; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
.icon-color1{ |
||||
|
background-color: #e4f2ff; |
||||
|
} |
||||
|
.icon-color2{ |
||||
|
background-color: #ffeff0; |
||||
|
} |
||||
|
.icon-color3{ |
||||
|
background-color: #e4fff4; |
||||
|
} |
||||
|
.icon-color4{ |
||||
|
background-color: #fef8e2; |
||||
|
} |
||||
|
.status-label { |
||||
|
font-size: 12px; |
||||
|
color: #333; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
swiper.banner-swiper{ |
||||
|
width: 100%; |
||||
|
height: 130px; |
||||
|
} |
||||
|
swiper.banner-swiper image{ |
||||
|
width: 100%; |
||||
|
height: 130px; |
||||
|
} |
||||
|
swiper.menu-swiper{ |
||||
|
width:100%; |
||||
|
margin-top: 10px; |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
|
||||
|
.menu-grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(4, 1fr); |
||||
|
.menu-item { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
padding: 10px 0; |
||||
|
.menu-icon{ |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
height: 30px; |
||||
|
::v-deep .uni-icons{ |
||||
|
color: #01a4fe !important; |
||||
|
} |
||||
|
} |
||||
|
.menu-label { |
||||
|
font-size: 12px; |
||||
|
color: #333; |
||||
|
text-align: center; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.library-card-section { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
width: 100%; |
||||
|
padding: 20px 0; |
||||
|
.section-title { |
||||
|
font-size: 22px; |
||||
|
font-weight: bold; |
||||
|
background: linear-gradient(140deg, #01a4ff, #2ec8fe); |
||||
|
-webkit-background-clip: text; |
||||
|
color: transparent; |
||||
|
letter-spacing: 0.1em; |
||||
|
margin-bottom: 5px; |
||||
|
} |
||||
|
.card-icon { |
||||
|
width: 80px; |
||||
|
height: 80px; |
||||
|
} |
||||
|
.card-tip { |
||||
|
font-size: 12px; |
||||
|
color: #999; |
||||
|
margin: 5px 0; |
||||
|
} |
||||
|
.bind-btn { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
border: 1px solid #06a8ff ; |
||||
|
width: 128px !important; |
||||
|
height: 28px; |
||||
|
border-radius: 28px; |
||||
|
background: linear-gradient(140deg, #01a4ff, #2ec8fe); |
||||
|
font-size: 14px; |
||||
|
color: #fff; |
||||
|
line-height: 28px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.recommendation-section { |
||||
|
background-color: #fff; |
||||
|
margin: 10px; |
||||
|
border-radius: 8px; |
||||
|
padding: 0 0 10px 0; |
||||
|
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05); |
||||
|
.section-title{ |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
height: 40px; |
||||
|
padding: 0 10px; |
||||
|
.left-txt{ |
||||
|
color: #343434; |
||||
|
font-size: 15px; |
||||
|
font-weight: 700; |
||||
|
} |
||||
|
.more-link{ |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: flex-start; |
||||
|
align-items: center; |
||||
|
color: #999; |
||||
|
font-size: 11px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
.library-card-has { |
||||
|
width: 100%; |
||||
|
padding: 20px 10px; |
||||
|
box-sizing: border-box; |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 22px; |
||||
|
font-weight: bold; |
||||
|
background: linear-gradient(140deg, #01a4ff, #2ec8fe); |
||||
|
-webkit-background-clip: text; |
||||
|
color: transparent; |
||||
|
letter-spacing: 0.1em; |
||||
|
margin-bottom: 10px; |
||||
|
padding-left: 5px; |
||||
|
} |
||||
|
|
||||
|
.card-list { |
||||
|
width: 100%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.card-swiper { |
||||
|
height: 106px; |
||||
|
.card-item{ |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 10px; |
||||
|
border: 2px solid #C6C6E2; |
||||
|
border-radius: 8px; |
||||
|
background: rgba(241,241,249,0.4); |
||||
|
cursor: pointer; |
||||
|
|
||||
|
&.active{ |
||||
|
border-color: #01a4fe; |
||||
|
background: rgba(1, 164, 254, 0.1); |
||||
|
} |
||||
|
|
||||
|
.card-left-img{ |
||||
|
width: 80px; |
||||
|
margin-right: 12px; |
||||
|
display: block; |
||||
|
} |
||||
|
|
||||
|
.card-right-info{ |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
|
||||
|
.info-title{ |
||||
|
font-size: 16px; |
||||
|
color: #333; |
||||
|
font-weight: bold; |
||||
|
padding-bottom: 12px; |
||||
|
} |
||||
|
|
||||
|
.info-num{ |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.default-tag { |
||||
|
position: absolute; |
||||
|
right: 12px; |
||||
|
top: 12px; |
||||
|
font-size: 11px; |
||||
|
color: #01a4fe; |
||||
|
border: 1px solid #01a4fe; |
||||
|
border-radius: 4px; |
||||
|
padding: 2px 6px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.erweima-style{ |
||||
|
position: absolute; |
||||
|
right: 12px; |
||||
|
bottom: 22px; |
||||
|
::v-deep .icon-erweima{ |
||||
|
color: #999 !important; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
After Width: 128 | Height: 128 | Size: 16 KiB |
@ -0,0 +1,484 @@ |
|||||
|
<template> |
||||
|
<view class="activity-list"> |
||||
|
<!-- tab栏 --> |
||||
|
<view class="tab-box"> |
||||
|
<view |
||||
|
class="tab-item" |
||||
|
v-for="(tab,idx) in tabList" |
||||
|
:key="idx" |
||||
|
:class="{active:activeTab === idx}" |
||||
|
@click="switchTab(idx)" |
||||
|
> |
||||
|
{{tab.label}} |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<scroll-view |
||||
|
scroll-y |
||||
|
@scrolltolower="onScrollLower" |
||||
|
lower-threshold="150" |
||||
|
class="scroll-view" |
||||
|
> |
||||
|
<view v-if="loading" class="loading-box"> |
||||
|
<text class="loading-text">加载中...</text> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 左滑组件 uni-swipe-action --> |
||||
|
<!-- :disabled="!(item.status === '未开始' && !item.isCancel)" --> |
||||
|
<uni-swipe-action> |
||||
|
<uni-swipe-action-item |
||||
|
v-for="item in activityList" |
||||
|
:key="item.signId" |
||||
|
> |
||||
|
<!-- 左侧主体内容 --> |
||||
|
<view class="activity-item" @click="toActivityDetail(item)"> |
||||
|
<view class="activity-info"> |
||||
|
<view class="title-row"> |
||||
|
<text class="title">{{ item.title }}</text> |
||||
|
<text class="status-tag" :class="getStatusClass(item.status)"> |
||||
|
{{ item.status }} |
||||
|
</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">开始时间</text> |
||||
|
<text class="value">{{ formatTime(item.start_time) }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">结束时间</text> |
||||
|
<text class="value">{{ formatTime(item.end_time) }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">预约人</text> |
||||
|
<text class="value">{{ item.signName }}</text> |
||||
|
</view> |
||||
|
<view class="item-info"> |
||||
|
<text class="label">参加人数</text> |
||||
|
<text class="value">{{ item.signNum }}</text> |
||||
|
</view> |
||||
|
<!-- 未开始 && 未取消预约 才显示取消预约按钮 --> |
||||
|
<view class="btn-box" v-if="item.status === '未开始' && !item.isCancel"> |
||||
|
<button class="activity-btn" type="primary" @click.stop="cancelAppoint(item)"> 取消预约 </button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 右滑出来的按钮插槽 --> |
||||
|
<!-- v-if="!(item.status === '未开始' && !item.isCancel)" --> |
||||
|
<!-- v-if="item.status !== '进行中'" --> |
||||
|
<template #right > |
||||
|
<view class="swipe-right-wrap"> |
||||
|
<view class="swipe-btn swipe-btn-delete" @click.stop="deleteSignActivity(item)"> |
||||
|
<uni-icons type="trash" size="24"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
</uni-swipe-action-item> |
||||
|
</uni-swipe-action> |
||||
|
|
||||
|
<!-- 非loading,有数据,是最后一页,哪怕仅1条也展示没有更多 --> |
||||
|
<view v-if="!loading && noMore && activityList.length > 0" class="nomore-box"> |
||||
|
<text class="nomore-text">没有更多数据了</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="empty-box" v-if="!loading && activityList.length === 0"> |
||||
|
<uni-icons type="empty" size="80" color="#ccc"></uni-icons> |
||||
|
<text class="empty-text">暂无预约活动~</text> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import config from '@/utils/config'; |
||||
|
import { FetchSessionKey } from '@/api/user.js'; |
||||
|
import { FetchMySignActivityInfo, FetchCancelSignActivity,FetchDeleteSignActivity } from '@/api/activity.js' |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
tabList:[ |
||||
|
{label:'全部',value:null}, |
||||
|
{label:'预约成功',value:false}, |
||||
|
{label:'已取消',value:true} |
||||
|
], |
||||
|
activeTab:0, |
||||
|
activityList: [], |
||||
|
refreshing: false, |
||||
|
loading: false, |
||||
|
noMore: false, |
||||
|
page: 0, |
||||
|
pageSize: 20, |
||||
|
sessionKey: '', |
||||
|
openid: '' |
||||
|
}; |
||||
|
}, |
||||
|
async onLoad() { |
||||
|
await this.getSessionKey(); |
||||
|
this.getActivityList(true); |
||||
|
|
||||
|
uni.$on('refreshMySignList',()=>{ |
||||
|
this.getActivityList(true) |
||||
|
}) |
||||
|
}, |
||||
|
onUnload(){ |
||||
|
uni.$off('refreshMySignList') |
||||
|
}, |
||||
|
onPullDownRefresh() { |
||||
|
if(this.loading){ |
||||
|
uni.stopPullDownRefresh() |
||||
|
return |
||||
|
} |
||||
|
this.getActivityList(true).finally(()=>{ |
||||
|
uni.stopPullDownRefresh() |
||||
|
}) |
||||
|
}, |
||||
|
methods: { |
||||
|
switchTab(index){ |
||||
|
this.activeTab = index |
||||
|
this.page = 0 |
||||
|
this.noMore = false |
||||
|
this.activityList = [] |
||||
|
this.getActivityList(true) |
||||
|
}, |
||||
|
|
||||
|
formatTime(timestamp) { |
||||
|
if (!timestamp) return ''; |
||||
|
const date = new Date(timestamp); |
||||
|
const y = date.getFullYear(); |
||||
|
const m = String(date.getMonth() + 1).padStart(2, '0'); |
||||
|
const d = String(date.getDate()).padStart(2, '0'); |
||||
|
const h = String(date.getHours()).padStart(2, '0'); |
||||
|
const min = String(date.getMinutes()).padStart(2, '0'); |
||||
|
return `${y}-${m}-${d} ${h}:${min}`; |
||||
|
}, |
||||
|
getStatusClass(status) { |
||||
|
if (status === '未开始') return 'status-0'; |
||||
|
if (status === '进行中') return 'status-1'; |
||||
|
if (status === '已结束') return 'status-2'; |
||||
|
return ''; |
||||
|
}, |
||||
|
async getSessionKey() { |
||||
|
return new Promise((resolve) => { |
||||
|
uni.login({ |
||||
|
success: async (loginRes) => { |
||||
|
console.log('loginRes', loginRes) |
||||
|
if (loginRes.code) { |
||||
|
const res = await FetchSessionKey({ |
||||
|
libcode: config.LIB_CODE, |
||||
|
code: loginRes.code |
||||
|
}); |
||||
|
if (res.code === 200) { |
||||
|
this.sessionKey = res.data.session_key; |
||||
|
this.openid = res.data.openid; |
||||
|
} |
||||
|
} |
||||
|
resolve() |
||||
|
}, |
||||
|
fail: () => { |
||||
|
resolve() |
||||
|
} |
||||
|
}); |
||||
|
}) |
||||
|
}, |
||||
|
async getActivityList(isRefresh = false) { |
||||
|
if (!this.openid) { |
||||
|
uni.showToast({ title: '获取用户信息失败', icon: 'none' }) |
||||
|
return |
||||
|
} |
||||
|
if (this.loading) return; |
||||
|
|
||||
|
if (isRefresh) { |
||||
|
this.page = 0; |
||||
|
this.noMore = false; |
||||
|
this.refreshing = true; |
||||
|
} else { |
||||
|
if (this.noMore) return; |
||||
|
} |
||||
|
|
||||
|
this.loading = true; |
||||
|
const currentTabItem = this.tabList[this.activeTab] |
||||
|
const params = { |
||||
|
openId: this.openid, |
||||
|
page: this.page, |
||||
|
pageSize: this.pageSize |
||||
|
} |
||||
|
if(currentTabItem.value !== null){ |
||||
|
params.isCancel = currentTabItem.value |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
const res = await FetchMySignActivityInfo(params); |
||||
|
console.log('FetchMySignActivityInfo返回结果', res) |
||||
|
if (res.code === 200) { |
||||
|
const pageData = res.data; |
||||
|
const list = pageData.content || []; |
||||
|
|
||||
|
const currentPage = pageData.number ?? 0; |
||||
|
const totalPage = pageData.totalPages ?? 0; |
||||
|
this.noMore = currentPage >= totalPage - 1; |
||||
|
|
||||
|
if (isRefresh) { |
||||
|
this.activityList = list; |
||||
|
} else { |
||||
|
this.activityList = [...this.activityList, ...list]; |
||||
|
} |
||||
|
} else { |
||||
|
if (isRefresh) this.activityList = []; |
||||
|
} |
||||
|
} catch (err) { |
||||
|
console.error('请求活动接口异常', err) |
||||
|
uni.showToast({ title: '网络请求失败', icon: 'none' }) |
||||
|
} finally { |
||||
|
this.refreshing = false; |
||||
|
this.loading = false; |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
onRefresh() { |
||||
|
if(this.loading) return |
||||
|
this.getActivityList(true); |
||||
|
}, |
||||
|
|
||||
|
onScrollLower() { |
||||
|
if(this.loading || this.noMore) return; |
||||
|
this.page += 1; |
||||
|
this.getActivityList(false); |
||||
|
}, |
||||
|
|
||||
|
cancelAppoint(item) { |
||||
|
uni.showModal({ |
||||
|
title: '提示', |
||||
|
content: `确定要取消活动【${item.title}】的预约吗?`, |
||||
|
success: async (res) => { |
||||
|
if (res.confirm) { |
||||
|
try { |
||||
|
const apiRes = await FetchCancelSignActivity({ |
||||
|
id: item.signId |
||||
|
}) |
||||
|
if(apiRes.code === 200){ |
||||
|
uni.showToast({ title: '取消成功', icon: 'success' }) |
||||
|
this.getActivityList(true) |
||||
|
}else{ |
||||
|
uni.showToast({ title: apiRes.message || '取消失败', icon: 'none' }) |
||||
|
} |
||||
|
}catch(err){ |
||||
|
console.error('取消预约失败', err) |
||||
|
uni.showToast({ title: '网络异常,取消失败', icon: 'none' }) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
deleteSignActivity(item){ |
||||
|
uni.showModal({ |
||||
|
title: '提示', |
||||
|
content: `确定要删除活动【${item.title}】的预约吗?`, |
||||
|
success: async (res) => { |
||||
|
if (res.confirm) { |
||||
|
try { |
||||
|
const apiRes = await FetchDeleteSignActivity({ |
||||
|
id: item.signId |
||||
|
}) |
||||
|
if(apiRes.code === 200){ |
||||
|
uni.showToast({ title: '删除成功', icon: 'success' }) |
||||
|
this.getActivityList(true) |
||||
|
}else{ |
||||
|
uni.showToast({ title: apiRes.message || '删除失败', icon: 'none' }) |
||||
|
} |
||||
|
}catch(err){ |
||||
|
console.error('删除预约失败', err) |
||||
|
uni.showToast({ title: '网络异常,删除失败', icon: 'none' }) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
toActivityDetail(item) { |
||||
|
console.log('toActivityDetail',item); |
||||
|
uni.navigateTo({ |
||||
|
url: "/subpkg/pages/activity-detail/activity-detail?item=" + encodeURIComponent(JSON.stringify(item)) |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.activity-list { |
||||
|
padding: 0; |
||||
|
height: 100vh; |
||||
|
box-sizing: border-box; |
||||
|
background-color: #f5f5f5; |
||||
|
display:flex; |
||||
|
flex-direction:column; |
||||
|
} |
||||
|
|
||||
|
.tab-box { |
||||
|
display: flex; |
||||
|
background-color: #fff; |
||||
|
margin-bottom: 10px; |
||||
|
position: sticky; |
||||
|
top: 0; |
||||
|
z-index: 99; |
||||
|
} |
||||
|
.tab-item{ |
||||
|
flex:1; |
||||
|
text-align:center; |
||||
|
padding:12px 0; |
||||
|
font-size:14px; |
||||
|
color:#666; |
||||
|
position:relative; |
||||
|
} |
||||
|
.tab-item.active{ |
||||
|
color:#01a4fe; |
||||
|
font-weight:bold; |
||||
|
} |
||||
|
.tab-item.active::after{ |
||||
|
content:""; |
||||
|
position:absolute; |
||||
|
bottom:0; |
||||
|
left:50%; |
||||
|
transform:translateX(-50%); |
||||
|
width:28px; |
||||
|
height:2px; |
||||
|
background:#01a4fe; |
||||
|
} |
||||
|
|
||||
|
.scroll-view { |
||||
|
flex:1; |
||||
|
height: 0; |
||||
|
padding: 0 12px; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.loading-box{ |
||||
|
padding:20px 0; |
||||
|
text-align:center; |
||||
|
} |
||||
|
.loading-text{ |
||||
|
font-size:14px; |
||||
|
color:#999; |
||||
|
} |
||||
|
|
||||
|
.nomore-box{ |
||||
|
padding:15px 0; |
||||
|
text-align:center; |
||||
|
} |
||||
|
.nomore-text{ |
||||
|
font-size:13px; |
||||
|
color:#999; |
||||
|
} |
||||
|
|
||||
|
.empty-box { |
||||
|
height: calc(100vh - 180px); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
.empty-text { |
||||
|
margin-top: 16px; |
||||
|
font-size: 14px; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.activity-item { |
||||
|
background: #fff; |
||||
|
border-radius: 12px; |
||||
|
overflow: hidden; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); |
||||
|
|
||||
|
.activity-info { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: flex-start; |
||||
|
padding: 16px; |
||||
|
|
||||
|
.title-row{ |
||||
|
width:100%; |
||||
|
display:flex; |
||||
|
justify-content: space-between; |
||||
|
align-items:flex-start; |
||||
|
margin-bottom:12px; |
||||
|
} |
||||
|
.title { |
||||
|
flex: 1; |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #222; |
||||
|
} |
||||
|
.item-info { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
padding: 4px 0; |
||||
|
font-size: 14px; |
||||
|
width:100%; |
||||
|
.label { |
||||
|
color: #666; |
||||
|
width: 72px; |
||||
|
} |
||||
|
.value { |
||||
|
color: #333; |
||||
|
flex: 1; |
||||
|
text-align: right; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.btn-box { |
||||
|
width: 100%; |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
margin-top: 10px; |
||||
|
padding-top: 10px; |
||||
|
border-top: 1px solid #e5e5e5; |
||||
|
} |
||||
|
|
||||
|
.status-tag { |
||||
|
padding: 2px 8px; |
||||
|
border-radius: 4px; |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
.status-tag.status-0 { |
||||
|
color: #01a4fe; |
||||
|
background: #e6f7ff; |
||||
|
} |
||||
|
.status-tag.status-1 { |
||||
|
color: #00b42a; |
||||
|
background: #e6ffed; |
||||
|
} |
||||
|
.status-tag.status-2 { |
||||
|
color: #999; |
||||
|
background: #f5f5f5; |
||||
|
} |
||||
|
|
||||
|
/* 👉 插槽外层容器:占满高度,垂直水平居中 */ |
||||
|
.swipe-right-wrap { |
||||
|
width: 80px; |
||||
|
height: calc(100% - 20px); |
||||
|
display: flex; |
||||
|
align-items: center; /* 垂直居中 */ |
||||
|
justify-content: center; /*水平居中*/ |
||||
|
// background-color: #f5222d; |
||||
|
} |
||||
|
|
||||
|
/* 圆形按钮,不再写height:100%,固定大小做圆圈 */ |
||||
|
.swipe-btn { |
||||
|
width: 48px; |
||||
|
height: 48px; |
||||
|
border-radius: 50%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
color: #ffffff !important; |
||||
|
} |
||||
|
|
||||
|
.swipe-btn-delete { |
||||
|
background-color: #f5222d; |
||||
|
} |
||||
|
|
||||
|
/* 深度修改uni-icons图标颜色,scoped必须加 ::v‑deep */ |
||||
|
::v-deep .swipe-btn .uni-icons { |
||||
|
color: #ffffff !important; |
||||
|
} |
||||
|
|
||||
|
</style> |
||||
@ -0,0 +1,241 @@ |
|||||
|
<template> |
||||
|
<view class="seat-booking"> |
||||
|
<!-- 顶部横幅 --> |
||||
|
<view class="banner"> |
||||
|
<image class="banner-bg" src="@/static/images/mingqi-beij@2x.png" mode="aspectFill"></image> |
||||
|
<view class="banner-overlay"> |
||||
|
<text class="banner-text">葛店经济开发区图书馆预约</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="content"> |
||||
|
<!-- 场馆选择下拉框 --> |
||||
|
<!-- <view class="venue-select"> |
||||
|
<picker :value="venueIndex" :range="venues" @change="onVenueChange"> |
||||
|
<view class="picker-content"> |
||||
|
<text>{{ venues[venueIndex] }}</text> |
||||
|
<uni-icons type="down" size="16" color="#666" /> |
||||
|
</view> |
||||
|
</picker> |
||||
|
</view> --> |
||||
|
|
||||
|
<!-- 楼层/区域卡片列表 --> |
||||
|
<view class="floor-list"> |
||||
|
<view class="floor-item" v-for="floor in floorList" :key="floor.id"> |
||||
|
<text class="floor-name">{{ floor.floor }}</text> |
||||
|
<div class="floor-info"> |
||||
|
<view class="floor-left"> |
||||
|
<text class="floor-title">{{ floor.title }}</text> |
||||
|
<image class="banner-bg" src="@/static/images/lib.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
<view class="floor-right"> |
||||
|
<text class="floor-desc">{{ floor.desc }}</text> |
||||
|
<view style="display: flex; justify-content: flex-end; width: 100%; text-align: end;"> |
||||
|
<button class="booking-btn" @click="bookingFloor(floor)">预约</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</div> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
data() { |
||||
|
return { |
||||
|
venueIndex: 0, |
||||
|
venues: ['所有场馆', '东馆', '西馆', '南馆'], |
||||
|
floorList: [ |
||||
|
{ |
||||
|
id: 1, |
||||
|
floor: '3楼', |
||||
|
title: '综合阅览一', |
||||
|
desc: '葛店图书馆三楼阅读广场共有464个座位,为读者提供备电源,读者可预约选择心仪的座位。区域采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
}, |
||||
|
{ |
||||
|
id: 2, |
||||
|
floor: '3楼', |
||||
|
title: '少儿阅览室', |
||||
|
desc: '少儿阅览室共有464个座位,为读者提供备电源、读者可自助选择位置,各个区采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
}, |
||||
|
{ |
||||
|
id: 3, |
||||
|
floor: '3楼', |
||||
|
title: '专题阅览室', |
||||
|
desc: '专题阅览室共有464个座位,为读者提供备电源、读者可自助选择位置,各个区采光良好,环境优美,读者可在休息时一览楼下的风景。', |
||||
|
image: '@/static/images/lib.png' |
||||
|
} |
||||
|
] |
||||
|
}; |
||||
|
}, |
||||
|
onLoad() { |
||||
|
this.loadSeatInfo(); |
||||
|
}, |
||||
|
methods: { |
||||
|
loadSeatInfo() { |
||||
|
console.log('加载座位信息'); |
||||
|
}, |
||||
|
onVenueChange(e) { |
||||
|
this.venueIndex = e.detail.value; |
||||
|
console.log('切换场馆:', this.venues[this.venueIndex]); |
||||
|
}, |
||||
|
bookingFloor(floor) { |
||||
|
uni.navigateTo({ |
||||
|
url: `/subpkg/pages/booking-detail/booking-detail?floor=${floor.floor}&title=${floor.title}` |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.seat-booking { |
||||
|
min-height: 100vh; |
||||
|
background-color: #f5f7fa; |
||||
|
} |
||||
|
|
||||
|
/* 顶部横幅 */ |
||||
|
.banner { |
||||
|
position: relative; |
||||
|
height: 140px; |
||||
|
} |
||||
|
.banner-bg { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
.banner-overlay { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.2); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
.banner-text { |
||||
|
color: #fff; |
||||
|
font-size: 20px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
padding: 16px; |
||||
|
// margin-top: -20px; |
||||
|
position: relative; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
|
||||
|
/* 场馆选择下拉框 */ |
||||
|
.venue-select { |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
.picker-content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 4px; |
||||
|
padding: 8px 16px; |
||||
|
background-color: #fff; |
||||
|
border: 1px solid #ddd; |
||||
|
border-radius: 4px; |
||||
|
font-size: 14px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
/* 楼层卡片 */ |
||||
|
.floor-list { |
||||
|
background-color: #fff; |
||||
|
border-radius: 12px; |
||||
|
padding: 16px; |
||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.05); |
||||
|
} |
||||
|
.floor-item { |
||||
|
margin-bottom: 16px; |
||||
|
padding-bottom: 16px; |
||||
|
border-bottom: 1px solid #eee; |
||||
|
&:last-child { |
||||
|
margin-bottom: 0; |
||||
|
padding-bottom: 0; |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.floor-name { |
||||
|
display: block; |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
padding-bottom: 8px; |
||||
|
} |
||||
|
.floor-info{ |
||||
|
display: inline-flex; |
||||
|
align-items: flex-start; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.floor-left { |
||||
|
position: relative; |
||||
|
width: 90px; |
||||
|
height: 100px; |
||||
|
border-radius: 8px; |
||||
|
margin-right: 12px; |
||||
|
} |
||||
|
|
||||
|
.floor-image { |
||||
|
width: 90px; |
||||
|
height: 100px; |
||||
|
|
||||
|
object-fit: cover; |
||||
|
} |
||||
|
.floor-title { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
text-align: center; |
||||
|
padding: 4px 0; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
color: #fff; |
||||
|
// font-weight: bold; |
||||
|
font-size: 12px; |
||||
|
// font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.floor-right { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.floor-desc { |
||||
|
font-size: 13px; |
||||
|
color: #666; |
||||
|
line-height: 1.5; |
||||
|
margin-bottom: 8px; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp: 3; |
||||
|
} |
||||
|
.booking-btn { |
||||
|
background-color: #01a4fe; |
||||
|
color: #fff; |
||||
|
font-size: 14px; |
||||
|
padding: 0 20px; |
||||
|
border: none; |
||||
|
margin: 6px 0 0 0; |
||||
|
height: 30px; |
||||
|
line-height: 30px; |
||||
|
} |
||||
|
.booking-btn::after { |
||||
|
border: none; |
||||
|
} |
||||
|
</style> |
||||
@ -1,8 +1,8 @@ |
|||||
const config = { |
const config = { |
||||
// 本地
|
// 本地
|
||||
// baseUrl: 'http://192.168.99.63:14000',
|
|
||||
|
baseUrl: 'http://192.168.99.63:14000', |
||||
// 线上
|
// 线上
|
||||
baseUrl: 'https://wechatapi.aiyxlib.com', |
|
||||
|
// baseUrl: 'https://wechatapi.aiyxlib.com',
|
||||
LIB_CODE: '1201' |
LIB_CODE: '1201' |
||||
}; |
}; |
||||
|
|
||||
|
|||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue