0) {
this.likeClick();
}
},
/**点赞 */
likeClick() {
const image = "./images-v2/" + this.getRandomInt(1, 13) + ".png";
const anmationData = {
id: new Date().getTime(),
timer: 0,
opacity: 0.5,
pathData: this.generatePathData(),
image: image,
factor: {
speed: 0.4, // 运动速度,值越小越慢
t: 0 // 贝塞尔函数系数
}
};
if (Object.keys(queue).length > 0) {
queue[anmationData.id] = anmationData;
} else {
queue[anmationData.id] = anmationData;
this.bubbleAnimate();
}
},
/**获取最大最小随机值 */
getRandom(min, max) {
return Math.random() * (max - min) + min;
},
/**获取最大最小之前随机值的整数 */
getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
/**获取图片路径 */
generatePathData() {
let width = this.data.width,
height = this.data.height;
const p0 = {
x: 0.65 * width,
y: height
};
const p1 = {
x: this.getRandom(0.22 * width, 0.33 * width),
y: this.getRandom(0.5 * height, 0.75 * height)
};
const p2 = {
x: this.getRandom(0, 0.88 * width),
y: this.getRandom(0.25 * height, 0.5 * height)
};
const p3 = {
x: this.getRandom(0, 0.88 * width),
y: this.getRandom(0, 0.125 * height)
};
return [p0, p1, p2, p3];
},
/**更新图片的最新运动路径 */
updatePath(data, factor) {
const p0 = data[0];
const p1 = data[1];
const p2 = data[2];
const p3 = data[3];
const t = factor.t;
/*计算多项式系数 (下同)*/
const cx1 = 3 * (p1.x - p0.x);
const bx1 = 3 * (p2.x - p1.x) - cx1;
const ax1 = p3.x - p0.x - cx1 - bx1;
const cy1 = 3 * (p1.y - p0.y);
const by1 = 3 * (p2.y - p1.y) - cy1;
const ay1 = p3.y - p0.y - cy1 - by1;
const x = ax1 * (t * t * t) + bx1 * (t * t) + cx1 * t + p0.x;
const y = ay1 * (t * t * t) + by1 * (t * t) + cy1 * t + p0.y;
return {
x,
y
};
},
/**点赞动画 */
bubbleAnimate() {
let width = this.data.width,
height = this.data.height;
Object.keys(queue).forEach(key => {
const anmationData = queue[+key];
const {
x,
y
} = this.updatePath(
anmationData.pathData,
anmationData.factor
);
const speed = anmationData.factor.speed;
anmationData.factor.t += speed;
var curWidth = 30;
curWidth = (height - y) / 1.5;
curWidth = Math.min(30, curWidth);
var curAlpha = anmationData.opacity;
curAlpha = y / height;
curAlpha = Math.min(1, curAlpha);
ctx.globalAlpha = curAlpha;
ctx.drawImage(anmationData.image, x - curWidth / 2, y, curWidth, curWidth);
if (anmationData.factor.t > 1) {
delete queue[anmationData.id];
}
if (y > height) {
delete queue[anmationData.id];
}
});
ctx.draw();
if (Object.keys(queue).length > 0) {
timer = setTimeout(() => {
this.bubbleAnimate();
}, 5);
} else {
clearTimeout(timer);
ctx.draw(); // 清空画面
}
}
},
ready() {
ctx = wx.createCanvasContext("bubble", this);
queue = {};
},
detached() {
if (timer) {
clearTimeout(timer);
}
}
});
================================================
FILE: packageStreamMedia/components/like-dz/like-dz.json
================================================
{
"component": true,
"usingComponents": {}
}
================================================
FILE: packageStreamMedia/components/like-dz/like-dz.wxml
================================================
================================================
FILE: packageStreamMedia/components/like-dz/like-dz.wxss
================================================
.like-fx {
position: absolute;
right: 0;
bottom: 140rpx;
pointer-events: none;
z-index: 9999999;
}
================================================
FILE: packageStreamMedia/pages/live-anchor/index.js
================================================
const app = getApp()
const CONFIG = require('../../../config.js')
const WXAPI = require('apifm-wxapi')
// websocket 第一步
let socketOpen = false
let socketMsgQueue = []
let that;
Page({
/**
* 页面的初始数据
*/
data: {
beauty: 0, // 美颜,取值范围 0-9 ,0 表示关闭
onlineNumber: 1, // 在线人数
barrageList: [], // 用户聊天记录
focus: false,
firstTap: false,
goodsList: [],
pageIndex: 1,
pageSize: 10,
hasMore: true,
showGoodsInfo: false,
showEmpty: false, // 是否展示缺省提示
ids: '', // 已经选中的商品id
online_people: '', // 观看人数
pusherUrl: "",
roomId: undefined,
showSetInfo: false,
},
// 某人加入房间、离开房间
showTips(avatarurl, msg) {
this.setData({
showTips: true,
showTipsAvatarUrl: avatarurl,
showTipsMsg: msg
})
if (!this.data.focus) {
this.setScrollTop();
}
setTimeout(() => {
this.setData({
showTips: false
})
}, 3000);
},
setScrollTop() {
var query = wx.createSelectorQuery(),
e = that;
wx.createSelectorQuery().in(e).select('.barrage').boundingClientRect(function (res) {
console.log(res)
e.setData({
chatbottom: res.bottom,
})
}).exec()
query.in(e).select('.item-outer').boundingClientRect(function (res) {
if (res.bottom > e.data.chatbottom) {
let temp = Math.ceil(parseInt(res.bottom) - parseInt(e.data.chatbottom))
e.setData({
scrollTop: temp // 如此保证scrollTop的值 让滚动条一直滚动到最后 9999 开发工具可以设置为辞职 苹果真机不行
})
}
}).exec()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// options.id = 13
this.data.id = options.id
// 读取自定义头高度
const systemInfo = wx.getSystemInfoSync()
const custom = wx.getMenuButtonBoundingClientRect()
this.setData({
systemInfo,
customBarHeight: custom.bottom + custom.top - systemInfo.statusBarHeight
})
this.getUserInfo()
this.myLiveRoomsInfo()
this.initWebSocket()
// 设置屏幕常亮 兼容ios
wx.setKeepScreenOn({
keepScreenOn: true
})
// 设置屏幕亮度 0-1范围 设置了 用户自己去设置调节屏幕的亮度
// wx.setScreenBrightness({ value: .6 })
this.ctx = wx.createLivePusherContext('pusher')
let query = wx.createSelectorQuery()
query.select('.barrage').boundingClientRect(function (rect) {
// console.log(rect)
}).exec();
},
// 主推商品详情
async toDetail(e) {
const id = e.currentTarget.dataset.id
const res = await WXAPI.goodsDetail(id, wx.getStorageSync('token'))
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
if (res.data.basicInfo.supplyType == 'cps_jd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-jd?id=${id}`,
})
} else if (res.data.basicInfo.supplyType == 'cps_pdd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-pdd?id=${id}`,
})
} else if (res.data.basicInfo.supplyType == 'cps_taobao') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-taobao?id=${id}`,
})
} else if (res.data.basicInfo.supplyType == 'vop_jd') {
wx.navigateTo({
url: `/pages/goods-details/vop?id=${res.data.basicInfo.yyId}&goodsId=${res.data.basicInfo.id}`,
})
} else {
wx.navigateTo({
url: `/pages/goods-details/index?id=${id}`,
})
}
},
preventDefault() {
return;
},
bindInput(e) {
this.setData({
inputVal: e.detail.value
})
},
/**
* 发送弹幕问题
*/
onComment() {
const inputVal = this.data.inputVal
if (!inputVal) {
wx.showToast({
title: '内容不能为空',
icon: 'none'
})
return;
}
this.sendSocketMessage(inputVal)
this.setData({
inputVal: '',
showInput: false
})
},
handleInteractionTap() {
let data = this.data
let temp;
if (!data.showInput) {
temp = data.fullScreenHeight - 50
} else {
temp = app.globalData.screenH
}
this.setData({
//showInput: !this.data.showInput,
fullScreenHeight: temp,
showInput: true,
focus: true
})
},
navCart() {
let url = `/pages/cart/cart`
wx.navigateTo({
url
})
},
// 设置为主推商品
async navPurchase(e) {
const mainlyGoods = this.data.liveRoomsInfo.goodsList[e.currentTarget.dataset.idx]
this.sendSocketMessage('act:mainlyGoods:' + mainlyGoods.id)
const res = await WXAPI.liveRoomGoodsMainly({
token: wx.getStorageSync('token'),
roomId: this.data.id,
goodsId: mainlyGoods.id
})
},
hideGoods() {
this.setData({
showGoodsInfo: false,
showInput: false
})
},
hidePeoples() { //隐藏人员信息
console.log(1);
this.hideGoods();
this.setData({
showPeopleInfo: false
})
},
hideSet() {
this.setData({
showSetInfo: false
})
},
async showPeoples() { //显示直播间人员
wx.showLoading({
title: '',
})
const res = await WXAPI.liveRoomOnlineUsers(wx.getStorageSync('token'), this.data.id)
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
this.setData({
showPeopleInfo: false,
peoplelist: null
})
} else {
this.setData({
showPeopleInfo: true,
peoplelist: res.data
})
}
},
lahei(e) { //拉黑用户
let uid = e.currentTarget.dataset.uid
const that = this
wx.showModal({
title: '确认拉黑',
content: '拉黑会强制该用户退出直播间',
success(res) {
if (res.confirm) {
//console.log('用户点击确定')
wx.showLoading({
title: '加载中',
})
WXAPI.liveRoomKickOutUser(wx.getStorageSync('token'), that.data.id, uid).then(res => {
that.showPeoples();
})
} else if (res.cancel) {
//console.log('用户点击取消')
}
}
})
},
showGoods() {
let data = this.data
if (!data.firstTap) {
this.setData({
firstTap: true
})
}
this.setData({
showGoodsInfo: true,
showEmpty: true,
})
},
onReady(res) {
this.ctx = wx.createLivePusherContext('pusher')
},
// 旋转相机
rotateTap() {
this.ctx.switchCamera({
success: res => {
console.log('switchCamera success')
},
fail: res => {
console.log('switchCamera fail')
}
})
},
backTap() {
this.ctx.pause()
wx.navigateBack()
},
exit() {
wx.showModal({
title: '提示',
content: '确定结束本场直播吗?',
success: res => {
if (res.confirm) {
this.ctx.stop({
success: res => {
console.log('stop success')
},
fail: res => {
console.log('stop fail')
}
})
wx.navigateBack({
delta: 2
})
app.closeSocket()
}
}
})
},
onUnload() {
wx.onSocketClose(res => {
console.log('WebSocket 已关闭!')
})
},
onShow() { //进入页面链接
console.log("app.globalData.socketStatus", app.globalData.socketStatus);
if (app.globalData.socketStatus == 'closed') {
// websocket方式
app.openSocket(this.data.roomId, this, "author")
}
},
// 主播分享自己的直播间
onShareAppMessage: function () {
return {
title: '快来我的直播间看看吧~',
imageUrl: this.data.liveRoomsInfo.roomInfo.coverImage,
path: `/packageStreamMedia/pages/live-client/client?id=${this.data.id}`
}
},
async getUserInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
apiUserInfoMap: res.data
})
}
},
showBeautySelect() {
this.setData({
showSelect09: true
})
},
select09(e) {
const num = e.currentTarget.dataset.num
this.setData({
beauty: num,
showSelect09: false
})
},
async myLiveRoomsInfo() {
const res = await WXAPI.myLiveRoomsInfo(wx.getStorageSync('token'), this.data.id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
wx.navigateBack()
return
}
let mainlyGoods = null
if (res.data.mainlyGoodsId) {
mainlyGoods = res.data.goodsList.find(ele => {
return ele.id == res.data.mainlyGoodsId
})
}
this.setData({
liveRoomsInfo: res.data,
mainlyGoods
})
},
bindstatechange(e) {
console.log(e);
},
// webscoket 第二步, 增加下面方法
connectSocket() {
wx.connectSocket({
url: 'wss://api.it120.cc/websocket/liveRoom/' + this.data.id + '/' + wx.getStorageSync('token')
})
},
initWebSocket() {
this.connectSocket()
wx.onSocketOpen(res => {
console.log(res);
socketOpen = true
for (let i = 0; i < socketMsgQueue.length; i++){
sendSocketMessage(socketMsgQueue[i])
}
socketMsgQueue = []
})
wx.onSocketClose(res => {
console.log(res);
// 关闭,重连
socketOpen = false
if (res.code == 1004 && res.reason == 'kickOut') {
wx.reLaunch({
url: '/pages/index/index'
})
return
}
wx.showToast({
title: res.code + ':' + res.reason,
icon: 'none'
})
setTimeout(() => {
this.connectSocket()
}, 3000);
})
wx.onSocketMessage(res => {
// 接收服务器推送的消息
if (res.code != 0) {
wx.showToast({
title: resJson.msg,
icon: 'none'
})
return
}
const resJson = JSON.parse(res.data)
this.processSocketMessage(resJson.data)
})
},
sendSocketMessage(msg) {
// 向 websocket 发送消息
if (socketOpen) {
wx.sendSocketMessage({
data: msg
})
} else {
socketMsgQueue.push(msg)
}
},
processSocketMessage(res) {
// 接收到服务器推送到消息
console.log(res)
if (res.act == 'onlineNumber') {
this.setData({
onlineNumber: res.data
})
}
if (res.act == 'userComing') {
this.showTips(res.avatarUrl, `${res.nick}进入直播间`)
}
if (res.act == 'msg') {
if (res.msg.indexOf('act:mainlyGoods:') == 0) {
const goodsId = res.msg.replace('act:mainlyGoods:', '')
console.log(goodsId);
const mainlyGoods = this.data.liveRoomsInfo.goodsList.find(ele => {
return ele.id == goodsId
})
this.setData({
mainlyGoods
})
return
}
if (res.msg == 'act:like') {
return
}
const barrageList = this.data.barrageList
barrageList.push({
nick: res.nick,
avatarUrl: res.avatarUrl,
msg: res.msg,
color: this.getRandomFontColor()
})
this.setData({
barrageList: barrageList.length > 100 ? barrageList.slice(50) : barrageList
})
if (this.data.focus) {
return
}
this.setScrollTop();
}
},
getRandomFontColor() {
// 随机颜色
let red = Math.floor(Math.random() * 266);
let green = Math.floor(Math.random() * 266);
let blue = Math.floor(Math.random() * 266);
return 'rgb(' + red + ',' + green + ' , ' + blue + ')'
},
})
================================================
FILE: packageStreamMedia/pages/live-anchor/index.json
================================================
{
"usingComponents": {},
"disableScroll": true,
"navigationStyle": "custom"
}
================================================
FILE: packageStreamMedia/pages/live-anchor/index.wxml
================================================
{{ apiUserInfoMap.base.nick }}
房间号: {{ liveRoomsInfo.roomInfo.id }}
在线人数: {{ onlineNumber }}
{{ showTipsMsg }}
{{ item.nick }}
{{ item.msg}}
全部人员
{{ item.nick }}
{{ item.ip }}
{{ item.ip }}
全部商品
{{ item.name }}
¥{{ item.minPrice }}
暂无商品~
{{ item }}
================================================
FILE: packageStreamMedia/pages/live-anchor/index.wxss
================================================
page {
height: 100%;
overflow: hidden;
}
.watcher {
color: greenyellow;
font-weight: 600;
margin-top: 15rpx;
text-align: right;
font-size: 24rpx;
padding-right: 50rpx;
}
.tips {
position: absolute;
top: 598rpx;
left: 0;
width: 80%;
height: 66rpx;
line-height: 66rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border-radius: 0 33rpx 33rpx 0;
color: #fff;
font-size: 24rpx;
background: #ef7471;
opacity: 0.4;
padding: 0 24rpx;
display: flex;
align-items: center;
}
.tips .avatar-img {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
margin-right: 10rpx;
}
live-player {
z-index: 99999;
position: relative;
}
.outer {
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
.outer .back {
width: 140rpx;
position: relative;
}
.outer .back .icon {
position: absolute;
left: 24rpx;
bottom: 8rpx;
width: 50rpx;
height: 50rpx;
background: rgba(0, 0, 0, 0.3);
border: 1rpx solid rgba(204, 204, 204, 1);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.outer .back .icon .back-icon {
transform: scale(0.6);
}
.outer .anchor-info {
margin-top: 50rpx;
padding: 0 30rpx;
height: 70rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.outer .anchor-info .left {
height: 100%;
width: auto;
display: flex;
align-items: center;
background: rgba(0, 0, 0, 0.3);
border-radius: 34rpx;
}
.outer .anchor-info .left .avatar {
width: 58rpx;
height: 58rpx;
border-radius: 50%;
margin-left: 6rpx;
}
.outer .anchor-info .left .mid {
display: flex;
flex-direction: column;
font-size: 24rpx;
color: #fff;
margin-left: 6rpx;
margin-right: 14rpx;
}
.outer .anchor-info .left .ops {
border-radius: 25rpx;
margin-right: 6rpx;
display: flex;
align-items: center;
}
.outer .anchor-info .left .ops .c-img {
transform: scale(0.6);
}
.outer .anchor-info .left .follow .add {
width: 40rpx;
height: 40rpx;
margin-left: 6rpx;
margin-right: 10rpx;
}
.outer .anchor-info .left .follow .txt {
font-size: 30rpx;
color: #fff;
}
.outer .anchor-info .right {
min-width: 174rpx;
height: 40rpx;
border-radius: 20rpx;
background: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
}
.outer .anchor-info .right .txt {
font-size: 24rpx;
color: #fff;
margin-left: 15rpx;
padding: 0 10rpx;
}
.outer .footer {
position: absolute;
bottom: 20rpx;
right: 24rpx;
left: 24rpx;
height: auto;
min-height: 100rpx;
display: flex;
align-items: center;
}
.outer .footer .item0 {
display: flex;
flex-direction: column;
align-items: center;
padding: 10rpx;
}
.outer .footer .item0 .goods {
width: 70rpx;
height: 70rpx;
}
.outer .footer .item0 .txt {
font-size: 24rpx;
color: #fff;
margin-top: 8rpx;
}
.outer .footer .item1 {
width: 400rpx;
height: 70rpx;
background: rgba(0, 0, 0, 0.3);
border-radius: 34rpx;
margin: 0 30rpx 0 30rpx;
display: flex;
align-items: center;
}
.outer .footer .item1 .cmt-icon {
width: 30rpx;
height: 30rpx;
margin: 0 20rpx;
}
.outer .footer .item1 .txt {
color: #fff;
font-size: 28rpx;
}
.outer .footer .item2 {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 12rpx;
}
.outer .footer .item2 .icon-wrap {
width: 70rpx;
height: 70rpx;
background: rgba(0, 0, 0, 0);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.outer .footer .item2 .icon-wrap .icons {
width: 36rpx;
height: 36rpx;
}
.outer .footer .item2 .txt {
font-size: 24rpx;
color: #fff;
margin-top: 8rpx;
}
.outer .barrage {
position: absolute;
width: 500rpx;
height: 500rpx;
bottom: 140rpx;
overflow-y: scroll;
background: transparent;
}
.outer .barrage .barrage-item {
padding: 5rpx 20rpx;
border-radius: 10rpx;
}
.outer .barrage .barrage-item .item-wrap {
border-radius: 15rpx;
display: inline-block;
padding: 6rpx;
background: rgba(0, 0, 0, 0.3);
}
.outer .barrage .barrage-item .item-wrap .avatar {
width: 46rpx;
height: 46rpx;
display: inline-block;
margin-right: 4rpx;
border-radius: 50%;
vertical-align: middle;
}
.outer .barrage .barrage-item .item-wrap .item-nickname {
max-width: 200rpx;
position: relative;
max-width: 150rpx;
overflow: hidden;
display: inline-block;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
.outer .barrage .barrage-item .item-wrap .item-words {
width:450rpx;
display: inline-block;
margin-left: 15rpx;
word-break: break-all;
white-space: nowrap;
color: #fff;
font-size: 26rpx;
overflow-x: scroll;
vertical-align: middle;
text-overflow:ellipsis;
word-wrap:break-word;
white-space:pre-wrap;
}
.send-barrage {
z-index: 99999;
position: absolute;
left: 0;
bottom: 0;
height: 50px;
line-height: 50px;
border: 1px solid #ccc;
width: 70%;
box-sizing: border-box;
padding: 0 8rpx;
}
.send-btn {
position: fixed;
z-index: 9999;
bottom: 0;
right: 0;
height: 50px;
line-height: 50px;
background: #010101;
color: #ffeab7;
font-size: 32rpx;
width: 30%;
text-align: center;
}
.hover-class {
color: #dfdfdf;
}
.goods-list {
position: absolute;
z-index: 99999;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.9);
border-radius: 10rpx 10rpx 0 0;
height: 900rpx;
overflow: hidden;
}
.goods-list .goods-empty {
position: absolute;
right: 0;
left: 0;
top: 300rpx;
z-index: 99999;
line-height: 100rpx;
text-align: center;
color: #888;
font-size: 26rpx;
}
.open {
transition: all 0.3s ease-out;
transform: translateY(0);
}
.close {
transition: all 0.3s ease-out;
transform: translateY(900rpx);
}
.left-input {
width: 12%;
z-index: 9999;
position: absolute;
left: 0;
bottom: 2rpx;
background: #fff;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.left-input .icon {
width: 30rpx;
height: 30rpx;
}
.line-wrap {
position: absolute;
z-index: 9999;
left: 11%;
bottom: 2rpx;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
height: 50px;
}
.line-wrap .line-icon {
width: 1px;
height: 50rpx;
}
.send-barrage {
z-index: 9999;
position: absolute;
left: 12%;
bottom: 2rpx;
height: 50px;
line-height: 50px;
width: 88%;
box-sizing: border-box;
padding: 0 8rpx;
background: #fff;
color: 28rpx;
border: 0;
outline: 0;
}
.send-btn {
position: absolute;
z-index: 9999;
bottom: 2rpx;
right: 0;
height: 50px;
line-height: 50px;
font-size: 32rpx;
width: 20%;
text-align: center;
background: #b25f4a;
color: #fff;
}
.hover-class {
color: #dfdfdf;
}
.goods-list .title {
padding: 0 24rpx;
position: absolute;
left: 0;
top: 32rpx;
right: 0;
min-height: 68rpx;
border-bottom: 1rpx solid #ccc;
}
.goods-list .item-list {
margin: 100rpx 24rpx 0;
overflow-y: scroll;
max-height: 900rpx;
}
.goods-list .item-list .item {
padding: 20rpx 0;
border-bottom: 1rpx solid #ccc;
position: relative;
}
.goods-list .item-list .item .goods-img {
width: 110rpx;
height: 110rpx;
border-radius: 10rpx;
margin-right: 15rpx;
}
.goods-list .item-list .item .info {
flex-direction: column;
justify-content: space-between;
padding: 10rpx 0;
}
.goods-list .item-list .item .info .price {
font-size: 28rpx;
}
.goods-list .item-list .item .info .goods-title {
width: 360rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods-list .item-list .item .btn {
position: absolute;
right: 0;
bottom: 10rpx;
width: 120rpx;
height: 50rpx;
font-size: 26rpx;
border-radius: 60rpx;
line-height: 50rpx;
background: #ff605a;
color: #fff;
}
.main-goods {
position: absolute;
top: 260rpx;
left: 24rpx;
z-index: 99;
}
.beauty-select {
position: absolute;
top: 300rpx;
left: 25rpx;
width: 700rpx;
display: flex;
justify-content: space-between;
z-index: 99999;
}
.beauty-select .item {
width: 64rpx;
height: 64rpx;
line-height: 64rpx;
text-align: center;
background: rgba(0, 0, 0, 0.3);
color: #fff;
border-radius: 50%;
}
================================================
FILE: packageStreamMedia/pages/live-anchor/list.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
this.myLiveRooms()
},
onShow: function () {
},
async myLiveRooms() {
const res = await WXAPI.myLiveRooms({
token: wx.getStorageSync('token')
})
if (res.code == 0) {
this.setData({
liveRooms: res.data.result
})
}
},
stop(e) {
wx.showModal({
title: '提示',
content: '确定结束本场直播吗?',
success: res => {
if (res.confirm) {
this._stop(e)
}
}
})
},
async _stop(e) {
const id = e.currentTarget.dataset.id
const res = await WXAPI.stopLiveRoom(wx.getStorageSync('token'), id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
this.myLiveRooms()
},
})
================================================
FILE: packageStreamMedia/pages/live-anchor/list.json
================================================
{
"navigationBarTitleText": "我的直播间"
}
================================================
FILE: packageStreamMedia/pages/live-anchor/list.wxml
================================================
结束本场直播
================================================
FILE: packageStreamMedia/pages/live-anchor/list.wxss
================================================
.coverImage {
width: 100vw;
}
.btn-group {
padding: 0 16rpx;
text-align: right;
}
================================================
FILE: packageStreamMedia/pages/live-client/client.js
================================================
const WXAPI = require('apifm-wxapi')
// websocket 第一步
let socketOpen = false
let socketMsgQueue = []
Page({
/**
* 页面的初始数据
*/
data: {
viewNumber: 0, // 观看人数
likeNumber: 0, // 点赞数量
follow: true,
inputVal: '',
userId: '', // 用户id
groupId: null, // 群id
playUrl: '', // 拉流地址
barrageList: [], // 用户聊天记录
showInput: false, // 是否显示输入框
focus: false,
goodsList: [],
pageIndex: 1,
pageSize: 10,
hasMore: true,
showGoodsInfo: false,
firstTap: false,
showEmpty: false, // 是否展示缺省提示
nickname: '', // 当前用户昵称
scrollTop: '', // 设置cover-view 设置顶部滚动的偏移量
online: '',
showTips: false, // 是否显示某个人加入进入直播间
online_people: '', // 观看人数
anchor_cover: '', // 主播封面
roomId:undefined,
intoRoomStatus:true
},
// 通知主播已经下线
showWarningOffAndExit() {
wx.showModal({
title: '提示',
content: '主播已经离开了~,下次再见,拜拜!',
showCancel: false,
confirmText: '我知道了',
confirmColor: '#FE6889',
success: res => {
if (res.confirm) {
wx.navigateBack()
}
}
})
},
// 通知被主播拉黑下线
lahei() {
wx.showToast({
title: '系统异常,强制退出直播间',
icon: 'none',
duration: 2000
})
setTimeout(function(){
wx.switchTab({
url : "/pages/index/index"
})
},3000);
},
// 某人加入房间
showTips(avatarurl, msg) {
this.setData({
showTips: true,
showTipsAvatarUrl: avatarurl,
showTipsMsg: msg
})
if (!this.data.focus) {
this.setScrollTop();
}
setTimeout(() => {
this.setData({
showTips: false
})
}, 3000);
},
setScrollTop() {
var query = wx.createSelectorQuery();
wx.createSelectorQuery().in(this).select('.barrage').boundingClientRect(res => {
console.log(res)
this.setData({
chatbottom: res.bottom,
})
}).exec()
query.in(this).select('.item-outer').boundingClientRect(res => {
if (res.bottom > this.data.chatbottom) {
let temp = Math.ceil(parseInt(res.bottom) - parseInt(e.data.chatbottom))
this.setData({
scrollTop: temp // 如此保证scrollTop的值 让滚动条一直滚动到最后 9999 开发工具可以设置为辞职 苹果真机不行
})
}
}).exec()
},
onLoad: function(options) {
// options.id = 15
this.data.id = options.id
// 读取自定义头高度
const systemInfo = wx.getSystemInfoSync()
const custom = wx.getMenuButtonBoundingClientRect()
this.setData({
systemInfo,
customBarHeight: custom.bottom + custom.top - systemInfo.statusBarHeight
})
//获取直播信息 主播信息
this.getLiveInfo()
this.initWebSocket()
// 设置屏幕常亮
wx.setKeepScreenOn({ keepScreenOn: true })
let query = wx.createSelectorQuery()
query.select('.barrage').boundingClientRect(function(rect) {
console.log(rect)
}).exec();
},
// 主推商品详情
async toDetail(e) {
const id = e.currentTarget.dataset.id
const res = await WXAPI.goodsDetail(id, wx.getStorageSync('token'))
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
if (res.data.basicInfo.supplyType == 'cps_jd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-jd?id=${id}`,
})
} else if (res.data.basicInfo.supplyType == 'vop_jd') {
wx.navigateTo({
url: `/pages/goods-details/vop?id=${res.data.basicInfo.yyId}&goodsId=${res.data.basicInfo.id}`,
})
} else if (res.data.basicInfo.supplyType == 'cps_pdd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-pdd?id=${id}`,
})
} else if (res.data.basicInfo.supplyType == 'cps_taobao') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-taobao?id=${id}`,
})
} else {
wx.navigateTo({
url: `/pages/goods-details/index?id=${id}`,
})
}
},
async handleLikeClick() {
await WXAPI.likeLiveRoom(wx.getStorageSync('token'), this.data.id)
this.sendSocketMessage('act:like')
},
preventDefault(e) {
return;
},
getUserInfo() {
let token = wx.getStorageSync('token')
return
api.get({
url: '/wxsmall/User/getUserInfo',
data: {
token,
},
success: res => {
console.log(res)
let {
nickname,
avatar
} = res.data
this.setData({
nickname,
avatar
})
}
})
},
hideGoods() {
// // 防止连续点击--开始
// if (this.data.payButtonClicked) {
// wx.showToast({
// title: '休息一下~',
// icon: 'none'
// })
// return
// }
// this.data.payButtonClicked = true
// setTimeout(() => {
// this.data.payButtonClicked = false
// }, 1500) // 可自行修改时间间隔(目前是3秒内只能点击一次支付按钮)
// // 防止连续点击--结束
this.setData({
showGoodsInfo: false,
showInput: false,
focus:false
})
},
showGoods() {
let data = this.data
if (!data.firstTap) {
this.getGoodsList()
this.setData({
firstTap: true
})
}
this.setData({ showGoodsInfo: true, showEmpty:true, })
},
async getGoodsList() {
wx.showLoading({
title: '加载中',
})
// https://www.yuque.com/apifm/nu0f75/wg5t98
const res = await WXAPI.goodsv2()
// console.log(res.data);
wx.hideLoading()
if (res.code == 0) {
if(res.data.length==0){
this.setData({
showEmpty: true
})
}else{
this.setData({
goodsList: res.data.result,
showEmpty: false
})
}
}
},
async getLiveInfo() {
const res = await WXAPI.liveRoomsInfo(wx.getStorageSync('token'), this.data.id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
wx.navigateBack()
return
}
let mainlyGoods = null
if (res.data.mainlyGoodsId) {
mainlyGoods = res.data.goodsList.find(ele => {
return ele.id == res.data.mainlyGoodsId
})
}
this.setData({
liveRoomsInfo: res.data,
viewNumber: res.data.roomInfo.viewNumber,
likeNumber: res.data.roomInfo.likeNumber,
mainlyGoods,
follow: true
})
// TODO follow true / false
},
/**
* 发送弹幕问题
*/
onComment() {
const inputVal = this.data.inputVal
if (!inputVal) {
wx.showToast({
title: '内容不能为空',
icon: 'none'
})
return;
}
this.sendSocketMessage(inputVal)
this.setData({
inputVal: '',
showInput: false
})
},
bindInput(e) {
this.setData({
inputVal: e.detail.value
})
},
handleInteractionTap() {
// 防止连续点击--开始
if (this.data.payButtonClicked) {
wx.showToast({
title: '慢点~',
icon: 'none'
})
return
}
this.data.payButtonClicked = true
setTimeout(() => {
this.data.payButtonClicked = false
}, 1500) // 可自行修改时间间隔(目前是3秒内只能点击一次按钮)
// 防止连续点击--结束
let data = this.data
let temp;
if (!data.showInput) {
temp = data.fullScreenHeight - 50
} else {
temp = app.globalData.screenH
}
this.setData({
//showInput: !this.data.showInput,
fullScreenHeight: temp,
showInput: true,
focus: true
})
},
followTap() {
var that = this
wx.request({
url: CONFIG.HTTP_REQUEST_URL+"customerConcern",
data: {
roomId:that.data.info.id,
userOpenId:wx.getStorageSync('openid'),
status:1
},
method: "GET",
header: {
'Content-Type': 'application/json;charset=utf-8 '
},
success: function (res2) {
console.log("followTap",res2);
if(res2.data.code==500){
wx.showToast({
title: res2.data.message,
duration: 1500,
icon: 'none',
mask: true,
})
return
}
wx.showToast({
title: '已关注',
icon: 'none'
})
that.setData({
follow: true
})
},
})
},
onReady(res) {
this.ctx = wx.createLivePlayerContext('player')
},
statechange(e) {
console.log('live-player code:', e.detail.code)
},
error(e) {
console.error('live-player error:', e.detail.errMsg)
},
onShow() {//进入页面链接
},
backTap() {
wx.navigateBack()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
return {
title: '快来我的直播间看看吧~',
imageUrl: this.data.liveRoomsInfo.roomInfo.coverImage,
path: `/packageStreamMedia/pages/live-client/client?id=${this.data.id}`
}
},
// webscoket 第二步, 增加下面方法
connectSocket() {
wx.connectSocket({
url: 'wss://api.it120.cc/websocket/liveRoom/' + this.data.id + '/' + wx.getStorageSync('token')
})
},
initWebSocket() {
this.connectSocket()
wx.onSocketOpen(res => {
console.log(res);
socketOpen = true
for (let i = 0; i < socketMsgQueue.length; i++){
sendSocketMessage(socketMsgQueue[i])
}
socketMsgQueue = []
})
wx.onSocketClose(res => {
console.log(res);
// 关闭,重连
socketOpen = false
if (res.code == 1004 && res.reason == 'kickOut') {
wx.reLaunch({
url: '/pages/index/index'
})
return
}
wx.showToast({
title: res.code + ':' + res.reason,
icon: 'none'
})
setTimeout(() => {
this.connectSocket()
}, 3000);
})
wx.onSocketMessage(res => {
// 接收服务器推送的消息
if (res.code != 0) {
wx.showToast({
title: resJson.msg,
icon: 'none'
})
return
}
const resJson = JSON.parse(res.data)
this.processSocketMessage(resJson.data)
})
},
sendSocketMessage(msg) {
// 向 websocket 发送消息
if (socketOpen) {
wx.sendSocketMessage({
data: msg
})
} else {
socketMsgQueue.push(msg)
}
},
processSocketMessage(res) {
// 接收到服务器推送到消息
console.log(res)
if (res.act == 'onlineNumber') {
this.setData({
onlineNumber: res.data
})
}
if (res.act == 'userComing') {
this.setData({
viewNumber: this.data.viewNumber + 1
})
this.showTips(res.avatarUrl, `${res.nick}进入直播间`)
}
if (res.act == 'msg') {
if (res.msg.indexOf('act:mainlyGoods:') == 0) {
const goodsId = res.msg.replace('act:mainlyGoods:', '')
console.log(goodsId);
const mainlyGoods = this.data.liveRoomsInfo.goodsList.find(ele => {
return ele.id == goodsId
})
this.setData({
mainlyGoods
})
return
}
if (res.msg == 'act:like') {
this.setData({
likeNumber: this.data.likeNumber + 1
})
return
}
const barrageList = this.data.barrageList
barrageList.push({
nick: res.nick,
avatarUrl: res.avatarUrl,
msg: res.msg,
color: this.getRandomFontColor()
})
this.setData({
barrageList: barrageList.length > 100 ? barrageList.slice(50) : barrageList
})
if (this.data.focus) {
return
}
this.setScrollTop();
}
},
getRandomFontColor() {
// 随机颜色
let red = Math.floor(Math.random() * 266);
let green = Math.floor(Math.random() * 266);
let blue = Math.floor(Math.random() * 266);
return 'rgb(' + red + ',' + green + ' , ' + blue + ')'
},
})
================================================
FILE: packageStreamMedia/pages/live-client/client.json
================================================
{
"navigationStyle": "custom",
"usingComponents": {
"like-dz":"../../components/like-dz/like-dz"
},
"disableScroll": true
}
================================================
FILE: packageStreamMedia/pages/live-client/client.wxml
================================================
{{ liveRoomsInfo.anchor.nick }}
房间号: {{ liveRoomsInfo.roomInfo.id }}
观看人数: {{ viewNumber }}
{{ showTipsMsg }}
{{ item.nick }}
{{ item.msg}}
{{ likeNumber }}
全部商品
{{ item.name }}
¥{{ item.minPrice }}
暂无商品~
================================================
FILE: packageStreamMedia/pages/live-client/client.wxss
================================================
page {
height: 100%;
overflow: hidden;
}
.watcher {
color: #fff;
margin-top: 15rpx;
text-align: right;
font-size: 20rpx;
padding-right: 50rpx;
}
.tips {
position: absolute;
top: 598rpx;
left: 0;
width: 80%;
height: 66rpx;
line-height: 66rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
border-radius: 0 33rpx 33rpx 0;
color: #fff;
font-size: 24rpx;
background: #EF7471;
opacity: .4;
padding: 0 24rpx;
display: flex;
align-items: center;
}
.tips .avatar-img {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
margin-right: 10rpx;
}
live-player {
z-index: 99;
position: relative;
}
.outer {
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
.outer .back {
width: 140rpx;
position: relative;
}
.outer .back .icon {
position: absolute;
left: 24rpx;
bottom: 8rpx;
width: 50rpx;
height: 50rpx;
background: rgba(0, 0, 0, 0.3);
border: 1rpx solid rgba(204, 204, 204, 1);
border-radius: 50%;
}
.outer .back .icon .back-icon {
transform: scale(0.6);
}
.outer .anchor-info {
margin-top: 50rpx;
padding: 0 30rpx;
height: 70rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.outer .anchor-info .left {
height: 100%;
width: auto;
display: flex;
align-items: center;
background: rgba(0, 0, 0, 0.3);
border-radius: 34rpx;
/* min-width: 300rpx; */
}
.outer .anchor-info .left .avatar {
width: 58rpx;
height: 58rpx;
border-radius: 50%;
margin-left: 6rpx;
}
.outer .anchor-info .left .mid {
display: flex;
flex-direction: column;
font-size: 24rpx;
color: #fff;
margin-left: 6rpx;
margin-right: 14rpx;
overflow: hidden;
}
.outer .anchor-info .left .mid .nickname {
max-width: 180rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.outer .anchor-info .left .follow {
width: 128rpx;
height: 50rpx;
border-radius: 25rpx;
margin-right: 6rpx;
display: flex;
align-items: center;
padding: 0 12rpx 0 2rpx;
background: linear-gradient(90deg, rgba(254, 104, 137, 1), rgba(255, 121, 108, 1));
background: rgba(254, 104, 137, 1);
}
.outer .anchor-info .left .follow .add {
width: 22rpx;
height: 22rpx;
margin-left: 6rpx;
margin-right: 10rpx;
}
.outer .anchor-info .left .follow .txt {
font-size: 30rpx;
color: #fff;
}
.follow-icon-wrap {
display: flex;
justify-content: center;
align-items: center;
width: 40rpx;
height: 40rpx;
background: #fff;
border-radius: 50%;
margin-right: 10rpx;
margin-left: 4rpx;
}
.outer .anchor-info .right {
min-width: 174rpx;
height: 40rpx;
border-radius: 20rpx;
background: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
}
.outer .anchor-info .right .txt {
font-size: 24rpx;
color: #fff;
margin-left: 15rpx;
}
.outer .footer {
position: absolute;
bottom: 20rpx;
right: 24rpx;
left: 24rpx;
height: auto;
min-height: 100rpx;
display: flex;
align-items: center;
background: transparent;
}
.outer .footer .item0 {
display: flex;
flex-direction: column;
align-items: center;
}
.outer .footer .item0 .goods {
width: 70rpx;
height: 70rpx;
}
.outer .footer .item0 .txt {
font-size: 24rpx;
color: #fff;
margin-top: 8rpx;
}
.outer .footer .item1 {
width: 400rpx;
height: 70rpx;
background: rgba(0, 0, 0, 0.3);
border-radius: 34rpx;
margin: 0 30rpx 0 30rpx;
display: flex;
align-items: center;
}
.outer .footer .item1 .cmt-icon {
width: 30rpx;
height: 30rpx;
margin: 0 20rpx;
}
.outer .footer .item1 .txt {
color: #fff;
font-size: 28rpx;
}
.outer .footer .item2 {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 12rpx;
}
.outer .footer .item2 .icon-wrap {
width: 70rpx;
height: 70rpx;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.3);
}
.outer .footer .item2 .icon-wrap .icons {
width: 36rpx;
height: 36rpx;
}
.outer .footer .item2 .txt {
font-size: 24rpx;
color: #fff;
margin-top: 8rpx;
}
.outer .barrage {
position: absolute;
width: 520rpx;
height: 500rpx;
bottom: 140rpx;
overflow-y: scroll;
background: transparent;
/* background: green; */
}
.outer .barrage .barrage-item {
padding: 5rpx 20rpx;
border-radius: 10rpx;
}
.outer .barrage .barrage-item .item-wrap {
border-radius: 15rpx;
display: inline-block;
padding: 6rpx;
background: rgba(0, 0, 0, 0.3);
}
.outer .barrage .barrage-item .item-wrap .avatar {
width: 46rpx;
height: 46rpx;
display: inline-block;
margin-right: 4rpx;
border-radius: 50%;
vertical-align: middle;
}
.outer .barrage .barrage-item .item-wrap .item-nickname {
max-width: 86rpx;
overflow: hidden;
display: inline-block;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
position: relative;
}
.outer .barrage .barrage-item .item-wrap .item-words {
width:450rpx;
display: inline-block;
margin-left: 15rpx;
word-break: break-all;
white-space: nowrap;
color: #fff;
overflow-x: scroll;
vertical-align: middle;
font-size: 26rpx;
text-overflow:ellipsis;
word-wrap:break-word;
white-space:pre-wrap;
}
.left-input {
width: 12%;
z-index: 9999;
position: absolute;
left: 0;
bottom: 2rpx;
background: #fff;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
}
.left-input .icon {
width: 30rpx;
height: 30rpx;
}
.line-wrap {
position: absolute;
z-index: 9999;
left: 11%;
bottom: 2rpx;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
height: 50px;
}
.line-wrap .line-icon {
width: 1px;
height: 50rpx;
}
.send-barrage {
z-index: 9999;
position: absolute;
left: 12%;
bottom: 2rpx;
height: 50px;
line-height: 50px;
width: 88%;
box-sizing: border-box;
padding: 0 8rpx;
background: #fff;
color: 28rpx;
}
.send-btn {
position: absolute;
z-index: 9999;
bottom: 2rpx;
right: 0;
height: 50px;
line-height: 50px;
font-size: 32rpx;
width: 20%;
text-align: center;
background: #b25f4a;
color: #fff;
}
.hover-class {
color: #dfdfdf;
}
.goods-list {
position: absolute;
z-index: 99999;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.9);
border-radius: 10rpx 10rpx 0 0;
height: 900rpx;
overflow: hidden;
}
.goods-list .goods-empty {
position: absolute;
right: 0;
left: 0;
top: 300rpx;
z-index: 99999;
line-height: 100rpx;
text-align: center;
color: #888;
font-size: 26rpx;
}
.open {
transition: all 0.3s ease-out;
transform: translateY(0);
}
.close {
transition: all 0.3s ease-out;
transform: translateY(900rpx);
}
.goods-list .title {
padding: 0 24rpx;
position: absolute;
left: 0;
top: 32rpx;
right: 0;
min-height: 68rpx;
border-bottom: 1rpx solid #ccc;
}
.goods-list .title .img {
width: 59rpx;
height: 53rpx;
}
.goods-list .item-list {
margin: 100rpx 24rpx 0;
overflow-y: scroll;
max-height: 900rpx;
}
.goods-list .item-list .item {
padding: 20rpx 0;
border-bottom: 1rpx solid #ccc;
position: relative;
}
.goods-list .item-list .item .goods-img {
width: 180rpx;
height: 180rpx;
border-radius: 10rpx;
margin-right: 15rpx;
}
.goods-list .item-list .item .info {
flex-direction: column;
justify-content: space-between;
padding: 10rpx 0;
}
.goods-list .item-list .item .info .price {
color: #ff605a;
font-size: 30rpx;
}
.goods-list .item-list .item .info .goods-title {
width: 360rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods-list .item-list .item .btn {
position: absolute;
right: 0;
bottom: 10rpx;
width: 120rpx;
height: 50rpx;
font-size: 26rpx;
border-radius: 60rpx;
line-height: 50rpx;
background: #ff605a;
color: #fff;
}
.like-box {
position: absolute;
right: 40rpx;
padding: 0 15rpx;
height: 40rpx;
line-height: 40rpx;
border-radius: 20rpx;
bottom: 118rpx;
font-size: 20rpx;
background: #f34861;
color: #fff;
}
.main-goods {
position: absolute;
top: 260rpx;
left: 24rpx;
z-index: 99;
}
================================================
FILE: packageStreamMedia/pages/live-client/list.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
page: 1, // 读取第几页数据
navIndex: 0,
liveList: [],
hasMore: true,
reload: false,
indicatorDots: false,
vertical: false,
autoplay: true,
interval: 3000,
duration: 500,
circular: true,
showEmpty: false,
cateList: [ // 直播分类
{
id: 1,
name: '精选'
}, {
id: 2,
name: '全部'
}
],
cate_id: 1,
navList: [{
type: 1,
iconPath: '../../images/live/nav01.png',
title: '入驻主播'
},
{
type: 2,
iconPath: '../../images/live/nav02.png',
title: '入驻经纪人'
},
{
type: 3,
iconPath: '../../images/live/nav03.png',
title: '入驻服务商'
},
{
type: 4,
iconPath: '../../images/live/nav04.png',
title: '入驻合伙人'
}
],
flashList: [], // 幻灯片
swiperCurIndex: 1,
left: 100,
showjoo: 1,
isCustom: true
},
async banners() {
//获取轮播
const bannerRes = await WXAPI.banners({
type: 'livelist'
})
this.setData({
flashList: bannerRes.data
})
},
onLoad: function(option) {
this.banners()
this.queryLiveRoomInfo()
},
onShow() {
},
bindChange(e) {
let current = e.detail.current
this.setData({
swiperCurIndex: current + 1
})
},
/**
* 首页导航
*/
tapItem(e) {
wx.showModal({
title: '提示',
content: '线上申请未开放,请联系客服申请入驻!',
success (res) {
if (res.confirm) {
//console.log('用户点击确定')
} else if (res.cancel) {
//console.log('用户点击取消')
}
}
})
return
let url = ''
let {
type
} = e.currentTarget.dataset
let {
userType,
live_status,
reason
} = app.globalData
// console.log('用户当前身份类型' + userType)
// console.log('想要申请类型' + type)
// console.log('申请状态' + live_status)
// console.log('如果被驳回的原因是' + reason)
// 申请入驻的条件为 入驻身份不能低于或等于当前身份
if (userType >= type) {
$api.msg('入驻身份不能低于当前身份')
return;
}
if (live_status == 1 || (live_status == 0 && reason)) { // 入驻主播正在申请中
url = `/packageB/pages/apply-status/index?status=${live_status}&reason=${reason}`
} else {
url = `/packageB/pages/apply-live/apply-live?type=${type}`
}
wx.navigateTo({
url
})
},
// 点击幻灯片去直播间
toLive(e) {
return
let {
id
} = e.currentTarget.dataset
console.log(id)
if (id == 0) return
let like;
let url;
setTimeout(() => {
wx.navigateTo({
url: `/pages/live-detail/live-detail?number=${id}&url=${encodeURIComponent(url)}&like=${like}`,
})
}, 200)
},
navDetail(e) {
let status = e.currentTarget.dataset.status;
let id = e.currentTarget.dataset.id;
if(status != 1){
wx.showToast({
title: '未开播,敬请期待',
icon: 'none'
})
return
}
wx.navigateTo({
url: '/pages/live-client/client?id=' + id
})
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
this.setData({
reload: true,
hasMore: true,
page: 1
})
this.queryLiveRoomInfo()
wx.stopPullDownRefresh()
},
// 导航切换
navTap(e) {
let temp = e.currentTarget.dataset
let navIndex = temp.index
let id = temp.id
if (navIndex == this.data.navIndex) return
let cate_id = ''
if (id) {
cate_id = id
}
this.setData({
navIndex,
reload: true,
page: 1,
hasMore: true,
cate_id:cate_id,
scrollLeft: navIndex * 50
})
this.queryLiveRoomInfo()
},
// 获取直播列表
async queryLiveRoomInfo(){
const res = await WXAPI.liveRooms({
page: this.data.page
})
if (res.code == 700) {
this.setData({
loading: false,
liveList: null,
hasMore: false
})
}
if (res.code == 0) {
const anchorMap = res.data.anchorMap
res.data.result.forEach(ele => {
if (anchorMap) {
ele.anchor = anchorMap[ele.uid]
}
})
this.setData({
loading: false,
liveList:res.data.result,
hasMore: res.data.totalPage > this.data.page ? true : false
})
}
},
getRandomNumber() {
let number = Math.floor(Math.random() * 15000)
return number
},
onReachBottom() {
const hasMore = this.data.hasMore
if(hasMore) {
this.data.page++
this.queryLiveRoomInfo()
}
},
})
================================================
FILE: packageStreamMedia/pages/live-client/list.json
================================================
{
"enablePullDownRefresh": true,
"navigationBarTitleText": "直播中心"
}
================================================
FILE: packageStreamMedia/pages/live-client/list.wxml
================================================
{{ item.title }}
{{ item.statusStr }}
{{ item.name }}
加载中...
没有更多~
================================================
FILE: packageStreamMedia/pages/live-client/list.wxss
================================================
.sort {
display: flex;
flex-direction: column;
align-items: center;
}
.sort-img {
width: 47rpx;
height: 47rpx;
}
.sort-txt {
color: #fff;
font-size: 22rpx;
}
.search {
margin-left: 24rpx;
}
.header {
background-color: #fff;
padding: 20rpx 24rpx;
align-items: center;
}
.header .header-left {
flex: 1;
align-items: center;
}
.header .header-left .store-name {
margin: 0 2rpx 0 15rpx;
max-width: 560rpx;
font-size: 30rpx;
}
.icon-store {
color: #f8b303;
font-size: 34rpx;
}
.icon-search {
font-size: 32rpx;
color: rgba(88, 88, 88, 1);
}
.icon-forward {
font-size: 30rpx;
}
/* Swiper */
.outer-wrap {
position: relative;
}
.outer-wrap .cus-indicator {
display: flex;
position: absolute;
left: 50%;
bottom: 16rpx;
transform: translateX(-50%);
}
.outer-wrap .cus-indicator .item {
width: 12rpx;
height: 12rpx;
background: rgba(255, 255, 255, 1);
border-radius: 50%;
margin-right: 15rpx;
}
.outer-wrap .cus-indicator .item.ac {
width: 42rpx;
height: 12rpx;
border-radius: 6rpx;
background: #ff605a;
}
.swiper {
height: 300rpx;
}
.swiper-item {
display: flex;
justify-content: center;
align-items: center;
}
.swiper-item image {
width: 100%;
height: 300rpx;
}
.swiper-index {
position: absolute;
right: 20rpx;
bottom: 15rpx;
min-width: 80rpx;
height: 40rpx;
font-size: 24rpx;
background: rgba(0, 0, 0, 0.2);
border-radius: 20rpx;
padding: 0 6rpx;
color: #fff;
text-align: center;
line-height: 40rpx;
}
/* categories */
.cates-wrap {
padding: 20rpx 0 0 0;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
background-color: #fff;
min-height: 340rpx;
}
.cates-wrap .item {
width: calc(100%/4);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 28rpx;
color: #484848;
}
.cates-wrap .item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 26rpx;
color: #484848;
padding-bottom: 27rpx;
}
.img-box {
width: 100rpx !important;
height: 100rpx !important;
}
.seckill-img-box {
width: 224rpx !important;
height: 185rpx !important;
}
/* categories ends */
/* find-service starts */
.find-service-wrapper {
margin-top: 10rpx;
background-color: #fff;
min-height: 220rpx;
padding: 0 24rpx;
}
.find-service-wrapper .service-item {
position: relative;
width: 166rpx;
height: 115rpx;
}
.find-service-wrapper .service-item .img-item {
border-radius: 6rpx;
}
.find-service-wrapper .service-item .text-item {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
text-align: center;
transform: translate(-50%, -50%);
color: #fff;
font-size: 25rpx;
z-index: 999;
}
.service-mask {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
position: absolute;
left: 0;
top: 0;
opacity: 0.8;
z-index: 99;
border-radius: 6rpx;
}
/* find-service ends */
/* 列表的公共头部 */
.same-style-header-wrap {
padding: 30rpx 36rpx 30rpx 24rpx;
position: relative;
}
.same-style-header-wrap .same-left {
font-size: 32rpx;
color: #101010;
font-weight: bold;
margin-left: 12rpx;
}
.same-style-header-wrap .same-right {
font-size: 24rpx;
color: rgba(181, 181, 181, 1);
}
.same-style-header-wrap .bundle {
position: absolute;
width: 6rpx;
height: 38%;
left: 18rpx;
top: 50%;
transform: translateY(-50%);
background: #ff3931;
}
/* 列表的公共头部ends */
/* 秒杀专区 */
.seckill-wrapper, .worth-wrapper {
margin-top: 10rpx;
background-color: #fff;
}
.content-wrap {
padding: 30rpx;
}
.content-wrap>.item {
flex: 1;
height: 320rpx;
padding: 0 0 38rpx;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.content-wrap>.item>.img-box {
width: 140rpx;
height: auto;
}
.content-wrap>.item .status {
height: 48rpx;
line-height: 48rpx;
border-radius: 24rpx;
padding: 0 40rpx;
background-color: #d4d2d3;
color: #fff;
}
.content-wrap>.item:nth-child(1) {
background-color: #efedee;
}
.content-wrap>.item:nth-child(2) {
background-color: #f2e6ea;
margin: 0 15rpx;
}
.content-wrap>.item:nth-child(3) {
background-color: #faf3eb;
}
.available {
background: #fe678b !important;
color: #fff !important;
}
/* 秒杀专区ends */
/* 广告 */
.adv {
width: 100%;
height: 203rpx;
}
/* 广告ends */
/* 新品上架 */
.new-wrapper {
background-color: #fff;
}
.content-wrap_new {
flex-wrap: wrap;
}
.content-wrap_new .item_new {
width: 50%;
box-sizing: border-box;
display: flex;
padding: 18rpx 0 25rpx;
flex-direction: column;
align-items: center;
height: auto;
}
.content-wrap_new .item_new .img-box_new {
height: 300rpx;
width: 300rpx;
display: block;
margin: 0 auto;
}
.content-wrap_new .item_new .img-box_new > image {
border-radius: 15rpx;
}
.content-wrap_new .item_new .desc-wrap {
margin-top: 10rpx;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.content-wrap_new .item_new .desc-wrap .title {
padding: 0 20rpx;
}
.content-wrap_new .item_new {
border-bottom: 2px solid #f1f1f1;
}
.content-wrap_new .item_new:nth-child(1),
.content-wrap_new .item_new:nth-child(2) {
padding-top: 0;
}
.new-sign-wrap {
position: absolute;
left: 0;
top: 10rpx;
width: 100rpx;
height: 40rpx;
background: #f2f3f7;
}
/* 新品上架ends */
/* 超值拼团 */
.content-wrap_worth {
background-color: #f4f4f4;
width: 100%;
}
.content-wrap_worth .inner {
margin: 32rpx 30rpx 0;
width: 100%;
}
.content-wrap_worth .inner .top, .content-wrap_worth .inner .bot {
margin-bottom: 28rpx;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.item_worth {
background-color: #fff;
padding: 18rpx 30rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
}
.item_worth .price-wrap {
margin: 15rpx 0;
}
.img-box_worth {
width: 274rpx;
height: 310rpx;
margin-bottom: 5px;
}
.out {
background: #d4d2d3 !important;
}
.together {
height: 50rpx;
width: 200rpx;
margin: 0 auto;
line-height: 50rpx;
text-align: center;
color: #fff;
background: #454648;
font-size: 24rpx;
}
/* 超值拼团ends */
/* 一件套餐包 */
.one-key-combo-wrapper {
background-color: #fff;
}
.one-key-combo-wrapper .combo-wrap {
padding: 22rpx 19rpx 37rpx 19rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.relative {
position: relative;
}
.combo-title {
position: absolute;
height: 40rpx;
line-height: 40rpx;
text-align: center;
color: #fff;
background: rgba(0, 0, 0, 0.4);
padding: 0 20rpx;
border-radius: 20rpx;
top: 20rpx;
left: 20rpx;
font-size: 20rpx;
}
.title-21 {
top: 53rpx;
left: 8rpx;
}
.title-02 {
background: rgba(0, 0, 0, 0);
left: 49rpx;
top: 53rpx;
color: #ab8394;
}
.title-22 {
background: rgba(0, 0, 0, 0);
left: 14rpx;
top: 53rpx;
color: #a3a3a3;
}
.title-20 {
color: #ab9d8a;
}
.title-23 {
left: 18rpx;
top: 53rpx;
}
.title-10 {
color: #8387a8;
}
.title-11 {
left: 130rpx;
top: 20rpx;
}
.combo-top {
display: flex;
justify-content: space-between;
}
.combo-top .top-item:nth-child(1) {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.combo-top .top-item:nth-child(1) > .item:nth-child(1) {
width: 460rpx;
height: 271rpx;
}
.combo-top .top-item:nth-child(1) > .item:nth-child(2) {
display: flex;
justify-content: space-between;
}
.combo-top .top-item:nth-child(1) > .item:nth-child(2) .sub-item:nth-child(1) {
width: 225rpx;
height: 141rpx;
}
.combo-top .top-item:nth-child(1) > .item:nth-child(2) .sub-item:nth-child(2) {
width: 225rpx;
height: 141rpx;
}
.combo-top .top-item:nth-child(2) {
width: 252rpx;
margin-left: 10rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.combo-top .top-item:nth-child(2) > .item:nth-child(1) {
width: 252rpx;
height: 158rpx;
background: rgba(210, 213, 237, 1);
}
.combo-top .top-item:nth-child(2) > .item:nth-child(2) {
margin-top: 10rpx;
width: 252rpx;
height: 253rpx;
}
.combo-bot {
margin-top: 10rpx;
display: flex;
justify-content: space-around;
align-items: center;
}
.combo-wrap .combo-bot .bot-item:nth-child(1) {
width: 264rpx;
height: 150rpx;
}
.combo-wrap .combo-bot .bot-item:nth-child(2) {
width: 141rpx;
height: 150rpx;
}
.combo-wrap .combo-bot .bot-item:nth-child(3) {
width: 141rpx;
height: 150rpx;
background: rgba(229, 229, 229, 1);
}
.combo-wrap .combo-bot .bot-item:nth-child(4) {
width: 141rpx;
height: 150rpx;
}
/* 一件套餐包ends */
/* 全屋设计 */
.whole-house-wrapper {
margin-top: 10rpx;
background-color: #fff;
}
.design-wrap {
border-bottom: 0.5px solid #ccc;
padding: 30rpx;
position: relative;
}
.design-wrap .top_design {
height: 62rpx;
}
.design-wrap .top_design .avatar-box-wrap {
height: 62rpx;
display: flex;
align-items: center;
}
.design-wrap .top_design .avatar-box {
height: 100%;
width: 62rpx;
margin-right: 10rpx;
}
.design-wrap .top_design .desinger-box {
width: 98rpx;
height: 32rpx;
}
.area-status {
display: flex;
justify-content: center;
align-items: center;
}
.area-item {
height: 42rpx;
line-height: 42rpx;
border-radius: 21rpx;
text-align: center;
background-color: #f5f5f5;
padding: 0 30rpx;
font-size: 28rpx;
}
.area-item:nth-child(1) {
margin-right: 10rpx;
}
.display, .display-diff {
margin-top: 30rpx;
margin-bottom: 30rpx;
}
.display-item {
flex: 1;
height: 183rpx;
border-radius: 10rpx;
}
.display-item:nth-child(2) {
margin: 0 10rpx;
}
.simple-desc {
width: 510rpx;
font-size: 28rpx;
color: #a5a5a5;
min-height: 30rpx;
}
.want {
width: 150rpx;
padding: 14rpx 0;
border-radius: 10rpx;
background-color: #454648;
color: #fff;
position: absolute;
bottom: 10rpx;
right: 30rpx;
text-align: center;
font-size: 28rpx;
}
.display-diff-item {
flex: 1;
height: 274rpx;
margin-left: 20rpx;
}
.display-diff-item image {
border-radius: 10rpx;
}
.diff {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.diff-item {
height: 48%;
width: 100%;
}
.diff-s {
display: flex;
justify-content: space-between;
align-items: center;
}
.diff-s-item {
width: 48%;
height: 100%;
}
/* 全屋设计ends */
.margin-top {
margin-top: 10rpx;
background-color: #fff;
}
/* 推荐品牌 */
.recommend-brand-wrapper {
background-color: #fff;
}
.recommend-brand-wrapper .brands-wrap {
padding: 48rpx 25rpx 30rpx;
justify-content: space-between;
flex-wrap: wrap;
}
.recommend-brand-wrapper .brands-wrap .brand-item {
width: 30%;
height: 100rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
box-sizing: border-box;
border: 1px solid #ddd;
}
/* 推荐品牌ends */
/* 设计圈 */
.design-circle-wrapper {
margin-top: 10rpx;
background-color: #fff;
}
.goods-list-wrap .item {
display: flex;
padding: 24rpx 28rpx 23rpx;
border-bottom: 0.5px solid #ededed;
margin-bottom: 30rpx;
}
.goods-list-wrap .item .img-wrap {
flex: 0 0 185rpx;
height: 185rpx;
position: relative;
margin-right: 30rpx;
border-radius: 10rpx;
}
.goods-list-wrap .item .img-wrap > .img-circle {
width: 100%;
height: 100%;
border-radius: 10rpx;
}
.goods-list-wrap .item .img-wrap .rank {
width: 40rpx;
height: 50rpx;
position: absolute;
top: 0;
left: 10rpx;
}
.goods-list-wrap .item .detail {
padding: 12rpx 0;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.date {
font-size: 24rpx;
color: #bbb;
}
.goods-list-wrap .item .detail .name {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
font-size: 30rpx;
}
.goods-list-wrap .item .detail .desc {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
font-size: 24rpx;
color: #707070;
}
/* 设计圈ends */
/* 以下是暂时不要的 */
.wrapper {
margin-top: 10rpx;
background-color: #fff;
}
.content-wrap {
padding: 20rpx 25rpx;
height: 360rpx;
}
.bundle {
width: 2px;
height: 30rpx;
background-color: #f8b303;
margin-right: 20rpx;
}
.c-color {
color: #ccc;
font-size: 28rpx;
}
.goods-wrap {
margin-top: 20rpx;
}
.top-goods-wrap {
border: 1px solid #ddd;
height: 190rpx;
box-sizing: border-box;
background-color: #f7f7f7;
}
.info {
width: 40%;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 18rpx;
font-size: 28rpx;
height: 100%;
}
.img {
flex-grow: 1;
padding: 14rpx 30rpx 14rpx 0;
}
.bot-goods-wrap {
margin-top: 10rpx;
}
.bot-goods-wrap .item {
width: 49.5%;
height: 190rpx;
background-color: #f7fbfb;
border: 1px solid #ddd;
box-sizing: border-box;
}
.img-2 {
padding: 50rpx 20rpx;
}
.work-wrap {
margin-top: 12rpx;
}
.work-img-box {
position: relative;
width: 100%;
height: 270rpx;
}
.work-name {
padding: 24rpx 0;
font-size: 28rpx;
}
.work-style {
color: #999;
font-size: 26rpx;
}
.work-master-wrap {
position: absolute;
right: 20rpx;
bottom: -82rpx;
height: 128rpx;
z-index: 999;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.avatar-box {
height: 80rpx;
width: 80rpx;
border-radius: 50%;
border: 1px solid #f8b303;
}
.avatar-box > image {
border-radius: 50%;
}
.f-size {
font-size: 24rpx;
}
.scroll-view_H {
white-space: nowrap;
}
.scroll-view-item_H {
display: inline-block;
/* height: 300rpx; */
width: 220rpx;
margin-right: 20rpx;
}
.scroll-view-item_H image {
border-radius: 10rpx;
}
.selected {
padding: 40rpx 10rpx;
border: 1px solid #f8b303;
background-color: #fefefe;
border-radius: 10rpx;
}
.detail-box {
font-size: 26rpx;
}
.detail-box .pro-name {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.detail-box > view {
text-align: center;
}
.empty {
text-align: center;
padding: 10rpx;
color: #ccc;
font-size: 28rpx;
}
.pri-orange {
color: #e2631c;
font-size: 30rpx;
font-weight: bold;
margin-top: 10rpx;
}
.new-c {
color: #ff605a;
}
.group-goods-name {
width: 274rpx;
}
/*---------------------------------------*/
page {
background: #f5f5f5;
}
.web-view-bg {
background: transparent;
background: red;
}
.white-bg {
background: #fff;
}
.back-bone {
width: 100%;
position: relative;
padding: 20rpx 24rpx 0 24rpx;
background: #fff;
box-sizing: border-box;
}
.back-bone .index-nav {
display: flex;
justify-content: space-around;
align-items: center;
padding: 40rpx 0;
}
.back-bone .index-nav .nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
.back-bone .index-nav .nav-item > image {
width: 69rpx;
height: 72rpx;
margin-bottom: 23rpx;
}
.back-bone .index-nav .nav-item > .txt {
font-size: 24rpx;
color: #7c7c7c;
}
.back-bone .swiper-wrap {
position: relative;
}
.back-bone .swiper-wrap swiper {
position: relative;
border-radius: 30rpx;
height: 322rpx;
}
.back-bone .swiper-wrap .cus-indicator {
display: flex;
position: absolute;
left: 50%;
bottom: 16rpx;
transform: translateX(-50%);
}
.back-bone .swiper-wrap .cus-indicator .item {
width: 12rpx;
height: 12rpx;
background: rgba(255, 255, 255, 1);
border-radius: 50%;
margin-right: 15rpx;
}
.back-bone .swiper-wrap .cus-indicator .item.ac {
width: 42rpx;
height: 12rpx;
border-radius: 6rpx;
background: #FF605A;
}
.back-bone .swiper-wrap swiper swiper-item {
border-radius: 30rpx;
}
.back-bone .swiper-wrap swiper swiper-item > image {
width: 100%;
height: 100%;
border-radius: 30rpx;
}
.nav {
padding: 0rpx 24rpx 20rpx;
}
.nav .scroll-view-H {
width: 100%;
white-space: nowrap;
}
.nav .scroll-view-H .nav-item {
position: relative;
padding-bottom: 8rpx;
margin-right: 30rpx;
min-width: 72rpx;
padding: 10rpx 15rpx;
display: inline-block;
color: #888;
}
.nav .scroll-view-H .nav-item .row-bundle {
position: absolute;
left: 50%;
bottom: 0;
width: 32rpx;
height: 4rpx;
border-radius: 2rpx;
transform: translate(-50%);
background: #ff605a;
}
.nav .nav-item .nav-actived {
font-size: 36rpx;
color: #ff605a;
font-weight: 600;
}
.live-list {
padding: 0 24rpx;
flex-wrap: wrap;
}
.item-wrap {
width: 100%;
border-radius: 20rpx;
margin-bottom: 30rpx;
}
.item-wrap .live-title {
background: white;
border-radius: 0 0 20rpx 20rpx;
padding: 20rpx;
}
.item-wrap .live-title .real-content {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
font-size: 26rpx;
height: 70rpx;
}
.live-list .live-item {
position: relative;
width: 100%;
height: 456rpx;
}
.live-list .live-item .cover {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border-radius: 20rpx 20rpx 0 0;
}
.live-list .live-item .people {
display: flex;
font-size: 20rpx;
align-items: center;
height: 40rpx;
border-radius: 0 20rpx 0 20rpx;
position: absolute;
right: 0;
background: rgba(0, 0, 0, 0.3);
color: #fff;
padding-right: 10rpx;
max-width: 400rpx;
overflow: hidden;
}
.live-list .live-item .people > image {
width: 20rpx;
height: 20rpx;
margin-left: 14rpx;
margin-right: 6rpx;
}
.live-list .live-item .foot {
position: absolute;
bottom: 20rpx;
left: 10rpx;
right: 10rpx;
}
.live-list .live-item .foot .left {
display: flex;
align-items: center;
}
.live-list .live-item .foot .left > image {
border-radius: 30rpx;
}
.live-list .live-item .foot .left .txt {
font-size: 28rpx;
color: #fff;
margin-left: 8rpx;
max-width: 184rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.live-list .live-item .foot .right {
display: flex;
align-items: center;
}
.live-list .live-item .foot .right .txt {
color: #fff;
font-size: 28rpx;
}
.live-list .live-item .foot .right > image {
width: 40rpx;
height: 40rpx;
margin-right: 14rpx;
}
.live-list .live-item .foot .left > image {
width: 50rpx;
height: 50rpx;
}
.live-list .live-item .status {
position: absolute;
top: 18rpx;
right: 18rpx;
width: 120rpx;
height: 36rpx;
line-height: 36rpx;
border-radius: 18rpx;
font-size: 26rpx;
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
.live {
background: linear-gradient(90deg, rgba(255, 212, 73, 1), rgba(248, 179, 3, 1));
}
.not-live {
background: linear-gradient(90deg, rgba(231, 230, 230, 1), rgba(189, 190, 190, 1));
}
.live-list .live-item .status > image {
width: 14rpx;
height: 14rpx;
}
.live-list .live-item .status .txt {
font-size: 24rpx;
margin-left: 6rpx;
}
.empty {
line-height: 100rpx;
color: #888;
font-size: 28rpx;
position: absolute;
left: 0;
right: 0;
top: 800rpx;
text-align: center;
}
.loadmore {
color: #888;
font-size: 30rpx;
line-height: 100rpx;
text-align: center;
width: 100%;
}
.loadmore.loading::before {
content: '';
width: 40rpx;
height: 40rpx;
margin-top: -10rpx;
margin-right: 10rpx;
display: inline-block;
vertical-align: middle;
animation: loading 1s steps(12) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
background-size: 100%;
}
================================================
FILE: packageStreamMedia/pages/videoCall/videoCall.js
================================================
const app = getApp()
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../../utils/auth')
Page({
data: {
callingFlag: false,
invitation: null,
incomingCallFlag: false,
inviteCallFlag: false,
pusherAvatar: ''
},
call: function() {
if (!this.data.uid) {
wx.showToast({
title: '请输入用户编号',
icon: 'none'
})
return
}
if (this.data.config.userID == this.data.uid) {
wx.showToast({
title: '不可呼叫本机',
})
return
}
this.data.config.type = 2
this.setData({
callingFlag: true,
inviteCallFlag: true,
config: this.data.config,
})
this.TRTCCalling.call({ userID: this.data.uid, type: 2 })
},
bindTRTCCallingRoomEvent: function() {
const TRTCCallingEvent = this.TRTCCalling.EVENT
this.TRTCCalling.on(TRTCCallingEvent.INVITED, (event) => {
this.setData({
invitation: event.data,
incomingCallFlag: true,
})
})
// 处理挂断的事件回调
this.TRTCCalling.on(TRTCCallingEvent.HANG_UP, () => {
this.setData({
callingFlag: false,
})
})
this.TRTCCalling.on(TRTCCallingEvent.REJECT, () => {
this.setData({
callingFlag: false,
inviteCallFlag: false,
})
wx.showToast({
title: '对方已拒绝',
})
this.TRTCCalling.hangup()
})
this.TRTCCalling.on(TRTCCallingEvent.USER_LEAVE, () => {
this.TRTCCalling.hangup()
wx.showToast({
title: '对方已挂断',
})
})
this.TRTCCalling.on(TRTCCallingEvent.NO_RESP, () => {
this.setData({
incomingCallFlag: false,
inviteCallFlag: false,
})
wx.showToast({
title: '无应答超时',
})
this.TRTCCalling.hangup()
})
this.TRTCCalling.on(TRTCCallingEvent.LINE_BUSY, () => {
this.setData({
incomingCallFlag: false,
inviteCallFlag: false,
})
wx.showToast({
title: '对方忙线中',
})
this.TRTCCalling.hangup()
})
this.TRTCCalling.on(TRTCCallingEvent.CALLING_CANCEL, () => {
this.setData({
incomingCallFlag: false,
})
wx.showToast({
title: '通话已取消',
})
})
this.TRTCCalling.on(TRTCCallingEvent.USER_ENTER, () => {
this.setData({
inviteCallFlag: false,
})
})
},
handleOnAccept: function() {
this.data.config.type = this.data.invitation.type
this.setData({
callingFlag: true,
incomingCallFlag: false,
config: this.data.config,
}, () => {
this.TRTCCalling.accept()
})
},
handleOnReject: function() {
this.setData({
incomingCallFlag: false,
}, () => {
this.TRTCCalling.reject()
})
},
handleOnCancel: function() {
this.TRTCCalling.hangup()
this.setData({
inviteCallFlag: false,
})
},
onBack: function() {
wx.navigateBack({
delta: 1,
})
this.TRTCCalling.logout()
},
onLoad: function() {
this.initTrtc()
},
onShow: function() {
AUTH.checkHasLogined().then(isLogined => {
this.data.isLogined = isLogined
if (!isLogined) {
AUTH.login(this)
}
})
},
async initTrtc () {
const res = await WXAPI.trtcUserSig(wx.getStorageSync('token'))
if (res.code == 0) {
app.globalData.sdkAppID = res.data.sDKAppID
this.data.config = {
sdkAppID: res.data.sDKAppID,
userID: res.data.userID + "",
userSig: res.data.userSig,
type: 2
}
this.setData({
config: this.data.config,
loaclPhoneNumber: res.data.userID,
pusherAvatar: this.data.pusherAvatar,
}, () => {
this.TRTCCalling = this.selectComponent('#TRTCCalling-component')
this.bindTRTCCallingRoomEvent()
this.TRTCCalling.login()
})
}
},
})
================================================
FILE: packageStreamMedia/pages/videoCall/videoCall.json
================================================
{
"usingComponents": {
"TRTCCalling": "../../components/TRTCCalling/TRTCCalling"
},
"navigationStyle": "custom",
"disableScroll": true
}
================================================
FILE: packageStreamMedia/pages/videoCall/videoCall.wxml
================================================
{{invitation.inviter}}
{{'邀请你' + (invitation.type === 1 ? '语音' : '视频') + '通话'}}
{{'等待' + uid + '接受邀请'}}
视频客服
立即呼叫
================================================
FILE: packageStreamMedia/pages/videoCall/videoCall.wxss
================================================
.container {
width: 100vw;
height: 100vh;
overflow: hidden;
background-image: url(https://mc.qcloudimg.com/static/img/7da57e0050d308e2e1b1e31afbc42929/bg.png);
margin: 0;
}
.trtc-calling-index {
width: 100vw;
height: 100vh;
color: white;
}
.trtc-calling-index-title {
position: relative;
display: flex;
width: 100%;
margin-top: 3.8vh;
justify-content: center;
}
.trtc-calling-index-title .title {
margin: 0;
font-family: PingFangSC-Regular;
font-size: 16px;
color: #FFFFFF;
letter-spacing: 0;
line-height: 36px;
padding: 1.2vh;
}
.btn-goback{
position: absolute;
left: 2vw;
top: 1.2vh;
width: 8vw;
height: 8vw;
z-index: 9;
}
.trtc-calling-index-search {
margin: 0;
}
.trtc-calling-index-search > .search {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.btn-search {
text-align: center;
width: 60px;
height: 40px;
margin-right: 5%;
z-index: 999;
line-height: 40px;
border-left: 1px solid rgba(255, 255, 255, 0.11);
background-image: linear-gradient(155deg, #0D2C5B 7%, #122755 93%);
font-size: 14px;
}
.search-result {
width: 90%;
height: 40px;
margin-left: 5%;
}
.input-search-user {
margin-left: 5%;
width: 90%;
height: 40px;
background-image: linear-gradient(155deg, #0D2C5B 7%, #122755 93%);
border: 0 solid #0062E3;
border-radius: 3px;
border-radius: 3px;
}
.user-to-call {
display: flex;
justify-content: space-between;
width: 100%;
height: 50px;
margin: 0;
}
.user-to-call > .userinfo-avatar {
height: 50px;
width: 50px;
}
.userinfo-userid {
height: 50px;
line-height: 50px;
text-align: center;
}
.btn-userinfo-call {
height: 30px;
line-height: 30px;
margin: 10px 0;
background-color: #0062E3;
color: rgba(255, 255, 255);
width: 15%;
text-align: center;
border-radius: 10%;
}
.hidden {
display: none;
}
.trtc-calling {
width: 100vw;
height: 100vh;
overflow: hidden;
background-image: url(https://mc.qcloudimg.com/static/img/7da57e0050d308e2e1b1e31afbc42929/bg.png);
margin: 0;
z-index: 99;
}
.user-to-call > image {
height: 50px;
line-height: 50px;
border-radius:50px
}
.title-number {
height: 20px;
margin-top: 3%;
padding: 5px 0;
border-top: 1px solid rgba(255, 255, 255, 0.11);
font-size: 12px;
}
.incoming-call {
width: 100vw;
height: 100vh;
}
.btn-operate {
display: flex;
justify-content: space-between;
position: absolute;
bottom: 5vh;
width: 100%;
}
.call-operate {
width: 15vw;
height: 15vw;
border-radius: 15vw;
padding: 5px;
margin: 0 15vw;
}
.tips {
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
color: seashell;
}
.invite-call {
background-image: url(https://mc.qcloudimg.com/static/img/7da57e0050d308e2e1b1e31afbc42929/bg.png);
position: absolute;
top: 0;
z-index: 100;
width: 100vw;
height: 100vh;
}
.invite-call > .btn-operate{
display: flex;
justify-content: center;
position: absolute;
bottom: 5vh;
width: 100%;
}
.incoming-call > image {
width: 40vw;
height: 40vw;
display: block;
margin: 20vw 30vw;
margin-top: 40vw;
}
.invite-call > image {
width: 40vw;
height: 40vw;
display: block;
margin: 20vw 30vw;
margin-top: 40vw;
}
.input {
width: 100vw;
margin-top: 88rpx;
}
.btn {
padding: 32rpx 0;
}
================================================
FILE: pages/about/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
if (!options.key) {
options.key = 'aboutus'
}
this.data.key = options.key
this.cmsPage()
},
onShow: function () {
},
async cmsPage() {
const res = await WXAPI.cmsPage(this.data.key)
if (res.code == 0) {
this.setData({
cmsPageDetail: res.data
})
wx.setNavigationBarTitle({
title: res.data.info.title,
})
}
},
onShareAppMessage: function() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - ' + this.data.cmsPageDetail.info.title,
path: `/pages/about/index?key=${this.data.key}&inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
onShareTimeline() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - ' + this.data.cmsPageDetail.info.title,
query: `key=${this.data.key}&inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
})
================================================
FILE: pages/about/index.json
================================================
{
"navigationBarTitleText": ""
}
================================================
FILE: pages/about/index.wxml
================================================
================================================
FILE: pages/about/index.wxss
================================================
.content {
padding: 32rpx;
color: #333;
line-height: 64rpx;
}
================================================
FILE: pages/address-add/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
var address_parse = require("../../utils/address_parse")
Page({
data: {
provinces: undefined,// 省份数据数组
pIndex: 0,//选择的省下标
cities: undefined,// 城市数据数组
cIndex: 0,//选择的市下标
areas: undefined,// 区县数数组
aIndex: 0,//选择的区下标
},
async provinces(provinceId, cityId, districtId, streetId) {
const res = await WXAPI.provinceV2()
if (res.code == 0) {
const provinces = [{
id: 0,
name: '请选择'
}].concat(res.data)
let pIndex = 0
if (provinceId) {
pIndex = provinces.findIndex(ele => {
return ele.id == provinceId
})
}
this.setData({
pIndex,
provinces: provinces
})
if (provinceId) {
const e = { detail: { value: pIndex}}
this.provinceChange(e, cityId, districtId, streetId)
}
}
},
async provinceChange(e, cityId, districtId, streetId) {
const index = e.detail.value
this.setData({
pIndex: index
})
const pid = this.data.provinces[index].id
if (pid == 0) {
this.setData({
cities: null,
cIndex: 0,
areas: null,
aIndex: 0
})
return
}
const res = await WXAPI.nextRegionV2(pid);
if (res.code == 0) {
const cities = [{
id: 0,
name: '请选择'
}].concat(res.data)
let cIndex = 0
if (cityId) {
cIndex = cities.findIndex(ele => {
return ele.id == cityId
})
}
this.setData({
cIndex,
cities: cities
})
if (cityId) {
const e = { detail: { value: cIndex } }
this.cityChange(e, districtId, streetId)
}
}
},
async cityChange(e, districtId, streetId) {
const index = e.detail.value
this.setData({
cIndex: index
})
const pid = this.data.cities[index].id
if (pid == 0) {
this.setData({
areas: null,
aIndex: 0
})
return
}
const res = await WXAPI.nextRegionV2(pid);
if (res.code == 0) {
const areas = [{
id: 0,
name: '请选择'
}].concat(res.data)
let aIndex = 0
if (districtId) {
aIndex = areas.findIndex(ele => {
return ele.id == districtId
})
}
this.setData({
aIndex,
areas: areas
})
if (districtId) {
const e = { detail: { value: aIndex } }
this.areaChange(e, streetId)
}
}
},
async areaChange(e, streetId) {
const index = e.detail.value
this.setData({
aIndex: index
})
const shipping_address_region_level = wx.getStorageSync('shipping_address_region_level')
if (shipping_address_region_level == 3) {
return
}
//
const pid = this.data.areas[index].id
if (pid == 0) {
this.setData({
streets: null,
sIndex: 0
})
return
}
const res = await WXAPI.nextRegionV2(pid);
if (res.code == 0) {
const streets = [{
id: 0,
name: '请选择'
}].concat(res.data)
let sIndex = 0
if (streetId) {
sIndex = streets.findIndex(ele => {
return ele.id == streetId
})
}
this.setData({
sIndex,
streets
})
if (streetId) {
const e = { detail: { value: sIndex } }
this.streetChange(e)
}
}
},
async streetChange(e) {
const index = e.detail.value
this.setData({
sIndex: index
})
},
async bindSave() {
if (this.data.pIndex == 0 ) {
wx.showToast({
title: '请选择省份',
icon: 'none'
})
return
}
if (this.data.cIndex == 0 ) {
wx.showToast({
title: '请选择城市',
icon: 'none'
})
return
}
if (this.data.aIndex == 0 ) {
wx.showToast({
title: '请选择区县',
icon: 'none'
})
return
}
const shipping_address_region_level = wx.getStorageSync('shipping_address_region_level')
if (shipping_address_region_level == 4) {
if (this.data.sIndex == 0 ) {
wx.showToast({
title: '请选择社区/街道',
icon: 'none'
})
return
}
}
const linkMan = this.data.linkMan;
const address = this.data.address;
const mobile = this.data.mobile;
if (this.data.shipping_address_gps == '1' && !this.data.addressData) {
wx.showToast({
title: '请选择定位',
icon: 'none',
})
return
}
const latitude = this.data.addressData ? this.data.addressData.latitude : null
const longitude = this.data.addressData ? this.data.addressData.longitude : null
if (!linkMan){
wx.showToast({
title: '请填写联系人姓名',
icon: 'none'
})
return
}
if (!mobile){
wx.showToast({
title: '请填写手机号码',
icon: 'none'
})
return
}
const postData = {
token: wx.getStorageSync('token'),
linkMan: linkMan,
address: address,
mobile: mobile,
isDefault: 'true'
}
if (this.data.shipping_address_gps == '1' && !latitude){
wx.showToast({
title: '请选择定位',
icon: 'none',
})
return
}
if (latitude) {
postData.latitude = latitude
}
if (longitude) {
postData.longitude = longitude
}
if (!address){
wx.showToast({
title: '请填写详细地址',
icon: 'none'
})
return
}
if (this.data.pIndex > 0) {
postData.provinceId = this.data.provinces[this.data.pIndex].id
}
if (this.data.cIndex > 0) {
postData.cityId = this.data.cities[this.data.cIndex].id
}
if (this.data.aIndex > 0) {
postData.districtId = this.data.areas[this.data.aIndex].id
}
if (this.data.sIndex > 0) {
postData.streetId = this.data.streets[this.data.sIndex].id
}
let apiResult
if (this.data.id) {
postData.id = this.data.id
apiResult = await WXAPI.updateAddress(postData)
} else {
apiResult = await WXAPI.addAddress(postData)
}
if (apiResult.code != 0) {
// 登录错误
wx.hideLoading();
wx.showToast({
title: apiResult.msg,
icon: 'none'
})
return;
} else {
wx.navigateBack()
}
},
async onLoad(e) {
// this.initFromClipboard('广州市天河区天河东路6号粤电广场北塔2302,徐小姐,18588998859')
const _this = this
if (e.id) { // 修改初始化数据库数据
const res = await WXAPI.addressDetail(wx.getStorageSync('token'), e.id)
if (res.code == 0) {
this.setData({
id: e.id,
...res.data.info
})
this.provinces(res.data.info.provinceId, res.data.info.cityId, res.data.info.districtId, res.data.info.streetId)
} else {
wx.showModal({
title: '错误',
content: '无法获取快递地址数据',
showCancel: false
})
}
} else {
this.provinces()
wx.getClipboardData({
success (res){
if (res.data) {
_this.initFromClipboard(res.data)
}
}
})
}
this.setData({
shipping_address_gps: wx.getStorageSync('shipping_address_gps')
})
},
async initFromClipboard (str) {
address_parse.smart(str).then(res => {
console.log('ggggggg', res);
if (res.name && res.phone && res.address) {
// 检测到收货地址
this.setData({
addressData: {
provinceId: res.provinceCode,
cityId: res.cityCode,
districtId: res.countyCode,
linkMan: res.name,
mobile: res.phone,
address: res.address,
},
address: res.address,
})
this.provinces(res.provinceCode, res.cityCode, res.countyCode)
}
})
},
deleteAddress: function (e) {
const id = e.currentTarget.dataset.id;
wx.showModal({
title: '提示',
content: '确定要删除该收货地址吗?',
success: function (res) {
if (res.confirm) {
WXAPI.deleteAddress(wx.getStorageSync('token'), id).then(function () {
wx.navigateBack({})
})
} else {
console.log('用户点击取消')
}
}
})
},
async readFromWx() {
let that = this;
wx.chooseAddress({
success: function (res) {
// res = {
// cityName: '上海市',
// countyName: '嘉定区',
// detailInfo: '惠民路123号',
// errMsg: 'chooseAddress.ok',
// nationalCode: '310114',
// postalCode: '201800',
// provinceName: '上海市',
// telNumber: '13500000000',
// userName: '测试',
// }
const provinceName = res.provinceName;
const cityName = res.cityName;
const diatrictName = res.countyName;
// 读取省
const pIndex = that.data.provinces.findIndex(ele => {
return ele.name == provinceName
})
if (pIndex != -1) {
const e = {
detail: {
value: pIndex
}
}
that.provinceChange(e, 0, 0).then(() => {
// 读取市
let cIndex = that.data.cities.findIndex(ele => {
return ele.name == cityName
})
if (cIndex == -1) {
cIndex = 1 // 兼容直辖市
}
if (cIndex != -1) {
const e = {
detail: {
value: cIndex
}
}
that.cityChange(e, 0).then(() => {
// 读取区县
const aIndex = that.data.areas.findIndex(ele => {
return ele.name == diatrictName
})
if (aIndex != -1) {
const e = {
detail: {
value: aIndex
}
}
that.areaChange(e)
}
})
}
})
}
that.setData({
linkMan: res.userName,
mobile: res.telNumber,
address: res.detailInfo
});
}
})
},
chooseLocation() {
wx.chooseLocation({
success: (res) => {
const addressData = this.data.addressData ? this.data.addressData : {}
addressData.address = res.name
addressData.latitude = res.latitude
addressData.longitude = res.longitude
this.setData({
addressData,
address: res.name,
})
address_parse.smart(res.address + res.name).then(res => {
if (res.address) {
// 检测到收货地址
this.setData({
addressData: {
provinceId: res.provinceCode || '',
cityId: res.cityCode || '',
districtId: res.countyCode || '',
address: addressData.address,
latitude: addressData.latitude,
longitude: addressData.longitude
},
address: addressData.address,
})
this.provinces(res.provinceCode, res.cityCode, res.countyCode)
}
})
},
fail: (e) => {
console.error(e)
},
})
}
})
================================================
FILE: pages/address-add/index.json
================================================
{
"navigationBarTitleText": "收货地址"
}
================================================
FILE: pages/address-add/index.wxml
================================================
📍
一键导入
使用微信收货地址
›
📮
收货地址
👤
联系人信息
================================================
FILE: pages/address-add/index.wxss
================================================
/* 页面基础样式 */
page {
background: #f7fafc;
min-height: 100vh;
}
page, view, image, input {
display: block;
box-sizing: border-box;
}
/* 页面容器 */
.page-container {
padding: 20rpx;
padding-bottom: 180rpx;
}
/* 快捷操作卡片 */
.quick-action-card {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 24rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.12);
animation: fadeInDown 0.5s ease;
position: relative;
overflow: hidden;
}
.quick-action-card::before {
content: '';
position: absolute;
top: -50%;
right: -10%;
width: 300rpx;
height: 300rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.06) 0%, rgba(118, 75, 162, 0.06) 100%);
border-radius: 50%;
pointer-events: none;
}
.quick-action-btn {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 24rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.04) 0%, rgba(118, 75, 162, 0.04) 100%);
border-radius: 16rpx;
transition: all 0.3s ease;
position: relative;
z-index: 1;
}
.quick-action-btn:active {
transform: scale(0.98);
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
}
.quick-action-btn:active .quick-icon {
transform: scale(0.95);
}
.quick-icon {
font-size: 48rpx;
margin-right: 20rpx;
transition: transform 0.3s ease;
}
.quick-text {
flex: 1;
color: #2d3748;
}
.quick-title {
font-size: 32rpx;
font-weight: 600;
margin-bottom: 6rpx;
letter-spacing: 1rpx;
color: #2d3748;
}
.quick-desc {
font-size: 24rpx;
color: #718096;
font-weight: 500;
}
.quick-arrow {
font-size: 56rpx;
color: #a0aec0;
font-weight: 300;
}
/* 表单卡片 */
.form-card {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 24rpx;
margin-bottom: 24rpx;
overflow: hidden;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.12);
animation: fadeInUp 0.5s ease;
}
.card-title {
display: flex;
align-items: center;
padding: 32rpx 32rpx 24rpx;
font-size: 32rpx;
font-weight: 600;
color: #1a1a1a;
border-bottom: 1rpx solid #f0f0f0;
}
.title-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.form-section {
padding: 0;
}
/* 自定义 Vant 组件样式 */
.custom-cell {
font-size: 30rpx !important;
padding: 28rpx 32rpx !important;
border-bottom: 1rpx solid #f5f5f5 !important;
transition: background-color 0.2s ease;
}
.custom-cell:last-child {
border-bottom: none !important;
}
.custom-cell:active {
background-color: #f8f9fa !important;
}
.custom-field {
font-size: 30rpx !important;
padding: 28rpx 32rpx !important;
border-bottom: 1rpx solid #f5f5f5 !important;
}
.custom-field:last-child {
border-bottom: none !important;
}
/* 底部操作区 */
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 32rpx;
background: linear-gradient(180deg, rgba(247, 250, 252, 0) 0%, rgba(247, 250, 252, 0.95) 30%, rgba(247, 250, 252, 1) 100%);
backdrop-filter: blur(20rpx);
z-index: 100;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.save-btn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
border-radius: 48rpx;
border: none;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.2);
transition: all 0.3s ease;
margin-bottom: 16rpx;
position: relative;
overflow: hidden;
}
.save-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.save-btn:active::before {
width: 300%;
height: 300%;
}
.primary-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
}
.primary-btn:active {
transform: translateY(2rpx);
box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.35);
}
.danger-btn {
background: linear-gradient(135deg, #ffffff 0%, #fff5f5 100%);
color: #e53e3e;
box-shadow: 0 8rpx 24rpx rgba(229, 62, 62, 0.15);
border: 2rpx solid rgba(229, 62, 62, 0.2);
}
.danger-btn:active {
transform: translateY(2rpx);
box-shadow: 0 4rpx 16rpx rgba(229, 62, 62, 0.25);
background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%);
}
.btn-text {
position: relative;
z-index: 1;
letter-spacing: 2rpx;
}
button[type="default"] {
background-color: #fff;
color: #000;
}
/* 安全区域 */
.safe-area-bottom {
height: env(safe-area-inset-bottom);
height: constant(safe-area-inset-bottom);
}
/* 兼容旧样式 */
picker {
display: block;
width: 100%;
}
.hui {
color: #999;
}
.showRegionSelect {
margin-left: 32rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
/* 动画效果 */
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-6rpx);
}
}
/* 输入框聚焦效果 */
.van-field__control:focus {
color: #667eea;
}
/* 响应式适配 */
@media (prefers-color-scheme: dark) {
page {
background: #1a1a1a;
}
.form-card {
background: #2a2a2a;
color: #fff;
}
.card-title {
color: #fff;
border-bottom-color: #3a3a3a;
}
}
================================================
FILE: pages/asset/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
balance: 0.00,
freeze: 0,
score: 0,
score_sign_continuous: 0,
cashlogs: undefined,
tabs: ["资金明细", "提现记录", "押金记录"],
activeIndex: 0,
sliderOffset: 0,
sliderLeft: 0,
withDrawlogs: undefined,
depositlogs: undefined,
rechargeOpen: false, // 是否开启充值[预存]功能
page: 1,
},
onLoad(e) {
const withdrawal = wx.getStorageSync('withdrawal')
if (withdrawal == '1') {
this.setData({
withdrawal,
tabs: ["资金明细", "提现记录", "押金记录"]
})
} else {
this.setData({
tabs: ["资金明细", "押金记录"]
})
}
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.initData()
} else {
getApp().loginOK = () => {
this.initData()
}
}
})
},
onShow() {
},
onPullDownRefresh() {
this.data.page = 1
this.fetchTabData(this.data.activeIndex)
wx.stopPullDownRefresh()
},
onReachBottom() {
this.data.page++
this.fetchTabData(this.data.activeIndex)
},
async initData() {
const token = wx.getStorageSync('token')
const res = await WXAPI.userAmount(token)
if (res.code == 700) {
wx.showToast({
title: '当前账户存在异常',
icon: 'none'
})
return
}
if (res.code == 0) {
this.setData({
balance: res.data.balance.toFixed(2),
freeze: res.data.freeze.toFixed(2),
totleConsumed: res.data.totleConsumed.toFixed(2),
score: res.data.score
})
}
this.fetchTabData(this.data.activeIndex)
},
fetchTabData(activeIndex){
if (activeIndex == 0) {
this.cashLogs()
}
if (activeIndex == 1) {
this.withDrawlogs()
}
if (activeIndex == 2) {
this.depositlogs()
}
},
async cashLogs() {
// https://www.yuque.com/apifm/nu0f75/khq7xu
wx.showLoading({
title: '',
})
const res = await WXAPI.cashLogsV3({
token: wx.getStorageSync('token'),
page: this.data.page,
dateAddBegin: this.data.dateAddBegin || '',
dateAddEnd: this.data.dateAddEnd || '',
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
cashlogs: res.data.result
})
} else {
this.setData({
cashlogs: this.data.cashlogs.concat(res.data.result)
})
}
} else {
if (this.data.page == 1) {
this.setData({
cashlogs: null
})
}
}
},
async withDrawlogs() {
// https://www.yuque.com/apifm/nu0f75/aw6qt6
wx.showLoading({
title: '',
})
const res = await WXAPI.withDrawLogsV2({
token: wx.getStorageSync('token'),
page: this.data.page
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
withDrawlogs: res.data.result
})
} else {
this.setData({
withDrawlogs: this.data.withDrawlogs.concat(res.data.result)
})
}
} else {
if (this.data.page == 1) {
this.setData({
withDrawlogs: null
})
}
}
},
async depositlogs() {
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/xd6g5h
const res = await WXAPI.depositListV2({
token: wx.getStorageSync('token'),
page: this.data.page
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
depositlogs: res.data.result
})
} else {
this.setData({
depositlogs: this.data.depositlogs.concat(res.data.result)
})
}
} else {
if (this.data.page == 1) {
this.setData({
depositlogs: null
})
}
}
},
recharge: function (e) {
wx.navigateTo({
url: "/pages/recharge/index"
})
},
withdraw: function (e) {
wx.navigateTo({
url: "/pages/withdraw/index"
})
},
payDeposit: function (e) {
wx.navigateTo({
url: "/pages/deposit/pay"
})
},
tabClick: function (e) {
this.setData({
activeIndex: e.detail.index
})
this.data.page = 1
this.fetchTabData(e.detail.index)
},
cancelLogin(){
wx.switchTab({
url: '/pages/my/index'
})
},
async confirmTX(e) {
const item = e.currentTarget.dataset.item
wx.showLoading({
title: '',
})
const res = await WXAPI.wxpayRequestMerchantTransferV2({
token: wx.getStorageSync('token'),
number: item.number
})
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.requestMerchantTransfer({
mchId: res.data.mchId,
appId: res.data.appId,
package: res.data.package,
openId: res.data.openId,
success: res => {
console.log(res);
this.setData({
activeIndex: 1
});
this.fetchTabData(1)
},
fail: res => {
console.error(res);
},
})
},
dateAddBeginChange(e) {
this.setData({
dateAddBegin: e.detail.value
})
this.fetchTabData(0)
},
dateAddEndChange(e) {
this.setData({
dateAddEnd: e.detail.value
})
this.fetchTabData(0)
},
async payStatusDepositV2(e) {
const item = e.currentTarget.dataset.item
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/mpsdwi
const res= await WXAPI.payStatusDepositV2({
token: wx.getStorageSync('token'),
id: item.id
})
wx.hideLoading()
if (res.code == 40000) {
// 余额不够
this.setData({
money: res.data,
paymentShow: true,
nextAction: {
type: 5,
amount: item.amount
}
})
return
} else if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showModal({
content: '支付成功',
showCancel: false,
success: (res) => {
this.page = 1
this.depositlogs()
}
})
},
async depositBackApplyV2(e) {
const item = e.currentTarget.dataset.item
wx.showModal({
content: '确定要申请退回吗?',
complete: async (res) => {
if (res.confirm) {
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/qx1f9u
const res= await WXAPI.depositBackApplyV2(wx.getStorageSync('token'), item.id)
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
})
return
}
wx.showModal({
content: '已申请,等待管理员处理',
showCancel: false,
success: (res) => {
this.page = 1
this.depositlogs()
}
})
}
}
})
},
})
================================================
FILE: pages/asset/index.json
================================================
{
"navigationBarTitleText": "我的资产",
"enablePullDownRefresh": true
}
================================================
FILE: pages/asset/index.wxml
================================================
可用余额(元)
¥
{{balance}}
¥{{freeze}}
冻结金额
¥{{totleConsumed}}
累计消费
¥{{ item.money }}
确认收款
¥{{ item.amount }}
支付押金
申请退回
================================================
FILE: pages/asset/index.wxss
================================================
/* 页面容器 */
page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
/* 顶部容器 */
.asset-container {
position: relative;
padding: 30rpx;
padding-bottom: 40rpx;
overflow: hidden;
}
/* 装饰背景圆圈 */
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 600rpx;
overflow: hidden;
pointer-events: none;
}
.bg-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.circle-1 {
width: 400rpx;
height: 400rpx;
top: -150rpx;
right: -100rpx;
animation: float 6s ease-in-out infinite;
}
.circle-2 {
width: 300rpx;
height: 300rpx;
top: 100rpx;
left: -100rpx;
animation: float 8s ease-in-out infinite;
}
.circle-3 {
width: 200rpx;
height: 200rpx;
top: 300rpx;
right: 50rpx;
animation: float 7s ease-in-out infinite;
}
@keyframes float {
0%, 100% {
transform: translateY(0) rotate(0deg);
}
50% {
transform: translateY(-30rpx) rotate(180deg);
}
}
/* 资产卡片 */
.asset-card {
position: relative;
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 32rpx;
padding: 50rpx 40rpx 40rpx;
margin-bottom: 30rpx;
box-shadow: 0 20rpx 60rpx rgba(102, 126, 234, 0.25);
overflow: hidden;
}
.asset-card::before {
content: '';
position: absolute;
top: -50%;
right: -10%;
width: 400rpx;
height: 400rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
border-radius: 50%;
}
/* 卡片头部 */
.asset-header {
margin-bottom: 40rpx;
position: relative;
}
.header-title {
font-size: 36rpx;
font-weight: 700;
color: #2d3748;
margin-bottom: 8rpx;
letter-spacing: 1rpx;
}
.header-subtitle {
font-size: 22rpx;
color: #a0aec0;
font-weight: 500;
letter-spacing: 2rpx;
text-transform: uppercase;
}
/* 主余额区域 */
.balance-main {
text-align: center;
padding: 30rpx 0;
margin-bottom: 30rpx;
position: relative;
}
.balance-label {
font-size: 26rpx;
color: #718096;
margin-bottom: 16rpx;
font-weight: 500;
}
.balance-amount {
display: flex;
align-items: baseline;
justify-content: center;
position: relative;
}
.currency-symbol {
font-size: 48rpx;
color: #667eea;
font-weight: 700;
margin-right: 8rpx;
}
.amount-number {
font-size: 88rpx;
font-weight: 800;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: 2rpx;
line-height: 1;
}
/* 统计信息 */
.asset-stats {
display: flex;
align-items: center;
justify-content: space-around;
padding: 30rpx 20rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
border-radius: 20rpx;
position: relative;
}
.stat-item {
flex: 1;
text-align: center;
}
.stat-value {
font-size: 36rpx;
font-weight: 700;
color: #2d3748;
margin-bottom: 8rpx;
}
.stat-label {
font-size: 24rpx;
color: #718096;
font-weight: 500;
}
.stat-divider {
width: 2rpx;
height: 60rpx;
background: linear-gradient(to bottom,
rgba(102, 126, 234, 0) 0%,
rgba(102, 126, 234, 0.3) 50%,
rgba(102, 126, 234, 0) 100%
);
}
/* 操作按钮区 */
.action-buttons {
display: flex;
gap: 20rpx;
margin-bottom: 30rpx;
position: relative;
}
.action-buttons form {
flex: 1;
}
.action-btn {
width: 100%;
height: 140rpx !important;
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 24rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: none;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.15);
transition: all 0.3s ease;
padding: 0 !important;
line-height: normal !important;
font-size: 28rpx;
position: relative;
overflow: hidden;
}
.action-btn::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.action-btn::after {
display: none;
}
.btn-icon {
font-size: 48rpx;
margin-bottom: 8rpx;
position: relative;
z-index: 1;
transition: transform 0.3s ease;
}
.btn-text {
font-size: 26rpx;
font-weight: 600;
color: #2d3748;
position: relative;
z-index: 1;
transition: color 0.3s ease;
}
.btn-hover {
transform: translateY(-4rpx);
box-shadow: 0 12rpx 32rpx rgba(102, 126, 234, 0.25) !important;
}
.btn-hover::before {
opacity: 1;
}
.btn-hover .btn-text {
color: #ffffff;
}
.btn-hover .btn-icon {
transform: scale(1.1);
}
/* 交易记录区域 */
.records-section {
background: #ffffff;
border-radius: 32rpx 32rpx 0 0;
min-height: 600rpx;
padding-top: 10rpx;
box-shadow: 0 -10rpx 40rpx rgba(0, 0, 0, 0.05);
}
/* 筛选区域 */
.filter-section {
padding: 20rpx 30rpx;
background: #f7fafc;
margin: 0 30rpx 20rpx;
border-radius: 20rpx;
}
/* 列表容器 */
.list-container {
padding: 0 30rpx 40rpx;
}
/* 价格样式 */
.price {
color: #667eea;
font-size: 32rpx;
font-weight: 700;
text-align: right;
margin-bottom: 10rpx;
}
.price text {
font-size: 24rpx;
margin-right: 4rpx;
}
/* van-tabs 样式覆盖 */
.records-section .van-tabs {
background: transparent;
}
.records-section .van-tabs__line {
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%) !important;
height: 6rpx !important;
border-radius: 3rpx !important;
}
/* van-cell 样式优化 */
.list-container .van-cell {
background: #ffffff;
margin-bottom: 20rpx;
border-radius: 16rpx;
padding: 30rpx !important;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.04);
}
.list-container .van-cell::after {
display: none;
}
/* 空状态样式 */
.list-container .van-empty {
padding: 100rpx 0;
}
/* 优化 van-cell-group */
.list-container .van-cell-group {
background: transparent;
}
.list-container .van-cell-group::after {
display: none;
}
/* 按钮基础样式重置 */
button {
background: none;
border: none;
outline: none;
}
button::after {
border: none;
}
/* 响应式适配 */
@media screen and (max-width: 320px) {
.amount-number {
font-size: 72rpx;
}
.action-btn {
height: 120rpx !important;
}
.btn-icon {
font-size: 40rpx;
}
}
================================================
FILE: pages/card/logs.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
page: 1 // 读取第几页
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.data.cardId = options.id
this.cardMyLogs()
},
async cardMyLogs(){
wx.showLoading({
title: '',
})
const res = await WXAPI.cardMyLogs({
token: wx.getStorageSync('token'),
cardId: this.data.cardId,
page: this.data.page
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
list: res.data.result,
})
} else {
this.setData({
list: this.data.list.concat(res.data.result),
})
}
} else {
if (this.data.page == 1) {
this.setData({
list: null,
})
} else {
wx.showToast({
title: '没有更多了',
icon: 'none'
})
}
}
},
onPullDownRefresh: function () {
this.data.page = 1
this.cardMyLogs()
wx.stopPullDownRefresh()
},
onReachBottom() {
this.data.page++
this.cardMyLogs()
},
})
================================================
FILE: pages/card/logs.json
================================================
{
"navigationBarTitleText": "会员卡消费明细",
"enablePullDownRefresh": true
}
================================================
FILE: pages/card/logs.wxml
================================================
📋
暂无消费记录
您还没有任何消费记录哦
================================================
FILE: pages/card/logs.wxss
================================================
/* pages/card/logs.wxss */
/* ============ 全局容器 ============ */
.container {
min-height: 100vh;
background: linear-gradient(180deg, #f5f5f5 0%, #ffffff 100%);
}
/* ============ 顶部Banner区域 ============ */
.header-banner {
position: relative;
height: 280rpx;
background: linear-gradient(135deg, #E1251B 0%, #E93323 50%, #F54336 100%);
overflow: hidden;
box-shadow: 0 8rpx 24rpx rgba(225, 37, 27, 0.15);
}
.header-content {
position: relative;
z-index: 2;
padding: 80rpx 40rpx 40rpx;
}
.header-title {
font-size: 48rpx;
font-weight: 700;
color: #ffffff;
letter-spacing: 2rpx;
margin-bottom: 12rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.header-subtitle {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 4rpx;
font-weight: 400;
}
/* 装饰性圆圈 */
.header-bg-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.08);
}
.circle-1 {
width: 400rpx;
height: 400rpx;
right: -100rpx;
top: -150rpx;
}
.circle-2 {
width: 280rpx;
height: 280rpx;
right: -80rpx;
bottom: -120rpx;
background: rgba(255, 255, 255, 0.05);
}
/* ============ 记录列表容器 ============ */
.records-wrapper {
margin-top: -40rpx;
position: relative;
z-index: 3;
padding: 0 30rpx 40rpx;
}
.records-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
/* ============ 卡片样式 ============ */
.record-card {
background: #ffffff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}
.record-card::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 8rpx;
height: 100%;
background: linear-gradient(180deg, #E1251B 0%, #E93323 100%);
}
/* 卡片头部 */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 32rpx 24rpx;
}
.record-left {
display: flex;
align-items: center;
flex: 1;
}
.record-icon {
margin-right: 24rpx;
}
.icon-circle {
width: 88rpx;
height: 88rpx;
background: linear-gradient(135deg, #FFF5F5 0%, #FFE8E8 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
box-shadow: 0 4rpx 12rpx rgba(225, 37, 27, 0.08);
}
.record-info {
flex: 1;
}
.record-type {
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 8rpx;
letter-spacing: 0.5rpx;
}
.record-date {
font-size: 24rpx;
color: #999999;
letter-spacing: 0.5rpx;
}
.record-right {
margin-left: 20rpx;
}
.record-amount {
font-size: 44rpx;
font-weight: 700;
color: #E1251B;
letter-spacing: 1rpx;
font-family: 'DIN Alternate', 'Arial', sans-serif;
}
/* 卡片底部 */
.card-footer {
background: linear-gradient(90deg, #FAFAFA 0%, #F5F5F5 100%);
padding: 24rpx 32rpx;
border-top: 1rpx solid #F0F0F0;
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
}
.balance-info {
display: flex;
align-items: baseline;
gap: 16rpx;
}
.balance-label {
font-size: 24rpx;
color: #666666;
letter-spacing: 0.5rpx;
}
.balance-value {
font-size: 32rpx;
font-weight: 600;
color: #333333;
font-family: 'DIN Alternate', 'Arial', sans-serif;
}
.card-ornament {
width: 60rpx;
height: 60rpx;
background: linear-gradient(135deg, #E1251B15 0%, #E9332315 100%);
border-radius: 50%;
position: absolute;
right: 20rpx;
opacity: 0.4;
}
/* ============ 空状态样式 ============ */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 40rpx;
background: #ffffff;
border-radius: 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.empty-icon {
font-size: 120rpx;
margin-bottom: 32rpx;
opacity: 0.6;
animation: float 3s ease-in-out infinite;
}
.empty-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
margin-bottom: 16rpx;
letter-spacing: 1rpx;
}
.empty-desc {
font-size: 26rpx;
color: #999999;
text-align: center;
line-height: 1.6;
}
/* ============ 动画效果 ============ */
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10rpx);
}
}
/* 卡片悬停效果(仅适用于支持的平台) */
.record-card:active {
transform: scale(0.98);
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
/* ============ 响应式优化 ============ */
@media (prefers-color-scheme: dark) {
.container {
background: linear-gradient(180deg, #1a1a1a 0%, #0f0f0f 100%);
}
.record-card {
background: #1f1f1f;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3);
}
.record-type {
color: #eeeeee;
}
.record-date {
color: #888888;
}
.balance-label {
color: #999999;
}
.balance-value {
color: #eeeeee;
}
.card-footer {
background: linear-gradient(90deg, #2a2a2a 0%, #252525 100%);
border-top-color: #333333;
}
.empty-state {
background: #1f1f1f;
}
.empty-title {
color: #eeeeee;
}
}
================================================
FILE: pages/category/category.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const TOOLS = require('../../utils/tools.js') // TOOLS.showTabBarBadge();
Page({
/**
* 页面的初始数据
*/
data: {
categories: [],
activeCategory: 0,
categorySelected: {
name: '',
id: ''
},
currentGoods: [],
onLoadStatus: true,
scrolltop: 0,
skuCurGoods: undefined,
page: 1,
pageSize: 20
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
wx.showShareMenu({
withShareTicket: true
})
this.setData({
categoryMod: wx.getStorageSync('categoryMod')
})
this.categories();
},
async categories() {
wx.showLoading({
title: '',
})
const res = await WXAPI.goodsCategory()
wx.hideLoading()
let activeCategory = 0
let categorySelected = this.data.categorySelected
if (res.code == 0) {
// const categories = res.data.filter(ele => {
// return !ele.vopCid1 && !ele.vopCid2
// })
const categories = res.data
categories.forEach(p => {
p.childs = categories.filter(ele => {
return p.id == ele.pid
})
})
const firstCategories = categories.filter(ele => { return ele.level == 1 })
if (this.data.categorySelected.id) {
activeCategory = firstCategories.findIndex(ele => {
return ele.id == this.data.categorySelected.id
})
categorySelected = firstCategories[activeCategory]
} else {
categorySelected = firstCategories[0]
}
let adPosition = null
if (categorySelected) {
const resAd = await WXAPI.adPosition('category_' + categorySelected.id)
if (resAd.code === 0) {
adPosition = resAd.data
}
}
this.setData({
page: 1,
activeCategory,
categories,
firstCategories,
categorySelected,
adPosition
})
this.getGoodsList()
}
},
async getGoodsList() {
if (this.data.categoryMod == 2) {
return
}
wx.showLoading({
title: '',
})
// secondCategoryId
let categoryId = ''
if (this.data.secondCategoryId) {
categoryId = this.data.secondCategoryId
} else if(this.data.categorySelected && this.data.categorySelected.id) {
categoryId = this.data.categorySelected.id
}
// https://www.yuque.com/apifm/nu0f75/wg5t98
const res = await WXAPI.goodsv2({
categoryId,
page: this.data.page,
pageSize: this.data.pageSize
})
wx.hideLoading()
if (res.code == 700) {
if (this.data.page == 1) {
this.setData({
currentGoods: null
});
} else {
wx.showToast({
title: '没有更多了',
icon: 'none'
})
}
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
if (this.data.page == 1) {
this.setData({
currentGoods: res.data.result
})
} else {
this.setData({
currentGoods: this.data.currentGoods.concat(res.data.result)
})
}
},
async onCategoryClick(e) {
const idx = e.target.dataset.idx
if (idx == this.data.activeCategory) {
this.setData({
scrolltop: 0,
})
return
}
const categorySelected = this.data.firstCategories[idx]
const res = await WXAPI.adPosition('category_' + categorySelected.id)
let adPosition = null
if (res.code === 0) {
adPosition = res.data
}
this.setData({
page: 1,
secondCategoryId: '',
activeCategory: idx,
categorySelected,
scrolltop: 0,
adPosition
});
this.getGoodsList();
},
onSecondCategoryClick(e) {
const idx = e.detail.index
let secondCategoryId = ''
if (idx) {
// 点击了具体的分类
secondCategoryId = this.data.categorySelected.childs[idx-1].id
}
this.setData({
page: 1,
secondCategoryId
});
this.getGoodsList();
},
bindconfirm(e) {
this.setData({
inputVal: e.detail
})
wx.navigateTo({
url: '/pages/goods/list?name=' + this.data.inputVal,
})
},
onShareAppMessage() {
return {
title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
}
},
onShareTimeline() {
return {
title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
query: '',
imageUrl: this.data.goodsDetail.basicInfo.pic
}
},
onShow() {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
TOOLS.showTabBarBadge() // 获取购物车数据,显示TabBarBadge
} else {
getApp().loginOK = () => {
TOOLS.showTabBarBadge() // 获取购物车数据,显示TabBarBadge
}
}
})
const _categoryId = wx.getStorageSync('_categoryId')
wx.removeStorageSync('_categoryId')
if (_categoryId) {
this.data.categorySelected.id = _categoryId
this.categories();
}
},
async addShopCar(e) {
const curGood = this.data.currentGoods.find(ele => {
return ele.id == e.currentTarget.dataset.id
})
if (!curGood) {
return
}
if (curGood.stores <= 0) {
wx.showToast({
title: '已售罄~',
icon: 'none'
})
return
}
// 判断是否有可选配件全局或者按分类的
const resGoodsAddition = await WXAPI.goodsAddition(curGood.id)
if (resGoodsAddition.code == 0) {
// 需要选择 SKU 和 可选配件
curGood.hasAddition = true
this.setData({
skuCurGoods: curGood
})
return
}
if (!curGood.propertyIds && !curGood.hasAddition) {
// 直接调用加入购物车方法
const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), curGood.id, 1, [])
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code == 30002) {
// 需要选择规格尺寸
this.setData({
skuCurGoods: curGood
})
} else if (res.code == 0) {
wx.showToast({
title: '加入成功',
icon: 'success'
})
wx.showTabBar()
TOOLS.showTabBarBadge() // 获取购物车数据,显示TabBarBadge
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
} else {
// 需要选择 SKU 和 可选配件
this.setData({
skuCurGoods: curGood
})
}
},
goodsGoBottom() {
this.data.page++
this.getGoodsList()
},
adPositionClick(e) {
const url = e.target.dataset.url
if (url) {
wx.navigateTo({
url: url
})
}
},
searchscan() {
wx.scanCode({
scanType: ['barCode', 'qrCode', 'datamatrix', 'pdf417'],
success: res => {
this.setData({
inputVal: res.result
})
wx.navigateTo({
url: '/pages/goods/list?name=' + res.result,
})
}
})
}
})
================================================
FILE: pages/category/category.json
================================================
{
"navigationBarTitleText": "分类"
}
================================================
FILE: pages/category/category.wxml
================================================
{{item.name}}
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.id
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.id
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.id
} else {
return '/pages/goods-details/index?id=' + item.id
}
}
}
================================================
FILE: pages/category/category.wxss
================================================
page {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
display: flex;
overflow: hidden;
}
.goods-btn {
position: absolute;
right: 32rpx;
bottom: 32rpx;
}
.category-container {
width: 180rpx;
height: 100%;
}
.goods-container {
flex: 1;
height: 100%;
}
.medium-category {
margin: 32rpx 0;
}
.medium-category .line {
width:60rpx;
}
.medium-category .txt {
color: #333;
}
.small-category-box {
width: 570rpx;
display: flex;
flex-wrap: wrap;
}
.small-category {
width: 147rpx;
margin-top: 32rpx;
margin-left: 32rpx;
}
.small-category image {
width: 147rpx;
height: 147rpx;
}
.small-category view {
text-align: center;
font-size: 24rpx;
color: #666;
}
.llargada{
width: 590rpx!important;
}
.sidebar-l {
width: 190rpx !important;
}
.adPosition {
width: 100%;
}
.title-class-apifm {
word-break: break-all;
}
================================================
FILE: pages/cms/list.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
categoryId: undefined, // 分类id
},
onLoad (options) {
this.data.categoryId = options.categoryId
this.cmsCategoryDetail()
this.articles()
},
onShow: function () {
},
async cmsCategoryDetail() {
const res = await WXAPI.cmsCategoryDetail(this.data.categoryId)
if (res.code == 0) {
this.setData({
category: res.data
})
wx.setNavigationBarTitle({
title: res.data.info.name,
})
}
},
async articles() {
wx.showLoading({
title: '',
})
const res = await WXAPI.cmsArticlesV3({
categoryId: this.data.categoryId || ''
})
wx.hideLoading()
if (res.code == 0) {
this.setData({
cmsArticles: res.data.result
})
} else {
this.setData({
cmsArticles: null
})
}
},
onShareAppMessage: function() {
return {
title: this.data.category.info.name,
path: '/pages/cms/list?categoryId='+ this.data.categoryId +'&inviter_id=' + wx.getStorageSync('uid')
}
},
onShareTimeline() {
return {
title: this.data.category.info.name,
query: 'categoryId='+ this.data.categoryId +'&inviter_id=' + wx.getStorageSync('uid'),
imageUrl: this.data.category.info.icon,
}
},
})
================================================
FILE: pages/cms/list.json
================================================
{
"navigationBarTitleText": ""
}
================================================
FILE: pages/cms/list.wxml
================================================
================================================
FILE: pages/cms/list.wxss
================================================
/* pages/cms/list.wxss */
================================================
FILE: pages/coupons/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
tabs: ['可领', '已领', '失效', '口令'],
activeIndex: 0,
showPwdPop: false
},
onLoad(e) {
},
onShow() {
if (this.data.activeIndex == 0) {
this.sysCoupons()
}
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
if (this.data.activeIndex == 1) {
this.getMyCoupons()
}
if (this.data.activeIndex == 2) {
this.invalidCoupons()
}
}
})
},
tabClick: function (e) {
this.setData({
activeIndex: e.detail.index
});
if (this.data.activeIndex == 0) {
this.sysCoupons()
}
if (this.data.activeIndex == 1) {
this.getMyCoupons()
}
if (this.data.activeIndex == 2) {
this.invalidCoupons()
}
},
sysCoupons() { // 读取可领取券列表
var _this = this;
wx.showLoading({
title: '',
})
WXAPI.coupons().then(function (res) {
wx.hideLoading({
success: (res) => {},
})
if (res.code == 0) {
_this.setData({
coupons: res.data
});
} else {
_this.setData({
coupons: null
});
}
})
},
getCounpon2(){
if (!this.data.couponPwd) {
wx.showToast({
title: '请输入口令',
icon: 'none'
})
return
}
const e = {
kl: true,
currentTarget: {
dataset: {
id: this.data.pwdCounponId
}
}
}
this.getCounpon(e)
},
getCounpon(e) {
if (e.currentTarget.dataset.pwd) {
this.setData({
pwdCounponId: e.currentTarget.dataset.id,
showPwdPop: true
})
return
} else {
if (!e.kl) {
this.data.couponPwd = ''
}
}
this.setData({
showPwdPop: false
})
WXAPI.fetchCoupons({
id: e.currentTarget.dataset.id,
token: wx.getStorageSync('token'),
pwd: this.data.couponPwd
}).then(res => {
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code == 20001 || res.code == 20002) {
wx.showModal({
content: '来晚了',
showCancel: false
})
return;
}
if (res.code == 20003) {
wx.showModal({
content: '你领过了,别贪心哦~',
showCancel: false
})
return;
}
if (res.code == 30001) {
wx.showModal({
content: '您的积分不足',
showCancel: false
})
return;
}
if (res.code == 20004) {
wx.showModal({
content: '已过期~',
showCancel: false
})
return;
}
if (res.code == 30002) {
// 发起微信支付
this.setData({
money: res.data,
paymentShow: true,
nextAction: {
// https://www.yuque.com/apifm/doc/aetmlb
type: 7,
couponRuleId: e.currentTarget.dataset.id
}
})
return;
}
if (res.code == 0) {
wx.showToast({
title: '领取成功',
icon: 'success'
})
} else {
wx.showModal({
content: res.msg,
showCancel: false
})
}
})
},
getMyCoupons: function () {
var _this = this;
wx.showLoading({
title: '',
})
WXAPI.myCoupons({
token: wx.getStorageSync('token'),
status: 0
}).then(function (res) {
wx.hideLoading({
success: (res) => {},
})
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code == 0) {
res.data.forEach(ele => {
if (ele.dateEnd) {
ele.dateEnd = ele.dateEnd.split(" ")[0]
}
})
_this.setData({
coupons: res.data
})
} else {
_this.setData({
coupons: null
})
}
})
},
invalidCoupons: function () {
var _this = this;
wx.showLoading({
title: '',
})
WXAPI.myCoupons({
token: wx.getStorageSync('token'),
status: '1,2,3'
}).then(function (res) {
wx.hideLoading({
success: (res) => {},
})
if (res.code == 0) {
_this.setData({
coupons: res.data
})
} else {
_this.setData({
coupons: null
})
}
})
},
async touse(e) {
const item = e.currentTarget.dataset.item
const res = await WXAPI.couponDetail(item.pid)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
if (!res.data.couponRefs || res.data.couponRefs.length == 0) {
wx.switchTab({
url: "/pages/index/index"
})
return
}
let categoryId, goodsId
res.data.couponRefs.forEach(ele => {
if (ele.type == 0) {
if (categoryId) {
categoryId = categoryId + ',' + ele.refId
} else {
categoryId = ele.refId
}
}
if (ele.type == 1) {
goodsId = ele.refId
}
})
if (categoryId) {
wx.navigateTo({
url: '/pages/goods/list?categoryId=' + categoryId,
})
return
}
if (goodsId) {
wx.navigateTo({
url: '/pages/goods-details/index?id=' + goodsId,
})
return
}
},
pwdCouponChange(e){
this.setData({
couponPwd: e.detail.value
})
},
onPullDownRefresh() {
if (this.data.activeIndex == 0) {
this.sysCoupons()
}
if (this.data.activeIndex == 1) {
this.getMyCoupons()
}
if (this.data.activeIndex == 2) {
this.invalidCoupons()
}
wx.stopPullDownRefresh()
},
closePwd() {
this.setData({
showPwdPop: false
})
},
async exchangeCoupons() {
if (!this.data.number) {
wx.showToast({
title: '请输入券号',
icon: 'none'
})
return
}
if (!this.data.pwd) {
wx.showToast({
title: '请输入密码',
icon: 'none'
})
return
}
this.setData({
exchangeCouponsLoading: true
})
wx.showLoading({
title: '',
})
const res = await WXAPI.exchangeCoupons(wx.getStorageSync('token'), this.data.number, this.data.pwd)
wx.hideLoading({
success: (res) => {},
})
this.setData({
exchangeCouponsLoading: false
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '兑换成功'
})
}
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/asset/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/coupons/index.json
================================================
{
"navigationBarTitleText": "优惠券",
"enablePullDownRefresh": true
}
================================================
FILE: pages/coupons/index.wxml
================================================
¥
{{item.moneyMin}}
{{item.moneyMin}}
折
满{{item.moneyHreshold}}元可用
代金券
{{item.name}}
领取即可使用
立即领取
¥
{{item.money}}
{{item.money}}
折
满{{item.moneyHreshold}}元可用
代金券
{{item.name}}
{{item.dateEnd}}到期
立即使用
¥
{{item.money}}
{{item.money}}
折
满{{item.moneyHreshold}}元可用
代金券
{{item.name}}
已失效
{{ item.statusStr }}
立即兑换
请输入口令
================================================
FILE: pages/coupons/index.wxss
================================================
page {
background: linear-gradient(180deg, #FFF5F5 0%, #F7F8FA 100%);
min-height: 100vh;
}
/* 页面头部 */
.page-header {
padding: 40rpx 32rpx 32rpx;
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
position: relative;
overflow: hidden;
}
.page-header::before {
content: '';
position: absolute;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
top: -200rpx;
right: -100rpx;
}
.page-header::after {
content: '';
position: absolute;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
bottom: -150rpx;
left: -80rpx;
}
.header-content {
position: relative;
z-index: 1;
}
.header-title {
display: block;
font-size: 48rpx;
font-weight: 700;
color: #FFFFFF;
margin-bottom: 12rpx;
letter-spacing: 2rpx;
}
.header-subtitle {
display: block;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 1rpx;
}
/* 标签栏优化 */
.tabs-wrapper {
background: #FFFFFF;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
/* 优惠券列表容器 */
.coupon-list-wrapper {
padding: 24rpx 24rpx 40rpx;
}
/* 优惠券卡片 */
.coupon-card {
position: relative;
display: flex;
margin-bottom: 24rpx;
height: 200rpx;
background: #FFFFFF;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.12);
transition: all 0.3s ease;
}
/* 优惠券左侧金额区域 */
.coupon-left {
position: relative;
width: 200rpx;
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.coupon-left::before,
.coupon-left::after {
content: '';
position: absolute;
right: -16rpx;
width: 32rpx;
height: 32rpx;
background: #F7F8FA;
border-radius: 50%;
}
.coupon-left::before {
top: -16rpx;
}
.coupon-left::after {
bottom: -16rpx;
}
.price-section {
text-align: center;
color: #FFFFFF;
}
.amount-wrapper {
display: flex;
align-items: baseline;
justify-content: center;
margin-bottom: 12rpx;
}
.currency {
font-size: 32rpx;
font-weight: 600;
margin-right: 4rpx;
}
.amount {
font-size: 72rpx;
font-weight: 700;
line-height: 1;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.percent {
font-size: 36rpx;
font-weight: 600;
margin-left: 4rpx;
}
.threshold {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.9);
font-weight: 400;
}
/* 优惠券右侧内容区域 */
.coupon-right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 16rpx 24rpx;
position: relative;
}
.coupon-content {
flex: 1;
}
.coupon-type-tag {
display: inline-block;
padding: 4rpx 16rpx;
background: linear-gradient(135deg, #FFE5E6 0%, #FFD4D5 100%);
border-radius: 6rpx;
font-size: 20rpx;
color: #E4393C;
font-weight: 600;
margin-bottom: 12rpx;
letter-spacing: 0.5rpx;
}
.coupon-name {
font-size: 30rpx;
color: #333333;
font-weight: 600;
margin-bottom: 8rpx;
line-height: 1.4;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.coupon-tips {
font-size: 22rpx;
color: #999999;
}
.expire-tips {
color: #FF6B00;
font-weight: 500;
}
/* 操作按钮 */
.coupon-action {
display: flex;
justify-content: flex-end;
}
.action-btn {
padding: 12rpx 32rpx;
border-radius: 30rpx;
font-size: 24rpx;
font-weight: 600;
text-align: center;
transition: all 0.3s ease;
}
.action-btn.active {
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
color: #FFFFFF;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
.action-btn.use-btn {
background: linear-gradient(135deg, #FF9500 0%, #FFB84D 100%);
color: #FFFFFF;
box-shadow: 0 4rpx 12rpx rgba(255, 149, 0, 0.3);
}
.action-btn.disabled-btn {
background: #F5F5F5;
color: #CCCCCC;
border: 1rpx solid #E5E5E5;
}
/* 装饰元素 */
.coupon-deco {
position: absolute;
right: 20rpx;
bottom: 20rpx;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: linear-gradient(135deg, rgba(228, 57, 60, 0.05) 0%, rgba(247, 80, 80, 0.08) 100%);
z-index: 0;
}
/* 已领券样式 */
.coupon-card.owned {
box-shadow: 0 8rpx 24rpx rgba(255, 149, 0, 0.12);
}
.gradient-owned {
background: linear-gradient(135deg, #FF9500 0%, #FFB84D 100%);
}
.owned-tag {
background: linear-gradient(135deg, #FFF4E6 0%, #FFE8CC 100%);
color: #FF9500;
}
/* 失效券样式 */
.coupon-card.disabled {
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
opacity: 0.7;
}
.gradient-disabled {
background: linear-gradient(135deg, #CCCCCC 0%, #DDDDDD 100%);
}
.disabled-tag {
background: #F5F5F5;
color: #999999;
}
.disabled-text {
color: #999999 !important;
}
.disabled-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.3);
pointer-events: none;
}
/* 底部占位 */
.bottom {
width: 100vw;
height: 40rpx;
}
/* 口令兑换区域 */
.koulingcoupon {
padding: 32rpx;
margin: 24rpx;
background: #FFFFFF;
border-radius: 20rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
}
.koulingcoupon::before {
content: '兑换优惠券';
display: block;
font-size: 36rpx;
font-weight: 700;
color: #333333;
margin-bottom: 32rpx;
text-align: center;
}
.block-btn {
margin: 40rpx 0 0;
}
/* 口令弹窗遮罩 */
.pwd-coupons-mask {
position: fixed;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
top: 0;
left: 0;
z-index: 999;
backdrop-filter: blur(4rpx);
}
/* 口令弹窗 */
.pwd-coupons {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600rpx;
background: #FFFFFF;
border-radius: 24rpx;
z-index: 1000;
box-shadow: 0 16rpx 48rpx rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.pwd-coupons .t {
padding: 48rpx 32rpx 24rpx;
text-align: center;
font-size: 36rpx;
font-weight: 700;
color: #333333;
background: linear-gradient(180deg, #FFF5F5 0%, #FFFFFF 100%);
position: relative;
}
.pwd-coupons .t::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 80rpx;
height: 6rpx;
background: linear-gradient(90deg, #E4393C 0%, #F75050 100%);
border-radius: 3rpx;
}
.pwd-coupons .input {
margin: 40rpx 40rpx 32rpx;
padding: 0 24rpx;
border: 2rpx solid #E5E5E5;
border-radius: 16rpx;
height: 96rpx;
line-height: 96rpx;
font-size: 32rpx;
color: #333333;
background: #FAFAFA;
transition: all 0.3s ease;
}
.pwd-coupons .input:focus {
border-color: #E4393C;
background: #FFFFFF;
}
.pwd-coupons button {
margin: 0 40rpx 40rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
color: #FFFFFF;
border: none;
box-shadow: 0 8rpx 20rpx rgba(228, 57, 60, 0.3);
}
.pwd-coupons button[plain] {
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
color: #FFFFFF;
border: none;
}
/* 合成提示 */
.hecheng {
margin: 24rpx;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* 优化 Vant 组件样式 */
.van-tab {
font-size: 28rpx;
font-weight: 600;
}
.van-tabs__line {
border-radius: 3rpx;
}
================================================
FILE: pages/coupons/merge.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
this.mergeCouponsRules();
},
onShow: function () {
},
async mergeCouponsRules() {
const res = await WXAPI.mergeCouponsRules()
if (res.code == 0) {
this.setData({
mergeCouponsRules: res.data
})
}
},
onPullDownRefresh() {
this.mergeCouponsRules()
wx.stopPullDownRefresh()
},
async merge(e) {
const idx = e.currentTarget.dataset.idx
const mergeCouponsRule = this.data.mergeCouponsRules[idx]
this.setData({loading: true})
let res = await WXAPI.myCoupons({
token: wx.getStorageSync('token'),
status: 0
})
if (res.code == 700) {
wx.showToast({
title: '您暂无可用的优惠券',
icon: 'none'
})
this.setData({loading: false})
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
this.setData({loading: false})
return
}
const myCoupons = res.data.reverse()
const couponIds = [] // 用来合成的优惠券id
let ok = true
let msg = ''
mergeCouponsRule.rules.filter(rule => {
return rule.type == 0
}).forEach(rule => {
for (let i = 0; i < rule.number; i++) {
const couponIndex = myCoupons.findIndex(ele => { return ele.pid == rule.couponId})
if (couponIndex == -1) {
ok = false
msg = rule.couponName
return
}
const coupon = myCoupons[couponIndex]
couponIds.push(coupon.id)
myCoupons.splice(couponIndex, 1)
}
})
if (!ok) {
wx.showToast({
title: '缺少优惠券:' + msg,
icon: 'none'
})
this.setData({loading: false})
return
}
res = await WXAPI.mergeCoupons({
token: wx.getStorageSync('token'),
mergeId: mergeCouponsRule.id,
couponIds: couponIds.join()
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
this.setData({loading: false})
return
}
wx.showToast({
title: '兑换成功'
})
this.setData({loading: false})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
}
})
================================================
FILE: pages/coupons/merge.json
================================================
{
"navigationBarTitleText": "优惠券合成",
"enablePullDownRefresh": true
}
================================================
FILE: pages/coupons/merge.wxml
================================================
立即合成
================================================
FILE: pages/coupons/merge.wxss
================================================
/* pages/coupons/merge.wxss */
================================================
FILE: pages/deposit/pay.js
================================================
const WXAPI = require('apifm-wxapi')
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
onShow: function () {
},
async bindSave(e) {
const amount = this.data.amount
if (!amount) {
wx.showToast({
title: '请填写正确的押金金额',
icon: 'none'
})
return
}
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/mpsdwi
const res= await WXAPI.payDepositV2({
token: wx.getStorageSync('token'),
amount
})
wx.hideLoading()
if (res.code == 40000) {
// 余额不够
this.setData({
money: res.data,
paymentShow: true,
nextAction: {
type: 5,
amount
}
})
return
} else if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showModal({
content: '支付成功',
showCancel: false,
success: (res) => {
wx.redirectTo({
url: "/pages/asset/index"
})
}
})
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/asset/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/deposit/pay.json
================================================
{
"usingComponents": {},
"navigationBarTitleText": "支付押金"
}
================================================
FILE: pages/deposit/pay.wxml
================================================
🔐
支付押金
完成押金支付后即可享受服务
¥
押金支付后,会显示在您的冻结余额里面
如需退还押金,请联系管理员进行退还操作
🔒
安全支付
✓
随时退还
⚡
即时到账
================================================
FILE: pages/deposit/pay.wxss
================================================
/* 页面基础样式 */
page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
/* 主容器 */
.deposit-container {
position: relative;
min-height: 100vh;
padding: 30rpx;
overflow: hidden;
}
/* 装饰背景圆圈 */
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 800rpx;
overflow: hidden;
pointer-events: none;
z-index: 0;
}
.bg-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.circle-1 {
width: 400rpx;
height: 400rpx;
top: -150rpx;
right: -100rpx;
animation: float 6s ease-in-out infinite;
}
.circle-2 {
width: 300rpx;
height: 300rpx;
top: 150rpx;
left: -100rpx;
animation: float 8s ease-in-out infinite;
}
.circle-3 {
width: 200rpx;
height: 200rpx;
top: 400rpx;
right: 50rpx;
animation: float 7s ease-in-out infinite;
}
@keyframes float {
0%, 100% {
transform: translateY(0) rotate(0deg);
}
50% {
transform: translateY(-30rpx) rotate(180deg);
}
}
/* 页面标题 */
.page-header {
position: relative;
z-index: 1;
padding: 30rpx 20rpx 40rpx;
text-align: center;
}
.header-title {
font-size: 48rpx;
font-weight: 700;
color: #ffffff;
margin-bottom: 12rpx;
letter-spacing: 2rpx;
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.header-subtitle {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
font-weight: 500;
letter-spacing: 3rpx;
text-transform: uppercase;
}
/* 押金卡片 */
.deposit-card {
position: relative;
z-index: 1;
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 32rpx;
padding: 50rpx 40rpx;
margin-bottom: 30rpx;
box-shadow: 0 20rpx 60rpx rgba(102, 126, 234, 0.25);
overflow: hidden;
}
.deposit-card::before {
content: '';
position: absolute;
top: -50%;
right: -10%;
width: 400rpx;
height: 400rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
border-radius: 50%;
}
.card-icon {
font-size: 80rpx;
text-align: center;
margin-bottom: 20rpx;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
.card-title {
font-size: 36rpx;
font-weight: 700;
color: #2d3748;
text-align: center;
margin-bottom: 12rpx;
letter-spacing: 1rpx;
position: relative;
}
.card-desc {
font-size: 24rpx;
color: #718096;
text-align: center;
margin-bottom: 40rpx;
position: relative;
}
/* 金额输入区 */
.amount-input-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx 30rpx;
margin: 30rpx 0;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
border-radius: 24rpx;
border: 3rpx solid rgba(102, 126, 234, 0.1);
transition: all 0.3s ease;
}
.amount-input-wrap:focus-within {
border-color: #667eea;
background: #ffffff;
box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.1);
}
.currency-label {
font-size: 56rpx;
font-weight: 700;
color: #667eea;
margin-right: 16rpx;
line-height: 1;
}
.amount-input {
flex: 1;
font-size: 64rpx;
font-weight: 700;
color: #2d3748;
text-align: left;
line-height: 1;
}
.input-placeholder {
color: #cbd5e0;
font-size: 32rpx;
font-weight: 500;
}
/* 支付按钮 */
.pay-btn {
width: 100%;
height: 100rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50rpx;
border: none;
box-shadow: 0 12rpx 32rpx rgba(102, 126, 234, 0.35);
margin-top: 20rpx;
padding: 0;
line-height: normal;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.pay-btn::after {
border: none;
}
.pay-btn::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.pay-btn-hover {
transform: translateY(-4rpx);
box-shadow: 0 16rpx 40rpx rgba(102, 126, 234, 0.45) !important;
}
.pay-btn-hover::before {
opacity: 1;
}
.btn-content {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.btn-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.btn-text {
font-size: 32rpx;
font-weight: 700;
color: #ffffff;
letter-spacing: 2rpx;
}
/* 提示卡片 */
.notice-card {
position: relative;
z-index: 1;
background: linear-gradient(135deg, #fff8e1 0%, #fff3e0 100%);
border-radius: 24rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 8rpx 24rpx rgba(255, 152, 0, 0.15);
border-left: 8rpx solid #ff9800;
}
.notice-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.notice-icon {
font-size: 36rpx;
margin-right: 12rpx;
}
.notice-title {
font-size: 28rpx;
font-weight: 700;
color: #e65100;
letter-spacing: 1rpx;
}
.notice-content {
padding-left: 48rpx;
}
.notice-item {
display: flex;
align-items: flex-start;
margin-bottom: 16rpx;
line-height: 1.6;
}
.notice-item:last-child {
margin-bottom: 0;
}
.notice-dot {
width: 12rpx;
height: 12rpx;
background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);
border-radius: 50%;
margin-right: 16rpx;
margin-top: 10rpx;
flex-shrink: 0;
}
.notice-text {
flex: 1;
font-size: 26rpx;
color: #5d4037;
line-height: 1.6;
}
.highlight {
color: #e65100;
font-weight: 700;
padding: 0 6rpx;
background: rgba(255, 152, 0, 0.15);
border-radius: 6rpx;
}
/* 安全提示 */
.security-tips {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: space-around;
background: rgba(255, 255, 255, 0.95);
border-radius: 24rpx;
padding: 30rpx 20rpx;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.15);
backdrop-filter: blur(10px);
}
.security-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.security-icon {
font-size: 36rpx;
margin-bottom: 8rpx;
}
.security-text {
font-size: 22rpx;
color: #718096;
font-weight: 600;
white-space: nowrap;
}
.security-divider {
width: 2rpx;
height: 50rpx;
background: linear-gradient(to bottom,
rgba(102, 126, 234, 0) 0%,
rgba(102, 126, 234, 0.3) 50%,
rgba(102, 126, 234, 0) 100%
);
}
/* 按钮基础样式重置 */
button {
background: none;
border: none;
outline: none;
}
button::after {
border: none;
}
/* 响应式适配 */
@media screen and (max-width: 320px) {
.header-title {
font-size: 40rpx;
}
.amount-input {
font-size: 52rpx;
}
.card-icon {
font-size: 64rpx;
}
}
================================================
FILE: pages/goods/fav.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.goodsFavList()
} else {
getApp().loginOK = () => {
this.goodsFavList()
}
}
})
},
onShow: function () {
},
async goodsFavList() {
// 搜索商品
wx.showLoading({
title: '加载中',
})
const _data = {
token: wx.getStorageSync('token'),
page: 1,
pageSize: 10000,
}
const res = await WXAPI.goodsFavList(_data)
wx.hideLoading()
if (res.code == 0) {
res.data.forEach(ele => {
if (ele.type == 1 && ele.json) {
ele.json = JSON.parse(ele.json)
}
})
this.setData({
goods: res.data,
})
} else {
this.setData({
goods: null
})
}
},
async removeFav(e){
const idx = e.currentTarget.dataset.idx
const fav = this.data.goods[idx]
const res = await WXAPI.goodsFavDeleteV2({
token: wx.getStorageSync('token'),
goodsId: fav.goodsId,
type: fav.type
})
if (res.code == 0) {
wx.showToast({
title: '取消收藏',
icon: 'success'
})
this.goodsFavList()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
})
================================================
FILE: pages/goods/fav.json
================================================
{
"navigationBarTitleText": "我的收藏"
}
================================================
FILE: pages/goods/fav.wxml
================================================
{{item.goodsName}}
取消收藏
{{item.json.name}}
取消收藏
💝
还没有收藏商品
快去发现心仪的商品吧
================================================
FILE: pages/goods/fav.wxss
================================================
/* 页面基础样式 */
page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
page, view, image, input {
display: block;
box-sizing: border-box;
}
/* 文本省略 */
.ellipsis {
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
word-break: break-all;
}
/* 页面容器 */
.fav-container {
position: relative;
min-height: 100vh;
padding: 30rpx 30rpx 60rpx;
overflow: hidden;
}
/* 装饰背景圆圈 */
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 600rpx;
overflow: hidden;
pointer-events: none;
z-index: 0;
}
.bg-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
.circle-1 {
width: 400rpx;
height: 400rpx;
top: -150rpx;
right: -100rpx;
animation: float 6s ease-in-out infinite;
}
.circle-2 {
width: 300rpx;
height: 300rpx;
top: 100rpx;
left: -100rpx;
animation: float 8s ease-in-out infinite;
}
.circle-3 {
width: 200rpx;
height: 200rpx;
top: 300rpx;
right: 50rpx;
animation: float 7s ease-in-out infinite;
}
@keyframes float {
0%, 100% {
transform: translateY(0) rotate(0deg);
}
50% {
transform: translateY(-30rpx) rotate(180deg);
}
}
/* 页面标题区域 */
.page-header {
position: relative;
z-index: 1;
text-align: center;
margin-bottom: 40rpx;
padding: 20rpx 0;
}
.header-title {
font-size: 48rpx;
font-weight: 800;
color: #ffffff;
margin-bottom: 10rpx;
letter-spacing: 2rpx;
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.header-subtitle {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
font-weight: 500;
letter-spacing: 3rpx;
text-transform: uppercase;
margin-bottom: 16rpx;
}
.header-count {
display: inline-block;
background: rgba(255, 255, 255, 0.2);
backdrop-filter: blur(10rpx);
-webkit-backdrop-filter: blur(10rpx);
color: #ffffff;
font-size: 24rpx;
padding: 8rpx 24rpx;
border-radius: 30rpx;
font-weight: 600;
letter-spacing: 1rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
/* 商品列表容器 */
.list2-box {
position: relative;
z-index: 1;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 24rpx;
}
/* 商品卡片 */
.list2 {
width: calc(50% - 15rpx);
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 28rpx;
overflow: hidden;
box-shadow: 0 12rpx 40rpx rgba(102, 126, 234, 0.2);
transition: all 0.3s ease;
position: relative;
}
.list2::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
opacity: 0;
transition: opacity 0.3s ease;
z-index: 0;
pointer-events: none;
}
/* 商品链接 */
.goods-link {
display: block;
position: relative;
z-index: 1;
}
/* 图片容器 */
.img-wrapper {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%;
overflow: hidden;
background: linear-gradient(135deg, #f0f0f0 0%, #e8e8e8 100%);
}
.img-wrapper .img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: transform 0.5s ease;
}
.img-wrapper .img-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to bottom,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.02) 100%
);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
.goods-link:active .img {
transform: scale(1.05);
}
.goods-link:active .img-overlay {
opacity: 1;
}
/* 商品信息区域 */
.goods-info {
padding: 20rpx 20rpx 16rpx;
position: relative;
z-index: 1;
}
.goods-info .title {
color: #2d3748;
font-size: 28rpx;
line-height: 1.5;
font-weight: 600;
min-height: 84rpx;
letter-spacing: 0.5rpx;
}
/* 删除按钮区域 */
.delete-btn-wrapper {
position: relative;
z-index: 2;
padding: 0 20rpx 20rpx;
}
.delete-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
width: 100%;
height: 64rpx;
background: linear-gradient(135deg, #fff 0%, #f8f9ff 100%);
border: 2rpx solid rgba(102, 126, 234, 0.15);
border-radius: 16rpx;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.delete-btn::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
opacity: 0;
transition: opacity 0.3s ease;
}
.delete-icon {
width: 32rpx;
height: 32rpx;
position: relative;
z-index: 1;
transition: all 0.3s ease;
}
.delete-text {
font-size: 24rpx;
color: #718096;
font-weight: 600;
position: relative;
z-index: 1;
transition: all 0.3s ease;
}
.delete-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 12rpx rgba(255, 107, 107, 0.3);
border-color: transparent;
}
.delete-btn:active::before {
opacity: 1;
}
.delete-btn:active .delete-text {
color: #ffffff;
}
.delete-btn:active .delete-icon {
filter: brightness(0) invert(1);
transform: scale(1.1);
}
/* 空状态容器 */
.empty-container {
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
min-height: 60vh;
padding: 40rpx;
}
.empty-card {
width: 100%;
max-width: 500rpx;
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 32rpx;
padding: 80rpx 60rpx;
text-align: center;
box-shadow: 0 20rpx 60rpx rgba(102, 126, 234, 0.25);
position: relative;
overflow: hidden;
}
.empty-card::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 300rpx;
height: 300rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
border-radius: 50%;
}
.empty-icon {
font-size: 120rpx;
margin-bottom: 32rpx;
animation: bounce 2s ease-in-out infinite;
position: relative;
z-index: 1;
}
@keyframes bounce {
0%, 100% {
transform: translateY(0) scale(1);
}
50% {
transform: translateY(-20rpx) scale(1.05);
}
}
.empty-title {
font-size: 32rpx;
font-weight: 700;
color: #2d3748;
margin-bottom: 16rpx;
position: relative;
z-index: 1;
letter-spacing: 1rpx;
}
.empty-desc {
font-size: 26rpx;
color: #718096;
line-height: 1.6;
position: relative;
z-index: 1;
font-weight: 500;
}
/* 响应式适配 */
@media screen and (max-width: 320px) {
.header-title {
font-size: 40rpx;
}
.list2 {
width: 100%;
}
.goods-info .title {
font-size: 26rpx;
}
}
================================================
FILE: pages/goods/his.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
/**
* 页面的初始数据
*/
data: {
name: '', // 搜索关键词
page: 1, // 读取第几页
categoryIndex: -1,
dayArray: ['全部', '一周内', '一月内', '半年内', '一年内'],
dayIndex: -1,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
name: options.name,
categoryId: options.categoryId
})
this.search()
this.readConfigVal()
// 补偿写法
getApp().configLoadOK = () => {
this.readConfigVal()
}
this.categories()
},
onShow: function () {
},
readConfigVal() {
},
search2(e) {
this.data.page = 1
this.data.name = e.detail
this.search()
},
search3() {
this.data.page = 1
this.data.name = ''
this.search()
},
async search(){
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/stigxd
const res = await WXAPI.myBuyGoodsHisV2({
page: this.data.page,
nameLike: this.data.name || '',
dateBuyBegin: this.data.dateBuyBegin || '',
dateBuyEnd: this.data.dateBuyEnd || '',
categoryId: this.data.categoryId || '',
token: wx.getStorageSync('token'),
pageSize: 20,
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
goods: res.data.result,
})
} else {
this.setData({
goods: this.data.goods.concat(res.data.result),
})
}
} else {
if (this.data.page == 1) {
this.setData({
goods: null,
})
}
}
},
onReachBottom() {
this.setData({
page: this.data.page + 1
});
this.search()
},
async categories() {
// https://www.yuque.com/apifm/nu0f75/racmle
const res = await WXAPI.goodsCategory()
if (res.code == 0) {
const categories = res.data
categories.forEach(p => {
p.childs = categories.filter(ele => {
return p.id == ele.pid
})
})
this.setData({
categories: [{id: 0, name: '全部'}].concat(res.data.filter(ele => ele.level == 1))
})
}
},
categoryChange(e) {
this.setData({
categoryIndex: e.detail.value,
categoryId: this.data.categories[e.detail.value].id
})
this.data.page = 1
this.search()
},
dayChange(e) {
const dayIndex = e.detail.value
this.data.page = 1
let dateBuyBegin = ''
if (dayIndex == 0) {
// 全部
dateBuyBegin = ''
}
if (dayIndex == 1) {
// 一周内
dateBuyBegin = dayjs().subtract(7, 'day').format('YYYY-MM-DD')
}
if (dayIndex == 2) {
// 一月内
dateBuyBegin = dayjs().subtract(1, 'month').format('YYYY-MM-DD')
}
if (dayIndex == 3) {
// 半年内
dateBuyBegin = dayjs().subtract(6, 'month').format('YYYY-MM-DD')
}
if (dayIndex == 4) {
// 1年内
dateBuyBegin = dayjs().subtract(1, 'year').format('YYYY-MM-DD')
}
this.setData({
dayIndex,
dateBuyBegin,
})
this.search()
},
})
================================================
FILE: pages/goods/his.json
================================================
{
"usingComponents": {},
"navigationBarTitleText": "历史购买记录"
}
================================================
FILE: pages/goods/his.wxml
================================================
📦
{{ categoryIndex == -1 ? '全部分类' : categories[categoryIndex].name }}
▼
⏰
{{ dayIndex == -1 ? '全部时间' : dayArray[dayIndex] }}
▼
🛍️
暂无浏览记录
快去逛逛吧~
去首页看看
已浏览
{{item.goodsName}}
¥
{{item.minPrice || '0.00'}}
{{item.numberSells}}人付款
{{item.dateAdd}}
再看看
— 向下滑动加载更多 —
================================================
FILE: pages/goods/his.wxss
================================================
/* ==================== 全局样式 ==================== */
page {
background: #f5f5f5;
min-height: 100vh;
}
page, view, image, input {
display: block;
box-sizing: border-box;
}
/* ==================== 页面头部 ==================== */
.page-header {
background: #fff;
padding: 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.header-title {
display: flex;
align-items: center;
color: #333;
}
.title-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.title-text {
font-size: 36rpx;
font-weight: 600;
letter-spacing: 1rpx;
}
.title-count {
margin-left: 16rpx;
background: #fff5f5;
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: #e4393c;
border: 1rpx solid #ffebeb;
}
/* ==================== 搜索栏 ==================== */
.search-container {
background: #fff;
padding: 16rpx 16rpx 0;
}
/* ==================== 筛选条件 ==================== */
.filters-wrapper {
background: #fff;
padding: 16rpx 16rpx 16rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.filters {
display: flex;
align-items: center;
background: #fff;
border-radius: 8rpx;
padding: 16rpx 20rpx;
border: 1rpx solid #e5e5e5;
}
.filter-item {
flex: 1;
font-size: 28rpx;
}
.picker-content {
display: flex;
align-items: center;
justify-content: center;
color: #666;
transition: all 0.3s ease;
}
.picker-content.active {
color: #e4393c;
font-weight: 500;
}
.picker-icon {
font-size: 28rpx;
margin-right: 8rpx;
}
.picker-text {
font-size: 28rpx;
}
.picker-arrow {
font-size: 20rpx;
margin-left: 8rpx;
color: #999;
}
.filter-divider {
width: 1rpx;
height: 28rpx;
background: #e5e5e5;
margin: 0 20rpx;
}
/* ==================== 空状态 ==================== */
.empty-container {
min-height: 60vh;
display: flex;
align-items: center;
justify-content: center;
padding: 100rpx 0;
background: #fff;
margin-top: 20rpx;
}
.empty-content {
text-align: center;
}
.empty-icon {
font-size: 140rpx;
margin-bottom: 32rpx;
opacity: 0.6;
}
.empty-text {
font-size: 32rpx;
color: #333;
font-weight: 500;
margin-bottom: 16rpx;
}
.empty-tip {
font-size: 26rpx;
color: #999;
margin-bottom: 48rpx;
}
.empty-btn {
display: inline-block;
background: #e4393c;
color: #fff;
padding: 20rpx 60rpx;
border-radius: 40rpx;
font-size: 28rpx;
transition: all 0.3s ease;
}
.empty-btn:active {
background: #c81623;
}
/* ==================== 商品容器 ==================== */
.goods-container {
padding: 20rpx 0 32rpx;
}
.list2-box {
padding: 0 16rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
/* ==================== 商品卡片 ==================== */
.list2 {
width: 355rpx;
margin-bottom: 16rpx;
background: #fff;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.list2:active {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.goods-card {
display: block;
}
/* 图片区域 */
.img-wrapper {
position: relative;
width: 100%;
height: 355rpx;
overflow: hidden;
background: #f8f8f8;
}
.img {
width: 100%;
height: 100%;
}
.viewed-badge {
position: absolute;
top: 12rpx;
left: 0;
background: rgba(228, 57, 60, 0.9);
color: #fff;
font-size: 20rpx;
padding: 6rpx 16rpx;
border-radius: 0 20rpx 20rpx 0;
font-weight: 400;
}
/* 商品信息 */
.goods-info {
padding: 16rpx;
}
.title {
color: #333;
font-size: 26rpx;
line-height: 38rpx;
height: 76rpx;
font-weight: 400;
margin-bottom: 12rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
/* 价格区域 */
.price-section {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 12rpx;
}
.price-wrapper {
display: flex;
align-items: baseline;
color: #e4393c;
}
.price-symbol {
font-size: 22rpx;
font-weight: 500;
margin-right: 2rpx;
}
.price-value {
font-size: 32rpx;
font-weight: 600;
font-family: Arial, 'PingFang SC', sans-serif;
}
.sales-info {
font-size: 22rpx;
color: #999;
}
/* 标签 */
.tags {
display: flex;
flex-wrap: wrap;
gap: 8rpx;
}
.tag {
display: inline-flex;
align-items: center;
}
.tag-text {
font-size: 20rpx;
color: #999;
background: #f7f7f7;
padding: 4rpx 12rpx;
border-radius: 4rpx;
}
/* 快捷操作按钮 */
.quick-actions {
padding: 0 16rpx 16rpx;
display: flex;
gap: 12rpx;
}
.action-btn {
flex: 1;
text-align: center;
padding: 16rpx 0;
border-radius: 40rpx;
font-size: 26rpx;
font-weight: 500;
transition: all 0.3s ease;
}
.action-btn.primary {
background: #e4393c;
color: #fff;
}
.action-btn:active {
background: #c81623;
}
/* ==================== 加载提示 ==================== */
.loading-tip {
text-align: center;
padding: 40rpx 0 60rpx;
color: #999;
font-size: 24rpx;
}
.loading-tip text {
position: relative;
display: inline-block;
}
.loading-tip text::before,
.loading-tip text::after {
content: '';
position: absolute;
top: 50%;
width: 60rpx;
height: 1rpx;
background: #e0e0e0;
}
.loading-tip text::before {
right: 100%;
margin-right: 20rpx;
}
.loading-tip text::after {
left: 100%;
margin-left: 20rpx;
}
/* ==================== 其他样式 ==================== */
.ellipsis {
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
word-break: break-all;
}
.originalPrice {
color: #aaa;
text-decoration: line-through;
margin-left: 20rpx;
font-size: 24rpx;
}
================================================
FILE: pages/goods/list-vop.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
listType: 1, // 1为1个商品一行,2为2个商品一行
name: '', // 搜索关键词
orderBy: '', // 排序规则
page: 1 // 读取第几页
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
name: options.name,
cid1: options.cid1,
cid2: options.cid2
})
this.search()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
async search(){
if (!this.data.cid1 && !this.data.cid2) {
return
}
wx.showLoading({
title: '加载中',
})
const _data = {
sortType: this.data.orderBy,
page: this.data.page,
pageSize: 20,
}
if (this.data.name) {
_data.keyword = this.data.name
}
if (this.data.cid1) {
_data.cid1 = this.data.cid1
}
if (this.data.cid2) {
_data.cid2 = this.data.cid2
}
const res = await WXAPI.jdvopGoodsListV3(_data)
wx.hideLoading()
if (res.code == 0) {
res.data.result.forEach(ele => {
ele.pic = res.data.imageDomain + ele.pic
})
if (this.data.page == 1) {
this.setData({
goods: res.data.result,
})
} else {
this.setData({
goods: this.data.goods.concat(res.data.result),
})
}
} else {
if (this.data.page == 1) {
this.setData({
goods: null,
})
} else {
wx.showToast({
title: '没有更多了',
icon: 'none'
})
}
}
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
this.setData({
page: this.data.page + 1
});
this.search()
},
changeShowType(){
if (this.data.listType == 1) {
this.setData({
listType: 2
})
} else {
this.setData({
listType: 1
})
}
},
bindinput(e){
this.setData({
name: e.detail.value
})
},
bindconfirm(e){
this.setData({
page: 1,
name: e.detail.value
})
this.search()
},
filter(e){
this.setData({
page: 1,
orderBy: e.currentTarget.dataset.val
})
this.search()
},
async addShopCar(e) {
const curGood = this.data.goods.find(ele => {
return ele.id == e.currentTarget.dataset.id
})
if (!curGood) {
return
}
if (curGood.stores <= 0) {
wx.showToast({
title: '已售罄~',
icon: 'none'
})
return
}
this.addShopCarCheck({
goodsId: curGood.id,
buyNumber: 1,
sku: []
})
},
async addShopCarCheck(options) {
this.addShopCarDone(options)
},
async addShopCarDone(options) {
const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), options.goodsId, options.buyNumber, options.sku)
if (res.code == 30002) {
// 需要选择规格尺寸
const skuCurGoodsRes = await WXAPI.goodsDetail(options.goodsId)
if (skuCurGoodsRes.code != 0) {
wx.showToast({
title: skuCurGoodsRes.msg,
icon: 'none'
})
return
}
const skuCurGoods = skuCurGoodsRes.data
skuCurGoods.basicInfo.storesBuy = 1
this.setData({
skuCurGoods
})
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '加入成功',
icon: 'success'
})
this.setData({
skuCurGoods: null
})
},
storesJia() {
const skuCurGoods = this.data.skuCurGoods
if (skuCurGoods.basicInfo.storesBuy < skuCurGoods.basicInfo.stores) {
skuCurGoods.basicInfo.storesBuy++
this.setData({
skuCurGoods
})
}
},
storesJian() {
const skuCurGoods = this.data.skuCurGoods
if (skuCurGoods.basicInfo.storesBuy > 1) {
skuCurGoods.basicInfo.storesBuy--
this.setData({
skuCurGoods
})
}
},
closeSku() {
this.setData({
skuCurGoods: null
})
wx.showTabBar()
},
skuSelect(e) {
const pid = e.currentTarget.dataset.pid
const id = e.currentTarget.dataset.id
// 处理选中
const skuCurGoods = this.data.skuCurGoods
const property = skuCurGoods.properties.find(ele => { return ele.id == pid })
property.childsCurGoods.forEach(ele => {
if (ele.id == id) {
ele.active = true
} else {
ele.active = false
}
})
this.setData({
skuCurGoods
})
},
addCarSku() {
const skuCurGoods = this.data.skuCurGoods
const propertySize = skuCurGoods.properties.length // 有几组SKU
const sku = []
skuCurGoods.properties.forEach(p => {
const o = p.childsCurGoods.find(ele => { return ele.active })
if (!o) {
return
}
sku.push({
optionId: o.propertyId,
optionValueId: o.id
})
})
if (sku.length != propertySize) {
wx.showToast({
title: '请选择规格',
icon: 'none'
})
return
}
const options = {
goodsId: skuCurGoods.basicInfo.id,
buyNumber: skuCurGoods.basicInfo.storesBuy,
sku
}
this.addShopCarDone(options)
},
})
================================================
FILE: pages/goods/list-vop.json
================================================
{
"navigationBarTitleText": "商品列表"
}
================================================
FILE: pages/goods/list-vop.wxml
================================================
综合
新品
销量
价格
{{item.skuName}}
¥ {{item.priceSale}}
{{item.skuName}}
¥ {{item.priceSale}}
================================================
FILE: pages/goods/list-vop.wxss
================================================
page {
background: #f5f5f5;
}
page,view,image,input {
display: block;
box-sizing: border-box;
}
.header {
padding: 32rpx;
background: #fff;
display: flex;
align-items: center;
}
.header .search {
position: relative;
width: 750rpx;
height: 66rpx;
}
.header .search input {
border: 1rpx solid #e3e3e3;
width: 100%;
height: 100%;
border-radius: 30rpx;
padding-left: 60rpx;
}
.header .search image {
width: 35rpx;
height: 35rpx;
position: absolute;
top: 16rpx;
right: 40rpx;
z-index: 9999;
}
.header .show-type {
width: 40rpx;
height: 40rpx;
margin-left: 20rpx;
}
.line {
width: 100vw;
height: 2rpx;
background: #dfdfdf;
}
.filters {
width: 100vw;
height: 88rpx;
background: #fff;
display: flex;
justify-content: space-around;
}
.filters .item {
line-height: 88rpx;
}
.filters .active {
color:#fa1e26;
}
.list1 {
margin: 16rpx;
width: 718rpx;
height: 220rpx;
display: flex;
background: #fff;
border-radius: 30rpx;
overflow: hidden;
position: relative;
}
.list1 .img {
width: 220rpx;
height: 220rpx;
flex-shrink: 0;
}
.list1 .goods-info {
padding: 16rpx 32rpx 0 24rpx;
width: 100%;
}
.list1 .goods-info .title {
color: #333;
font-size: 30rpx;
}
.ellipsis {
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
word-break: break-all;
}
.list1 .goods-info .price {
color: #FF3B30;
font-size: 34rpx;
}
.list1 .goods-info .buy-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.list1 .goods-info .buy-info .num {
font-size:24rpx;
color:#999999;
}
.list1 .goods-info .buy-info .car {
position: absolute;
right: 16rpx;
bottom: 16rpx;
width: 50rpx;
height: 50rpx;
}
.list2-box {
margin: 16rpx;
width: 718rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list2 {
margin: 16rpx 0;
width: 350rpx;
background: #fff;
border-radius: 30rpx;
overflow: hidden;
position: relative;
}
.list2 .img {
width: 350rpx;
height: 350rpx;
}
.list2 .goods-info {
padding: 16rpx;
}
.list2 .goods-info .title {
color: #333;
font-size: 30rpx;
}
.list2 .goods-info .price {
color: #FF3B30;
font-size: 34rpx;
}
.list2 .goods-info .buy-info {
display: flex;
justify-content: space-between;
align-items: center;
}
.list2 .goods-info .buy-info .num {
font-size:24rpx;
color:#999999;
}
.list2 .goods-info .buy-info .car {
width: 50rpx;
height: 50rpx;
position: absolute;
right: 16rpx;
bottom: 16rpx;
}
.sku-mask {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.3);
}
.sku-container {
position: fixed;
width: 100vw;
bottom: 90rpx;
left: 0;
background: #fff;
padding: 32rpx 32rpx 0 32rpx;
}
.sku-container .close {
position: absolute;
width: 54rpx;
height: 54rpx;
top: 16rpx;
right: 16rpx;
/* border: 1rpx solid #666;
border-radius: 50%; */
}
.sku-container .sku {
border-bottom: 1rpx solid #eee;
padding-bottom: 24rpx;
margin-bottom: 16rpx;
}
.sku-container .sku .t {
color: #333;
}
.sku-container .sku .items {
display: flex;
flex-wrap: wrap;
}
.sku-container .sku .items text {
padding: 8rpx;
border: 1rpx solid #999;
color: #999;
margin: 24rpx 24rpx 0 0;
font-size: 26rpx;
border-radius: 12rpx;
}
.sku-container .sku .items text.active {
border: 1rpx solid #e64340;
color: #e64340;
}
.sku-container .num {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
}
.sku-container .num .t {
color: #333;
}
.sku-container .num .num-box {
display: flex;
}
.sku-container .num .num-box .a {
width: 64rpx;
height: 64rpx;
border: 1rpx solid #999;
text-align: center;
line-height: 64rpx;
font-size: 46rpx;
color: #666;
}
.sku-container .num .num-box .b {
color: #333;
line-height: 64rpx;
padding: 0 32rpx;
border-top: 1rpx solid #999;
border-bottom: 1rpx solid #999;
}
.sku-btn {
width: 100vw;
height: 90rpx;
line-height: 90rpx;
background: #e64340;
color: #fff;
position: fixed;
bottom: 0;
left: 0;
text-align: center;
}
================================================
FILE: pages/goods/list.js
================================================
const WXAPI = require('apifm-wxapi')
const TOOLS = require('../../utils/tools.js') // TOOLS.showTabBarBadge();
Page({
/**
* 页面的初始数据
*/
data: {
listType: 1, // 1为1个商品一行,2为2个商品一行
name: '', // 搜索关键词
orderBy: '', // 排序规则
page: 1 // 读取第几页
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
name: options.name,
categoryId: options.categoryId
})
this.search()
this.readConfigVal()
// 补偿写法
getApp().configLoadOK = () => {
this.readConfigVal()
}
},
onShow: function () {
},
readConfigVal() {
const show_seller_number = wx.getStorageSync('show_seller_number')
const goods_search_show_type = wx.getStorageSync('goods_search_show_type')
let listType = 1
if (goods_search_show_type == 2) {
listType = 2
}
this.setData({
show_seller_number,
listType
})
},
async search(){
wx.showLoading({
title: '加载中',
})
const _data = {
orderBy: this.data.orderBy,
page: this.data.page,
pageSize: 20,
}
if (this.data.name) {
_data.k = this.data.name
}
if (this.data.categoryId) {
_data.categoryId = this.data.categoryId
}
const res = await WXAPI.goodsv2(_data)
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
goods: res.data.result,
})
} else {
this.setData({
goods: this.data.goods.concat(res.data.result),
})
}
} else {
if (this.data.page == 1) {
this.setData({
goods: null,
})
} else {
wx.showToast({
title: '没有更多了',
icon: 'none'
})
}
}
},
onReachBottom() {
this.setData({
page: this.data.page + 1
});
this.search()
},
changeShowType(){
if (this.data.listType == 1) {
this.setData({
listType: 2
})
} else {
this.setData({
listType: 1
})
}
},
bindinput(e){
this.setData({
name: e.detail.value
})
},
bindconfirm(e){
this.setData({
page: 1,
name: e.detail.value
})
this.search()
},
filter(e){
this.setData({
page: 1,
orderBy: e.currentTarget.dataset.val
})
this.search()
},
async addShopCar(e) {
const curGood = this.data.goods.find(ele => {
return ele.id == e.currentTarget.dataset.id
})
if (!curGood) {
return
}
if (curGood.stores <= 0) {
wx.showToast({
title: '已售罄~',
icon: 'none'
})
return
}
if (!curGood.propertyIds && !curGood.hasAddition) {
// 直接调用加入购物车方法
const res = await WXAPI.shippingCarInfoAddItem(wx.getStorageSync('token'), curGood.id, 1, [])
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code == 30002) {
// 需要选择规格尺寸
this.setData({
skuCurGoods: curGood
})
} else if (res.code == 0) {
wx.showToast({
title: '加入成功',
icon: 'success'
})
wx.showTabBar()
TOOLS.showTabBarBadge() // 获取购物车数据,显示TabBarBadge
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
} else {
// 需要选择 SKU 和 可选配件
this.setData({
skuCurGoods: curGood
})
}
},
})
================================================
FILE: pages/goods/list.json
================================================
{
"navigationBarTitleText": "商品列表"
}
================================================
FILE: pages/goods/list.wxml
================================================
综合
新品
销量
价格
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.id
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.id
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.id
} else {
return '/pages/goods-details/index?id=' + item.id
}
}
}
{{item.name}}
{{item.characteristic}}
¥ {{item.minPrice}}¥ {{item.originalPrice}}
已售出{{item.numberSells}}件
{{item.name}}
{{item.characteristic}}
¥ {{item.minPrice}}¥ {{item.originalPrice}}
{{item.numberOrders}}人已购{{item.numberSells}}件
================================================
FILE: pages/goods/list.wxss
================================================
/* 京东风格 - 页面基础样式 */
page {
background: #F5F5F5;
}
page, view, image, input {
display: block;
box-sizing: border-box;
}
/* 顶部搜索栏 - 京东风格 */
.header {
padding: 20rpx 24rpx;
background: linear-gradient(135deg, #E4393C 0%, #E1251B 100%);
display: flex;
align-items: center;
box-shadow: 0 4rpx 12rpx rgba(225, 37, 27, 0.15);
}
.header .search {
position: relative;
flex: 1;
height: 64rpx;
}
.header .search input {
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.95);
border-radius: 32rpx;
padding: 0 80rpx 0 32rpx;
font-size: 28rpx;
color: #333;
border: none;
}
.header .search input::placeholder {
color: #999;
}
.header .search image {
width: 32rpx;
height: 32rpx;
position: absolute;
top: 16rpx;
right: 24rpx;
z-index: 10;
}
.header .show-type {
width: 40rpx;
height: 40rpx;
margin-left: 20rpx;
filter: brightness(0) invert(1);
}
/* 筛选栏 - 京东风格 */
.filters {
width: 100vw;
height: 88rpx;
background: #FFFFFF;
display: flex;
justify-content: space-around;
align-items: center;
border-bottom: 1rpx solid #F0F0F0;
position: relative;
}
.filters .item {
font-size: 28rpx;
color: #666;
font-weight: 500;
padding: 0 20rpx;
transition: all 0.3s ease;
}
.filters .active {
color: #E4393C;
font-weight: 600;
position: relative;
}
.filters .active::after {
content: '';
position: absolute;
bottom: -14rpx;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background: #E4393C;
border-radius: 2rpx;
}
/* 列表模式1 - 横向卡片 */
.list1 {
margin: 20rpx 24rpx 0;
width: 702rpx;
display: flex;
background: #FFFFFF;
border-radius: 16rpx;
position: relative;
overflow: hidden;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.list1:active {
transform: scale(0.98);
}
.list1 .img {
width: 240rpx;
height: 240rpx;
flex-shrink: 0;
background: #F8F8F8;
}
.list1 .goods-info {
padding: 20rpx 24rpx;
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.list1 .goods-info .title {
color: #333333;
font-size: 28rpx;
line-height: 40rpx;
font-weight: 500;
margin-bottom: 8rpx;
}
.list1 .goods-info .characteristic {
font-size: 24rpx;
color: #999;
line-height: 34rpx;
margin-bottom: 12rpx;
}
.ellipsis {
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
word-break: break-all;
}
.list1 .goods-info .price {
color: #E4393C;
font-size: 36rpx;
font-weight: 700;
margin-bottom: 8rpx;
display: flex;
align-items: baseline;
}
.list1 .goods-info .price::before {
content: '¥';
font-size: 24rpx;
font-weight: 500;
margin-right: 2rpx;
}
.list1 .goods-info .buy-info {
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 60rpx;
}
.list1 .goods-info .buy-info .num {
font-size: 22rpx;
color: #999999;
background: #F5F5F5;
padding: 4rpx 12rpx;
border-radius: 4rpx;
}
.list1 .goods-info .buy-info .car {
position: absolute;
right: 20rpx;
bottom: 20rpx;
width: 56rpx;
height: 56rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
/* 购物车图标设置为白色 */
.list1 .goods-info .buy-info .car .van-icon {
color: #FFFFFF !important;
}
/* 列表模式2 - 网格布局 */
.list2-box {
padding: 12rpx 20rpx;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list2 {
margin: 12rpx 0;
width: 345rpx;
background: #FFFFFF;
border-radius: 16rpx;
overflow: hidden;
position: relative;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.list2:active {
transform: scale(0.97);
}
.list2 .img {
width: 345rpx;
height: 345rpx;
background: #F8F8F8;
}
.list2 .goods-info {
padding: 16rpx 16rpx 20rpx;
}
.list2 .goods-info .title {
color: #333333;
font-size: 26rpx;
line-height: 38rpx;
font-weight: 500;
height: 76rpx;
margin-bottom: 8rpx;
}
.list2 .goods-info .characteristic {
font-size: 22rpx;
color: #999;
line-height: 32rpx;
margin-bottom: 12rpx;
}
.list2 .goods-info .price {
color: #E4393C;
font-size: 32rpx;
font-weight: 700;
margin-bottom: 8rpx;
display: flex;
align-items: baseline;
}
.list2 .goods-info .price::before {
content: '¥';
font-size: 22rpx;
font-weight: 500;
margin-right: 2rpx;
}
.list2 .goods-info .buy-info {
display: flex;
justify-content: space-between;
align-items: center;
padding-right: 60rpx;
}
.list2 .goods-info .buy-info .num {
font-size: 20rpx;
color: #999999;
background: #F5F5F5;
padding: 4rpx 10rpx;
border-radius: 4rpx;
}
.list2 .goods-info .buy-info .car {
width: 52rpx;
height: 52rpx;
position: absolute;
right: 16rpx;
bottom: 16rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
/* 购物车图标设置为白色 */
.list2 .goods-info .buy-info .car .van-icon {
color: #FFFFFF !important;
}
/* 原价样式 */
.originalPrice {
color: #BBBBBB;
text-decoration: line-through;
margin-left: 12rpx;
font-size: 22rpx;
font-weight: 400;
}
================================================
FILE: pages/goods-details/day.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
data: {
list: undefined,
maxDate: dayjs().add(7, 'day').valueOf(),
},
onLoad(options) {
this.setData({
goodsId: options.goodsId
})
this.goodsPriceDaily()
},
onShow() {
},
async goodsPriceDaily() {
// https://www.yuque.com/apifm/nu0f75/zg7uw6
const res = await WXAPI.goodsPriceDaily(this.data.goodsId)
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
const list = res.data.filter(ele => ele.stores > 0)
this.setData({
list
})
},
async onSelect(event) {
event.detail.forEach(ele => {
const day = dayjs(ele).format('YYYY-MM-DD')
const item = this.data.list.find(a => a.day == day)
if (!item) {
wx.showModal({
content: day + '预约已满,请更换日期'
})
}
})
},
async onConfirm(event) {
const days = []
event.detail.forEach(ele => {
days.push(dayjs(ele).format('YYYY-MM-DD'))
})
const goodsJsonStr = [{
goodsId: this.data.goodsId,
number: days.length,
days
}]
const d = {
token: wx.getStorageSync('token'),
goodsJsonStr: JSON.stringify(goodsJsonStr),
}
// https://www.yuque.com/apifm/nu0f75/qx4w98
const res = await WXAPI.orderCreate(d)
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
this.setData({
orderId: res.data.id,
money: res.data.amountReal,
paymentShow: true,
nextAction: {
type: 0,
id: res.data.id
}
})
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/order-details/index?id=' + this.data.orderId,
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/goods-details/day.json
================================================
{
"navigationBarTitleText": "按天定价演示"
}
================================================
FILE: pages/goods-details/day.wxml
================================================
================================================
FILE: pages/goods-details/day.wxss
================================================
/* pages/goods-details/day.wxss */
================================================
FILE: pages/goods-details/index.js
================================================
const WXAPI = require('apifm-wxapi')
const TOOLS = require('../../utils/tools.js')
const AUTH = require('../../utils/auth')
const CONFIG = require('../../config.js')
import Poster from 'wxa-plugin-canvas/poster/poster'
Page({
data: {
createTabs: false, //绘制tabs
goodsDetail: {},
hasMoreSelect: false,
selectSizePrice: 0,
selectSizeOPrice: 0,
totalScoreToPay: 0,
shopNum: 0,
hideShopPopup: true,
buyNumber: 0,
buyNumMin: 1,
buyNumMax: 0,
propertyChildIds: "",
propertyChildNames: "",
canSubmit: false, // 选中规格尺寸时候是否允许加入购物车
shopType: "addShopCar", //购物类型,加入购物车或立即购买,默认为加入购物车
},
bindscroll(e) {
if (this.data.tabclicked) {
return
}
//计算页面 轮播图、详情、评价(砍价)view 高度
this.getTopHeightFunction()
var tabsHeight = this.data.tabsHeight //顶部距离(tabs高度)
if (this.data.tabs[0].topHeight-tabsHeight<=0 && 0 < this.data.tabs[1].topHeight-tabsHeight) { //临界值,根据自己的需求来调整
this.setData({
active: this.data.tabs[0].tabs_name //设置当前标签栏
})
} else if (this.data.tabs.length == 2) {
this.setData({
active: this.data.tabs[1].tabs_name
})
} else if (this.data.tabs[1].topHeight-tabsHeight<=0 && 0 < this.data.tabs[2].topHeight-tabsHeight) {
this.setData({
active: this.data.tabs[1].tabs_name
})
} else if (this.data.tabs[2].topHeight-tabsHeight<=0) {
this.setData({
active: this.data.tabs[2].tabs_name
})
}
},
onLoad(e) {
// e.id = 122843
// 读取分享链接中的邀请人编号
if (e && e.inviter_id) {
wx.setStorageSync('referrer', e.inviter_id)
}
// 读取小程序码中的邀请人编号
if (e && e.scene) {
const scene = decodeURIComponent(e.scene) // 处理扫码进商品详情页面的逻辑
if (scene && scene.split(',').length >= 2) {
e.id = scene.split(',')[0]
wx.setStorageSync('referrer', scene.split(',')[1])
}
}
this.data.goodsId = e.id
this.data.kjJoinUid = e.kjJoinUid
let goodsDetailSkuShowType = wx.getStorageSync('goodsDetailSkuShowType')
if (!goodsDetailSkuShowType) {
goodsDetailSkuShowType = 0
}
// 补偿写法
getApp().configLoadOK = () => {
this.readConfigVal()
}
this.setData({
goodsDetailSkuShowType,
curuid: wx.getStorageSync('uid'),
customerServiceType: CONFIG.customerServiceType
})
this.readConfigVal()
this.getGoodsDetailAndKanjieInfo(this.data.goodsId)
this.shippingCartInfo()
this.goodsAddition()
// 弹出编辑昵称头像框
getApp().initNickAvatarUrlPOP(this)
},
readConfigVal() {
// 读取系统参数
const hide_reputation = wx.getStorageSync('hide_reputation')
let tabs = [{
tabs_name: '商品简介',
view_id: 'swiper-container',
topHeight: 0
}, {
tabs_name: '商品详情',
view_id: 'goods-des-info',
topHeight: 0,
}, {
tabs_name: '商品评价',
view_id: 'reputation',
topHeight: 0,
}]
if (hide_reputation == '1') {
// 隐藏评价
tabs = [{
tabs_name: '商品简介',
view_id: 'swiper-container',
topHeight: 0
}, {
tabs_name: '商品详情',
view_id: 'goods-des-info',
topHeight: 0,
}]
} else {
// 读取评价
if (!this.data.reputation) { // 保证只读取一次
this.reputation(this.data.goodsId)
}
}
this.setData({
hide_reputation,
tabs
})
},
async goodsAddition() {
const res = await WXAPI.goodsAddition(this.data.goodsId)
if (res.code == 0) {
this.setData({
goodsAddition: res.data,
hasMoreSelect: true,
})
}
},
async shippingCartInfo() {
const number = await TOOLS.showTabBarBadge(true)
this.setData({
shopNum: number
})
},
onShow() {
this.setData({
createTabs: true //绘制tabs
})
//计算tabs高度
var query = wx.createSelectorQuery();
query.select('#tabs').boundingClientRect((rect) => {
var tabsHeight = rect.height
this.setData({
tabsHeight:tabsHeight
})
}).exec()
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.goodsFavCheck()
}
})
},
getTopHeightFunction() {
var that = this
var tabs = that.data.tabs
tabs.forEach((element, index) => {
var viewId = "#" + element.view_id
that.getTopHeight(viewId, index)
});
},
getTopHeight(viewId, index) {
var query = wx.createSelectorQuery();
query.select(viewId).boundingClientRect((rect) => {
if (!rect) {
return
}
let top = rect.top
var tabs = this.data.tabs
tabs[index].topHeight = top
this.setData({
tabs: tabs
})
}).exec()
},
async goodsFavCheck() {
const res = await WXAPI.goodsFavCheck(wx.getStorageSync('token'), this.data.goodsId)
if (res.code == 0) {
this.setData({
faved: true
})
} else {
this.setData({
faved: false
})
}
},
async addFav() {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
if (this.data.faved) {
// 取消收藏
WXAPI.goodsFavDelete(wx.getStorageSync('token'), '', this.data.goodsId).then(res => {
this.goodsFavCheck()
})
} else {
// 加入收藏
WXAPI.goodsFavPut(wx.getStorageSync('token'), this.data.goodsId).then(res => {
this.goodsFavCheck()
})
}
} else {
wx.navigateTo({
url: '/pages/login/index',
})
}
})
},
async getGoodsDetailAndKanjieInfo(goodsId) {
const token = wx.getStorageSync('token')
const that = this;
const goodsDetailRes = await WXAPI.goodsDetail(goodsId, token ? token : '')
const goodsKanjiaSetRes = await WXAPI.kanjiaSet(goodsId)
if (goodsDetailRes.code == 0) {
if (!goodsDetailRes.data.pics || goodsDetailRes.data.pics.length == 0) {
goodsDetailRes.data.pics = [{
pic: goodsDetailRes.data.basicInfo.pic
}]
}
const _data = {
goodsDetail: goodsDetailRes.data,
selectSizePrice: goodsDetailRes.data.basicInfo.minPrice,
selectSizeOPrice: goodsDetailRes.data.basicInfo.originalPrice,
totalScoreToPay: goodsDetailRes.data.basicInfo.minScore,
buyNumMax: goodsDetailRes.data.basicInfo.stores,
buyNumber: (goodsDetailRes.data.basicInfo.stores > 0) ? 1 : 0
}
if (goodsDetailRes.data.properties) {
_data.hasMoreSelect = true
}
if (goodsDetailRes.data.basicInfo.shopId) {
this.shopSubdetail(goodsDetailRes.data.basicInfo.shopId)
}
if (goodsDetailRes.data.basicInfo.pingtuan) {
that.pingtuanList(goodsId)
}
that.data.goodsDetail = goodsDetailRes.data;
if (goodsDetailRes.data.basicInfo.videoId) {
that.getVideoSrc(goodsDetailRes.data.basicInfo.videoId);
}
if (goodsKanjiaSetRes.code == 0) {
_data.curGoodsKanjia = goodsKanjiaSetRes.data[0]
that.data.kjId = _data.curGoodsKanjia.id
// 获取当前砍价进度
if (!that.data.kjJoinUid) {
that.data.kjJoinUid = wx.getStorageSync('uid')
}
const curKanjiaprogress = await WXAPI.kanjiaDetail(_data.curGoodsKanjia.id, that.data.kjJoinUid)
const myHelpDetail = await WXAPI.kanjiaHelpDetail(wx.getStorageSync('token'), _data.curGoodsKanjia.id, that.data.kjJoinUid)
if (curKanjiaprogress.code == 0) {
_data.curKanjiaprogress = curKanjiaprogress.data
}
if (myHelpDetail.code == 0) {
_data.myHelpDetail = myHelpDetail.data
}
//砍价商品 tabs栏显示砍价情况
// var tabs = that.data.tabs
// tabs[2].tabs_name="砍价记录"
// tabs[2].view_id="kanjia"
// that.setData({
// tabs:tabs
// })
}
if (goodsDetailRes.data.basicInfo.pingtuan) {
const pingtuanSetRes = await WXAPI.pingtuanSet(goodsId)
if (pingtuanSetRes.code == 0) {
_data.pingtuanSet = pingtuanSetRes.data
// 如果是拼团商品, 默认显示拼团价格
_data.selectSizePrice = goodsDetailRes.data.basicInfo.pingtuanPrice
}
}
that.setData(_data)
}
},
async shopSubdetail(shopId) {
const res = await WXAPI.shopSubdetail(shopId)
if (res.code == 0) {
this.setData({
shopSubdetail: res.data
})
}
},
goShopCar: function () {
wx.reLaunch({
url: "/pages/shop-cart/index"
});
},
toAddShopCar: function () {
this.setData({
shopType: "addShopCar"
})
this.bindGuiGeTap();
},
tobuy: function () {
this.setData({
shopType: "tobuy"
});
this.bindGuiGeTap();
},
toPingtuan: function (e) {
let pingtuanopenid = 0
if (e.currentTarget.dataset.pingtuanopenid) {
pingtuanopenid = e.currentTarget.dataset.pingtuanopenid
}
this.setData({
shopType: "toPingtuan",
selectSizePrice: this.data.goodsDetail.basicInfo.pingtuanPrice,
selectSizeOPrice: this.data.goodsDetail.basicInfo.originalPrice,
pingtuanopenid: pingtuanopenid,
hideShopPopup: false,
skuGoodsPic: this.data.goodsDetail.basicInfo.pic
});
},
/**
* 规格选择弹出框
*/
bindGuiGeTap: function () {
this.setData({
hideShopPopup: false,
selectSizePrice: this.data.goodsDetail.basicInfo.minPrice,
selectSizeOPrice: this.data.goodsDetail.basicInfo.originalPrice,
skuGoodsPic: this.data.goodsDetail.basicInfo.pic
})
},
/**
* 规格选择弹出框隐藏
*/
closePopupTap: function () {
this.setData({
hideShopPopup: true
})
},
stepChange(event) {
this.setData({
buyNumber: event.detail
})
},
// 判断当前商品是否支持某个sku的属性
checkHasSkuItems(sk) {
this.data.goodsDetail.skuList.filter(ele => {
const a = this.data.goodsDetail.properties.filter(ele => {
return ele.optionValueId
})
console.log(a);
for (let index = 0; index < array.length; index++) {
const element = array[index];
}
})
},
/**
* 选择商品规格
*/
async labelItemTap(e) {
const propertyindex = e.currentTarget.dataset.propertyindex
const propertychildindex = e.currentTarget.dataset.propertychildindex
const property = this.data.goodsDetail.properties[propertyindex]
const child = property.childsCurGoods[propertychildindex]
const _childActive = child.active
// 当前位置往下的所有sku取消选中状态
for (let index = propertyindex; index < this.data.goodsDetail.properties.length; index++) {
const element = this.data.goodsDetail.properties[index]
element.optionValueId = null
element.childsCurGoods.forEach(child => {
child.active = false
})
}
// // 取消该分类下的子栏目所有的选中状态
// property.childsCurGoods.forEach(child => {
// child.active = false
// })
// 设置当前选中状态,或者取消选中
property.optionValueId = child.id
child.active = true
// 下面代码块,支持点击后取消选中
// if (!_childActive) {
// property.optionValueId = child.id
// child.active = true
// } else {
// property.optionValueId = null
// child.active = false
// }
// 获取所有的选中规格尺寸数据
const needSelectNum = this.data.goodsDetail.properties.length
let curSelectNum = 0;
let propertyChildIds = "";
let propertyChildNames = "";
let _skuList = this.data.goodsDetail.skuList
this.data.goodsDetail.properties.forEach(p => {
p.childsCurGoods.forEach(c => {
// 处理当前选中的sku信息
if (c.active) {
_skuList = _skuList.filter(aaa => {
return aaa.propertyChildIds.indexOf(p.id + ':' + c.id) != -1
})
curSelectNum++;
propertyChildIds = propertyChildIds + p.id + ":" + c.id + ",";
propertyChildNames = propertyChildNames + p.name + ":" + c.name + " ";
} else if(!p.optionValueId) {
const nextO = _skuList.find(aaa => {
return aaa.propertyChildIds.indexOf(p.id + ':' + c.id) != -1
})
c.hidden = nextO ? false : true
}
})
})
let canSubmit = false;
if (needSelectNum == curSelectNum) {
canSubmit = true;
}
let skuGoodsPic = this.data.skuGoodsPic
if (this.data.goodsDetail.subPics && this.data.goodsDetail.subPics.length > 0) {
const _subPic = this.data.goodsDetail.subPics.find(ele => {
return ele.optionValueId == child.id
})
if (_subPic) {
skuGoodsPic = _subPic.pic
}
}
this.setData({
goodsDetail: this.data.goodsDetail,
canSubmit,
skuGoodsPic,
propertyChildIds,
propertyChildNames,
})
this.calculateGoodsPrice()
},
async calculateGoodsPrice() {
// 计算最终的商品价格
let price = this.data.goodsDetail.basicInfo.minPrice
let originalPrice = this.data.goodsDetail.basicInfo.originalPrice
let totalScoreToPay = this.data.goodsDetail.basicInfo.minScore
let buyNumMax = this.data.goodsDetail.basicInfo.stores
let buyNumber = this.data.goodsDetail.basicInfo.minBuyNumber
if (this.data.shopType == 'toPingtuan') {
price = this.data.goodsDetail.basicInfo.pingtuanPrice
}
// 计算 sku 价格
if (this.data.canSubmit) {
const token = wx.getStorageSync('token')
const res = await WXAPI.goodsPriceV2({
token: token ? token : '',
goodsId: this.data.goodsDetail.basicInfo.id,
propertyChildIds: this.data.propertyChildIds
})
if (res.code == 0) {
price = res.data.price
if (this.data.shopType == 'toPingtuan') {
price = res.data.pingtuanPrice
}
originalPrice = res.data.originalPrice
totalScoreToPay = res.data.score
buyNumMax = res.data.stores
}
}
// 计算配件价格
if (this.data.goodsAddition) {
this.data.goodsAddition.forEach(big => {
big.items.forEach(small => {
if (small.active) {
price = (price * 100 + small.price * 100) / 100
}
})
})
}
this.setData({
selectSizePrice: price,
selectSizeOPrice: originalPrice,
totalScoreToPay: totalScoreToPay,
buyNumMax,
buyNumber: (buyNumMax >= buyNumber) ? buyNumber : 0
});
},
/**
* 选择可选配件
*/
async labelItemTap2(e) {
const propertyindex = e.currentTarget.dataset.propertyindex
const propertychildindex = e.currentTarget.dataset.propertychildindex
const goodsAddition = this.data.goodsAddition
const property = goodsAddition[propertyindex]
const child = property.items[propertychildindex]
if (child.active) {
// 该操作为取消选择
child.active = false
this.setData({
goodsAddition
})
this.calculateGoodsPrice()
return
}
// 单选配件取消所有子栏目选中状态
if (property.type == 0) {
property.items.forEach(child => {
child.active = false
})
}
// 设置当前选中状态
child.active = true
this.setData({
goodsAddition
})
this.calculateGoodsPrice()
},
/**
* 加入购物车
*/
async addShopCar() {
if (this.data.goodsDetail.properties && !this.data.canSubmit) {
if (!this.data.canSubmit) {
wx.showToast({
title: '请选择规格',
icon: 'none'
})
}
this.bindGuiGeTap()
return
}
const goodsAddition = []
if (this.data.goodsAddition) {
let canSubmit = true
this.data.goodsAddition.forEach(ele => {
if (ele.required) {
const a = ele.items.find(item => {
return item.active
})
if (!a) {
canSubmit = false
}
}
ele.items.forEach(item => {
if (item.active) {
goodsAddition.push({
id: item.id,
pid: item.pid
})
}
})
})
if (!canSubmit) {
wx.showToast({
title: '请选择配件',
icon: 'none'
})
this.bindGuiGeTap()
return
}
}
if (this.data.buyNumber < 1) {
wx.showToast({
title: '请选择购买数量',
icon: 'none'
})
return
}
const isLogined = await AUTH.checkHasLogined()
if (!isLogined) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
const token = wx.getStorageSync('token')
const goodsId = this.data.goodsDetail.basicInfo.id
const sku = []
if (this.data.goodsDetail.properties) {
this.data.goodsDetail.properties.forEach(p => {
sku.push({
optionId: p.id,
optionValueId: p.optionValueId
})
})
}
const res = await WXAPI.shippingCarInfoAddItem(token, goodsId, this.data.buyNumber, sku, goodsAddition)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
this.closePopupTap();
wx.showToast({
title: '加入购物车',
icon: 'success'
})
this.shippingCartInfo()
},
/**
* 立即购买
*/
async buyNow(e) {
const isLogined = await AUTH.checkHasLogined()
if (!isLogined) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
let that = this
let shoptype = e.currentTarget.dataset.shoptype
if (this.data.goodsDetail.properties && !this.data.canSubmit) {
wx.showToast({
title: '请选择规格',
icon: 'none'
})
this.bindGuiGeTap()
return;
}
if (this.data.goodsAddition) {
let canSubmit = true
this.data.goodsAddition.forEach(ele => {
if (ele.required) {
const a = ele.items.find(item => {
return item.active
})
if (!a) {
canSubmit = false
}
}
})
if (!canSubmit) {
wx.showToast({
title: '请选择配件',
icon: 'none'
})
this.bindGuiGeTap()
return
}
}
if (this.data.buyNumber < 1) {
wx.showModal({
title: '提示',
content: '购买数量不能为0!',
showCancel: false
})
return;
}
//组建立即购买信息
var buyNowInfo = this.buliduBuyNowInfo(shoptype);
// 写入本地存储
wx.setStorage({
key: "buyNowInfo",
data: buyNowInfo
})
this.closePopupTap();
if (shoptype == 'toPingtuan') {
if (this.data.pingtuanopenid) {
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow&pingtuanOpenId=" + this.data.pingtuanopenid
})
} else {
WXAPI.pingtuanOpen(wx.getStorageSync('token'), that.data.goodsDetail.basicInfo.id).then(function (res) {
if (res.code == 2000) {
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none',
duration: 2000
})
return
}
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow&pingtuanOpenId=" + res.data.id
})
})
}
} else {
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow"
})
}
},
/**
* 组建立即购买信息
*/
buliduBuyNowInfo: function (shoptype) {
var shopCarMap = {};
shopCarMap.goodsId = this.data.goodsDetail.basicInfo.id;
shopCarMap.shopId = this.data.goodsDetail.basicInfo.shopId;
shopCarMap.pic = this.data.goodsDetail.basicInfo.pic;
shopCarMap.name = this.data.goodsDetail.basicInfo.name;
// shopCarMap.label=this.data.goodsDetail.basicInfo.id; 规格尺寸
shopCarMap.propertyChildIds = this.data.propertyChildIds;
shopCarMap.label = this.data.propertyChildNames;
shopCarMap.price = this.data.selectSizePrice;
// if (shoptype == 'toPingtuan') { // 20190714 拼团价格注释掉
// shopCarMap.price = this.data.goodsDetail.basicInfo.pingtuanPrice;
// }
shopCarMap.score = this.data.totalScoreToPay;
shopCarMap.left = "";
shopCarMap.active = true;
shopCarMap.number = this.data.buyNumber;
shopCarMap.logisticsType = this.data.goodsDetail.basicInfo.logisticsId;
shopCarMap.logistics = this.data.goodsDetail.logistics;
shopCarMap.weight = this.data.goodsDetail.basicInfo.weight;
if (this.data.goodsAddition && this.data.goodsAddition.length > 0) {
const additions = []
this.data.goodsAddition.forEach(ele => {
ele.items.forEach(item => {
if (item.active) {
additions.push({
id: item.id,
name: item.name,
pid: ele.id,
pname: ele.name
})
}
})
})
if (additions.length > 0) {
shopCarMap.additions = additions
}
}
var buyNowInfo = {};
buyNowInfo.shopNum = 0;
buyNowInfo.shopList = [];
buyNowInfo.shopList.push(shopCarMap);
buyNowInfo.kjId = this.data.kjId;
if (this.data.shopSubdetail) {
buyNowInfo.shopInfo = this.data.shopSubdetail.info
} else {
buyNowInfo.shopInfo = {
id: 0,
name: "其他",
pic: null,
serviceDistance: 99999999,
}
}
return buyNowInfo;
},
onShareAppMessage() {
let _data = {
title: this.data.goodsDetail.basicInfo.name,
path: '/pages/goods-details/index?id=' + this.data.goodsDetail.basicInfo.id + '&inviter_id=' + wx.getStorageSync('uid'),
success: function (res) {
// 转发成功
},
fail: function (res) {
// 转发失败
}
}
if (this.data.kjJoinUid) {
_data.title = this.data.curKanjiaprogress.joiner.nick + '邀请您帮TA砍价'
_data.path += '&kjJoinUid=' + this.data.kjJoinUid
}
return _data
},
onShareTimeline() {
let title = this.data.goodsDetail.basicInfo.name
let query = 'id=' + this.data.goodsDetail.basicInfo.id + '&inviter_id=' + wx.getStorageSync('uid')
if (this.data.kjJoinUid) {
title = this.data.curKanjiaprogress.joiner.nick + '邀请您帮TA砍价'
query += '&kjJoinUid=' + this.data.kjJoinUid
}
return {
title,
query,
imageUrl: this.data.goodsDetail.basicInfo.pic
}
},
reputation: function (goodsId) {
var that = this;
WXAPI.goodsReputationV2({
goodsId: goodsId
}).then(function (res) {
if (res.code == 0) {
res.data.result.forEach(ele => {
if (ele.goods.goodReputation == 0) {
ele.goods.goodReputation = 1
} else if (ele.goods.goodReputation == 1) {
ele.goods.goodReputation = 3
} else if (ele.goods.goodReputation == 2) {
ele.goods.goodReputation = 5
}
})
that.setData({
reputation: res.data
});
} else {
if (that.data.tabs && that.data.tabs.length == 3) {
const tabs = that.data.tabs
tabs.splice(2, 1)
that.setData({
tabs
})
}
}
})
},
pingtuanList: function (goodsId) {
var that = this;
WXAPI.pingtuanList({
goodsId: goodsId,
status: 0
}).then(function (res) {
if (res.code == 0) {
that.setData({
pingtuanList: res.data.result
});
}
})
},
getVideoSrc: function (videoId) {
var that = this;
WXAPI.videoDetail(videoId).then(function (res) {
if (res.code == 0) {
that.setData({
videoMp4Src: res.data.fdMp4
});
}
})
},
joinKanjia() {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.doneJoinKanjia();
}
})
},
doneJoinKanjia: function () { // 报名参加砍价活动
const _this = this;
if (!_this.data.curGoodsKanjia) {
return;
}
wx.showLoading({
title: '加载中',
mask: true
})
WXAPI.kanjiaJoin(wx.getStorageSync('token'), _this.data.curGoodsKanjia.id).then(function (res) {
wx.hideLoading()
if (res.code == 0) {
_this.setData({
kjJoinUid: wx.getStorageSync('uid'),
myHelpDetail: null
})
_this.getGoodsDetailAndKanjieInfo(_this.data.goodsDetail.basicInfo.id)
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
})
},
joinPingtuan: function (e) {
let pingtuanopenid = e.currentTarget.dataset.pingtuanopenid
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow&pingtuanOpenId=" + pingtuanopenid
})
},
goIndex() {
wx.switchTab({
url: '/pages/index/index',
});
},
helpKanjia() {
const _this = this;
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
_this.helpKanjiaDone()
}
})
},
helpKanjiaDone() {
const _this = this;
WXAPI.kanjiaHelp(wx.getStorageSync('token'), _this.data.kjId, _this.data.kjJoinUid, '').then(function (res) {
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return;
}
_this.setData({
myHelpDetail: res.data
});
wx.showModal({
title: '成功',
content: '成功帮TA砍掉 ' + res.data.cutPrice + ' 元',
showCancel: false
})
_this.getGoodsDetailAndKanjieInfo(_this.data.goodsDetail.basicInfo.id)
})
},
closePop() {
this.setData({
posterShow: false
})
},
async drawSharePic() {
const _this = this
// https://www.yuque.com/apifm/nu0f75/ak40es
const accountInfo = wx.getAccountInfoSync()
const envVersion = accountInfo.miniProgram.envVersion
const qrcodeRes = await WXAPI.wxaQrcode({
scene: _this.data.goodsDetail.basicInfo.id + ',' + wx.getStorageSync('uid'),
page: 'pages/goods-details/index',
is_hyaline: true,
autoColor: true,
expireHours: 1,
env_version: envVersion,
check_path: envVersion == 'release' ? true : false,
})
if (qrcodeRes.code != 0) {
wx.showToast({
title: qrcodeRes.msg,
icon: 'none'
})
return
}
const qrcode = qrcodeRes.data
const pic = _this.data.goodsDetail.basicInfo.pic
wx.getImageInfo({
src: pic,
success(res) {
const height = 490 * res.height / res.width
_this.drawSharePicDone(height, qrcode)
},
fail(e) {
console.error(e)
}
})
},
drawSharePicDone(picHeight, qrcode) {
const _this = this
const _baseHeight = 74 + (picHeight + 120)
this.setData({
posterConfig: {
width: 750,
height: picHeight + 660,
backgroundColor: '#fff',
debug: false,
blocks: [{
x: 76,
y: 74,
width: 604,
height: picHeight + 120,
borderWidth: 2,
borderColor: '#c2aa85',
borderRadius: 8
}],
images: [{
x: 133,
y: 133,
url: _this.data.goodsDetail.basicInfo.pic, // 商品图片
width: 490,
height: picHeight
},
{
x: 76,
y: _baseHeight + 199,
url: qrcode, // 二维码
width: 222,
height: 222
}
],
texts: [{
x: 375,
y: _baseHeight + 80,
width: 650,
lineNum: 2,
text: _this.data.goodsDetail.basicInfo.name,
textAlign: 'center',
fontSize: 40,
color: '#333'
},
{
x: 375,
y: _baseHeight + 180,
text: '¥' + _this.data.goodsDetail.basicInfo.minPrice,
textAlign: 'center',
fontSize: 50,
color: '#e64340'
},
{
x: 352,
y: _baseHeight + 320,
text: '长按识别小程序码',
fontSize: 28,
color: '#999'
}
],
}
}, () => {
Poster.create();
});
},
onPosterSuccess(e) {
console.log('success:', e)
this.setData({
posterImg: e.detail,
showposterImg: true
})
},
onPosterFail(e) {
console.error('fail:', e)
},
savePosterPic() {
const _this = this
wx.saveImageToPhotosAlbum({
filePath: this.data.posterImg,
success: (res) => {
wx.showModal({
content: '已保存到手机相册',
showCancel: false,
confirmText: '知道了',
confirmColor: '#333'
})
},
complete: () => {
_this.setData({
showposterImg: false
})
},
fail: (res) => {
if (res.errMsg.indexOf('fail privacy permission is not authorized') != -1) {
wx.showModal({
content: '请阅读并同意隐私条款以后才能继续本操作',
confirmText: '阅读协议',
cancelText: '取消',
success (res) {
if (res.confirm) {
wx.requirePrivacyAuthorize() // 弹出用户隐私授权框
}
}
})
} else if (res.errMsg.indexOf('fail auth deny') != -1) {
wx.showModal({
content: '本次操作需要您同意并将图片写入手机相册',
confirmText: '立即授权',
cancelText: '取消',
success (res) {
if (res.confirm) {
// 弹出设置窗口,让用户去设置
wx.openSetting({
withSubscriptions: true,
fail: aaa => console.log(aaa)
});
}
}
})
} else if (res.errMsg.indexOf('fail cancel') != -1) {
wx.showToast({
title: '已取消',
icon: 'none'
})
} else {
console.error(res);
wx.showToast({
title: res.errMsg,
icon: 'none'
})
}
}
})
},
previewImage(e) {
const url = e.currentTarget.dataset.url
wx.previewImage({
current: url, // 当前显示图片的http链接
urls: [url] // 需要预览的图片http链接列表
})
},
previewImage2(e) {
const url = e.currentTarget.dataset.url
const urls = []
this.data.goodsDetail.pics.forEach(ele => {
urls.push(ele.pic)
})
wx.previewImage({
current: url, // 当前显示图片的http链接
urls // 需要预览的图片http链接列表
})
},
onTabsChange(e) {
var index = e.detail.index
this.setData({
toView: this.data.tabs[index].view_id,
tabclicked: true
})
setTimeout(() => {
this.setData({
tabclicked: false
})
}, 1000);
},
backToHome() {
wx.switchTab({
url: '/pages/index/index',
})
},
customerService() {
wx.openCustomerServiceChat({
extInfo: {url: wx.getStorageSync('customerServiceChatUrl')},
corpId: wx.getStorageSync('customerServiceChatCorpId'),
showMessageCard: true,
sendMessageTitle: this.data.goodsDetail.basicInfo.name,
sendMessagePath: '/pages/goods-details/index?id=' + this.data.goodsDetail.basicInfo.id,
sendMessageImg: this.data.goodsDetail.basicInfo.pic,
success: res => {},
fail: err => {
console.error(err)
}
})
},
})
================================================
FILE: pages/goods-details/index.json
================================================
{
"navigationBarTitleText": "商品详情",
"usingComponents": {
"poster": "wxa-plugin-canvas/poster"
}
}
================================================
FILE: pages/goods-details/index.wxml
================================================
¥ {{selectSizePrice}}
¥ {{selectSizeOPrice}}
分享
二维码
{{goodsDetail.basicInfo.name}}
购买须知
{{ goodsDetail.basicInfo.purchaseNotes }}
商品特色
{{ goodsDetail.basicInfo.characteristic }}
分享有赏,好友下单后可得
{{goodsDetail.basicInfo.commission}} 积分奖励
分享有赏,好友下单后可得
{{goodsDetail.basicInfo.commission}}元 现金奖励
帮
{{curKanjiaprogress.joiner.nick}} 砍价吧!
{{pingtuanList.length}}人在拼单,可直接参与
{{item.apiExtUser.nick}}
已有
{{item.helpNumber}} 人参与
截止: {{item.dateEnd}}
请选择:
{{item.name}}
{{item.name}}
选择商品规格
{{property.name}}
{{item.name}}
{{shopSubdetail.info.name}}
{{shopSubdetail.info.address}}
商品详情
module.exports = {
v : function(goodsDetail) {
if (!goodsDetail || !goodsDetail.basicInfo) {
return "100"
}
var goodReputation = goodsDetail.basicInfo.numberGoodReputation / goodsDetail.basicInfo.numberReputation * 100
goodReputation = goodReputation.toFixed(0)
if (goodReputation > 100) {
goodReputation = 100
}
return goodReputation
}
}
宝贝评价 {{goodsDetail.basicInfo.numberGoodReputation}}
好评度:{{goodReputationPercent.v(goodsDetail)}}%
{{myHelpDetail?"您已砍过":"帮TA砍"}}
用当前价购买
保存到相册
{{property.name}}
{{item.name}}
{{property.name}}
{{item.name}}
加入购物车
立即购买
================================================
FILE: pages/goods-details/index.wxss
================================================
page,
view,
image,
input,
textarea {
display: block;
box-sizing: border-box;
}
.van-cell {
padding: 10px 38rpx;
}
.container {
background-color: #F2f2f2;
min-height: 100vh;
padding-bottom: 100rpx;
}
.scroll-container {
box-sizing: border-box;
height: 100vh;
padding-bottom: 64rpx;
}
.tabs-container {
width: 100%;
display: flex;
background-color: white;
}
.home-o {
width: 20%;
}
.swiper-container {
width: 100%;
position: relative;
}
.swiper_box {
width: 100%;
height: 748rpx;
}
swiper-item image {
width: 100%;
display: inline-block;
overflow: hidden;
height: 748rpx;
}
.goods-info {
background-color: #fff;
padding-top: 35rpx;
width: 100%;
position: relative;
}
.goods-info-top-container {
display: flex;
justify-content: space-between;
}
.goods-info-fx {
display: flex;
align-items: center;
justify-content: space-between;
margin-right: 35rpx;
position: relative;
}
.goods-info-fx .item {
/* height: 50rpx; */
right: 130rpx;
top: 100rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 24rpx;
background: #fff;
z-index: 20;
}
.goods-info-fx .left {
margin-right: 10px;
}
.goods-info-fx .icon-title{
padding-top:5px ;
font-size: 11px;
}
.goods-info-fx .item image {
width: 50rpx;
height: 50rpx;
}
.goods-info-fx .item button {
position: absolute;
height: 100%;
width: 100%;
opacity: 0;
z-index: 99;
}
.goods-info .goods-title {
box-sizing: border-box;
padding: 0 30rpx;
font-size: 32rpx;
line-height: 1.4;
color: #000;
/* padding-bottom: 26rpx; */
}
.goods-info .goods-share {
box-sizing: border-box;
padding: 0 30rpx;
font-size: 25rpx;
line-height: 1.4;
color: #CC0000;
padding-top: 26rpx;
}
.vcell{
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
.goods-profile {
display: flex;
align-items: center;
}
.goods-profile .p {
color: #e64340;
font-size: 20pt;
margin-left: 30rpx;
}
.goods-profile .p text {
font-size: 12pt;
}
.goods-profile .r {
color: #ccc;
font-size: 10pt;
margin-left: 30rpx;
}
.row-arrow {
width: 100vw;
padding: 0 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
height: 102rpx;
font-size: 28rpx;
line-height: 102rpx;
background: #fff;
margin-bottom: 32rpx;
}
.row-arrow image {
width: 40rpx;
height: 40rpx;
}
.goods-des-info {
width: 100%;
box-sizing: border-box;
background-color: #fff;
border-radius: 12px;
}
.label-title {
font-size: 28rpx;
color: #000000;
padding: 30rpx;
display: flex;
justify-content: space-between;
}
.label-title .left{
border-left: 3px solid #e64340;
height: auto;
padding-left: 10px;
}
.goods-text {
padding: 0 10rpx;
font-size: 28rpx;
color: #666666;
line-height: 56rpx;
margin-bottom: 30rpx;
}
.goods-text image {
width: 100%;
margin-top: -1rpx;
}
.des-imgs {
width: 100%;
}
.des-imgs image {
width: 100%;
}
.footer-box {
width: 100%;
height: 100rpx;
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
display: flex;
box-shadow: 0 0 1rpx 0;
align-items: center;
}
.footer-box .contact {
position: relative;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-left: 32rpx;
}
.footer-box .contact button {
position: absolute;
height: 100%;
width: 100%;
opacity: 0;
z-index: 99;
}
.footer-box .contact image {
width: 60rpx;
height: 60rpx;
}
.footer-box .shop-cart-btn {
position: relative;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-left: 32rpx;
}
.footer-box .shop-cart-btn image {
width: 55rpx;
height: 55rpx;
}
.fav-icon {
width: 60rpx;
height: 60rpx;
margin-left: 32rpx;
/*707070*/
}
.footer-box .shop-cart-btn .shop-num {
position: absolute;
color: #fff;
left: 32rpx;
top: 10rpx;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border-radius: 50%;
background: #e64340;
font-size: 24rpx;
}
.footer-box .join-shop-cart {
text-align: center;
height: 100%;
line-height: 100rpx;
background-color: #ff6850;
color: #fff;
font-size: 34rpx;
flex: 1;
margin-left: 32rpx;
}
.footer-box .now-buy {
text-align: center;
height: 100%;
width: 250rpx;
line-height: 100rpx;
background-color: #e64340;
color: #fff;
font-size: 34rpx;
flex: 1;
}
.show-popup {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
.popup-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 5;
}
.popup-contents {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: #fff;
z-index: 6;
}
.pop-goods-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 32rpx;
margin-right: 32rpx;
padding: 30rpx 0;
border-bottom: 1px solid #eee;
}
.pop-img-box {
width: 120rpx;
height: 120rpx;
overflow: hidden;
margin-right: 26rpx;
}
.pop-img-box .goods-thumbnail {
width: 120rpx;
height: 120rpx;
}
.pop-goods-title {
width: 484rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 26rpx;
color: #000000;
}
.pop-goods-price {
font-size: 26rpx;
color: #e64340;
margin-top: 20rpx;
}
.pop-goods-price .t1 {
font-size: 50rpx;
}
.pop-goods-price-original {
font-size: 26rpx;
color: #aaa;
text-decoration: line-through;
margin-left: 16rpx;
}
.pop-goods-close {
width: 36rpx;
height: 36rpx;
}
.goods-property-container {
height: 56px;
align-items: center;
border-radius: 12px;
padding: 0 16px;
}
.size-label-box2 {
width: 100vw;
background: #fff;
}
.size-label-box .label {
font-size: 26rpx;
color: #000;
padding-left: 30rpx;
padding: 30rpx 0 20rpx 30rpx;
}
.size-label-box .label-item-box {
display: flex;
margin-left: 30rpx;
flex-direction: row;
flex-wrap: wrap;
}
.size-label-box .label-item {
font-size: 26rpx;
color: #000;
padding: 14rpx 20rpx;
border: 1px solid #ddd;
border-radius: 6rpx;
margin: 0 20rpx 20rpx 0;
}
.size-label-box .label-item.active {
color: #e64340;
border: 1px solid #e64340;
}
.buy-num-box {
display: flex;
justify-content: space-between;
padding: 30rpx 30rpx 48rpx 0;
margin-left: 30rpx;
border-top: 1px solid #eee;
margin-top: 30rpx;
align-items: center;
}
.num-label {
font-size: 26rpx;
color: #000000;
}
.buy-num-box .num-box {
display: flex;
}
.buy-num-box .num-box .num-jian,
.buy-num-box .num-box .num-input,
.buy-num-box .num-box .num-jia {
width: 80rpx;
height: 64rpx;
line-height: 62rpx;
text-align: center;
border: 1px solid #eee;
}
.buy-num-box .num-box .num-input {
font-size: 28rpx;
}
.buy-num-box .num-box .num-input input {
height: 100%;
}
.popup-join-btn {
width: 100%;
height: 89rpx;
text-align: center;
line-height: 89rpx;
font-size: 34rpx;
color: #ffffff;
background-color: #e64340;
}
.buy-num-box .num-box .hui {
background-color: #f5f5f9;
}
.curKanjiaprogress {
width: 750rpx;
background-color: #fff;
margin-top: 20rpx;
}
.curKanjiaprogress .name {
font-size: 40rpx;
padding: 20rpx;
text-align: center;
}
.curKanjiaprogress .placeholder {
margin-left: 30rpx;
margin-right: 30rpx;
text-align: center;
font-size: 26rpx;
width: 100rpx;
color: #999;
}
.kjBuyButton {
position: fixed;
left: 0;
bottom: calc(env(safe-area-inset-bottom) / 2);
width: 750rpx;
display: flex;
}
.kjBuyButton .item {
flex: 1;
}
.shareFloatDiv1 {
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
background-color: #555;
filter: Alpha(Opacity=60);
opacity: 0.6;
z-index: 99998;
}
.shareFloatDiv2 {
position: fixed;
width: 100%;
height: 400rpx;
background-color: #ffffff;
bottom: 0rpx;
z-index: 99999;
}
.shareFloatDiv2 .p1 {
height: 260rpx;
}
.shareFloatDiv2 .p2 {
height: 20rpx;
background-color: #EEEEEE;
}
.shareFloatDiv2 .p3 {
height: 120rpx;
line-height: 120rpx;
text-align: center;
color: #555555;
font-size: 16px;
}
.qrcode-button {
padding: 30rpx;
margin-top: 50rpx;
}
.qrcode {
width: 300rpx;
height: 300rpx;
margin-top: 50rpx;
}
.posterImg-box {
position: absolute;
top: 104rpx;
left: 32rpx;
width: 686rpx;
margin-bottom: 100rpx;
z-index: 999999;
}
.posterImg {
width: 100%;
}
.btn-create {
margin: 32rpx;
margin-bottom: 0;
height: 88rpx;
line-height: 88rpx;
background: #e64340;
color: #fff;
text-align: center;
border-radius: 8rpx;
}
.clearfix:after {
/*伪元素是行内元素 正常浏览器清除浮动方法*/
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.shop-container {
width: 100vw;
margin: 16rpx 0rpx;
padding: 32rpx;
display: flex;
align-items: center;
background: #fff;
}
.shop-container image {
width: 90rpx;
height: 90rpx;
}
.shop-container .info {
margin-left: 32rpx;
}
.shop-container .info .title {
font-size: 30rpx;
color: #333;
}
.shop-container .info .address {
font-size: 26rpx;
color: #666;
}
.reputation-cell-group{
background-color:white !important;
border-radius: 12px;
}
.reputation-cell {
padding-bottom: 0rpx !important;
--cell-icon-size: 88rpx;
}
.reputation-cell .van-icon {
top: 16rpx !important;
}
.reputation-cell .avatarUrl-img{
width: 40px;
height: 40px;
border-radius: 100%;
margin-right: 26rpx;
}
.reputation-cell-reamrk {
/* padding-left: 96rpx; */
}
.reputation-pics {
width: 100vw;
display: flex;
flex-wrap: wrap;
background: #ffffff;
}
.reputation-pics image {
width: 207rpx;
height: 207rpx;
margin: 32rpx 0 0 32rpx;
border-radius: 16rpx;
}
.characteristic {
padding: 8rpx 32rpx;
color: #000;
font-size: 28rpx;
line-height: 64rpx;
}
.van-progress {
margin: 32rpx 0;
}
.flex {
display: flex;
width: 100vw;
}
.kjbutton {
flex: 1;
padding: 30rpx;
}
.kjlj {
display: flex;
background-color: #ffffff;
padding: 0 32rpx;
align-items: center;
}
.kjlj-l {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
flex-shrink: 0;
}
================================================
FILE: pages/goods-details/times01.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
data: {
list: undefined,
},
onLoad(options) {
this.setData({
goodsId: options.goodsId
})
this.goodsTimesDays()
},
onShow() {
},
async goodsTimesDays() {
// https://www.yuque.com/apifm/nu0f75/wy8nlq
const res = await WXAPI.goodsTimesDays(this.data.goodsId)
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
const list = res.data
this.setData({
list,
maxDate: dayjs(list[list.length - 1]).valueOf(),
})
},
async onConfirm(event) {
const day = dayjs(event.detail).format('YYYY-MM-DD')
if (!this.data.list.includes(day)) {
wx.showModal({
content: day + '预约已满,请更换日期'
})
return
}
wx.navigateTo({
url: '/pages/goods-details/times02?goodsId='+ this.data.goodsId +'&day=' + day,
})
},
})
================================================
FILE: pages/goods-details/times01.json
================================================
{
"navigationBarTitleText": "时段定价演示"
}
================================================
FILE: pages/goods-details/times01.wxml
================================================
================================================
FILE: pages/goods-details/times01.wxss
================================================
/* pages/goods-details/times01.wxss */
================================================
FILE: pages/goods-details/times02.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
data: {
list: undefined,
maxDate: dayjs().add(7, 'day').valueOf(),
},
onLoad(options) {
this.setData({
goodsId: options.goodsId,
day: options.day
})
this.goodsTimesDayItems()
},
onShow() {
},
async goodsTimesDayItems() {
// https://www.yuque.com/apifm/nu0f75/dlpp5v
const res = await WXAPI.goodsTimesDayItems(this.data.day, this.data.goodsId)
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
const list = res.data.filter(ele => ele.stores > 0)
this.setData({
list
})
},
async submit(event) {
console.log(event);
const idx = event.target.dataset.idx
const item = this.data.list[idx]
const goodsJsonStr = [{
goodsId: this.data.goodsId,
number: 1,
goodsTimesDay: this.data.day,
goodsTimesItem: item.name,
}]
const d = {
token: wx.getStorageSync('token'),
goodsJsonStr: JSON.stringify(goodsJsonStr),
}
// https://www.yuque.com/apifm/nu0f75/qx4w98
const res = await WXAPI.orderCreate(d)
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
this.setData({
orderId: res.data.id,
money: res.data.amountReal,
paymentShow: true,
nextAction: {
type: 0,
id: res.data.id
}
})
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/order-details/index?id=' + this.data.orderId,
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/goods-details/times02.json
================================================
{
"navigationBarTitleText": "选择时段"
}
================================================
FILE: pages/goods-details/times02.wxml
================================================
================================================
FILE: pages/goods-details/times02.wxss
================================================
/* pages/goods-details/times02.wxss */
================================================
FILE: pages/goods-details/vop.js
================================================
const WXAPI = require('apifm-wxapi')
const TOOLS = require('../../utils/tools.js')
const AUTH = require('../../utils/auth')
const CONFIG = require('../../config.js')
import Poster from 'wxa-plugin-canvas/poster/poster'
Page({
data: {
createTabs: false, //绘制tabs
tabs: [{
tabs_name: '商品简介',
view_id: 'swiper-container',
topHeight: 0
}, {
tabs_name: '商品详情',
view_id: 'goods-des-info',
topHeight: 0,
}],
goodsDetail: {},
hasMoreSelect: false,
selectSizePrice: 0,
selectSizeOPrice: 0,
totalScoreToPay: 0,
shopNum: 0,
hideShopPopup: true,
buyNumber: 1,
buyNumMin: 1,
buyNumMax: 0,
propertyChildIds: "",
propertyChildNames: "",
canSubmit: false, // 选中规格尺寸时候是否允许加入购物车
shopType: "addShopCar", //购物类型,加入购物车或立即购买,默认为加入购物车
},
bindscroll(e) {
if (this.data.tabclicked) {
return
}
//计算页面 轮播图、详情、评价(砍价)view 高度
this.getTopHeightFunction()
var tabsHeight = this.data.tabsHeight //顶部距离(tabs高度)
if (this.data.tabs[0].topHeight-tabsHeight<=0 && 0 < this.data.tabs[1].topHeight-tabsHeight) { //临界值,根据自己的需求来调整
this.setData({
active: this.data.tabs[0].tabs_name //设置当前标签栏
})
} else if (this.data.tabs[1].topHeight-tabsHeight<=0) {
this.setData({
active: this.data.tabs[1].tabs_name
})
}
},
onLoad(e) {
// e.id = 4659376
// 读取分享链接中的邀请人编号
if (e && e.inviter_id) {
wx.setStorageSync('referrer', e.inviter_id)
}
// 读取小程序码中的邀请人编号
if (e && e.scene) {
const scene = decodeURIComponent(e.scene) // 处理扫码进商品详情页面的逻辑
if (scene && scene.split(',').length >= 2) {
e.id = scene.split(',')[0]
e.goodsId = scene.split(',')[1]
}
if (scene && scene.split(',').length >= 3) {
e.id = scene.split(',')[0]
e.goodsId = scene.split(',')[1]
wx.setStorageSync('referrer', scene.split(',')[2])
}
}
this.data.goodsId = e.id
this.data.goodsId2 = e.goodsId ? e.goodsId : ''
this.data.kjJoinUid = e.kjJoinUid
let goodsDetailSkuShowType = wx.getStorageSync('goodsDetailSkuShowType')
if (!goodsDetailSkuShowType) {
goodsDetailSkuShowType = 0
}
this.setData({
goodsDetailSkuShowType,
curuid: wx.getStorageSync('uid'),
customerServiceType: CONFIG.customerServiceType
})
this.getGoodsDetailAndKanjieInfo(this.data.goodsId)
this.skuImages(this.data.goodsId)
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.goodsFavCheck()
this.shippingCartInfo()
this.initShippingAddress()
} else {
getApp().loginOK = () => {
this.goodsFavCheck()
this.shippingCartInfo()
this.initShippingAddress()
}
}
})
},
async initShippingAddress() {
const res = await WXAPI.defaultAddress(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
curAddressData: res.data.info
})
this.checkCanBuy()
} else {
this.setData({
curAddressData: null
});
}
},
selectAddress: function () {
wx.navigateTo({
url: "/pages/select-address/index"
})
},
async shippingCartInfo(){
const number = await TOOLS.showTabBarBadge(true)
this.setData({
shopNum: number
})
},
async checkCanBuy(){
const token = wx.getStorageSync('token')
if (!token) {
return
}
const curAddressData = this.data.curAddressData
const sku = [
{"skuId": this.data.goodsId,"skuNumber": 1}
]
const res = await WXAPI.jdvopGoodsCheckCanBuyV3({
checkSkuSale: 1,
checkAreaLimit: 1,
sku: JSON.stringify(sku),
address: curAddressData.provinceStr + curAddressData.cityStr + curAddressData.areaStr + curAddressData.streetStr + curAddressData.address
})
if (res.code == 0) {
this.setData({
canPurchase: res.data[0].canPurchase
})
} else {
this.setData({
canPurchase: false
})
}
},
onShow (){
this.setData({
createTabs: true //绘制tabs
})
//计算tabs高度
var query = wx.createSelectorQuery();
query.select('#tabs').boundingClientRect((rect) => {
var tabsHeight = rect.height
this.setData({
tabsHeight:tabsHeight
})
}).exec()
this.initShippingAddress()
},
getTopHeightFunction() {
var that = this
var tabs = that.data.tabs
tabs.forEach((element, index) => {
var viewId = "#" + element.view_id
that.getTopHeight(viewId, index)
});
},
getTopHeight(viewId, index) {
var query = wx.createSelectorQuery();
query.select(viewId).boundingClientRect((rect) => {
if (!rect) {
return
}
let top = rect.top
var tabs = this.data.tabs
tabs[index].topHeight = top
this.setData({
tabs: tabs
})
}).exec()
},
async goodsFavCheck() {
const res = await WXAPI.goodsFavCheck(wx.getStorageSync('token'), this.data.goodsId)
if (res.code == 0) {
this.setData({
faved: true
})
} else {
this.setData({
faved: false
})
}
},
async addFav(){
if (this.data.faved) {
// 取消收藏
WXAPI.goodsFavDeleteV2({
token: wx.getStorageSync('token'),
goodsId: this.data.goodsId,
type: 1
}).then(res => {
this.goodsFavCheck()
})
} else {
const extJsonStr = {
wxaurl: `/pages/goods-details/vop?id=${this.data.goodsId}&goodsId=${this.data.goodsId2}`,
skuId: this.data.goodsId,
pic: this.data.imageDomain + this.data.info.imagePath,
name: this.data.info.name
}
// 加入收藏
WXAPI.goodsFavAdd({
token: wx.getStorageSync('token'),
goodsId: this.data.goodsId,
type: 1,
extJsonStr: JSON.stringify(extJsonStr)
}).then(res => {
this.goodsFavCheck()
})
}
},
async getGoodsDetailAndKanjieInfo(goodsId) {
const token = wx.getStorageSync('token')
if (this.data.goodsId2) {
const goodsDetailRes = await WXAPI.goodsDetail(this.data.goodsId2, token ? token : '')
if (goodsDetailRes.code == 0) {
this.setData({
goodsDetail: goodsDetailRes.data
})
}
}
const res = await WXAPI.jdvopGoodsDetailV3({
skuId: goodsId,
queryExts: 3
})
if (res.data.info.introduceWechat) {
res.data.wxintroduction = JSON.parse(res.data.info.introduceWechat)
}
if (res.code == 0) {
this.setData(res.data)
}
},
async skuImages(goodsId) {
const res = await WXAPI.jdvopGoodsSkuImagesV2(goodsId)
if (res.code == 0) {
this.setData({
skuImages: res.data
})
}
},
async shopSubdetail(shopId){
const res = await WXAPI.shopSubdetail(shopId)
if (res.code == 0) {
this.setData({
shopSubdetail: res.data
})
}
},
goShopCar: function() {
wx.reLaunch({
url: "/pages/shop-cart/index"
});
},
toAddShopCar: function() {
this.setData({
shopType: "addShopCar"
})
this.bindGuiGeTap();
},
tobuy: function() {
this.setData({
shopType: "tobuy"
});
this.bindGuiGeTap();
},
toPingtuan: function(e) {
let pingtuanopenid = 0
if (e.currentTarget.dataset.pingtuanopenid) {
pingtuanopenid = e.currentTarget.dataset.pingtuanopenid
}
this.setData({
shopType: "toPingtuan",
selectSizePrice: this.data.goodsDetail.basicInfo.pingtuanPrice,
selectSizeOPrice: this.data.goodsDetail.basicInfo.originalPrice,
pingtuanopenid: pingtuanopenid,
hideShopPopup: false,
skuGoodsPic: this.data.goodsDetail.basicInfo.pic
});
},
/**
* 规格选择弹出框
*/
bindGuiGeTap: function() {
this.setData({
hideShopPopup: false
})
},
/**
* 规格选择弹出框隐藏
*/
closePopupTap: function() {
this.setData({
hideShopPopup: true
})
},
stepChange(event) {
this.setData({
buyNumber: event.detail
})
},
/**
* 选择商品规格
*/
async labelItemTap(e) {
const propertyindex = e.currentTarget.dataset.propertyindex
const propertychildindex = e.currentTarget.dataset.propertychildindex
const property = this.data.goodsDetail.properties[propertyindex]
const child = property.childsCurGoods[propertychildindex]
// 取消该分类下的子栏目所有的选中状态
property.childsCurGoods.forEach(child => {
child.active = false
})
// 设置当前选中状态
property.optionValueId = child.id
child.active = true
// 获取所有的选中规格尺寸数据
const needSelectNum = this.data.goodsDetail.properties.length
let curSelectNum = 0;
let propertyChildIds = "";
let propertyChildNames = "";
this.data.goodsDetail.properties.forEach(p => {
p.childsCurGoods.forEach(c => {
if (c.active) {
curSelectNum++;
propertyChildIds = propertyChildIds + p.id + ":" + c.id + ",";
propertyChildNames = propertyChildNames + p.name + ":" + c.name + " ";
}
})
})
let canSubmit = false;
if (needSelectNum == curSelectNum) {
canSubmit = true;
}
let skuGoodsPic = this.data.skuGoodsPic
if (this.data.goodsDetail.subPics && this.data.goodsDetail.subPics.length > 0) {
const _subPic = this.data.goodsDetail.subPics.find(ele => {
return ele.optionValueId == child.id
})
if (_subPic) {
skuGoodsPic = _subPic.pic
}
}
this.setData({
goodsDetail: this.data.goodsDetail,
canSubmit,
skuGoodsPic,
propertyChildIds,
propertyChildNames,
})
this.calculateGoodsPrice()
},
async calculateGoodsPrice() {
// 计算最终的商品价格
let price = this.data.goodsDetail.basicInfo.minPrice
let originalPrice = this.data.goodsDetail.basicInfo.originalPrice
let totalScoreToPay = this.data.goodsDetail.basicInfo.minScore
let buyNumMax = this.data.goodsDetail.basicInfo.stores
let buyNumber = this.data.goodsDetail.basicInfo.minBuyNumber
if (this.data.shopType == 'toPingtuan') {
price = this.data.goodsDetail.basicInfo.pingtuanPrice
}
// 计算 sku 价格
if (this.data.canSubmit) {
const token = wx.getStorageSync('token')
const res = await WXAPI.goodsPriceV2({
token: token ? token : '',
goodsId: this.data.goodsDetail.basicInfo.id,
propertyChildIds: this.data.propertyChildIds
})
if (res.code == 0) {
price = res.data.price
if (this.data.shopType == 'toPingtuan') {
price = res.data.pingtuanPrice
}
originalPrice = res.data.originalPrice
totalScoreToPay = res.data.score
buyNumMax = res.data.stores
}
}
// 计算配件价格
if (this.data.goodsAddition) {
this.data.goodsAddition.forEach(big => {
big.items.forEach(small => {
if (small.active) {
price = (price*100 + small.price*100) / 100
}
})
})
}
this.setData({
selectSizePrice: price,
selectSizeOPrice: originalPrice,
totalScoreToPay: totalScoreToPay,
buyNumMax,
buyNumber: (buyNumMax >= buyNumber) ? buyNumber : 0
});
},
/**
* 选择可选配件
*/
async labelItemTap2(e) {
const propertyindex = e.currentTarget.dataset.propertyindex
const propertychildindex = e.currentTarget.dataset.propertychildindex
const goodsAddition = this.data.goodsAddition
const property = goodsAddition[propertyindex]
const child = property.items[propertychildindex]
if (child.active) {
// 该操作为取消选择
child.active = false
this.setData({
goodsAddition
})
this.calculateGoodsPrice()
return
}
// 单选配件取消所有子栏目选中状态
if (property.type == 0) {
property.items.forEach(child => {
child.active = false
})
}
// 设置当前选中状态
child.active = true
this.setData({
goodsAddition
})
this.calculateGoodsPrice()
},
/**
* 加入购物车
*/
async addShopCar() {
if (this.data.buyNumber < 1) {
wx.showToast({
title: '请选择购买数量',
icon: 'none'
})
return
}
const token = wx.getStorageSync('token')
const goodsId = this.data.goodsId
const res = await WXAPI.jdvopCartAddV2({
token,
goodsId,
number: this.data.buyNumber
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
this.closePopupTap();
wx.showToast({
title: '加入购物车',
icon: 'success'
})
this.shippingCartInfo()
},
/**
* 立即购买
*/
buyNow(e) {
let shoptype = e.currentTarget.dataset.shoptype
if (this.data.buyNumber < 1) {
wx.showModal({
title: '提示',
content: '购买数量不能为0!',
showCancel: false
})
return;
}
//组建立即购买信息
var buyNowInfo = this.buliduBuyNowInfo(shoptype);
// 写入本地存储
wx.setStorage({
key: "buyNowInfo",
data: buyNowInfo
})
this.closePopupTap();
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow&shopCarType=1"
})
},
/**
* 组建立即购买信息
*/
buliduBuyNowInfo: function(shoptype) {
var shopCarMap = {};
shopCarMap.goodsId = this.data.goodsId;
shopCarMap.pic = this.data.imageDomain + this.data.price.pic;
shopCarMap.name = this.data.price.skuName;
shopCarMap.price = this.data.price.priceSale;
shopCarMap.left = "";
shopCarMap.active = true;
shopCarMap.number = this.data.buyNumber;
var buyNowInfo = {};
buyNowInfo.shopNum = 0;
buyNowInfo.shopList = [shopCarMap];
return buyNowInfo;
},
onShareAppMessage() {
return {
title: this.data.price.skuName,
path: '/pages/goods-details/vop?id=' + this.data.goodsId + '&goodsId=' + this.data.goodsId2 + '&inviter_id=' + wx.getStorageSync('uid'),
success: function(res) {
// 转发成功
},
fail: function(res) {
// 转发失败
}
}
},
onShareTimeline() {
return {
title: this.data.price.skuName,
query: 'id=' + this.data.goodsId + '&goodsId=' + this.data.goodsId2 + '&inviter_id=' + wx.getStorageSync('uid'),
imageUrl: wx.getStorageSync('share_pic'),
}
},
reputation: function(goodsId) {
var that = this;
WXAPI.goodsReputation({
goodsId: goodsId
}).then(function(res) {
if (res.code == 0) {
res.data.forEach(ele => {
if (ele.goods.goodReputation == 0) {
ele.goods.goodReputation = 1
} else if (ele.goods.goodReputation == 1) {
ele.goods.goodReputation = 3
} else if (ele.goods.goodReputation == 2) {
ele.goods.goodReputation = 5
}
})
that.setData({
reputation: res.data
});
}
})
},
pingtuanList: function(goodsId) {
var that = this;
WXAPI.pingtuanList({
goodsId: goodsId,
status: 0
}).then(function(res) {
if (res.code == 0) {
that.setData({
pingtuanList: res.data.result
});
}
})
},
getVideoSrc: function(videoId) {
var that = this;
WXAPI.videoDetail(videoId).then(function(res) {
if (res.code == 0) {
that.setData({
videoMp4Src: res.data.fdMp4
});
}
})
},
joinKanjia(){
this.doneJoinKanjia();
},
doneJoinKanjia: function() { // 报名参加砍价活动
const _this = this;
if (!_this.data.curGoodsKanjia) {
return;
}
wx.showLoading({
title: '加载中',
mask: true
})
WXAPI.kanjiaJoin(wx.getStorageSync('token'), _this.data.curGoodsKanjia.id).then(function(res) {
wx.hideLoading()
if (res.code == 0) {
_this.setData({
kjJoinUid: wx.getStorageSync('uid'),
myHelpDetail: null
})
_this.getGoodsDetailAndKanjieInfo(_this.data.goodsDetail.basicInfo.id)
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
})
},
joinPingtuan: function(e) {
let pingtuanopenid = e.currentTarget.dataset.pingtuanopenid
wx.navigateTo({
url: "/pages/to-pay-order/index?orderType=buyNow&pingtuanOpenId=" + pingtuanopenid
})
},
goIndex() {
wx.switchTab({
url: '/pages/index/index',
});
},
helpKanjia() {
this.helpKanjiaDone()
},
helpKanjiaDone(){
const _this = this;
WXAPI.kanjiaHelp(wx.getStorageSync('token'), _this.data.kjId, _this.data.kjJoinUid, '').then(function (res) {
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return;
}
_this.setData({
myHelpDetail: res.data
});
wx.showModal({
title: '成功',
content: '成功帮TA砍掉 ' + res.data.cutPrice + ' 元',
showCancel: false
})
_this.getGoodsDetailAndKanjieInfo(_this.data.goodsDetail.basicInfo.id)
})
},
closePop(){
this.setData({
posterShow: false
})
},
async drawSharePic() {
const _this = this
const accountInfo = wx.getAccountInfoSync()
const envVersion = accountInfo.miniProgram.envVersion
const qrcodeRes = await WXAPI.wxaQrcode({
scene: _this.data.goodsId + ',' + _this.data.goodsId2 + ',' + wx.getStorageSync('uid'),
page: 'pages/goods-details/vop',
is_hyaline: true,
autoColor: true,
expireHours: 1,
env_version: envVersion,
check_path: envVersion == 'release' ? true : false,
})
if (qrcodeRes.code != 0) {
wx.showToast({
title: qrcodeRes.msg,
icon: 'none'
})
return
}
const qrcode = qrcodeRes.data
const pic = _this.data.goodsDetail.basicInfo.pic
wx.getImageInfo({
src: pic,
success(res) {
const height = 490 * res.height / res.width
_this.drawSharePicDone(height, qrcode)
},
fail(e) {
console.error(e)
}
})
},
drawSharePicDone(picHeight, qrcode) {
const _this = this
const _baseHeight = 74 + (picHeight + 120)
this.setData({
posterConfig: {
width: 750,
height: picHeight + 660,
backgroundColor: '#fff',
debug: false,
blocks: [
{
x: 76,
y: 74,
width: 604,
height: picHeight + 120,
borderWidth: 2,
borderColor: '#c2aa85',
borderRadius: 8
}
],
images: [
{
x: 133,
y: 133,
url: _this.data.goodsDetail.basicInfo.pic, // 商品图片
width: 490,
height: picHeight
},
{
x: 76,
y: _baseHeight + 199,
url: qrcode, // 二维码
width: 222,
height: 222
}
],
texts: [
{
x: 375,
y: _baseHeight + 80,
width: 650,
lineNum:2,
text: _this.data.goodsDetail.basicInfo.name,
textAlign: 'center',
fontSize: 40,
color: '#333'
},
{
x: 375,
y: _baseHeight + 180,
text: '¥' + _this.data.goodsDetail.basicInfo.minPrice,
textAlign: 'center',
fontSize: 50,
color: '#e64340'
},
{
x: 352,
y: _baseHeight + 320,
text: '长按识别小程序码',
fontSize: 28,
color: '#999'
}
],
}
}, () => {
Poster.create();
});
},
onPosterSuccess(e) {
console.log('success:', e)
this.setData({
posterImg: e.detail,
showposterImg: true
})
},
onPosterFail(e) {
console.error('fail:', e)
},
savePosterPic() {
const _this = this
wx.saveImageToPhotosAlbum({
filePath: this.data.posterImg,
success: (res) => {
wx.showModal({
content: '已保存到手机相册',
showCancel: false,
confirmText: '知道了',
confirmColor: '#333'
})
},
complete: () => {
_this.setData({
showposterImg: false
})
},
fail: (res) => {
if (res.errMsg.indexOf('fail privacy permission is not authorized') != -1) {
wx.showModal({
content: '请阅读并同意隐私条款以后才能继续本操作',
confirmText: '阅读协议',
cancelText: '取消',
success (res) {
if (res.confirm) {
wx.requirePrivacyAuthorize() // 弹出用户隐私授权框
}
}
})
} else if (res.errMsg.indexOf('fail auth deny') != -1) {
wx.showModal({
content: '本次操作需要您同意并将图片写入手机相册',
confirmText: '立即授权',
cancelText: '取消',
success (res) {
if (res.confirm) {
// 弹出设置窗口,让用户去设置
wx.openSetting({
withSubscriptions: true,
fail: aaa => console.log(aaa)
});
}
}
})
} else {
console.error(res);
wx.showToast({
title: res.errMsg,
icon: 'none'
})
}
}
})
},
previewImage(e) {
const url = e.currentTarget.dataset.url
wx.previewImage({
current: url, // 当前显示图片的http链接
urls: [url] // 需要预览的图片http链接列表
})
},
onTabsChange(e) {
var index = e.detail.index
this.setData({
toView: this.data.tabs[index].view_id,
tabclicked: true
})
setTimeout(() => {
this.setData({
tabclicked: false
})
}, 1000);
},
backToHome() {
wx.switchTab({
url: '/pages/index/index',
})
},
customerService() {
wx.openCustomerServiceChat({
extInfo: {url: wx.getStorageSync('customerServiceChatUrl')},
corpId: wx.getStorageSync('customerServiceChatCorpId'),
showMessageCard: true,
sendMessageTitle: this.data.price.skuName,
sendMessagePath: '/pages/goods-details/vop?id='+ this.data.goodsId +'&goodsId=' + this.data.goodsId2,
sendMessageImg: this.data.imageDomain + this.data.price.pic,
success: res => {},
fail: err => {
console.error(err)
}
})
},
})
================================================
FILE: pages/goods-details/vop.json
================================================
{
"navigationBarTitleText": "商品详情",
"usingComponents": {
"poster": "wxa-plugin-canvas/poster"
}
}
================================================
FILE: pages/goods-details/vop.wxml
================================================
¥ {{price.priceSale}}
¥
{{price.priceJd}}
分享
二维码
{{price.skuName}}
{{goodsDetail.basicInfo.characteristic}}
{{pingtuanList.length}}人在拼单,可直接参与
{{item.apiExtUser.nick}}
已有
{{item.helpNumber}} 人参与
截止: {{item.dateEnd}}
请选择:
{{item.name}}
{{item.name}}
选择商品规格
{{property.name}}
{{item.name}}
{{shopSubdetail.info.name}}
{{shopSubdetail.info.address}}
商品详情
{{myHelpDetail?"您已砍过":"帮TA砍"}}
用当前价购买
保存到相册
添加收货地址
该地区已售罄
加入购物车
立即购买
================================================
FILE: pages/goods-details/vop.wxss
================================================
page,
view,
image,
input,
textarea {
display: block;
box-sizing: border-box;
}
.van-cell {
padding: 10px 38rpx;
}
.container {
background-color: #F2f2f2;
min-height: 100%;
padding-bottom: 100rpx;
}
.scroll-container {
height: 100vh;
padding-bottom: 64rpx;
}
.tabs-container {
width: 100%;
display: flex;
background-color: white;
}
.home-o {
width: 20%;
}
.swiper-container {
width: 100%;
position: relative;
}
.swiper_box {
width: 100%;
height: 748rpx;
}
swiper-item image {
width: 100%;
display: inline-block;
overflow: hidden;
height: 748rpx;
}
.goods-info {
background-color: #fff;
padding: 35rpx 0;
width: 100%;
position: relative;
}
.goods-info-top-container {
display: flex;
justify-content: space-between;
margin-bottom: 10rpx;
}
.goods-info-fx {
bottom: 60rpx;
display: flex;
align-items: center;
justify-content: space-between;
margin-right: 35rpx;
}
.goods-info-fx .item {
/* height: 50rpx; */
right: 130rpx;
top: 100rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 24rpx;
background: #fff;
z-index: 20;
}
.goods-info-fx .left {
margin-right: 10px;
}
.goods-info-fx .icon-title{
padding-top:5px ;
font-size: 11px;
}
.goods-info-fx .item image {
width: 50rpx;
height: 50rpx;
}
.goods-info-fx .item button {
position: absolute;
height: 100%;
width: 100%;
opacity: 0;
z-index: 99;
}
.goods-info .goods-title {
box-sizing: border-box;
padding: 0 30rpx;
font-size: 32rpx;
line-height: 1.4;
color: #000;
/* padding-bottom: 26rpx; */
}
.goods-info .goods-share {
box-sizing: border-box;
padding: 0 30rpx;
font-size: 25rpx;
line-height: 1.4;
color: #CC0000;
padding-top: 26rpx;
}
.vcell{
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
.goods-profile {
display: flex;
align-items: center;
}
.goods-profile .p {
color: #e64340;
font-size: 20pt;
margin-left: 30rpx;
}
.goods-profile .p text {
font-size: 12pt;
}
.goods-profile .r {
color: #ccc;
font-size: 10pt;
margin-left: 30rpx;
}
.row-arrow {
width: 100vw;
padding: 0 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
height: 102rpx;
font-size: 28rpx;
line-height: 102rpx;
background: #fff;
margin-bottom: 32rpx;
}
.row-arrow image {
width: 40rpx;
height: 40rpx;
}
.goods-des-info {
width: 100%;
box-sizing: border-box;
background-color: #fff;
border-radius: 12px;
}
.label-title {
font-size: 28rpx;
color: #000000;
padding: 30rpx;
display: flex;
justify-content: space-between;
}
.label-title .left{
border-left: 3px solid #e64340;
height: auto;
padding-left: 10px;
}
.goods-text {
padding: 0 10rpx;
font-size: 28rpx;
color: #666666;
line-height: 56rpx;
margin-bottom: 30rpx;
}
.goods-text image {
width: 100%;
}
.des-imgs {
width: 100%;
}
.des-imgs image {
width: 100%;
}
.footer-box {
width: 100%;
height: 100rpx;
background-color: #fff;
position: fixed;
bottom: 0;
left: 0;
display: flex;
box-shadow: 0 0 1rpx 0;
align-items: center;
}
.footer-box .contact {
position: relative;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-left: 32rpx;
}
.footer-box .contact button {
position: absolute;
height: 100%;
width: 100%;
opacity: 0;
z-index: 99;
}
.footer-box .contact image {
width: 60rpx;
height: 60rpx;
}
.footer-box .shop-cart-btn {
position: relative;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-left: 32rpx;
}
.footer-box .shop-cart-btn image {
width: 55rpx;
height: 55rpx;
}
.fav-icon {
width: 60rpx;
height: 60rpx;
margin-left: 32rpx;
/*707070*/
}
.footer-box .shop-cart-btn .shop-num {
position: absolute;
color: #fff;
left: 32rpx;
top: 10rpx;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border-radius: 50%;
background: #e64340;
font-size: 24rpx;
}
.footer-box .join-shop-cart {
text-align: center;
height: 100%;
line-height: 100rpx;
background-color: #ff6850;
color: #fff;
font-size: 34rpx;
flex: 1;
margin-left: 32rpx;
}
.footer-box .now-buy {
text-align: center;
height: 100%;
width: 250rpx;
line-height: 100rpx;
background-color: #e64340;
color: #fff;
font-size: 34rpx;
flex: 1;
}
.show-popup {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
}
.popup-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 5;
}
.popup-contents {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: #fff;
z-index: 6;
}
.pop-goods-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 32rpx;
margin-right: 32rpx;
padding: 30rpx 0;
border-bottom: 1px solid #eee;
}
.pop-img-box {
width: 120rpx;
height: 120rpx;
overflow: hidden;
margin-right: 26rpx;
}
.pop-img-box .goods-thumbnail {
width: 120rpx;
height: 120rpx;
}
.pop-goods-title {
width: 484rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 26rpx;
color: #000000;
}
.pop-goods-price {
font-size: 26rpx;
color: #e64340;
margin-top: 20rpx;
}
.pop-goods-price .t1 {
font-size: 50rpx;
}
.pop-goods-price-original {
font-size: 26rpx;
color: #aaa;
text-decoration: line-through;
margin-left: 16rpx;
}
.pop-goods-close {
width: 36rpx;
height: 36rpx;
}
.goods-property-container {
height: 56px;
align-items: center;
border-radius: 12px;
padding: 0 16px;
}
.size-label-box2 {
width: 100vw;
background: #fff;
}
.size-label-box .label {
font-size: 26rpx;
color: #000;
padding-left: 30rpx;
padding: 30rpx 0 20rpx 30rpx;
}
.size-label-box .label-item-box {
display: flex;
margin-left: 30rpx;
flex-direction: row;
flex-wrap: wrap;
}
.size-label-box .label-item {
font-size: 26rpx;
color: #000;
padding: 14rpx 20rpx;
border: 1px solid #ddd;
border-radius: 6rpx;
margin: 0 20rpx 20rpx 0;
}
.size-label-box .label-item.active {
color: #e64340;
border: 1px solid #e64340;
}
.buy-num-box {
display: flex;
justify-content: space-between;
padding: 30rpx 30rpx 48rpx 0;
margin-left: 30rpx;
border-top: 1px solid #eee;
margin-top: 30rpx;
align-items: center;
}
.num-label {
font-size: 26rpx;
color: #000000;
}
.buy-num-box .num-box {
display: flex;
}
.buy-num-box .num-box .num-jian,
.buy-num-box .num-box .num-input,
.buy-num-box .num-box .num-jia {
width: 80rpx;
height: 64rpx;
line-height: 62rpx;
text-align: center;
border: 1px solid #eee;
}
.buy-num-box .num-box .num-input {
font-size: 28rpx;
}
.buy-num-box .num-box .num-input input {
height: 100%;
}
.popup-join-btn {
width: 100%;
height: 89rpx;
text-align: center;
line-height: 89rpx;
font-size: 34rpx;
color: #ffffff;
background-color: #e64340;
}
.buy-num-box .num-box .hui {
background-color: #f5f5f9;
}
.curKanjiaprogress {
width: 750rpx;
background-color: #fff;
margin-top: 20rpx;
}
.curKanjiaprogress .name {
font-size: 40rpx;
padding: 20rpx;
text-align: center;
}
.curKanjiaprogress .placeholder {
margin-left: 30rpx;
margin-right: 30rpx;
text-align: center;
font-size: 26rpx;
width: 100rpx;
color: #999;
}
.curKanjiaprogress .kjbutton {
padding: 30rpx;
}
.kjBuyButton {
position: fixed;
left: 0;
bottom: calc(env(safe-area-inset-bottom) / 2);
width: 750rpx;
display: flex;
}
.kjBuyButton .item {
flex: 1;
}
.shareFloatDiv1 {
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
background-color: #555;
filter: Alpha(Opacity=60);
opacity: 0.6;
z-index: 99998;
}
.shareFloatDiv2 {
position: fixed;
width: 100%;
height: 400rpx;
background-color: #ffffff;
bottom: 0rpx;
z-index: 99999;
}
.shareFloatDiv2 .p1 {
height: 260rpx;
}
.shareFloatDiv2 .p2 {
height: 20rpx;
background-color: #EEEEEE;
}
.shareFloatDiv2 .p3 {
height: 120rpx;
line-height: 120rpx;
text-align: center;
color: #555555;
font-size: 16px;
}
.qrcode-button {
padding: 30rpx;
margin-top: 50rpx;
}
.qrcode {
width: 300rpx;
height: 300rpx;
margin-top: 50rpx;
}
.posterImg-box {
position: absolute;
top: 104rpx;
left: 32rpx;
width: 686rpx;
margin-bottom: 100rpx;
z-index: 999999;
}
.posterImg {
width: 100%;
}
.btn-create {
margin: 32rpx;
margin-bottom: 0;
height: 88rpx;
line-height: 88rpx;
background: #e64340;
color: #fff;
text-align: center;
border-radius: 8rpx;
}
.clearfix:after {
/*伪元素是行内元素 正常浏览器清除浮动方法*/
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.shop-container {
width: 100vw;
margin: 32rpx 0rpx;
padding: 32rpx;
display: flex;
align-items: center;
background: #fff;
}
.shop-container image {
width: 90rpx;
height: 90rpx;
}
.shop-container .info {
margin-left: 32rpx;
}
.shop-container .info .title {
font-size: 30rpx;
color: #333;
}
.shop-container .info .address {
font-size: 26rpx;
color: #666;
}
.reputation-cell-group{
background-color:white !important;
border-radius: 12px;
}
.reputation-cell {
padding-bottom: 0rpx !important;
--cell-icon-size: 88rpx;
}
.reputation-cell .van-icon {
top: 16rpx !important;
}
.reputation-cell .avatarUrl-img{
width: 40px;
height: 40px;
border-radius: 100%;
margin-right: 26rpx;
}
.reputation-cell-reamrk {
/* padding-left: 96rpx; */
}
.reputation-pics {
width: 100vw;
display: flex;
flex-wrap: wrap;
background: #ffffff;
}
.reputation-pics image {
width: 207rpx;
height: 207rpx;
margin: 32rpx 0 0 32rpx;
border-radius: 16rpx;
}
.characteristic {
padding: 8rpx 32rpx;
color: #666;
font-size: 26rpx;
}
================================================
FILE: pages/help/detail.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
// options.id = 34094
this.data.id = options.id
this.fetchDetail()
},
onShow: function () {
},
async fetchDetail() {
const res = await WXAPI.cmsArticleDetailV3({ id: this.data.id })
if (res.code == 0) {
this.setData({
cmsArticleDetail: res.data.info
})
wx.setNavigationBarTitle({
title: res.data.info.title,
})
}
},
onShareAppMessage: function() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - ' + this.data.cmsArticleDetail.title,
path: `/pages/help/detail?id=${this.data.id}&inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
onShareTimeline() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - ' + this.data.cmsArticleDetail.title,
query: `id=${this.data.id}&inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
})
================================================
FILE: pages/help/detail.json
================================================
{
"navigationBarTitleText": ""
}
================================================
FILE: pages/help/detail.wxml
================================================
================================================
FILE: pages/help/detail.wxss
================================================
.content {
padding: 32rpx;
color: #333;
line-height: 64rpx;
}
================================================
FILE: pages/help/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
this.category()
},
onShow: function () {
},
async category() {
const res = await WXAPI.cmsCategories()
if (res.code == 0) {
const category = res.data.filter(ele => {
return ele.type == 'qa'
})
this.setData({
category: category
})
if (category && category.length > 0) {
this.articles(category[0].id)
}
}
},
async articles(categoryId) {
wx.showLoading({
title: '',
})
const res = await WXAPI.cmsArticlesV3({
categoryId
})
wx.hideLoading()
if (res.code == 0) {
this.setData({
cmsArticles: res.data.result
})
} else {
this.setData({
cmsArticles: null
})
}
},
categoryChange(e) {
const index = e.detail
const category = this.data.category[index]
this.articles(category.id)
},
onShareAppMessage: function() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - 帮助中心',
path: `/pages/help/index?inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
onShareTimeline() {
const uid = wx.getStorageSync('uid')
return {
title: wx.getStorageSync('mallName') + ' - 帮助中心',
query: `inviter_id=${ uid ? uid : ''}`,
imageUrl: wx.getStorageSync('share_pic')
}
},
})
================================================
FILE: pages/help/index.json
================================================
{
"navigationBarTitleText": "帮助中心"
}
================================================
FILE: pages/help/index.wxml
================================================
================================================
FILE: pages/help/index.wxss
================================================
page {
width: 100vw;
height: 100vh;
display: flex;
}
.category {
width: 176rpx;
height: 100vh;
flex-shrink: 0;
}
.articles {
height: 100vh;
flex: 1;
}
================================================
FILE: pages/idCheck/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
},
async submit() {
if (!this.data.name) {
wx.showToast({
title: '请输入姓名',
icon: 'none'
})
return
}
if (!this.data.idcard) {
wx.showToast({
title: '请输入身份证号码',
icon: 'none'
})
return
}
wx.showLoading({
title: '',
})
this.setData({
loading: true
})
const res = await WXAPI.idcardCheck(wx.getStorageSync('token'), this.data.name, this.data.idcard)
wx.hideLoading({
success: (res) => {},
})
this.setData({
loading: false
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '认证通过',
})
setTimeout(() => {
wx.navigateBack()
}, 1000);
},
})
================================================
FILE: pages/idCheck/index.json
================================================
{
"navigationBarTitleText": "实名认证"
}
================================================
FILE: pages/idCheck/index.wxml
================================================
立即认证
================================================
FILE: pages/idCheck/index.wxss
================================================
.btn {
width: 700rpx;
margin: 64rpx auto;
}
================================================
FILE: pages/index/index.js
================================================
const WXAPI = require('apifm-wxapi')
const TOOLS = require('../../utils/tools.js')
const AUTH = require('../../utils/auth')
const APP = getApp()
Page({
data: {
inputVal: "", // 搜索框内容
goodsRecommend: [], // 推荐商品
kanjiaList: [], //砍价商品列表
pingtuanList: [], //拼团商品列表
loadingHidden: false, // loading
selectCurrent: 0,
categories: [],
goods: [],
loadingMoreHidden: true,
coupons: [],
curPage: 1,
pageSize: 20
},
tabClick(e) {
// 商品分类点击
const category = this.data.categories.find(ele => {
return ele.id == e.currentTarget.dataset.id
})
if (category.vopCid1 || category.vopCid2) {
wx.navigateTo({
url: '/pages/goods/list-vop?cid1=' + (category.vopCid1 ? category.vopCid1 : '') + '&cid2=' + (category.vopCid2 ? category.vopCid2 : ''),
})
} else {
wx.setStorageSync("_categoryId", category.id)
wx.switchTab({
url: '/pages/category/category',
})
}
},
tabClickCms(e) {
// 文章分类点击
const category = this.data.cmsCategories[e.currentTarget.dataset.idx]
wx.navigateTo({
url: '/pages/cms/list?categoryId=' + category.id,
})
},
toDetailsTap: function(e) {
console.log(e);
const id = e.currentTarget.dataset.id
const supplytype = e.currentTarget.dataset.supplytype
const yyId = e.currentTarget.dataset.yyid
if (supplytype == 'cps_jd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-jd?id=${id}`,
})
} else if (supplytype == 'vop_jd') {
wx.navigateTo({
url: `/pages/goods-details/vop?id=${yyId}&goodsId=${id}`,
})
} else if (supplytype == 'cps_pdd') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-pdd?id=${id}`,
})
} else if (supplytype == 'cps_taobao') {
wx.navigateTo({
url: `/packageCps/pages/goods-details/cps-taobao?id=${id}`,
})
} else {
wx.navigateTo({
url: `/pages/goods-details/index?id=${id}`,
})
}
},
tapBanner(e) {
const item = e.currentTarget.dataset.item
if (item.linkType == 1) {
// 跳小程序
wx.navigateToMiniProgram({
appId: item.appid,
path: item.linkUrl || '',
})
} else {
if (item.linkUrl) {
wx.navigateTo({
url: item.linkUrl
})
}
}
},
adClick: function(e) {
const url = e.currentTarget.dataset.url
if (url) {
wx.navigateTo({
url
})
}
},
bindTypeTap: function(e) {
this.setData({
selectCurrent: e.index
})
},
onLoad: function(e) {
wx.showShareMenu({
withShareTicket: true,
})
const that = this
// 读取分享链接中的邀请人编号
if (e && e.inviter_id) {
wx.setStorageSync('referrer', e.inviter_id)
}
// 读取小程序码中的邀请人编号
if (e && e.scene) {
const scene = decodeURIComponent(e.scene)
if (scene) {
wx.setStorageSync('referrer', scene.substring(11))
}
}
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
TOOLS.showTabBarBadge()
} else {
getApp().loginOK = () => {
TOOLS.showTabBarBadge()
}
}
})
this.initBanners()
this.cmsCategories()
// https://www.yuque.com/apifm/nu0f75/wg5t98
WXAPI.goodsv2({
recommendStatus: 1
}).then(res => {
if (res.code === 0){
that.setData({
goodsRecommend: res.data.result
})
}
})
that.getCoupons()
that.getNotice()
that.kanjiaGoods()
that.pingtuanGoods()
this.adPosition()
// 读取系统参数
this.readConfigVal()
getApp().configLoadOK = () => {
this.readConfigVal()
}
},
readConfigVal() {
const mallName = wx.getStorageSync('mallName')
if (!mallName) {
return
}
this.categories()
wx.setNavigationBarTitle({
title: mallName
})
this.setData({
mallName:wx.getStorageSync('mallName')?wx.getStorageSync('mallName'):'',
show_buy_dynamic: wx.getStorageSync('show_buy_dynamic'),
hidden_goods_index: wx.getStorageSync('hidden_goods_index'),
})
const shopMod = wx.getStorageSync('shopMod')
const shopInfo = wx.getStorageSync('shopInfo')
if (shopMod == '1' && !shopInfo) {
wx.redirectTo({
url: '/pages/shop/select'
})
}
},
async miaoshaGoods(){
// https://www.yuque.com/apifm/nu0f75/wg5t98
const res = await WXAPI.goodsv2({
miaosha: true
})
if (res.code == 0) {
res.data.result.forEach(ele => {
const _now = new Date().getTime()
if (ele.dateStart) {
ele.dateStartInt = new Date(ele.dateStart.replace(/-/g, '/')).getTime() - _now
}
if (ele.dateEnd) {
ele.dateEndInt = new Date(ele.dateEnd.replace(/-/g, '/')).getTime() -_now
}
})
this.setData({
miaoshaGoods: res.data.result
})
}
},
async initBanners(){
const _data = {}
// 读取头部轮播图
const res1 = await WXAPI.banners({
type: 'index'
})
if (res1.code == 700) {
wx.showModal({
title: '提示',
content: '请在后台添加 banner 轮播图片,自定义类型填写 index',
showCancel: false
})
} else {
_data.banners = res1.data
}
this.setData(_data)
},
onShow: function(e){
this.setData({
navHeight: APP.globalData.navHeight,
navTop: APP.globalData.navTop,
windowHeight: APP.globalData.windowHeight,
menuButtonObject: APP.globalData.menuButtonObject //小程序胶囊信息
})
this.setData({
shopInfo: wx.getStorageSync('shopInfo')
})
// 获取购物车数据,显示TabBarBadge
TOOLS.showTabBarBadge()
this.goodsDynamicV2()
this.miaoshaGoods()
const refreshIndex = wx.getStorageSync('refreshIndex')
if (refreshIndex) {
this.onPullDownRefresh()
wx.removeStorageSync('refreshIndex')
}
},
async goodsDynamicV2(){
const res = await WXAPI.goodsDynamicV2({
type: 0
})
if (res.code == 0) {
this.setData({
goodsDynamicV2: res.data.result
})
}
},
async categories(){
const res = await WXAPI.goodsCategory()
let categories = [];
if (res.code == 0) {
const _categories = res.data.filter(ele => {
return ele.level == 1
})
categories = categories.concat(_categories)
}
this.setData({
categories: categories,
curPage: 1
});
this.getGoodsList(0);
},
async getGoodsList(categoryId, append) {
if (categoryId == 0) {
categoryId = "";
}
wx.showLoading({
title: ''
})
// https://www.yuque.com/apifm/nu0f75/wg5t98
const res = await WXAPI.goodsv2({
categoryId: categoryId,
page: this.data.curPage,
pageSize: this.data.pageSize
})
wx.hideLoading()
if (res.code == 404 || res.code == 700) {
let newData = {
loadingMoreHidden: false
}
if (!append) {
newData.goods = []
}
this.setData(newData);
return
}
let goods = [];
if (append) {
goods = this.data.goods
}
for (var i = 0; i < res.data.result.length; i++) {
const item = res.data.result[i]
const hidden_goods_index = wx.getStorageSync('hidden_goods_index')
if (hidden_goods_index.indexOf(item.id) != -1) {
continue
}
goods.push(item);
}
this.setData({
loadingMoreHidden: true,
goods: goods,
});
},
getCoupons: function() {
var that = this;
WXAPI.coupons().then(function (res) {
if (res.code == 0) {
that.setData({
coupons: res.data
});
}
})
},
onShareAppMessage: function() {
return {
title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
path: '/pages/index/index?inviter_id=' + wx.getStorageSync('uid')
}
},
onShareTimeline() {
return {
title: '"' + wx.getStorageSync('mallName') + '" ' + wx.getStorageSync('share_profile'),
query: 'inviter_id=' + wx.getStorageSync('uid'),
imageUrl: wx.getStorageSync('share_pic')
}
},
getNotice: function() {
var that = this;
WXAPI.noticeList({pageSize: 5}).then(function (res) {
if (res.code == 0) {
that.setData({
noticeList: res.data
});
}
})
},
onReachBottom: function() {
this.setData({
curPage: this.data.curPage + 1
});
this.getGoodsList(0, true)
},
onPullDownRefresh: function() {
this.setData({
curPage: 1
});
this.getGoodsList(0)
wx.stopPullDownRefresh()
},
// 获取砍价商品
async kanjiaGoods(){
// https://www.yuque.com/apifm/nu0f75/wg5t98
const res = await WXAPI.goodsv2({
kanjia: true
});
if (res.code == 0) {
const kanjiaGoodsIds = []
res.data.result.forEach(ele => {
kanjiaGoodsIds.push(ele.id)
})
const goodsKanjiaSetRes = await WXAPI.kanjiaSet(kanjiaGoodsIds.join())
if (goodsKanjiaSetRes.code == 0) {
res.data.result.forEach(ele => {
const _process = goodsKanjiaSetRes.data.find(_set => {
return _set.goodsId == ele.id
})
if (_process) {
ele.process = 100 * _process.numberBuy / _process.number
ele.process = ele.process.toFixed(0)
}
})
this.setData({
kanjiaList: res.data.result
})
}
}
},
goCoupons: function (e) {
wx.switchTab({
url: "/pages/coupons/index"
})
},
pingtuanGoods(){ // 获取团购商品列表
const _this = this
// https://www.yuque.com/apifm/nu0f75/wg5t98
WXAPI.goodsv2({
pingtuan: true
}).then(res => {
if (res.code === 0) {
_this.setData({
pingtuanList: res.data.result
})
}
})
},
goSearch(){
wx.navigateTo({
url: '/pages/search/index'
})
},
goNotice(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({
url: '/pages/notice/show?id=' + id,
})
},
async adPosition() {
let res = await WXAPI.adPosition('indexPop')
if (res.code == 0) {
this.setData({
adPositionIndexPop: res.data
})
}
res = await WXAPI.adPosition('index-live-pic')
if (res.code == 0) {
this.setData({
adPositionIndexLivePic: res.data
})
}
},
clickAdPositionIndexLive() {
if (!this.data.adPositionIndexLivePic || !this.data.adPositionIndexLivePic.url) {
return
}
wx.navigateTo({
url: this.data.adPositionIndexLivePic.url,
})
},
closeAdPositionIndexPop() {
this.setData({
adPositionIndexPop: null
})
},
clickAdPositionIndexPop() {
const adPositionIndexPop = this.data.adPositionIndexPop
this.setData({
adPositionIndexPop: null
})
if (!adPositionIndexPop || !adPositionIndexPop.url) {
return
}
wx.navigateTo({
url: adPositionIndexPop.url,
})
},
async cmsCategories() {
// https://www.yuque.com/apifm/nu0f75/slu10w
const res = await WXAPI.cmsCategories()
if (res.code == 0) {
const cmsCategories = res.data.filter(ele => {
return ele.type == 'index' // 只筛选类型为 index 的分类
})
this.setData({
cmsCategories
})
}
},
})
================================================
FILE: pages/index/index.json
================================================
{
"enablePullDownRefresh": true
}
================================================
FILE: pages/index/index.wxml
================================================
{{shopInfo.name}}
切换
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId
} else {
return '/pages/goods-details/index?id=' + item.goodsId
}
}
}
{{item.nick}} 购买了 {{item.goodsName}}
{{item.name}}
{{item.name}}
{{item.name}}
{{item.name}}
{{item.characteristic}}
¥
{{item.minPrice}}
¥{{item.originalPrice}}
{{item.name}}
{{item.characteristic}}
{{item.tags}}
{{item.name}}
{{item.characteristic}}
{{item.name}}
{{item.characteristic}}
¥
{{item.minPrice}}
¥{{item.originalPrice}}
— 已经到底啦 —
================================================
FILE: pages/index/index.wxss
================================================
/* ==========================
京东风格 - 首页样式
配色: 京东红 #E4393C, 黑色 #333, 灰色 #999, 浅灰 #F5F5F5
========================== */
page {
background-color: #F5F5F5;
}
/* ========== 顶部搜索栏 ========== */
.jd-search-container {
background: linear-gradient(135deg, #E4393C 0%, #D81E06 100%);
padding: 20rpx 24rpx 24rpx;
position: relative;
}
.jd-search {
position: relative;
width: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
}
.jd-search-title {
font-weight: bold;
font-size: 36rpx;
color: #FFFFFF;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 16rpx;
letter-spacing: 2rpx;
}
.jd-search-box {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(10rpx);
height: 72rpx;
border-radius: 36rpx;
padding: 0 28rpx;
margin: 0 24rpx 16rpx;
box-shadow: 0 6rpx 24rpx rgba(0, 0, 0, 0.12);
transition: all 0.3s ease;
}
.jd-search-icon {
width: 32rpx;
height: 32rpx;
margin-right: 16rpx;
flex-shrink: 0;
opacity: 0.5;
}
.jd-search-box input {
flex: 1;
height: 72rpx;
line-height: 72rpx;
font-size: 28rpx;
color: #333;
background: transparent;
}
.jd-search-placeholder {
font-size: 28rpx;
color: #999;
}
/* ========== 门店选择 ========== */
.jd-shop-selector {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 24rpx;
background: #FFFFFF;
margin: 16rpx 24rpx;
border-radius: 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
}
.jd-shop-info {
display: flex;
align-items: center;
flex: 1;
}
.jd-shop-info image {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx;
}
.jd-shop-name {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.jd-shop-change {
display: flex;
align-items: center;
font-size: 26rpx;
color: #E4393C;
}
.jd-shop-change text {
margin-right: 8rpx;
}
.jd-shop-change image {
width: 24rpx;
height: 24rpx;
}
/* ========== 轮播图 ========== */
.jd-banner-container {
width: 100%;
height: 400rpx;
position: relative;
margin-bottom: 20rpx;
padding-top: 16rpx;
}
.jd-banner-swiper {
width: 100%;
height: 400rpx;
}
.jd-banner-item {
width: 100%;
height: 400rpx;
padding: 0 24rpx;
box-sizing: border-box;
}
.jd-banner-item image {
width: 100%;
height: 100%;
border-radius: 16rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}
/* 购买动态 */
.jd-buy-dynamic {
position: absolute;
bottom: 32rpx;
left: 48rpx;
right: 48rpx;
z-index: 10;
}
.jd-dynamic-swiper {
width: 100%;
height: 60rpx;
}
.jd-dynamic-item {
display: flex;
align-items: center;
background: linear-gradient(90deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.4) 100%);
backdrop-filter: blur(10rpx);
border-radius: 30rpx;
padding: 8rpx 20rpx;
font-size: 24rpx;
color: #FFFFFF;
}
.jd-dynamic-item image {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
margin-right: 12rpx;
border: 2rpx solid #FFFFFF;
flex-shrink: 0;
}
.jd-dynamic-item text {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ========== 分类导航 ========== */
.jd-category-container {
background: #FFFFFF;
padding: 28rpx 16rpx 32rpx;
margin: 0 24rpx 20rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.jd-category-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.jd-category-item {
width: 20%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 24rpx;
}
.jd-category-icon-wrap {
width: 88rpx;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 12rpx;
border-radius: 16rpx;
background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.1);
transition: all 0.3s ease;
}
.jd-category-icon-wrap image {
width: 64rpx;
height: 64rpx;
}
.jd-category-name {
font-size: 24rpx;
color: #333;
text-align: center;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ========== 公告通知 ========== */
.jd-notice-container {
margin: 0 24rpx 20rpx;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
.jd-notice-swiper {
height: 72rpx;
}
.jd-notice-icon {
width: 120rpx;
height: 32rpx;
margin-right: 16rpx;
}
/* ========== 主容器 ========== */
.jd-main-container {
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 直播广告横幅 */
.jd-live-banner {
display: block;
width: 702rpx;
margin: 0 auto 28rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}
/* ========== 区块标题 ========== */
.jd-section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx 24rpx 28rpx;
}
.jd-section-title {
display: flex;
align-items: center;
}
.jd-section-icon {
width: 40rpx;
height: 40rpx;
margin-right: 12rpx;
}
.jd-section-name {
font-size: 36rpx;
font-weight: bold;
color: #333;
position: relative;
}
.jd-section-name::after {
content: '';
position: absolute;
bottom: -6rpx;
left: 0;
width: 60%;
height: 6rpx;
background: linear-gradient(90deg, #E4393C 0%, transparent 100%);
border-radius: 3rpx;
}
.jd-section-more {
font-size: 26rpx;
color: #999;
display: flex;
align-items: center;
}
/* ========== 秒杀商品 ========== */
.jd-seckill-container {
padding: 0 24rpx 20rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
}
.jd-seckill-item {
background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.12);
position: relative;
}
.jd-seckill-img-wrap {
width: 100%;
height: 702rpx;
position: relative;
overflow: hidden;
}
.jd-seckill-img-wrap image {
width: 100%;
height: 100%;
display: block;
}
.jd-seckill-info {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.95) 30%, rgba(255, 255, 255, 1) 60%);
padding: 80rpx 24rpx 24rpx;
}
.jd-seckill-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 16rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.jd-seckill-countdown {
background: linear-gradient(135deg, #FFF0F0 0%, #FFE5E5 100%);
border-radius: 8rpx;
padding: 12rpx 20rpx;
margin-bottom: 20rpx;
display: inline-block;
}
.jd-seckill-countdown .van-count-down {
color: #E4393C !important;
font-size: 26rpx !important;
font-weight: bold !important;
}
.jd-seckill-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.jd-seckill-price {
display: flex;
align-items: baseline;
}
.jd-price-symbol {
font-size: 32rpx;
color: #E4393C;
font-weight: bold;
margin-right: 4rpx;
}
.jd-price-num {
font-size: 48rpx;
color: #E4393C;
font-weight: bold;
line-height: 1;
}
.jd-price-del {
font-size: 26rpx;
color: #999;
text-decoration: line-through;
margin-left: 16rpx;
}
.jd-seckill-btn-wrap {
flex-shrink: 0;
}
.jd-seckill-btn {
min-width: 160rpx;
height: 64rpx;
line-height: 64rpx;
text-align: center;
border-radius: 32rpx;
font-size: 28rpx;
font-weight: bold;
padding: 0 32rpx;
}
.jd-btn-active {
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
color: #FFFFFF;
box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.4);
}
.jd-btn-disabled {
background: #F5F5F5;
color: #999;
}
/* ========== 商品网格(推荐、列表) ========== */
.jd-goods-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 24rpx 20rpx;
gap: 20rpx;
}
.jd-goods-card {
width: calc(50% - 15rpx);
background: #FFFFFF;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.jd-goods-img-wrap {
width: 100%;
height: 345rpx;
position: relative;
overflow: hidden;
background: #F9F9F9;
}
.jd-goods-img-wrap image {
width: 100%;
height: 100%;
display: block;
}
.jd-goods-info {
padding: 16rpx;
}
.jd-goods-name {
font-size: 28rpx;
color: #333;
line-height: 1.4;
height: 78rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 8rpx;
}
.jd-goods-desc {
font-size: 24rpx;
color: #999;
line-height: 1.3;
height: 31rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 12rpx;
}
.jd-goods-price-box {
display: flex;
align-items: baseline;
justify-content: space-between;
}
.jd-goods-price {
display: flex;
align-items: baseline;
color: #E4393C;
}
.jd-goods-price .jd-price-symbol {
font-size: 24rpx;
}
.jd-goods-price .jd-price-num {
font-size: 36rpx;
}
.jd-goods-original-price {
font-size: 22rpx;
color: #999;
text-decoration: line-through;
margin-left: 8rpx;
}
/* ========== 砍价商品 ========== */
.jd-kanjia-container {
padding: 0 24rpx 20rpx;
display: flex;
flex-direction: column;
gap: 20rpx;
}
.jd-kanjia-card {
display: flex;
background: #FFFFFF;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
padding: 20rpx;
}
.jd-kanjia-img-wrap {
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
overflow: hidden;
flex-shrink: 0;
margin-right: 20rpx;
background: #F9F9F9;
}
.jd-kanjia-img-wrap image {
width: 100%;
height: 100%;
display: block;
}
.jd-kanjia-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.jd-kanjia-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 8rpx;
}
.jd-kanjia-desc {
font-size: 24rpx;
color: #999;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 12rpx;
}
.jd-kanjia-progress {
margin-bottom: 16rpx;
}
.jd-kanjia-bar {
border-radius: 3rpx !important;
}
.jd-kanjia-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.jd-kanjia-price {
display: flex;
align-items: baseline;
}
.jd-kanjia-price .jd-price-symbol {
font-size: 26rpx;
}
.jd-kanjia-price .jd-price-num {
font-size: 40rpx;
}
.jd-kanjia-btn {
min-width: 140rpx;
height: 56rpx;
line-height: 56rpx;
text-align: center;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
color: #FFFFFF;
border-radius: 28rpx;
font-size: 26rpx;
font-weight: bold;
padding: 0 24rpx;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
/* ========== 拼团商品 ========== */
.jd-pingtuan-container {
padding: 0 0 20rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
}
.jd-pingtuan-card {
background: #FFFFFF;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.jd-pingtuan-img-wrap {
width: 100%;
height: 420rpx;
position: relative;
overflow: hidden;
background: linear-gradient(135deg, #F9F9F9 0%, #FFFFFF 100%);
}
.jd-pingtuan-img-wrap image {
width: 100%;
height: 100%;
display: block;
}
.jd-pingtuan-tag {
position: absolute;
top: 16rpx;
left: 16rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
color: #FFFFFF;
font-size: 22rpx;
padding: 8rpx 16rpx;
border-radius: 20rpx 20rpx 20rpx 4rpx;
font-weight: bold;
box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.4);
}
.jd-pingtuan-info {
padding: 20rpx;
}
.jd-pingtuan-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-bottom: 8rpx;
min-height: 78rpx;
}
.jd-pingtuan-desc {
font-size: 24rpx;
color: #999;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 16rpx;
}
.jd-pingtuan-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.jd-pingtuan-price {
display: flex;
align-items: baseline;
}
.jd-pingtuan-price .jd-price-symbol {
font-size: 26rpx;
}
.jd-pingtuan-price .jd-price-num {
font-size: 40rpx;
}
.jd-pingtuan-btn {
min-width: 140rpx;
height: 56rpx;
line-height: 56rpx;
text-align: center;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
color: #FFFFFF;
border-radius: 28rpx;
font-size: 26rpx;
font-weight: bold;
padding: 0 24rpx;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
/* ========== 优惠券悬浮按钮 ========== */
.jd-coupon-float {
position: fixed;
right: 24rpx;
bottom: 120rpx;
width: 104rpx;
height: 104rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 32rpx rgba(228, 57, 60, 0.45);
z-index: 100;
animation: float-bounce 3s ease-in-out infinite;
}
@keyframes float-bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-8rpx);
}
}
.jd-coupon-float image {
width: 52rpx;
height: 52rpx;
margin-bottom: 4rpx;
filter: brightness(0) invert(1);
}
.jd-coupon-float text {
font-size: 22rpx;
color: #FFFFFF;
font-weight: bold;
letter-spacing: 1rpx;
}
/* ========== 弹窗广告 ========== */
.adPositionIndexPop {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.adPositionIndexPop image {
max-width: 600rpx;
border-radius: 16rpx;
}
.adPositionIndexPop .close {
margin-top: 48rpx;
}
/* ========== 底部分割线 ========== */
.jd-end-divider {
margin-top: 40rpx !important;
margin-bottom: 40rpx !important;
color: #999 !important;
font-size: 24rpx !important;
}
/* ========== 滚动条隐藏 ========== */
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
/* ========== 通用间距 ========== */
.space {
height: 24rpx;
}
/* ========== 兼容旧样式 ========== */
.container {
background-color: #F5F5F5;
}
/* Van组件自定义样式 */
.van-card__price-integer {
font-size: 36rpx !important;
color: #E4393C !important;
font-weight: bold !important;
}
.van-progress__portion {
background: #E4393C !important;
}
.van-count-down {
color: #E4393C !important;
font-size: 26rpx !important;
}
/* ========== 响应式优化 ========== */
@media (max-width: 375px) {
.jd-section-name {
font-size: 32rpx;
}
.jd-goods-name {
font-size: 26rpx;
}
}
================================================
FILE: pages/invoice/apply.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
/**
* 页面的初始数据
*/
data: {
consumption: '服务费'
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(e) {
// 读取分享链接中的邀请人编号
if (e && e.inviter_id) {
wx.setStorageSync('referrer', e.inviter_id)
}
// 弹出编辑昵称头像框
getApp().initNickAvatarUrlPOP(this)
},
onShow() {
},
chooseInvoiceTitle(){
wx.chooseInvoiceTitle({
success: (res) => {
this.setData({
wxInvoiceInfo: res,
comName: res.title,
tfn: res.taxNumber,
address: res.companyAddress + res.telephone,
bank: res.bankName + res.bankAccount,
})
},
fail: err => {
console.error(err);
wx.showToast({
title: '读取失败',
icon: 'none'
})
}
})
},
onShareAppMessage() {
return {
title: '申请开票',
path: '/pages/invoice/apply?inviter_id=' + wx.getStorageSync('uid'),
imageUrl: wx.getStorageSync('invoice_share_pic')
}
},
onShareTimeline() {
return {
title: '申请开票',
query: 'inviter_id=' + wx.getStorageSync('uid'),
imageUrl: wx.getStorageSync('invoice_share_pic')
}
},
async bindSave() {
const invoice_subscribe_ids = wx.getStorageSync('invoice_subscribe_ids')
if (invoice_subscribe_ids) {
wx.requestSubscribeMessage({
tmplIds: invoice_subscribe_ids.split(','),
success(res) {
console.log(res)
},
fail(err) {
console.error(err)
},
complete: (res) => {
this._bindSave()
},
})
} else {
this._bindSave()
}
},
async _bindSave() {
// 提交保存
let comName = this.data.comName;
let tfn = this.data.tfn;
let mobile = this.data.mobile;
let amount = this.data.amount;
let consumption = this.data.consumption;
let remark = this.data.remark || '';
let email = this.data.email
let address = this.data.address;
let bank = this.data.bank;
if (!mobile) {
wx.showToast({
title: '请填写您在工厂注册的手机号码',
icon: 'none'
})
return
}
if (!comName) {
wx.showToast({
title: '公司名称不能为空',
icon: 'none'
})
return
}
if (!tfn) {
wx.showToast({
title: '税号不能为空',
icon: 'none'
})
return
}
if (!consumption) {
wx.showToast({
title: '发票内容不能为空',
icon: 'none'
})
return
}
if (!email) {
wx.showToast({
title: '请填写邮箱地址',
icon: 'none'
})
return
}
if (!amount || amount*1 < 100) {
wx.showToast({
title: '开票金额不能低于100',
icon: 'none'
})
return
}
const extJsonStr = {}
extJsonStr['api工厂账号'] = mobile
extJsonStr['地址与电话'] = address
extJsonStr['开户行与账号'] = bank
WXAPI.invoiceApply({
token: wx.getStorageSync('token'),
comName,
tfn,
amount,
consumption,
remark,
email,
extJsonStr: JSON.stringify(extJsonStr)
}).then(res => {
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code == 0) {
wx.showModal({
title: '成功',
content: '提交成功,请耐心等待我们处理!',
showCancel: false,
confirmText: '我知道了',
success(res) {
wx.navigateTo({
url: "/pages/invoice/list"
})
}
})
} else {
wx.showModal({
title: '失败',
content: res.msg,
showCancel: false,
confirmText: '我知道了'
})
}
})
},
})
================================================
FILE: pages/invoice/apply.json
================================================
{
"navigationBarTitleText": "发票申请"
}
================================================
FILE: pages/invoice/apply.wxml
================================================
📋
快速填写
读取微信开票信息
›
工厂账号
*
发票抬头
*
税号
*
发票内容
*
发票金额
*
¥
地址与电话
开户行与账号
电子邮箱
*
备注
💡 温馨提示
• 发票金额不能低于100元
• 电子发票将在3-5个工作日内发送到您的邮箱
查看开票记录
›
================================================
FILE: pages/invoice/apply.wxss
================================================
/* 京东风格 - 发票申请页面 */
page {
background: linear-gradient(180deg, #f8f8f8 0%, #ffffff 100%);
min-height: 100vh;
}
.page-container {
padding-bottom: 40rpx;
}
/* 顶部装饰栏 */
.header-bar {
background: linear-gradient(135deg, #E4393C 0%, #F85959 100%);
padding: 40rpx 32rpx 60rpx;
position: relative;
overflow: hidden;
}
.header-bar::after {
content: '';
position: absolute;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
right: -100rpx;
top: -200rpx;
}
.header-content {
position: relative;
z-index: 1;
}
.header-title {
font-size: 40rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 8rpx;
letter-spacing: 2rpx;
}
.header-subtitle {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.9);
letter-spacing: 1rpx;
font-weight: 300;
}
/* 快捷导入卡片 */
.quick-import-card {
margin: -30rpx 24rpx 20rpx;
background: #ffffff;
border-radius: 16rpx;
padding: 28rpx 32rpx;
box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.12);
display: flex;
align-items: center;
position: relative;
overflow: hidden;
}
.quick-import-card::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6rpx;
background: linear-gradient(180deg, #E4393C 0%, #F85959 100%);
}
.import-icon {
font-size: 48rpx;
margin-right: 24rpx;
margin-left: 12rpx;
}
.import-content {
flex: 1;
}
.import-title {
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-bottom: 4rpx;
}
.import-desc {
font-size: 24rpx;
color: #999999;
}
.import-arrow {
font-size: 48rpx;
color: #E4393C;
font-weight: 300;
margin-right: 8rpx;
}
/* 主表单卡片 */
.form-card {
margin: 0 24rpx 20rpx;
background: #ffffff;
border-radius: 16rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
overflow: hidden;
}
.card-header {
padding: 32rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.card-title {
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
.title-icon {
width: 6rpx;
height: 28rpx;
background: linear-gradient(180deg, #E4393C 0%, #F85959 100%);
border-radius: 3rpx;
margin-right: 16rpx;
}
/* 表单内容 */
.form-content {
padding: 0 32rpx;
}
.input-group {
padding: 32rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.input-group.last-group {
border-bottom: none;
}
.input-label {
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.label-text {
font-size: 28rpx;
color: #333333;
font-weight: 500;
}
.required {
color: #E4393C;
margin-left: 6rpx;
font-size: 28rpx;
}
.input-wrapper {
position: relative;
}
.custom-input {
width: 100%;
height: 80rpx;
background: #f8f9fa;
border-radius: 12rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333333;
border: 2rpx solid transparent;
transition: all 0.3s;
}
.custom-input:focus {
background: #ffffff;
border-color: #E4393C;
}
.placeholder {
color: #bbbbbb;
font-size: 26rpx;
}
/* 金额输入特殊样式 */
.amount-group {
position: relative;
}
.amount-wrapper {
display: flex;
align-items: center;
background: #fff5f5;
border-radius: 12rpx;
padding: 0 24rpx;
border: 2rpx solid #ffe5e5;
}
.currency-symbol {
font-size: 32rpx;
color: #E4393C;
font-weight: 600;
margin-right: 12rpx;
}
.amount-input {
flex: 1;
background: transparent !important;
font-size: 32rpx;
font-weight: 600;
color: #E4393C;
padding: 0;
height: 80rpx;
border: none !important;
}
/* 温馨提示卡片 */
.tips-card {
margin: 0 24rpx 20rpx;
background: linear-gradient(135deg, #fff9e6 0%, #fff5dc 100%);
border-radius: 16rpx;
padding: 28rpx 32rpx;
border: 1rpx solid #ffe8b3;
}
.tips-title {
font-size: 28rpx;
font-weight: 600;
color: #ff9900;
margin-bottom: 16rpx;
display: flex;
align-items: center;
}
.tips-text {
font-size: 24rpx;
color: #666666;
line-height: 38rpx;
margin-bottom: 8rpx;
}
.tips-text:last-child {
margin-bottom: 0;
}
/* 底部操作区 */
.bottom-actions {
padding: 0 24rpx;
margin-top: 20rpx;
}
.submit-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #E4393C 0%, #F85959 100%);
border-radius: 48rpx;
font-size: 32rpx;
font-weight: 600;
color: #ffffff;
border: none;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
display: flex;
align-items: center;
justify-content: center;
letter-spacing: 2rpx;
transition: all 0.3s;
}
.submit-btn::after {
border: none;
}
.submit-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.3);
}
.record-link {
display: flex;
align-items: center;
justify-content: center;
margin-top: 28rpx;
padding: 24rpx 0;
font-size: 28rpx;
color: #666666;
}
.record-link text:first-child {
margin-right: 8rpx;
}
.link-arrow {
font-size: 36rpx;
color: #E4393C;
font-weight: 300;
}
================================================
FILE: pages/invoice/list.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
invoiceList: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.invoiceList()
} else {
getApp().loginOK = () => {
this.invoiceList()
}
}
})
},
onShow: function () {
},
async invoiceList() {
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/ygzggg
const res = await WXAPI.invoiceList({
token: wx.getStorageSync('token')
})
wx.hideLoading()
if (res.code == 0) {
this.setData({
invoiceList: res.data.result
})
} else {
this.setData({
invoiceList: []
})
}
},
download(e) {
const _this = this
const file = e.currentTarget.dataset.file
wx.downloadFile({
url: file,
success (res) {
const tempFilePath = res.tempFilePath
console.log(tempFilePath);
wx.openDocument({
filePath: tempFilePath,
showMenu: true,
success: function (res) {
console.log('打开文档成功')
}
})
}
})
},
})
================================================
FILE: pages/invoice/list.json
================================================
{
"navigationBarTitleText": "开票记录"
}
================================================
FILE: pages/invoice/list.wxml
================================================
暂无开票信息
您还没有申请过发票哦~
开票金额
¥{{item.amount}}
发票内容
{{item.consumption}}
接收邮箱
{{item.email}}
申请时间
{{item.dateAdd}}
================================================
FILE: pages/invoice/list.wxss
================================================
/* 京东风格 - 发票记录页面 */
page {
background: linear-gradient(180deg, #f5f5f5 0%, #ffffff 100%);
min-height: 100vh;
}
/* ========== 容器 ========== */
.invoice-container {
padding: 20rpx;
min-height: 100vh;
}
/* ========== 空状态 ========== */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 200rpx 40rpx;
}
.empty-icon {
width: 240rpx;
height: 240rpx;
margin-bottom: 40rpx;
opacity: 0.6;
}
.empty-text {
font-size: 32rpx;
color: #666666;
font-weight: 500;
margin-bottom: 16rpx;
}
.empty-tip {
font-size: 26rpx;
color: #999999;
}
/* ========== 发票列表 ========== */
.invoice-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
/* ========== 发票卡片 ========== */
.invoice-card {
background: #ffffff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.invoice-card:active {
transform: scale(0.98);
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
/* ========== 卡片头部 ========== */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 28rpx 24rpx;
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
border-bottom: 2rpx solid #f5f5f5;
}
.header-left {
display: flex;
align-items: center;
flex: 1;
overflow: hidden;
}
.invoice-icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
flex-shrink: 0;
}
.company-name {
font-size: 32rpx;
font-weight: 600;
color: #333333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ========== 状态标签 ========== */
.status-tag {
padding: 8rpx 20rpx;
border-radius: 20rpx;
font-size: 24rpx;
font-weight: 500;
flex-shrink: 0;
margin-left: 16rpx;
}
.status-0 {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: #ffffff;
box-shadow: 0 4rpx 12rpx rgba(79, 172, 254, 0.3);
}
.status-1 {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: #ffffff;
box-shadow: 0 4rpx 12rpx rgba(245, 87, 108, 0.3);
}
.status-2 {
background: linear-gradient(135deg, #ffd89b 0%, #ff9a56 100%);
color: #ffffff;
box-shadow: 0 4rpx 12rpx rgba(255, 154, 86, 0.3);
}
.status-3 {
background: linear-gradient(135deg, #a8edea 0%, #52d29a 100%);
color: #ffffff;
box-shadow: 0 4rpx 12rpx rgba(82, 210, 154, 0.3);
}
/* ========== 卡片内容 ========== */
.card-content {
padding: 24rpx 28rpx;
}
/* ========== 金额区域 ========== */
.amount-section {
display: flex;
align-items: baseline;
justify-content: space-between;
padding: 24rpx;
background: linear-gradient(135deg, #fff5f5 0%, #ffe8e8 100%);
border-radius: 12rpx;
margin-bottom: 24rpx;
border-left: 6rpx solid #E4393C;
}
.amount-label {
font-size: 26rpx;
color: #666666;
font-weight: 500;
}
.amount-value {
font-size: 44rpx;
font-weight: 700;
color: #E4393C;
letter-spacing: 1rpx;
}
/* ========== 信息区域 ========== */
.info-section {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 16rpx 0;
border-bottom: 1rpx solid #f5f5f5;
}
.info-item:last-child {
border-bottom: none;
}
.info-label {
font-size: 28rpx;
color: #999999;
min-width: 140rpx;
flex-shrink: 0;
}
.info-value {
font-size: 28rpx;
color: #333333;
text-align: right;
flex: 1;
word-break: break-all;
line-height: 1.6;
}
/* ========== 卡片底部(查看按钮区域) ========== */
.card-footer {
padding: 20rpx 28rpx 28rpx;
border-top: 2rpx solid #f5f5f5;
background: #fafafa;
}
/* ========== 查看电子发票按钮(京东风格) ========== */
.view-invoice-btn {
display: flex;
align-items: center;
justify-content: center;
height: 80rpx;
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
border-radius: 40rpx;
box-shadow: 0 6rpx 20rpx rgba(228, 57, 60, 0.35);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.view-invoice-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.6s ease;
}
.view-invoice-btn:active::before {
left: 100%;
}
.view-invoice-btn:active {
transform: scale(0.96);
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.4);
}
.btn-icon {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx;
}
.btn-text {
font-size: 30rpx;
color: #ffffff;
font-weight: 600;
letter-spacing: 2rpx;
}
/* ========== 动画效果 ========== */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.invoice-card {
animation: fadeInUp 0.4s ease-out backwards;
}
.invoice-card:nth-child(1) { animation-delay: 0.1s; }
.invoice-card:nth-child(2) { animation-delay: 0.15s; }
.invoice-card:nth-child(3) { animation-delay: 0.2s; }
.invoice-card:nth-child(4) { animation-delay: 0.25s; }
.invoice-card:nth-child(5) { animation-delay: 0.3s; }
================================================
FILE: pages/live/index.js
================================================
const WXAPI = require('apifm-wxapi')
const APP = getApp()
// fixed首次打开不显示标题的bug
APP.configLoadOK = () => {
wx.setNavigationBarTitle({
})
}
Date.prototype.format = function(format) {
var date = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"S+": this.getMilliseconds()
};
if (/(y+)/i.test(format)) {
format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for (var k in date) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1
? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
}
}
return format;
}
Page({
/**
* 页面的初始数据
*/
data: {
aliveRooms: [],
useFingerprintEmoji: false // 新增
},
onLoad: function (options) {
this.wxaMpLiveRooms()
this.setData({ useFingerprintEmoji: this.shouldUseFingerprintEmoji() })
},
onShow: function () {
},
async wxaMpLiveRooms(){
wx.showLoading({
title: '',
})
const res = await WXAPI.wxaMpLiveRooms()
wx.hideLoading({
success: (res) => {},
})
if (res.code == 0 && res.data.length > 0) {
res.data.forEach(ele => {
if (ele.start_time) {
ele.start_time_str = new Date(ele.start_time*1000).format('yyyy-MM-dd h:m:s')
}
})
this.setData({
aliveRooms: res.data
})
}
},
onPullDownRefresh: function() {
// console.log('ppppp')
this.setData({
curPage: 1
});
this.wxaMpLiveRooms()
wx.stopPullDownRefresh()
},
goLiveRoom(e) {
const roomId = e.currentTarget.dataset.id
const status = e.currentTarget.dataset.status
if (status == 107 || status == 106 || status == 104) {
return
}
wx.navigateTo({
url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${roomId}`
})
},
/* 与 sign 页完全相同的判断逻辑*/
shouldUseFingerprintEmoji() {
try {
const info = wx.getDeviceInfo ? wx.getDeviceInfo() : wx.getSystemInfoSync()
const plat = (info.platform || '').toLowerCase()
const sys = info.system || ''
if (plat === 'android') {
const m = sys.match(/Android\s+(\d+)/)
return m ? (parseInt(m[1]) >= 16) : false
}
if (plat === 'ios') {
const m = sys.match(/iOS\s+(\d+)\.(\d+)/)
if (!m) return false
const major = parseInt(m[1]), minor = parseInt(m[2])
return major > 18 || (major === 18 && minor >= 4)
}
if (plat === 'windows' || plat === 'win32') {
const m = sys.match(/Windows\s+(\d+)\s*H(\d+)/)
if (!m) return false
const build = parseInt(m[1]), h = parseInt(m[2])
return build >= 25 && h >= 2
}
} catch (e) {}
return false
}
})
================================================
FILE: pages/live/index.json
================================================
{
"navigationBarTitleText": "品质直播",
"enablePullDownRefresh": true
}
================================================
FILE: pages/live/index.wxml
================================================
正在直播
即将开播
已结束
已过期
{{item.name}}
{{item.anchor_name}}
{{item.start_time_str}}
已过期
预约提醒
查看回放
进入直播间
暂无直播内容
================================================
FILE: pages/live/index.wxss
================================================
/* 页面容器 */
.live-page {
min-height: 100vh;
background: linear-gradient(180deg, #f8f8f8 0%, #ffffff 100%);
padding-bottom: 32rpx;
}
/* 页面头部 */
.page-header {
padding: 48rpx 32rpx 32rpx;
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
position: relative;
overflow: hidden;
}
.page-header::after {
content: '';
position: absolute;
right: -50rpx;
top: -50rpx;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
}
.header-title {
font-size: 48rpx;
font-weight: 700;
color: #ffffff;
letter-spacing: 2rpx;
position: relative;
z-index: 1;
}
.header-subtitle {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.85);
margin-top: 12rpx;
position: relative;
z-index: 1;
}
/* 直播列表容器 */
.live-container {
padding: 24rpx 24rpx 0;
}
/* 直播卡片 */
.live-card {
background: #ffffff;
border-radius: 20rpx;
margin-bottom: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.live-card:active {
transform: scale(0.98);
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
}
/* 直播封面区域 */
.live-cover {
width: 100%;
height: 400rpx;
position: relative;
overflow: hidden;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.cover-image {
width: 100%;
height: 100%;
display: block;
}
/* 渐变遮罩 */
.cover-mask {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 120rpx;
background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.3) 100%);
pointer-events: none;
}
/* 状态标签 */
.status-badge {
position: absolute;
top: 24rpx;
left: 24rpx;
padding: 12rpx 24rpx;
border-radius: 40rpx;
backdrop-filter: blur(12rpx);
-webkit-backdrop-filter: blur(12rpx);
display: flex;
align-items: center;
gap: 8rpx;
font-size: 24rpx;
font-weight: 600;
z-index: 2;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
/* 正在直播 */
.status-badge.status-101 {
background: rgba(232, 67, 62, 0.95);
color: #ffffff;
}
/* 即将开播 */
.status-badge.status-102 {
background: rgba(255, 148, 62, 0.95);
color: #ffffff;
}
/* 已结束 */
.status-badge.status-103 {
background: rgba(153, 153, 153, 0.95);
color: #ffffff;
}
/* 已过期 */
.status-badge.status-104,
.status-badge.status-106,
.status-badge.status-107 {
background: rgba(204, 204, 204, 0.85);
color: #666666;
}
.status-text {
line-height: 1;
}
/* 直播中圆点动画 */
.status-dot {
width: 12rpx;
height: 12rpx;
background: #ffffff;
border-radius: 50%;
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.6;
transform: scale(1.3);
}
}
/* 直播信息区域 */
.live-info {
padding: 28rpx 28rpx 24rpx;
}
.live-title {
font-size: 32rpx;
font-weight: 600;
color: #333333;
line-height: 1.4;
margin-bottom: 20rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
min-height: 90rpx;
}
/* 元信息 */
.live-meta {
display: flex;
flex-direction: column;
gap: 12rpx;
margin-bottom: 24rpx;
}
.meta-item {
display: flex;
align-items: center;
gap: 8rpx;
}
.meta-text {
font-size: 26rpx;
color: #666666;
line-height: 1.2;
}
/* 操作按钮区域 */
.live-action {
padding-top: 16rpx;
border-top: 1rpx solid #f0f0f0;
}
.action-btn {
height: 80rpx;
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
font-size: 28rpx;
font-weight: 600;
letter-spacing: 1rpx;
position: relative;
transition: all 0.3s ease;
}
/* 正在直播按钮 */
.btn-live {
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
color: #ffffff;
box-shadow: 0 8rpx 24rpx rgba(232, 67, 62, 0.3);
}
.btn-live:active {
transform: scale(0.96);
}
/* 直播脉冲动画 */
.live-pulse {
width: 16rpx;
height: 16rpx;
background: #ffffff;
border-radius: 50%;
position: relative;
animation: livePulse 2s ease-in-out infinite;
}
.live-pulse::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
background: #ffffff;
border-radius: 50%;
animation: ripple 2s ease-out infinite;
}
@keyframes livePulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.7;
}
}
@keyframes ripple {
0% {
width: 16rpx;
height: 16rpx;
opacity: 0.8;
}
100% {
width: 40rpx;
height: 40rpx;
opacity: 0;
}
}
/* 即将开播按钮 */
.btn-upcoming {
background: linear-gradient(135deg, #FF943E 0%, #FF7F39 100%);
color: #ffffff;
box-shadow: 0 8rpx 24rpx rgba(255, 148, 62, 0.25);
}
/* 已结束按钮 */
.btn-ended {
background: linear-gradient(135deg, #999999 0%, #777777 100%);
color: #ffffff;
box-shadow: 0 6rpx 20rpx rgba(153, 153, 153, 0.2);
}
/* 已过期按钮 */
.btn-disabled {
background: #f5f5f5;
color: #cccccc;
border: 1rpx solid #e5e5e5;
}
/* 空状态 */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-image {
width: 300rpx;
height: 300rpx;
opacity: 0.4;
margin-bottom: 32rpx;
}
.empty-text {
font-size: 28rpx;
color: #999999;
}
/* 响应式优化 */
@media (prefers-color-scheme: dark) {
.live-page {
background: #1a1a1a;
}
.live-card {
background: #2a2a2a;
}
.live-title {
color: #e5e5e5;
}
.meta-text {
color: #999999;
}
}
/* 滚动条隐藏 */
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
/* 以下为旧样式保留(备用) */
.shops-container {
display: flex;
justify-content: space-between;
align-items: center;
margin: 16rpx;
}
.shops-container .l {
display: flex;
align-items: center;
}
.shops-container .l text {
color: #666;
margin-left: 16rpx;
}
.shops-container .l image {
width: 40rpx;
height: 40rpx;
}
.shops-container .r {
display: flex;
align-items: center;
}
.shops-container .r text {
color: #666;
}
.shops-container .r image {
width: 40rpx;
height: 40rpx;
}
.search {
position: absolute;
top: 32rpx;
left: 25rpx;
width: 700rpx;
height: 66rpx;
display: block;
box-sizing: border-box;
}
.search input {
display: block;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
border: 1rpx solid #e3e3e3;
width: 700rpx;
height: 66rpx;
border-radius: 30rpx;
padding-left: 32rpx;
}
.search image {
width: 35rpx;
height: 35rpx;
position: absolute;
top: 16rpx;
right: 32rpx;
z-index: 99;
}
.goodsDynamic {
position: absolute;
top: 110rpx;
left: 25rpx;
width: 650rpx;
height:66rpx;
line-height:66rpx;
background: rgba(0, 0, 0, 0.6);
color: #fff;
padding: 0 16rpx;
border-radius: 32rpx;
font-size: 24rpx;
}
.goodsDynamic .swiper2 {
width: 100%;
height: 100%;
}
.goodsDynamic-item {
width: 100%;
display: flex;
align-items: center;
}
.goodsDynamic-item image {
width: 32rpx;
height: 32rpx;
border-radius: 50%;
flex-shrink: 0;
}
.goodsDynamic-item text {
margin-left: 8rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.notice-box {
display: flex;
box-sizing: border-box;
width: 100vw;
height: 88rpx;
line-height: 88rpx;
justify-content: space-between;
align-items: center;
padding-right: 32rpx;
border-bottom: 1rpx solid #efeff4;
}
.notice{
display: flex;
justify-content: space-between;
align-items: center;
width: 600rpx;
}
.notice_icon {
margin-left:20rpx;
width:30rpx;
height:30rpx;
}
.notice_swiper{
height: 88rpx;
width: 600rpx;
}
.notice_itemr {
padding-left: 16rpx;
font-size: 24rpx;
overflow: hidden;
color: #e64340;
}
.notice-box .more {
color: #666;
font-size: 24rpx;
}
.container {
background-color: #fff;
min-height: 100%;
display: block;
}
.category-box {
background-color: #fff;
display: flex;
flex-wrap: wrap;
}
.category-list{
flex:1;
margin-top:20rpx;
text-align: center;
display: inline-block;
overflow: hidden;
}
.category-column{
width:100%;
margin-top:20rpx;
overflow: hidden;
}
.category-imgbox{
width:90rpx;
height:90rpx;
}
.category-title{
font-size: 24rpx;
text-align:center;
margin-top:10rpx;
}
.swiper-container{
width: 750rpx;
height: 375rpx;
position: relative;
}
.swiper-container .swiper1 {
width: 750rpx;
height: 375rpx;
}
.swiper-container .swiper1 image {
width: 750rpx;
height: 375rpx;
}
.type-item-on{
color:#e64340;
border-bottom: 1rpx solid #e64340;
}
.goods-container{
display: flex;
justify-content: space-between;
flex-wrap:wrap;
box-sizing: content-box;
padding: 24rpx;
background-color: #F2f2f2;
}
.goods-box{
width: 339rpx;
height: 472rpx;
background-color: #fff;
overflow: hidden;
margin-bottom: 24rpx;
border-radius:5px;
}
.goods-box .img-box{
width: 339rpx;
height: 339rpx;
overflow: hidden;
}
.goods-box .img-box image{
width: 339rpx;
height: 339rpx;
}
.goods-box .goods-title{
width: 280rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 24rpx;
padding: 24rpx 0 0rpx 0;
color:#000;
margin-left: 24rpx;
}
.goods-box .goods-price{
width: 280rpx;
overflow: hidden;
font-size: 24rpx;
padding: 24rpx 0;
color:#e64340;
margin-left: 24rpx;
}
.pos-fiexd{
position: fixed;
top: 0;
left: 0;
}
.coupons{
margin-top:10rpx;
width: 100%;
height: 180rpx;
overflow: hidden;
}
.coupons-scroll{
white-space: nowrap;
height: 180rpx;
width: 100%;
background-color: #fff;
}
.coupons-item{
width:300rpx;
height: 180rpx;
margin: 10rpx;
padding-top: 20rpx;
padding-left: 15rpx;
background-color: #f1a83b;
box-sizing: content-box;
font-size: 20rpx;
line-height: 35rpx;
overflow: hidden;
color: #fff;
display: inline-block;
}
.coupons-float {
position: fixed;
right:15rpx;
bottom:80rpx;
text-align: center;
}
.coupons-float image {
width:110rpx;
height:110rpx;
margin-top: 10rpx;
}
.tuan {
width:750rpx;
background-color: #F2f2f2;
padding-top:10rpx;
}
.tuan-item {
width:720rpx;
margin: auto;
margin-top: 20rpx;
background-color: #FFF;
position: relative;
}
.tuan-goods-pic {
width:720rpx;
height: 250rpx;
overflow: hidden;
}
.tuan-goods-pic image {
width:720rpx;
}
.tuan-title {
margin-top: 20rpx;
margin-left: 20rpx;
font-size:30rpx;
font-weight: 400;
}
.tuan-profile {
margin-left: 20rpx;
font-size:28rpx;
color:#999;
}
.tuan-price {
margin-left: 20rpx;
}
.tuan-price .now {
font-size:36rpx;
color:#e64340;
}
.tuan-price .original {
margin-left: 20rpx;
font-size:26rpx;
color:#999;
text-decoration:line-through;
}
.tuan-btn {
position: absolute;
right:30rpx;
bottom: 10rpx;
}
.category-goods-title {
width: 100vw;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8rpx;
border-bottom: 1rpx solid #efeff4;
}
.category-goods-title .more {
color: #666;
font-size: 24rpx;
margin-right: 32rpx;
}
.progress {
width: 686rpx;
padding: 0 32rpx;
margin-bottom: 16rpx;
}
/* 旧的秒杀样式(保留作为备用) */
.miaosha-container {
padding: 0;
}
.miaosha-goods-list {
margin: 20rpx;
background: #f6f6f6;
border-radius: 16rpx;
display: flex;
padding: 20rpx;
}
.miaosha-goods-list .image {
width: 260rpx;
height: 260rpx;
flex-shrink: 0;
border-radius: 16rpx;
}
.miaosha-goods-list .r {
margin-left: 32rpx;
}
.miaosha-goods-list .r .goods-title {
color: #333;
font-size: 28rpx;
}
.miaosha-goods-list .r .label {
color: #e64340;
font-size: 24rpx;
display: flex;
align-items: flex-start;
margin-top: 8rpx;
}
.miaosha-goods-list .r .label text {
margin-left: 8rpx;
}
.miaosha-goods-list .count-down {
background: #e64340;
padding: 8rpx 16rpx;
border-radius: 16rpx;
margin-top: 12rpx;
}
.van-count-down {
color: #fff !important;
font-size: 26rpx !important;
text-align: center;
}
.miaosha-price-btn {
padding-top: 32rpx;
}
.miaosha-price-btn .price {
color: #e64340;
font-size: 40rpx;
margin-top: 12rpx;
}
.miaosha-price-btn .price text {
color: #666666;
font-size: 26rpx;
text-decoration:line-through;
}
.empty-emoji {
display: block; /* 同 image 默认 block */
width: 200rpx; /* 与原图默认尺寸一致,若原图不是 200rpx 请按实际改 */
height: 200rpx;
margin: 0 auto;
font-size: 160rpx; /* 视觉上填满容器,可微调 */
line-height: 200rpx;
text-align: center;
cursor: pointer;
}
================================================
FILE: pages/login/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad(options) {
},
onShow() {
},
xieyiChange(e) {
this.setData({
checked: e.detail,
})
},
goxieyi(e) {
wx.navigateTo({
url: '/pages/about/index?key=' + e.currentTarget.dataset.key,
})
},
showModal2() {
wx.showModal({
title: '温馨提示',
content: '已经阅读并同意《用户协议》、《隐私协议》',
cancelText: '不同意',
confirmText: '同意',
success: res => {
if (res.confirm) {
this.setData({
checked: true
})
}
}
})
},
showModal(action) {
wx.showModal({
title: '温馨提示',
content: '已经阅读并同意《用户协议》、《隐私协议》',
cancelText: '不同意',
confirmText: '同意',
success: res => {
if (res.confirm) {
this.setData({
checked: true
})
if (action == 'loginOne') {
this.loginOne()
}
}
}
})
},
async loginOne() {
if (!this.data.checked) {
this.showModal('loginOne')
return
}
const res = await AUTH.login20241025()
if (res.code == 10000) {
// 用户不存在
wx.showModal({
content: '您还未注册,请使用《手机号安全登陆》方式登陆',
showCancel: false
})
return
}
if (res.code != 0) {
// 登录错误
return
}
wx.reLaunch({
url: '/pages/index/index',
})
},
async getPhoneNumber(e) {
if (e.detail.errMsg.indexOf('privacy permission is not authorized') != -1) {
wx.showModal({
content: '请阅读并同意隐私条款以后才能继续本操作',
confirmText: '阅读协议',
cancelText: '取消',
success (res) {
if (res.confirm) {
wx.requirePrivacyAuthorize() // 弹出用户隐私授权框
}
}
})
return
}
if (!e.detail.errMsg) {
wx.showModal({
content: 'getPhoneNumber异常',
showCancel: false
})
return
}
if (e.detail.errMsg == "getPhoneNumber:fail user deny") {
return
}
if (!e.detail.errMsg || e.detail.errMsg != "getPhoneNumber:ok") {
wx.showModal({
content: e.detail.errMsg,
showCancel: false
})
return;
}
this._getPhoneNumber(e)
},
async _getPhoneNumber(e) {
let referrer = '' // 推荐人
let referrer_storge = wx.getStorageSync('referrer');
if (referrer_storge) {
referrer = referrer_storge;
}
wx.showLoading({
title: '',
})
const code = await AUTH.wxaCode()
// https://www.yuque.com/apifm/nu0f75/yiglsl
const res = await WXAPI.loginWxaMobileV3({
code,
codeMobile: e.detail.code,
autoReg: true,
referrer
})
wx.hideLoading()
if (res.code != 0) {
// 登录错误
return
}
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
wx.setStorageSync('openid', res.data.openid)
wx.setStorageSync('mobile', res.data.mobile)
wx.reLaunch({
url: '/pages/index/index',
})
},
})
================================================
FILE: pages/login/index.json
================================================
{
"usingComponents": {},
"navigationBarTitleText": "账户登录"
}
================================================
FILE: pages/login/index.wxml
================================================
本次操作需要先登陆
手机号安全登录
手机号安全登录
一键登录
阅读并同意
《用户协议》、
《隐私协议》
================================================
FILE: pages/login/index.wxss
================================================
page {
background: rgb(236, 236, 236);
}
.box {
margin: 32rpx;
background: #fff;
border-radius: 24rpx;
padding-bottom: 64rpx;
}
.title {
padding: 88rpx 0 56rpx 0;
text-align: center;
}
.btn {
box-sizing: border-box;
margin: 32rpx 125rpx 0 125rpx;
}
.van-button--default {
background: #000 !important;
color: #fff !important;
padding: 16rpx !important;
border-radius: 64rpx;
}
.xieyi {
padding: 0 32rpx;
font-size: 24rpx;
color: #000;
display: flex;
align-items: center;
}
================================================
FILE: pages/maidan/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
payType: 'wxpay'
},
onLoad(e) {
this.payBillDiscounts()
// 读取系统参数
this.readConfigVal()
getApp().configLoadOK = () => {
this.readConfigVal()
}
},
onShow () {
AUTH.checkHasLogined().then(isLogined => {
if (!isLogined) {
AUTH.login(this)
} else {
this.userAmount()
}
})
},
readConfigVal() {
this.setData({
balance_pay_pwd: wx.getStorageSync('balance_pay_pwd'),
needBindMobile: wx.getStorageSync('needBindMobile'),
})
},
async payBillDiscounts() {
const res = await WXAPI.payBillDiscounts()
if (res.code === 0) {
this.setData({
rechargeSendRules: res.data
})
}
},
async userAmount() {
const res = await WXAPI.userAmount(wx.getStorageSync('token'))
if (res.code === 0) {
this.setData({
balance: res.data.balance
})
}
},
async bindSave() {
const amount = this.data.amount;
if (!amount) {
wx.showToast({
title: '请填写正确的消费金额',
icon: 'none'
})
return
}
if (this.data.payType == 'balance') {
if (this.data.balance_pay_pwd == '1' && !this.data.pwd) {
wx.showToast({
title: '请输入交易密码',
icon: 'none'
})
return
}
}
// 判断是否需要绑定手机号码
// https://www.yuque.com/apifm/nu0f75/zgf8pu
if (this.data.needBindMobile == 1) {
const resUserDetail = await WXAPI.userDetail(wx.getStorageSync('token'))
if (resUserDetail.code == 0 && !resUserDetail.data.base.mobile) {
this.setData({
bindMobileShow: true
})
return
}
}
const res = await WXAPI.payBillV2({
token: wx.getStorageSync('token'),
money: amount,
calculate: true
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
const amountReal = res.data.realMoney
const _msg = `您本次消费${amount},优惠后只需支付${amountReal}`
wx.showModal({
title: '请确认消费金额',
content: _msg,
confirmText: "确认支付",
cancelText: "取消支付",
success: res => {
if (res.confirm) {
this.goPay(amount, amountReal)
}
}
});
},
async goPay(amount, wxpayAmount){
if (this.data.payType == 'balance') {
const res = await WXAPI.payBillV2({
token: wx.getStorageSync('token'),
money: amount,
pwd: this.data.pwd
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showModal({
title: '成功',
content: '买单成功,欢迎下次光临!',
showCancel: false
})
} else {
this.setData({
money: wxpayAmount,
paymentShow: true,
nextAction: {
type: 4,
uid: wx.getStorageSync('uid'),
money: amount
}
})
}
},
payTypeChange(event) {
this.setData({
payType: event.detail,
});
},
payTypeClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
payType: name,
});
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false
})
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/asset/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/maidan/index.json
================================================
{
"navigationBarTitleText": "优惠买单"
}
================================================
FILE: pages/maidan/index.wxml
================================================
确认支付
================================================
FILE: pages/maidan/index.wxss
================================================
/* 京东风格 - 页面整体样式 */
page {
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
min-height: 100vh;
padding: 32rpx 0 40rpx 0;
box-sizing: border-box;
width: 100%;
overflow-x: hidden;
}
/* 输入框容器美化 */
.van-cell-group {
margin: 24rpx !important;
border-radius: 20rpx !important;
overflow: hidden !important;
}
/* 标题美化 */
.van-cell-group__title {
padding: 32rpx 32rpx 24rpx 32rpx !important;
font-size: 32rpx !important;
font-weight: 600 !important;
color: #333 !important;
position: relative;
}
.van-cell-group__title::before {
content: '';
position: absolute;
left: 16rpx;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 32rpx;
background: linear-gradient(180deg, #E1251B 0%, #FF6B6B 100%);
border-radius: 3rpx;
}
/* 让输入框标题和内容分成两行显示 */
.van-field .van-cell {
flex-direction: column !important;
align-items: flex-start !important;
padding: 0 !important;
}
.van-field .van-cell__title {
width: 100% !important;
margin-bottom: 20rpx !important;
font-size: 28rpx !important;
color: #666 !important;
font-weight: 400 !important;
}
.van-field .van-cell__value {
width: 100% !important;
}
/* 输入框单元格美化 */
.van-cell {
padding: 28rpx 32rpx !important;
font-size: 28rpx !important;
transition: all 0.3s ease;
box-sizing: border-box !important;
width: 100% !important;
}
.van-cell::after {
border-bottom: 1rpx solid #f5f5f5 !important;
}
.van-cell:last-child::after {
border-bottom: none !important;
}
/* 输入框标签 */
.van-cell__title {
font-size: 30rpx !important;
color: #333 !important;
font-weight: 500 !important;
}
/* 输入框内容 */
.van-field__control {
font-size: 40rpx !important;
color: #E1251B !important;
font-weight: 600 !important;
width: 100% !important;
}
.van-field__control::-webkit-input-placeholder {
color: #bbb !important;
font-weight: 400 !important;
font-size: 28rpx !important;
}
/* 金额输入特殊样式 - 取消右对齐,因为改成两行了 */
.van-field__control[type="digit"] {
text-align: left !important;
}
/* 余额显示美化 */
.van-cell__label {
color: #E1251B !important;
font-size: 26rpx !important;
margin-top: 8rpx !important;
font-weight: 500 !important;
}
/* 单选框美化 */
.van-radio__icon--checked {
background-color: #E1251B !important;
border-color: #E1251B !important;
}
.van-radio__icon {
border: 2rpx solid #ddd !important;
width: 40rpx !important;
height: 40rpx !important;
}
/* 支付方式容器 */
.van-radio-group {
width: 100%;
box-sizing: border-box;
}
/* 支付方式标题样式 */
.van-radio-group .van-cell-group__title {
background: linear-gradient(135deg, #fff 0%, #fafafa 100%);
}
/* 确认支付按钮容器 */
.btn {
margin: 24rpx 24rpx 0 24rpx;
padding: 0;
box-sizing: border-box;
}
/* 支付按钮美化 - 京东红色主题 */
.van-button--primary {
background: linear-gradient(135deg, #E1251B 0%, #FF4655 100%) !important;
border: none !important;
border-radius: 50rpx !important;
height: 96rpx !important;
font-size: 36rpx !important;
font-weight: 600 !important;
box-shadow: 0 8rpx 24rpx rgba(225, 37, 27, 0.35) !important;
transition: all 0.3s ease !important;
letter-spacing: 4rpx !important;
position: relative;
overflow: hidden;
}
/* 按钮按下效果 */
.van-button--primary:active {
transform: translateY(4rpx);
box-shadow: 0 4rpx 16rpx rgba(225, 37, 27, 0.25) !important;
}
/* 按钮光泽效果 */
.van-button--primary::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.15), transparent);
transform: rotate(45deg);
animation: buttonShine 3s infinite;
}
@keyframes buttonShine {
0% {
transform: translateX(-100%) translateY(-100%) rotate(45deg);
}
50%, 100% {
transform: translateX(100%) translateY(100%) rotate(45deg);
}
}
/* 输入框聚焦效果 */
.van-field__control:focus {
background-color: #fffbfb !important;
}
/* 清除按钮美化 */
.van-field__clear {
color: #E1251B !important;
}
/* 付款方式选项卡片效果 */
.van-radio-group .van-cell {
position: relative;
transition: all 0.3s ease;
}
.van-radio-group .van-cell:active {
background-color: #fff5f5 !important;
}
/* 已选中的支付方式高亮 */
.van-cell--clickable:active {
background-color: #fffbfb !important;
}
/* 分隔线美化 */
.van-hairline--top-bottom::after {
border-color: #f0f0f0 !important;
}
/* 图标增强 */
.van-icon {
transition: all 0.3s ease;
}
/* 空状态美化 */
.van-empty {
padding: 80rpx 0;
}
================================================
FILE: pages/my/feedback.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
data: {
autosize: {
minHeight: 100
},
day: dayjs().format('YYYY-MM-DD')
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
},
onShow: function() {
this.checkTodayComments()
},
async checkTodayComments() {
// 判断一天只能留言5次
const res = await WXAPI.jsonList({
token: wx.getStorageSync('token'),
type: 'feedback_times_' + this.data.day
})
if (res.code === 0) {
this.setData({
feedbackTimes: res.data[0]
})
}
},
async bindSave() {
const comment_subscribe_ids = wx.getStorageSync('comment_subscribe_ids')
if (comment_subscribe_ids) {
wx.requestSubscribeMessage({
tmplIds: comment_subscribe_ids.split(','),
success(res) {
console.log(res)
},
fail(err) {
console.error(err)
},
complete: (res) => {
this._bindSave()
},
})
} else {
this._bindSave()
}
},
async _bindSave() {
if (!this.data.name) {
wx.showToast({
title: '请填写您的姓名',
icon: 'none',
})
return
}
if (!this.data.content) {
wx.showToast({
title: '请填写反馈信息',
icon: 'none',
})
return
}
const extJsonStr = {}
extJsonStr['姓名'] = this.data.name
extJsonStr['联系电话'] = this.data.mobile
extJsonStr['微信'] = this.data.wx
// 批量上传附件
if (this.data.picsList) {
for (let index = 0; index < this.data.picsList.length; index++) {
const pic = this.data.picsList[index];
const res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), pic.url)
if (res.code == 0) {
extJsonStr['file' + index] = res.data.url
}
}
}
const res = await WXAPI.addComment({
token: wx.getStorageSync('token'),
type: 1,
extJsonStr: JSON.stringify(extJsonStr),
content: this.data.content
})
if (res.code == 0) {
// 提交次数 + 1
let feedbackTimes = this.data.feedbackTimes
if (!feedbackTimes) {
feedbackTimes = {
id: '',
refId: 0,
content: '{}'
}
}
await WXAPI.jsonSet({
token: wx.getStorageSync('token'),
id: feedbackTimes.id,
type: 'feedback_times_' + this.data.day,
refId: feedbackTimes.refId + 1,
content: feedbackTimes.content
})
await this.checkTodayComments()
wx.showToast({
title: '提交成功',
})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
afterPicRead(e) {
let picsList = this.data.picsList
if (!picsList) {
picsList = []
}
picsList = picsList.concat(e.detail.file)
this.setData({
picsList
})
},
afterPicDel(e) {
let picsList = this.data.picsList
picsList.splice(e.detail.index, 1)
this.setData({
picsList
})
}
})
================================================
FILE: pages/my/feedback.json
================================================
{
"navigationBarTitleText": "意见反馈"
}
================================================
FILE: pages/my/feedback.wxml
================================================
📞
联系方式
✍️
反馈内容
📷
添加图片或视频
(选填)
提交反馈
温馨提示:
• 我们将在1-3个工作日内处理您的反馈
• 如需快速联系,请留下您的手机号
• 每天最多可提交5次反馈
================================================
FILE: pages/my/feedback.wxss
================================================
/* 京东风格 - 意见反馈页面 */
page {
background: #f4f4f4;
}
.feedback-container {
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 页面头部 */
.feedback-header {
background: linear-gradient(135deg, #E93323 0%, #E4393C 100%);
padding: 60rpx 40rpx 50rpx;
color: #fff;
position: relative;
overflow: hidden;
}
.feedback-header::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.header-title {
font-size: 48rpx;
font-weight: bold;
margin-bottom: 16rpx;
position: relative;
z-index: 1;
}
.header-subtitle {
font-size: 26rpx;
opacity: 0.9;
position: relative;
z-index: 1;
}
/* 限制提示 */
.limit-tips {
margin-top: 40rpx;
padding: 0 40rpx;
}
/* 反馈卡片 */
.feedback-card {
background: #fff;
margin: 24rpx 30rpx;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(233, 51, 35, 0.08);
}
.card-title {
display: flex;
align-items: center;
padding: 32rpx 30rpx 24rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.title-icon {
font-size: 36rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
flex: 1;
}
.title-tip {
font-size: 24rpx;
color: #999;
margin-left: 8rpx;
}
.card-content {
padding: 8rpx 0 16rpx;
}
.upload-content {
padding: 16rpx 30rpx 24rpx;
}
/* 提交按钮 */
.submit-wrapper {
padding: 40rpx 30rpx 20rpx;
}
.submit-btn {
background: linear-gradient(90deg, #E93323 0%, #E4393C 100%);
height: 96rpx;
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(233, 51, 35, 0.3);
transition: all 0.3s;
}
.submit-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(233, 51, 35, 0.2);
}
.submit-text {
font-size: 34rpx;
font-weight: 600;
color: #fff;
letter-spacing: 2rpx;
}
/* 温馨提示 */
.tips-box {
background: #fff;
margin: 24rpx 30rpx;
padding: 32rpx;
border-radius: 16rpx;
border-left: 6rpx solid #E93323;
}
.tips-title {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
}
.tips-item {
font-size: 26rpx;
color: #666;
line-height: 44rpx;
padding-left: 8rpx;
}
/* 优化 van-field 样式 */
.feedback-card /deep/ .van-cell {
padding: 20rpx 30rpx;
font-size: 28rpx;
}
.feedback-card /deep/ .van-field__label {
color: #333;
font-weight: 500;
width: 140rpx;
}
.feedback-card /deep/ .van-field__control {
color: #333;
}
.feedback-card /deep/ .van-field__placeholder {
color: #c8c9cc;
}
/* 文本域特殊样式 */
.feedback-card /deep/ .van-field__control--textarea {
min-height: 200rpx;
padding: 24rpx 30rpx;
font-size: 28rpx;
line-height: 44rpx;
}
/* 上传组件优化 */
.upload-content /deep/ .van-uploader__wrapper {
margin: -8rpx;
}
.upload-content /deep/ .van-uploader__preview,
.upload-content /deep/ .van-uploader__upload {
margin: 8rpx;
width: 160rpx;
height: 160rpx;
border-radius: 12rpx;
}
.upload-content /deep/ .van-uploader__upload {
border: 2rpx dashed #E4393C;
background: #fff5f5;
}
.upload-content /deep/ .van-uploader__upload-icon {
color: #E4393C;
font-size: 48rpx;
}
.upload-content /deep/ .van-uploader__upload-text {
color: #E4393C;
font-size: 24rpx;
margin-top: 8rpx;
}
/* 响应式优化 */
@media (max-width: 375px) {
.header-title {
font-size: 44rpx;
}
.feedback-card {
margin: 20rpx 24rpx;
}
}
================================================
FILE: pages/my/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const TOOLS = require('../../utils/tools.js')
const CONFIG = require('../../config.js')
Page({
data: {
balance:0.00,
freeze:0,
score:0,
growth:0,
score_sign_continuous:0,
rechargeOpen: false, // 是否开启充值[预存]功能
// 用户订单统计数据
count_id_no_confirm: 0,
count_id_no_pay: 0,
count_id_no_reputation: 0,
count_id_no_transfer: 0,
nick: undefined,
cardsExpanded: false, // 会员卡展开状态
// 会员等级配置(根据不同等级显示不同图标和样式)
vipLevelConfig: {
1: { icon: '🥇', name: '黄金会员' },
2: { icon: '💎', name: '白金会员' },
3: { icon: '💠', name: '钻石会员' },
4: { icon: '👑', name: '至尊会员' },
5: { icon: '🔱', name: '皇冠会员' }
}
},
onLoad() {
this.readConfigVal()
// 补偿写法
getApp().configLoadOK = () => {
this.readConfigVal()
}
},
onShow() {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.getUserApiInfo();
this.getUserAmount();
this.orderStatistics();
this.cardMyList();
TOOLS.showTabBarBadge();
} else {
getApp().loginOK = () => {
this.getUserApiInfo();
this.getUserAmount();
this.orderStatistics();
this.cardMyList();
TOOLS.showTabBarBadge();
}
}
})
},
readConfigVal() {
this.setData({
order_hx_uids: wx.getStorageSync('order_hx_uids'),
cps_open: wx.getStorageSync('cps_open'),
recycle_open: wx.getStorageSync('recycle_open'),
show_3_seller: wx.getStorageSync('show_3_seller'),
show_quan_exchange_score: wx.getStorageSync('show_quan_exchange_score'),
show_score_exchange_growth: wx.getStorageSync('show_score_exchange_growth'),
show_score_sign: wx.getStorageSync('show_score_sign'),
fx_type: wx.getStorageSync('fx_type'),
invoice_open: wx.getStorageSync('invoice_open'),
customerServiceType: CONFIG.customerServiceType
})
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
let _data = {}
_data.apiUserInfoMap = res.data
if (res.data.base.mobile) {
_data.userMobile = res.data.base.mobile
}
_data.nick = res.data.base.nick
if (this.data.order_hx_uids && this.data.order_hx_uids.indexOf(res.data.base.id) != -1) {
_data.canHX = true // 具有扫码核销的权限
}
if (res.data.peisongMember && res.data.peisongMember.status == 1) {
_data.memberChecked = false
} else {
_data.memberChecked = true
}
this.setData(_data);
}
},
async memberCheckedChange() {
const res = await WXAPI.peisongMemberChangeWorkStatus(wx.getStorageSync('token'))
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
this.getUserApiInfo()
}
},
getUserAmount: function () {
var that = this;
WXAPI.userAmount(wx.getStorageSync('token')).then(function (res) {
if (res.code == 0) {
that.setData({
balance: res.data.balance.toFixed(2),
freeze: res.data.freeze.toFixed(2),
score: res.data.score,
growth: res.data.growth
});
}
})
},
handleOrderCount: function (count) {
return count > 99 ? '99+' : count;
},
orderStatistics: function () {
WXAPI.orderStatistics(wx.getStorageSync('token')).then((res) => {
if (res.code == 0) {
const {
count_id_no_confirm,
count_id_no_pay,
count_id_no_reputation,
count_id_no_transfer,
} = res.data || {}
this.setData({
count_id_no_confirm: this.handleOrderCount(count_id_no_confirm),
count_id_no_pay: this.handleOrderCount(count_id_no_pay),
count_id_no_reputation: this.handleOrderCount(count_id_no_reputation),
count_id_no_transfer: this.handleOrderCount(count_id_no_transfer),
})
}
})
},
goAsset: function () {
wx.navigateTo({
url: "/pages/asset/index"
})
},
goScore: function () {
wx.navigateTo({
url: "/pages/score/index"
})
},
goOrder: function (e) {
wx.navigateTo({
url: "/pages/order-list/index?type=" + e.currentTarget.dataset.type
})
},
scanOrderCode(){
wx.scanCode({
success(res) {
console.log('res', res);
if (res.scanType == 'WX_CODE' && res.path) {
wx.navigateTo({
url: '/' + res.path,
})
} else {
wx.navigateTo({
url: '/pages/order-details/scan-result?hxNumber=' + res.result,
})
}
},
fail(err) {
console.error(err)
wx.showToast({
title: err.errMsg,
icon: 'none'
})
}
})
},
gogrowth() {
wx.navigateTo({
url: '/pages/score/growth',
})
},
async cardMyList() {
const res = await WXAPI.cardMyList(wx.getStorageSync('token'))
if (res.code == 0) {
const myCards = res.data.filter(ele => { return ele.status == 0 })
if (myCards.length > 0) {
this.setData({
myCards: res.data
})
}
}
},
editNick() {
this.setData({
nickShow: true
})
},
async _editNick() {
if (!this.data.nick) {
wx.showToast({
title: '请填写昵称',
icon: 'none'
})
return
}
const postData = {
token: wx.getStorageSync('token'),
nick: this.data.nick,
}
// https://www.yuque.com/apifm/nu0f75/ykr2zr
const res = await WXAPI.modifyUserInfoV2(postData)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '设置成功',
})
this.hideNickModal()
this.getUserApiInfo()
},
async onChooseAvatar(e) {
console.log(e);
const avatarUrl = e.detail.avatarUrl
let res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), avatarUrl)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
// https://www.yuque.com/apifm/nu0f75/ykr2zr
res = await WXAPI.modifyUserInfoV2({
token: wx.getStorageSync('token'),
avatarUrl: res.data.url,
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '设置成功',
})
this.getUserApiInfo()
},
goUserCode() {
wx.navigateTo({
url: '/pages/my/user-code',
})
},
customerService() {
wx.openCustomerServiceChat({
extInfo: {url: wx.getStorageSync('customerServiceChatUrl')},
corpId: wx.getStorageSync('customerServiceChatCorpId'),
success: res => {},
fail: err => {
console.error(err)
}
})
},
copyUid() {
wx.setClipboardData({
data: this.data.apiUserInfoMap.base.id + '',
})
},
login() {
wx.navigateTo({
url: '/pages/login/index',
})
},
hideNickModal() {
this.setData({
nickShow: false
})
},
toggleCards() {
this.setData({
cardsExpanded: !this.data.cardsExpanded
})
},
})
================================================
FILE: pages/my/index.json
================================================
{
"navigationBarTitleText": "会员中心"
}
================================================
FILE: pages/my/index.wxml
================================================
余额(元)
¥
{{balance}}
冻结(元)
¥
{{freeze}}
{{score}}
积分
{{growth}}
成长值
我的会员卡
💳
剩余次数
{{ item.amount }}
{{ cardsExpanded ? '收起' : '查看更多(' + (myCards.length - 1) + ')' }}
›
💰
{{count_id_no_pay}}
待付款
📦
{{count_id_no_transfer}}
待发货
🚚
{{count_id_no_confirm}}
待收货
⭐
{{count_id_no_reputation}}
待评价
🛠
售后
常用功能
📋
历史购买
📷
扫码核销
💳
优惠买单
📊
资金明细
🧾
申请发票
📄
开票记录
🎫
优惠券
📅
签到赚积分
配送员工作台
三级分销
其他功能
================================================
FILE: pages/my/index.wxss
================================================
/* 全局样式 */
page {
background: #f5f5f5;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
}
.page-container {
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 头部用户信息区域 */
.header-section {
background: #fff;
padding: 0rpx 32rpx 32rpx;
margin-bottom: 20rpx;
}
/* 未登录状态 */
.login-container {
display: flex;
flex-direction: column;
align-items: center;
padding: 60rpx 0;
}
.login-tips {
font-size: 32rpx;
margin-bottom: 32rpx;
color: #333;
font-weight: 500;
}
.login-btn {
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
color: #fff;
padding: 28rpx 88rpx;
border-radius: 48rpx;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
}
/* 已登录用户信息 */
.user-info-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 0;
}
.user-main {
display: flex;
align-items: center;
flex: 1;
}
.avatar-btn {
background: transparent;
border: none;
padding: 0;
margin: 0;
line-height: 1;
position: relative;
}
.avatar {
width: 128rpx;
height: 128rpx;
border-radius: 50%;
display: block;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.avatar-border {
position: absolute;
top: -6rpx;
left: -6rpx;
right: -6rpx;
bottom: -6rpx;
border-radius: 50%;
border: 4rpx solid transparent;
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
pointer-events: none;
opacity: 0.8;
}
.user-detail {
margin-left: 24rpx;
flex: 1;
}
.nickname-row {
display: flex;
align-items: center;
margin-bottom: 12rpx;
}
.nickname {
font-size: 36rpx;
font-weight: 700;
color: #333;
letter-spacing: 0.5rpx;
}
.user-id {
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.qr-code-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0;
}
.qr-icon-box {
width: 88rpx;
height: 88rpx;
background: linear-gradient(135deg, #FFF5F5 0%, #FFE8E8 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8rpx;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.12);
}
.qr-text {
font-size: 22rpx;
color: #666;
font-weight: 500;
}
/* 会员等级卡片 */
.vip-card-wrapper {
margin: 24rpx 0 0;
}
.vip-card {
position: relative;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
transition: all 0.3s ease;
}
.vip-card:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
/* 会员卡背景 */
.vip-card-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
/* 不同等级会员的配色方案 */
/* 黄金会员 - VIP1 */
.vip-level-1 {
background: linear-gradient(135deg, #FFD700 0%, #FFA500 50%, #FF8C00 100%);
}
.vip-level-1 .vip-card-bg {
background:
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.2) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(255, 140, 0, 0.3) 0%, transparent 50%);
}
/* 白金会员 - VIP2 */
.vip-level-2 {
background: linear-gradient(135deg, #E8E8E8 0%, #C0C0C0 50%, #A8A8A8 100%);
}
.vip-level-2 .vip-card-bg {
background:
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(192, 192, 192, 0.3) 0%, transparent 50%);
}
/* 钻石会员 - VIP3 */
.vip-level-3 {
background: linear-gradient(135deg, #B9F2FF 0%, #00CED1 50%, #4682B4 100%);
}
.vip-level-3 .vip-card-bg {
background:
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(70, 130, 180, 0.3) 0%, transparent 50%);
}
/* 至尊会员 - VIP4 */
.vip-level-4 {
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 50%, #1a1a1a 100%);
}
.vip-level-4 .vip-card-bg {
background:
radial-gradient(circle at 20% 30%, rgba(255, 215, 0, 0.2) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(255, 165, 0, 0.15) 0%, transparent 50%);
}
/* 皇冠会员 - VIP5 */
.vip-level-5 {
background: linear-gradient(135deg, #8B008B 0%, #9932CC 50%, #BA55D3 100%);
}
.vip-level-5 .vip-card-bg {
background:
radial-gradient(circle at 20% 30%, rgba(255, 255, 255, 0.2) 0%, transparent 50%),
radial-gradient(circle at 80% 70%, rgba(186, 85, 211, 0.3) 0%, transparent 50%);
}
/* 默认会员样式 */
.vip-card-active {
min-height: 200rpx;
}
/* 光效动画 */
.vip-shine {
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(
45deg,
transparent 30%,
rgba(255, 255, 255, 0.15) 50%,
transparent 70%
);
animation: shine 4s infinite;
}
.vip-shine-2 {
animation-delay: 2s;
}
@keyframes shine {
0% {
transform: translateX(-100%) translateY(-100%) rotate(45deg);
}
100% {
transform: translateX(100%) translateY(100%) rotate(45deg);
}
}
/* 装饰元素 */
.vip-decoration {
position: absolute;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
}
.vip-decoration-1 {
top: -40rpx;
right: 60rpx;
}
.vip-decoration-2 {
bottom: -40rpx;
left: 60rpx;
}
/* 未开通会员样式 */
.vip-card-inactive {
background: linear-gradient(135deg, #FAFAFA 0%, #F5F5F5 100%);
border: 2rpx solid #E8E8E8;
}
.vip-pattern {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0.03;
background-image:
repeating-linear-gradient(45deg, #000 0, #000 2rpx, transparent 0, transparent 50%),
repeating-linear-gradient(-45deg, #000 0, #000 2rpx, transparent 0, transparent 50%);
background-size: 30rpx 30rpx;
}
/* 卡片内容 */
.vip-card-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
}
.vip-main-info {
display: flex;
align-items: center;
flex: 1;
}
/* 会员徽章 */
.vip-badge-wrapper {
position: relative;
margin-right: 24rpx;
}
.vip-badge {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10rpx);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.15);
border: 3rpx solid rgba(255, 255, 255, 0.4);
}
@keyframes float {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-6rpx);
}
}
.vip-badge-glow {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100rpx;
height: 100rpx;
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
border-radius: 50%;
animation: glow 2s ease-in-out infinite;
}
@keyframes glow {
0%, 100% {
opacity: 0.5;
transform: translate(-50%, -50%) scale(1);
}
50% {
opacity: 1;
transform: translate(-50%, -50%) scale(1.3);
}
}
/* 未开通会员徽章 */
.vip-badge-inactive .vip-badge {
background: linear-gradient(135deg, #E8E8E8 0%, #D0D0D0 100%);
border: 3rpx solid #C0C0C0;
}
.vip-badge-gray {
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.vip-badge-inactive .vip-badge-icon {
animation: none;
opacity: 0.6;
}
/* 会员文字信息 */
.vip-text-info {
flex: 1;
}
.vip-name-row {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.vip-level-name {
font-size: 32rpx;
font-weight: 700;
color: #FFFFFF;
letter-spacing: 1rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
margin-right: 12rpx;
}
.vip-level-tag {
font-size: 20rpx;
font-weight: 700;
color: rgba(255, 255, 255, 0.9);
background: rgba(0, 0, 0, 0.2);
padding: 4rpx 12rpx;
border-radius: 12rpx;
letter-spacing: 0.5rpx;
}
.vip-desc {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 0.5rpx;
}
/* 未开通会员文字样式 */
.vip-inactive-name {
color: #666;
text-shadow: none;
font-size: 28rpx;
}
.vip-inactive-desc {
color: #999;
font-size: 24rpx;
}
/* 操作按钮 */
.vip-action-btn {
display: flex;
align-items: center;
padding: 16rpx 24rpx;
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10rpx);
border-radius: 48rpx;
border: 2rpx solid rgba(255, 255, 255, 0.3);
}
.vip-action-text {
font-size: 24rpx;
color: #FFFFFF;
font-weight: 600;
margin-right: 6rpx;
text-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.2);
}
.vip-action-arrow {
font-size: 28rpx;
color: #FFFFFF;
font-weight: 600;
}
/* 立即开通按钮 */
.vip-open-btn {
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
padding: 16rpx 32rpx;
border-radius: 48rpx;
box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.4);
display: flex;
flex-direction: column;
align-items: center;
}
.vip-open-text {
font-size: 26rpx;
color: #FFFFFF;
font-weight: 700;
}
/* 卡片底部信息 */
.vip-card-footer {
position: relative;
z-index: 1;
padding: 20rpx 32rpx 28rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1rpx solid rgba(255, 255, 255, 0.15);
}
.vip-expire-info {
display: flex;
align-items: center;
}
.vip-expire-icon {
font-size: 24rpx;
margin-right: 8rpx;
}
.vip-expire-text {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.8);
letter-spacing: 0.5rpx;
}
.vip-upgrade-hint {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.9);
font-weight: 600;
}
.upgrade-hint-text {
text-decoration: underline;
text-underline-offset: 4rpx;
}
/* 未开通会员的权益预览 */
.vip-benefits-preview {
border-top: 1rpx solid #E8E8E8;
padding: 24rpx 32rpx;
display: flex;
justify-content: space-between;
gap: 8rpx;
}
.benefit-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.benefit-icon {
font-size: 32rpx;
margin-bottom: 6rpx;
display: block;
}
.benefit-text {
font-size: 20rpx;
color: #666;
text-align: center;
line-height: 1.3;
}
/* 资产卡片 */
.asset-card {
margin: 0 32rpx 20rpx;
background: #fff;
border-radius: 24rpx;
padding: 0;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
overflow: hidden;
text-align: center;
}
.asset-wrapper {
display: flex;
}
.asset-item {
flex: 1;
display: flex;
flex-direction: column;
padding: 40rpx 24rpx;
position: relative;
}
.asset-item:not(:last-child)::after {
content: '';
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
width: 2rpx;
height: 60rpx;
background: linear-gradient(to bottom, rgba(238, 238, 238, 0), #eeeeee, rgba(238, 238, 238, 0));
}
.asset-primary {
background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
}
.asset-secondary {
background: linear-gradient(135deg, #FFFFFF 0%, #F8F8F8 100%);
}
.asset-label {
font-size: 26rpx;
color: #999;
margin-bottom: 16rpx;
font-weight: 500;
}
.asset-amount-row {
display: flex;
align-items: baseline;
justify-content: center;
}
.asset-symbol {
font-size: 32rpx;
color: #E4393C;
font-weight: 600;
margin-right: 4rpx;
}
.asset-amount {
font-size: 48rpx;
font-weight: 700;
color: #E4393C;
line-height: 1;
letter-spacing: 1rpx;
}
.asset-divider {
height: 2rpx;
background: linear-gradient(to right, rgba(238, 238, 238, 0), #eeeeee, rgba(238, 238, 238, 0));
margin: 0 32rpx;
}
/* 会员卡区域 */
.card-section {
margin: 0 32rpx 24rpx;
padding: 32rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.section-title {
font-size: 32rpx;
font-weight: 700;
color: #333;
margin-bottom: 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.title-text {
letter-spacing: 0.5rpx;
}
.title-icon {
font-size: 36rpx;
}
.card-list {
display: flex;
flex-direction: column;
gap: 20rpx;
transition: all 0.3s ease;
overflow: hidden;
}
.card-item {
display: block;
color: inherit;
}
navigator.card-item {
display: block;
}
.card-item-animate {
animation: cardSlideIn 0.4s ease-out;
transform-origin: top;
}
@keyframes cardSlideIn {
0% {
opacity: 0;
transform: translateY(-20rpx) scaleY(0.8);
}
100% {
opacity: 1;
transform: translateY(0) scaleY(1);
}
}
.card-gradient {
background: linear-gradient(135deg, #E4393C 0%, #C81623 100%);
border-radius: 20rpx;
padding: 32rpx;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.25);
position: relative;
overflow: hidden;
}
.card-gradient::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 200rpx;
height: 200rpx;
background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%);
border-radius: 50%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.card-name {
font-size: 32rpx;
font-weight: 700;
color: #fff;
letter-spacing: 1rpx;
}
.card-badge {
background: rgba(255, 215, 0, 0.9);
color: #C81623;
font-size: 20rpx;
font-weight: 700;
padding: 6rpx 16rpx;
border-radius: 20rpx;
letter-spacing: 1rpx;
}
.card-body {
margin-bottom: 24rpx;
}
.card-amount-box {
display: flex;
flex-direction: column;
}
.card-amount-label {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
margin-bottom: 8rpx;
}
.card-amount-value {
font-size: 56rpx;
font-weight: 700;
color: #fff;
letter-spacing: 2rpx;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 20rpx;
border-top: 1rpx solid rgba(255, 255, 255, 0.2);
}
.card-expire {
display: flex;
align-items: center;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
}
.expire-icon {
margin-right: 6rpx;
font-size: 26rpx;
}
.card-arrow {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
font-weight: 500;
}
/* 查看更多按钮 */
.toggle-btn {
display: flex;
align-items: center;
justify-content: center;
margin-top: 24rpx;
padding: 20rpx 0;
border-radius: 12rpx;
background: linear-gradient(135deg, #f8f8f8 0%, #f0f0f0 100%);
cursor: pointer;
transition: all 0.3s ease;
}
.toggle-btn:active {
background: linear-gradient(135deg, #f0f0f0 0%, #e8e8e8 100%);
transform: scale(0.98);
}
.toggle-text {
font-size: 28rpx;
color: #E4393C;
font-weight: 600;
margin-right: 8rpx;
}
.toggle-icon {
font-size: 36rpx;
color: #E4393C;
font-weight: 600;
transform: rotate(90deg);
transition: transform 0.3s ease;
display: inline-block;
}
.toggle-icon.rotated {
transform: rotate(270deg);
}
.arrow {
font-size: 40rpx;
color: #ccc;
font-weight: 300;
}
/* 订单区域 */
.order-section {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}
.order-section .section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
padding-left: 20rpx;
border-left: 6rpx solid #E4393C;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.section-header .section-title {
margin-bottom: 0;
}
.more-link {
display: flex;
align-items: center;
font-size: 26rpx;
color: #999;
}
.more-link .arrow {
margin-left: 8rpx;
font-size: 32rpx;
}
.order-grid {
display: flex;
justify-content: space-around;
}
.order-item {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.order-icon-wrapper {
position: relative;
margin-bottom: 12rpx;
}
.order-icon {
font-size: 56rpx;
display: block;
}
.order-badge {
position: absolute;
top: -8rpx;
right: -8rpx;
background: #E4393C;
color: #fff;
font-size: 20rpx;
padding: 4rpx 8rpx;
border-radius: 16rpx;
min-width: 32rpx;
text-align: center;
line-height: 1;
font-style: normal;
}
.order-label {
font-size: 24rpx;
color: #666;
}
/* 通用菜单项 */
.menu-item {
background: #fff;
margin: 0;
padding: 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 0;
border-bottom: 1rpx solid #f5f5f5;
}
.menu-item:last-child {
border-bottom: none;
}
.menu-card {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.menu-card .menu-item {
margin: 0;
border-radius: 0;
box-shadow: none;
}
.menu-label {
font-size: 28rpx;
color: #333;
}
.menu-right {
display: flex;
align-items: center;
}
.menu-value {
font-size: 26rpx;
color: #999;
margin-right: 8rpx;
}
/* 常用功能区域 */
.function-section {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
}
.function-section .section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 24rpx;
padding-left: 20rpx;
border-left: 6rpx solid #E4393C;
display: block;
}
.function-grid {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
}
.function-item {
width: 25%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 32rpx 0;
}
.function-icon {
font-size: 56rpx;
margin-bottom: 12rpx;
display: block;
}
.function-label {
font-size: 24rpx;
color: #666;
text-align: center;
}
/* 配送员工作台 */
.work-section {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.work-section .section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
background: #fff;
margin: 0;
padding: 32rpx;
border-bottom: 1rpx solid #f5f5f5;
padding-left: 52rpx;
border-left: 6rpx solid #E4393C;
display: block;
}
.work-section .menu-item {
margin: 0;
border-radius: 0;
}
/* 分销区域 */
.distribution-section {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.distribution-section .section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
background: #fff;
margin: 0;
padding: 32rpx;
border-bottom: 1rpx solid #f5f5f5;
padding-left: 52rpx;
border-left: 6rpx solid #E4393C;
display: block;
}
.distribution-section .menu-item {
margin: 0;
border-radius: 0;
}
/* 其他功能 */
.other-section {
margin: 0 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
overflow: hidden;
}
.other-section .section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
background: #fff;
margin: 0;
padding: 32rpx;
border-bottom: 1rpx solid #f5f5f5;
padding-left: 52rpx;
border-left: 6rpx solid #E4393C;
display: block;
}
.other-section .menu-item {
margin: 0;
border-radius: 0;
}
/* 弹窗样式 */
.modal-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.modal-content {
width: 600rpx;
background: #fff;
border-radius: 24rpx;
overflow: hidden;
}
.modal-header {
padding: 48rpx 32rpx 32rpx;
font-size: 32rpx;
font-weight: 600;
color: #333;
text-align: center;
border-bottom: 1rpx solid #f5f5f5;
}
.modal-body {
padding: 48rpx 32rpx;
}
.nick-input {
width: 100%;
padding: 24rpx;
border: 2rpx solid #eee;
border-radius: 12rpx;
font-size: 28rpx;
background: #f8f8f8;
}
.input-placeholder {
color: #ccc;
}
.modal-footer {
display: flex;
border-top: 1rpx solid #f5f5f5;
}
.modal-btn {
flex: 1;
padding: 32rpx;
text-align: center;
font-size: 32rpx;
}
.cancel-btn {
color: #666;
border-right: 1rpx solid #f5f5f5;
}
.confirm-btn {
color: #E4393C;
font-weight: 600;
}
/* 微信原生组件适配 */
switch {
transform: scale(0.85);
}
navigator {
display: block;
color: inherit;
text-decoration: none;
}
navigator.function-item {
display: flex;
}
button {
background: transparent;
border: none;
padding: 0;
margin: 0;
line-height: inherit;
}
button::after {
border: none;
}
/* navigator包裹menu-card时的特殊处理 */
navigator.menu-card {
display: block;
}
navigator.menu-item {
display: flex;
}
================================================
FILE: pages/my/info-menu.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
this.getUserApiInfo()
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
let _data = {}
_data.apiUserInfoMap = res.data
if (res.data.base.mobile) {
_data.userMobile = res.data.base.mobile
}
if (this.data.order_hx_uids && this.data.order_hx_uids.indexOf(res.data.base.id) != -1) {
_data.canHX = true // 具有扫码核销的权限
}
if (res.data.peisongMember && res.data.peisongMember.status == 1) {
_data.memberChecked = false
} else {
_data.memberChecked = true
}
this.setData(_data);
}
},
bindMobile() {
this.setData({
bindMobileShow: true
})
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false
})
this.getUserApiInfo()
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
})
================================================
FILE: pages/my/info-menu.json
================================================
{
"navigationBarTitleText": "个人信息",
"navigationBarBackgroundColor": "#667eea",
"navigationBarTextStyle": "white",
"backgroundColor": "#f5f7fa"
}
================================================
FILE: pages/my/info-menu.wxml
================================================
================================================
FILE: pages/my/info-menu.wxss
================================================
/* pages/my/info-menu.wxss */
/* 页面容器 */
.page-container {
min-height: 100vh;
background: linear-gradient(180deg, #f5f7fa 0%, #ffffff 100%);
padding-bottom: 40rpx;
}
/* 顶部装饰背景 */
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 360rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 0 0 50% 50% / 0 0 60rpx 60rpx;
z-index: 0;
}
/* 主要内容区域 */
.content-wrapper {
position: relative;
z-index: 1;
padding: 40rpx 32rpx;
}
/* 卡片模块 */
.section-card {
background: #ffffff;
border-radius: 24rpx;
margin-bottom: 32rpx;
overflow: hidden;
box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.08);
transition: all 0.3s ease;
}
.section-card:active {
transform: scale(0.99);
}
/* 模块标题区域 */
.section-header {
padding: 36rpx 32rpx 24rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.03) 0%, rgba(118, 75, 162, 0.03) 100%);
border-bottom: 1rpx solid rgba(102, 126, 234, 0.08);
}
.section-title {
display: flex;
align-items: center;
}
.title-icon {
font-size: 44rpx;
margin-right: 16rpx;
display: flex;
align-items: center;
justify-content: center;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #2c3e50;
letter-spacing: 1rpx;
}
/* 菜单列表 */
.menu-list {
padding: 0;
}
/* Navigator 包装器 */
.menu-item-nav {
display: block;
text-decoration: none;
}
/* 菜单项 */
.menu-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32rpx 32rpx;
position: relative;
transition: all 0.3s ease;
background: #ffffff;
}
.menu-item::after {
content: '';
position: absolute;
left: 96rpx;
right: 32rpx;
bottom: 0;
height: 1rpx;
background: linear-gradient(90deg, rgba(102, 126, 234, 0.1) 0%, transparent 100%);
}
.menu-item:last-child::after {
display: none;
}
/* Hover效果 */
.menu-item-hover {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.03) 100%);
}
/* 左侧内容 */
.item-left {
display: flex;
align-items: center;
flex: 1;
}
.item-icon {
width: 88rpx;
height: 88rpx;
border-radius: 20rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
margin-right: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.15);
}
.item-info {
display: flex;
flex-direction: column;
justify-content: center;
}
.item-title {
font-size: 30rpx;
font-weight: 500;
color: #2c3e50;
margin-bottom: 6rpx;
letter-spacing: 0.5rpx;
}
.item-subtitle {
font-size: 24rpx;
color: #8492a6;
font-weight: 400;
}
/* 右侧内容 */
.item-right {
display: flex;
align-items: center;
margin-left: 20rpx;
}
.item-value {
font-size: 26rpx;
color: #667eea;
font-weight: 500;
margin-right: 8rpx;
}
.arrow {
font-size: 40rpx;
color: #c0c4cc;
font-weight: 300;
line-height: 1;
transform: translateY(-2rpx);
}
/* 立即绑定按钮 */
.bind-btn {
padding: 12rpx 32rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
font-size: 26rpx;
font-weight: 500;
border-radius: 40rpx;
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.35);
transition: all 0.3s ease;
letter-spacing: 1rpx;
}
.bind-btn:active {
transform: scale(0.95);
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.25);
}
/* 响应式优化 */
@media (prefers-color-scheme: dark) {
.page-container {
background: linear-gradient(180deg, #1a1a1a 0%, #2d2d2d 100%);
}
.section-card {
background: #2d2d2d;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.3);
}
.section-header {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%);
border-bottom-color: rgba(102, 126, 234, 0.15);
}
.title-text {
color: #e4e7ed;
}
.item-title {
color: #e4e7ed;
}
.item-subtitle {
color: #909399;
}
.menu-item {
background: #2d2d2d;
}
.menu-item-hover {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.08) 100%);
}
}
================================================
FILE: pages/my/info.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
avatarUrl: undefined,
avatarUrlTmpFile: undefined,
gender: undefined,
genderArray: [ '男性', '女性'],
genderIndex: -1
},
onLoad(e) {
this.getUserApiInfo()
},
onShow() {
},
bindMobile() {
this.setData({
bindMobileShow: true
})
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false
})
this.getUserApiInfo()
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
let _data = {}
_data.apiUserInfoMap = res.data
_data.nick = res.data.base.nick
_data.avatarUrl = res.data.base.avatarUrl
if (!res.data.base.gender) {
_data.gender = '未知'
}
if (res.data.base.gender == 1) {
_data.gender = '男性'
}
if (res.data.base.gender == 2) {
_data.gender = '女性'
}
this.setData(_data)
}
},
async formSubmit() {
const postData = {
token: wx.getStorageSync('token'),
nick: this.data.nick
}
if (this.data.avatarUrlTmpFile) {
const res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), this.data.avatarUrlTmpFile)
if (res.code == 0) {
postData.avatarUrl = res.data.url
}
}
if (this.data.genderIndex != -1) {
postData.gender = this.data.genderIndex*1 + 1
}
// https://www.yuque.com/apifm/nu0f75/ykr2zr
const res = await WXAPI.modifyUserInfoV2(postData)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
wx.showToast({
title: '编辑成功',
})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
},
async onChooseAvatar(e) {
console.log(e);
const avatarUrl = e.detail.avatarUrl
this.setData({
avatarUrl: avatarUrl,
avatarUrlTmpFile: avatarUrl
})
},
bindPickerChange: function(e) {
this.setData({
genderIndex: e.detail.value,
gender: this.data.genderArray[e.detail.value]
})
},
})
================================================
FILE: pages/my/info.json
================================================
{
"navigationBarTitleText": "编辑资料"
}
================================================
FILE: pages/my/info.wxml
================================================
基本信息
👤
昵称
⚥
性别
{{ gender || '请选择' }}
›
📱
手机号码
{{ apiUserInfoMap.base.mobile || '未绑定' }}
{{ apiUserInfoMap.base.mobile ? '更换' : '绑定' }}
扩展信息
📝
{{ k }}
保存修改
================================================
FILE: pages/my/info.wxss
================================================
page {
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
min-height: 100vh;
}
.profile-container {
padding-bottom: 40rpx;
}
/* ========== 头部区域 ========== */
.header-section {
position: relative;
height: 400rpx;
margin-bottom: -80rpx;
overflow: hidden;
}
.header-bg {
width: 100%;
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
position: relative;
}
.header-bg::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.header-bg::after {
content: '';
position: absolute;
bottom: -30%;
left: -10%;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
}
.avatar-wrapper {
position: absolute;
top: 88rpx;
left: 50%;
transform: translateX(-50%);
z-index: 10;
}
.avatar-button {
position: relative;
width: 180rpx;
height: 180rpx;
padding: 0;
margin: 0;
border: none;
background: transparent;
border-radius: 50%;
overflow: visible;
}
.avatar-button::after {
border: none;
}
.avatar-image {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
border: 8rpx solid #ffffff;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
display: block;
}
.avatar-mask {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 160rpx;
height: 50rpx;
background: rgba(0, 0, 0, 0.6);
border-radius: 0 0 50% 50%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
.avatar-button:active .avatar-mask {
opacity: 1;
}
.avatar-text {
color: #ffffff;
font-size: 22rpx;
font-weight: 500;
}
/* ========== 信息卡片 ========== */
.info-card {
margin: 100rpx 30rpx 30rpx;
background: #ffffff;
border-radius: 24rpx;
padding: 40rpx 32rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
.info-card:first-of-type {
margin-top: 100rpx;
}
.card-title {
display: flex;
align-items: center;
margin-bottom: 36rpx;
}
.title-line {
width: 6rpx;
height: 32rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 3rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #2c3e50;
letter-spacing: 1rpx;
}
/* ========== 表单项 ========== */
.form-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 0;
min-height: 88rpx;
}
.item-label {
display: flex;
align-items: center;
flex-shrink: 0;
width: 200rpx;
}
.label-icon {
font-size: 36rpx;
margin-right: 16rpx;
line-height: 1;
}
.label-text {
font-size: 30rpx;
color: #34495e;
font-weight: 500;
}
.item-input {
flex: 1;
text-align: right;
font-size: 28rpx;
color: #2c3e50;
padding-right: 8rpx;
}
.input-placeholder {
color: #bdc3c7;
font-size: 28rpx;
}
.item-value {
display: flex;
align-items: center;
flex: 1;
justify-content: flex-end;
}
.value-text {
font-size: 28rpx;
color: #7f8c8d;
margin-right: 8rpx;
}
.arrow-icon {
font-size: 48rpx;
color: #bdc3c7;
font-weight: 300;
line-height: 1;
margin-top: -4rpx;
}
/* ========== 手机号区域 ========== */
.mobile-wrapper {
display: flex;
align-items: center;
flex: 1;
justify-content: flex-end;
}
.mobile-text {
font-size: 28rpx;
color: #7f8c8d;
margin-right: 16rpx;
}
.bind-btn {
padding: 10rpx 24rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
}
.bind-text {
font-size: 24rpx;
color: #ffffff;
font-weight: 500;
}
/* ========== 分割线 ========== */
.divider {
height: 1rpx;
background: linear-gradient(to right,
rgba(189, 195, 199, 0) 0%,
rgba(189, 195, 199, 0.3) 50%,
rgba(189, 195, 199, 0) 100%);
margin: 0 -16rpx;
}
/* ========== 保存按钮 ========== */
.save-section {
padding: 60rpx 30rpx 40rpx;
}
.save-button {
height: 96rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.4);
position: relative;
overflow: hidden;
}
.save-button::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent);
transition: left 0.5s;
}
.save-button:active::before {
left: 100%;
}
.save-button:active {
transform: scale(0.98);
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.3);
}
.save-text {
font-size: 32rpx;
color: #ffffff;
font-weight: 600;
letter-spacing: 4rpx;
}
/* ========== 响应式优化 ========== */
@media (prefers-color-scheme: dark) {
page {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
}
.info-card {
background: #0f3460;
}
.title-text {
color: #e8ecf1;
}
.label-text {
color: #e8ecf1;
}
.item-input {
color: #e8ecf1;
}
.value-text,
.mobile-text {
color: #95a5a6;
}
}
================================================
FILE: pages/my/setting.js
================================================
const CONFIG = require('../../config.js')
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
enableDebug: wx.getSystemInfoSync().enableDebug
},
onLoad: function (options) {
this.setData({
version: CONFIG.version
})
},
onShow: function () {
this.getUserApiInfo()
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
let _data = {}
_data.apiUserInfoMap = res.data
if (res.data.base.mobile) {
_data.userMobile = res.data.base.mobile
}
if (this.data.order_hx_uids && this.data.order_hx_uids.indexOf(res.data.base.id) != -1) {
_data.canHX = true // 具有扫码核销的权限
}
if (res.data.peisongMember && res.data.peisongMember.status == 1) {
_data.memberChecked = false
} else {
_data.memberChecked = true
}
this.setData(_data);
}
},
clearStorage(){
wx.clearStorageSync()
wx.showToast({
title: '已清除',
icon: 'success'
})
},
setEnableDebug() {
const enableDebug = wx.getSystemInfoSync().enableDebug
if (enableDebug) {
wx.setEnableDebug({
enableDebug: false
})
} else {
wx.setEnableDebug({
enableDebug: true
})
}
},
openSetting() {
wx.openSetting({
withSubscriptions: true
})
},
loginOut() {
AUTH.loginOut()
wx.navigateTo({
url: '/pages/login/index',
})
},
})
================================================
FILE: pages/my/setting.json
================================================
{
"navigationBarTitleText": "设置"
}
================================================
FILE: pages/my/setting.wxml
================================================
ℹ️
关于我们
了解更多信息
›
📹
视频客服
在线视频咨询
›
💬
意见反馈
您的建议很重要
›
🗑️
清除缓存
释放存储空间
›
🔧
{{ enableDebug ? '关闭调试模式' : '打开调试模式' }}
开发者选项
›
🔐
权限与设置
管理应用权限
›
✨
当前版本
{{version}}
最新版
================================================
FILE: pages/my/setting.wxss
================================================
/* 页面容器 */
.setting-container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 0 0 60rpx 0;
}
/* 头部区域 */
.header-section {
position: relative;
padding: 80rpx 40rpx 60rpx;
text-align: center;
overflow: hidden;
}
.header-decoration {
position: absolute;
top: -100rpx;
right: -100rpx;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
animation: float 6s ease-in-out infinite;
}
@keyframes float {
0%, 100% {
transform: translate(0, 0) scale(1);
}
50% {
transform: translate(-20rpx, 20rpx) scale(1.05);
}
}
.header-title {
display: block;
font-size: 56rpx;
font-weight: 700;
color: #ffffff;
letter-spacing: 4rpx;
margin-bottom: 12rpx;
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
.header-subtitle {
display: block;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 2rpx;
font-weight: 300;
}
/* 分组卡片 */
.section-card {
margin: 0 30rpx 32rpx;
background: #ffffff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
transition: all 0.3s ease;
}
.section-card:active {
transform: scale(0.98);
}
/* 分组标题 */
.section-header {
display: flex;
align-items: center;
padding: 32rpx 32rpx 24rpx;
background: linear-gradient(135deg, #f5f7fa 0%, #f8f9fb 100%);
border-bottom: 2rpx solid #f0f2f5;
}
.section-icon {
width: 56rpx;
height: 56rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.3);
}
.icon-text {
font-size: 32rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #1a1a1a;
letter-spacing: 1rpx;
}
/* 卡片内容 */
.card-content {
padding: 0 32rpx;
}
/* 设置项 */
.setting-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32rpx 0;
border-bottom: 1rpx solid #f0f2f5;
transition: all 0.3s ease;
position: relative;
}
.setting-item:last-child {
border-bottom: none;
}
.setting-item::before {
content: '';
position: absolute;
left: -32rpx;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 3rpx;
transition: height 0.3s ease;
}
.item-hover {
background: #f8f9fb;
}
.setting-item:active::before {
height: 60%;
}
.item-left {
display: flex;
align-items: center;
flex: 1;
}
/* 图标样式 */
.item-icon {
width: 80rpx;
height: 80rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
font-size: 36rpx;
position: relative;
overflow: hidden;
}
.item-icon::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
z-index: 0;
}
.iconfont {
position: relative;
z-index: 1;
}
/* 不同图标的颜色 */
.icon-about {
background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%);
}
.icon-video {
background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%);
}
.icon-feedback {
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
}
.icon-clear {
background: linear-gradient(135deg, #fce4ec 0%, #f8bbd0 100%);
}
.icon-debug {
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
}
.icon-permission {
background: linear-gradient(135deg, #fff9c4 0%, #fff59d 100%);
}
/* 文字信息 */
.item-info {
display: flex;
flex-direction: column;
}
.item-title {
font-size: 30rpx;
font-weight: 500;
color: #1a1a1a;
margin-bottom: 8rpx;
letter-spacing: 0.5rpx;
}
.item-desc {
font-size: 24rpx;
color: #999999;
font-weight: 300;
}
/* 箭头 */
.item-arrow {
font-size: 48rpx;
color: #d0d0d0;
font-weight: 200;
transition: all 0.3s ease;
}
.setting-item:active .item-arrow {
color: #667eea;
transform: translateX(6rpx);
}
/* 版本卡片 */
.version-card {
margin: 48rpx 30rpx 32rpx;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fb 100%);
border: 2rpx solid #f0f2f5;
}
.version-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 40rpx 32rpx;
position: relative;
}
.version-icon {
font-size: 48rpx;
margin-right: 24rpx;
}
.version-info {
flex: 1;
display: flex;
flex-direction: column;
}
.version-label {
font-size: 28rpx;
color: #666666;
margin-bottom: 8rpx;
font-weight: 400;
}
.version-number {
font-size: 36rpx;
font-weight: 600;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
letter-spacing: 1rpx;
}
.version-tag {
padding: 8rpx 20rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
font-size: 22rpx;
border-radius: 20rpx;
font-weight: 500;
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
}
/* 底部装饰 */
.footer-decoration {
padding: 60rpx 40rpx 40rpx;
text-align: center;
}
.footer-text {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.7);
letter-spacing: 2rpx;
font-weight: 300;
}
/* 保留原有的btn类以防万一 */
.btn {
padding: 32rpx;
}
/* Navigator组件重置 */
navigator {
display: block;
text-decoration: none;
}
navigator.setting-item {
color: inherit;
}
================================================
FILE: pages/my/user-code.js
================================================
const WXAPI = require('apifm-wxapi')
import wxbarcode from 'wxbarcode'
Page({
data: {
balance: 0,
freeze: 0,
score: 0,
growth: 0,
userCode: undefined
},
onLoad(e) {
this.getUserAmount()
this.dynamicUserCode()
},
onShow: function () {
},
async getUserAmount() {
const res = await WXAPI.userAmount(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
balance: res.data.balance,
freeze: res.data.freeze,
score: res.data.score,
growth: res.data.growth
})
}
},
async dynamicUserCode() {
const res = await WXAPI.dynamicUserCode(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
userCode: res.data
})
wxbarcode.barcode('barcode', res.data, 560, 200);
wxbarcode.qrcode('qrcode', res.data, 480, 480);
}
},
onPullDownRefresh() {
this.getUserAmount()
this.dynamicUserCode()
wx.stopPullDownRefresh()
},
})
================================================
FILE: pages/my/user-code.json
================================================
{
"navigationBarTitleText": "会员码",
"enablePullDownRefresh": true
}
================================================
FILE: pages/my/user-code.wxml
================================================
会员编号
{{ userCode }}
请向商家出示此码
我的资产
¥
{{ balance }}
账户余额
★
{{ score }}
积分
✓
支持扫码支付
✓
积分自动累积
================================================
FILE: pages/my/user-code.wxss
================================================
page {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding-bottom: 60rpx;
}
.page-container {
position: relative;
min-height: 100vh;
overflow: hidden;
}
/* 顶部装饰 */
.header-decoration {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 400rpx;
overflow: hidden;
z-index: 0;
}
.decoration-circle {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
animation: float 6s ease-in-out infinite;
}
.circle-1 {
width: 300rpx;
height: 300rpx;
top: -100rpx;
right: -50rpx;
animation-delay: 0s;
}
.circle-2 {
width: 200rpx;
height: 200rpx;
top: 150rpx;
left: -80rpx;
animation-delay: 2s;
}
.circle-3 {
width: 150rpx;
height: 150rpx;
top: 50rpx;
left: 50%;
animation-delay: 4s;
}
@keyframes float {
0%, 100% {
transform: translateY(0) scale(1);
opacity: 0.3;
}
50% {
transform: translateY(-30rpx) scale(1.1);
opacity: 0.5;
}
}
/* 会员卡片 */
.membership-card {
position: relative;
margin: 40rpx 30rpx;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border-radius: 32rpx;
padding: 50rpx 40rpx 60rpx;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.15),
0 8rpx 20rpx rgba(0, 0, 0, 0.1);
z-index: 1;
overflow: hidden;
}
.membership-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 8rpx;
background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #f093fb 100%);
}
.card-header {
text-align: center;
margin-bottom: 40rpx;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #f0f0f0;
}
.card-title {
font-size: 40rpx;
font-weight: 700;
color: #2c3e50;
letter-spacing: 4rpx;
margin-bottom: 12rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.card-subtitle {
font-size: 22rpx;
color: #95a5a6;
letter-spacing: 6rpx;
font-weight: 500;
}
/* 会员码编号 */
.code-number {
text-align: center;
margin-bottom: 40rpx;
padding: 24rpx;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 16rpx;
border: 2rpx dashed #d0d7de;
}
.code-label {
font-size: 24rpx;
color: #6c757d;
margin-bottom: 8rpx;
}
.code-value {
font-size: 32rpx;
font-weight: 600;
color: #495057;
letter-spacing: 4rpx;
font-family: 'Courier New', monospace;
}
/* 二维码容器 */
.qrcode-container {
display: flex;
flex-direction: column;
align-items: center;
margin: 40rpx 0;
}
.qrcode-wrapper {
position: relative;
padding: 30rpx;
background: #ffffff;
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08),
inset 0 2rpx 4rpx rgba(255, 255, 255, 0.9);
}
.user-code {
width: 480rpx;
height: 480rpx;
display: block;
border-radius: 16rpx;
}
/* 二维码四角装饰 */
.qrcode-corners {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
}
.corner {
position: absolute;
width: 50rpx;
height: 50rpx;
border-color: #667eea;
border-style: solid;
}
.corner-tl {
top: 20rpx;
left: 20rpx;
border-width: 6rpx 0 0 6rpx;
border-radius: 24rpx 0 0 0;
}
.corner-tr {
top: 20rpx;
right: 20rpx;
border-width: 6rpx 6rpx 0 0;
border-radius: 0 24rpx 0 0;
}
.corner-bl {
bottom: 20rpx;
left: 20rpx;
border-width: 0 0 6rpx 6rpx;
border-radius: 0 0 0 24rpx;
}
.corner-br {
bottom: 20rpx;
right: 20rpx;
border-width: 0 6rpx 6rpx 0;
border-radius: 0 0 24rpx 0;
}
.scan-tip {
margin-top: 24rpx;
font-size: 26rpx;
color: #6c757d;
letter-spacing: 2rpx;
}
/* 条形码容器 */
.barcode-container {
display: flex;
justify-content: center;
margin-top: 40rpx;
padding: 20rpx;
background: #ffffff;
border-radius: 16rpx;
box-shadow: inset 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}
.user-code-bar {
width: 560rpx;
height: 160rpx;
display: block;
}
/* 资产卡片 */
.assets-card {
margin: 30rpx 30rpx 0;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
border-radius: 32rpx;
padding: 40rpx;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.15),
0 8rpx 20rpx rgba(0, 0, 0, 0.1);
z-index: 1;
position: relative;
}
.assets-title {
font-size: 32rpx;
font-weight: 700;
color: #2c3e50;
margin-bottom: 32rpx;
text-align: center;
letter-spacing: 2rpx;
}
.assets-grid {
display: flex;
align-items: center;
justify-content: space-around;
}
.asset-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
padding: 24rpx;
}
.asset-divider {
width: 2rpx;
height: 120rpx;
background: linear-gradient(180deg, transparent 0%, #e9ecef 50%, transparent 100%);
}
.asset-icon {
width: 88rpx;
height: 88rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16rpx;
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.asset-icon::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.3);
transform: translateX(-100%);
transition: transform 0.6s;
}
.balance-icon {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.points-icon {
background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%);
}
.icon-text {
font-size: 40rpx;
color: #ffffff;
font-weight: 700;
z-index: 1;
}
.asset-value {
font-size: 44rpx;
font-weight: 700;
color: #2c3e50;
margin-bottom: 8rpx;
letter-spacing: 2rpx;
}
.asset-label {
font-size: 24rpx;
color: #6c757d;
letter-spacing: 1rpx;
}
/* 底部提示 */
.bottom-tips {
display: flex;
justify-content: center;
align-items: center;
margin: 40rpx 30rpx;
padding: 32rpx;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(20rpx);
border-radius: 24rpx;
border: 2rpx solid rgba(255, 255, 255, 0.3);
}
.tip-item {
display: flex;
align-items: center;
margin: 0 20rpx;
}
.tip-icon {
font-size: 28rpx;
color: #ffffff;
margin-right: 8rpx;
font-weight: 700;
}
.tip-text {
font-size: 24rpx;
color: #ffffff;
letter-spacing: 1rpx;
}
================================================
FILE: pages/notagree/index.js
================================================
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
},
})
================================================
FILE: pages/notagree/index.json
================================================
{
"navigationBarTitleText": "很抱歉~"
}
================================================
FILE: pages/notagree/index.wxml
================================================
Oops!
很遗憾,若您不同意《用户协议》和《隐私协议》,将无法继续使用我们的服务。
================================================
FILE: pages/notagree/index.wxss
================================================
.notagree {
padding: 64rpx;
}
.title {
font-size: 100rpx;
font-weight: bold;
}
.profile {
margin-top: 64rpx;
color: #666;
line-height: 48rpx;
}
.img {
margin-top: 64rpx;
}
================================================
FILE: pages/notice/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
WXAPI.noticeList().then(res => {
this.setData({
noticeList: res.data.dataList
})
})
},
onShow: function () {
},
})
================================================
FILE: pages/notice/index.json
================================================
{
"navigationBarTitleText": "公告"
}
================================================
FILE: pages/notice/index.wxml
================================================
{{item.title}}
{{ item.dateAdd }}
查看 >
================================================
FILE: pages/notice/index.wxss
================================================
page {
background-color: #f3f4f5;
}
.no-order {
margin-top: 96rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.no-order image {
width: 294rpx;
height: 310rpx;
}
.no-order view {
margin-top: 30rpx;
font-family: PingFangSC-Medium;
font-size: 30rpx;
color: #333;
letter-spacing: 0;
}
.cashlogs {
width: 702rpx;
margin-top: 24rpx;
margin-left: 24rpx;
height: 148rpx;
background: #FFFFFF;
box-shadow: 0 0 16rpx 0 rgba(36,44,69,0.20);
border-radius: 8rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.cashlogs .profile {
display: flex;
flex-direction: column;
margin-left: 24rpx;
}
.cashlogs .amount {
font-size: 24rpx;
color: #FEB21C;
margin-right: 24rpx;
flex-shrink: 0;
}
.cashlogs .profile .typeStr {
font-size: 30rpx;
color: #333333;
}
.cashlogs .profile .dateAdd {
margin-top: 16rpx;
font-size: 24rpx;
color: #999999;
}
.bottom {
width: 100vw;
height: 24rpx;
}
================================================
FILE: pages/notice/show.js
================================================
const app = getApp();
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad: function (options) {
var that = this;
WXAPI.noticeDetail(options.id).then(function (res) {
if (res.code == 0) {
that.setData({
notice: res.data
});
}
})
},
onShareAppMessage() {
},
onShareTimeline() {
return {
title: this.data.notice.title,
query: 'id=' + this.data.notice.id,
imageUrl: wx.getStorageSync('share_pic')
}
},
subscribe() {
const notice_subscribe_ids = wx.getStorageSync('notice_subscribe_ids')
if (notice_subscribe_ids) {
wx.requestSubscribeMessage({
tmplIds: notice_subscribe_ids.split(','),
success(res) {
wx.showToast({
title: '订阅成功',
})
},
fail(err) {
console.error(err)
},
})
}
},
})
================================================
FILE: pages/notice/show.json
================================================
{
"navigationBarTitleText": "公告详情"
}
================================================
FILE: pages/notice/show.wxml
================================================
{{notice.title}}
================================================
FILE: pages/notice/show.wxss
================================================
.notice {
padding: 32rpx;
font-size: 26rpx;
color: #333;
}
.title {
width: 100%;
font-weight: bold;
border-bottom: 1rpx solid #eaeaea;
padding-bottom: 32rpx;
}
.text {
margin-top: 32rpx;
line-height: 64rpx;
}
.text image {
max-width: 100%;
}
================================================
FILE: pages/order/refundApply.js
================================================
const WXAPI = require('apifm-wxapi')
const CONFIG = require('../../config.js')
Page({
data: {
autosize: {
minHeight: 100
},
orderId: 1,
number: 0,
amount: 999.00,
type: '0',
typeItems: [
{ name: '我要退款(无需退货)', value: '0', checked: true },
{ name: '我要退货退款', value: '1' },
{ name: '我要换货', value: '2' },
],
logisticsStatus:'0',
logisticsStatusItems: [
{ name: '未收到货', value: '0', checked: true },
{ name: '已收到货', value: '1' }
],
reason: '不喜欢/不想要',
reasons: [
"不喜欢/不想要",
"空包裹",
"未按约定时间发货",
"快递/物流一直未送达",
"货物破损已拒签",
"退运费",
"规格尺寸与商品页面描述不符",
"功能/效果不符",
"质量问题",
"少件/漏发",
"包装/商品破损",
"发票问题",
],
reasonIndex: 0,
files: [],
pics: [],
// 快递信息弹窗
logisticsDialogShow: false,
shipperName: '',
trackingNumber: ''
},
onLoad: function (e) {
this.setData({
orderId: e.id,
amount: e.amount,
customerServiceType: CONFIG.customerServiceType,
})
this.orderDetail()
},
onShow(){
},
async orderDetail() {
const token = wx.getStorageSync('token')
const res = await WXAPI.orderDetail(token, this.data.orderId)
if (res.code != 0) {
wx.showModal({
content: res.msg,
success: (res) => {
wx.navigateBack()
}
})
return
}
res.data.goods.forEach(ele => {
if (ele.afterSale) {
ele.afterSale.split(',').forEach(a => {
ele['afterSale' + a] = true
})
}
})
// 读取已申请售后记录
const res2 = await WXAPI.refundApplyDetail(token, this.data.orderId)
let refundApplyList = []
if (res2.code == 0) {
res2.data.forEach(ele => {
ele.goodInfo = res.data.goods.find(g => g.id == ele.baseInfo.orderGoodsId)
console.log(ele.goodInfo);
})
refundApplyList = res2.data
}
this.setData({
goods: res.data.goods,
refundApplyList
})
},
async refundApplyCancel(){
wx.showLoading({
title: '',
})
const res = await WXAPI.refundApplyCancel(wx.getStorageSync('token'), this.data.curRufund.baseInfo.orderId, this.data.curRufund.baseInfo.orderGoodsId)
wx.hideLoading()
if (res.code == 0) {
wx.showToast({
title: '已取消',
})
this.popClose()
this.orderDetail()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
typeChange(event) {
this.setData({
type: event.detail,
});
},
typeClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
type: name,
});
},
logisticsStatusChange(event) {
this.setData({
logisticsStatus: event.detail,
});
},
logisticsStatusClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
logisticsStatus: name,
});
},
reasonChange(event) {
this.setData({
reason: event.detail,
});
},
reasonClick(event) {
const { name } = event.currentTarget.dataset;
this.setData({
reason: name,
});
},
reasonChange: function (e) {
this.setData({
reasonIndex: e.detail.value
})
},
afterPicRead(e) {
let picsList = this.data.picsList
if (!picsList) {
picsList = []
}
picsList = picsList.concat(e.detail.file)
this.setData({
picsList
})
},
afterPicDel(e) {
let picsList = this.data.picsList
picsList.splice(e.detail.index, 1)
this.setData({
picsList
})
},
previewImage: function (e) {
const that = this;
wx.previewImage({
current: e.currentTarget.id, // 当前显示图片的http链接
urls: that.data.files // 需要预览的图片http链接列表
})
},
async bindSave () {
let amount = this.data.curGoods.amountSingle * this.data.number
if (this.data.type == 2) {
// 换货金额为0
amount = 0.00
}
wx.showLoading({
title: '',
})
// 批量上传附件
if (this.data.picsList) {
for (let index = 0; index < this.data.picsList.length; index++) {
const pic = this.data.picsList[index];
const res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), pic.url)
if (res.code == 0) {
this.data.pics.push(res.data.url)
}
}
}
const res = await WXAPI.refundApply({
token: wx.getStorageSync('token'),
orderId: this.data.orderId,
orderGoodsId: this.data.curGoods.id,
type: this.data.type,
logisticsStatus: this.data.logisticsStatus,
reason: this.data.reason,
number: this.data.number,
amount,
remark: this.data.remark || '',
pic: this.data.pics.join()
})
wx.hideLoading()
if (res.code == 20000) {
wx.showModal({
content: '当前商品正在售后中,如需重新申请,请先撤销之前的售后申请',
showCancel: false
})
return
}
if (res.code == 0) {
wx.showModal({
content: '提交成功,请耐心等待我们处理!',
showCancel: false,
success: res => {
wx.navigateBack()
}
})
} else {
wx.showModal({
content: res.msg,
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
},
goodsClick(e) {
const goodsIndex = e.currentTarget.dataset.name
const curGoods = this.data.goods[goodsIndex]
if (!curGoods || !curGoods.afterSale) {
return
}
this.setData({
goodsIndex,
curGoods,
number: curGoods.number
})
},
numberChange(e) {
let number = e.detail
if (!number) {
return
}
if (number > this.data.curGoods.number) {
number = this.data.curGoods.number
}
this.setData({
number
})
},
refundDetail(e) {
const index = e.currentTarget.dataset.idx
const curRufund = this.data.refundApplyList[index]
const imageList = []
if (curRufund.pics) {
curRufund.pics.forEach(ele => {
imageList.push(ele.pic + '_m')
})
}
let logisticsContent = curRufund.baseInfo.logisticsContent
if (logisticsContent) {
logisticsContent = JSON.parse(logisticsContent)
}
this.setData({
popShow: true,
curRufund,
imageList,
logisticsContent
})
},
popClose() {
this.setData({
popShow: false
})
},
previewImageimageList(e) {
console.log(e);
wx.previewImage({
current: e.currentTarget.dataset.current,
urls: this.data.imageList,
})
},
customerService() {
wx.openCustomerServiceChat({
extInfo: {url: wx.getStorageSync('customerServiceChatUrl')},
corpId: wx.getStorageSync('customerServiceChatCorpId'),
success: res => {},
fail: err => {
console.error(err)
}
})
},
// 显示快递信息输入弹窗
showLogisticsDialog() {
this.setData({
logisticsDialogShow: true,
shipperName: '',
trackingNumber: ''
})
},
// 关闭快递信息输入弹窗
closeLogisticsDialog() {
this.setData({
logisticsDialogShow: false,
shipperName: '',
trackingNumber: ''
})
},
// 提交快递信息
async submitLogistics() {
const { shipperName, trackingNumber } = this.data
// 验证输入
if (!shipperName || !shipperName.trim()) {
wx.showToast({
title: '请输入快递公司名称',
icon: 'none'
})
return
}
if (!trackingNumber || !trackingNumber.trim()) {
wx.showToast({
title: '请输入快递单号',
icon: 'none'
})
return
}
wx.showLoading({
title: '提交中...',
})
// https://www.yuque.com/apifm/nu0f75/eckfsmlf1yhi5fn4
const res = await WXAPI.refundApplySetBackLogistics({
token: wx.getStorageSync('token'),
orderId: this.data.curRufund.baseInfo.orderId,
applyId: this.data.curRufund.baseInfo.id,
shipperName: shipperName.trim(),
trackingNumber: trackingNumber.trim()
})
wx.hideLoading()
if (res.code == 0) {
wx.showToast({
title: '提交成功',
icon: 'success'
})
// 关闭弹窗
this.closeLogisticsDialog()
// 刷新售后详情
this.orderDetail()
// 关闭详情弹窗
this.popClose()
} else {
wx.showToast({
title: res.msg || '提交失败',
icon: 'none'
})
}
}
});
================================================
FILE: pages/order/refundApply.json
================================================
{
"navigationBarTitleText": "申请售后"
}
================================================
FILE: pages/order/refundApply.wxml
================================================
我的售后
{{ item.goodInfo.goodsName }}
x{{ item.baseInfo.number }}
¥{{ item.baseInfo.amount }}
申请时间:{{ item.baseInfo.dateAdd }}
{{ item.baseInfo.statusStr }}
›
选择需要售后的商品
{{ item.goodsName }}
该商品不支持售后
商品信息
{{ curGoods.goodsName }}
¥{{ curGoods.amount }}
退货数量
售后类型
{{ item.name }}
货物状态
{{ item.name }}
售后原因
{{ item }}
售后说明
(选填)
上传凭证
(选填,最多9张)
💡
请填写您寄回商品的快递信息
快递公司
快递单号
================================================
FILE: pages/order/refundApply.wxss
================================================
/* 页面容器 */
page {
background: #F5F5F5;
}
.refund-container {
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 通用标题样式 */
.section-title {
display: flex;
align-items: center;
padding: 32rpx 32rpx 24rpx;
position: relative;
}
.title-line {
width: 6rpx;
height: 32rpx;
background: linear-gradient(180deg, #E4393C 0%, #FF6B6B 100%);
border-radius: 3rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
letter-spacing: 0.5rpx;
}
.title-tip {
font-size: 24rpx;
color: #999;
margin-left: 8rpx;
}
/* 通用卡片样式 */
.section-card {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
/* 售后历史记录 */
.refund-history {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.history-list {
padding: 0 32rpx 24rpx;
}
.history-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.history-item:last-child {
border-bottom: none;
}
.history-goods {
display: flex;
flex: 1;
margin-right: 24rpx;
}
.goods-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
background: #F5F5F5;
flex-shrink: 0;
}
.goods-info {
flex: 1;
margin-left: 20rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.goods-name {
font-size: 28rpx;
color: #333;
line-height: 40rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.goods-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 8rpx;
}
.goods-num {
font-size: 24rpx;
color: #999;
}
.goods-price {
font-size: 28rpx;
color: #E4393C;
font-weight: 600;
}
.apply-time {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.history-status {
display: flex;
align-items: center;
flex-shrink: 0;
}
.status-text {
font-size: 26rpx;
color: #E4393C;
font-weight: 500;
}
.arrow-icon {
font-size: 48rpx;
color: #DCDCDC;
margin-left: 8rpx;
line-height: 1;
}
/* 商品列表 */
.goods-list {
padding: 0 32rpx 24rpx;
}
.goods-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.goods-item:last-child {
border-bottom: none;
}
.goods-item.disabled {
opacity: 0.5;
}
.goods-content {
flex: 1;
margin-right: 24rpx;
}
.goods-name-text {
font-size: 28rpx;
color: #333;
line-height: 40rpx;
}
.not-support {
font-size: 24rpx;
color: #FF6B6B;
margin-top: 8rpx;
}
/* 商品预览 */
.goods-preview {
display: flex;
padding: 24rpx 32rpx;
background: linear-gradient(135deg, #FFF9F9 0%, #FFFFFF 100%);
border-bottom: 1rpx solid #F0F0F0;
}
.preview-image {
width: 140rpx;
height: 140rpx;
border-radius: 12rpx;
background: #F5F5F5;
flex-shrink: 0;
}
.preview-info {
flex: 1;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
}
.preview-name {
font-size: 30rpx;
color: #333;
font-weight: 500;
line-height: 42rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.preview-price {
font-size: 36rpx;
color: #E4393C;
font-weight: 600;
margin-top: 16rpx;
}
.preview-price::before {
content: '¥';
font-size: 28rpx;
}
/* 数量选择器 */
.quantity-selector {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
}
.selector-label {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
/* 选项列表 */
.option-list,
.reason-list {
padding: 0 32rpx 24rpx;
}
.option-item,
.reason-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.option-item:last-child,
.reason-item:last-child {
border-bottom: none;
}
.option-text,
.reason-text {
font-size: 28rpx;
color: #333;
flex: 1;
margin-right: 24rpx;
}
/* 备注输入框 */
.remark-box {
padding: 24rpx 32rpx 32rpx;
}
.remark-input {
width: 100%;
min-height: 180rpx;
padding: 24rpx;
background: #F8F8F8;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
line-height: 42rpx;
box-sizing: border-box;
}
.remark-placeholder {
color: #BFBFBF;
}
/* 上传区域 */
.upload-box {
padding: 24rpx 32rpx 32rpx;
}
/* 提交按钮 */
.submit-box {
padding: 40rpx 24rpx 0;
}
.submit-btn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
border-radius: 48rpx;
font-size: 32rpx;
color: #fff;
font-weight: 600;
border: none;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
letter-spacing: 2rpx;
}
.submit-btn::after {
border: none;
}
/* 底部安全区 */
.safe-area {
height: 40rpx;
}
/* ========== 弹窗样式 ========== */
.popup-container {
background: #F5F5F5;
padding-bottom: 40rpx;
}
/* 弹窗头部 */
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
background: #fff;
position: sticky;
top: 0;
z-index: 10;
}
.popup-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.popup-close {
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
color: #999;
background: #F5F5F5;
border-radius: 50%;
}
/* 弹窗商品信息 */
.popup-goods {
display: flex;
padding: 24rpx 32rpx;
background: #fff;
margin-top: 2rpx;
}
.popup-goods-image {
width: 140rpx;
height: 140rpx;
border-radius: 12rpx;
background: #F5F5F5;
flex-shrink: 0;
}
.popup-goods-info {
flex: 1;
margin-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: center;
}
.popup-goods-name {
font-size: 30rpx;
color: #333;
font-weight: 500;
line-height: 42rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.popup-goods-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
}
.popup-goods-num {
font-size: 26rpx;
color: #999;
}
.popup-goods-price {
font-size: 36rpx;
color: #E4393C;
font-weight: 600;
}
/* 状态提示 */
.popup-notice {
display: flex;
align-items: center;
padding: 24rpx 32rpx;
margin: 24rpx 24rpx 0;
border-radius: 12rpx;
background: #FFF9F0;
border-left: 6rpx solid #FF9800;
}
.popup-notice.info {
background: #E8F4FF;
border-left-color: #1890FF;
}
.popup-notice.success {
background: #F0F9F0;
border-left-color: #52C41A;
}
.popup-notice.error {
background: #FFF1F0;
border-left-color: #FF4D4F;
}
.notice-icon {
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
margin-right: 16rpx;
}
.notice-text {
flex: 1;
font-size: 26rpx;
color: #666;
line-height: 38rpx;
}
/* 详细信息 */
.popup-details {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 12rpx;
padding: 16rpx 32rpx;
}
.detail-item {
display: flex;
padding: 24rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.detail-item:last-child {
border-bottom: none;
}
.detail-label {
width: 160rpx;
font-size: 28rpx;
color: #999;
flex-shrink: 0;
}
.detail-value {
flex: 1;
font-size: 28rpx;
color: #333;
text-align: right;
}
.detail-value.remark {
text-align: left;
line-height: 40rpx;
}
/* 举证照片 */
.popup-photos {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 12rpx;
padding: 24rpx 32rpx 32rpx;
}
.photos-title {
font-size: 28rpx;
color: #333;
font-weight: 500;
margin-bottom: 20rpx;
}
.photos-grid {
display: flex;
flex-wrap: wrap;
margin: -8rpx;
}
.photo-item {
width: 200rpx;
height: 200rpx;
border-radius: 12rpx;
background: #F5F5F5;
margin: 8rpx;
}
/* 底部操作 */
.popup-actions {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 12rpx;
padding: 24rpx 32rpx;
}
.action-service {
display: flex;
align-items: center;
justify-content: center;
padding: 24rpx;
background: #F8F8F8;
border-radius: 12rpx;
margin-bottom: 20rpx;
}
.service-icon {
font-size: 36rpx;
margin-right: 12rpx;
}
.service-text {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.action-btn-box {
display: flex;
}
.action-btn {
flex: 1;
height: 88rpx;
line-height: 88rpx;
text-align: center;
border-radius: 44rpx;
font-size: 30rpx;
font-weight: 500;
border: none;
}
.action-btn::after {
border: none;
}
.action-btn.cancel {
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
color: #fff;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
}
.action-btn.disabled {
background: #F5F5F5;
color: #BFBFBF;
}
.action-btn.disabled.success {
background: #F0F9F0;
color: #52C41A;
}
/* ========== 寄回地址卡片 ========== */
.back-address-card {
background: #fff;
margin: 24rpx 24rpx 0;
border-radius: 12rpx;
overflow: hidden;
}
.address-header {
display: flex;
align-items: center;
padding: 24rpx 32rpx;
background: linear-gradient(135deg, #FFF9F9 0%, #FFFFFF 100%);
border-bottom: 1rpx solid #F0F0F0;
}
.header-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.header-title {
font-size: 30rpx;
color: #333;
font-weight: 600;
}
.address-content {
padding: 24rpx 32rpx;
}
.address-row {
display: flex;
margin-bottom: 20rpx;
}
.address-row:last-child {
margin-bottom: 0;
}
.address-row.full {
flex-direction: column;
}
.address-label {
font-size: 28rpx;
color: #999;
min-width: 140rpx;
flex-shrink: 0;
}
.address-row.full .address-label {
margin-bottom: 12rpx;
}
.address-text {
font-size: 28rpx;
color: #333;
line-height: 40rpx;
flex: 1;
}
/* 填写快递按钮 */
.logistics-action {
padding: 0 32rpx 32rpx;
}
.fill-logistics-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
border-radius: 44rpx;
font-size: 30rpx;
color: #fff;
font-weight: 600;
border: none;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
}
.fill-logistics-btn::after {
border: none;
}
/* 已填写快递信息 */
.logistics-filled {
padding: 0 32rpx 32rpx;
}
.filled-header {
display: flex;
align-items: center;
padding: 20rpx 24rpx;
background: #F0F9F0;
border-radius: 12rpx;
margin-bottom: 20rpx;
}
.filled-icon {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
background: #52C41A;
color: #fff;
border-radius: 50%;
font-size: 24rpx;
margin-right: 12rpx;
}
.filled-title {
font-size: 28rpx;
color: #52C41A;
font-weight: 600;
}
.filled-content {
padding: 20rpx 24rpx;
background: #F8F8F8;
border-radius: 12rpx;
}
.filled-row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.filled-row:last-child {
margin-bottom: 0;
}
.filled-label {
font-size: 26rpx;
color: #999;
min-width: 140rpx;
}
.filled-value {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
/* ========== 快递信息输入弹窗 ========== */
.logistics-dialog {
background: #fff;
border-radius: 24rpx;
overflow: hidden;
}
.dialog-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
border-bottom: 1rpx solid #F0F0F0;
}
.dialog-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.dialog-close {
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 40rpx;
color: #999;
background: #F5F5F5;
border-radius: 50%;
}
.dialog-content {
padding: 32rpx;
}
.dialog-tip {
display: flex;
align-items: center;
padding: 20rpx 24rpx;
background: #FFF9F0;
border-radius: 12rpx;
margin-bottom: 32rpx;
border-left: 6rpx solid #FF9800;
}
.tip-icon {
font-size: 32rpx;
margin-right: 12rpx;
}
.tip-text {
font-size: 26rpx;
color: #666;
line-height: 38rpx;
}
.input-group {
margin-bottom: 32rpx;
}
.input-group:last-child {
margin-bottom: 0;
}
.input-label {
font-size: 28rpx;
color: #333;
font-weight: 500;
margin-bottom: 16rpx;
}
.input-label::before {
content: '*';
color: #E4393C;
margin-right: 4rpx;
}
.input-field {
width: 100%;
height: 88rpx;
padding: 0 24rpx;
background: #F8F8F8;
border-radius: 12rpx;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
}
.input-placeholder {
color: #BFBFBF;
}
.dialog-actions {
display: flex;
padding: 24rpx 32rpx 32rpx;
gap: 24rpx;
}
.dialog-btn {
flex: 1;
height: 88rpx;
line-height: 88rpx;
text-align: center;
border-radius: 44rpx;
font-size: 30rpx;
font-weight: 500;
border: none;
}
.dialog-btn::after {
border: none;
}
.cancel-btn {
background: #F5F5F5;
color: #666;
}
.confirm-btn {
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
color: #fff;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.3);
}
================================================
FILE: pages/order-details/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data:{
orderId:0,
goodsList:[]
},
onLoad:function(e){
// e.id = e.sfsdffd
// e.payOrderNo = 'ZF2408290780106421'
this.setData({
orderId: e.id,
payOrderNo: e.payOrderNo,
})
if (e.payOrderNo) {
this.payLogs()
}
},
onShow() {
this.orderDetail()
},
async payLogs() {
wx.showLoading({
title: '',
})
const res = await WXAPI.payLogs({
token: wx.getStorageSync('token'),
orderNo: this.data.payOrderNo
})
wx.hideLoading()
if (res.code != 0) {
wx.showModal({
content: res.msg,
showCancel: false
})
return
}
const nextAction = res.data[0].nextAction
if(!nextAction) {
wx.navigateTo({
url: '/pages/asset/index',
})
return
}
const _nextAction = JSON.parse(nextAction)
if (_nextAction.type != 0) {
wx.navigateTo({
url: '/pages/asset/index',
})
return
}
this.setData({
orderId: _nextAction.id,
})
this.orderDetail()
},
async orderDetail() {
if (!this.data.orderId) {
return
}
wx.showLoading({
title: '',
})
const res = await WXAPI.orderDetail(wx.getStorageSync('token'), this.data.orderId)
wx.hideLoading()
if (res.code != 0) {
wx.showModal({
content: res.msg,
showCancel: false
})
return
}
// 绘制核销码
if (res.data.orderInfo.hxNumber && res.data.orderInfo.status > 0 && res.data.orderInfo.status < 3) {
this.wxaQrcode(res.data.orderInfo.hxNumber)
}
// 子快递单信息
if (res.data.orderLogisticsShippers) {
res.data.orderLogisticsShippers.forEach(ele => {
if (ele.traces) {
ele.tracesArray = JSON.parse (ele.traces)
if (ele.tracesArray && ele.tracesArray.length > 0) {
ele.tracesLast = ele.tracesArray[ele.tracesArray.length - 1].AcceptStation + '\n' + ele.tracesArray[ele.tracesArray.length - 1].AcceptTime
}
}
})
}
let iotControl = false
res.data.goods.forEach(ele => {
if (ele.iotControl) {
iotControl = true
}
})
if (iotControl) {
// 读取IoT设备列表
this._shopIotDevices()
}
let orderStores = null
if (res.data.orderStores) {
orderStores = res.data.orderStores.filter(ele => ele.type == 2)
}
if (!res.data.extJson || Object.keys(res.data.extJson).length == 0) {
delete res.data.extJson
}
this.setData({
orderDetail: res.data,
orderStores
})
},
wuliuDetailsTap:function(e){
var orderId = e.currentTarget.dataset.id;
wx.navigateTo({
url: "/pages/wuliu/index?id=" + orderId
})
},
confirmBtnTap:function(e){
let that = this;
let orderId = this.data.orderId;
wx.showModal({
title: '确认您已收到商品?',
content: '',
success: function(res) {
if (res.confirm) {
WXAPI.orderDelivery(wx.getStorageSync('token'), orderId).then(function (res) {
if (res.code == 0) {
that.orderDetail()
}
})
}
}
})
},
async submitReputation(e) {
let that = this;
let postJsonString = {};
postJsonString.token = wx.getStorageSync('token');
postJsonString.orderId = this.data.orderId;
let reputations = [];
let i = 0;
while (e.detail.value["orderGoodsId" + i]) {
let orderGoodsId = e.detail.value["orderGoodsId" + i];
let goodReputation = e.detail.value["goodReputation" + i];
const goodReputationNumber = goodReputation
let goodReputationRemark = e.detail.value["goodReputationRemark" + i];
if (!goodReputation) {
goodReputation = 0
} else if(goodReputation <= 1) {
goodReputation = 0
} else if(goodReputation <= 4) {
goodReputation = 1
} else {
goodReputation = 2
}
let reputations_json = {};
reputations_json.id = orderGoodsId;
reputations_json.reputation = goodReputation;
reputations_json.reputationNumber = goodReputationNumber
reputations_json.remark = goodReputationRemark;
if (this.data.picsList && this.data.picsList[i] && this.data.picsList[i].length > 0) {
reputations_json.pics = []
for (let index = 0; index < this.data.picsList[i].length; index++) {
const pic = this.data.picsList[i][index];
const res = await WXAPI.uploadFileV2(wx.getStorageSync('token'), pic.url)
if (res.code == 0) {
reputations_json.pics.push(res.data.url)
}
}
}
reputations.push(reputations_json);
i++;
}
postJsonString.reputations = reputations;
WXAPI.orderReputation({
postJsonString: JSON.stringify(postJsonString)
}).then(function (res) {
if (res.code == 0) {
that.orderDetail()
}
})
},
afterPicRead(e) {
const idx = e.currentTarget.dataset.idx
let picsList = this.data.picsList
if (!picsList) {
picsList = []
for (let index = 0; index < this.data.orderDetail.goods.length; index++) {
picsList[index] = []
}
}
picsList[idx] = picsList[idx].concat(e.detail.file)
this.setData({
picsList
})
},
afterPicDel(e) {
const idx = e.currentTarget.dataset.idx
let picsList = this.data.picsList
picsList[idx].splice(e.detail.index, 1)
this.setData({
picsList
})
},
async wxaQrcode(hxNumber) {
// https://www.yuque.com/apifm/nu0f75/ak40es
const accountInfo = wx.getAccountInfoSync()
const envVersion = accountInfo.miniProgram.envVersion
const res = await WXAPI.wxaQrcode({
scene: hxNumber,
page: 'pages/order-details/scan-result',
autoColor: true,
expireHours: 1,
env_version: envVersion,
check_path: envVersion == 'release' ? true : false,
})
if (res.code != 0) {
wx.showModal({
content: res.msg,
showCancel: false
})
return
}
this.setData({
hxNumberQrcode: res.data
})
},
async _shopIotDevices() {
// https://www.yuque.com/apifm/nu0f75/ibg4icu15di25hfc
const res = await WXAPI.shopIotDevices({
token: wx.getStorageSync('token'),
orderId: this.data.orderId
})
if (res.code == 0) {
this.setData({
shopIotDevices: res.data
})
}
},
async shopIotCmds(e) {
const idx = e.target.dataset.idx
const item = this.data.shopIotDevices[idx]
// https://www.yuque.com/apifm/nu0f75/rek5dwng8b9cdoko
const res = await WXAPI.shopIotCmds({
token: wx.getStorageSync('token'),
orderId: this.data.orderId,
topic: item.topic
})
if (res.code != 0) {
wx.showModal({
content: res.msg
})
return
}
this.setData({
cmdList: res.data,
cmdListShow: true
})
},
cmdClose() {
this.setData({ cmdListShow: false });
},
async cmdSelect(event) {
// https://www.yuque.com/apifm/nu0f75/uq495hlq3ho5kw4t
console.log(event.detail);
const res = await WXAPI.shopIotExecute({
token: wx.getStorageSync('token'),
orderId: this.data.orderId,
topic: event.detail.topic,
cmdId: event.detail.id,
})
if (res.code != 0) {
wx.showModal({
content: res.msg
})
} else {
wx.showToast({
title: '已发送',
})
}
},
})
================================================
FILE: pages/order-details/index.json
================================================
{
"navigationBarTitleText": "订单详情"
}
================================================
FILE: pages/order-details/index.wxml
================================================
物流信息
{{orderDetail.logistics.linkMan}} {{orderDetail.logistics.mobile}}
{{orderDetail.logistics.provinceStr}} {{orderDetail.logistics.cityStr}} {{orderDetail.logistics.areaStr}} {{orderDetail.logistics.address}}
核销二维码
出示给店员扫码或长按保存
商品信息
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId
} else {
return '/pages/goods-details/index?id=' + item.goodsId
}
}
}
日期详情
{{ item.remark }} ×{{ item.stores }}
{{ item.day }}
优惠券
优惠券
{{item.coupon}}
其他信息
✦
{{ key }}
{{ item }}
订单金额
商品金额
¥ {{orderDetail.orderInfo.amount}}
运费
¥ {{orderDetail.orderInfo.amountLogistics}}
{{ item.name }}
¥ {{ item.amount }}
应付总额
¥ {{orderDetail.orderInfo.amountReal}}
订单记录
{{ item.typeStr }}
{{ item.dateAdd }}
设备控制
{{ item.name }}
控制
================================================
FILE: pages/order-details/index.wxss
================================================
/* 全局样式 */
page {
min-height: 100%;
background: linear-gradient(to bottom, #f5f7fa 0%, #e8ecf1 100%);
}
.container {
min-height: 100%;
padding: 20rpx 24rpx;
padding-bottom: 40rpx;
}
/* 卡片通用样式 */
.card-section {
width: 100%;
margin-bottom: 24rpx;
background: #ffffff;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.card-title {
display: flex;
align-items: center;
padding: 32rpx 32rpx 24rpx;
font-size: 32rpx;
font-weight: 600;
color: #1a1a1a;
}
.title-line {
width: 6rpx;
height: 32rpx;
background: linear-gradient(to bottom, #ff6b6b, #ee5a52);
border-radius: 3rpx;
margin-right: 16rpx;
}
/* 订单状态卡片 */
.status-card {
width: 90%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 24rpx;
padding: 40rpx 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.3);
}
.status-header {
display: flex;
align-items: center;
}
.status-icon-wrap {
width: 96rpx;
height: 96rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 24rpx;
backdrop-filter: blur(10rpx);
}
.status-icon {
width: 64rpx;
height: 64rpx;
}
.status-info {
flex: 1;
}
.status-title {
font-size: 36rpx;
font-weight: 600;
color: #ffffff;
margin-bottom: 12rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.order-number-text {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.85);
letter-spacing: 0.5rpx;
}
/* 物流信息卡片 */
.logistics-card {
margin: 0 32rpx 24rpx;
padding: 28rpx;
background: linear-gradient(135deg, #f6f8fc 0%, #fafbfd 100%);
border-radius: 16rpx;
border: 1rpx solid #e8ecf1;
}
.logistics-header {
display: flex;
align-items: flex-start;
}
.logistics-icon {
width: 48rpx;
height: 48rpx;
margin-right: 20rpx;
flex-shrink: 0;
}
.icon-img {
width: 100%;
height: 100%;
}
.logistics-info {
flex: 1;
min-width: 0;
}
.tracking-number {
font-size: 28rpx;
font-weight: 500;
color: #2c3e50;
margin-bottom: 12rpx;
}
.logistics-status {
font-size: 26rpx;
color: #5a6c7d;
line-height: 40rpx;
margin-bottom: 8rpx;
}
.logistics-time {
font-size: 24rpx;
color: #95a5a6;
}
.arrow-icon {
width: 32rpx;
height: 32rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 16rpx;
flex-shrink: 0;
}
.multi-logistics {
margin: 0 32rpx 24rpx;
border-radius: 16rpx;
overflow: hidden;
}
/* 收货地址卡片 */
.address-card {
margin: 0 32rpx 32rpx;
padding: 28rpx;
background: #fff;
border-radius: 16rpx;
border: 2rpx dashed #e8ecf1;
display: flex;
align-items: flex-start;
}
.address-icon {
width: 40rpx;
height: 40rpx;
margin-right: 20rpx;
flex-shrink: 0;
}
.address-info {
flex: 1;
min-width: 0;
}
.address-name {
font-size: 30rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 16rpx;
}
.address-phone {
font-weight: 400;
color: #667eea;
margin-left: 16rpx;
}
.address-detail {
font-size: 26rpx;
color: #5a6c7d;
line-height: 40rpx;
}
/* 核销码卡片 */
.hx-section {
background: linear-gradient(135deg, #ffeaa7 0%, #fdcb6e 100%);
}
.hx-card {
padding: 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.hx-tip {
font-size: 28rpx;
color: #2d3436;
margin-bottom: 24rpx;
font-weight: 500;
}
.hx-qrcode {
width: 400rpx;
height: 400rpx;
border-radius: 16rpx;
background: #fff;
padding: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
}
/* 商品信息卡片 */
.goods-section {
padding-bottom: 0;
}
.goods-card {
padding: 0 32rpx;
}
.reputation-group {
margin-top: 24rpx;
border-radius: 16rpx;
overflow: hidden;
}
.action-btn-wrap {
padding: 32rpx;
display: flex;
justify-content: flex-end;
}
.action-btn {
border: none;
border-radius: 48rpx;
font-size: 28rpx;
font-weight: 500;
padding: 0 56rpx;
height: 80rpx;
line-height: 80rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
}
.primary-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
}
/* 信息卡片通用样式 */
.info-card {
padding: 16rpx 0 24rpx;
width: 100%;
box-sizing: border-box;
}
.info-row {
display: flex;
justify-content: space-between;
align-items: flex-start;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f0f2f5;
min-height: 60rpx;
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
font-size: 28rpx;
color: #7f8c8d;
font-weight: 400;
flex-shrink: 0;
margin-right: 32rpx;
line-height: 40rpx;
max-width: 240rpx;
}
.info-value {
font-size: 28rpx;
color: #2c3e50;
font-weight: 500;
text-align: right;
word-break: break-all;
flex: 1;
line-height: 40rpx;
}
/* 其他信息特殊样式 */
.ext-json-section {
background: linear-gradient(135deg, #fff9f5 0%, #ffffff 100%);
border-left: 4rpx solid #ff6b6b;
}
.ext-info-card {
background: #fff;
border-radius: 0;
margin: 0;
padding: 8rpx 0 24rpx;
width: 100%;
}
.ext-info-row {
border-bottom: none !important;
background: #fff;
margin: 0 32rpx;
padding: 20rpx 24rpx;
border-radius: 12rpx;
margin-bottom: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(255, 107, 107, 0.08);
border: 1rpx solid #ffe8e8;
display: flex;
justify-content: left;
align-items: center;
gap: 16rpx;
}
.ext-info-row:last-child {
margin-bottom: 0;
}
.ext-label {
color: #e74c3c;
font-weight: 600;
font-size: 24rpx;
padding: 8rpx 16rpx;
background: linear-gradient(135deg, #ffe0e0 0%, #fff0f0 100%);
border-radius: 8rpx;
max-width: fit-content;
line-height: 32rpx;
display: flex;
align-items: center;
gap: 8rpx;
margin-right: 0 !important;
text-align: left;
}
.label-icon {
font-size: 20rpx;
color: #ff6b6b;
line-height: 1;
}
.ext-value {
color: #2c3e50;
font-weight: 600;
font-size: 30rpx;
padding: 12rpx 20rpx;
border-radius: 8rpx;
line-height: 44rpx;
text-align: left;
word-break: break-all;
margin-right: 0 !important;
flex: none;
width: auto;
}
/* 优惠券卡片 */
.coupon-card {
padding: 24rpx 32rpx 32rpx;
}
.coupon-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
background: linear-gradient(135deg, #fff3e0 0%, #ffe8cc 100%);
border-radius: 12rpx;
margin-bottom: 16rpx;
}
.coupon-item:last-child {
margin-bottom: 0;
}
.coupon-label {
font-size: 28rpx;
color: #e67e22;
font-weight: 500;
}
.coupon-value {
font-size: 28rpx;
color: #d35400;
font-weight: 600;
}
.coupon-image {
width: 100%;
border-radius: 12rpx;
margin-bottom: 16rpx;
}
.coupon-image:last-child {
margin-bottom: 0;
}
/* 订单金额卡片 */
.amount-section {
background: #ffffff;
}
.amount-card {
padding: 16rpx 0 24rpx;
width: 100%;
box-sizing: border-box;
}
.amount-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f5f7fa;
min-height: 60rpx;
}
.amount-row:last-child {
border-bottom: none;
}
.amount-label {
font-size: 28rpx;
color: #7f8c8d;
font-weight: 400;
line-height: 40rpx;
}
.amount-value {
font-size: 30rpx;
color: #2c3e50;
font-weight: 600;
line-height: 40rpx;
}
.total-row {
margin: 16rpx 32rpx 0;
padding: 28rpx 32rpx;
background: linear-gradient(135deg, #fff4f4 0%, #ffe8e8 100%);
border-radius: 16rpx;
border-bottom: none;
box-shadow: 0 4rpx 12rpx rgba(231, 76, 60, 0.1);
}
.total-label {
font-size: 32rpx;
font-weight: 700;
color: #e74c3c;
letter-spacing: 1rpx;
}
.total-value {
font-size: 40rpx;
font-weight: 700;
color: #e74c3c;
letter-spacing: 1rpx;
}
/* 订单记录卡片 */
.logs-card {
padding: 24rpx 32rpx 32rpx;
}
.timeline {
position: relative;
padding-left: 40rpx;
}
.timeline-item {
position: relative;
padding-bottom: 48rpx;
}
.timeline-item:last-child {
padding-bottom: 0;
}
.timeline-dot {
position: absolute;
left: -40rpx;
top: 8rpx;
width: 24rpx;
height: 24rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
border: 4rpx solid #ffffff;
box-shadow: 0 0 0 4rpx #f0f2f5;
z-index: 2;
}
.timeline-line {
position: absolute;
left: -28rpx;
top: 32rpx;
bottom: -32rpx;
width: 2rpx;
background: linear-gradient(to bottom, #e8ecf1 0%, #f5f7fa 100%);
z-index: 1;
}
.timeline-content {
background: linear-gradient(135deg, #f8f9fc 0%, #ffffff 100%);
border-radius: 12rpx;
padding: 24rpx;
border: 1rpx solid #e8ecf1;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
}
.log-operation {
font-size: 30rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 12rpx;
line-height: 42rpx;
}
.log-time {
font-size: 24rpx;
color: #95a5a6;
line-height: 36rpx;
display: flex;
align-items: center;
}
.log-time::before {
content: '🕐';
margin-right: 8rpx;
font-size: 22rpx;
}
/* 设备控制卡片 */
.iot-card {
padding: 16rpx 32rpx 32rpx;
}
.iot-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 28rpx 24rpx;
background: linear-gradient(135deg, #e3f2fd 0%, #e1f5fe 100%);
border-radius: 12rpx;
margin-bottom: 16rpx;
}
.iot-item:last-child {
margin-bottom: 0;
}
.iot-name {
font-size: 28rpx;
color: #1976d2;
font-weight: 500;
}
.iot-control {
display: flex;
align-items: center;
font-size: 26rpx;
color: #1565c0;
}
.iot-control text {
margin-right: 8rpx;
}
/* 底部安全区域 */
.bottom-safe-area {
height: 40rpx;
}
/* 适配暗色模式 */
@media (prefers-color-scheme: dark) {
page {
background: linear-gradient(to bottom, #1a1a1a 0%, #2d2d2d 100%);
}
.card-section {
background: #2d2d2d;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.3);
}
.card-title {
color: #f0f0f0;
}
}
/* 动画效果 */
.card-section {
animation: fadeInUp 0.4s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 确保按钮样式正确 */
button::after {
border: none;
}
================================================
FILE: pages/order-details/scan-result.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
apiOK: false,
},
onLoad: function (e) {
// e.hxNumber = '2307150981053363'
// 读取小程序码中的核销码
console.log('e', e);
if (e && e.scene) {
const scene = decodeURIComponent(e.scene)
if (scene) {
e.hxNumber = scene
}
}
this.setData({
hxNumber: e.hxNumber
})
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.orderDetail()
} else {
getApp().loginOK = () => {
this.orderDetail()
}
}
})
},
onShow() {
},
async orderDetail() {
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/qlzy3q
const resConfig = await WXAPI.queryConfigValue('order_hx_uids')
const res = await WXAPI.orderDetail(wx.getStorageSync('token'), '', this.data.hxNumber)
wx.hideLoading()
if (resConfig.code != 0) {
wx.showModal({
content: resConfig.msg,
showCancel: false
})
return;
}
if (res.code != 0) {
wx.showModal({
content: res.msg,
showCancel: false
})
return;
}
const order_hx_uids = resConfig.data
const uid = wx.getStorageSync('uid')
if (order_hx_uids.indexOf(uid) != -1) {
this.setData({
apiOK: true,
canHX: true,
orderDetail: res.data
})
} else {
this.setData({
apiOK: true,
orderDetail: res.data
})
}
},
wuliuDetailsTap: function (e) {
var orderId = e.currentTarget.dataset.id;
wx.navigateTo({
url: "/pages/wuliu/index?id=" + orderId
})
},
async doneHx(){
wx.showLoading({
title: '处理中...',
})
const res = await WXAPI.orderHXV2({
token: wx.getStorageSync('token'),
hxNumber: this.data.hxNumber
})
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '核销完成',
icon: 'none'
})
this.orderDetail()
}
},
})
================================================
FILE: pages/order-details/scan-result.json
================================================
{
"navigationBarTitleText": "订单详情"
}
================================================
FILE: pages/order-details/scan-result.wxml
================================================
{{orderDetail.orderInfo.statusStr}}
请于11时59分59秒内付款,超时订单将自动关闭
快递单号:{{orderDetail.logistics.trackingNumber}}
{{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptStation}}
{{orderDetail.logisticsTraces[orderDetail.logisticsTraces.length-1].AcceptTime}}
快递单号:{{orderDetail.logistics.trackingNumber}}
暂无物流信息
{{orderDetail.logistics.linkMan}} {{orderDetail.logistics.mobile}}
{{orderDetail.logistics.provinceStr}} {{orderDetail.logistics.cityStr}} {{orderDetail.logistics.areaStr}} {{orderDetail.logistics.address}}
商品信息
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId
} else {
return '/pages/goods-details/index?id=' + item.goodsId
}
}
}
{{item.goodsName}}
¥ {{item.amount}}
{{item.property}}
x {{item.number}}
优惠券
{{item.coupon}}
暂无核销权限
{{ orderDetail.orderInfo.statusStr }}
确认核销
================================================
FILE: pages/order-details/scan-result.wxss
================================================
page{
min-height: 100%;
background-color: #F2f2f2;
}
.container{
min-height: 100%;
overflow: hidden;
overflow-y: hidden;
}
.sec-wrap{
background-color: #fff;
margin-top: 20rpx;
}
.bottom-fiexd{
position: fixed;
bottom: 0;
left: 0;
}
.sec-wrap .order-status{
width: 720rpx;
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
height: 140rpx;
display: flex;
align-items: center;
}
.order-status .icon-box{
width: 80rpx;
height: 80rpx;
overflow: hidden;
margin-right: 30rpx;
}
.order-status .icon-box .icon{
width: 80rpx;
height: 80rpx;
}
.order-status .right-text{
width: 580rpx;
overflow: hidden;
}
.order-status .right-text .status{
font-size:28rpx;
color:#000;
margin-bottom: 10rpx;
}
.order-status .right-text .red{
color:#e64340;
}
.order-status .right-text .des{
font-size:24rpx;
color:#999;
}
.address-sec{
width: 720rpx;
margin-left: 30rpx;
display: flex;
align-items: center;
padding: 30rpx 0;
}
.address-sec .icon-box{
width: 30rpx;
align-self: flex-start;
overflow: hidden;
margin-right: 35rpx;
}
.address-sec .icon-box .icon{
width: 30rpx;
height: 30rpx;
}
.address-sec .right-box{
width: 620rpx;
}
.address-sec .right-box .name-tel{
font-size:28rpx;
color:#000000;
margin-bottom: 20rpx;
}
.address-sec .right-box .text{
font-size:24rpx;
color:#888888;
line-height:36rpx;
height: 72rpx;
overflow: hidden;
}
.wuliu-box{
width: 720rpx;
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
display: flex;
align-items: center;
padding: 30rpx 0;
}
.wuliu-box .icon-box {
width: 40rpx;
height: 40rpx;
overflow: hidden;
margin-right: 31rpx;
align-self: flex-start;
}
.wuliu-box .icon-box .icon{
width: 40rpx;
height: 40rpx;
}
.wuliu-box .arrow-right{
width: 15rpx;
height: 24rpx;
}
.wuliu-box .arrow-right .arrow{
width: 15rpx;
height: 24rpx;
}
.wuliu-box .right-text{
width: 575rpx;
margin-right: 30rpx;
}
.wuliu-box .right-text .order-number{
font-size:28rpx;
color:#000;
margin-bottom: 14rpx;
}
.wuliu-box .right-text .wuliu-text,
.wuliu-box .right-text .wuliu-date{
font-size:24rpx;
color:#888888;
line-height:36rpx;
}
.goods-list{
width:100%;
background-color: #fff;
margin-bottom: 20rpx;
margin-top: 20rpx;
}
.goods-list .list-title{
font-size: 28rpx;
color: #000;
padding: 30rpx 0 25rpx 30rpx;
}
.goods-list .a-goods{
width: 720rpx;
margin-left: 30rpx;
display: flex;
/*justify-content: space-between;*/
border-top: 1px solid #eee;
padding: 30rpx 30rpx 30rpx 0;
}
.goods-list .a-goods .img-box{
width: 160rpx;
height:160rpx;
overflow: hidden;
margin-right: 20rpx;
background-color: #d8d8d8;
}
.goods-list .img-box .img{
width: 160rpx;
height:160rpx;
}
.goods-list .a-goods .text-box{
width: 510rpx;
box-sizing: border-box;
padding-top: 10rpx;
}
.goods-list .btn-row{
width: 720rpx;
margin-left: 30rpx;
border-top: 1rpx solid #eee;
}
.confirm-btn{
background:#ffffff;
border:1rpx solid #e64340;
border-radius:6rpx;
width:164rpx;
height:60rpx;
line-height: 60rpx;
margin: 20rpx 30rpx 20rpx auto;
font-size:26rpx;
color:#e64340;
text-align:center;
}
.a-goods .text-box .arow{
display: flex;
justify-content: space-between;
align-items: center;
}
.a-goods .text-box .arow .goods-name{
width: 360rpx;
font-size:26rpx;
height: 74rpx;
color:#000000;
line-height: 1.6;
overflow: hidden;
}
.a-goods .text-box .arow01{
margin-bottom: 30rpx;
}
.a-goods .text-box .arow .goods-price{
font-size:26rpx;
color:#000000;
align-self: flex-start;
}
.a-goods .text-box .arow .goods-label{
font-size: 26rpx;
color: #999;
}
.a-goods .text-box .arow .goods-num{
font-size: 26rpx;
color: #999;
}
.peisong-way{
width: 100%;
background-color: #fff;
margin-bottom: 20rpx;
}
.peisong-way .row-box{
width: 720rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 0;
border-bottom: 1rpx solid #eee;
margin-left: 30rpx;
}
.peisong-way .row-label{
font-size: 28rpx;
color: #000;
}
.peisong-way .right-text{
font-size: 28rpx;
color: #666;
padding-right: 30rpx;
}
.peisong-way .liuyan{
width: 510rpx;
font-size: 28rpx;
}
.goods-info{
width: 100%;
background-color: #fff;
margin-bottom: 120rpx;
padding-bottom: 24rpx;
}
.goods-info .row-box{
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 30rpx 12rpx 30rpx;
font-size: 28rpx;
color: #000;
}
.goods-info .row-box .right-text{
text-align: right;
}
.jiesuan-box{
display: flex;
justify-content: space-between;
width: 100%;
height: 100rpx;
position: fixed;
bottom: 0;
left: 0;
border-top:1px solid #eee;
background-color: #fff;
z-index: 4;
}
.jiesuan-box .to-pay-btn{
width:250rpx;
text-align: center;
height: 100%;
line-height: 100rpx;
background-color: #e64340;
font-size:32rpx;
color:#ffffff;
border-radius: 0;
}
.jiesuan-box .left-price{
display: flex;
width: 500rpx;
justify-content:flex-end;
line-height: 100rpx;
padding: 0 30rpx 0 0;
font-size:28rpx;
box-sizing: border-box;
}
.jiesuan-box .total{
color: #e64340;
text-align: right;
}
.hx-title {
text-align: center;
}
.hx-canvas {
width: 650rpx;
height: 650rpx;
margin-left: 50rpx;
}
.btn {
padding: 32rpx;
}
================================================
FILE: pages/order-list/index.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
page: 1,
tabIndex: 0,
statusType: [
{
status: 9999,
label: '全部'
},
{
status: 0,
label: '待付款'
},
{
status: 1,
label: '待发货'
},
{
status: 2,
label: '待收货'
},
{
status: 3,
label: '待评价'
},
],
status: 9999,
hasRefund: false,
badges: [0, 0, 0, 0, 0]
},
statusTap: function(e) {
const index = e.detail.index
const status = this.data.statusType[index].status
this.setData({
page: 1,
status
});
this.orderList();
},
cancelOrderTap: function(e) {
const that = this;
const orderId = e.currentTarget.dataset.id;
wx.showModal({
title: '确定要取消该订单吗?',
content: '',
success: function(res) {
if (res.confirm) {
WXAPI.orderClose(wx.getStorageSync('token'), orderId).then(function(res) {
if (res.code == 0) {
that.data.page = 1
that.orderList()
that.getOrderStatistics()
}
})
}
}
})
},
async refundApply (e) {
// 申请售后 todo 判断是去申请页面还是去查看页面
const orderId = e.currentTarget.dataset.id;
const amount = e.currentTarget.dataset.amount;
wx.navigateTo({
url: "/pages/order/refundApply?id=" + orderId
})
},
toPayTap: function(e) {
// 防止连续点击--开始
if (this.data.payButtonClicked) {
wx.showToast({
title: '休息一下~',
icon: 'none'
})
return
}
this.data.payButtonClicked = true
setTimeout(() => {
this.data.payButtonClicked = false
}, 3000) // 可自行修改时间间隔(目前是3秒内只能点击一次支付按钮)
// 防止连续点击--结束
const that = this;
const orderId = e.currentTarget.dataset.id;
let money = e.currentTarget.dataset.money;
const needScore = e.currentTarget.dataset.score;
WXAPI.userAmount(wx.getStorageSync('token')).then(function(res) {
if (res.code == 0) {
const order_pay_user_balance = wx.getStorageSync('order_pay_user_balance')
if (order_pay_user_balance != '1') {
res.data.balance = 0
}
// 增加提示框
if (res.data.score < needScore) {
wx.showToast({
title: '您的积分不足,无法支付',
icon: 'none'
})
return;
}
let _msg = '订单金额: ' + money +' 元'
if (res.data.balance > 0) {
_msg += ',可用余额为 ' + res.data.balance +' 元'
if (money - res.data.balance > 0) {
_msg += ',仍需微信支付 ' + (money - res.data.balance).toFixed(2) + ' 元'
}
}
if (needScore > 0) {
_msg += ',并扣除 ' + needScore + ' 积分'
}
money = money - res.data.balance
wx.showModal({
title: '请确认支付',
content: _msg,
confirmText: "确认支付",
cancelText: "取消支付",
success: function (res) {
console.log(res);
if (res.confirm) {
that._toPayTap(orderId, money)
} else {
console.log('用户点击取消支付')
}
}
});
} else {
wx.showModal({
title: '错误',
content: '无法获取用户资金信息',
showCancel: false
})
}
})
},
async wxSphGetpaymentparams(e) {
const orderId = e.currentTarget.dataset.id
const res = await WXAPI.wxSphGetpaymentparams(wx.getStorageSync('token'), orderId)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return;
}
// 发起支付
wx.requestPayment({
timeStamp: res.data.timeStamp,
nonceStr: res.data.nonceStr,
package: res.data.package,
signType: res.data.signType,
paySign: res.data.paySign,
fail: aaa => {
console.error(aaa)
wx.showToast({
title: '支付失败:' + aaa
})
},
success: () => {
// 提示支付成功
wx.showToast({
title: '支付成功'
})
this.orderList()
}
})
},
_toPayTap: function (orderId, money){
const _this = this
if (money <= 0) {
// 直接使用余额支付
WXAPI.orderPay(wx.getStorageSync('token'), orderId).then(function (res) {
_this.data.page = 1
_this.orderList()
_this.getOrderStatistics()
})
} else {
this.setData({
orderId,
money,
paymentShow: true,
nextAction: {
type: 0,
id: orderId
}
})
}
},
onLoad: function(options) {
if (options && options.type) {
if (options.type == 99) {
this.setData({
hasRefund: true
});
} else {
const tabIndex = this.data.statusType.findIndex(ele => {
return ele.status == options.type
})
this.setData({
status: options.type,
tabIndex
});
}
}
this.getOrderStatistics();
this.orderList();
this.setData({
sphpay_open: wx.getStorageSync('sphpay_open')
})
},
onReady: function() {
// 生命周期函数--监听页面初次渲染完成
},
getOrderStatistics() {
WXAPI.orderStatistics(wx.getStorageSync('token')).then(res => {
if (res.code == 0) {
const badges = this.data.badges;
badges[1] = res.data.count_id_no_pay
badges[2] = res.data.count_id_no_transfer
badges[3] = res.data.count_id_no_confirm
badges[4] = res.data.count_id_no_reputation
this.setData({
badges
})
}
})
},
onShow: function() {
},
onPullDownRefresh: function () {
this.data.page = 1
this.getOrderStatistics()
this.orderList()
wx.stopPullDownRefresh()
},
onReachBottom() {
this.setData({
page: this.data.page + 1
});
this.orderList()
},
async orderList(){
wx.showLoading({
title: '',
})
var postData = {
page: this.data.page,
pageSize: 20,
token: wx.getStorageSync('token')
};
if (this.data.hasRefund) {
postData.hasRefund = true
}
if (!postData.hasRefund) {
postData.status = this.data.status;
}
if (postData.status == 9999) {
postData.status = ''
}
const res = await WXAPI.orderList(postData)
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
orderList: res.data.orderList,
logisticsMap: res.data.logisticsMap,
goodsMap: res.data.goodsMap
})
} else {
this.setData({
orderList: this.data.orderList.concat(res.data.orderList),
logisticsMap: Object.assign(this.data.logisticsMap, res.data.logisticsMap),
goodsMap: Object.assign(this.data.goodsMap, res.data.goodsMap)
})
}
} else {
if (this.data.page == 1) {
this.setData({
orderList: null,
logisticsMap: {},
goodsMap: {}
})
} else {
wx.showToast({
title: '没有更多了',
icon: 'none'
})
}
}
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/order-list/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
goOrderDetail(e) {
const item = e.currentTarget.dataset.item
wx.navigateTo({
url: '/pages/order-details/index?id=' + item.id,
})
},
})
================================================
FILE: pages/order-list/index.json
================================================
{
"navigationBarTitleText":"订单列表",
"enablePullDownRefresh": true
}
================================================
FILE: pages/order-list/index.wxml
================================================
module.exports = {
url : function(item) {
if (item.supplyType == 'cps_jd') {
return '/packageCps/pages/goods-details/cps-jd?id=' + item.goodsId
} else if (item.supplyType == 'vop_jd') {
return '/pages/goods-details/vop?id=' + item.yyId + '&goodsId=' + item.id
} else if (item.supplyType == 'cps_pdd') {
return '/packageCps/pages/goods-details/cps-pdd?id=' + item.goodsId
} else if (item.supplyType == 'cps_taobao') {
return '/packageCps/pages/goods-details/cps-taobao?id=' + item.goodsId
} else {
return '/pages/goods-details/index?id=' + item.goodsId
}
}
}
{{goodsMap[item.id][0].goodsName}}
¥{{goodsMap[item.id][0].amountSingle}}
x{{goodsMap[item.id][0].number}}
共{{item.goodsNumber}}件商品
订单金额
¥
{{item.amountReal}}
+{{item.score}}积分
================================================
FILE: pages/order-list/index.wxss
================================================
/* 页面容器 - 京东风格 */
.container {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 20rpx;
}
/* 订单列表 */
.order-list {
width: 100%;
padding: 0 20rpx;
box-sizing: border-box;
}
/* 订单卡片 */
.order-card {
background: #ffffff;
border-radius: 12rpx;
margin-top: 20rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
}
/* 订单头部 */
.order-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 28rpx;
background: #ffffff;
border-bottom: 1px solid #f0f0f0;
}
.order-header-left {
flex: 1;
}
.order-number {
font-size: 24rpx;
color: #666666;
margin-bottom: 8rpx;
font-weight: 400;
}
.order-time {
font-size: 22rpx;
color: #999999;
}
.order-status {
font-size: 26rpx;
font-weight: 500;
color: #E4393C;
}
/* ========== 1个商品布局:横向,左图右信息 ========== */
.goods-content-single {
display: flex;
padding: 28rpx 28rpx 20rpx;
background: #ffffff;
gap: 24rpx;
}
.goods-image-single {
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
background: #f8f8f8;
border: 1px solid #eeeeee;
flex-shrink: 0;
}
.goods-info-single {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding: 8rpx 0;
}
.goods-name {
font-size: 28rpx;
color: #333333;
line-height: 1.5;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.goods-price-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16rpx;
}
.goods-price {
font-size: 32rpx;
color: #E4393C;
font-weight: 700;
font-family: DIN, -apple-system, system-ui;
}
.goods-quantity {
font-size: 26rpx;
color: #999999;
}
/* ========== 2个商品布局:左两图+右价格信息 ========== */
.goods-content-double {
display: flex;
padding: 28rpx 28rpx 20rpx;
background: #ffffff;
gap: 20rpx;
}
.goods-left {
display: flex;
gap: 16rpx;
}
.goods-item-double {
position: relative;
}
.goods-image-double {
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
background: #f8f8f8;
border: 1px solid #eeeeee;
}
.goods-right {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.price-info-compact {
text-align: center;
}
.goods-count-compact {
font-size: 24rpx;
color: #999999;
margin-bottom: 20rpx;
}
.total-price-compact {
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
}
.label-compact {
font-size: 24rpx;
color: #666666;
font-weight: 500;
}
.price-amount {
display: flex;
align-items: baseline;
}
.price-symbol-compact {
font-size: 24rpx;
color: #E4393C;
font-weight: 600;
}
.price-value-compact {
font-size: 40rpx;
color: #E4393C;
font-weight: 700;
font-family: DIN, -apple-system, system-ui;
}
.score-value-compact {
font-size: 20rpx;
color: #E4393C;
margin-top: 4rpx;
}
/* ========== 多个商品布局:网格 ========== */
.goods-content {
padding: 28rpx 28rpx 20rpx;
background: #ffffff;
}
.goods-grid {
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.goods-item {
width: 200rpx;
position: relative;
}
.goods-item-hover {
opacity: 0.85;
}
.goods-image {
width: 200rpx;
height: 200rpx;
border-radius: 8rpx;
background: #f8f8f8;
border: 1px solid #eeeeee;
}
/* 备注信息 */
.order-remark {
display: flex;
align-items: flex-start;
padding: 20rpx 28rpx;
background: #fff9f0;
border-top: 1px solid #f0f0f0;
border-bottom: 1px solid #f0f0f0;
}
.remark-label {
font-size: 24rpx;
color: #E4393C;
margin-right: 8rpx;
font-weight: 500;
flex-shrink: 0;
}
.remark-text {
flex: 1;
font-size: 24rpx;
color: #666666;
line-height: 1.6;
word-break: break-all;
}
/* 订单底部 */
.order-footer {
padding: 20rpx 28rpx 24rpx;
background: #ffffff;
}
.order-summary {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.goods-count {
font-size: 24rpx;
color: #999999;
}
.total-price {
display: flex;
align-items: baseline;
}
.total-price .label {
font-size: 24rpx;
color: #333333;
margin-right: 8rpx;
font-weight: 500;
}
.total-price .price-symbol {
font-size: 22rpx;
color: #E4393C;
font-weight: 600;
}
.total-price .price-value {
font-size: 32rpx;
color: #E4393C;
font-weight: 700;
font-family: DIN, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui;
}
.total-price .score-value {
font-size: 20rpx;
color: #E4393C;
margin-left: 8rpx;
font-weight: 400;
}
/* 操作按钮 */
.order-actions {
display: flex;
justify-content: flex-end;
gap: 16rpx;
flex-wrap: wrap;
}
.action-btn {
padding: 14rpx 28rpx;
border-radius: 4rpx;
font-size: 26rpx;
font-weight: 400;
text-align: center;
transition: all 0.2s ease;
min-width: 160rpx;
}
.btn-default {
background: #ffffff;
color: #666666;
border: 1px solid #cccccc;
}
.btn-default:active {
background: #f5f5f5;
border-color: #999999;
}
.btn-primary {
background: #E4393C;
color: #ffffff;
border: 1px solid #E4393C;
}
.btn-primary:active {
background: #c7302f;
border-color: #c7302f;
}
/* 底部安全区域 */
.safeAreaOldMarginBttom,
.safeAreaNewMarginBttom {
height: 40rpx;
}
================================================
FILE: pages/peisong/detail.js
================================================
const app = getApp();
const CONFIG = require('../../config.js')
const WXAPI = require('apifm-wxapi')
import wxbarcode from 'wxbarcode'
Page({
data:{
orderId:0,
goodsList:[],
fileList: [],
membersSelectIndex: -1,
membersSelectStr: '请选择分配配送员',
},
onLoad:function(e){
// e.peisongOrderId = 54
var peisongOrderId = e.peisongOrderId;
this.setData({
peisongOrderId
});
this.peisongOrderDetail()
this.peisongMemberInfo()
},
async peisongOrderDetail() {
const res = await WXAPI.peisongOrderDetail(wx.getStorageSync('token'), this.data.peisongOrderId)
if (res.code == 0) {
this.setData({
peisongOrderDetail: res.data
})
}
},
async peisongMemberInfo() {
const res = await WXAPI.peisongMemberInfo(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
peisongMemberInfo: res.data
})
if (res.data.type == 2) {
this.peisongMembers()
}
}
},
async peisongMembers() {
const res = await WXAPI.peisongMembers({
token: wx.getStorageSync('token')
})
if (res.code == 0) {
res.data.result.forEach(ele => {
ele.showStr = ele.name + ' ' + ele.mobile + ' ' + ele.statusStr
})
this.setData({
peisongMembers: res.data.result
})
}
},
onShow : function () {
var that = this;
WXAPI.orderDetail(wx.getStorageSync('token'), 0, '', that.data.peisongOrderId).then(function (res) {
if (res.code != 0) {
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false
})
return;
}
// 绘制核销码
if (res.data.orderInfo.hxNumber && res.data.orderInfo.status > 0) {
wxbarcode.qrcode('qrcode', res.data.orderInfo.hxNumber, 650, 650);
}
that.setData({
orderDetail: res.data
});
})
},
wuliuDetailsTap:function(e){
var orderId = e.currentTarget.dataset.id;
wx.navigateTo({
url: "/pages/wuliu/index?id=" + orderId
})
},
confirmBtnTap:function(e){
let that = this;
let orderId = this.data.orderId;
wx.showModal({
title: '确认服务已完成?',
content: '',
success: function(res) {
if (res.confirm) {
WXAPI.orderDelivery(wx.getStorageSync('token'), orderId).then(function (res) {
if (res.code == 0) {
that.onShow();
}
})
}
}
})
},
submitReputation: function (e) {
let that = this;
let postJsonString = {};
postJsonString.token = wx.getStorageSync('token');
postJsonString.orderId = this.data.orderId;
let reputations = [];
let i = 0;
while (e.detail.value["orderGoodsId" + i]) {
let orderGoodsId = e.detail.value["orderGoodsId" + i];
let goodReputation = e.detail.value["goodReputation" + i];
let goodReputationRemark = e.detail.value["goodReputationRemark" + i];
let reputations_json = {};
reputations_json.id = orderGoodsId;
reputations_json.reputation = goodReputation;
reputations_json.remark = goodReputationRemark;
reputations.push(reputations_json);
i++;
}
postJsonString.reputations = reputations;
WXAPI.orderReputation({
postJsonString: JSON.stringify(postJsonString)
}).then(function (res) {
if (res.code == 0) {
that.onShow();
}
})
},
afterRead(event) {
console.log(event.detail);
const fileList = this.data.fileList
event.detail.file.forEach(ele => {
fileList.push({
url: ele.path,
name: '图片'
})
})
this.setData({
fileList
});
},
deletePic(event) {
const fileList = this.data.fileList
fileList.splice(event.detail.index, 1)
this.setData({
fileList
});
},
async startService() {
const extJsonStr = {}
wx.showLoading({
title: '提交中',
})
const res = await WXAPI.peisongStartService({
token: wx.getStorageSync('token'),
id: this.data.peisongOrderId,
extJsonStr: JSON.stringify(extJsonStr)
})
wx.hideLoading({
complete: (res) => {},
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '提交成功',
icon: 'success'
})
this.peisongOrderDetail()
this.onShow()
}
},
async endService() {
const extJsonStr = {}
let picNumber = 0
wx.showLoading({
title: '提交中',
})
const res = await WXAPI.peisongEndService({
token: wx.getStorageSync('token'),
id: this.data.peisongOrderId,
extJsonStr: JSON.stringify(extJsonStr)
})
wx.hideLoading({
complete: (res) => {},
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '提交成功',
icon: 'success'
})
this.setData({
fileList: []
})
this.peisongOrderDetail()
this.onShow()
}
},
previewImage(e) {
const logid = e.currentTarget.dataset.logid
const current = e.currentTarget.dataset.current
const urls = []
this.data.peisongOrderDetail.logs.forEach(ele => {
if (ele.id == logid) {
Object.values(ele.extJson).forEach(_ele => {
urls.push(_ele)
})
}
})
wx.previewImage({
urls,
current
})
},
bindPickerChange: function(e) {
const obj = this.data.peisongMembers[e.detail.value]
this.setData({
membersSelectIndex: e.detail.value,
membersSelectStr: obj.name + ' ' + obj.mobile
})
},
async paidan() {
if (this.data.membersSelectIndex == -1) {
wx.showToast({
title: '请选择洗车工',
icon: 'none'
})
return
}
const member = this.data.peisongMembers[this.data.membersSelectIndex]
const res = await WXAPI.peisongOrderAllocation(wx.getStorageSync('token'), this.data.peisongOrderId, member.id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '派单成功',
icon: 'success'
})
wx.navigateBack({
complete: (res) => {},
})
}
},
callMobile() {
wx.makePhoneCall({
phoneNumber: this.data.orderDetail.peisongMember.mobile,
})
},
callMobile2() {
wx.makePhoneCall({
phoneNumber: this.data.orderDetail.logistics.mobile,
})
},
goMap() {
const _this = this
const latitude = this.data.orderDetail.logistics.latitude
const longitude = this.data.orderDetail.logistics.longitude
wx.openLocation({
latitude,
longitude,
scale: 18
})
},
estimatedCompletionTimeChange(value) {
this.data.estimatedCompletionTimeChange = value.detail
},
async estimatedCompletionTime(){
if (!this.data.estimatedCompletionTimeChange) {
wx.showToast({
title: '填写预计完成时间',
icon: 'none'
})
return;
}
const res = await WXAPI.peisongOrderEstimatedCompletionTime({
token: wx.getStorageSync('token'),
id: this.data.peisongOrderId,
estimatedCompletionTime: this.data.estimatedCompletionTimeChange
})
if (res.code == 0) {
wx.showToast({
title: '设置成功',
icon: 'success'
})
this.peisongOrderDetail()
this.onShow()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
async peisongOrderGrab(){
if (!this.data.estimatedCompletionTimeChange) {
wx.showToast({
title: '填写预计完成时间',
icon: 'none'
})
return;
}
const res = await WXAPI.peisongOrderGrab({
token: wx.getStorageSync('token'),
id: this.data.peisongOrderId,
estimatedCompletionTime: this.data.estimatedCompletionTimeChange
})
if (res.code == 0) {
wx.showToast({
title: '抢单成功',
icon: 'success'
})
this.peisongOrderDetail()
this.onShow()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
})
================================================
FILE: pages/peisong/detail.json
================================================
{
"navigationBarTitleText": "订单详情"
}
================================================
FILE: pages/peisong/detail.wxml
================================================
客户已申请退款
操作台
抢单
派单
设置预计完成时间
开始配送
配送完成
优惠券
{{item.coupon}}
商品金额
¥ {{orderDetail.orderInfo.amount}}
配送费
¥ {{orderDetail.orderInfo.amountLogistics}}
应付总额
¥ {{orderDetail.orderInfo.amountReal}}
================================================
FILE: pages/peisong/detail.wxss
================================================
page{
min-height: 100%;
background-color: #F2f2f2;
}
.container{
min-height: 100%;
overflow: hidden;
overflow-y: hidden;
}
.sec-wrap{
background-color: #fff;
margin-top: 20rpx;
}
.bottom-fiexd{
position: fixed;
bottom: 0;
left: 0;
}
.sec-wrap .order-status{
width: 720rpx;
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
height: 140rpx;
display: flex;
align-items: center;
}
.order-status .icon-box{
width: 80rpx;
height: 80rpx;
overflow: hidden;
margin-right: 30rpx;
}
.order-status .icon-box .icon{
width: 80rpx;
height: 80rpx;
}
.order-status .right-text{
width: 580rpx;
overflow: hidden;
}
.order-status .right-text .status{
font-size:28rpx;
color:#000;
margin-bottom: 10rpx;
}
.order-status .right-text .red{
color:#e64340;
}
.order-status .right-text .des{
font-size:24rpx;
color:#999;
}
.address-sec{
width: 720rpx;
margin-left: 30rpx;
display: flex;
align-items: center;
padding: 30rpx 0;
}
.address-sec .icon-box{
width: 30rpx;
align-self: flex-start;
overflow: hidden;
margin-right: 35rpx;
}
.address-sec .icon-box .icon{
width: 30rpx;
height: 30rpx;
}
.address-sec .right-box{
width: 620rpx;
}
.address-sec .right-box .name-tel{
font-size:28rpx;
color:#000000;
margin-bottom: 20rpx;
}
.address-sec .right-box .text{
font-size:24rpx;
color:#888888;
overflow: hidden;
}
.wuliu-box{
width: 720rpx;
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
display: flex;
align-items: center;
padding: 30rpx 0;
}
.wuliu-box .icon-box {
width: 40rpx;
height: 40rpx;
overflow: hidden;
margin-right: 31rpx;
align-self: flex-start;
}
.wuliu-box .icon-box .icon{
width: 40rpx;
height: 40rpx;
}
.wuliu-box .arrow-right{
width: 15rpx;
height: 24rpx;
}
.wuliu-box .arrow-right .arrow{
width: 15rpx;
height: 24rpx;
}
.wuliu-box .right-text{
width: 575rpx;
margin-right: 30rpx;
}
.wuliu-box .right-text .order-number{
font-size:28rpx;
color:#000;
margin-bottom: 14rpx;
}
.wuliu-box .right-text .wuliu-text,
.wuliu-box .right-text .wuliu-date{
font-size:24rpx;
color:#888888;
line-height:36rpx;
}
.goods-list{
width:100%;
background-color: #fff;
margin-bottom: 20rpx;
margin-top: 20rpx;
}
.goods-list .list-title{
font-size: 28rpx;
color: #000;
padding: 30rpx 0 25rpx 30rpx;
}
.goods-list .a-goods{
width: 720rpx;
margin-left: 30rpx;
display: flex;
/*justify-content: space-between;*/
border-top: 1px solid #eee;
padding: 30rpx 30rpx 30rpx 0;
}
.goods-list .a-goods .img-box{
width: 160rpx;
height:160rpx;
overflow: hidden;
margin-right: 20rpx;
background-color: #d8d8d8;
}
.goods-list .img-box .img{
width: 160rpx;
height:160rpx;
}
.goods-list .a-goods .text-box{
width: 510rpx;
box-sizing: border-box;
padding-top: 10rpx;
}
.goods-list .btn-row{
box-sizing: border-box;
width: 750rpx;
padding: 32rpx;
border-top: 1rpx solid #eee;
}
.confirm-btn{
background:#ffffff;
border:1rpx solid #e64340;
border-radius:6rpx;
width:164rpx;
height:60rpx;
line-height: 60rpx;
margin: 20rpx 30rpx 20rpx auto;
font-size:26rpx;
color:#e64340;
text-align:center;
}
.a-goods .text-box .arow{
display: flex;
justify-content: space-between;
align-items: center;
}
.a-goods .text-box .arow .goods-name{
width: 360rpx;
font-size:26rpx;
height: 74rpx;
color:#000000;
line-height: 1.6;
overflow: hidden;
}
.a-goods .text-box .arow01{
margin-bottom: 30rpx;
}
.a-goods .text-box .arow .goods-price{
font-size:26rpx;
color:#000000;
align-self: flex-start;
}
.a-goods .text-box .arow .goods-label{
font-size: 26rpx;
color: #999;
}
.a-goods .text-box .arow .goods-num{
font-size: 26rpx;
color: #999;
}
.peisong-way{
width: 100%;
background-color: #fff;
margin-bottom: 20rpx;
}
.peisong-way .row-box{
width: 720rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 0;
border-bottom: 1rpx solid #eee;
margin-left: 30rpx;
}
.peisong-way .row-label{
font-size: 28rpx;
color: #000;
}
.peisong-way .right-text{
font-size: 28rpx;
color: #666;
padding-right: 30rpx;
}
.peisong-way .liuyan{
width: 510rpx;
font-size: 28rpx;
}
.goods-info{
width: 100%;
background-color: #fff;
padding-bottom: 24rpx;
}
.goods-info .row-box{
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 30rpx 12rpx 30rpx;
font-size: 28rpx;
color: #000;
}
.goods-info .row-box .right-text{
text-align: right;
}
.jiesuan-box{
display: flex;
justify-content: space-between;
width: 100%;
height: 100rpx;
position: fixed;
bottom: 0;
left: 0;
border-top:1px solid #eee;
background-color: #fff;
z-index: 4;
}
.jiesuan-box .to-pay-btn{
width:250rpx;
text-align: center;
height: 100%;
line-height: 100rpx;
background-color: #e64340;
font-size:32rpx;
color:#ffffff;
border-radius: 0;
}
.jiesuan-box .left-price{
display: flex;
width: 500rpx;
justify-content:flex-end;
line-height: 100rpx;
padding: 0 30rpx 0 0;
font-size:28rpx;
box-sizing: border-box;
}
.jiesuan-box .total{
color: #e64340;
text-align: right;
}
.hx-title {
text-align: center;
}
.hx-canvas {
width: 650rpx;
height: 650rpx;
margin-left: 50rpx;
}
.vant-contaner {
box-sizing: border-box;
width: 100vw;
}
.select-peisong-member {
padding-left: 0 !important;
padding-right: 0 !important;
}
.pic-box {
display: flex;
flex-wrap: wrap;
}
.pic-box .pic {
margin: 16rpx 0 0 16rpx;
width: 228rpx;
height: 228rpx;
}
.refundStatus {
background: #ee0a24;
color: #ffffff;
padding: 16rpx;
text-align: center;
}
================================================
FILE: pages/peisong/orders.js
================================================
const WXAPI = require('apifm-wxapi')
const APP = getApp()
// fixed首次打开不显示标题的bug
APP.configLoadOK = () => {
}
var timer
Page({
data: {
active: 0,
tabs: ['已接单', '服务中', '全部'],
},
onLoad: function (options) {
this.data.status = options.status // -1 待接单订单 ; 1 待分配订单 ; 其他状态: 我的维修单
this.setData({
status: options.status
})
if (options.status == -1) {
wx.setNavigationBarTitle({
title: '抢单任务大厅',
})
} else if (options.status == 1) {
wx.setNavigationBarTitle({
title: '管理员派单管理',
})
} else {
wx.setNavigationBarTitle({
title: '我的配送单',
})
}
if (this.data.status == -1) {
timer =setInterval(() => {
this.peisongOrdersGrabbing()
}, 1000)
}
},
onShow: function () {
if (this.data.status != -1) {
this.orders()
}
},
onUnload() {
if (timer) {
clearTimeout(timer)
}
},
async orders() {
wx.showLoading({
title: '',
})
const _data = {
token: wx.getStorageSync('token'),
}
if(this.data.status) {
// 管理员派单
_data.statusBatch = this.data.status
_data.refundStatusBatch = '0,2'
} else {
// 我的配送单
_data.uid = wx.getStorageSync('uid')
if (this.data.active == 0) {
_data.status = 2
} else if (this.data.active == 1) {
_data.status = 3
}
}
const res = await WXAPI.peisongOrders(_data)
wx.hideLoading()
if (res.code != 0) {
this.setData({
orderList: null
})
} else {
res.data.result.forEach(ele => {
if (ele.status == 2) {
ele.statusStr = '已接单'
}
if (ele.status == 3) {
ele.statusStr = '配送中'
}
})
this.setData({
orderList: res.data.result
})
}
},
async peisongOrdersGrabbing() {
// wx.showLoading({
// title: '',
// })
const res = await WXAPI.peisongOrdersGrabbing(wx.getStorageSync('token'))
// wx.hideLoading({
// complete: (res) => {},
// })
if (res.code != 0) {
// wx.showToast({
// title: res.msg,
// icon: 'none'
// })
this.setData({
orderList: null
})
} else {
res.data.forEach(ele => {
if (ele.status == 2) {
ele.statusStr = '已接单'
}
if (ele.status == 3) {
ele.statusStr = '服务中'
}
})
this.setData({
orderList: res.data
})
}
},
tabClick(e) {
this.setData({
active: e.detail.index
})
this.orders()
},
})
================================================
FILE: pages/peisong/orders.json
================================================
{
"navigationBarTitleText": ""
}
================================================
FILE: pages/peisong/orders.wxml
================================================
================================================
FILE: pages/peisong/orders.wxss
================================================
================================================
FILE: pages/peisong/statistics.js
================================================
const WXAPI = require('apifm-wxapi')
const dayjs = require("dayjs")
Page({
data: {
active: 0,
tabs: ['本月', '今天', '昨天'],
page: 1,
month: undefined,
today: undefined,
yesday: undefined,
},
onLoad(options) {
this.setData({
month: dayjs().format('YYYYMM'),
today: dayjs().format('YYYYMMDD'),
yesday: dayjs().add(-1, 'day').format('YYYYMMDD'),
})
this.peisongMemberStatistics()
},
onShow() {
},
onReachBottom() {
this.data.page++
this.peisongMemberStatistics()
},
tabClick(e) {
this.data.page = 1
this.setData({
active: e.detail.index
})
this.peisongMemberStatistics()
},
async peisongMemberStatistics() {
wx.showLoading({
title: ''
})
const data = {
token: wx.getStorageSync('token'),
page: this.data.page,
}
if (this.data.active == 0) {
data.day = this.data.month
} else if (this.data.active == 1) {
data.day = this.data.today
} else if (this.data.active == 2) {
data.day = this.data.yesday
}
const res = await WXAPI.peisongMemberStatistics(data)
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
list: res.data.result
})
} else {
this.setData({
list: this.data.list.concat(res.data.result)
})
}
} else {
if (this.data.page > 1) {
wx.showToast({
title: '没有更多了~',
icon: 'none'
})
} else {
this.setData({
list: null
})
}
}
},
})
================================================
FILE: pages/peisong/statistics.json
================================================
{
"usingComponents": {},
"navigationBarTitleText": "业绩统计"
}
================================================
FILE: pages/peisong/statistics.wxml
================================================
================================================
FILE: pages/peisong/statistics.wxss
================================================
================================================
FILE: pages/pwd-pay/modify.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
},
async submit() {
if (!this.data.pwdOld) {
wx.showToast({
title: '请输入原来的交易密码',
icon: 'none'
})
return
}
if (!this.data.pwd) {
wx.showToast({
title: '请输入新的交易密码',
icon: 'none'
})
return
}
if (!this.data.pwd2) {
wx.showToast({
title: '请再次输入新的交易密码',
icon: 'none'
})
return
}
if (this.data.pwd != this.data.pwd2) {
wx.showToast({
title: '两次输入不一致',
icon: 'none'
})
return
}
const res = await WXAPI.modifyPayPassword(wx.getStorageSync('token'), this.data.pwdOld, this.data.pwd)
if (res.code == 2000) {
AUTH.login(this)
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '修改成功'
})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
},
})
================================================
FILE: pages/pwd-pay/modify.json
================================================
{
"navigationBarTitleText": "修改交易密码"
}
================================================
FILE: pages/pwd-pay/modify.wxml
================================================
修改交易密码
================================================
FILE: pages/pwd-pay/modify.wxss
================================================
.btn {
margin-top: 32rpx;
}
================================================
FILE: pages/pwd-pay/reset.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
this.getUserApiInfo()
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 2000) {
AUTH.login(this)
return
}
if (res.code == 0) {
this.setData({
mobile: res.data.base.mobile
})
}
},
async sendSms() {
const res = await WXAPI.smsValidateCodeByToken(wx.getStorageSync('token'))
if (res.code == 2000) {
AUTH.login(this)
return
}
if (res.code == 0) {
this.setData({
smsloading: true,
smsloadingSecond: 60
})
wx.showToast({
title: '短信已发送',
})
this.countDown()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
countDown() {
const smsloadingSecond = this.data.smsloadingSecond
if (smsloadingSecond) {
this.setData({
smsloadingSecond: smsloadingSecond-1
})
setTimeout(() => {
this.countDown()
}, 1000);
} else {
this.setData({
smsloading: false
})
}
},
async submit() {
if (!this.data.mobile) {
wx.showToast({
title: '请先绑定手机号码',
icon: 'none'
})
return
}
if (!this.data.code) {
wx.showToast({
title: '请输入短信验证码',
icon: 'none'
})
return
}
if (!this.data.pwd) {
wx.showToast({
title: '请输入交易密码',
icon: 'none'
})
return
}
if (!this.data.pwd2) {
wx.showToast({
title: '请再次输入交易密码',
icon: 'none'
})
return
}
if (this.data.pwd != this.data.pwd2) {
wx.showToast({
title: '两次输入不一致',
icon: 'none'
})
return
}
const res = await WXAPI.resetPayPassword(this.data.mobile, this.data.code, this.data.pwd)
if (res.code == 2000) {
AUTH.login(this)
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '设置成功'
})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
},
bindMobile() {
this.setData({
bindMobileShow: true
})
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false
})
this.getUserApiInfo()
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
})
================================================
FILE: pages/pwd-pay/reset.json
================================================
{
"navigationBarTitleText": "重置交易密码"
}
================================================
FILE: pages/pwd-pay/reset.wxml
================================================
{{ smsloading ? smsloadingSecond + '秒后重新获取' : '发送验证码' }}
立即绑定
重置交易密码
================================================
FILE: pages/pwd-pay/reset.wxss
================================================
.btn {
margin-top: 32rpx;
}
================================================
FILE: pages/pwd-pay/set.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
},
onLoad: function (options) {
},
onShow: function () {
},
async submit() {
if (!this.data.pwd) {
wx.showToast({
title: '请输入交易密码',
icon: 'none'
})
return
}
if (!this.data.pwd2) {
wx.showToast({
title: '请再次输入交易密码',
icon: 'none'
})
return
}
if (this.data.pwd != this.data.pwd2) {
wx.showToast({
title: '两次输入不一致',
icon: 'none'
})
return
}
const res = await WXAPI.setPayPassword(wx.getStorageSync('token'), this.data.pwd)
if (res.code == 2000) {
AUTH.login(this)
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '设置成功'
})
setTimeout(() => {
wx.navigateBack({
delta: 0,
})
}, 1000);
},
})
================================================
FILE: pages/pwd-pay/set.json
================================================
{
"navigationBarTitleText": "设置交易密码"
}
================================================
FILE: pages/pwd-pay/set.wxml
================================================
设置交易密码
================================================
FILE: pages/pwd-pay/set.wxss
================================================
.btn {
margin-top: 32rpx;
}
================================================
FILE: pages/raffle/index.js
================================================
const WXAPI = require('apifm-wxapi');
const {
unix
} = require('dayjs');
//计数器
var interval = null;
//值越大旋转时间越长 即旋转速度
var intime = 50;
Page({
data: {
id: undefined,
border: ['border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none', 'border:none'],
btnconfirm: 'https://dcdn.it120.cc/2024/04/12/21578e4c-575a-48dd-9825-072d92f7a3e8.png',
clickLuck: 'clickLuck',
luckPosition: 0,
},
onLoad(e) {
this.data.id = e.id
this.loadAnimation(); // 进入页面时缓慢切换
this.luckyInfo()
},
onShow() {},
onShareAppMessage() {
},
async luckyInfo() {
wx.showLoading({
title: ''
})
const res = await WXAPI.luckyInfo(this.data.id)
wx.hideLoading()
if (res.code == 0) {
let timesPerUser = res.data.info.timesPerUser
let luckyGoods = res.data.luckyGoods
if (!luckyGoods) {
luckyGoods = []
}
// 补全9个
for (let index = 0; index < 9; index++) {
luckyGoods.push({
goodsId: -2, // 补全
pic: "https://dcdn.it120.cc/2024/04/12/b5fa1fa4-66f2-4ac0-9261-480e6df1df9b.jpg",
title: "谢谢参与"
})
}
const uid = wx.getStorageSync('uid')
let logs
if (uid) {
const res2 = await WXAPI.luckyInfoJoinLogs({
lid: this.data.id,
uid
})
if (res2.code == 0) {
timesPerUser -= res2.data.totalRow
logs = res2.data.result
}
} else {
logs = null
}
this.setData({
timesPerUser,
logs,
luckyGoods
})
}
},
loadAnimation() {
var e = this;
var index = 0;
// if (interval == null){
interval = setInterval(function () {
if (index > 7) {
index = 0;
e.data.border[7] = 'border:none'
} else if (index != 0) {
e.data.border[index - 1] = 'border:none'
}
e.data.border[index] = 'border:6rpx solid #9077c4;border-radius:40rpx;width:168rpx;height:168rpx'
e.setData({
border: e.data.border,
})
index++;
}, 1000);
// }
},
async getLuckyInfoJoin() { // 点击抽奖
if (this.data.clickLuck == '') {
return;
}
if (this.data.timesPerUser <= 0) {
wx.showToast({
title: '抽奖次数已用完',
icon: 'none'
})
return
}
const token = wx.getStorageSync('token')
wx.showLoading({
title: '',
})
const res = await WXAPI.luckyInfoJoin(this.data.id, token)
wx.hideLoading()
if (res.code == 2000) {
wx.navigateTo({
url: '/pages/login/index',
})
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
const prizeName = res.data.prizeName
const luckPosition = this.data.luckyGoods.findIndex(ele => ele.title == prizeName) // 服务器返回的中奖的是哪个商品
this.setData({
luckPosition
})
this.clickLuck()
},
clickLuck() {
var e = this;
if (this.data.clickLuck == '') {
return;
}
//设置按钮不可点击
this.setData({
btnconfirm: 'https://dcdn.it120.cc/2024/04/12/816d31c4-cb18-4107-8934-00999356a682.png',
clickLuck: '',
})
//清空计时器
clearInterval(interval);
var index = 0;
//循环设置每一项的透明度
interval = setInterval(function () {
if (index > 7) {
index = 0;
e.data.border[7] = 'border:none'
} else if (index != 0) {
e.data.border[index - 1] = 'border:none'
}
e.data.border[index] = 'border:6rpx solid #9077c4;border-radius:40rpx;width:168rpx;height:168rpx'
e.setData({
border: e.data.border
})
index++;
}, intime);
//模拟网络请求时间 设为两秒
var stoptime = 2000;
setTimeout(function () {
e.stop(e.data.luckPosition);
}, stoptime)
},
stop(which) {
var e = this;
//清空计数器
clearInterval(interval);
//初始化当前位置
var current = -1;
var border = e.data.border;
for (var i = 0; i < border.length; i++) {
if (border[i] == 'border:6rpx solid #ee6916;border-radius:40rpx;width:168rpx;height:168rpx') {
current = i;
}
}
//下标从1开始
var index = current + 1;
this.stopLuck(which, index, intime, 10);
},
/**
* which:中奖位置
* index:当前位置
* time:时间标记
* splittime:每次增加的时间 值越大减速越快
*/
stopLuck(which, index, time, splittime) {
var e = this;
//值越大出现中奖结果后减速时间越长
var border = e.data.border;
setTimeout(function () {
//重置前一个位置
if (index > 7) {
index = 0;
border[7] = 'border:none;'
} else if (index != 0) {
border[index - 1] = 'border:none;'
}
//当前位置为选中状态
e.data.border[index] = 'border:6rpx solid #ee6916;border-radius:40rpx;width:168rpx;height:168rpx'
e.setData({
border: e.data.border
})
//如果旋转时间过短或者当前位置不等于中奖位置则递归执行
//直到旋转至中奖位置
if (time < 400 || index != which) {
//越来越慢
splittime++;
time += splittime;
//当前位置+1
index++;
e.stopLuck(which, index, time, splittime);
} else {
//抽奖后是否可以再次抽奖,可以的再次抽奖设为:'clickLuck',不能再次抽奖设为''
e.setData({
clickLuck: 'clickLuck'
})
//1秒后显示弹窗
setTimeout(function () {
wx.showModal({
title: '中奖提示',
content: e.data.luckPosition == 6 ? '非常遗憾,您没有中奖,谢谢您的参与。' : '恭喜抽中: ' + e.data.luckyGoods[e.data.luckPosition].title,
showCancel: false,
success: function (res) {
if (res.confirm) {
//设置按钮可以点击
e.setData({
btnconfirm: 'https://dcdn.it120.cc/2024/04/12/21578e4c-575a-48dd-9825-072d92f7a3e8.png',
clickLuck: 'clickLuck',
})
e.loadAnimation();
e.luckyInfo()
}
}
})
}, 600);
}
}, time);
console.log(time);
},
})
================================================
FILE: pages/raffle/index.json
================================================
{
"navigationBarTitleText": "抽奖"
}
================================================
FILE: pages/raffle/index.wxml
================================================
剩余抽奖次数: {{ timesPerUser }}
================================================
FILE: pages/raffle/index.wxss
================================================
page {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.frame_view{
bottom: 160rpx;
left: 60rpx;
right: 60rpx;
width:590rpx;
height:590rpx;
padding: 20rpx;
background: #6339b5;
z-index: 3;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
border-radius: 30rpx;
}
.frame_row{
width:580rpx;
height:180rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.frame_item{
width:180rpx;
height:180rpx;
}
.top_img_button {
box-shadow: 6rpx 6rpx #e85c33;
box-sizing: border-box;
display: inline-block;
height: 42px;
line-height: 42px;
border-radius: 20px;
padding: 0 14px;
color:#fe7520;
font-size: 14px;
background: white;
text-align: center;
}
button:after{
border: none;
}
.number {
margin: 64rpx 0;
padding: 8rpx 16rpx;
color: #ffffff;
background: #9077c4;
border-radius: 16rpx;
font-size: 30rpx;
}
.logs {
width: 90vw;
background: #fff;
}
================================================
FILE: pages/recharge/index.js
================================================
const WXAPI = require('apifm-wxapi')
const CONFIG = require('../../config.js')
Page({
data: {
},
onLoad(e) {
// 读取系统参数
this.readConfigVal()
getApp().configLoadOK = () => {
this.readConfigVal()
}
this.rechargeSendRules()
},
onShow: function () {
},
readConfigVal() {
let recharge_amount_min = wx.getStorageSync('recharge_amount_min')
if (!recharge_amount_min) {
recharge_amount_min = 0;
}
this.setData({
recharge_amount_min: recharge_amount_min,
needBindMobile: wx.getStorageSync('needBindMobile'),
})
},
async rechargeSendRules() {
const res = await WXAPI.rechargeSendRules()
if (res.code == 0) {
this.setData({
rechargeSendRules: res.data
})
}
},
/**
* 点击充值优惠的充值送
*/
async rechargeAmount(e) {
// 判断是否需要绑定手机号码
// https://www.yuque.com/apifm/nu0f75/zgf8pu
if (this.data.needBindMobile == 1) {
const resUserDetail = await WXAPI.userDetail(wx.getStorageSync('token'))
if (resUserDetail.code == 0 && !resUserDetail.data.base.mobile) {
this.setData({
bindMobileShow: true
})
return
}
}
var confine = e.currentTarget.dataset.confine;
var amount = confine;
this.setData({
amount,
paymentShow: true
})
},
async bindSave() {
const amount = this.data.amount;
if (!amount || amount * 1 < 0) {
wx.showModal({
title: '错误',
content: '请填写正确的充值金额',
showCancel: false
})
return
}
if (amount * 1 < this.data.recharge_amount_min * 1) {
wx.showModal({
title: '错误',
content: '单次充值金额至少' + this.data.recharge_amount_min + '元',
showCancel: false
})
return
}
// 判断是否需要绑定手机号码
// https://www.yuque.com/apifm/nu0f75/zgf8pu
if (this.data.needBindMobile == 1) {
console.log(123);
const resUserDetail = await WXAPI.userDetail(wx.getStorageSync('token'))
if (resUserDetail.code == 0 && !resUserDetail.data.base.mobile) {
this.setData({
bindMobileShow: true
})
return
}
}
this.setData({
paymentShow: true
})
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false
})
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.switchTab({
url: '/pages/my/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
})
================================================
FILE: pages/recharge/index.json
================================================
{
"navigationBarTitleText": "在线充值"
}
================================================
FILE: pages/recharge/index.wxml
================================================
💰
充值金额
¥
快速选择
¥{{item.confine}}
送¥{{item.send}}
ℹ️
温馨提示
• 充值金额实时到账,可随时使用
• 支持微信支付,安全可靠
• 充值记录可在"我的"页面查看
立即充值
→
================================================
FILE: pages/recharge/index.wxss
================================================
/* 页面容器 */
page {
background: linear-gradient(180deg, #FF4D4F 0%, #FF7A7C 30%, #F5F5F5 30%, #F5F5F5 100%);
min-height: 100vh;
}
.page-container {
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 头部区域 */
.header-section {
position: relative;
height: 280rpx;
overflow: hidden;
}
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
}
.header-bg::after {
content: '';
position: absolute;
bottom: -2rpx;
left: 0;
right: 0;
height: 80rpx;
background: #F5F5F5;
border-radius: 50% 50% 0 0 / 100% 100% 0 0;
}
.header-content {
position: relative;
z-index: 2;
padding-top: 80rpx;
text-align: center;
}
.header-title {
font-size: 44rpx;
font-weight: bold;
color: #FFFFFF;
letter-spacing: 2rpx;
margin-bottom: 16rpx;
}
.header-subtitle {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.9);
letter-spacing: 1rpx;
}
/* 充值金额卡片 */
.amount-card {
margin: -60rpx 30rpx 30rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 40rpx 30rpx;
box-shadow: 0 8rpx 32rpx rgba(228, 57, 60, 0.15);
position: relative;
z-index: 10;
}
.card-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.title-icon {
font-size: 40rpx;
margin-right: 12rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333333;
}
.amount-input-wrapper {
display: flex;
align-items: center;
padding: 30rpx 24rpx;
background: #F8F8F8;
border-radius: 16rpx;
border: 2rpx solid #E8E8E8;
transition: all 0.3s;
}
.amount-input-wrapper:focus-within {
background: #FFF;
border-color: #E4393C;
box-shadow: 0 0 0 4rpx rgba(228, 57, 60, 0.1);
}
.amount-symbol {
font-size: 48rpx;
font-weight: bold;
color: #E4393C;
margin-right: 12rpx;
}
.amount-input {
flex: 1;
font-size: 48rpx;
font-weight: bold;
color: #333333;
}
.amount-placeholder {
color: #BBBBBB;
font-size: 28rpx;
font-weight: normal;
}
/* 快速充值选择区域 */
.quick-amount-section {
margin: 0 30rpx 30rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 30rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
}
.section-title {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30rpx;
}
.title-line {
flex: 1;
height: 2rpx;
background: linear-gradient(to right, transparent, #E8E8E8, transparent);
}
.section-title .title-text {
padding: 0 24rpx;
font-size: 28rpx;
font-weight: 500;
color: #666666;
}
.amount-options {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.amount-option {
width: calc(50% - 15rpx);
background: linear-gradient(135deg, #FFF8F8 0%, #FFFFFF 100%);
border: 2rpx solid #FFE5E5;
border-radius: 16rpx;
padding: 32rpx 20rpx;
text-align: center;
position: relative;
transition: all 0.3s;
overflow: hidden;
box-sizing: border-box;
}
.amount-option::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
opacity: 0;
transition: opacity 0.3s;
}
.amount-option:active {
transform: scale(0.95);
}
.amount-option:active::before {
opacity: 1;
}
.option-amount {
font-size: 36rpx;
font-weight: bold;
color: #E4393C;
position: relative;
z-index: 1;
transition: color 0.3s;
}
.amount-option:active .option-amount {
color: #FFFFFF;
}
.option-gift {
margin-top: 12rpx;
position: relative;
z-index: 1;
}
.gift-tag {
display: inline-block;
background: linear-gradient(135deg, #FF4D4F 0%, #FF6B6B 100%);
color: #FFFFFF;
font-size: 20rpx;
padding: 4rpx 12rpx;
border-radius: 20rpx;
font-weight: 500;
box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.3);
transition: all 0.3s;
}
.amount-option:active .gift-tag {
background: #FFFFFF;
color: #E4393C;
}
/* 温馨提示 */
.tips-section {
margin: 0 30rpx 30rpx;
background: linear-gradient(135deg, #FFF9F0 0%, #FFFFFF 100%);
border-radius: 20rpx;
padding: 30rpx;
border-left: 6rpx solid #FFA940;
}
.tips-title {
display: flex;
align-items: center;
margin-bottom: 20rpx;
font-size: 28rpx;
font-weight: 600;
color: #333333;
}
.tips-icon {
font-size: 32rpx;
margin-right: 8rpx;
}
.tips-content {
padding-left: 8rpx;
}
.tip-item {
font-size: 24rpx;
color: #666666;
line-height: 40rpx;
margin-bottom: 8rpx;
}
.tip-item:last-child {
margin-bottom: 0;
}
/* 提交按钮区域 */
.submit-section {
margin: 60rpx 30rpx 30rpx;
}
.submit-btn {
display: flex;
align-items: center;
justify-content: center;
height: 96rpx;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
border-radius: 48rpx;
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.4);
position: relative;
overflow: hidden;
transition: all 0.3s;
}
.submit-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s;
}
.submit-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.3);
}
.submit-btn:active::before {
left: 100%;
}
.btn-text {
font-size: 34rpx;
font-weight: bold;
color: #FFFFFF;
letter-spacing: 2rpx;
}
.btn-icon {
font-size: 32rpx;
color: #FFFFFF;
margin-left: 8rpx;
font-weight: bold;
}
/* 兼容vant组件样式 */
.amount-input .van-field__control {
font-size: 48rpx !important;
font-weight: bold;
color: #333333;
}
================================================
FILE: pages/recycle/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
logisticsType: '0', // 0 自己送货 1 快递
shopIndex: -1
},
onLoad(e) {
// e.type = 1
// e.orderId = 3
// e.platform = 'jd'
this.setData({
type: e.type,
orderId: e.orderId,
platform: e.platform
})
wx.getLocation({
type: 'gcj02', // 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标
success: res => {
this.data.latitude = res.latitude
this.data.longitude = res.longitude
this.initData()
},
fail: err => {
console.error(err)
this.initData()
AUTH.checkAndAuthorize('scope.userLocation')
}
})
},
onShow() {
},
async initData() {
this.fetchShops()
if (this.data.type == 1 && this.data.platform == 'jd') {
this.cpsJdOrderDetail()
}
if (this.data.type == 1 && this.data.platform == 'pdd') {
this.cpsPddOrderDetail()
}
},
async fetchShops(){
const p = {}
if (this.data.latitude) {
p.curlatitude = this.data.latitude
}
if (this.data.longitude) {
p.curlongitude = this.data.longitude
}
const res = await WXAPI.fetchShops(p)
if (res.code == 0) {
res.data.forEach(ele => {
if (ele.distance) {
ele.distance = ele.distance.toFixed(3) // 距离保留3位小数
}
})
this.setData({
shops: res.data
})
}
},
async cpsJdOrderDetail() {
wx.showLoading({
title: '',
})
const res = await WXAPI.cpsJdOrderDetail(wx.getStorageSync('token'), this.data.orderId)
wx.hideLoading()
if (res.code == 0) {
const orderInfo = res.data.orderInfo
if (orderInfo.validCode != 17) {
wx.showModal({
title: '错误',
content: '已完成订单才可以申请回收',
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
if (orderInfo.recycleOrderId) {
wx.showModal({
title: '错误',
content: '请勿重复申请回收',
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
this.setData({
orderInfo,
amountRecycle: orderInfo.estimateCosPrice,
name: orderInfo.skuName,
pic: orderInfo.imageUrl,
amount: orderInfo.actualCosPrice,
})
} else {
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
},
async cpsPddOrderDetail() {
wx.showLoading({
title: '',
})
const res = await WXAPI.cpsPddOrderDetail(wx.getStorageSync('token'), this.data.orderId)
wx.hideLoading()
if (res.code == 0) {
const orderInfo = res.data.orderInfo
if (orderInfo.status != 2 && orderInfo.status != 3 && orderInfo.status != 5) {
wx.showModal({
title: '错误',
content: '已完成订单才可以申请回收',
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
if (orderInfo.recycleOrderId) {
wx.showModal({
title: '错误',
content: '请勿重复申请回收',
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
this.setData({
orderInfo,
amountRecycle: orderInfo.orderAmount,
name: orderInfo.goodsName,
pic: orderInfo.imageUrl,
amount: orderInfo.orderAmount,
})
} else {
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
},
logisticsTypeChange(e) {
this.setData({
logisticsType: e.detail
})
},
logisticsTypeClick(e) {
this.setData({
logisticsType: e.currentTarget.dataset.name
})
},
shopSelect(e) {
this.setData({
shopIndex: e.detail.value
})
},
callMobile() {
const shop = this.data.shops[this.data.shopIndex]
wx.makePhoneCall({
phoneNumber: shop.linkPhone,
})
},
goMap() {
const shop = this.data.shops[this.data.shopIndex]
const latitude = shop.latitude
const longitude = shop.longitude
wx.openLocation({
latitude,
longitude,
scale: 18
})
},
async submit() {
if (!this.data.amountRecycle) {
wx.showToast({
title: '填写回收价格',
icon: 'none'
})
return
}
if (this.data.shopIndex == -1) {
wx.showToast({
title: '请选择回收点',
icon: 'none'
})
return
}
const res = await WXAPI.recycleOrderApply({
token: wx.getStorageSync('token'),
type: this.data.type,
platform: this.data.platform,
buyOrderId: this.data.orderId,
name: this.data.name,
pic: this.data.pic,
amount: this.data.amount,
amountRecycle: this.data.amountRecycle,
logisticsType: this.data.logisticsType,
shopId: this.data.shops[this.data.shopIndex].id,
remark: this.data.remark ? this.data.remark : '',
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showModal({
title: '成功',
content: '提交成功,耐心等待审核',
showCancel: false,
success: res => {
wx.redirectTo({
url: '/pages/recycle/orders',
})
}
})
}
})
================================================
FILE: pages/recycle/index.json
================================================
{
"navigationBarTitleText":"申请回收"
}
================================================
FILE: pages/recycle/index.wxml
================================================
申请回收
================================================
FILE: pages/recycle/index.wxss
================================================
.btn {
padding: 32rpx;
}
================================================
FILE: pages/recycle/order-detail.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
import wxbarcode from 'wxbarcode'
Page({
data: {
logisticsType: '0', // 0 自己送货 1 快递
shopIndex: -1
},
onLoad(e) {
// e.id = 3
this.data.id = e.id
this.recycleOrderDetail()
},
onShow() {
},
async recycleOrderDetail() {
wx.showLoading({
title: '',
})
const res = await WXAPI.recycleOrderDetail(wx.getStorageSync('token'), this.data.id)
wx.hideLoading()
if (res.code == 0) {
const orderInfo = res.data.orderInfo
if (orderInfo.shopId) {
this.shopSubdetail(orderInfo.shopId)
}
if (orderInfo.logisticsType == 0) {
wxbarcode.qrcode('qrcode', orderInfo.hxNumber, 650, 650);
}
this.setData({
orderInfo,
shipperName: orderInfo.shipperName,
trackingNumber: orderInfo.trackingNumber
})
} else {
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false,
success: res => {
wx.navigateBack()
}
})
}
},
async shopSubdetail(shopId) {
const res = await WXAPI.shopSubdetail(shopId)
if (res.code == 0) {
this.setData({
shopInfodetail: res.data
})
}
},
callMobile() {
wx.makePhoneCall({
phoneNumber: this.data.shopInfodetail.info.linkPhone,
})
},
goMap() {
const shop = this.data.shopInfodetail.info
const latitude = shop.latitude
const longitude = shop.longitude
wx.openLocation({
latitude,
longitude,
scale: 18
})
},
fahuo() {
this.setData({
popupShow: true
})
},
popupClose() {
this.setData({
popupShow: false
})
},
trackingNumberScan() {
wx.scanCode({
success: res => {
this.setData({
trackingNumber: res.result
})
}
})
},
async submit() {
if (!this.data.shipperName) {
wx.showToast({
title: '填写回快递公司',
icon: 'none'
})
return
}
if (!this.data.trackingNumber) {
wx.showToast({
title: '填写回快递单号',
icon: 'none'
})
return
}
this.setData({
submitButtonLoading: true
})
const res = await WXAPI.recycleOrderFahuo({
token: wx.getStorageSync('token'),
id: this.data.id,
shipperName: this.data.shipperName,
trackingNumber: this.data.trackingNumber,
})
this.setData({
submitButtonLoading: false
})
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '提交成功',
})
this.popupClose()
this.recycleOrderDetail()
}
})
================================================
FILE: pages/recycle/order-detail.json
================================================
{
"navigationBarTitleText":"回收订单详情"
}
================================================
FILE: pages/recycle/order-detail.wxml
================================================
核销码
工作人员扫描该码完成回收
填写快递信息
确认
================================================
FILE: pages/recycle/order-detail.wxss
================================================
.btn {
padding: 32rpx;
}
.hx-qrcode {
padding: 32rpx;
text-align: center;
color: #333;
}
.hx-qrcode .t {
font-weight: bold;
}
.hx-qrcode .t2 {
font-size: 26rpx;
color: #666;
}
.hx-qrcode .hx-canvas {
width: 650rpx;
height: 650rpx;
}
.statusStr {
color: #e64340 !important;
font-weight: bold;
}
================================================
FILE: pages/recycle/orders.js
================================================
const WXAPI = require('apifm-wxapi')
Page({
data: {
},
onLoad(e) {
this.recycleOrders()
},
onShow() {
},
async recycleOrders() {
wx.showLoading({
title: '',
})
const res = await WXAPI.recycleOrders({
token: wx.getStorageSync('token')
})
wx.hideLoading()
if (res.code == 0) {
this.setData({
list: res.data.result
})
}
},
onPullDownRefresh() {
this.recycleOrders()
wx.stopPullDownRefresh()
},
detail(e) {
const id = e.currentTarget.dataset.id
wx.navigateTo({
url: `/pages/recycle/order-detail?id=${id}`,
})
},
async recycleOrderClose(e) {
wx.showModal({
title: '提示',
content: '确认要取消该订单吗?',
success: res => {
if (res.confirm) {
this._recycleOrderClose(e)
}
}
})
},
async _recycleOrderClose(e) {
const id = e.currentTarget.dataset.id
const res = await WXAPI.recycleOrderClose(wx.getStorageSync('token'), id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '已取消',
})
this.recycleOrders()
},
async recycleOrderDelete(e) {
wx.showModal({
title: '提示',
content: '确认要删除该订单吗?',
success: res => {
if (res.confirm) {
this._recycleOrderDelete(e)
}
}
})
},
async _recycleOrderDelete(e) {
const id = e.currentTarget.dataset.id
const res = await WXAPI.recycleOrderDelete(wx.getStorageSync('token'), id)
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
return
}
wx.showToast({
title: '删除成功',
})
this.recycleOrders()
}
})
================================================
FILE: pages/recycle/orders.json
================================================
{
"navigationBarTitleText":"回收订单",
"enablePullDownRefresh": true
}
================================================
FILE: pages/recycle/orders.wxml
================================================
订单号 {{ item.orderNumber }}
回收时间 {{ item.dateAdd }}
详情
取消
删除
================================================
FILE: pages/recycle/orders.wxss
================================================
.btn {
margin-left: 16rpx;
}
================================================
FILE: pages/score/growth.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
growth: 0.00,
page: 1
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(e) {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.userAmountV2()
this.growthLogsV2()
} else {
getApp().loginOK = () => {
this.userAmountV2()
this.growthLogsV2()
}
}
})
},
onShow: function () {
},
onReachBottom() {
this.data.page++
this.growthLogsV2()
},
async userAmountV2() {
// https://www.yuque.com/apifm/nu0f75/wrqkcb
const res = await WXAPI.userAmountV2(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
growth: res.data.growth
})
}
},
async growthLogsV2() {
wx.showLoading({
title: '',
})
// https://www.yuque.com/apifm/nu0f75/gpb15y
const res = await WXAPI.growthLogsV2({
token: wx.getStorageSync('token'),
page: this.data.page,
})
wx.hideLoading()
if (res.code == 0) {
if (this.data.page == 1) {
this.setData({
cashlogs: res.data.result
})
} else {
this.setData({
cashlogs: this.data.cashlogs.concat(res.data.result)
})
}
} else {
if (this.data.page == 1) {
this.setData({
cashlogs: null
})
}
}
},
exchangeGrowth: function (e) {
wx.navigateTo({
url: '/pages/score-excharge/growth',
})
}
})
================================================
FILE: pages/score/growth.json
================================================
{
"navigationBarTitleText": "成长值明细"
}
================================================
FILE: pages/score/growth.wxml
================================================
当前成长值
{{growth}}
🎁
用积分兑换成长值
积分越多,成长越快
›
暂无成长值明细~
{{ item.typeStr }} {{ item.remark? '('+ item.remark +')' : '' }}
{{ item.dateAdd }}
剩余成长值: {{ item.growthLeft }}
{{ (item.behavior ==0 ) ? '+' : '' }} {{ item.growth }}
================================================
FILE: pages/score/growth.wxss
================================================
/* 页面整体背景 */
page {
background: #f5f5f5;
}
/* 顶部成长值展示区 - 京东风格渐变红 */
.score {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 750rpx;
padding: 60rpx 0 80rpx;
background: linear-gradient(135deg, #e93b3d 0%, #e4393c 50%, #d42727 100%);
box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.3);
overflow: hidden;
}
/* 顶部装饰圆 */
.score::before {
content: '';
position: absolute;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
top: -200rpx;
right: -100rpx;
}
.score::after {
content: '';
position: absolute;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
bottom: -150rpx;
left: -80rpx;
}
.score view:first-child {
position: relative;
z-index: 1;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 16rpx;
letter-spacing: 1rpx;
}
.score view:last-child {
position: relative;
z-index: 1;
font-size: 80rpx;
font-weight: bold;
color: #fff;
line-height: 90rpx;
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
}
/* 空数据提示 */
.no-data {
margin-top: 200rpx;
text-align: center;
font-size: 28rpx;
color: #999;
}
/* 明细列表容器 */
.cashlogs {
display: flex;
align-items: center;
justify-content: space-between;
margin: 20rpx 30rpx;
padding: 30rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
/* 列表项左侧装饰条 */
.cashlogs::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 60%;
background: linear-gradient(180deg, #e93b3d 0%, #e4393c 100%);
border-radius: 0 4rpx 4rpx 0;
}
/* 明细信息区域 */
.cashlogs .profile {
flex: 1;
display: flex;
flex-direction: column;
padding-left: 24rpx;
}
/* 类型描述文字 */
.cashlogs .profile .typeStr {
font-size: 30rpx;
color: #333;
font-weight: 500;
margin-bottom: 12rpx;
line-height: 40rpx;
}
/* 日期时间 */
.cashlogs .profile .dateAdd {
font-size: 24rpx;
color: #999;
line-height: 32rpx;
}
/* 剩余成长值 */
.cashlogs .profile .growthLeft {
font-size: 24rpx;
color: #666;
line-height: 32rpx;
margin-top: 4rpx;
}
/* 成长值金额 */
.cashlogs .amount {
flex-shrink: 0;
min-width: 120rpx;
text-align: right;
font-size: 36rpx;
font-weight: bold;
padding-right: 8rpx;
}
/* 积分兑换成长值入口 */
.exchange-entry {
display: flex;
align-items: center;
margin: 30rpx 30rpx 20rpx;
padding: 32rpx 30rpx;
background: linear-gradient(135deg, #fff 0%, #fafafa 100%);
border-radius: 20rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.08);
border: 1rpx solid rgba(233, 59, 61, 0.1);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.exchange-entry::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6rpx;
background: linear-gradient(180deg, #e93b3d 0%, #e4393c 100%);
border-radius: 0 4rpx 4rpx 0;
}
.exchange-entry:active {
transform: translateY(2rpx);
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.12);
}
.exchange-icon {
font-size: 48rpx;
margin-right: 24rpx;
flex-shrink: 0;
}
.exchange-content {
flex: 1;
display: flex;
flex-direction: column;
}
.exchange-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
line-height: 44rpx;
margin-bottom: 8rpx;
}
.exchange-desc {
font-size: 26rpx;
color: #999;
line-height: 36rpx;
}
.exchange-arrow {
font-size: 32rpx;
color: #ccc;
margin-left: 16rpx;
flex-shrink: 0;
}
================================================
FILE: pages/score/index.js
================================================
const app = getApp()
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
balance: 0.00,
freeze: 0,
score: 0,
score_sign_continuous: 0,
cashlogs: undefined
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.initData()
} else {
getApp().loginOK = () => {
this.initData()
}
}
})
},
onShow: function () {
},
initData() {
const _this = this
const token = wx.getStorageSync('token')
WXAPI.userAmount(token).then(function (res) {
if (res.code == 0) {
_this.setData({
balance: res.data.balance.toFixed(2),
freeze: res.data.freeze.toFixed(2),
totleConsumed: res.data.totleConsumed.toFixed(2),
score: res.data.score
});
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
})
// 读取积分明细
WXAPI.scoreLogs({
token: token,
page:1,
pageSize:50
}).then(res => {
if (res.code == 0) {
_this.setData({
cashlogs: res.data.result
})
}
})
},
recharge: function (e) {
wx.navigateTo({
url: "/pages/recharge/index"
})
},
withdraw: function (e) {
wx.navigateTo({
url: "/pages/withdraw/index"
})
},
sign() {
wx.navigateTo({
url: '/pages/sign/index',
})
},
exchange() {
wx.navigateTo({
url: '/pages/score-excharge/index',
})
},
})
================================================
FILE: pages/score/index.json
================================================
{
"navigationBarTitleText": "积分明细"
}
================================================
FILE: pages/score/index.wxml
================================================
获取积分
签
每日签到
签到得积分
券
积分券兑换
券兑积分
积分明细
📋
暂无积分明细
{{ (item.behavior ==0 ) ? '得' : '用' }}
{{ item.typeStr }}
{{ item.dateAdd }}
{{ (item.behavior ==0 ) ? '+' : '-' }}
{{ item.score }}
================================================
FILE: pages/score/index.wxss
================================================
/* 页面容器 */
.page-container {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 40rpx;
}
/* 顶部积分卡片 - 京东红色渐变 */
.score-header {
padding: 40rpx 30rpx 60rpx;
background: linear-gradient(135deg, #E4393C 0%, #FF6B6B 100%);
position: relative;
}
.score-bg {
text-align: center;
color: #fff;
position: relative;
z-index: 1;
}
.score-title {
font-size: 28rpx;
opacity: 0.95;
margin-bottom: 20rpx;
font-weight: 400;
letter-spacing: 2rpx;
}
.score-value {
font-size: 88rpx;
font-weight: bold;
line-height: 1.2;
margin-bottom: 10rpx;
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
}
.score-desc {
font-size: 24rpx;
opacity: 0.9;
margin-top: 10rpx;
}
/* 获取积分途径区域 */
.score-ways {
margin: -30rpx 30rpx 30rpx;
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
position: relative;
z-index: 2;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
}
.title-text {
font-size: 32rpx;
font-weight: 600;
color: #333;
position: relative;
padding-left: 20rpx;
}
.title-text::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: linear-gradient(180deg, #E4393C 0%, #FF6B6B 100%);
border-radius: 3rpx;
}
.title-line {
flex: 1;
height: 1rpx;
background: linear-gradient(to right, #eee 0%, transparent 100%);
margin-left: 20rpx;
}
.ways-grid {
display: flex;
justify-content: space-between;
gap: 20rpx;
}
.way-item {
flex: 1;
background: linear-gradient(135deg, #fff 0%, #fafafa 100%);
border-radius: 16rpx;
padding: 40rpx 20rpx 30rpx;
text-align: center;
border: 2rpx solid #f0f0f0;
transition: all 0.3s;
position: relative;
overflow: hidden;
}
.way-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(228, 57, 60, 0.05) 0%, rgba(255, 107, 107, 0.05) 100%);
opacity: 0;
transition: opacity 0.3s;
}
.way-item:active::before {
opacity: 1;
}
.way-icon {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
margin: 0 auto 20rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.sign-icon {
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
box-shadow: 0 8rpx 20rpx rgba(228, 57, 60, 0.3);
}
.coupon-icon {
background: linear-gradient(135deg, #FFA726 0%, #FF6F00 100%);
box-shadow: 0 8rpx 20rpx rgba(255, 167, 38, 0.3);
}
.icon-text {
font-size: 40rpx;
font-weight: bold;
color: #fff;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
.way-title {
font-size: 28rpx;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
}
.way-desc {
font-size: 22rpx;
color: #999;
}
/* 积分明细区域 */
.score-logs {
margin: 0 30rpx;
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
/* 空数据样式 */
.no-data {
text-align: center;
padding: 80rpx 0;
}
.no-data-icon {
font-size: 80rpx;
margin-bottom: 20rpx;
opacity: 0.3;
}
.no-data-text {
font-size: 28rpx;
color: #ccc;
}
/* 积分明细列表 */
.log-list {
margin-top: 10rpx;
}
.log-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 0;
border-bottom: 1rpx solid #f5f5f5;
position: relative;
}
.log-item:last-child {
border-bottom: none;
}
.log-left {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
}
.log-icon {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-right: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.log-icon-text {
font-size: 32rpx;
font-weight: bold;
color: #fff;
}
.log-info {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 8rpx;
}
.log-title {
font-size: 28rpx;
font-weight: 500;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.log-remark {
font-size: 24rpx;
color: #999;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.log-time {
font-size: 22rpx;
color: #bbb;
}
.log-amount {
font-size: 32rpx;
font-weight: 600;
flex-shrink: 0;
margin-left: 20rpx;
display: flex;
align-items: baseline;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
}
.amount-symbol {
font-size: 24rpx;
margin-right: 2rpx;
}
.amount-value {
font-size: 36rpx;
}
================================================
FILE: pages/score-excharge/growth.js
================================================
const app = getApp()
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
score: 0,
growth: 0,
uid: undefined
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
AUTH.checkHasLogined().then(isLogined => {
if (isLogined) {
this.initData()
} else {
getApp().loginOK = () => {
this.initData()
}
}
})
},
onShow: function () {
},
async initData(){
const token = wx.getStorageSync('token')
const res1 = await WXAPI.userAmount(token)
if (res1.code == 0) {
this.data.score = res1.data.score
this.data.growth = res1.data.growth
}
const res2 = await WXAPI.scoreDeductionRules(1);
if (res2.code == 0) {
this.data.deductionRules = res2.data
}
this.setData({
score: this.data.score,
growth: this.data.growth,
deductionRules: this.data.deductionRules,
})
},
async bindSave() {
if (!this.data.score2) {
wx.showToast({
title: '请输入积分数量',
icon: 'none'
})
return
}
// https://www.yuque.com/apifm/nu0f75/sq3tzp
const res = await WXAPI.exchangeScoreToGrowthV2({
token: wx.getStorageSync('token'),
deductionScore: this.data.score2
})
if (res.code == 0) {
wx.showModal({
content: '恭喜您,成功兑换'+ res.data +'成长值',
showCancel: false
})
this.initData()
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
})
================================================
FILE: pages/score-excharge/growth.json
================================================
{
"navigationBarTitleText": "积分兑换成长值"
}
================================================
FILE: pages/score-excharge/growth.wxml
================================================
💎
积分兑换成长值
兑换积分
ℹ️
积分可兑换成长值,助您快速升级
================================================
FILE: pages/score-excharge/growth.wxss
================================================
/* 页面整体样式 */
page {
height: 100%;
background: linear-gradient(180deg, #f5f5f5 0%, #ffffff 100%);
}
/* 顶部渐变背景区 - 京东红 */
.top-header {
background: linear-gradient(135deg, #E3393C 0%, #F44336 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
overflow: hidden;
}
.top-header::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.top-header::after {
content: '';
position: absolute;
bottom: -30%;
left: -10%;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
}
/* 资产展示卡片 */
.assets-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 24rpx;
padding: 50rpx 40rpx;
display: flex;
justify-content: space-around;
align-items: center;
box-shadow: 0 8rpx 32rpx rgba(227, 57, 60, 0.2);
backdrop-filter: blur(10rpx);
position: relative;
z-index: 2;
}
.asset-item {
flex: 1;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.asset-label {
font-size: 26rpx;
color: #999999;
margin-bottom: 16rpx;
font-weight: 400;
}
.asset-value {
font-size: 68rpx;
color: #E3393C;
font-weight: bold;
line-height: 1.2;
background: linear-gradient(135deg, #E3393C 0%, #F44336 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.asset-unit {
font-size: 24rpx;
color: #666666;
margin-top: 8rpx;
}
.divider-line {
width: 2rpx;
height: 100rpx;
background: linear-gradient(180deg,
rgba(227, 57, 60, 0) 0%,
rgba(227, 57, 60, 0.3) 50%,
rgba(227, 57, 60, 0) 100%
);
margin: 0 20rpx;
}
/* 主容器 */
.container {
background-color: transparent;
justify-content: initial;
padding: 0 30rpx;
margin-top: -50rpx;
position: relative;
z-index: 3;
}
/* 兑换卡片 */
.exchange-card {
background: #ffffff;
border-radius: 24rpx;
padding: 40rpx 30rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
margin-bottom: 30rpx;
width: 90%;
}
.card-title {
display: flex;
align-items: center;
margin-bottom: 40rpx;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #f5f5f5;
}
.title-icon {
font-size: 40rpx;
margin-right: 16rpx;
}
.title-text {
font-size: 32rpx;
color: #333333;
font-weight: bold;
}
/* 输入区域 */
.input-wrapper {
margin-bottom: 30rpx;
}
.input-label {
font-size: 28rpx;
color: #666666;
margin-bottom: 20rpx;
font-weight: 500;
}
.input-box {
background: #f8f8f8;
border-radius: 16rpx;
padding: 0 24rpx;
border: 2rpx solid #f0f0f0;
transition: all 0.3s ease;
}
.input-box .input {
height: 88rpx;
line-height: 88rpx;
font-size: 30rpx;
color: #333333;
}
.placeholder-style {
color: #bbbbbb;
font-size: 28rpx;
}
/* 提示信息 */
.exchange-hint {
display: flex;
align-items: center;
background: linear-gradient(135deg, #FFF3F3 0%, #FFE8E8 100%);
padding: 20rpx 24rpx;
border-radius: 12rpx;
border-left: 6rpx solid #E3393C;
}
.hint-icon {
font-size: 28rpx;
margin-right: 12rpx;
}
.hint-text {
font-size: 24rpx;
color: #E3393C;
line-height: 1.6;
}
/* 兑换按钮 - 京东风格 */
.exchange-btn {
width: 690rpx;
height: 96rpx;
background: linear-gradient(135deg, #E3393C 0%, #F44336 100%);
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(227, 57, 60, 0.35);
border: none;
margin: 0 auto;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.exchange-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: translate(-50%, -50%);
transition: width 0.6s, height 0.6s;
}
.exchange-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(227, 57, 60, 0.3);
}
.exchange-btn:active::before {
width: 200%;
height: 200%;
}
.btn-text {
font-size: 32rpx;
color: #ffffff;
font-weight: bold;
letter-spacing: 2rpx;
position: relative;
z-index: 1;
}
/* 兑换规则样式优化 */
.van-cell-group {
margin-top: 30rpx;
border-radius: 24rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
/* 移除旧样式 */
.form-box,
.row-wrap,
.save-btn,
.cancel-btn,
.addr-details {
display: none;
}
/* 保留的通用样式 */
picker {
min-width: 20rpx;
height: 100%;
margin-right: 20rpx;
}
.hui {
color: #777;
}
================================================
FILE: pages/score-excharge/index.js
================================================
const app = getApp()
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
uid: undefined
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
},
onShow: function() {
},
bindSave(e) {
var that = this;
var amount = this.data.amount;
if (amount == "") {
wx.showModal({
title: '错误',
content: '请填写正确的券号',
showCancel: false
})
return
}
WXAPI.scoreExchange(wx.getStorageSync('token'), amount).then(function(res) {
if (res.code == 700) {
wx.showModal({
title: '错误',
content: '券号不正确',
showCancel: false
})
return
}
if (res.code == 0) {
wx.showModal({
title: '成功',
content: '恭喜您,成功兑换 ' + res.data.score + ' 积分',
showCancel: false,
success: function(res) {
if (res.confirm) {
that.bindCancel();
}
}
})
} else {
wx.showModal({
title: '错误',
content: res.data.msg,
showCancel: false
})
}
})
}
})
================================================
FILE: pages/score-excharge/index.json
================================================
{
"navigationBarTitleText": "积分券兑换积分"
}
================================================
FILE: pages/score-excharge/index.wxml
================================================
积分券兑换
输入积分券号码,立即获得积分奖励
积分券号码
•
积分券仅限本平台使用,不可转让
•
每个积分券仅可使用一次
•
兑换成功后积分将立即到账
•
如有疑问请联系客服
================================================
FILE: pages/score-excharge/index.wxss
================================================
/* 页面整体样式 - 京东风格 */
page {
height: 100%;
background: linear-gradient(180deg, #FFF1F0 0%, #FFFFFF 50%);
}
.exchange-page {
min-height: 100vh;
position: relative;
overflow: hidden;
}
/* 头部装饰区域 - 京东红色系 */
.header-decoration {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 400rpx;
pointer-events: none;
overflow: hidden;
}
.decoration-circle {
position: absolute;
border-radius: 50%;
opacity: 0.08;
}
.decoration-circle.circle1 {
width: 260rpx;
height: 260rpx;
background: linear-gradient(135deg, #E1251B, #FF4747);
top: -130rpx;
right: -80rpx;
}
.decoration-circle.circle2 {
width: 180rpx;
height: 180rpx;
background: linear-gradient(135deg, #E1251B, #FF6B6B);
top: 100rpx;
left: -60rpx;
}
.decoration-circle.circle3 {
width: 140rpx;
height: 140rpx;
background: linear-gradient(135deg, #FF4747, #FF8989);
top: 260rpx;
right: 120rpx;
}
/* 主要内容区域 */
.exchange-content {
padding: 80rpx 32rpx 40rpx;
position: relative;
z-index: 1;
}
/* 标题区域 - 京东风格 */
.title-section {
text-align: center;
margin-bottom: 60rpx;
}
.icon-wrapper {
width: 120rpx;
height: 120rpx;
background: linear-gradient(135deg, #E1251B 0%, #FF4747 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 32rpx;
box-shadow: 0 12rpx 32rpx rgba(225, 37, 27, 0.35);
position: relative;
}
.icon-wrapper::after {
content: '';
position: absolute;
width: 140rpx;
height: 140rpx;
border: 2rpx solid rgba(225, 37, 27, 0.2);
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.15);
opacity: 0.5;
}
}
.gift-icon {
width: 60rpx;
height: 60rpx;
filter: brightness(0) invert(1);
}
.main-title {
display: block;
font-weight: 700;
font-size: 52rpx;
color: #333333;
margin-bottom: 16rpx;
letter-spacing: 2rpx;
}
.sub-title {
display: block;
font-size: 28rpx;
color: #999999;
line-height: 40rpx;
}
/* 兑换表单 - 京东卡片风格 */
.exchange-form {
background: #FFFFFF;
border-radius: 24rpx;
padding: 48rpx 40rpx;
margin-bottom: 40rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
position: relative;
}
.exchange-form::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 8rpx;
background: linear-gradient(90deg, #E1251B 0%, #FF4747 100%);
border-radius: 24rpx 24rpx 0 0;
}
.form-item {
margin-bottom: 48rpx;
}
.form-label {
display: block;
font-weight: 600;
font-size: 30rpx;
color: #333333;
margin-bottom: 24rpx;
position: relative;
padding-left: 20rpx;
}
.form-label::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: linear-gradient(180deg, #E1251B, #FF4747);
border-radius: 3rpx;
}
.input-wrapper {
position: relative;
background: #F8F9FA;
border-radius: 16rpx;
border: 2rpx solid #E9ECEF;
transition: all 0.3s ease;
overflow: hidden;
}
.input-wrapper::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 0;
height: 4rpx;
background: linear-gradient(90deg, #E1251B, #FF4747);
transition: width 0.3s ease;
}
/* 聚焦状态 */
.coupon-input:focus {
background: #FFFFFF;
}
.input-wrapper:focus-within {
border-color: #E1251B;
background: #FFFFFF;
box-shadow: 0 0 0 6rpx rgba(225, 37, 27, 0.08);
}
.input-wrapper:focus-within::after {
width: 100%;
}
.coupon-input {
width: 100%;
height: 96rpx;
padding: 0 32rpx;
font-size: 32rpx;
color: #333333;
background: transparent;
border: none;
line-height: 96rpx;
}
.input-placeholder {
color: #BBBBBB;
font-size: 28rpx;
}
/* 兑换按钮 - 京东红 */
.exchange-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #E1251B 0%, #FF4747 100%);
border-radius: 48rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(225, 37, 27, 0.35);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.exchange-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s ease;
}
.exchange-btn:active::before {
left: 100%;
}
.exchange-btn:active {
transform: translateY(2rpx);
box-shadow: 0 4rpx 16rpx rgba(225, 37, 27, 0.3);
}
.exchange-btn::after {
border: none;
}
.btn-text {
font-weight: 600;
font-size: 34rpx;
color: #FFFFFF;
letter-spacing: 4rpx;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
}
/* 使用说明 - 京东风格 */
.tips-section {
background: #FFFFFF;
border-radius: 24rpx;
padding: 40rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
.tips-header {
display: flex;
align-items: center;
margin-bottom: 32rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #F5F5F5;
}
.info-icon {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: linear-gradient(135deg, #E1251B, #FF4747);
color: #FFFFFF;
font-size: 24rpx;
font-weight: bold;
font-style: italic;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
}
.tips-title {
font-weight: 600;
font-size: 30rpx;
color: #333333;
}
.tips-list {
padding-left: 8rpx;
}
.tips-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
padding-left: 12rpx;
}
.tips-item:last-child {
margin-bottom: 0;
}
.tips-dot {
font-weight: 700;
font-size: 32rpx;
color: #E1251B;
margin-right: 16rpx;
line-height: 40rpx;
flex-shrink: 0;
}
.tips-text {
flex: 1;
font-size: 26rpx;
color: #666666;
line-height: 40rpx;
}
================================================
FILE: pages/search/index.js
================================================
Page({
data: {
},
onLoad: function (options) {
const hot_search_words = wx.getStorageSync('hot_search_words')
this.setData({
list: wx.getStorageSync('searchHis'),
hot_search_words: hot_search_words ? hot_search_words.split(',') : null
})
},
onShow: function () {
},
search(e) {
this.setData({
inputVal: e.detail
})
if (e.detail) {
let searchHis = wx.getStorageSync('searchHis')
if (!searchHis) {
searchHis = [e.detail]
}
if (!searchHis.includes(e.detail)) {
searchHis.push(e.detail)
}
wx.setStorageSync('searchHis', searchHis)
this.setData({
list: searchHis
})
}
wx.navigateTo({
url: '/pages/goods/list?name=' + this.data.inputVal,
})
},
onClose(e) {
const idx = e.currentTarget.dataset.idx
const searchHis = this.data.list
searchHis.splice(idx, 1)
wx.setStorageSync('searchHis', searchHis)
this.setData({
list: searchHis
})
},
go(e) {
const idx = e.currentTarget.dataset.idx
const keywords = this.data.list[idx]
wx.navigateTo({
url: '/pages/goods/list?name=' + keywords,
})
},
go2(e) {
const idx = e.currentTarget.dataset.idx
const keywords = this.data.hot_search_words[idx]
wx.navigateTo({
url: '/pages/goods/list?name=' + keywords,
})
},
searchscan() {
wx.scanCode({
scanType: ['barCode', 'qrCode', 'datamatrix', 'pdf417'],
success: res => {
wx.navigateTo({
url: '/pages/goods/list?name=' + res.result,
})
}
})
}
})
================================================
FILE: pages/search/index.json
================================================
{
"navigationBarTitleText": "搜索"
}
================================================
FILE: pages/search/index.wxml
================================================
{{ item }}
{{ index + 1 }}
{{ item }}
暂无搜索记录
快去搜索你想要的商品吧~
================================================
FILE: pages/search/index.wxss
================================================
/* pages/search/index.wxss - 京东风格搜索页面 */
/* 页面整体 */
.search-page {
min-height: 100vh;
background: linear-gradient(180deg, #E4393C 0%, #E4393C 120rpx, #f5f5f5 120rpx);
}
/* ==================== 搜索头部区域 ==================== */
.search-header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background: #E4393C;
padding: 16rpx 24rpx;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.15);
}
.search-container {
position: relative;
}
/* 覆盖van-search默认样式 */
.search-header .van-search {
padding: 0;
}
.search-header .van-search__content {
background: rgba(255, 255, 255, 0.95);
border-radius: 48rpx;
padding-left: 32rpx;
padding-right: 32rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
}
.search-header .van-field__control {
font-size: 28rpx;
color: #333;
}
.scan-icon {
display: flex;
align-items: center;
justify-content: center;
width: 56rpx;
height: 56rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
border-radius: 50%;
margin-left: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.3);
}
/* ==================== 内容区域 ==================== */
.search-content {
padding-top: 120rpx;
padding-bottom: 40rpx;
}
/* ==================== 搜索区块 ==================== */
.search-section {
margin: 32rpx 24rpx;
background: #fff;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
/* 区块头部 */
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24rpx;
}
.header-left {
display: flex;
align-items: center;
}
.icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 48rpx;
height: 48rpx;
background: linear-gradient(135deg, #FFE5E5 0%, #FFD5D5 100%);
border-radius: 12rpx;
margin-right: 16rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
letter-spacing: 0.5rpx;
}
/* ==================== 标签容器 ==================== */
.tag-container {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.tag-item {
position: relative;
display: flex;
align-items: center;
padding: 16rpx 32rpx;
background: #f8f8f8;
border-radius: 48rpx;
font-size: 28rpx;
color: #666;
transition: all 0.3s ease;
border: 2rpx solid transparent;
}
.tag-item:active {
background: #fff;
border-color: #E4393C;
transform: translateY(-2rpx);
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.15);
}
.tag-text {
max-width: 400rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 关闭按钮 */
.tag-close {
display: flex;
align-items: center;
justify-content: center;
width: 32rpx;
height: 32rpx;
margin-left: 12rpx;
background: #e8e8e8;
border-radius: 50%;
transition: all 0.2s ease;
}
.tag-close:active {
background: #E4393C;
}
.tag-close:active .van-icon {
color: #fff !important;
}
/* ==================== 热门标签特殊样式 ==================== */
.hot-tag {
background: linear-gradient(135deg, #FFF5F5 0%, #FFE8E8 100%);
color: #E4393C;
font-weight: 500;
border: 2rpx solid #FFD5D5;
padding-left: 24rpx;
}
.hot-tag:active {
background: linear-gradient(135deg, #FFE8E8 0%, #FFD5D5 100%);
border-color: #E4393C;
box-shadow: 0 4rpx 16rpx rgba(228, 57, 60, 0.2);
}
.hot-badge {
display: flex;
align-items: center;
justify-content: center;
width: 32rpx;
height: 32rpx;
background: linear-gradient(135deg, #FF6B6B 0%, #E4393C 100%);
color: #fff;
font-size: 20rpx;
font-weight: 600;
border-radius: 50%;
margin-right: 12rpx;
box-shadow: 0 2rpx 8rpx rgba(228, 57, 60, 0.3);
}
/* ==================== 空状态 ==================== */
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 48rpx;
margin: 80rpx 24rpx;
background: #fff;
border-radius: 24rpx;
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
}
.empty-icon {
width: 160rpx;
height: 160rpx;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #f8f8f8 0%, #f0f0f0 100%);
border-radius: 50%;
margin-bottom: 32rpx;
}
.empty-text {
font-size: 32rpx;
color: #999;
margin-bottom: 16rpx;
font-weight: 500;
}
.empty-tip {
font-size: 26rpx;
color: #ccc;
}
/* ==================== 动画效果 ==================== */
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.search-section {
animation: slideInUp 0.4s ease-out;
}
/* ==================== 响应式优化 ==================== */
@media (max-width: 375px) {
.tag-item {
padding: 14rpx 28rpx;
font-size: 26rpx;
}
.section-title {
font-size: 30rpx;
}
}
================================================
FILE: pages/select-address/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const app = getApp()
Page({
data: {
page: 1
},
selectTap: function(e) {
console.log(e);
var id = e.currentTarget.dataset.id;
WXAPI.updateAddress({
token: wx.getStorageSync('token'),
id: id,
isDefault: 'true'
}).then(function(res) {
wx.navigateBack({})
})
},
addAddess: function() {
wx.navigateTo({
url: "/pages/address-add/index"
})
},
editAddess: function(e) {
console.log(e);
wx.navigateTo({
url: "/pages/address-add/index?id=" + e.currentTarget.dataset.id
})
},
onLoad() {
},
onShow: function() {
this.initShippingAddress();
},
async initShippingAddress() {
wx.showLoading({
title: '',
})
const res = await WXAPI.queryAddressV2({
token: wx.getStorageSync('token')
})
wx.hideLoading({
success: (res) => {},
})
if (res.code == 0) {
this.setData({
addressList: res.data.result
});
} else if (res.code == 700) {
this.setData({
addressList: null
});
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
},
onPullDownRefresh() {
this.data.page = 1
this.initShippingAddress()
wx.stopPullDownRefresh()
},
deleteAddress(e) {
const id = e.currentTarget.dataset.id
const index = e.currentTarget.dataset.index
wx.showModal({
content: '确定要删除该收货地址吗?',
success: async (res) => {
if (res.confirm) {
// https://www.yuque.com/apifm/nu0f75/gb0a2k
wx.showLoading({
title: '',
})
const res = await WXAPI.deleteAddress(wx.getStorageSync('token'), id)
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '删除成功',
icon: 'none'
})
this.data.addressList.splice(index, 1)
this.setData({
addressList: this.data.addressList
})
}
}
}
})
},
})
================================================
FILE: pages/select-address/index.json
================================================
{
"navigationBarTitleText": "选择收货地址",
"enablePullDownRefresh": true
}
================================================
FILE: pages/select-address/index.wxml
================================================
{{item.address}}
编辑
删除
新增收货地址
================================================
FILE: pages/select-address/index.wxss
================================================
/* 容器样式 */
.address-container {
min-height: 100vh;
background-color: #f5f5f5;
padding: 20rpx;
box-sizing: border-box;
}
/* 地址列表 */
.address-list {
margin-bottom: 120rpx;
}
/* 地址卡片 */
.address-item {
background: #ffffff;
border-radius: 16rpx;
margin-bottom: 20rpx;
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
}
.address-item:active {
transform: scale(0.98);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12);
}
/* 地址内容区域 */
.address-content {
padding: 32rpx 28rpx 24rpx;
position: relative;
}
/* 地址头部 */
.address-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
/* 用户信息 */
.user-info {
display: flex;
align-items: center;
gap: 20rpx;
}
.user-name {
font-size: 32rpx;
font-weight: 600;
color: #333333;
letter-spacing: 1rpx;
}
.user-phone {
font-size: 30rpx;
color: #666666;
font-weight: 500;
}
/* 默认地址标签 */
.default-tag {
background: linear-gradient(135deg, #ff6a00 0%, #ee0a24 100%);
color: #ffffff;
font-size: 22rpx;
padding: 6rpx 16rpx;
border-radius: 24rpx;
font-weight: 500;
letter-spacing: 1rpx;
box-shadow: 0 2rpx 8rpx rgba(238, 10, 36, 0.25);
}
/* 地址详情 */
.address-detail {
display: flex;
align-items: flex-start;
line-height: 1.6;
}
.address-text {
font-size: 28rpx;
color: #666666;
line-height: 42rpx;
word-break: break-all;
}
/* 操作按钮区域 */
.address-actions {
display: flex;
align-items: center;
border-top: 1rpx solid #f0f0f0;
background: #fafafa;
}
.action-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
padding: 24rpx 0;
font-size: 28rpx;
color: #666666;
transition: all 0.2s ease;
}
.action-btn:active {
background: #f0f0f0;
}
.action-btn text {
font-weight: 500;
}
.edit-btn {
color: #333333;
}
.delete-btn {
color: #ee0a24;
}
.action-divider {
width: 1rpx;
height: 32rpx;
background: #e5e5e5;
}
/* 底部操作区 */
.safe-bottom-box {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 30rpx;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
background: linear-gradient(to top, rgba(255,255,255,0.98) 0%, rgba(255,255,255,0.95) 100%);
backdrop-filter: blur(10rpx);
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
z-index: 100;
box-sizing: border-box;
}
.add-btn {
width: 100%;
height: 88rpx;
background: linear-gradient(135deg, #ff6a00 0%, #ee0a24 100%);
border-radius: 44rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 12rpx;
color: #ffffff;
font-size: 32rpx;
font-weight: 600;
letter-spacing: 2rpx;
box-shadow: 0 8rpx 20rpx rgba(238, 10, 36, 0.3);
transition: all 0.3s ease;
box-sizing: border-box;
}
.add-btn:active {
transform: scale(0.96);
box-shadow: 0 4rpx 12rpx rgba(238, 10, 36, 0.4);
}
================================================
FILE: pages/shop/select.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
const APP = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
wx.getLocation({
type: 'gcj02', //wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标
success: (res) => {
this.data.latitude = res.latitude
this.data.longitude = res.longitude
this.fetchShops(res.latitude, res.longitude, '')
},
fail(e){
console.error(e)
AUTH.checkAndAuthorize('scope.userLocation')
}
})
},
async fetchShops(latitude, longitude, kw){
const res = await WXAPI.fetchShops({
curlatitude: latitude,
curlongitude: longitude,
nameLike: kw
})
if (res.code == 0) {
res.data.forEach(ele => {
ele.distance = ele.distance.toFixed(3) // 距离保留3位小数
})
this.setData({
shops: res.data
})
} else {
this.setData({
shops: null
})
}
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
searchChange(event){
this.setData({
searchValue: event.detail.value
})
},
search(event){
console.log('search')
this.setData({
searchValue: event.detail.value
})
this.fetchShops(this.data.latitude, this.data.longitude, event.detail.value)
},
goShop(e){
const idx = e.currentTarget.dataset.idx
wx.setStorageSync('shopInfo', this.data.shops[idx])
wx.setStorageSync('shopIds', this.data.shops[idx].id)
wx.setStorageSync('refreshIndex', 1)
wx.switchTab({
url: '/pages/index/index'
})
}
})
================================================
FILE: pages/shop/select.json
================================================
{
"usingComponents": {},
"navigationBarTitleText": "选择门店"
}
================================================
FILE: pages/shop/select.wxml
================================================
{{ item.address }}
{{ item.openingHours }}
{{ item.linkPhone }}
选择门店
================================================
FILE: pages/shop/select.wxss
================================================
/* 页面容器 */
.page-container {
min-height: 100vh;
background: linear-gradient(to bottom, #f5f5f5 0%, #ffffff 300rpx);
}
/* ==================== 搜索栏样式 ==================== */
.search-wrapper {
padding: 24rpx 24rpx 20rpx;
background: #ffffff;
}
.search-box {
position: relative;
background: #f5f5f5;
border-radius: 36rpx;
height: 72rpx;
display: flex;
align-items: center;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
}
.search-icon {
position: absolute;
width: 32rpx;
height: 32rpx;
left: 28rpx;
z-index: 2;
}
.search-input {
flex: 1;
height: 72rpx;
padding-left: 72rpx;
padding-right: 28rpx;
font-size: 28rpx;
color: #333;
}
.search-placeholder {
color: #999;
font-size: 28rpx;
}
/* ==================== 门店列表容器 ==================== */
.shops-container {
padding: 0 24rpx 24rpx;
}
/* ==================== 门店卡片样式 ==================== */
.shop-card {
position: relative;
background: #ffffff;
border-radius: 16rpx;
margin-top: 24rpx;
padding: 32rpx 28rpx 28rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
overflow: hidden;
}
/* 最近门店卡片特殊样式 */
.shop-card-nearest {
border: 2rpx solid #E93B3D;
box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.15);
}
/* ==================== 门店头部 ==================== */
.shop-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
padding-right: 12rpx;
}
.shop-name-wrapper {
display: flex;
align-items: center;
flex: 1;
}
.shop-icon {
width: 32rpx;
height: 38rpx;
margin-right: 16rpx;
}
.shop-name {
font-size: 32rpx;
color: #333333;
font-weight: 600;
letter-spacing: 0.5rpx;
line-height: 44rpx;
}
.shop-name-active {
color: #E93B3D;
}
/* 距离显示 */
.distance-wrapper {
display: flex;
align-items: baseline;
padding: 8rpx 16rpx;
background: #f5f5f5;
border-radius: 24rpx;
margin-left: 16rpx;
}
.distance-active {
background: linear-gradient(135deg, #FFE8E8 0%, #FFE0E0 100%);
}
.distance-num {
font-size: 32rpx;
font-weight: 600;
color: #333333;
letter-spacing: 0.5rpx;
}
.distance-active .distance-num {
color: #E93B3D;
}
.distance-unit {
font-size: 24rpx;
color: #666666;
margin-left: 4rpx;
}
.distance-active .distance-unit {
color: #E93B3D;
}
/* ==================== 门店信息 ==================== */
.shop-info {
background: #f9f9f9;
border-radius: 12rpx;
padding: 24rpx 20rpx;
margin-bottom: 24rpx;
}
.info-item {
display: flex;
align-items: flex-start;
margin-bottom: 20rpx;
}
.info-item:last-child {
margin-bottom: 0;
}
.info-icon {
width: 28rpx;
height: 28rpx;
margin-right: 16rpx;
margin-top: 2rpx;
flex-shrink: 0;
}
.info-text {
flex: 1;
font-size: 26rpx;
color: #666666;
line-height: 38rpx;
letter-spacing: 0.3rpx;
}
/* ==================== 操作按钮 ==================== */
.shop-action {
margin-top: 8rpx;
}
/* 进入门店按钮 */
.btn-enter-shop {
width: 100%;
height: 80rpx;
background: linear-gradient(135deg, #E93B3D 0%, #F54749 100%);
border-radius: 40rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 20rpx rgba(233, 59, 61, 0.25);
transition: all 0.3s ease;
}
.btn-enter-shop::after {
border: none;
}
.btn-text {
font-size: 30rpx;
color: #ffffff;
font-weight: 600;
letter-spacing: 2rpx;
}
/* 选择门店按钮 */
.btn-select-shop {
width: 100%;
height: 80rpx;
background: #ffffff;
border: 2rpx solid #E93B3D;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
position: relative;
transition: all 0.3s ease;
}
.btn-select-text {
font-size: 30rpx;
color: #E93B3D;
font-weight: 500;
letter-spacing: 1rpx;
}
.btn-arrow {
width: 20rpx;
height: 20rpx;
margin-left: 12rpx;
}
/* ==================== 响应式优化 ==================== */
@media (max-width: 375px) {
.shop-name {
font-size: 30rpx;
}
.distance-num {
font-size: 28rpx;
}
.info-text {
font-size: 24rpx;
}
}
/* ==================== 动画效果 ==================== */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.shop-card {
animation: fadeIn 0.4s ease-out;
}
================================================
FILE: pages/shop-cart/index.js
================================================
const WXAPI = require('apifm-wxapi')
const TOOLS = require('../../utils/tools.js')
const AUTH = require('../../utils/auth')
const app = getApp()
Page({
data: {
shopCarType: 0, //0自营 1云货架
saveHidden: true,
allSelect: true,
delBtnWidth: 120, //删除按钮宽度单位(rpx)
},
//获取元素自适应后的实际宽度
getEleWidth: function (w) {
var real = 0;
try {
var res = wx.getSystemInfoSync().windowWidth
var scale = (750 / 2) / (w / 2)
// console.log(scale);
real = Math.floor(res / scale);
return real;
} catch (e) {
return false;
// Do something when catch error
}
},
initEleWidth: function () {
var delBtnWidth = this.getEleWidth(this.data.delBtnWidth);
this.setData({
delBtnWidth: delBtnWidth
});
},
onLoad: function () {
this.initEleWidth();
this.onShow();
this.setData({
shopping_cart_vop_open: wx.getStorageSync('shopping_cart_vop_open')
})
},
onShow: function () {
this.shippingCarInfo()
},
async shippingCarInfo() {
const token = wx.getStorageSync('token')
if (!token) {
return
}
if (this.data.shopCarType == 0) { //自营购物车
var res = await WXAPI.shippingCarInfo(token)
} else if (this.data.shopCarType == 1) { //云货架购物车
var res = await WXAPI.jdvopCartInfoV2(token)
}
if (res.code == 0) {
if (this.data.shopCarType == 0) //自营商品
{
res.data.items.forEach(ele => {
if (!ele.stores || ele.status == 1) {
ele.selected = false
}
})
}
this.setData({
shippingCarInfo: res.data
})
} else {
this.setData({
shippingCarInfo: null
})
}
},
toIndexPage: function () {
wx.switchTab({
url: "/pages/index/index"
});
},
touchS: function (e) {
if (e.touches.length == 1) {
this.setData({
startX: e.touches[0].clientX
});
}
},
touchM: function (e) {
const index = e.currentTarget.dataset.index;
if (e.touches.length == 1) {
var moveX = e.touches[0].clientX;
var disX = this.data.startX - moveX;
var delBtnWidth = this.data.delBtnWidth;
var left = "";
if (disX == 0 || disX < 0) { //如果移动距离小于等于0,container位置不变
left = "margin-left:0px";
} else if (disX > 0) { //移动距离大于0,container left值等于手指移动距离
left = "margin-left:-" + disX + "px";
if (disX >= delBtnWidth) {
left = "left:-" + delBtnWidth + "px";
}
}
this.data.shippingCarInfo.items[index].left = left
this.setData({
shippingCarInfo: this.data.shippingCarInfo
})
}
},
touchE: function (e) {
var index = e.currentTarget.dataset.index;
if (e.changedTouches.length == 1) {
var endX = e.changedTouches[0].clientX;
var disX = this.data.startX - endX;
var delBtnWidth = this.data.delBtnWidth;
//如果距离小于删除按钮的1/2,不显示删除按钮
var left = disX > delBtnWidth / 2 ? "margin-left:-" + delBtnWidth + "px" : "margin-left:0px";
this.data.shippingCarInfo.items[index].left = left
this.setData({
shippingCarInfo: this.data.shippingCarInfo
})
}
},
async delItem(e) {
const key = e.currentTarget.dataset.key
this.delItemDone(key)
},
async delItemDone(key) {
const token = wx.getStorageSync('token')
if(this.data.shopCarType == 0){
var res = await WXAPI.shippingCarInfoRemoveItem(token, key)
}
if(this.data.shopCarType == 1){
var res = await WXAPI.jdvopCartRemoveV2(token, key)
}
if (res.code != 0 && res.code != 700) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
this.shippingCarInfo()
TOOLS.showTabBarBadge()
}
},
async jiaBtnTap(e) {
const index = e.currentTarget.dataset.index;
const item = this.data.shippingCarInfo.items[index]
const number = item.number + 1
const token = wx.getStorageSync('token')
if(this.data.shopCarType == 0){
var res = await WXAPI.shippingCarInfoModifyNumber(token, item.key, number)
}
else if(this.data.shopCarType == 1){
var res = await WXAPI.jdvopCartModifyNumberV2(token, item.key, number)
}
this.shippingCarInfo()
},
async jianBtnTap(e) {
const index = e.currentTarget.dataset.index;
const item = this.data.shippingCarInfo.items[index]
const number = item.number - 1
if (number <= 0) {
// 弹出删除确认
wx.showModal({
content: '确定要删除该商品吗?',
success: (res) => {
if (res.confirm) {
this.delItemDone(item.key)
}
}
})
return
}
const token = wx.getStorageSync('token')
if(this.data.shopCarType == 0)
{
var res = await WXAPI.shippingCarInfoModifyNumber(token, item.key, number)
}
if(this.data.shopCarType == 1)
{
var res = await WXAPI.jdvopCartModifyNumberV2(token, item.key, number)
}
this.shippingCarInfo()
},
changeCarNumber(e) {
const key = e.currentTarget.dataset.key
const num = e.detail.value
const token = wx.getStorageSync('token')
if(this.data.shopCarType == 0){
WXAPI.shippingCarInfoModifyNumber(token, key, num).then(res => {
this.shippingCarInfo()
})}
else if(this.data.shopCarType == 1){
WXAPI.jdvopCartModifyNumberV2(token, key, num).then(res => {
this.shippingCarInfo()
})
}
},
async radioClick(e) {
var index = e.currentTarget.dataset.index;
var item = this.data.shippingCarInfo.items[index]
const token = wx.getStorageSync('token')
if (this.data.shopCarType == 0) { //自营购物车
if (!item.stores || item.status == 1) {
return
}
var res = await WXAPI.shippingCartSelected(token, item.key, !item.selected)
} else if (this.data.shopCarType == 1) { //云货架购物车
var res = await WXAPI.jdvopCartSelectV2(token, item.key, !item.selected)
}
this.shippingCarInfo()
},
onChange(event) {
this.setData({
shopCarType: event.detail.name
})
this.shippingCarInfo()
},
goDetail(e) {
const item = e.currentTarget.dataset.item
wx.navigateTo({
url: '/pages/goods-details/index?id=' + item.goodsId,
})
},
})
================================================
FILE: pages/shop-cart/index.json
================================================
{
"navigationBarTitleText": "购物车"
}
================================================
FILE: pages/shop-cart/index.wxml
================================================
================================================
FILE: pages/shop-cart/index.wxss
================================================
@import "../template-cart/template-cart.wxss";
page{
min-height: 100%;
background-color: #F2f2f2;
}
.container {
background-color: #F2f2f2;
min-height: 100%;
}
.pos-fiexd{
position: fixed;
bottom: 0;
left: 0;
}
.vtabs{
width: 100vw;
}
================================================
FILE: pages/sign/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
minDate: new Date().getTime(),
maxDate: new Date().getTime(),
formatter(day) {
return day;
},
useFingerprintEmoji: false // 默认用图片,支持Unicode 16及以上的操作系统才用指纹emoji()
},
onLoad: function(options) {
this.scoreSignLogs()
this.setData({ useFingerprintEmoji: this.shouldUseFingerprintEmoji() });
},
onShow: function() {
AUTH.checkHasLogined().then(isLogined => {
if (!isLogined) {
AUTH.login(this)
}
})
},
async scoreSignLogs() {
const res = await WXAPI.scoreSignLogs({
token: wx.getStorageSync('token')
})
if (res.code == 0) {
this.setData({
scoreSignLogs: res.data.result,
formatter(day) {
const _log = res.data.result.find(ele => {
const year = day.date.getYear() + 1900
let month = day.date.getMonth() + 1
month = month + ''
if (month.length == 1) {
month = '0' + month
}
let date = day.date.getDate() + ''
if (date.length == 1) {
date = '0' + date
}
return ele.dateAdd.indexOf(`${year}-${month}-${date}`) == 0
})
if (_log) {
day.bottomInfo = '已签到'
}
return day;
}
})
}
},
async sign() {
const res = await WXAPI.scoreSign(wx.getStorageSync('token'))
if (res.code == 10000) {
wx.showToast({
title: '签到成功',
icon: 'success'
})
this.scoreSignLogs()
return
}
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '签到成功',
icon: 'success'
})
this.scoreSignLogs()
}
},
/* 简单版判断:满足 Win11-25H2 及以上 / Android16+ / iOS18.4+ 返回 true */
shouldUseFingerprintEmoji() {
try {
const info = wx.getDeviceInfo ? wx.getDeviceInfo() : wx.getSystemInfoSync();
const plat = (info.platform || '').toLowerCase();
const sys = info.system || '';
if (plat === 'android') {
const m = sys.match(/Android\s+(\d+)/);
return m ? (parseInt(m[1]) >= 16) : false;
}
if (plat === 'ios') {
const m = sys.match(/iOS\s+(\d+)\.(\d+)/);
if (!m) return false;
const major = parseInt(m[1]);
const minor = parseInt(m[2]);
return major > 18 || (major === 18 && minor >= 4);
}
if (plat === 'windows' || plat === 'win32') { // 开发者工具里 platform 可能是 windows
const m = sys.match(/Windows\s+(\d+)\s*H(\d+)/);
if (!m) return false;
const build = parseInt(m[1]);
const h = parseInt(m[2]);
return build >= 25 && h >= 2; // 25H2 及以上
}
} catch (e) { /* 忽略错误,统一走图片 */ }
return false; // 其余系统或解析失败都用 png
}
})
================================================
FILE: pages/sign/index.json
================================================
{
"navigationBarTitleText": "每日签到"
}
================================================
FILE: pages/sign/index.wxml
================================================
点击签到
================================================
FILE: pages/sign/index.wxss
================================================
.todo-dot-bottom {
color: red !important;
}
.zwqd-box {
text-align: center;
margin: auto;
margin-top: 32rpx;
}
.zwqd-box image {
width: 140rpx;
height: 140rpx;
margin: auto;
}
.zwqd-box view {
margin-top: 16rpx;
color: #999;
font-size: 26rpx;
}
.emoji-icon {
display: block; /* 同 image 默认 block */
width: 140rpx;
height: 140rpx;
margin: auto;
font-size: 110rpx; /* 视觉上与 140rpx 图片接近,可自行微调 */
line-height: 140rpx;
text-align: center;
cursor: pointer;
}
================================================
FILE: pages/start/start.js
================================================
const WXAPI = require('apifm-wxapi')
const CONFIG = require('../../config.js')
Page({
data: {
swiperMaxNumber: 0,
swiperCurrent: 0
},
onLoad(e){
// e.shopId = 6040 // 测试,测试完了注释掉
this.data.shopId = e.shopId
this.readConfigVal()
// 补偿写法
getApp().configLoadOK = () => {
this.readConfigVal()
}
},
onShow:function(){
},
async readConfigVal() {
const mallName = wx.getStorageSync('mallName')
if (!mallName) {
return
}
wx.setNavigationBarTitle({
title: wx.getStorageSync('mallName')
})
let shopMod = wx.getStorageSync('shopMod')
if (!shopMod) {
shopMod = 0
}
const app_show_pic_version = wx.getStorageSync('app_show_pic_version')
if (app_show_pic_version && app_show_pic_version == CONFIG.version) {
if (shopMod==1) {
this.goShopSelectPage()
} else {
wx.switchTab({
url: '/pages/index/index',
})
}
} else {
// 展示启动页
const res = await WXAPI.banners({
type: 'app'
})
if (res.code == 700) {
if (shopMod==1) {
this.goShopSelectPage()
} else {
wx.switchTab({
url: '/pages/index/index',
})
}
} else {
this.setData({
banners: res.data,
swiperMaxNumber: res.data.length
});
}
}
},
swiperchange: function (e) {
//console.log(e.detail.current)
this.setData({
swiperCurrent: e.detail.current
})
},
goLeft() {
if (this.data.swiperCurrent == 0) {
this.setData({
swiperCurrent: this.data.swiperMaxNumber - 1
})
} else {
this.setData({
swiperCurrent: this.data.swiperCurrent - 1
})
}
},
goRight() {
if (this.data.swiperCurrent == this.data.swiperMaxNumber - 1) {
this.setData({
swiperCurrent: 0
})
} else {
this.setData({
swiperCurrent: this.data.swiperCurrent + 1
})
}
},
goToIndex: function (e) {
let shopMod = wx.getStorageSync('shopMod')
if (!shopMod) {
shopMod = 0
}
if (getApp().globalData.isConnected) {
wx.setStorage({
key: 'app_show_pic_version',
data: CONFIG.version
})
if (shopMod == 1) {
this.goShopSelectPage()
} else {
wx.switchTab({
url: '/pages/index/index',
});
}
} else {
wx.showToast({
title: '当前无网络',
icon: 'none',
})
}
},
async goShopSelectPage() {
if (!this.data.shopId) {
wx.redirectTo({
url: '/pages/shop/select'
})
return
}
// 有传入门店ID
const res = await WXAPI.shopSubdetail(this.data.shopId)
if (res.code != 0) {
wx.redirectTo({
url: '/pages/shop/select'
})
return
}
wx.setStorageSync('shopInfo', res.data.info)
wx.setStorageSync('shopIds', res.data.info.id)
wx.switchTab({
url: '/pages/index/index'
})
}
});
================================================
FILE: pages/start/start.json
================================================
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"disableScroll": true,
"navigationStyle": "custom"
}
================================================
FILE: pages/start/start.wxml
================================================
立即进入
精彩内容等你探索
加载中...
================================================
FILE: pages/start/start.wxss
================================================
/* 京东风格 - 启动页样式 */
/* 页面容器 */
page {
width: 100vw;
height: 100vh;
overflow: hidden;
background: #000;
}
/* 启动页主容器 */
.start-container {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
}
/* 轮播图容器 */
.swiper_box {
width: 100vw;
height: 100vh;
}
swiper-item {
width: 100vw;
height: 100vh;
}
/* 轮播项包装器 */
.swiper-item-wrapper {
width: 100%;
height: 100%;
position: relative;
}
/* 轮播图片 */
.banner-image {
width: 100vw;
height: 100vh;
display: block;
}
/* 图片渐变遮罩 - 京东风格 */
.image-mask {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 50%;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.75));
z-index: 1;
pointer-events: none;
}
/* 左右切换按钮样式 - 优雅半透明风格 */
.swiper-icon {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 80rpx;
height: 80rpx;
background: rgba(255, 255, 255, 0.15);
border: 2rpx solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
backdrop-filter: blur(20rpx);
z-index: 10;
transition: all 0.3s ease;
}
.swiper-icon.left-icon {
left: 40rpx;
}
.swiper-icon.right-icon {
right: 40rpx;
}
.swiper-icon:active {
transform: translateY(-50%) scale(0.9);
background: rgba(255, 255, 255, 0.25);
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
}
.swiper-icon image {
width: 32rpx;
height: 32rpx;
filter: brightness(0) invert(1);
}
/* 指示器容器 */
.dots-wrapper {
position: absolute;
bottom: 260rpx;
left: 0;
width: 100%;
display: flex;
justify-content: center;
z-index: 10;
}
.dots-container {
display: flex;
align-items: center;
gap: 12rpx;
padding: 12rpx 24rpx;
background: rgba(0, 0, 0, 0.25);
backdrop-filter: blur(10rpx);
border-radius: 40rpx;
}
/* 指示器小点 */
.dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: rgba(255, 255, 255, 0.4);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* 指示器激活状态 - 京东红色 */
.dot-active {
width: 48rpx;
height: 16rpx;
border-radius: 8rpx;
background: linear-gradient(90deg, #E93B3D, #FF6B6B);
box-shadow: 0 4rpx 12rpx rgba(233, 59, 61, 0.4);
}
/* 底部按钮区域 */
.jump-btn-box {
position: absolute;
left: 0;
bottom: calc(env(safe-area-inset-bottom) + 80rpx);
width: 100vw;
display: flex;
flex-direction: column;
align-items: center;
z-index: 10;
gap: 24rpx;
}
/* 进入按钮 - 京东风格 */
.jump-btn {
position: relative;
padding: 28rpx 120rpx;
background: linear-gradient(135deg, #E93B3D 0%, #E61717 100%);
border-radius: 60rpx;
box-shadow: 0 12rpx 40rpx rgba(233, 59, 61, 0.45),
0 4rpx 12rpx rgba(0, 0, 0, 0.2);
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.jump-btn:active {
transform: scale(0.96);
box-shadow: 0 8rpx 28rpx rgba(233, 59, 61, 0.4),
0 2rpx 8rpx rgba(0, 0, 0, 0.2);
}
/* 按钮文字 */
.btn-text {
position: relative;
color: #FFFFFF;
font-size: 32rpx;
font-weight: 600;
letter-spacing: 2rpx;
z-index: 2;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
}
/* 按钮光泽效果 */
.btn-shine {
position: absolute;
top: -50%;
left: -100%;
width: 100%;
height: 200%;
background: linear-gradient(90deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent);
transform: skewX(-25deg);
animation: shine 3s infinite;
}
@keyframes shine {
0% {
left: -100%;
}
20% {
left: 100%;
}
100% {
left: 100%;
}
}
/* 提示文字 */
.skip-hint {
color: rgba(255, 255, 255, 0.75);
font-size: 24rpx;
letter-spacing: 1rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
animation: breath 2s ease-in-out infinite;
}
@keyframes breath {
0%, 100% {
opacity: 0.75;
}
50% {
opacity: 1;
}
}
/* 全屏加载效果样式 */
.loading-container {
width: 100vw;
height: 100vh;
background: #000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
/* 加载动画容器 */
.loading-spinner-wrapper {
width: 120rpx;
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 60rpx;
}
/* 旋转加载图标 */
.loading-spinner {
width: 80rpx;
height: 80rpx;
border: 6rpx solid rgba(255, 255, 255, 0.1);
border-top: 6rpx solid #E93B3D;
border-radius: 50%;
animation: loading-spin 1.5s linear infinite;
}
/* 加载文字 */
.loading-text {
color: rgba(255, 255, 255, 0.8);
font-size: 28rpx;
font-weight: 400;
letter-spacing: 2rpx;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.3);
animation: loading-text-fade 2s ease-in-out infinite;
}
/* 加载图标旋转动画 */
@keyframes loading-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* 加载文字淡化动画 */
@keyframes loading-text-fade {
0%, 100% {
opacity: 0.6;
}
50% {
opacity: 1;
}
}
================================================
FILE: pages/template-cart/template-cart.js
================================================
================================================
FILE: pages/template-cart/template-cart.wxml
================================================
去逛逛
{{item.name}}
{{option.optionName}}:{{option.optionValueName}}
{{option.pname}}:{{option.name}}
¥ {{item.price}}
-
+
删除
{{item.name}}
{{option.optionName}}:{{option.optionValueName}}
{{option.pname}}:{{option.name}}
¥ {{item.price}}
-
+
删除
合计:¥ {{price}} + {{score}} 积分
合计:¥ {{price}}
去结算
================================================
FILE: pages/template-cart/template-cart.wxss
================================================
.container {
justify-content: initial;
}
.no-goods-icon {
width: 382rpx;
height: 323rpx;
margin-top: 109rpx;
}
.title-box {
width: 100vw;
margin-top: 30rpx;
text-align: center;
font-size: 28rpx;
color: #999;
margin-bottom: 50rpx;
}
.to-index-btn {
line-height: 60rpx;
text-align: center;
font-size: 28rpx;
width: 140rpx;
height: 60rpx;
background: #FFD43E;
border-radius: 30px;
border: 2px solid #393640;
}
.list-top {
width: 100%;
height: 88rpx;
line-height: 88rpx;
box-sizing: border-box;
display: flex;
justify-content: space-between;
padding: 0 30rpx;
font-size: 28rpx;
align-items: center;
}
.list-top .label {
color: #000;
}
.list-top .edit-btn {
color: #999;
height: 100%;
}
.goodsList {
width: 100%;
padding-bottom: 110rpx;
}
.a-gooods {
width: 725rpx;
overflow: hidden;
position: relative;
margin-left: 18rpx;
background-color: white;
border-radius: 10rpx;
margin-top: 10rpx;
}
.a-goods-conts {
display: flex;
justify-content: space-between;
padding-left: 30rpx;
width: 850rpx;
box-sizing: border-box;
transition: margin-left 0.2s ease-in-out;
}
.goods-info {
display: flex;
padding: 30rpx 0 30rpx 0;
width: 720rpx;
box-sizing: border-box;
}
.goods-info .img-box {
width: 160rpx;
height: 160rpx;
overflow: hidden;
margin-right: 20rpx;
background-color: #d8d8d8;
flex-shrink: 0;
border-radius: 16rpx;
}
.goods-info .text-box {
width: 440rpx;
position: relative;
}
.goods-info .text-box .goods-title {
width: 450rpx;
font-size: 28rpx;
color: #000;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
padding: 10rpx 20rpx 5rpx 0;
}
.goods-info .text-box .goods-label {
font-size: 26rpx;
color: #999;
height: 38rpx;
line-height: 38rpx;
margin: 8rpx 0 25rpx 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.goods-info .text-box .goods-price {
font-size: 26rpx;
color: #e64340;
}
.goods-info .text-box .buy-num {
width: 164rpx;
height: 48rpx;
line-height: 48rpx;
position: absolute;
right: 30rpx;
bottom: 0;
display: flex;
/*justify-content: space-between;*/
font-size: 24rpx;
text-align: center;
}
.goods-info .text-box .buy-num .jian-btn {
width: 48rpx;
height: 100%;
background-color: #F2F3F5;
border-radius: 6rpx;
line-height: 46rpx;
font-size: 18px;
color: #323233;
}
.goods-info .text-box .buy-num .jian-btn.disabled {
background-color: #f5f5f9;
border-left: 1rpx solid #eee;
border-bottom: 1rpx solid #eee;
border-top: 1rpx solid #eee;
color: #ccc;
border-radius: 6rpx;
line-height: 48rpx;
font-size: 16px;
color: #323233;
}
.goods-info .text-box .buy-num .jia-btn {
width: 48rpx;
height: 100%;
border-radius: 6rpx;
background-color: #F2F3F5;
line-height: 48rpx;
font-size: 16px;
color: #323233;
}
.goods-info .text-box .buy-num .jia-btn.disabled {
background-color: #f5f5f9;
color: #ccc;
border-radius: 6rpx;
line-height: 48rpx;
font-size: 16px;
color: #323233;
}
.goods-info .text-box .buy-num input {
width: 68rpx;
height: 48rpx;
min-height: 48rpx;
text-align: center;
font-size: 24rpx;
}
.goods-info .img-box .img {
width: 160rpx;
height: 160rpx;
border-radius: 16rpx;
}
.a-goods-conts .delete-btn {
width: 120rpx;
line-height: 220rpx;
text-align: center;
background: #e64340;
font-size: 24rpx;
color: #fff;
}
.jiesuan-box {
display: flex;
justify-content: space-between;
width: 100%;
height: 100rpx;
position: fixed;
bottom: 0;
left: 0;
background-color: #FAFAFA;
z-index: 999;
}
.jiesuan-box .to-pay-btn {
text-align: center;
line-height: 76rpx;
width: 200rpx;
height: 76rpx;
background: linear-gradient(270deg, #FF972A 0%, #FF444A 100%);
border-radius: 38rpx;
margin-top: 12rpx;
margin-right: 20rpx;
color: white;
}
.jiesuan-box .to-pay-btn.no-select {
background-color: #ccc;
}
.jiesuan-box .left-price {
display: flex;
width: 510rpx;
justify-content: space-between;
line-height: 100rpx;
padding: 0 30rpx 0 32rpx;
font-size: 28rpx;
box-sizing: border-box;
}
.jiesuan-box .total {
color: #e64340;
}
.trip {
background: #e64340;
padding: 8rpx 32rpx;
color: #fff;
width: 686rpx;
font-size: 24rpx;
}
.del-icon {
position: absolute;
right: 0rpx;
top: 12rpx;
width: 50rpx;
height: 50rpx;
}
.vw100 {
width: 700rpx !important;
font-size: 24rpx !important;
}
.radio-box {
display: flex;
justify-content: center;
align-items: center;
padding: 8rpx;
}
================================================
FILE: pages/test/wifi.js
================================================
Page({
data: {
test: '1893年
奥斯曼大街上诞生了一间70平米的商铺。在128年间,它发展成为一家7万平方米的大型百货商场。它就是巴黎老佛爷奥斯曼旗舰店。
'
},
onLoad(options) {
},
onShow() {
},
})
================================================
FILE: pages/test/wifi.json
================================================
{
"usingComponents": {}
}
================================================
FILE: pages/test/wifi.wxml
================================================
================================================
FILE: pages/test/wifi.wxss
================================================
/* pages/test/wifi.wxss */
================================================
FILE: pages/to-pay-order/index.js
================================================
const CONFIG = require('../../config.js')
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Date.prototype.format = function(format) {
var date = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"S+": this.getMilliseconds()
};
if (/(y+)/i.test(format)) {
format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for (var k in date) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1
? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
}
}
return format;
}
Page({
data: {
totalScoreToPay: 0,
goodsList: [],
isNeedLogistics: 0, // 是否需要物流信息
yunPrice: 0,
amountLogistics2: 0,
allGoodsAndYunPrice: 0,
goodsJsonStr: "",
orderType: "", //订单类型,购物车下单或立即支付下单,默认是购物车, buyNow 说明是立即购买
pingtuanOpenId: undefined, //拼团的话记录团号
hasNoCoupons: true,
coupons: [],
couponAmount: 0, //优惠券金额
curCoupon: null, // 当前选择使用的优惠券
curCouponShowText: '请选择使用优惠券', // 当前选择使用的优惠券
peisongType: 'kd', // 配送方式 kd,zq 分别表示快递/到店自取
remark: '',
shopIndex: -1,
pageIsEnd: false,
bindMobileStatus: 0, // 0 未判断 1 已绑定手机号码 2 未绑定手机号码
userScore: 0, // 用户可用积分
deductionScore: '-1', // 本次交易抵扣的积分数, -1 为不抵扣,0 为自动抵扣,其他金额为抵扣多少积分
shopCarType: 0, //0自营购物车,1云货架购物车
dyopen: 0, // 是否开启订阅
dyunit: 0, // 按天
dyduration: 1, // 订阅间隔
dytimes: 1, // 订阅次数
dateStart: undefined, // 订阅首次扣费时间
minDate: new Date().getTime(),
maxDate: new Date(2030, 10, 1).getTime(),
currentDate: new Date().getTime(),
formatter: (type, value) => {
if (type === 'year') {
return `${value}年`;
}
if (type === 'month') {
return `${value}月`;
}
if (type === 'day') {
return `${value}日`;
}
if (type === 'hour') {
return `${value}点`;
}
if (type === 'minute') {
return `${value}分`;
}
return value;
},
cardId: '0', // 使用的次卡ID
// 优惠券选择弹窗相关
couponPickerShow: false,
couponPickerShopShow: false,
currentShopIndex: -1,
currentShopCoupons: [],
currentShopSelectedCoupon: null,
// 口令兑换相关
exchangeCouponShow: false,
exchangeNumber: '',
exchangePwd: ''
},
onShow() {
if (this.data.pageIsEnd) {
return
}
this.doneShow()
},
async doneShow() {
let goodsList = []
let shopList = []
const token = wx.getStorageSync('token')
//立即购买下单
if ("buyNow" == this.data.orderType) {
var buyNowInfoMem = wx.getStorageSync('buyNowInfo');
this.data.kjId = buyNowInfoMem.kjId;
if (buyNowInfoMem && buyNowInfoMem.shopList) {
goodsList = buyNowInfoMem.shopList
}
} else {
//购物车下单
if (this.data.shopCarType == 0) {//自营购物车
var res = await WXAPI.shippingCarInfo(token)
shopList = res.data.shopList
} else if (this.data.shopCarType == 1) {//云货架购物车
var res = await WXAPI.jdvopCartInfoV2(token)
shopList = [{
id: 0,
name: '其他',
hasNoCoupons: true,
serviceDistance: 99999999
}]
}
if (res.code == 0) {
goodsList = res.data.items.filter(ele => {
return ele.selected
})
const shopIds = []
goodsList.forEach(ele => {
if (this.data.shopCarType == 1) {
ele.shopId = 0
}
shopIds.push(ele.shopId)
})
shopList = shopList.filter(ele => {
return shopIds.includes(ele.id)
})
}
}
shopList.forEach(ele => {
ele.hasNoCoupons = true
})
const extRequired = []; // 必填项
if (this.data.create_order_ext) {
const _create_order_ext = JSON.parse(this.data.create_order_ext)
goodsList.forEach(g => {
Object.keys(_create_order_ext).forEach(k => {
if (k.split(',').includes(g.goodsId + '')) {
console.log(1212, _create_order_ext[k]);
_create_order_ext[k].split(',').forEach(v => {
if (!extRequired.includes(v)) {
extRequired.push(v)
}
})
}
})
})
}
this.setData({
shopList,
goodsList,
peisongType: this.data.peisongType,
extRequired
});
this.initShippingAddress()
this.userAmount()
},
onLoad(e) {
const nowDate = new Date();
let _data = {
isNeedLogistics: 1,
dateStart: nowDate.format('yyyy-MM-dd h:m:s'),
orderPeriod_open: wx.getStorageSync('orderPeriod_open'),
order_pay_user_balance: wx.getStorageSync('order_pay_user_balance'),
zt_open_hx: wx.getStorageSync('zt_open_hx'),
create_order_ext: wx.getStorageSync('create_order_ext'),
needBindMobile: wx.getStorageSync('needBindMobile'),
}
if (e.orderType) {
_data.orderType = e.orderType
}
if (e.pingtuanOpenId) {
_data.pingtuanOpenId = e.pingtuanOpenId
}
if (e.shopCarType) {
_data.shopCarType = e.shopCarType
}
this.setData(_data)
this.getUserApiInfo()
this.cardMyList()
},
async userAmount() {
const res = await WXAPI.userAmount(wx.getStorageSync('token'))
const order_pay_user_balance = wx.getStorageSync('order_pay_user_balance')
if (res.code == 0) {
this.setData({
balance: order_pay_user_balance == '1' ? res.data.balance : 0,
userScore: res.data.score
})
}
},
getDistrictId: function (obj, aaa) {
if (!obj) {
return "";
}
if (!aaa) {
return "";
}
return aaa;
},
remarkChange(e) {
this.data.remark = e.detail.value
},
async goCreateOrder() {
this.setData({
btnLoading: true
})
// 检测实名认证状态
if (wx.getStorageSync('needIdCheck') == 1) {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0 && !res.data.base.isIdcardCheck) {
wx.navigateTo({
url: '/pages/idCheck/index',
})
this.setData({
btnLoading: false
})
return
}
}
const subscribe_ids = wx.getStorageSync('subscribe_ids')
if (subscribe_ids) {
wx.requestSubscribeMessage({
tmplIds: subscribe_ids.split(','),
success(res) {
console.log(res)
},
fail(e) {
console.error(e)
},
complete: (e) => {
this.createOrder(true)
},
})
} else {
this.createOrder(true)
}
},
async createOrder(e) {
// shopCarType: 0 //0自营购物车,1云货架购物车
const loginToken = wx.getStorageSync('token') // 用户登录 token
const postData = {
token: loginToken,
goodsJsonStr: this.data.goodsJsonStr,
remark: this.data.remark,
peisongType: this.data.peisongType,
goodsType: this.data.shopCarType,
cardId: this.data.cardId,
}
if (this.data.deductionScore != '-1') {
postData.deductionScore = this.data.deductionScore
}
if (this.data.cardId == '0') {
postData.cardId = ''
}
if (this.data.dyopen == 1) {
const orderPeriod = {
unit: this.data.dyunit,
duration: this.data.dyduration,
dateStart: this.data.dateStart,
times: this.data.dytimes,
autoPay: true
}
postData.orderPeriod = JSON.stringify(orderPeriod)
}
if (this.data.kjId) {
postData.kjid = this.data.kjId
}
if (this.data.pingtuanOpenId) {
postData.pingtuanOpenId = this.data.pingtuanOpenId
}
if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.provinceId) {
postData.provinceId = this.data.curAddressData.provinceId;
}
if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.cityId) {
postData.cityId = this.data.curAddressData.cityId;
}
if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.districtId) {
postData.districtId = this.data.curAddressData.districtId;
}
if (postData.peisongType == 'kd' && this.data.curAddressData && this.data.curAddressData.streetId) {
postData.streetId = this.data.curAddressData.streetId;
}
if (this.data.shopCarType == 1) {
// vop 需要地址来计算运费
postData.address = this.data.curAddressData.address;
postData.linkMan = this.data.curAddressData.linkMan;
postData.mobile = this.data.curAddressData.mobile;
postData.code = this.data.curAddressData.code;
}
if (e && this.data.isNeedLogistics > 0 && postData.peisongType == 'kd') {
if (!this.data.curAddressData) {
wx.hideLoading();
wx.showToast({
title: '请设置收货地址',
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
if (postData.peisongType == 'kd') {
postData.address = this.data.curAddressData.address;
postData.linkMan = this.data.curAddressData.linkMan;
postData.mobile = this.data.curAddressData.mobile;
postData.code = this.data.curAddressData.code;
}
}
if (this.data.curCoupon) {
postData.couponId = this.data.curCoupon.id;
}
if (!e) {
postData.calculate = "true";
} else {
if (postData.peisongType == 'zq' && this.data.shops && this.data.shopIndex == -1) {
wx.showToast({
title: '请选择自提门店',
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
const extJsonStr = {}
if (this.data.extRequired && this.data.extRequired.length > 0) {
const extRequiredMap = this.data.extRequiredMap
if (!extRequiredMap) {
wx.showToast({
title: '请填写必填项',
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
this.data.extRequired.forEach(k => {
if (!extRequiredMap[k]) {
wx.showToast({
title: '请填写' + k,
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
extJsonStr[k] = extRequiredMap[k]
})
}
if (postData.peisongType == 'zq') {
if (!this.data.name) {
wx.showToast({
title: '请填写联系人',
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
if (!this.data.mobile) {
wx.showToast({
title: '请填写联系电话',
icon: 'none'
})
this.setData({
btnLoading: false
})
return;
}
extJsonStr['联系人'] = this.data.name
extJsonStr['联系电话'] = this.data.mobile
postData.isCanHx = this.data.zt_open_hx == '1' ? true : false
}
if (postData.peisongType == 'zq' && this.data.shops) {
postData.shopIdZt = this.data.shops[this.data.shopIndex].id
postData.shopNameZt = this.data.shops[this.data.shopIndex].name
}
postData.extJsonStr = JSON.stringify(extJsonStr)
}
const shopList = this.data.shopList
let totalRes = {
code: 0,
msg: 'success',
data: {
score: 0,
amountReal: 0,
orderIds: []
}
}
if (shopList && shopList.length > 1) {
// 多门店的商品下单
let totalScoreToPay = 0
let isNeedLogistics = false
let allGoodsAndYunPrice = 0
let yunPrice = 0
let amountLogistics2 = 0
let deductionMoney = 0
let couponAmount = 0
let goodsAdditionalPriceMap = {}
for (let index = 0; index < shopList.length; index++) {
const curShop = shopList[index]
console.log(curShop);
postData.filterShopId = curShop.id
if (curShop.curCoupon) {
postData.couponId = curShop.curCoupon.id
} else {
postData.couponId = ''
}
const res = await WXAPI.orderCreate(postData)
this.data.pageIsEnd = true
if (res.code != 0) {
this.data.pageIsEnd = false
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false
})
this.setData({
btnLoading: false
})
return;
}
totalRes.data.score += res.data.score
totalRes.data.amountReal += res.data.amountReal
totalRes.data.orderIds.push(res.data.id)
console.log('e:', e);
if (!e) {
curShop.hasNoCoupons = true
console.log(curShop);
if (res.data.couponUserList) {
curShop.hasNoCoupons = false
res.data.couponUserList.forEach(ele => {
let moneyUnit = '元'
if (ele.moneyType == 1) {
moneyUnit = '%'
}
if (ele.moneyHreshold) {
ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ',满' + ele.moneyHreshold + '元可用]'
} else {
ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ']'
}
})
curShop.curCouponShowText = '请选择使用优惠券'
curShop.coupons = res.data.couponUserList
if (res.data.couponId && res.data.couponId.length > 0) {
curShop.curCoupon = curShop.coupons.find(ele => { return ele.id == res.data.couponId[0] })
curShop.curCouponShowText = curShop.curCoupon.nameExt
}
}
shopList.splice(index, 1, curShop)
// 计算积分抵扣规则 userScore
let scoreDeductionRules = res.data.scoreDeductionRules
if (scoreDeductionRules) {
// 如果可叠加,计算可抵扣的最大积分数
scoreDeductionRules.forEach(ele => {
if (ele.loop) {
let loopTimes = Math.floor(this.data.userScore / ele.score) // 按剩余积分取最大
let loopTimesMax = Math.floor((res.data.amountTotle + res.data.deductionMoney) / ele.money) // 按金额取最大
if (loopTimes > loopTimesMax) {
loopTimes = loopTimesMax
}
ele.score = ele.score * loopTimes
ele.money = ele.money * loopTimes
}
})
// 剔除积分数为0的情况
scoreDeductionRules = scoreDeductionRules.filter(ele => {
return ele.score > 0
})
curShop.scoreDeductionRules = scoreDeductionRules
shopList.splice(index, 1, curShop)
}
totalScoreToPay += res.data.score
if (res.data.isNeedLogistics) {
isNeedLogistics = true
}
allGoodsAndYunPrice += res.data.amountReal
yunPrice += res.data.amountLogistics
amountLogistics2 += res.data.amountLogistics2 || 0
deductionMoney += res.data.deductionMoney
couponAmount += res.data.couponAmount
goodsAdditionalPriceMap = Object.assign(goodsAdditionalPriceMap, res.data.goodsAdditionalPriceMap)
}
}
this.setData({
shopList,
totalScoreToPay,
isNeedLogistics,
allGoodsAndYunPrice,
goodsAdditionalPriceMap,
yunPrice,
amountLogistics2,
hasNoCoupons: true,
deductionMoney,
couponAmount
});
} else {
// 单门店单商品下单
if (shopList && shopList.length == 1) {
if (shopList[0].curCoupon) {
postData.couponId = shopList[0].curCoupon.id
} else {
postData.couponId = ''
}
}
const res = await WXAPI.orderCreate(postData)
this.data.pageIsEnd = true
if (res.code != 0) {
this.data.pageIsEnd = false
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false
})
this.setData({
btnLoading: false
})
return;
}
totalRes = res
if (!e) {
let hasNoCoupons = true
let coupons = null
if (res.data.couponUserList) {
hasNoCoupons = false
res.data.couponUserList.forEach(ele => {
let moneyUnit = '元'
if (ele.moneyType == 1) {
moneyUnit = '%'
}
if (ele.moneyHreshold) {
ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ',满' + ele.moneyHreshold + '元可用]'
} else {
ele.nameExt = ele.name + ' [面值' + ele.money + moneyUnit + ']'
}
})
coupons = res.data.couponUserList
if (shopList && shopList.length == 1 && !hasNoCoupons) {
hasNoCoupons = true
const curShop = shopList[0]
curShop.hasNoCoupons = false
curShop.curCouponShowText = '请选择使用优惠券'
curShop.coupons = res.data.couponUserList
if (res.data.couponId && res.data.couponId.length > 0) {
curShop.curCoupon = curShop.coupons.find(ele => { return ele.id == res.data.couponId[0] })
curShop.curCouponShowText = curShop.curCoupon.nameExt
}
shopList[0] = curShop
}
}
// 计算积分抵扣规则 userScore
let scoreDeductionRules = res.data.scoreDeductionRules
if (scoreDeductionRules) {
// 如果可叠加,计算可抵扣的最大积分数
scoreDeductionRules.forEach(ele => {
if (ele.loop) {
let loopTimes = Math.floor(this.data.userScore / ele.score) // 按剩余积分取最大
let loopTimesMax = Math.floor((res.data.amountTotle + res.data.deductionMoney) / ele.money) // 按金额取最大
if (loopTimes > loopTimesMax) {
loopTimes = loopTimesMax
}
ele.score = ele.score * loopTimes
ele.money = ele.money * loopTimes
}
})
// 剔除积分数为0的情况
scoreDeductionRules = scoreDeductionRules.filter(ele => {
return ele.score > 0
})
}
this.setData({
shopList,
totalScoreToPay: res.data.score,
isNeedLogistics: res.data.isNeedLogistics,
allGoodsAndYunPrice: res.data.amountReal,
goodsAdditionalPriceMap: res.data.goodsAdditionalPriceMap,
yunPrice: res.data.amountLogistics,
amountLogistics2: res.data.amountLogistics2,
hasNoCoupons,
coupons,
deductionMoney: res.data.deductionMoney,
couponAmount: res.data.couponAmount,
scoreDeductionRules
})
}
}
if (!e) {
this.data.pageIsEnd = false
return
}
if (e && "buyNow" != this.data.orderType) {
// 清空购物车数据
const keyArrays = []
this.data.goodsList.forEach(ele => {
keyArrays.push(ele.key)
})
if (this.data.shopCarType == 0) { //自营购物车
WXAPI.shippingCarInfoRemoveItem(loginToken, keyArrays.join())
} else if (this.data.shopCarType == 1) {//云货架购物车
WXAPI.jdvopCartRemoveV2(loginToken, keyArrays.join())
}
}
this.processAfterCreateOrder(totalRes)
},
async processAfterCreateOrder(res) {
this.setData({
btnLoading: false
})
if (res.data.status != 0) {
wx.redirectTo({
url: "/pages/order-list/index"
})
return
}
let orderId = ''
if (res.data.orderIds && res.data.orderIds.length > 0) {
orderId = res.data.orderIds.join()
} else {
orderId = res.data.id
}
// 直接弹出支付,取消支付的话,去订单列表
await this.userAmount()
const balance = this.data.balance
const userScore = this.data.userScore
if (userScore < res.data.score) {
wx.showModal({
title: '提示',
content: '您当前可用积分不足,请稍后前往订单管理进行支付',
showCancel: false,
success: res2 => {
wx.redirectTo({
url: "/pages/order-list/index"
})
}
})
return
}
if (balance || res.data.amountReal * 1 == 0) {
// 有余额
const money = (res.data.amountReal * 1 - balance * 1).toFixed(2)
if (money <= 0) {
// 余额足够
wx.showModal({
title: '请确认支付',
content: `您当前可用余额¥${balance},使用余额支付¥${res.data.amountReal}?`,
confirmText: "确认支付",
cancelText: "暂不付款",
success: res2 => {
if (res2.confirm) {
// 使用余额支付
WXAPI.orderPay(wx.getStorageSync('token'), orderId).then(res3 => {
if (res3.code != 0) {
wx.showToast({
title: res3.msg,
icon: 'none'
})
return
}
wx.redirectTo({
url: "/pages/order-list/index"
})
})
} else {
wx.redirectTo({
url: "/pages/order-list/index"
})
}
}
})
} else {
// 余额不够
wx.showModal({
title: '请确认支付',
content: `您当前可用余额¥${balance},仍需支付¥${money}`,
confirmText: "确认支付",
cancelText: "暂不付款",
success: res2 => {
if (res2.confirm) {
// 使用余额支付
this.setData({
orderId,
money,
paymentShow: true,
nextAction: {
type: 0,
id: orderId
}
})
} else {
wx.redirectTo({
url: "/pages/order-list/index"
})
}
}
})
}
} else {
// 没余额
this.setData({
orderId,
money: res.data.amountReal,
paymentShow: true,
nextAction: {
type: 0,
id: orderId
}
})
}
},
async initShippingAddress() {
const res = await WXAPI.defaultAddress(wx.getStorageSync('token'))
if (res.code == 0) {
this.setData({
curAddressData: res.data.info
});
} else {
this.setData({
curAddressData: null
});
}
this.processYunfei();
},
processYunfei() {
var goodsList = this.data.goodsList
if (goodsList.length == 0) {
return
}
const goodsJsonStr = []
var isNeedLogistics = 0;
let inviter_id = 0;
let inviter_id_storge = wx.getStorageSync('referrer');
if (inviter_id_storge) {
inviter_id = inviter_id_storge;
}
for (let i = 0; i < goodsList.length; i++) {
let carShopBean = goodsList[i];
if (carShopBean.logistics || carShopBean.logisticsId) {
isNeedLogistics = 1;
}
const _goodsJsonStr = {
propertyChildIds: carShopBean.propertyChildIds
}
if (carShopBean.sku && carShopBean.sku.length > 0) {
let propertyChildIds = ''
carShopBean.sku.forEach(option => {
propertyChildIds = propertyChildIds + ',' + option.optionId + ':' + option.optionValueId
})
_goodsJsonStr.propertyChildIds = propertyChildIds
}
if (carShopBean.additions && carShopBean.additions.length > 0) {
let goodsAdditionList = []
carShopBean.additions.forEach(option => {
goodsAdditionList.push({
pid: option.pid,
id: option.id
})
})
_goodsJsonStr.goodsAdditionList = goodsAdditionList
}
_goodsJsonStr.goodsId = carShopBean.goodsId
_goodsJsonStr.number = carShopBean.number
_goodsJsonStr.logisticsType = 0
_goodsJsonStr.inviter_id = inviter_id
goodsJsonStr.push(_goodsJsonStr)
}
if (this.data.shopCarType == 1) {
// vop 商品必须快递
isNeedLogistics = 1
}
this.setData({
isNeedLogistics: isNeedLogistics,
goodsJsonStr: JSON.stringify(goodsJsonStr)
});
this.createOrder();
},
addAddress: function () {
wx.navigateTo({
url: "/pages/address-add/index"
})
},
selectAddress: function () {
wx.navigateTo({
url: "/pages/select-address/index"
})
},
bindChangeCoupon: function (e) {
const selIndex = e.detail.value;
this.setData({
curCoupon: this.data.coupons[selIndex],
curCouponShowText: this.data.coupons[selIndex].nameExt
});
this.processYunfei()
},
bindChangeCouponShop: function (e) {
const selIndex = e.detail.value;
const shopIndex = e.currentTarget.dataset.sidx
const shopList = this.data.shopList
const curshop = shopList[shopIndex]
curshop.curCoupon = curshop.coupons[selIndex]
curshop.curCouponShowText = curshop.coupons[selIndex].nameExt
shopList.splice(shopIndex, 1, curshop)
this.setData({
shopList
});
this.processYunfei()
},
radioChange(e) {
this.setData({
peisongType: e.detail.value
})
this.processYunfei()
if (e.detail.value == 'zq') {
this.fetchShops()
}
},
dyChange(e) {
this.setData({
dyopen: e.detail.value
})
},
dyunitChange(e) {
this.setData({
dyunit: e.detail.value
})
},
cancelLogin() {
wx.navigateBack()
},
async fetchShops() {
const res = await WXAPI.fetchShops()
if (res.code == 0) {
let shopIndex = this.data.shopIndex
const shopInfo = wx.getStorageSync('shopInfo')
if (shopInfo) {
shopIndex = res.data.findIndex(ele => {
return ele.id == shopInfo.id
})
}
this.setData({
shops: res.data,
shopIndex
})
}
},
shopSelect(e) {
this.setData({
shopIndex: e.detail.value
})
},
goMap() {
const _this = this
const shop = this.data.shops[this.data.shopIndex]
const latitude = shop.latitude
const longitude = shop.longitude
wx.openLocation({
latitude,
longitude,
scale: 18
})
},
callMobile() {
const shop = this.data.shops[this.data.shopIndex]
wx.makePhoneCall({
phoneNumber: shop.linkPhone,
})
},
async getUserApiInfo() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code == 0) {
let bindMobileStatus = res.data.base.mobile ? 1 : 2 // 账户绑定的手机号码状态
if (this.data.needBindMobile != 1) {
bindMobileStatus = 1
}
this.setData({
bindMobileStatus,
mobile: res.data.base.mobile,
name: res.data.base.nick,
})
}
},
bindMobile() {
this.setData({
bindMobileShow: true
})
},
bindMobileOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
bindMobileShow: false,
mobile: e.detail.mobile,
bindMobileStatus: 1
})
},
bindMobileCancel() {
this.setData({
bindMobileShow: false
})
},
deductionScoreChange(event) {
this.setData({
deductionScore: event.detail,
})
this.processYunfei()
},
deductionScoreClick(event) {
const {
name
} = event.currentTarget.dataset;
this.setData({
deductionScore: name,
})
this.processYunfei()
},
cardChange(event) {
this.setData({
cardId: event.detail,
})
this.processYunfei()
},
cardClick(event) {
const {
name
} = event.currentTarget.dataset;
this.setData({
cardId: name,
})
this.processYunfei()
},
dateStartclick(e) {
this.setData({
dateStartpop: true
})
},
dateStartconfirm(e) {
const d = new Date(e.detail)
this.setData({
dateStart: d.format('yyyy-MM-dd h:m:s'),
dateStartpop: false
})
console.log(e);
},
dateStartcancel(e) {
this.setData({
dateStartpop: false
})
},
async cardMyList() {
const res = await WXAPI.cardMyList(wx.getStorageSync('token'))
if (res.code == 0) {
const myCards = res.data.filter(ele => { return ele.status == 0 && ele.amount > 0 && ele.cardInfo.refs })
if (myCards.length > 0) {
this.setData({
myCards: res.data
})
}
}
},
paymentOk(e) {
console.log(e.detail); // 这里是组件里data的数据
this.setData({
paymentShow: false
})
wx.redirectTo({
url: '/pages/order-list/index',
})
},
paymentCancel() {
this.setData({
paymentShow: false
})
},
extRequiredChange(e) {
let extRequiredMap = this.data.extRequiredMap
if (!extRequiredMap) {
extRequiredMap = {}
}
extRequiredMap[e.target.dataset.name] = e.detail
console.log(extRequiredMap);
this.setData({
extRequiredMap
})
},
// 显示优惠券选择弹窗
showCouponPicker() {
this.setData({
couponPickerShow: true
})
},
// 关闭优惠券选择弹窗
closeCouponPicker() {
this.setData({
couponPickerShow: false
})
},
// 选择优惠券
selectCoupon(e) {
const index = e.currentTarget.dataset.index
const selectedCoupon = this.data.coupons[index]
this.setData({
curCoupon: selectedCoupon,
curCouponShowText: selectedCoupon.nameExt,
couponPickerShow: false
})
this.processYunfei()
},
// 选择不使用优惠券
selectNoCoupon() {
this.setData({
curCoupon: null,
curCouponShowText: '请选择使用优惠券',
couponPickerShow: false
})
this.processYunfei()
},
// 显示门店优惠券选择弹窗
showCouponPickerShop(e) {
const shopIndex = e.currentTarget.dataset.sidx
const shopList = this.data.shopList
const currentShop = shopList[shopIndex]
this.setData({
currentShopIndex: shopIndex,
currentShopCoupons: currentShop.coupons || [],
currentShopSelectedCoupon: currentShop.curCoupon || null,
couponPickerShopShow: true
})
},
// 关闭门店优惠券选择弹窗
closeCouponPickerShop() {
this.setData({
couponPickerShopShow: false
})
},
// 选择门店优惠券
selectCouponShop(e) {
const index = e.currentTarget.dataset.index
const selectedCoupon = this.data.currentShopCoupons[index]
const shopIndex = this.data.currentShopIndex
const shopList = this.data.shopList
const curshop = shopList[shopIndex]
curshop.curCoupon = selectedCoupon
curshop.curCouponShowText = selectedCoupon.nameExt
shopList.splice(shopIndex, 1, curshop)
this.setData({
shopList,
couponPickerShopShow: false
})
this.processYunfei()
},
// 选择不使用门店优惠券
selectNoCouponShop() {
const shopIndex = this.data.currentShopIndex
const shopList = this.data.shopList
const curshop = shopList[shopIndex]
curshop.curCoupon = null
curshop.curCouponShowText = '请选择使用优惠券'
shopList.splice(shopIndex, 1, curshop)
this.setData({
shopList,
couponPickerShopShow: false
})
this.processYunfei()
},
// 显示口令兑换弹窗
showExchangeCoupon() {
this.setData({
exchangeCouponShow: true,
exchangeNumber: '',
exchangePwd: ''
})
},
// 关闭口令兑换弹窗
closeExchangeCoupon() {
this.setData({
exchangeCouponShow: false
})
},
// 确认兑换优惠券
async confirmExchangeCoupon() {
if (!this.data.exchangeNumber) {
wx.showToast({
title: '请输入券号',
icon: 'none'
})
return
}
if (!this.data.exchangePwd) {
wx.showToast({
title: '请输入密码',
icon: 'none'
})
return
}
wx.showLoading({
title: '兑换中...',
})
const res = await WXAPI.exchangeCoupons(
wx.getStorageSync('token'),
this.data.exchangeNumber,
this.data.exchangePwd
)
wx.hideLoading()
if (res.code != 0) {
wx.showToast({
title: res.msg,
icon: 'none'
})
} else {
wx.showToast({
title: '兑换成功',
icon: 'success'
})
this.setData({
exchangeCouponShow: false
})
// 重新加载优惠券列表
this.processYunfei()
}
},
})
================================================
FILE: pages/to-pay-order/index.json
================================================
{
"navigationBarTitleText": "确认订单"
}
================================================
FILE: pages/to-pay-order/index.wxml
================================================
请先登录
为了保障您的交易安全和订单信息准确
接收订单物流信息
保障账户资金安全
提供专属售后服务
🔒
您的信息将被加密保护,绝不泄露给第三方
{{item.label}}
{{option.optionName}}:{{option.optionValueName}}
{{option.pname}}:{{option.name}}
🎫
优惠券
{{ shop.curCouponShowText }}
›
{{item.label}}
{{option.optionName}}:{{option.optionValueName}}
{{option.pname}}:{{option.name}}
{{curAddressData.linkMan}} {{curAddressData.mobile}}
{{curAddressData.address}}
自动获取
备注
{{ dyunit == 0 ? '天': '' }}
{{ dyunit == 1 ? '月': '' }}
{{ dyunit == 2 ? '年': '' }}
次
🎫
优惠券
{{curCouponShowText}}
›
💰
没有优惠券?点击使用口令兑换
›
¥
{{ item.moneyType == 0 ? item.money : item.money }}
折
满{{item.moneyHreshold}}元
{{item.name}}
{{item.nameExt}}
✓
不使用优惠券
✓
¥
{{ item.moneyType == 0 ? item.money : item.money }}
折
满{{item.moneyHreshold}}元
{{item.name}}
{{item.nameExt}}
✓
不使用优惠券
✓
取消
立即兑换
================================================
FILE: pages/to-pay-order/index.wxss
================================================
page,view,image,input,textarea {
display: block;
box-sizing: border-box;
}
page {
background-color: #f2f2f2;
padding-bottom: 48rpx;
}
.address-box {
width: 100vw;
margin: 20rpx 0;
border-bottom: 1rpx solid #eee;
}
.add-address {
width: 100vw;
display: flex;
align-items: center;
padding-left: 32rpx;
}
.add-address image {
width: 40rpx;
height: 40rpx;
}
.add-address view {
margin-left: 16rpx;
font-size: 28rpx;
color: #000;
padding: 40rpx 0;
}
.show-address {
width: 750rpx;
box-sizing: border-box;
padding: 0 32rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.show-address .name-tel {
font-size: 28rpx;
color: #000;
padding: 30rpx 0 20rpx 0;
}
.show-address .addr-text {
font-size: 24rpx;
color: #888;
padding-bottom: 34rpx;
line-height: 36rpx;
}
.show-address .next {
width: 40rpx;
height: 40rpx;
}
form {
width: 100%;
}
.goods-list {
width: 100%;
background-color: #fff;
margin-bottom: 20rpx;
}
.goods-list .list-title {
font-size: 28rpx;
color: #000;
padding: 30rpx 0 25rpx 30rpx;
}
.goods-list .a-goods {
width: 720rpx;
margin-left: 30rpx;
display: flex;
/*justify-content: space-between;*/
border-top: 1px solid #eee;
padding: 30rpx 30rpx 30rpx 0;
}
.goods-list .a-goods .img-box {
width: 160rpx;
height: 160rpx;
overflow: hidden;
margin-right: 20rpx;
background-color: #d8d8d8;
}
.goods-list .img-box .img {
width: 160rpx;
height: 160rpx;
}
.goods-list .a-goods .text-box {
width: 510rpx;
box-sizing: border-box;
padding-top: 10rpx;
}
.a-goods .text-box .arow {
display: flex;
justify-content: space-between;
align-items: center;
}
.a-goods .text-box .arow .goods-name {
width: 360rpx;
font-size: 26rpx;
height: 74rpx;
color: #000;
line-height: 1.6;
overflow: hidden;
}
.a-goods .text-box .arow01 {
margin-bottom: 30rpx;
}
.a-goods .text-box .arow .goods-price {
font-size: 26rpx;
color: #000;
align-self: flex-start;
}
.a-goods .text-box .arow .goods-label {
font-size: 26rpx;
color: #999;
}
.a-goods .text-box .arow .goods-num {
font-size: 26rpx;
color: #999;
}
.peisong-way {
width: 100%;
background-color: #fff;
margin-bottom: 20rpx;
}
.peisong-way .row-box {
width: 720rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 0 24rpx 30rpx;
border-bottom: 1rpx solid #eee;
}
.peisong-way .row-label.t {
color: #333;
}
.peisong-way .row-label {
font-size: 28rpx;
color: #666;
}
.peisong-way .right-text {
font-size: 28rpx;
color: #666;
padding-right: 30rpx;
}
.peisong-way .liuyan {
width: 510rpx;
font-size: 28rpx;
}
.goods-info {
width: 100%;
background-color: #fff;
margin-bottom: 120rpx;
padding-bottom: 24rpx;
}
.goods-info .row-box {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
padding: 24rpx 30rpx 12rpx 30rpx;
font-size: 28rpx;
color: #000;
}
.goods-info .row-box .right-text {
text-align: right;
}
.row-box .next {
width: 40rpx;
height: 40rpx;
}
.jiesuan-box {
display: flex;
justify-content: space-between;
width: 100%;
height: 100rpx;
position: fixed;
bottom: calc(env(safe-area-inset-bottom) / 2);
left: 0;
border-top: 1px solid #eee;
background-color: #fff;
z-index: 999;
}
.jiesuan-box .to-pay-btn {
width: 250rpx;
text-align: center;
height: 100%;
line-height: 100rpx;
background-color: #e64340;
font-size: 32rpx;
color: #fff;
border-radius: 0;
}
.jiesuan-box .left-price {
display: flex;
width: 500rpx;
justify-content: flex-end;
line-height: 100rpx;
padding: 0 30rpx 0 0;
font-size: 28rpx;
box-sizing: border-box;
}
.jiesuan-box .total {
color: #e64340;
text-align: right;
}
.box-v2 {
width: 100vw;
}
.bottom-box {
height: 120rpx;
}
.cell-group {
margin-top: 16rpx;
}
/* 绑定手机号容器 */
.bind-mobile-container {
min-height: 100vh;
background: linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 40rpx;
box-sizing: border-box;
}
/* 卡片主体 */
.bind-mobile-card {
width: 100%;
max-width: 670rpx;
background: #ffffff;
border-radius: 24rpx;
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.08);
padding: 80rpx 48rpx 60rpx;
box-sizing: border-box;
position: relative;
overflow: hidden;
}
.bind-mobile-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 6rpx;
background: linear-gradient(90deg, #e93b3d 0%, #e2231a 100%);
}
/* 图标区域 */
.card-icon {
display: flex;
justify-content: center;
margin-bottom: 40rpx;
}
.icon-shield {
width: 120rpx;
height: 140rpx;
background: linear-gradient(135deg, #e93b3d 0%, #e2231a 100%);
border-radius: 60rpx 60rpx 20rpx 20rpx;
position: relative;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.3);
}
.shield-inner {
width: 56rpx;
height: 66rpx;
border: 6rpx solid #ffffff;
border-radius: 28rpx 28rpx 10rpx 10rpx;
position: relative;
}
.shield-inner::after {
content: '';
position: absolute;
top: 24rpx;
left: 50%;
transform: translateX(-50%);
width: 12rpx;
height: 24rpx;
border: 4rpx solid #ffffff;
border-top: none;
border-left: none;
transform: translateX(-50%) rotate(45deg);
margin-top: -8rpx;
}
/* 标题区域 */
.card-title {
font-size: 44rpx;
font-weight: bold;
color: #333333;
text-align: center;
margin-bottom: 20rpx;
letter-spacing: 1rpx;
}
.card-subtitle {
font-size: 28rpx;
color: #666666;
text-align: center;
line-height: 44rpx;
margin-bottom: 60rpx;
padding: 0 20rpx;
}
/* 功能列表 */
.feature-list {
background: #f8f8f8;
border-radius: 16rpx;
padding: 32rpx 40rpx;
margin-bottom: 60rpx;
}
.feature-item {
display: flex;
align-items: center;
margin-bottom: 24rpx;
}
.feature-item:last-child {
margin-bottom: 0;
}
.feature-dot {
width: 12rpx;
height: 12rpx;
background: linear-gradient(135deg, #e93b3d 0%, #e2231a 100%);
border-radius: 50%;
margin-right: 20rpx;
flex-shrink: 0;
}
.feature-text {
font-size: 28rpx;
color: #666666;
line-height: 40rpx;
}
/* 按钮区域 */
.bind-btn-wrapper {
margin-bottom: 40rpx;
}
.bind-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(90deg, #e93b3d 0%, #e2231a 100%);
border-radius: 48rpx;
border: none;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(233, 59, 61, 0.3);
transition: all 0.3s;
position: relative;
overflow: hidden;
}
.bind-btn::after {
border: none;
}
.bind-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.2);
transition: left 0.5s;
}
.bind-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(233, 59, 61, 0.4);
}
.bind-btn-text {
font-size: 32rpx;
color: #ffffff;
font-weight: bold;
letter-spacing: 2rpx;
}
/* 安全提示 */
.security-tips {
display: flex;
align-items: center;
justify-content: center;
padding: 24rpx;
background: #fff9f0;
border-radius: 12rpx;
border: 1rpx solid #ffe5cc;
}
.tips-icon {
font-size: 28rpx;
margin-right: 12rpx;
}
.tips-text {
font-size: 24rpx;
color: #999999;
line-height: 34rpx;
}
/* 优惠券选择器 */
.coupon-selector {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32rpx;
background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
border-radius: 16rpx;
margin: 24rpx 0;
box-shadow: 0 4rpx 20rpx rgba(228, 57, 60, 0.08);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.coupon-selector::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 6rpx;
height: 100%;
background: linear-gradient(180deg, #E4393C 0%, #F75050 100%);
}
.coupon-selector:active {
transform: scale(0.98);
box-shadow: 0 2rpx 12rpx rgba(228, 57, 60, 0.12);
}
.coupon-selector-left {
display: flex;
align-items: center;
flex: 1;
}
.coupon-icon {
font-size: 48rpx;
margin-right: 24rpx;
}
.coupon-text-wrapper {
flex: 1;
}
.coupon-label {
font-size: 24rpx;
color: #999999;
margin-bottom: 8rpx;
}
.coupon-selected-text {
font-size: 28rpx;
color: #333333;
font-weight: 600;
}
.coupon-selector-right {
display: flex;
align-items: center;
}
.coupon-arrow {
font-size: 48rpx;
color: #CCCCCC;
font-weight: 300;
}
/* 口令兑换提示 */
.coupon-exchange-tip {
display: flex;
align-items: center;
padding: 24rpx 32rpx;
background: linear-gradient(135deg, #FFF9F0 0%, #FFFFFF 100%);
border-radius: 16rpx;
margin: 24rpx 0;
border: 2rpx dashed #FFD700;
transition: all 0.3s ease;
}
.coupon-exchange-tip:active {
transform: scale(0.98);
background: linear-gradient(135deg, #FFF4E0 0%, #FFFAF0 100%);
}
.tip-icon {
font-size: 40rpx;
margin-right: 20rpx;
}
.tip-text {
flex: 1;
font-size: 26rpx;
color: #FF9500;
font-weight: 500;
}
.tip-arrow {
font-size: 40rpx;
color: #FFD700;
font-weight: 300;
}
/* 优惠券选择弹窗 */
.coupon-picker-container {
background: #FFFFFF;
border-radius: 24rpx 24rpx 0 0;
max-height: 80vh;
display: flex;
flex-direction: column;
}
.coupon-picker-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 32rpx 40rpx;
border-bottom: 1rpx solid #F0F0F0;
position: relative;
}
.coupon-picker-header::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 80rpx;
height: 6rpx;
background: linear-gradient(90deg, #E4393C 0%, #F75050 100%);
border-radius: 3rpx;
}
.picker-title {
font-size: 36rpx;
font-weight: 700;
color: #333333;
}
.picker-close {
font-size: 48rpx;
color: #999999;
font-weight: 300;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
}
.picker-close:active {
background: #F5F5F5;
}
.coupon-picker-list {
box-sizing: border-box;
flex: 1;
padding: 24rpx;
max-height: 60vh;
}
.coupon-picker-item {
margin-bottom: 24rpx;
}
.picker-coupon-card {
position: relative;
display: flex;
align-items: center;
padding: 32rpx;
background: linear-gradient(135deg, #FFF5F5 0%, #FFFFFF 100%);
border-radius: 16rpx;
border: 2rpx solid #F0F0F0;
transition: all 0.3s ease;
}
.picker-coupon-card.selected {
border-color: #E4393C;
background: linear-gradient(135deg, #FFF0F0 0%, #FFFFFF 100%);
box-shadow: 0 8rpx 24rpx rgba(228, 57, 60, 0.15);
}
.picker-coupon-card:active {
transform: scale(0.98);
}
.picker-coupon-left {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 160rpx;
padding-right: 32rpx;
border-right: 2rpx dashed #E5E5E5;
}
.picker-amount-wrapper {
display: flex;
align-items: baseline;
margin-bottom: 8rpx;
}
.picker-currency {
font-size: 28rpx;
color: #E4393C;
font-weight: 600;
margin-right: 4rpx;
}
.picker-amount {
font-size: 56rpx;
color: #E4393C;
font-weight: 700;
line-height: 1;
}
.picker-percent {
font-size: 32rpx;
color: #E4393C;
font-weight: 600;
margin-left: 4rpx;
}
.picker-threshold {
font-size: 22rpx;
color: #999999;
}
.picker-coupon-right {
flex: 1;
padding-left: 32rpx;
}
.picker-coupon-name {
font-size: 30rpx;
color: #333333;
font-weight: 600;
margin-bottom: 12rpx;
line-height: 1.4;
}
.picker-coupon-desc {
font-size: 24rpx;
color: #999999;
line-height: 1.5;
}
.picker-check-icon {
position: absolute;
top: 16rpx;
right: 16rpx;
width: 48rpx;
height: 48rpx;
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #FFFFFF;
font-weight: 700;
}
.picker-coupon-card.no-coupon {
justify-content: center;
background: #F7F8FA;
border: 2rpx dashed #E5E5E5;
}
.picker-coupon-card.no-coupon.selected {
background: linear-gradient(135deg, #FFF0F0 0%, #FFFFFF 100%);
border-color: #E4393C;
}
.no-coupon-text {
font-size: 28rpx;
color: #666666;
font-weight: 500;
}
/* 口令兑换弹窗 */
.exchange-coupon-container {
width: 600rpx;
background: #FFFFFF;
border-radius: 24rpx;
overflow: hidden;
}
.exchange-header {
padding: 48rpx 40rpx 32rpx;
background: linear-gradient(180deg, #FFF5F5 0%, #FFFFFF 100%);
text-align: center;
position: relative;
}
.exchange-header::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 80rpx;
height: 6rpx;
background: linear-gradient(90deg, #E4393C 0%, #F75050 100%);
border-radius: 3rpx;
}
.exchange-title {
font-size: 36rpx;
font-weight: 700;
color: #333333;
margin-bottom: 12rpx;
}
.exchange-subtitle {
font-size: 24rpx;
color: #999999;
}
.exchange-form {
padding: 40rpx 40rpx 24rpx;
}
.exchange-actions {
display: flex;
padding: 0 40rpx 40rpx;
gap: 24rpx;
}
.exchange-btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
transition: all 0.3s ease;
}
.exchange-btn.cancel {
background: #F7F8FA;
color: #666666;
}
.exchange-btn.cancel:active {
background: #E5E5E5;
}
.exchange-btn.confirm {
background: linear-gradient(135deg, #E4393C 0%, #F75050 100%);
color: #FFFFFF;
box-shadow: 0 8rpx 20rpx rgba(228, 57, 60, 0.3);
}
.exchange-btn.confirm:active {
transform: scale(0.98);
box-shadow: 0 4rpx 12rpx rgba(228, 57, 60, 0.4);
}
================================================
FILE: pages/vip/detail.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
levelId: 0,
levelDetail: null,
extJsonKeys: [],
priceList: [],
selectedPrice: null,
userBalance: 0,
paymentShow: false,
money: 0,
nextAction: null,
successShow: false,
successBenefits: []
},
onLoad(options) {
if (options.id) {
this.setData({ levelId: options.id })
this.loadData()
}
},
async loadData() {
wx.showLoading({ title: '加载中...' })
await Promise.all([
this.getLevelDetail(),
this.getPriceList(),
this.getUserBalance()
])
wx.hideLoading()
},
async getLevelDetail() {
const res = await WXAPI.userLevelDetail(this.data.levelId)
if (res.code === 0) {
const extJsonKeys = []
if (res.data.extJson && typeof res.data.extJson === 'object') {
Object.keys(res.data.extJson).forEach(key => {
extJsonKeys.push({
key: key,
value: res.data.extJson[key]
})
})
}
this.setData({
levelDetail: res.data,
extJsonKeys
})
} else {
wx.showToast({
title: res.msg || '加载失败',
icon: 'none'
})
setTimeout(() => {
wx.navigateBack()
}, 1500)
}
},
async getPriceList() {
const res = await WXAPI.userLevelPrices(this.data.levelId)
if (res.code === 0) {
const list = res.data || []
if (list.length === 0) {
wx.showToast({
title: '该等级暂无可购买项目',
icon: 'none'
})
}
this.setData({
priceList: list,
selectedPrice: list.length > 0 ? list[0] : null
})
}
},
async getUserBalance() {
const res = await WXAPI.userAmountV2(wx.getStorageSync('token'))
if (res.code === 0) {
this.setData({
userBalance: res.data.balance || 0
})
}
},
selectPrice(e) {
const { item } = e.currentTarget.dataset
this.setData({
selectedPrice: item
})
},
async handleBuy() {
if (!this.data.selectedPrice) {
wx.showToast({
title: '请选择购买时长',
icon: 'none'
})
return
}
const price = this.data.selectedPrice.price
const balance = this.data.userBalance
if (balance >= price) {
// 余额充足,使用余额购买
this.buyWithBalance()
} else {
// 余额不足,使用在线支付
this.buyWithOnlinePay(price, balance)
}
},
buyWithBalance() {
const price = this.data.selectedPrice.price
const balance = this.data.userBalance
wx.showModal({
title: '确认购买',
content: `当前余额:¥${balance}\n需支付:¥${price}\n确认使用余额购买?`,
confirmText: '确认购买',
success: async (res) => {
if (res.confirm) {
wx.showLoading({ title: '购买中...' })
const result = await WXAPI.userLevelBuy(
wx.getStorageSync('token'),
this.data.selectedPrice.id,
false
)
wx.hideLoading()
if (result.code === 0) {
this.showSuccessModal()
} else {
wx.showToast({
title: result.msg || '购买失败',
icon: 'none'
})
}
}
}
})
},
buyWithOnlinePay(price, balance) {
const needPay = (price - balance).toFixed(2)
wx.showModal({
title: '余额不足',
content: `当前余额:¥${balance}\n需支付:¥${price}\n还需支付:¥${needPay}\n是否继续支付?`,
confirmText: '去支付',
success: (res) => {
if (res.confirm) {
// 拉起支付组件
this.setData({
money: needPay,
paymentShow: true,
nextAction: {
type: 6,
userLevelPriceId: this.data.selectedPrice.id,
isAutoRenew: false
}
})
}
}
})
},
showSuccessModal() {
const benefits = []
const info = this.data.levelDetail.info
if (info.rebate < 10) {
benefits.push(`${info.rebate}折优惠`)
}
if (info.upgradeSendScore > 0) {
benefits.push(`赠送${info.upgradeSendScore}积分`)
}
if (info.sendPerMonthScore > 0) {
benefits.push(`每月${info.sendPerMonthScore}积分`)
}
if (info.sendPerMonthCoupons) {
benefits.push('专享优惠券')
}
this.setData({
successShow: true,
successBenefits: benefits
})
},
handleSuccessConfirm() {
this.setData({
successShow: false
})
wx.navigateBack()
},
paymentOk(e) {
console.log('支付成功', e.detail)
this.setData({
paymentShow: false
})
this.showSuccessModal()
},
paymentCancel() {
this.setData({
paymentShow: false
})
}
})
================================================
FILE: pages/vip/detail.json
================================================
{
"navigationBarTitleText": "会员等级详情",
"usingComponents": {
"vip-success": "/components/vip-success/index"
}
}
================================================
FILE: pages/vip/detail.wxml
================================================
会员权益
购物折扣
{{levelDetail.info.rebate}}折
升级赠送
{{levelDetail.info.upgradeSendScore}}积分
每月赠送
{{levelDetail.info.sendPerMonthScore}}积分
专享优惠券
每月赠送
更多权益
{{item.key}}
{{item.value}}
选择购买时长
{{item.duration}}
{{item.unitStr}}
¥
{{item.price}}
当前等级暂不开放升级
需支付
¥{{selectedPrice ? selectedPrice.price : 0}}
立即升级
================================================
FILE: pages/vip/detail.wxss
================================================
.detail-container {
min-height: 100vh;
background: #f8f9fa;
padding-bottom: 140rpx;
}
.level-header {
position: relative;
height: 500rpx;
overflow: hidden;
}
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.header-bg::before {
content: '';
position: absolute;
top: -30%;
left: -20%;
width: 600rpx;
height: 600rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.header-bg::after {
content: '';
position: absolute;
bottom: -30%;
right: -20%;
width: 500rpx;
height: 500rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
}
.header-content {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
gap: 20rpx;
}
.level-badge-large {
width: 160rpx;
height: 160rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10rpx);
border: 6rpx solid rgba(255, 255, 255, 0.3);
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
}
.badge-icon {
width: 80rpx;
height: 80rpx;
}
.level-name {
font-size: 48rpx;
font-weight: bold;
color: #ffffff;
text-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.2);
}
.level-desc {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
.benefits-section,
.ext-section,
.price-section {
margin: 30rpx;
background: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
}
.benefits-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
}
.benefit-card {
display: flex;
flex-direction: column;
align-items: center;
padding: 32rpx 20rpx;
background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%);
border-radius: 16rpx;
border: 2rpx solid #e8ecff;
}
.benefit-icon {
margin-bottom: 16rpx;
}
.benefit-title {
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.benefit-value {
font-size: 28rpx;
font-weight: bold;
color: #667eea;
}
.ext-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.ext-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
background: #f8f9fa;
border-radius: 12rpx;
}
.ext-label {
font-size: 28rpx;
color: #666;
}
.ext-value {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.price-list {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.price-item {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
background: #f8f9fa;
border-radius: 16rpx;
border: 3rpx solid transparent;
transition: all 0.3s;
}
.price-item.active {
background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%);
border-color: #667eea;
}
.price-duration {
display: flex;
align-items: baseline;
gap: 8rpx;
}
.duration-num {
font-size: 40rpx;
font-weight: bold;
color: #333;
}
.duration-unit {
font-size: 24rpx;
color: #999;
}
.price-amount {
display: flex;
align-items: baseline;
gap: 4rpx;
}
.price-symbol {
font-size: 24rpx;
color: #ff6b35;
}
.price-num {
font-size: 40rpx;
font-weight: bold;
color: #ff6b35;
padding-right: 48rpx;
}
.price-check {
position: absolute;
top: 32rpx;
right: 16rpx;
width: 40rpx;
height: 40rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
background: #ffffff;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.06);
z-index: 100;
}
.price-info {
display: flex;
flex-direction: column;
gap: 4rpx;
}
.price-label {
font-size: 24rpx;
color: #999;
}
.price-total {
font-size: 40rpx;
font-weight: bold;
color: #ff6b35;
}
.buy-btn {
padding: 24rpx 80rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
font-size: 32rpx;
font-weight: bold;
border-radius: 48rpx;
box-shadow: 0 8rpx 24rpx rgba(102, 126, 234, 0.4);
}
.empty-price {
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
padding: 60rpx 0;
}
.empty-price .empty-text {
font-size: 28rpx;
color: #999;
}
================================================
FILE: pages/vip/history.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
recordList: [],
page: 1,
pageSize: 20,
totalPage: 0,
loading: false,
hasMore: true,
levelMap: {}
},
onLoad(options) {
this.loadData()
},
async loadData() {
this.setData({
page: 1,
recordList: [],
hasMore: true
})
await this.loadLevelList()
await this.loadRecords()
},
async loadLevelList() {
const res = await WXAPI.userLevelList({ page: 1, pageSize: 100 })
if (res.code === 0) {
const levelMap = {}
const list = res.data.result || []
list.forEach(item => {
levelMap[item.id] = item.name
})
this.setData({ levelMap })
}
},
async loadRecords() {
if (this.data.loading) return
this.setData({ loading: true })
const res = await WXAPI.userLevelBuyLogs({
token: wx.getStorageSync('token'),
page: this.data.page,
pageSize: this.data.pageSize
})
this.setData({ loading: false })
if (res.code === 0) {
const list = res.data.result || []
// 添加等级名称
list.forEach(item => {
item.levelName = this.data.levelMap[item.levelId] || '未知等级'
})
const allRecords = [...this.data.recordList, ...list]
this.setData({
recordList: allRecords,
totalPage: res.data.totalPage || 0,
hasMore: this.data.page < res.data.totalPage
})
} else {
wx.showToast({
title: res.msg || '加载失败',
icon: 'none'
})
}
},
loadMore() {
if (!this.data.hasMore || this.data.loading) return
this.setData({
page: this.data.page + 1
})
this.loadRecords()
},
onPullDownRefresh() {
this.data.page = 1
this.data.totalPage = 0
this.loadData().then(() => {
wx.stopPullDownRefresh()
})
},
onReachBottom() {
this.loadMore()
}
})
================================================
FILE: pages/vip/history.json
================================================
{
"navigationBarTitleText": "购买记录",
"enablePullDownRefresh": true
}
================================================
FILE: pages/vip/history.wxml
================================================
订单号
{{item.orderNumber}}
购买时间
{{item.dateAdd}}
备注
{{item.remark}}
暂无购买记录~
加载中...
加载更多
没有更多了
================================================
FILE: pages/vip/history.wxss
================================================
.history-container {
min-height: 100vh;
background: #f8f9fa;
padding-bottom: 40rpx;
}
.stats-card {
margin: 30rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 24rpx;
padding: 40rpx;
display: flex;
align-items: center;
justify-content: space-around;
box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.3);
}
.stats-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 12rpx;
}
.stats-label {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
.stats-value {
font-size: 40rpx;
font-weight: bold;
color: #ffffff;
}
.stats-divider {
width: 2rpx;
height: 60rpx;
background: rgba(255, 255, 255, 0.3);
}
.record-list {
padding: 30rpx;
}
.record-item {
background: #ffffff;
border-radius: 20rpx;
padding: 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 24rpx;
border-bottom: 2rpx solid #f0f0f0;
margin-bottom: 24rpx;
}
.level-info {
display: flex;
align-items: center;
gap: 12rpx;
}
.level-icon {
width: 48rpx;
height: 48rpx;
background: linear-gradient(135deg, #f5f7ff 0%, #e8ecff 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.level-name {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.record-amount {
display: flex;
align-items: baseline;
gap: 4rpx;
}
.amount-symbol {
font-size: 24rpx;
color: #ff6b35;
}
.amount-num {
font-size: 36rpx;
font-weight: bold;
color: #ff6b35;
}
.record-body {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.record-info-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.info-label {
font-size: 26rpx;
color: #999;
}
.info-value {
font-size: 26rpx;
color: #666;
max-width: 400rpx;
text-align: right;
word-break: break-all;
}
.empty-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-img {
width: 300rpx;
height: 300rpx;
margin-bottom: 32rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
.loading-wrap {
display: flex;
justify-content: center;
align-items: center;
padding: 60rpx 0;
}
.loadmore-wrap {
display: flex;
justify-content: center;
padding: 40rpx 0;
}
.loadmore-text {
font-size: 28rpx;
color: #667eea;
padding: 16rpx 48rpx;
background: #f5f7ff;
border-radius: 40rpx;
}
.no-more {
text-align: center;
padding: 40rpx 0;
font-size: 24rpx;
color: #999;
}
================================================
FILE: pages/vip/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
data: {
userLevel: null,
levelList: [],
loading: true
},
onLoad(options) {
},
onShow() {
AUTH.checkHasLogined().then(isLogined => {
if (!isLogined) {
AUTH.login(this)
} else {
this.loadData()
}
})
},
async loadData() {
this.setData({ loading: true })
await Promise.all([
this.getUserLevel(),
this.getLevelList()
])
this.setData({ loading: false })
},
async getUserLevel() {
const res = await WXAPI.userDetail(wx.getStorageSync('token'))
if (res.code === 0) {
this.setData({
userLevel: res.data.userLevel
})
}
},
async getLevelList() {
const res = await WXAPI.userLevelList({ page: 1, pageSize: 50 })
if (res.code === 0) {
const list = res.data.result || []
// 按等级排序
list.sort((a, b) => b.level - a.level)
this.setData({
levelList: list
})
}
},
goLevelDetail(e) {
const { id } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/vip/detail?id=${id}`
})
},
goBuyHistory() {
wx.navigateTo({
url: '/pages/vip/history'
})
},
onPullDownRefresh() {
this.loadData().then(() => {
wx.stopPullDownRefresh()
})
}
})
================================================
FILE: pages/vip/index.json
================================================
{
"navigationBarTitleText": "会员权益",
"enablePullDownRefresh": true
}
================================================
FILE: pages/vip/index.wxml
================================================
会员等级
选择适合您的会员等级
{{item.rebate}}折优惠
升级送{{item.upgradeSendScore}}积分
每月送{{item.sendPerMonthScore}}积分
每月赠送专享优惠券
暂无会员等级
加载中...
================================================
FILE: pages/vip/index.wxss
================================================
.vip-container {
min-height: 100vh;
background: linear-gradient(180deg, #f8f9fa 0%, #ffffff 100%);
padding-bottom: 40rpx;
}
.vip-header {
position: relative;
}
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.header-bg::after {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 500rpx;
height: 500rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
}
.header-content {
position: relative;
z-index: 1;
padding: 60rpx 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.current-level {
display: flex;
align-items: center;
gap: 24rpx;
}
.level-badge {
width: 120rpx;
height: 120rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
backdrop-filter: blur(10rpx);
border: 4rpx solid rgba(255, 255, 255, 0.3);
}
.badge-icon {
width: 60rpx;
height: 60rpx;
}
.level-info {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.level-name {
font-size: 40rpx;
font-weight: bold;
color: #ffffff;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.level-desc {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
}
.history-btn {
display: flex;
align-items: center;
gap: 8rpx;
padding: 16rpx 24rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 40rpx;
backdrop-filter: blur(10rpx);
border: 2rpx solid rgba(255, 255, 255, 0.3);
font-size: 24rpx;
color: #ffffff;
}
.level-list {
margin-top: 32rpx;
padding: 0 30rpx;
}
.section-title {
text-align: center;
margin-bottom: 40rpx;
}
.title-text {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 12rpx;
}
.title-desc {
font-size: 24rpx;
color: #999;
}
.level-cards {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.level-card {
background: #ffffff;
border-radius: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s;
border: 2rpx solid transparent;
}
.level-card:active {
transform: scale(0.98);
}
.level-card.current {
border-color: #667eea;
background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%);
box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.2);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
padding-bottom: 24rpx;
border-bottom: 2rpx solid #f0f0f0;
}
.level-title {
display: flex;
align-items: center;
gap: 16rpx;
}
.level-title .name {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.current-tag {
padding: 4rpx 16rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
font-size: 20rpx;
border-radius: 20rpx;
}
.level-badge-small {
width: 80rpx;
height: 80rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.level-num {
font-size: 24rpx;
font-weight: bold;
color: #ffffff;
}
.card-benefits {
display: flex;
flex-direction: column;
gap: 16rpx;
margin-bottom: 24rpx;
}
.benefit-item {
display: flex;
align-items: center;
gap: 12rpx;
font-size: 26rpx;
color: #666;
}
.card-footer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8rpx;
padding-top: 16rpx;
border-top: 2rpx solid #f0f0f0;
}
.view-detail {
font-size: 24rpx;
color: #999;
}
.loading-wrap {
display: flex;
justify-content: center;
align-items: center;
padding: 80rpx 0;
}
.empty-wrap {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 120rpx 0;
}
.empty-img {
width: 300rpx;
height: 300rpx;
margin-bottom: 32rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
}
================================================
FILE: pages/withdraw/index.js
================================================
const WXAPI = require('apifm-wxapi')
const AUTH = require('../../utils/auth')
Page({
/**
* 页面的初始数据
*/
data: {
balance: 0.00
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
this.setData({
balance_pay_pwd: wx.getStorageSync('balance_pay_pwd')
})
},
onShow: function() {
AUTH.checkHasLogined().then(isLogined => {
if (!isLogined) {
AUTH.login(this)
} else {
this.userAmount()
}
})
},
async userAmount() {
const res = await WXAPI.userAmount(wx.getStorageSync('token'))
if (res.code === 0) {
this.setData({
balance: res.data.balance
})
}
},
async bindSave() {
let minWidthAmount = wx.getStorageSync('WITHDRAW_MIN');
if (!minWidthAmount) {
minWidthAmount = 0
}
const amount = this.data.amount;
if (!amount) {
wx.showToast({
title: '请填写正确的提现金额',
icon: 'none',
})
return
}
if (this.data.balance_pay_pwd == '1' && !this.data.pwd) {
wx.showToast({
title: '请输入交易密码',
icon: 'none'
})
return
}
if (amount * 1 < minWidthAmount) {
wx.showToast({
title: '提现金额不能低于' + minWidthAmount,
icon: 'none',
})
return
}
if (amount * 1 > 2000) {
if (!this.data.name) {
wx.showToast({
title: '请输入真实姓名',
icon: 'none'
})
return
}
} else {
this.data.name = ''
}
const res = await WXAPI.withDrawApplyV3({
token: wx.getStorageSync('token'),
money: amount,
pwd: this.data.pwd ? this.data.pwd : '',
name: this.data.name ? this.data.name : '',
})
if (res.code == 0) {
wx.showModal({
title: '成功',
content: '您的提现申请已提交,等待财务打款',
showCancel: false,
success: function(res) {
if (res.confirm) {
wx.navigateBack({
delta: 0,
})
}
}
})
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
}
}
})
================================================
FILE: pages/withdraw/index.json
================================================
{
"navigationBarTitleText": "申请提现"
}
================================================
FILE: pages/withdraw/index.wxml
================================================
可提现余额(元)
¥
{{ balance }}
提现将在1-3个工作日内到账
提现信息
💰
提现金额
👤
真实姓名
🔒
交易密码
ℹ️
温馨提示
• 提现金额将原路返回至您的账户
• 每日最多可申请3次提现
• 如有疑问请联系客服
立即提现
================================================
FILE: pages/withdraw/index.wxss
================================================
/* 京东风格 - 提现页面样式 */
page {
background: #f5f5f5;
min-height: 100vh;
}
.withdraw-container {
padding-bottom: 40rpx;
}
/* 顶部余额卡片 */
.balance-card {
padding: 40rpx 30rpx;
background: linear-gradient(135deg, #E93323 0%, #C81623 100%);
position: relative;
overflow: hidden;
}
.balance-card::before {
content: '';
position: absolute;
width: 400rpx;
height: 400rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
top: -200rpx;
right: -100rpx;
}
.balance-card::after {
content: '';
position: absolute;
width: 300rpx;
height: 300rpx;
background: rgba(255, 255, 255, 0.08);
border-radius: 50%;
bottom: -150rpx;
left: -50rpx;
}
.balance-bg {
position: relative;
z-index: 1;
}
.balance-label {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 20rpx;
font-weight: 400;
}
.balance-amount {
display: flex;
align-items: baseline;
margin-bottom: 16rpx;
}
.balance-symbol {
font-size: 40rpx;
color: #fff;
font-weight: bold;
margin-right: 8rpx;
}
.balance-value {
font-size: 72rpx;
color: #fff;
font-weight: bold;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
}
.balance-tips {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
/* 提现表单 */
.withdraw-form {
margin: 24rpx 30rpx;
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.form-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 32rpx;
padding-left: 16rpx;
border-left: 6rpx solid #E93323;
}
.form-item {
margin-bottom: 36rpx;
padding-bottom: 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.form-item:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.item-label {
display: flex;
align-items: center;
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
font-weight: 500;
}
.label-icon {
font-size: 32rpx;
margin-right: 12rpx;
}
/* 温馨提示 */
.tips-box {
margin: 24rpx 30rpx;
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04);
}
.tips-title {
display: flex;
align-items: center;
font-size: 28rpx;
color: #333;
font-weight: 600;
margin-bottom: 24rpx;
}
.tips-icon {
font-size: 32rpx;
margin-right: 12rpx;
}
.tips-content {
padding-left: 44rpx;
}
.tips-item {
font-size: 26rpx;
color: #999;
line-height: 44rpx;
position: relative;
}
/* 提交按钮 */
.submit-btn-wrapper {
padding: 40rpx 30rpx;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, #fff 0%, rgba(255, 255, 255, 0.95) 100%);
z-index: 100;
}
.submit-btn {
height: 96rpx;
background: linear-gradient(135deg, #E93323 0%, #C81623 100%);
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(233, 51, 35, 0.3);
transition: all 0.3s;
position: relative;
overflow: hidden;
}
.submit-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.5s;
}
.submit-btn:active {
transform: scale(0.98);
box-shadow: 0 4rpx 16rpx rgba(233, 51, 35, 0.4);
}
.btn-text {
font-size: 32rpx;
color: #fff;
font-weight: 600;
letter-spacing: 2rpx;
}
/* van-field 自定义样式覆盖 */
.form-item .van-field {
padding: 0 !important;
}
.form-item .van-field__control {
color: #333;
font-weight: 500;
}
.form-item .van-field__control::-webkit-input-placeholder {
color: #ccc;
font-weight: 400;
}
================================================
FILE: pages/wuliu/index.js
================================================
const WXAPI = require('apifm-wxapi')
const app = getApp()
Page({
data: {},
onLoad: function (e) {
this.data.orderId = e.id
this.data.trackingNumber = e.trackingNumber
this.orderDetail()
},
onShow: function () {
},
async orderDetail() {
// https://www.yuque.com/apifm/nu0f75/oamel8
const res = await WXAPI.orderDetail(wx.getStorageSync('token'), this.data.orderId)
if (res.code != 0) {
wx.showModal({
title: '错误',
content: res.msg,
showCancel: false,
success: () => {
wx.navigateBack()
}
})
return;
}
const orderLogisticsShippers = res.data.orderLogisticsShippers
let trackingNumber = this.data.trackingNumber
if (!trackingNumber) {
trackingNumber = res.data.logistics.trackingNumber
}
let shipperName = this.data.shipperName
if (!shipperName) {
shipperName = res.data.logistics.shipperName
}
let logisticsTraces = null
if (this.data.trackingNumber && orderLogisticsShippers) {
// 查看子快递单
const entity = orderLogisticsShippers.find(ele => { return ele.trackingNumber == this.data.trackingNumber })
if (entity.traces) {
entity.tracesArray = JSON.parse (entity.traces)
logisticsTraces = entity.tracesArray.reverse()
}
} else {
if (res.data.logisticsTraces) {
logisticsTraces = res.data.logisticsTraces.reverse()
}
}
this.setData({
trackingNumber,
shipperName,
orderDetail: res.data,
logisticsTraces
});
},
})
================================================
FILE: pages/wuliu/index.json
================================================
{
"navigationBarTitleText": "物流信息"
}
================================================
FILE: pages/wuliu/index.wxml
================================================
{{item.AcceptTime}}
{{item.AcceptStation}}
最新
================================================
FILE: pages/wuliu/index.wxss
================================================
page {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding-bottom: 40rpx;
}
.container {
min-height: 100vh;
}
/* ==================== 顶部物流信息卡片 ==================== */
.top-header {
padding: 40rpx 30rpx 30rpx;
}
.header-card {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border-radius: 24rpx;
padding: 40rpx 32rpx;
box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.25);
position: relative;
overflow: hidden;
}
.header-card::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 300rpx;
height: 300rpx;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
border-radius: 50%;
}
.header-content {
display: flex;
align-items: flex-start;
position: relative;
z-index: 1;
}
.header-icon {
margin-right: 24rpx;
}
.icon-truck {
width: 88rpx;
height: 88rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 44rpx;
box-shadow: 0 8rpx 16rpx rgba(102, 126, 234, 0.3);
}
.header-info {
flex: 1;
}
.info-row {
margin-bottom: 20rpx;
}
.info-row:last-child {
margin-bottom: 0;
}
.info-label {
font-size: 24rpx;
color: #8b8fa3;
margin-bottom: 8rpx;
font-weight: 500;
letter-spacing: 1rpx;
}
.info-value {
font-size: 28rpx;
color: #2d3142;
font-weight: 600;
word-break: break-all;
}
/* ==================== 物流轨迹容器 ==================== */
.timeline-container {
background: #ffffff;
margin: 0 30rpx;
border-radius: 24rpx;
padding: 40rpx 0;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
}
.timeline-header {
padding: 0 40rpx 32rpx;
border-bottom: 2rpx solid #f0f1f5;
}
.timeline-title {
font-size: 36rpx;
font-weight: 700;
color: #2d3142;
margin-bottom: 8rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.timeline-subtitle {
font-size: 22rpx;
color: #a8adbf;
font-weight: 500;
letter-spacing: 2rpx;
text-transform: uppercase;
}
/* ==================== 时间轴内容 ==================== */
.timeline-content {
padding: 40rpx 0 20rpx;
position: relative;
}
.timeline-item {
display: flex;
padding: 0 40rpx;
margin-bottom: 32rpx;
position: relative;
animation: fadeInUp 0.6s ease-out forwards;
opacity: 0;
}
.timeline-item:nth-child(1) { animation-delay: 0.1s; }
.timeline-item:nth-child(2) { animation-delay: 0.2s; }
.timeline-item:nth-child(3) { animation-delay: 0.3s; }
.timeline-item:nth-child(4) { animation-delay: 0.4s; }
.timeline-item:nth-child(5) { animation-delay: 0.5s; }
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ==================== 时间轴节点 ==================== */
.timeline-node {
width: 48rpx;
margin-right: 24rpx;
display: flex;
justify-content: center;
flex-shrink: 0;
}
.node-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
}
.node-dot {
width: 28rpx;
height: 28rpx;
border-radius: 50%;
background: #e5e7eb;
position: relative;
flex-shrink: 0;
transition: all 0.3s ease;
}
.node-dot-active {
width: 32rpx;
height: 32rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow: 0 0 0 8rpx rgba(102, 126, 234, 0.15),
0 0 0 16rpx rgba(102, 126, 234, 0.08);
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
box-shadow: 0 0 0 8rpx rgba(102, 126, 234, 0.15),
0 0 0 16rpx rgba(102, 126, 234, 0.08);
}
50% {
box-shadow: 0 0 0 12rpx rgba(102, 126, 234, 0.2),
0 0 0 24rpx rgba(102, 126, 234, 0.1);
}
}
.dot-inner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background: #ffffff;
}
.node-line {
width: 3rpx;
flex: 1;
background: linear-gradient(to bottom, #e5e7eb 0%, rgba(229, 231, 235, 0.3) 100%);
margin-top: 8rpx;
min-height: 60rpx;
}
.timeline-item-active .node-line {
background: linear-gradient(to bottom,
rgba(102, 126, 234, 0.3) 0%,
rgba(229, 231, 235, 0.3) 100%);
}
/* ==================== 内容卡片 ==================== */
.timeline-card {
flex: 1;
background: #f8f9ff;
border-radius: 16rpx;
padding: 24rpx 28rpx;
position: relative;
border: 2rpx solid transparent;
transition: all 0.3s ease;
margin-bottom: 8rpx;
}
.timeline-item-active .timeline-card {
background: linear-gradient(135deg, #f8f9ff 0%, #ffffff 100%);
border: 2rpx solid rgba(102, 126, 234, 0.2);
box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.15);
}
.timeline-card::before {
content: '';
position: absolute;
left: -12rpx;
top: 24rpx;
width: 0;
height: 0;
border-top: 8rpx solid transparent;
border-bottom: 8rpx solid transparent;
border-right: 12rpx solid #f8f9ff;
}
.timeline-item-active .timeline-card::before {
border-right-color: #f8f9ff;
}
.card-time {
font-size: 24rpx;
color: #8b8fa3;
margin-bottom: 12rpx;
font-weight: 500;
display: flex;
align-items: center;
}
.card-time::before {
content: '🕒';
margin-right: 8rpx;
font-size: 22rpx;
}
.timeline-item-active .card-time {
color: #667eea;
font-weight: 600;
}
.card-content {
font-size: 28rpx;
color: #2d3142;
line-height: 44rpx;
font-weight: 500;
}
.timeline-item-active .card-content {
font-weight: 600;
color: #1a1d2e;
}
.card-badge {
position: absolute;
top: -12rpx;
right: 20rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
font-size: 20rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-weight: 600;
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.4);
letter-spacing: 1rpx;
}
/* ==================== 空状态优化 ==================== */
.timeline-container van-empty {
padding: 80rpx 0;
}
================================================
FILE: project.config.json
================================================
{
"description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"setting": {
"urlCheck": true,
"es6": true,
"enhance": true,
"postcss": false,
"preloadBackgroundData": false,
"minified": true,
"newFeature": true,
"coverView": true,
"nodeModules": false,
"autoAudits": false,
"showShadowRootInWxmlPanel": true,
"scopeDataCheck": false,
"uglifyFileName": false,
"checkInvalidKey": true,
"checkSiteMap": true,
"uploadWithSourceMap": true,
"compileHotReLoad": true,
"useMultiFrameRuntime": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"useIsolateContext": true,
"userConfirmedBundleSwitch": false,
"packNpmManually": false,
"packNpmRelationList": [],
"minifyWXSS": true,
"disableUseStrict": false,
"minifyWXML": true,
"showES6CompileOption": false,
"useCompilerPlugins": false,
"ignoreUploadUnusedFiles": true,
"useStaticServer": true,
"condition": false
},
"compileType": "miniprogram",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {
"plugin": {
"list": []
},
"game": {
"list": []
},
"gamePlugin": {
"list": []
},
"miniprogram": {
"list": []
}
},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
},
"packOptions": {
"ignore": [],
"include": []
},
"appid": "wxa46b09d413fbcaff"
}
================================================
FILE: project.private.config.json
================================================
{
"setting": {
"compileHotReLoad": true,
"urlCheck": false,
"bigPackageSizeSupport": false
},
"condition": {},
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"libVersion": "3.14.1",
"projectname": "%E5%A4%A9%E4%BD%BF%E7%AB%A5%E8%A3%85"
}
================================================
FILE: sitemap.json
================================================
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
================================================
FILE: typings/wx.d.ts
================================================
// generate time:2017-08-23 21:12:06
// Type definitions for wx app
// Definitions by: hellopao
/************************************************
* *
* 微信小程序 API *
* *
************************************************/
interface IAnimation {
/**
* 透明度,参数范围 0~1
*/
opacity(value: number): IAnimation;
/**
* 颜色值
*/
backgroundColor(color: string): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
width(length: number): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
height(length: number): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
top(length: number): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
left(length: number): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
bottom(length: number): IAnimation;
/**
* 长度值,如果传入 Number 则默认使用 px,可传入其他自定义单位的长度值
*/
right(length: number): IAnimation;
/**
* deg的范围-180~180,从原点顺时针旋转一个deg角度
*/
rotate(deg: number): IAnimation;
/**
* deg的范围-180~180,在X轴旋转一个deg角度
*/
rotateX(deg: number): IAnimation;
/**
* deg的范围-180~180,在Y轴旋转一个deg角度
*/
rotateY(deg: number): IAnimation;
/**
* deg的范围-180~180,在Z轴旋转一个deg角度
*/
rotateZ(deg: number): IAnimation;
/**
* 同transform-function rotate3d
*/
rotate3d(x: number, y: number, z: number, deg: number): IAnimation;
/**
* 一个参数时,表示在X轴、Y轴同时缩放sx倍数;两个参数时表示在X轴缩放sx倍数,在Y轴缩放sy倍数
*/
scale(sx: number, sy?: number): IAnimation;
/**
* 在X轴缩放sx倍数
*/
scaleX(sx: number): IAnimation;
/**
* 在Y轴缩放sy倍数
*/
scaleY(sy: number): IAnimation;
/**
* 在Z轴缩放sy倍数
*/
scaleZ(sz: number): IAnimation;
/**
* 在X轴缩放sx倍数,在Y轴缩放sy倍数,在Z轴缩放sz倍数
*/
scale3d(sx: number, sy: number, sz: number): IAnimation;
/**
* 一个参数时,表示在X轴偏移tx,单位px;两个参数时,表示在X轴偏移tx,在Y轴偏移ty,单位px。
*/
translate(tx: number, ty?: number): IAnimation;
/**
* 在X轴偏移tx,单位px
*/
translateX(tx: number): IAnimation;
/**
* 在Y轴偏移tx,单位px
*/
translateY(tx: number): IAnimation;
/**
* 在Z轴偏移tx,单位px
*/
translateZ(tx: number): IAnimation;
/**
* 在X轴偏移tx,在Y轴偏移ty,在Z轴偏移tz,单位px
*/
translate3d(tx: number, ty: number, tz: number): IAnimation;
/**
* 参数范围-180~180;一个参数时,Y轴坐标不变,X轴坐标延顺时针倾斜ax度;两个参数时,分别在X轴倾斜ax度,在Y轴倾斜ay度
*/
skew(ax: number, ay?: number): IAnimation;
/**
* 参数范围-180~180;Y轴坐标不变,X轴坐标延顺时针倾斜ax度
*/
skewX(ax: number): IAnimation;
/**
* 参数范围-180~180;X轴坐标不变,Y轴坐标延顺时针倾斜ay度
*/
skewY(ay: number): IAnimation;
/**
* 同transform-function matrix
*/
matrix(a, b, c, d, tx, ty): IAnimation;
/**
* 同transform-function matrix3d
*/
matrix3d(): IAnimation;
}
interface ICanvasContext {
/**
* 设置填充色, 如果没有设置 fillStyle,默认颜色为 black。
*/
setFillStyle(color: string): void;
/**
* 设置边框颜色, 如果没有设置 fillStyle,默认颜色为 black。
*/
setStrokeStyle(color: string): void;
/**
* 设置阴影
*/
setShadow(offsetX: number, offsetY: number, blur: number, color: string): void;
/**
* 创建一个线性的渐变颜色。需要使用 addColorStop() 来指定渐变点,至少要两个。
*/
createLinearGradient(x0: number, y0: number, x1: number, y1: number): void;
/**
* 创建一个圆形的渐变颜色。 起点在圆心,终点在圆环。 需要使用 addColorStop() 来指定渐变点,至少要两个。
*/
createCircularGradient(x: number, y: number, r: number): void;
/**
* 创建一个颜色的渐变点。小于最小 stop 的部分会按最小 stop 的 color 来渲染,大于最大 stop 的部分会按最大 stop 的 color 来渲染。需要使用 addColorStop() 来指定渐变点,至少要两个。
*/
addColorStop(stop: number, color: string): void;
/**
* 设置线条端点的样式
*/
setLineCap(lineCap: 'butt' | 'round' | 'square'): void;
/**
* 设置两线相交处的样式
*/
setLineJoin(lineJoin: 'bevel' | 'round' | 'miter'): void;
/**
* 设置线条宽度
*/
setLineWidth(lineWidth: number): void;
/**
* 设置最大倾斜
*/
setMiterLimit(miterLimit: number): void;
/**
* 添加一个矩形路径到当前路径。
*/
rect(x: number, y: number, width: number, height: number): void;
/**
* 填充一个矩形。用 setFillStyle() 设置矩形的填充色,如果没设置默认是黑色。
*/
fillRect(x: number, y: number, width: number, height: number): void;
/**
* 一个矩形(非填充)。用 setFillStroke() 设置矩形线条的颜色,如果没设置默认是黑色。
*/
strokeRect(x: number, y: number, width: number, height: number): void;
/**
* 在给定的矩形区域内,清除画布上的像素
*/
clearRect(x: number, y: number, width: number, height: number): void;
/**
* 对当前路径进行填充
*/
fill(): void;
/**
* 对当前路径进行描边
*/
stroke(): void;
/**
* 开始一个路径
*/
beginPath(): void;
/**
* 关闭一个路径
*/
closePath(): void;
/**
* 把路径移动到画布中的指定点,但不创建线条。
*/
moveTo(x: number, y: number): void;
/**
* 添加一个新点,然后在画布中创建从该点到最后指定点的线条。
*/
lineTo(x: number, y: number): void;
/**
* 添加一个弧形路径到当前路径,顺时针绘制。
*/
arc(x: number, y: number, radius: number, startAngle: number, sweepAngle: number): void;
/**
* 创建二次方贝塞尔曲线
*/
quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;
/**
* 创建三次方贝塞尔曲线
*/
bezierCurveTo(cpx1: number, cpy1: number, cpx2: number, cpy2: number, x: number, y: number): void;
/**
* 对横纵坐标进行缩放
*/
scale(scaleWidth: number/**横坐标缩放的倍数1 = 100%,0.5 = 50%,2 = 200%,依次类 */, scaleHeight: number/** 纵坐标轴缩放的倍数1 = 100%,0.5 = 50%,2 = 200%,依次类 */): void;
/**
* 对坐标轴进行顺时针旋转
*/
rotate(deg: number/**degrees * Math.PI/180;degrees范围为0~360;旋转角度,以弧度计 */): void;
/**
* 对坐标原点进行缩放
*/
translate(x: number/**水平坐标平移量 */, y: number/**竖直坐标平移量 */): void;
/**
* 在画布上绘制被填充的文本
*/
fillText(text: string, x: number, y: number): void;
/**
* 设置字体大小
*/
setFontSize(fontSize: number): void;
/**
* 在画布上绘制图像
*/
drawImage(imageResource: string, x: number, y: number, width: number, height: number): void;
/**
* 设置全局画笔透明度。
*/
setGlobalAlpha(alpha: number): void;
/**
* 保存当前坐标轴的缩放、旋转、平移信息
*/
save(): void;
/**
* 恢复之前保存过的坐标轴的缩放、旋转、平移信息
*/
restore(): void;
/**
* 进行绘图
*/
draw(): void;
}
interface IAudioContext {
/**
* 播放
*/
play: () => void;
/**
* 暂停
*/
pause: () => void;
/**
* 跳转到指定位置,单位 s
*/
seek: (position: number) => void;
}
interface IVideoContext {
/**
* 播放
*/
play: () => void;
/**
* 暂停
*/
pause: () => void;
/**
* 跳转到指定位置,单位 s
*/
seek: (position: number) => void;
/**
* 发送弹幕,danmu 包含两个属性 text, color。
*/
sendDanmu: (danmu: {text: string; color: string;}) => void;
}
interface IMapContext {
/**
* 获取当前地图中心的经纬度,返回的是 gcj02 坐标系,可以用于 wx.openLocation
*/
getCenterLocation: (obj: {
/**
* 接口调用成功的回调函数 ,res = { longitude: "经度", latitude: "纬度"}
*/
success?: (res: {longitude: string; latitude: string}) => void;
/**
* 接口调用失败的回调函数
*/
fail?: () => void;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: () => void;
}) => void;
/**
* 将地图中心移动到当前定位点,需要配合map组件的show-location使用
*/
moveToLocation: () => void;
}
interface Application {
setData: (obj: any) => void;
}
interface AppConstructor {
new (): Application;
(opts: {
/**
* 生命周期函数--监听小程序初始化
*/
onLaunch?: () => void;
/**
* 生命周期函数--监听小程序显示
*/
onShow?: () => void;
/**
* 生命周期函数--监听小程序隐藏
*/
onHide?: () => void;
[key: string]: any;
}): Application;
}
declare var App: AppConstructor;
declare function getApp(): Application;
declare function getCurrentPages(): Page[];
interface Page {
setData: (obj: any) => void;
}
interface PageConstructor {
new (): Page;
(opts: {
/**
* 页面的初始数据
*/
data?: any;
/**
* 页面的初始数据
*/
onLoad?: () => void;
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady?: () => void;
/**
* 生命周期函数--监听页面显示
*/
onShow?: () => void;
/**
* 生命周期函数--监听页面隐藏
*/
onHide?: () => void;
/**
* 生命周期函数--监听页面卸载
*/
onUnload?: () => void;
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefreash?: () => void;
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom?: () => void;
/**
* 用户点击右上角分享
*/
onShareAppMessage?: () => {
/**
* 分享标题, 默认值当前小程序名称
*/
title: string;
/**
* 分享描述, 默认值当前小程序名称
*/
desc: string;
/**
* 分享路径 默认值当前页面 path ,必须是以 / 开头的完整路径
*/
path: string;
};
[key: string]: any;
}): Page;
}
declare var Page: PageConstructor;
declare var wx: {
// # 网络 #
request(obj: {
/**
* 开发者服务器接口地址
*/
url: string;
/**
* 请求的参数
*/
data?: any | string;
/**
* 设置请求的 header , header 中不能设置 Referer
*/
header?: any;
/**
* 默认为 GET,有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
*/
method?: string;
/**
* 默认为 json。如果设置了 dataType 为 json,则会尝试对响应的数据做一次 JSON.parse
*/
dataType?: string;
/**
* 收到开发者服务成功返回的回调函数,res = {data: '开发者服务器返回的内容'}
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 将本地资源上传到开发者服务器。如页面通过 wx.chooseImage 等接口获取到一个本地资源的临时文件路径后,可通过此接口将本地资源上传到指定服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data 。
*/
uploadFile(obj: {
/**
* 开发者服务器 url
*/
url: string;
/**
* 要上传文件资源的路径
*/
filePath: string;
/**
* 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
*/
name: string;
/**
* HTTP 请求 Header , header 中不能设置 Referer
*/
header?: any;
/**
* HTTP 请求中其他额外的 form data
*/
formData?: any;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 下载文件资源到本地。客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。
*/
downloadFile(obj: {
/**
* 下载资源的 url
*/
url: string;
/**
* HTTP 请求 Header
*/
header?: any;
/**
* 下载成功后以 tempFilePath 的形式传给页面,res = {tempFilePath: '文件的临时路径'}
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 创建一个 WebSocket 连接;一个微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。
*/
connectSocket(obj: {
/**
* 开发者服务器接口地址,必须是 wss 协议,且域名必须是后台配置的合法域名
*/
url: string;
/**
* 请求的数据
*/
data?: any;
/**
* HTTP Header , header 中不能设置 Referer
*/
header?: any;
/**
* 默认是GET,有效值: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
*/
method?: string;
/**
* 子协议数组
*/
protocols?: string[];
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 监听WebSocket连接打开事件。
*/
onSocketOpen(callback: Function): void;
/**
* 监听WebSocket错误。
*/
onSocketError(callback: Function): void;
/**
* 通过 WebSocket 连接发送数据,需要先 wx.connectSocket,并在 wx.onSocketOpen 回调之后才能发送。
*/
sendSocketMessage(obj: {
/**
* 需要发送的内容
*/
data: undefined;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 监听WebSocket接受到服务器的消息事件。
*/
onSocketMessage(callback: Function): void;
/**
* 关闭WebSocket连接。
*/
closeSocket(obj: {
/**
* 一个数字值表示关闭连接的状态号,表示连接被关闭的原因。如果这个参数没有被指定,默认的取值是1000 (表示正常连接关闭)
*/
code?: number;
/**
* 一个可读的字符串,表示连接被关闭的原因。这个字符串必须是不长于123字节的UTF-8 文本(不是字符)
*/
reason?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 监听WebSocket关闭。
*/
onSocketClose(callback: Function): void;
// # 媒体 #
/**
* 从本地相册选择图片或使用相机拍照。
*/
chooseImage(obj: {
/**
* 最多可以选择的图片张数,默认9
*/
count?: number;
/**
* original 原图,compressed 压缩图,默认二者都有
*/
sizeType?: string[];
/**
* album 从相册选图,camera 使用相机,默认二者都有
*/
sourceType?: string[];
/**
* 成功则返回图片的本地文件路径列表 tempFilePaths
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 预览图片。
*/
previewImage(obj: {
/**
* 当前显示图片的链接,不填则默认为 urls 的第一张
*/
current?: string;
/**
* 需要预览的图片链接列表
*/
urls: string[];
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 获取图片信息
*/
getImageInfo(obj: {
/**
* 图片的路径,可以是相对路径,临时文件路径,存储文件路径,网络图片路径
*/
src: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
saveImageToPhotosAlbum(obj: {
/**
* 图片文件路径,可以是临时文件路径也可以是永久文件路径,不支持网络图片路径
*/
filePath: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 开始录音。当主动调用wx.stopRecord,或者录音超过1分钟时自动结束录音,返回录音文件的临时文件路径。当用户离开小程序时,此接口无法调用。
*/
startRecord(obj: {
/**
* 录音成功后调用,返回录音文件的临时文件路径,res = {tempFilePath: '录音文件的临时路径'}
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 主动调用停止录音。
*/
stopRecord(): void;
/**
* 开始播放语音,同时只允许一个语音文件正在播放,如果前一个语音文件还没播放完,将中断前一个语音播放。
*/
playVoice(obj: {
/**
* 需要播放的语音文件的文件路径
*/
filePath: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 暂停正在播放的语音。再次调用wx.playVoice播放同一个文件时,会从暂停处开始播放。如果想从头开始播放,需要先调用 wx.stopVoice。
*/
pauseVoice(): void;
/**
* 结束播放语音。
*/
stopVoice(): void;
/**
* 获取后台音乐播放状态。
*/
getBackgroundAudioPlayerState(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 使用后台播放器播放音乐,对于微信客户端来说,只能同时有一个后台音乐在播放。当用户离开小程序后,音乐将暂停播放;当用户点击“显示在聊天顶部”时,音乐不会暂停播放;当用户在其他小程序占用了音乐播放器,原有小程序内的音乐将停止播放。
*/
playBackgroundAudio(obj: {
/**
* 音乐链接,目前支持的格式有 m4a, aac, mp3, wav
*/
dataUrl: string;
/**
* 音乐标题
*/
title?: string;
/**
* 封面URL
*/
coverImgUrl?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 暂停播放音乐。
*/
pauseBackgroundAudio(): void;
/**
* 控制音乐播放进度。
*/
seekBackgroundAudio(obj: {
/**
* 音乐位置,单位:秒
*/
position: number;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 停止播放音乐。
*/
stopBackgroundAudio(): void;
/**
* 监听音乐播放。
*/
onBackgroundAudioPlay(callback: Function): void;
/**
* 监听音乐暂停。
*/
onBackgroundAudioPause(callback: Function): void;
/**
* 监听音乐停止。
*/
onBackgroundAudioStop(callback: Function): void;
getBackgroundAudioManager(): void;
/**
* 创建并返回 audio 上下文 audioContext 对象
*/
createAudioContext(audioId: string): IAudioContext;
/**
* 拍摄视频或从手机相册中选视频,返回视频的临时文件路径。
*/
chooseVideo(obj: {
/**
* album 从相册选视频,camera 使用相机拍摄,默认为:['album', 'camera']
*/
sourceType?: string[];
/**
* 拍摄视频最长拍摄时间,单位秒。最长支持 60 秒
*/
maxDuration?: number;
/**
* 默认调起的为前置还是后置摄像头。front: 前置,back: 后置,默认 back
*/
camera?: string;
/**
* 接口调用成功,返回视频文件的临时文件路径,详见返回参数说明
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
saveVideoToPhotosAlbum(obj: {
/**
* 视频文件路径,可以是临时文件路径也可以是永久文件路径
*/
filePath: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 创建并返回 video 上下文 videoContext 对象
*/
createVideoContext(videoId: string): IVideoContext;
// # 文件 #
/**
* 保存文件到本地。
*/
saveFile(obj: {
/**
* 需要保存的文件的临时路径
*/
tempFilePath: string;
/**
* 返回文件的保存路径,res = {savedFilePath: '文件的保存路径'}
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 获取本地已保存的文件列表
*/
getSavedFileList(obj: {
/**
* 接口调用成功的回调函数,返回结果见success返回参数说明
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 获取本地文件的文件信息。此接口只能用于获取已保存到本地的文件,若需要获取临时文件信息,请使用 wx.getFileInfo 接口。
*/
getSavedFileInfo(obj: {
/**
* 文件路径
*/
filePath: string;
/**
* 接口调用成功的回调函数,返回结果见success返回参数说明
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 删除本地存储的文件
*/
removeSavedFile(obj: {
/**
* 需要删除的文件路径
*/
filePath: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx
*/
openDocument(obj: {
/**
* 文件路径,可通过 downFile 获得
*/
filePath: string;
/**
* 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx
*/
fileType?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getFileInfo(obj: {
/**
* 本地文件路径
*/
filePath: string;
/**
* 计算文件摘要的算法,默认值 md5,有效值:md5,sha1
*/
digestAlgorithm?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
// # 数据缓存 #
/**
* 将数据存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个异步接口。
*/
setStorage(obj: {
/**
* 本地缓存中的指定的 key
*/
key: string;
/**
* 需要存储的内容
*/
data: any;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
*/
setStorageSync(key: string, data: any, ): void;
/**
* 从本地缓存中异步获取指定 key 对应的内容。
*/
getStorage(obj: {
/**
* 本地缓存中的指定的 key
*/
key: string;
/**
* 接口调用的回调函数,res = {data: key对应的内容}
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 从本地缓存中同步获取指定 key 对应的内容。
*/
getStorageSync(key: string): void;
/**
* 异步获取当前storage的相关信息
*/
getStorageInfo(obj: {
/**
* 接口调用的回调函数,详见返回参数说明
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 同步获取当前storage的相关信息
*/
getStorageInfoSync(): void;
/**
* 从本地缓存中异步移除指定 key 。
*/
removeStorage(obj: {
/**
* 本地缓存中的指定的 key
*/
key: string;
/**
* 接口调用的回调函数
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 从本地缓存中同步移除指定 key 。
*/
removeStorageSync(key: string): void;
/**
* 清理本地数据缓存。
*/
clearStorage(): void;
/**
* 同步清理本地数据缓存
*/
clearStorageSync(): void;
// # 位置 #
/**
* 获取当前的地理位置、速度。当用户离开小程序后,此接口无法调用;当用户点击“显示在聊天顶部”时,此接口可继续调用。
*/
getLocation(obj: {
/**
* 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于wx.openLocation的坐标
*/
type?: string;
/**
* 接口调用成功的回调函数,返回内容详见返回参数说明。
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 打开地图选择位置
*/
chooseLocation(obj: {
/**
* 接口调用成功的回调函数,返回内容详见返回参数说明。
*/
success: Function;
/**
* 用户取消时调用
*/
cancel?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 使用微信内置地图查看位置
*/
openLocation(obj: {
/**
* 纬度,范围为-90~90,负数表示南纬
*/
latitude: number;
/**
* 经度,范围为-180~180,负数表示西经
*/
longitude: number;
/**
* 缩放比例,范围5~18,默认为18
*/
scale?: number;
/**
* 位置名
*/
name?: string;
/**
* 地址的详细说明
*/
address?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 创建并返回 map 上下文 mapContext 对象
*/
createMapContext(mapId: string): IMapContext;
// # 设备 #
/**
* 获取系统信息。
*/
getSystemInfo(obj: {
/**
* 接口调用成功的回调
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 获取系统信息同步接口
*/
getSystemInfoSync(): void;
/**
* 获取网络类型。
*/
getNetworkType(obj: {
/**
* 接口调用成功,返回网络类型 networkType
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
onNetworkStatusChange(callback: Function): void;
setScreenBrightness(obj: {
/**
* 屏幕亮度值,范围 0~1,0 最暗,1 最亮
*/
value: number;
/**
* 接口调用成功
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getScreenBrightness(obj: {
/**
* 接口调用成功
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
vibrateLong(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
vibrateShort(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 监听加速度数据,频率:5次/秒,接口调用后会自动开始监听,可使用 wx.stopAccelerometer 停止监听。
*/
onAccelerometerChange(callback: Function): void;
startAccelerometer(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
stopAccelerometer(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 监听罗盘数据,频率:5次/秒,接口调用后会自动开始监听,可使用wx.stopCompass停止监听。
*/
onCompassChange(callback: Function): void;
startCompass(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
stopCompass(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
makePhoneCall(obj: {
/**
* 需要拨打的电话号码
*/
phoneNumber: string;
/**
* 接口调用成功的回调
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 调起客户端扫码界面,扫码成功后返回对应的结果
*/
scanCode(obj: {
/**
* 是否只能从相机扫码,不允许从相册选择图片
*/
onlyFromCamera?: boolean;
/**
* 接口调用成功的回调函数,返回内容详见返回参数说明。
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
setClipboardData(obj: {
/**
* 需要设置的内容
*/
data: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getClipboardData(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
openBluetoothAdapter(obj: {
/**
* 成功则返回成功初始化信息
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
closeBluetoothAdapter(obj: {
/**
* 成功则返回成功关闭模块信息
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getBluetoothAdapterState(obj: {
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
onBluetoothAdapterStateChange(callback: Function): void;
startBluetoothDevicesDiscovery(obj: {
/**
* 蓝牙设备主 service 的 uuid 列表
*/
services?: Array;
/**
* 是否允许重复上报同一设备, 如果允许重复上报,则onDeviceFound 方法会多次上报同一设备,但是 RSSI 值会有不同
*/
allowDuplicatesKey?: boolean;
/**
* 上报设备的间隔,默认为0,意思是找到新设备立即上报,否则根据传入的间隔上报
*/
interval?: number;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
stopBluetoothDevicesDiscovery(obj: {
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getBluetoothDevices(obj: {
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
onBluetoothDeviceFound(callback: Function): void;
getConnectedBluetoothDevices(obj: {
/**
* 蓝牙设备主 service 的 uuid 列表
*/
services: Array;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
createBLEConnection(obj: {
/**
* 蓝牙设备 id,参考 getDevices 接口
*/
deviceId: string;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
closeBLEConnection(obj: {
/**
* 蓝牙设备 id,参考 getDevices 接口
*/
deviceId: string;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getBLEDeviceServices(obj: {
/**
* 蓝牙设备 id,参考 getDevices 接口
*/
deviceId: string;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getBLEDeviceCharacteristics(obj: {
/**
* 蓝牙设备 id,参考 device 对象
*/
deviceId: string;
/**
* 蓝牙服务 uuid
*/
serviceId: string;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
readBLECharacteristicValue(obj: {
/**
* 蓝牙设备 id,参考 device 对象
*/
deviceId: string;
/**
* 蓝牙特征值对应服务的 uuid
*/
serviceId: string;
/**
* 蓝牙特征值的 uuid
*/
characteristicId: string;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
writeBLECharacteristicValue(obj: {
/**
* 蓝牙设备 id,参考 device 对象
*/
deviceId: string;
/**
* 蓝牙特征值对应服务的 uuid
*/
serviceId: string;
/**
* 蓝牙特征值的 uuid
*/
characteristicId: string;
/**
* 蓝牙设备特征值对应的二进制值(注意:vConsole 无法打印出 ArrayBuffer 类型数据)
*/
value: undefined;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
notifyBLECharacteristicValueChange(obj: {
/**
* 蓝牙设备 id,参考 device 对象
*/
deviceId: string;
/**
* 蓝牙特征值对应服务的 uuid
*/
serviceId: string;
/**
* 蓝牙特征值的 uuid
*/
characteristicId: string;
/**
* true: 启用 notify; false: 停用 notify
*/
state: boolean;
/**
* 成功则返回本机蓝牙适配器状态
*/
success: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
onBLEConnectionStateChange(callback: Function): void;
onBLECharacteristicValueChange(callback: Function): void;
startBeaconDiscovery(obj: {
/**
* iBeacon设备广播的 uuids
*/
uuids: string[];
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
stopBeaconDiscovery(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getBeacons(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
onBeaconUpdate(callback: Function): void;
onBeaconServiceChange(callback: Function): void;
onUserCaptureScreen(callback: Function): void;
addPhoneContact(obj: {
/**
* 头像本地文件路径
*/
photoFilePath?: string;
/**
* 昵称
*/
nickName?: string;
/**
* 姓氏
*/
lastName?: string;
/**
* 中间名
*/
middleName?: string;
/**
* 名字
*/
firstName: string;
/**
* 备注
*/
remark?: string;
/**
* 手机号
*/
mobilePhoneNumber?: string;
/**
* 微信号
*/
weChatNumber?: string;
/**
* 联系地址国家
*/
addressCountry?: string;
/**
* 联系地址省份
*/
addressState?: string;
/**
* 联系地址城市
*/
addressCity?: string;
/**
* 联系地址街道
*/
addressStreet?: string;
/**
* 联系地址邮政编码
*/
addressPostalCode?: string;
/**
* 公司
*/
organization?: string;
/**
* 职位
*/
title?: string;
/**
* 工作传真
*/
workFaxNumber?: string;
/**
* 工作电话
*/
workPhoneNumber?: string;
/**
* 公司电话
*/
hostNumber?: string;
/**
* 电子邮件
*/
email?: string;
/**
* 网站
*/
url?: string;
/**
* 工作地址国家
*/
workAddressCountry?: string;
/**
* 工作地址省份
*/
workAddressState?: string;
/**
* 工作地址城市
*/
workAddressCity?: string;
/**
* 工作地址街道
*/
workAddressStreet?: string;
/**
* 工作地址邮政编码
*/
workAddressPostalCode?: string;
/**
* 住宅传真
*/
homeFaxNumber?: string;
/**
* 住宅电话
*/
homePhoneNumber?: string;
/**
* 住宅地址国家
*/
homeAddressCountry?: string;
/**
* 住宅地址省份
*/
homeAddressState?: string;
/**
* 住宅地址城市
*/
homeAddressCity?: string;
/**
* 住宅地址街道
*/
homeAddressStreet?: string;
/**
* 住宅地址邮政编码
*/
homeAddressPostalCode?: string;
/**
* 接口调用成功
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
// # 界面 #
/**
* 显示消息提示框
*/
showToast(obj: {
/**
* 提示的内容
*/
title: string;
/**
* 图标,有效值 "success", "loading"
*/
icon?: string;
/**
* 自定义图标的本地路径,image 的优先级高于 icon
*/
image?: string;
/**
* 提示的延迟时间,单位毫秒,默认:1500
*/
duration?: number;
/**
* 是否显示透明蒙层,防止触摸穿透,默认:false
*/
mask?: boolean;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
showLoading(obj: {
/**
* 提示的内容
*/
title: string;
/**
* 是否显示透明蒙层,防止触摸穿透,默认:false
*/
mask?: boolean;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 隐藏消息提示框
*/
hideToast(): void;
hideLoading(): void;
/**
* 显示模态弹窗
*/
showModal(obj: {
/**
* 提示的标题
*/
title: string;
/**
* 提示的内容
*/
content: string;
/**
* 是否显示取消按钮,默认为 true
*/
showCancel?: boolean;
/**
* 取消按钮的文字,默认为"取消",最多 4 个字符
*/
cancelText?: string;
/**
* 取消按钮的文字颜色,默认为"#000000"
*/
cancelColor?: undefined;
/**
* 确定按钮的文字,默认为"确定",最多 4 个字符
*/
confirmText?: string;
/**
* 确定按钮的文字颜色,默认为"#3CC51F"
*/
confirmColor?: undefined;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 显示操作菜单
*/
showActionSheet(obj: {
/**
* 按钮的文字数组,数组长度最大为6个
*/
itemList: undefined;
/**
* 按钮的文字颜色,默认为"#000000"
*/
itemColor?: undefined;
/**
* 接口调用成功的回调函数,详见返回参数说明
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
setTopBarText(obj: {
/**
* 置顶栏文字内容
*/
text: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 动态设置当前页面的标题。
*/
setNavigationBarTitle(obj: {
/**
* 页面标题
*/
title: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 在当前页面显示导航条加载动画。
*/
showNavigationBarLoading(): void;
/**
* 隐藏导航条加载动画。
*/
hideNavigationBarLoading(): void;
/**
* 保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面。
*/
navigateTo(obj: {
/**
* 需要跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2'
*/
url: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 关闭当前页面,跳转到应用内的某个页面。
*/
redirectTo(obj: {
/**
* 需要跳转的应用内非 tabBar 的页面的路径,路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2'
*/
url: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
reLaunch(obj: {
/**
* 需要跳转的应用内页面路径 , 路径后可以带参数。参数与路径之间使用?分隔,参数键与参数值用=相连,不同参数用&分隔;如 'path?key=value&key2=value2',如果跳转的页面路径是 tabBar 页面则不能带参数
*/
url: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
*/
switchTab(obj: {
/**
* 需要跳转的 tabBar 页面的路径(需在 app.json 的 tabBar 字段定义的页面),路径后不能带参数
*/
url: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages()) 获取当前的页面栈,决定需要返回几层。
*/
navigateBack(obj: {
/**
* 返回的页面数,如果 delta 大于现有页面数,则返回到首页。
*/
delta?: number;
}): void;
/**
* 创建一个动画实例animation。调用实例的方法来描述动画。最后通过动画实例的export方法导出动画数据传递给组件的animation属性。
*/
createAnimation(obj: {
/**
* 400
*/
duration?: number;
/**
* "linear"
*/
timingFunction?: string;
/**
* 0
*/
delay?: number;
/**
* "50% 50% 0"
*/
transformOrigin?: string;
}): IAnimation;
pageScrollTo(obj: {
/**
* 滚动到页面的目标位置(单位px)
*/
scrollTop: number;
}): void;
/**
* 创建 canvas 绘图上下文(指定 canvasId).Tip: 需要指定 canvasId,该绘图上下文只作用于对应的
*/
createCanvasContext(canvasId: string): ICanvasContext;
/**
* 把当前画布的内容导出生成图片,并返回文件路径
*/
canvasToTempFilePath(canvasId: string): void;
startPullDownRefresh(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 停止当前页面下拉刷新。
*/
stopPullDownRefresh(): void;
// # WXML节点信息 #
// # 第三方平台 #
getExtConfig(obj: {
/**
* 返回第三方平台自定义的数据
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getExtConfigSync(): void;
// # 开放接口 #
/**
* 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)。用户数据的加解密通讯需要依赖会话密钥完成。
*/
login(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 通过上述接口获得的用户登录态拥有一定的时效性。用户越久未使用小程序,用户登录态越有可能失效。反之如果用户一直在使用小程序,则用户登录态一直保持有效。具体时效逻辑由微信维护,对开发者透明。开发者只需要调用wx.checkSession接口检测当前用户登录态是否有效。登录态过期后开发者可以再调用wx.login获取新的用户登录态。
*/
checkSession(obj: {
/**
* 接口调用成功的回调函数,登录态未过期
*/
success?: Function;
/**
* 接口调用失败的回调函数,登录态已过期
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
authorize(obj: {
/**
* 需要获取权限的scope,详见 scope 列表
*/
scope: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 获取用户信息,withCredentials 为 true 时需要先调用 wx.login 接口。
*/
getUserInfo(obj: {
/**
* 是否带上登录态信息
*/
withCredentials?: boolean;
/**
* 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文
*/
lang?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
/**
* 发起微信支付。
*/
requestPayment(obj: {
/**
* 时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间
*/
timeStamp: string;
/**
* 随机字符串,长度为32个字符以下。
*/
nonceStr: string;
/**
* 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
*/
package: string;
/**
* 签名算法,暂支持 MD5
*/
signType: string;
/**
* 签名,具体签名方案参见小程序支付接口文档;
*/
paySign: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
chooseAddress(obj: {
/**
* 返回用户选择的收货地址信息
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
addCard(obj: {
/**
* 需要添加的卡券列表,列表内对象说明请参见请求对象说明
*/
cardList: undefined;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
openCard(obj: {
/**
* 需要打开的卡券列表,列表内参数详见openCard 请求对象说明
*/
cardList: undefined;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
openSetting(obj: {
/**
* 接口调用成功的回调函数,返回内容详见返回参数说明。
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getSetting(obj: {
/**
* 接口调用成功的回调函数,返回内容详见返回参数说明。
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
getWeRunData(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
navigateToMiniProgram(obj: {
/**
* 要打开的小程序 appId
*/
appId: string;
/**
* 打开的页面路径,如果为空则打开首页
*/
path?: string;
/**
* 需要传递给目标小程序的数据,目标小程序可在 App.onLaunch(),App.onShow() 中获取到这份数据。详情
*/
extraData?: any;
/**
* 要打开的小程序版本,有效值 develop(开发版),trial(体验版),release(正式版) ,仅在当前小程序为开发版或体验版时此参数有效;如果当前小程序是体验版或正式版,则打开的小程序必定是正式版。默认值 release
*/
envVersion?: string;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
chooseInvoiceTitle(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
checkIsSupportSoterAuthentication(obj: {
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
// # 数据 #
/**
* 自定义分析数据上报接口。使用前,需要在小程序管理后台自定义分析中新建事件,配置好事件名与字段。
*/
reportAnalytics(eventName: string, data: string, ): void;
// # 拓展接口 #
arrayBufferToBase64(arrayBuffer: string): void;
base64ToArrayBuffer(base64: string): void;
// # 调试接口 #
setEnableDebug(obj: {
/**
* 是否打开调试
*/
enableDebug: boolean;
/**
* 接口调用成功的回调函数
*/
success?: Function;
/**
* 接口调用失败的回调函数
*/
fail?: Function;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: Function;
}): void;
}
================================================
FILE: utils/address_parse.js
================================================
const WXAPI = require('apifm-wxapi')
var addressList = []; //地址列表
var smartObj = {};
/**
* 解析邮编
* @param event识别的地址
* @returns
*/
async function smart(event) {
console.log('event1', event);
event = stripscript(event); //过滤特殊字符
console.log('event2', event);
let obj = {};
let copyaddress = JSON.parse(JSON.stringify(event));
console.log('copyaddress', copyaddress);
copyaddress = copyaddress.split(" ");
console.log('地址转为数组:', copyaddress);
for (let index = 0; index < copyaddress.length; index++) {
let res = copyaddress[index];
if (res) {
if (res.length == 1) {
res += "XX"; // 过滤掉一位的名字或者地址
}
let addressObj = await smatrAddress(res);
obj = Object.assign(obj, addressObj);
if (JSON.stringify(addressObj) === "{}") {
obj.name = res.replace("XX", "");
}
}
}
return obj;
}
async function smatrAddress(event) {
smartObj = {};
let address = event;
//address= event.replace(/\s/g, ''); //去除空格
address = stripscript(address); //过滤特殊字符
//身份证号匹配
if (IdentityCodeValid(address)) {
smartObj.idCard = address;
address = address.replace(address, "");
}
//电话匹配
let phone = address.match(
/(86-[1][0-9]{10}) | (86[1][0-9]{10})|([1][0-9]{10})/g
);
if (phone) {
smartObj.phone = phone[0];
address = address.replace(phone[0], "");
}
console.log('smatrAddress:', address);
let matchAddress = "";
//省匹配 比如输入北京市朝阳区,会用北 北京 北京市 北京市朝 以此类推在addressList里的province中做匹配,会得到北京市 河北省 天津市等等;
const resProvince = await WXAPI.provinceV2()
const provinceList = resProvince.data
let matchProvince = []; //粗略匹配上的省份
// for (let begIndex = 0; begIndex < address.length; begIndex++) {
matchAddress = "";
for (let endIndex = 0; endIndex < address.length; endIndex++) {
// if (endIndex > begIndex) {
matchAddress = address.slice(0, endIndex + 2);
provinceList.forEach(res => {
if (res.name.indexOf(matchAddress) != -1) {
matchProvince.push({
province: res.name,
provinceCode: res.id,
matchValue: matchAddress
});
}
});
// }
}
// }
//统计筛选初略统计出的省份
matchProvince.forEach(res => {
res.index = 0;
matchProvince.forEach(el => {
if (res.province == el.province) {
el.index++;
if (res.matchValue.length > el.matchValue.length) {
el.matchValue = res.matchValue;
}
}
});
});
if (matchProvince.length != 0) {
let province = matchProvince.reduce((p, v) => (p.index < v.index ? v : p));
smartObj.province = province.province;
smartObj.provinceCode = province.provinceCode;
address = address.replace(province.matchValue, "");
}
//市查找
const resCity = await WXAPI.cityV2()
let cityList = resCity.data
if (smartObj.provinceCode) {
cityList = resCity.data.filter(ele => {
return ele.pid == smartObj.provinceCode
})
}
let matchCity = []; //粗略匹配上的市
matchAddress = "";
for (let endIndex = 0; endIndex < address.length; endIndex++) {
matchAddress = address.slice(0, endIndex + 2)
cityList.forEach(res => {
if (res.name.indexOf(matchAddress) != -1) {
matchCity.push({
city: res.name,
cityCode: res.id,
pid: res.pid,
matchValue: matchAddress,
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
});
}
//统计筛选初略统计出的市
matchCity.forEach(res => {
res.index = 0;
matchCity.forEach(el => {
if (res.city == el.city) {
el.index++;
if (res.matchValue.length > el.matchValue.length) {
el.matchValue = res.matchValue;
}
}
});
});
// 直辖市处理
if (smartObj.province == '北京市') {
matchCity.push({
city: '北京市',
cityCode: '110100000000',
matchValue: '',
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
if (smartObj.province == '上海市') {
matchCity.push({
city: '上海市',
cityCode: '310100000000',
matchValue: '',
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
if (smartObj.province == '天津市') {
matchCity.push({
city: '天津市',
cityCode: '120100000000',
matchValue: '',
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
if (smartObj.province == '重庆市') {
matchCity.push({
city: '重庆市',
cityCode: '500100000000',
matchValue: '',
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
if (matchCity.length != 0) {
let city = matchCity.reduce((p, v) => (p.index < v.index ? v : p));
smartObj.city = city.city;
smartObj.cityCode = city.cityCode;
// smartObj.county = city.county;
// smartObj.countyCode = city.countyCode;
if (!smartObj.province) {
const _province = provinceList.find(ele => {
return ele.id == city.pid
})
smartObj.province = _province.name;
smartObj.provinceCode = city.pid;
}
address = address.replace(city.matchValue, "");
}
//区县查找
const resDistricts = await WXAPI.districts()
let districtList = resDistricts.data
if (smartObj.cityCode) {
districtList = resDistricts.data.filter(ele => {
return ele.pid == smartObj.cityCode
})
}
console.log('smartObj', smartObj);
let matchCounty = []; //粗略匹配上的区县
matchAddress = "";
for (let endIndex = 0; endIndex < address.length; endIndex++) {
matchAddress = address.slice(0, endIndex + 2);
districtList.forEach(res => {
if (res.name.indexOf(matchAddress) != -1) {
matchCounty.push({
county: res.name,
countyCode: res.id,
city: smartObj.city,
cityCode: smartObj.cityCode,
matchValue: matchAddress,
province: smartObj.province,
provinceCode: smartObj.provinceCode
});
}
});
}
//统计筛选初略统计出的区县
matchCounty.forEach(res => {
res.index = 0;
matchCounty.forEach(el => {
if (res.city == el.city) {
el.index++;
if (res.matchValue.length > el.matchValue.length) {
el.matchValue = res.matchValue;
}
}
});
});
if (matchCounty.length != 0) {
let city = matchCounty.reduce((p, v) => (p.index < v.index ? v : p));
smartObj.county = city.county;
smartObj.countyCode = city.countyCode;
if (!smartObj.province) {
smartObj.province = city.province;
smartObj.provinceCode = city.provinceCode;
}
if (!smartObj.city) {
smartObj.city = city.city;
smartObj.cityCode = city.cityCode;
}
address = address.replace(city.matchValue, "");
}
//街道查找
let matchStreet = []; //粗略匹配上的街道查
matchAddress = "";
for (let endIndex = 0; endIndex < address.length; endIndex++) {
matchAddress = address.slice(0, endIndex + 3);
addressList.forEach(el => {
if (el.name == smartObj.province) {
if (
smartObj.province == "北京市" ||
smartObj.province == "天津市" ||
smartObj.province == "上海市" ||
smartObj.province == "重庆市"
) {
//nothing
} else {
el.children.forEach(element => {
if (element.name == smartObj.city) {
element.children.forEach(item => {
if (item.name == smartObj.county) {
item.children.forEach(res => {
if (res["street"].indexOf(matchAddress) != -1) {
matchStreet.push({
street: res.street,
streetCode: res.code,
matchValue: matchAddress
});
}
});
}
});
}
});
}
}
});
}
//统计筛选初略统计出的区县
matchStreet.forEach(res => {
res.index = 0;
matchStreet.forEach(el => {
if (res.city == el.city) {
el.index++;
if (res.matchValue.length > el.matchValue.length) {
el.matchValue = res.matchValue;
}
}
});
});
if (matchStreet.length != 0) {
let city = matchStreet.reduce((p, v) => (p.index < v.index ? v : p));
smartObj.street = city.street;
smartObj.streetCode = city.streetCode;
address = address.replace(city.matchValue, "");
}
//姓名查找
if (smartObj.province) {
smartObj.address = address;
}
return smartObj;
}
////过滤特殊字符
function stripscript(s) {
s = s.replace(/\t/g, " ")
s = s.replace(/(\d{3})-(\d{4})-(\d{4})/g, "$1$2$3");
s = s.replace(/(\d{3}) (\d{4}) (\d{4})/g, "$1$2$3");
var pattern = new RegExp(
"[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“’。,、?-]"
);
var rs = "";
for (var i = 0; i < s.length; i++) {
rs = rs + s.substr(i, 1).replace(pattern, " ");
}
rs = rs.replace(/[\r\n]/g, "");
return rs;
}
function IdentityCodeValid(code) {
let pass;
var city = {
11: "北京",
12: "天津",
13: "河北",
14: "山西",
15: "内蒙古",
21: "辽宁",
22: "吉林",
23: "黑龙江 ",
31: "上海",
32: "江苏",
33: "浙江",
34: "安徽",
35: "福建",
36: "江西",
37: "山东",
41: "河南",
42: "湖北 ",
43: "湖南",
44: "广东",
45: "广西",
46: "海南",
50: "重庆",
51: "四川",
52: "贵州",
53: "云南",
54: "西藏 ",
61: "陕西",
62: "甘肃",
63: "青海",
64: "宁夏",
65: "新疆",
71: "台湾",
81: "香港",
82: "澳门",
91: "国外 "
};
var tip = "";
pass = true;
if (!code || !/^\d{17}(\d|X)$/i.test(code)) {
tip = "身份证号格式错误";
pass = false;
} else if (!city[code.substr(0, 2)]) {
tip = "地址编码错误";
pass = false;
} else {
//18位身份证需要验证最后一位校验位
if (code.length == 18) {
code = code.split("");
//∑(ai×Wi)(mod 11)
//加权因子
var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//校验位
var parity = [1, 0, "X", 9, 8, 7, 6, 5, 4, 3, 2];
var sum = 0;
var ai = 0;
var wi = 0;
for (var i = 0; i < 17; i++) {
ai = code[i];
wi = factor[i];
sum += ai * wi;
}
var last = parity[sum % 11];
if (parity[sum % 11] != code[17]) {
tip = "校验位错误";
pass = false;
}
}
}
return pass;
}
module.exports = {
smart: smart
};
================================================
FILE: utils/auth.js
================================================
const WXAPI = require('apifm-wxapi')
const CONFIG = require('../config.js')
async function checkSession(){
return new Promise((resolve, reject) => {
wx.checkSession({
success() {
return resolve(true)
},
fail() {
return resolve(false)
}
})
})
}
async function bindSeller() {
const token = wx.getStorageSync('token')
const referrer = wx.getStorageSync('referrer')
if (!token) {
return
}
if (!referrer) {
return
}
const res = await WXAPI.bindSeller({
token,
uid: referrer
})
}
// 检测登录状态,返回 true / false
async function checkHasLogined() {
const token = wx.getStorageSync('token')
if (!token) {
return false
}
const loggined = await checkSession()
if (!loggined) {
wx.removeStorageSync('token')
return false
}
const checkTokenRes = await WXAPI.checkToken(token)
if (checkTokenRes.code != 0) {
wx.removeStorageSync('token')
return false
}
return true
}
async function wxaCode(){
return new Promise((resolve, reject) => {
wx.login({
success(res) {
return resolve(res.code)
},
fail() {
wx.showToast({
title: '获取code失败',
icon: 'none'
})
return resolve('获取code失败')
}
})
})
}
async function login(page){
const _this = this
wx.login({
success: function (res) {
const extConfigSync = wx.getExtConfigSync()
if (extConfigSync.subDomain) {
WXAPI.wxappServiceLogin({
code: res.code
}).then(function (res) {
if (res.code == 10000) {
// 去注册
return;
}
if (res.code != 0) {
// 登录错误
wx.showModal({
title: '无法登录',
content: res.msg,
showCancel: false
})
return;
}
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
if (CONFIG.bindSeller) {
_this.bindSeller()
}
if ( page ) {
page.onShow()
}
})
} else {
WXAPI.login_wx(res.code).then(function (res) {
if (res.code == 10000) {
// 去注册
return;
}
if (res.code != 0) {
// 登录错误
wx.showModal({
title: '无法登录',
content: res.msg,
showCancel: false
})
return;
}
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
if (CONFIG.bindSeller) {
_this.bindSeller()
}
if ( page ) {
page.onShow()
}
})
}
}
})
}
async function authorize() {
// const code = await wxaCode()
// const resLogin = await WXAPI.login_wx(code)
// if (resLogin.code == 0) {
// wx.setStorageSync('token', resLogin.data.token)
// wx.setStorageSync('uid', resLogin.data.uid)
// return resLogin
// }
return new Promise((resolve, reject) => {
wx.login({
success: function (res) {
const code = res.code
let referrer = '' // 推荐人
let referrer_storge = wx.getStorageSync('referrer');
if (referrer_storge) {
referrer = referrer_storge;
}
// 下面开始调用注册接口
const extConfigSync = wx.getExtConfigSync()
if (extConfigSync.subDomain) {
WXAPI.wxappServiceAuthorize({
code: code,
referrer: referrer
}).then(function (res) {
if (res.code == 0) {
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
resolve(res)
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
reject(res.msg)
}
})
} else {
WXAPI.authorize({
code: code,
referrer: referrer
}).then(function (res) {
if (res.code == 0) {
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
resolve(res)
} else {
wx.showToast({
title: res.msg,
icon: 'none'
})
reject(res.msg)
}
})
}
},
fail: err => {
reject(err)
}
})
})
}
// 最新的登陆接口,建议用这个
async function login20241025() {
const code = await wxaCode()
const extConfigSync = wx.getExtConfigSync()
if (extConfigSync.subDomain) {
// 服务商模式
const res = await WXAPI.wxappServiceLogin({ code })
if (res.code == 10000) {
// 去注册
return res
}
if (res.code != 0) {
// 登录错误
wx.showModal({
content: res.msg,
showCancel: false
})
return res
}
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
wx.setStorageSync('openid', res.data.openid)
wx.setStorageSync('mobile', res.data.mobile)
if (CONFIG.bindSeller) {
this.bindSeller()
}
return res
} else {
// 非服务商模式
const res = await WXAPI.login_wx(code)
if (res.code == 10000) {
// 去注册
return res;
}
if (res.code != 0) {
// 登录错误
wx.showModal({
content: res.msg,
showCancel: false
})
return res;
}
wx.setStorageSync('token', res.data.token)
wx.setStorageSync('uid', res.data.uid)
wx.setStorageSync('openid', res.data.openid)
wx.setStorageSync('mobile', res.data.mobile)
if (CONFIG.bindSeller) {
this.bindSeller()
}
return res
}
}
function loginOut(){
wx.removeStorageSync('token')
wx.removeStorageSync('uid')
wx.removeStorageSync('openid')
wx.removeStorageSync('mobile')
}
async function checkAndAuthorize (scope) {
return new Promise((resolve, reject) => {
wx.getSetting({
success(res) {
if (!res.authSetting[scope]) {
wx.authorize({
scope: scope,
success() {
resolve() // 无返回参数
},
fail(e){
console.error(e)
// if (e.errMsg.indexof('auth deny') != -1) {
// wx.showToast({
// title: e.errMsg,
// icon: 'none'
// })
// }
wx.showModal({
title: '无权操作',
content: '需要获得您的授权',
showCancel: false,
confirmText: '立即授权',
confirmColor: '#e64340',
success(res) {
wx.openSetting();
},
fail(e){
console.error(e)
reject(e)
},
})
}
})
} else {
resolve() // 无返回参数
}
},
fail(e){
console.error(e)
reject(e)
}
})
})
}
module.exports = {
checkHasLogined: checkHasLogined,
wxaCode: wxaCode,
login: login,
login20241025: login20241025,
loginOut: loginOut,
checkAndAuthorize: checkAndAuthorize,
authorize: authorize,
bindSeller: bindSeller
}
================================================
FILE: utils/image.js
================================================
function imageUtil (originalWidth, originalHeight) {
let imageSize = {}
wx.getSystemInfo({
success: function (res) {
const windowWidth = res.windowWidth
imageSize.x = 0
imageSize.y = 0
imageSize.windowWidth = windowWidth
imageSize.imageWidth = originalWidth
imageSize.imageHeight = originalHeight
if (originalWidth > windowWidth) {
imageSize.imageWidth = windowWidth
imageSize.imageHeight = windowWidth * originalHeight / originalWidth
} else {
imageSize.x = (windowWidth - originalWidth) / 2
}
}
})
return imageSize
}
module.exports = {
imageUtil: imageUtil
}
================================================
FILE: utils/pay.js
================================================
const WXAPI = require('apifm-wxapi')
/**
* type: order 支付订单 recharge 充值 paybill 优惠买单
* data: 扩展数据对象,用于保存参数
*/
function wxpay(type, money, orderId, redirectUrl, data, content) {
const postData = {
token: wx.getStorageSync('token'),
money: money,
remark: "在线充值",
content: content ? content : ''
}
if (type === 'order') {
postData.remark = "支付订单 :" + orderId;
postData.nextAction = {
type: 0,
id: orderId
};
}
if (type === 'paybill') {
postData.remark = "优惠买单 :" + data.money;
postData.nextAction = {
type: 4,
uid: wx.getStorageSync('uid'),
money: data.money
};
}
if (type === 'fxsBuy') {
postData.remark = "购买分销资格";
postData.nextAction = {
type: 13
};
}
if (type === 'payTz') {
postData.remark = "购买团长 :" + money;
postData.nextAction = {
type: 14
};
}
postData.payName = postData.remark;
if (postData.nextAction) {
postData.nextAction = JSON.stringify(postData.nextAction);
}
const url = wx.getStorageSync('wxpay_api_url')
WXAPI.payVariableUrl(url ? url : '/pay/wx/wxapp', postData).then(function (res) {
if (res.code == 0) {
// 发起支付
wx.requestPayment({
timeStamp: res.data.timeStamp,
nonceStr: res.data.nonceStr,
package: res.data.package,
signType: res.data.signType,
paySign: res.data.paySign,
fail: function (aaa) {
console.error(aaa)
wx.showToast({
title: '支付失败:' + aaa
})
},
success: function () {
// 提示支付成功
wx.showToast({
title: '支付成功'
})
wx.redirectTo({
url: redirectUrl
});
}
})
} else {
wx.showModal({
title: '出错了',
content: JSON.stringify(res),
showCancel: false
})
}
})
}
module.exports = {
wxpay: wxpay
}
================================================
FILE: utils/tools.js
================================================
const WXAPI = require('apifm-wxapi')
// 显示购物车tabBar的Badge
async function showTabBarBadge(noTabBarPage){
const token = wx.getStorageSync('token')
if (!token) {
return 0
}
let number = 0
// 自营商品
let res = await WXAPI.shippingCarInfo(token)
if (res.code == 0) {
number += res.data.number
}
// vop 购物车
const shopping_cart_vop_open = wx.getStorageSync('shopping_cart_vop_open')
if (shopping_cart_vop_open == '1') {
res = await WXAPI.jdvopCartInfoV2(token)
if (res.code == 0) {
number += res.data.number
}
}
if (!noTabBarPage) {
if (number == 0) {
// 删除红点点
wx.removeTabBarBadge({
index: 3
})
} else {
// 显示红点点
wx.setTabBarBadge({
index: 3,
text: number + ''
})
}
}
return number
}
module.exports = {
showTabBarBadge: showTabBarBadge
}
================================================
FILE: utils/tools.wxs
================================================
// 页面上使用的公共类
//
// tools.tofix2(12.33333)
module.exports = {
msg: 'wxs-tools',
tofix2: function(num) {
return num.toFixed(2)
}
};