diff --git a/App.vue b/App.vue index eebadb1..8baccb7 100644 --- a/App.vue +++ b/App.vue @@ -222,4 +222,19 @@ button.hide { .uni-tabbar__icon { height: 50px !important; } + +@keyframes m-zoom { + 0% { + transform: scale(1); + } + + 50% { + transform: scale(0.9); + } + + 100% { + transform: scale(1); + } +} + diff --git a/common/request.js b/common/request.js index 63a7bc3..26e256f 100644 --- a/common/request.js +++ b/common/request.js @@ -25,6 +25,14 @@ class RequestManager { return whitelistUrls.some(whiteItem => url.indexOf(whiteItem) > -1) } + /** + * 生成唯一的nonce值 + * @returns {String} nonce值 + */ + static generateNonce() { + return md5(Date.now() + Math.random().toString(36).substring(2, 15)); + } + /** * 发送网络请求 * @param {Object} param 请求参数 @@ -43,7 +51,7 @@ class RequestManager { return new Promise((resolve, reject) => { // 参数检查 if (!param || typeof param !== 'object') { - reject(new Error('请求参数错误11')) + reject(new Error('请求参数错误')) return } @@ -90,9 +98,48 @@ class RequestManager { console.log('请求URL:', requestUrl) + // 使用正则表达式从URL中提取主机名 + const hostRegex = /^(?:https?:\/\/)?([^\/]+)/i + const matches = requestUrl.match(hostRegex) + const host = matches && matches[1] ? matches[1] : 'localhost' + let header = {} + // 添加签名和防重放攻击参数 + // 1. 添加时间戳 + data.timestamp = Math.floor(Date.now() / 1000) + // 2. 添加nonce随机字符串 + data.nonce = RequestManager.generateNonce() + if (method.toUpperCase() == 'POST') { + // 按照键名对参数进行排序 + const sortedParams = {} + Object.keys(data).sort().forEach(key => { + sortedParams[key] = data[key] + }) + + // 组合参数为字符串 + let signStr = '' + for (const key in sortedParams) { + if (typeof sortedParams[key] === 'object') { + signStr += key + '=' + JSON.stringify(sortedParams[key]) + '&' + } else { + signStr += key + '=' + sortedParams[key] + '&' + } + } + + // 获取时间戳,组合为密钥 + const timestamp = data.timestamp + const appSecret = host + timestamp + + // 添加密钥并去除最后的& + signStr = signStr.substring(0, signStr.length - 1) + appSecret + console.log('签名字符串:', signStr) + + // 使用MD5生成签名 + const sign = md5(signStr) + data.sign = sign + header = { 'content-type': 'application/x-www-form-urlencoded', client: client, @@ -102,41 +149,32 @@ class RequestManager { } } else { // GET请求,添加签名 - if (data) { - // 添加时间戳参数 - data.timestamp = Math.floor(Date.now() / 1000); + // 按照键名对参数进行排序 + const sortedParams = {} + Object.keys(data).sort().forEach(key => { + sortedParams[key] = data[key] + }) - // 按照键名对参数进行排序 - const sortedParams = {}; - Object.keys(data).sort().forEach(key => { - sortedParams[key] = data[key]; - }); - - // 组合参数为字符串 - let signStr = ''; - for (const key in sortedParams) { - signStr += key + '=' + sortedParams[key] + '&'; - } - - // 获取当前请求的域名和时间戳,组合为密钥 - // 使用正则表达式从URL中提取主机名 - const hostRegex = /^(?:https?:\/\/)?([^\/]+)/i; - const matches = requestUrl.match(hostRegex); - const host = matches && matches[1] ? matches[1] : 'localhost'; - const timestamp = data.timestamp; - const appSecret = host + timestamp; - - // 添加密钥并去除最后的& - signStr = signStr.substring(0, signStr.length - 1) + appSecret; - console.log(signStr); - - // 使用MD5生成签名 - const sign = md5(signStr); - - // 添加签名到请求参数 - data.sign = sign; + // 组合参数为字符串 + let signStr = '' + for (const key in sortedParams) { + signStr += key + '=' + sortedParams[key] + '&' } + // 获取时间戳,组合为密钥 + const timestamp = data.timestamp + const appSecret = host + timestamp + + // 添加密钥并去除最后的& + signStr = signStr.substring(0, signStr.length - 1) + appSecret + console.log('签名字符串:', signStr) + + // 使用MD5生成签名 + const sign = md5(signStr) + + // 添加签名到请求参数 + data.sign = sign + header = { 'content-type': 'application/json', token: token, diff --git a/components/banner/banner.vue b/components/banner/banner.vue index 0cc54f1..0a27dfd 100644 --- a/components/banner/banner.vue +++ b/components/banner/banner.vue @@ -4,17 +4,17 @@ - - + + - + - + - + @@ -37,7 +37,12 @@ export default { height: { type: [Number, String], default: 465 - } + }, + // 图片自定义样式 + imgWidth: { + type: Number, + default: 92 + }, }, data() { return { @@ -63,55 +68,17 @@ export default { } }); }, - + // 轮播切换事件 swChange(e) { this.swCur = e.detail.current; }, - + // 点击轮播图跳转 navTo(item) { - /* 领券中心 */ - if (item.ttype == 1) { - this.$c.to({ - url: '/package/index/coupon-center', - query: { - coupon_id: item.coupon_id - } - }) - } + this.$c.navTo(item); - if (item.goods_id > 0) { - if (item.ttype == 2) { - /* 一番赏 */ - this.$c.to({ - url: '/pages/shouye/detail', - query: { - goods_id: item.goods_id - } - }) - } - /* 无限赏 */ - if (item.ttype == 3) { - this.$c.to({ - url: '/pages/shouye/detail_wuxian', - query: { - goods_id: item.goods_id - } - }) - } - - /* 连击赏 */ - if (item.ttype == 4) { - this.$c.to({ - url: '/package/index/lian-ji', - query: { - goods_id: item.goods_id - } - }) - } - } } } } @@ -133,7 +100,7 @@ export default { } /* 允许插槽内的元素可以被点击 */ -.banner-slot-container > * { +.banner-slot-container>* { pointer-events: auto; } @@ -157,7 +124,7 @@ export default { position: absolute; bottom: 20rpx; width: 100%; - + &-item { width: 12rpx; height: 12rpx; @@ -165,7 +132,7 @@ export default { background-color: rgba(255, 255, 255, 0.5); margin: 0 5rpx; transition: all 0.3s; - + &.act { width: 24rpx; border-radius: 6rpx; @@ -173,4 +140,4 @@ export default { } } } - \ No newline at end of file + \ No newline at end of file diff --git a/components/detail-wuxian-lingzhu/detail-wuxian-lingzhu.vue b/components/detail-wuxian-lingzhu/detail-wuxian-lingzhu.vue index 9c35602..478ed96 100644 --- a/components/detail-wuxian-lingzhu/detail-wuxian-lingzhu.vue +++ b/components/detail-wuxian-lingzhu/detail-wuxian-lingzhu.vue @@ -16,6 +16,9 @@ {{ localBossCardData.king_user.z_nums }} 发 + + 虚位以待 + 查看更多 > @@ -24,7 +27,7 @@ - + 领主接力 @@ -41,7 +44,7 @@ - {{ localBossCardData.king_user.nickname }} + {{ (localBossCardData.king_user == null ? "虚位以待" : localBossCardData.king_user.nickname) }} @@ -67,8 +70,7 @@ - + \ No newline at end of file diff --git a/pages/infinite/bonus_house_details.vue b/pages/infinite/bonus_house_details.vue index a6eb0a0..dc5205a 100644 --- a/pages/infinite/bonus_house_details.vue +++ b/pages/infinite/bonus_house_details.vue @@ -47,8 +47,8 @@ - + @@ -74,10 +74,8 @@ - + {{ index + 1 }} @@ -96,10 +94,8 @@ - + {{ index + 1 }} @@ -122,8 +118,7 @@ - {{ buttonText }} @@ -147,7 +142,7 @@ 提示:需在指定时间{{ bonusData.start_time }}-{{ bonusData.end_time }}消耗达到{{ bonusData.choujiang_xianzhi - }}钻石,即可加入房间,还需{{ remainingDiamond }}钻石. + }}钻石,即可加入房间,还需{{ $c.removeTrailingZeros(remainingDiamond) }}钻石. @@ -224,7 +219,7 @@ export default { isAgree: true, loading: false, user_count: 0, //用户已经购买的次数 - + // 动画状态控制变量 headerShow: false, contentShow: false, @@ -232,7 +227,7 @@ export default { tabsShow: [false, false, false], participantRowsShow: [], awardRowsShow: [], - + // 按钮脉冲动画 buttonPulse: false } @@ -245,7 +240,7 @@ export default { return ''; }, remainingDiamond() { - let t = this.bonusData.choujiang_xianzhi - this.user_total_consumption; + let t = (this.bonusData.choujiang_xianzhi - this.user_total_consumption).toFixed(2); return t > 0 ? t : 0; } }, @@ -253,7 +248,7 @@ export default { console.log(options) this.goods_id = options.goods_id await this.load(options.goods_id) - + // 添加页面加载动画 setTimeout(() => { this.applyPageTransitions(); @@ -475,11 +470,11 @@ export default { this.remainingTime = this.formatRemainingTime(endDate - serverNow, "距离开奖时间:"); return; } - - + + }, 1000); - + }, onUnload() { @@ -512,7 +507,7 @@ export default { } catch (error) { console.error("加载参与人数列表失败", error); } - + if (this.currentTab === 1) { setTimeout(() => { this.animateListItems('participant-row'); @@ -543,7 +538,7 @@ export default { } catch (error) { console.error("加载赏品记录失败", error); } - + if (this.currentTab === 2) { setTimeout(() => { this.animateListItems('award-row'); @@ -566,7 +561,7 @@ export default { // 根据列表类型初始化动画状态数组 if (className === 'participant-row') { this.participantRowsShow = Array(this.participantList.length).fill(false); - + // 逐个显示列表项 for (let i = 0; i < this.participantList.length; i++) { ((index) => { @@ -577,7 +572,7 @@ export default { } } else if (className === 'award-row') { this.awardRowsShow = Array(this.awardRecordList.length).fill(false); - + // 逐个显示列表项 for (let i = 0; i < this.awardRecordList.length; i++) { ((index) => { @@ -595,7 +590,7 @@ export default { const endDate = new Date(this.bonusData.end_time.replace(/-/g, '/')); const openDate = new Date(this.bonusData.open_time.replace(/-/g, '/')); // console.log(currentDate,startDate); - + if (currentDate < startDate) { this.buttonText = "未开始"; } else if (currentDate >= startDate && currentDate <= endDate) { @@ -617,7 +612,7 @@ export default { setTimeout(() => { this.buttonPulse = false; }, 400); // 动画时长结束后移除类 - + // 调用原始点击处理程序 this.handleButtonClick(); }, @@ -700,19 +695,19 @@ export default { url: '/pages/shouye/index' }); }, - + applyPageTransitions() { // 头部信息 this.headerShow = true; - + // 标签 setTimeout(() => { this.tabsShow[0] = true; }, 100); setTimeout(() => { this.tabsShow[1] = true; }, 200); setTimeout(() => { this.tabsShow[2] = true; }, 300); - + // 内容区 setTimeout(() => { this.contentShow = true; }, 200); - + // 按钮 setTimeout(() => { this.buttonShow = true; }, 300); } @@ -736,7 +731,7 @@ export default { position: relative; margin-right: 25rpx; transition: all 0.3s ease; - + &:active { transform: scale(0.95); } @@ -764,7 +759,7 @@ export default { font-weight: 400; font-size: 28rpx; color: #CCCCCC; - + &::after { content: ''; position: absolute; @@ -784,6 +779,7 @@ export default { from { width: 0; } + to { width: 48rpx; } @@ -807,25 +803,25 @@ export default { padding: 8rpx; border-radius: 12rpx; position: relative; - + &:active { transform: translateY(-6rpx) scale(1.05); background-color: rgba(0, 0, 0, 0.02); } - + image { transition: all 0.25s ease; box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1); } - + &:active image { box-shadow: 0 8rpx 12rpx rgba(0, 0, 0, 0.15); } - + text { transition: color 0.25s ease; } - + &:active text { color: #666 !important; } @@ -839,11 +835,11 @@ export default { overflow: visible; border: none !important; outline: none !important; - + &::after { border: none !important; } - + &::before { content: ''; position: absolute; @@ -857,11 +853,11 @@ export default { opacity: 0; transition: all 0.2s ease; } - + &:active { transform: scale(0.9) rotate(15deg); } - + &:active::before { transform: scale(1); opacity: 1; @@ -924,18 +920,18 @@ export default { box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); position: relative; overflow: hidden; - + // 页面加载动画 opacity: 0; transform: translateY(20rpx); transition: transform 0.5s ease, opacity 0.5s ease, background-color 0.2s ease, box-shadow 0.2s ease; transition-delay: 0.3s; - + &.show { opacity: 1; transform: translateY(0); } - + &.pulse { animation: buttonPulse 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } @@ -969,7 +965,7 @@ export default { font-size: 35rpx; background-color: #f9f9f9; position: relative; - + &::after { content: ''; position: absolute; @@ -1011,11 +1007,11 @@ export default { transition: all 0.25s ease; position: relative; overflow: hidden; - + &:active { transform: scale(0.95); } - + &::after { content: ''; position: absolute; @@ -1029,12 +1025,12 @@ export default { opacity: 0; transition: all 0.3s ease-out; } - + &:active::after { transform: translate(-50%, -50%) scale(3); opacity: 0; } - + text { position: relative; z-index: 1; @@ -1046,11 +1042,11 @@ export default { .cancel-button { background-color: #FFFFFF; border: 1px solid #eee; - + text { color: #333333; } - + &:active { background-color: #f5f5f5; } @@ -1059,11 +1055,11 @@ export default { .confirm-button { background-color: #CDEF27; box-shadow: 0 4rpx 8rpx rgba(205, 239, 39, 0.3); - + text { color: #333333; } - + &:active { background-color: #b9d721; box-shadow: 0 2rpx 4rpx rgba(205, 239, 39, 0.2); @@ -1075,6 +1071,7 @@ export default { transform: scale(0.9); opacity: 0; } + to { transform: scale(1); opacity: 1; @@ -1086,6 +1083,7 @@ export default { opacity: 0; transform: translateY(20rpx); } + to { opacity: 1; transform: translateY(0); @@ -1096,7 +1094,7 @@ export default { opacity: 0; transform: translateX(-20rpx); transition: all 0.4s ease; - + &.show { opacity: 1; transform: translateX(0); @@ -1107,7 +1105,7 @@ export default { opacity: 0; transform: translateX(-20rpx); transition: all 0.4s ease; - + &.show { opacity: 1; transform: translateX(0); @@ -1118,7 +1116,7 @@ export default { opacity: 0; transform: translateY(-20rpx); transition: all 0.5s ease; - + &.show { opacity: 1; transform: translateY(0); @@ -1129,7 +1127,7 @@ export default { opacity: 0; transform: translateY(10rpx); transition: all 0.4s ease; - + &.show { opacity: 1; transform: translateY(0); @@ -1141,7 +1139,7 @@ export default { transform: translateY(20rpx); transition: all 0.5s ease; transition-delay: 0.2s; - + &.show { opacity: 1; transform: translateY(0); @@ -1153,15 +1151,18 @@ export default { transform: scale(1); box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); } + 40% { transform: scale(0.92); box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.05); } + 80% { transform: scale(1.05); box-shadow: 0 6rpx 10rpx rgba(0, 0, 0, 0.15); background-color: #e0ff3a; } + 100% { transform: scale(1); box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1); diff --git a/pages/mall/index.vue b/pages/mall/index.vue index 586b14b..85aebc8 100644 --- a/pages/mall/index.vue +++ b/pages/mall/index.vue @@ -1,87 +1,81 @@ @@ -252,7 +248,7 @@ export default { if (this.zhifu == 1) { } - + }, confirmSubmit(type) { diff --git a/pages/sangdai/sangdai copy.vue b/pages/sangdai/sangdai copy.vue index a18fff5..9b32055 100644 --- a/pages/sangdai/sangdai copy.vue +++ b/pages/sangdai/sangdai copy.vue @@ -1,58 +1,33 @@ \ No newline at end of file diff --git a/pages/user/tui-guang.vue b/pages/user/tui-guang.vue index 529f602..9cd099f 100644 --- a/pages/user/tui-guang.vue +++ b/pages/user/tui-guang.vue @@ -85,18 +85,17 @@ - + - +