修改若干安卓端的语法

This commit is contained in:
tsui110 2026-03-23 20:28:33 +08:00
parent eb3257f1bd
commit d643abe7e1
13 changed files with 161 additions and 46 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@ node_modules/
.claude/settings.local.json .claude/settings.local.json
.hbuilderx/project.config.json .hbuilderx/project.config.json
clean-cache.bat clean-cache.bat
.hbuilderx/launch.json

View File

@ -4,6 +4,7 @@ import { getPublicConfig } from '@/api/appUser'
export default { export default {
onLaunch: function(options) { onLaunch: function(options) {
console.log('App Launch', options) console.log('App Launch', options)
try { uni.setStorageSync('app_session_id', String(Date.now())) } catch (_) {} try { uni.setStorageSync('app_session_id', String(Date.now())) } catch (_) {}
if (options && options.query && options.query.invite_code) { if (options && options.query && options.query.invite_code) {
console.log('App Launch captured invite_code:', options.query.invite_code) console.log('App Launch captured invite_code:', options.query.invite_code)

View File

@ -222,6 +222,10 @@ export function createWechatOrder(data) {
return authRequest({ url: '/api/app/pay/wechat/jsapi/preorder', method: 'POST', data }) return authRequest({ url: '/api/app/pay/wechat/jsapi/preorder', method: 'POST', data })
} }
export function createWechatAppOrder(data) {
return authRequest({ url: '/api/app/pay/wechat/app/preorder', method: 'POST', data })
}
export function getLotteryResult(order_no) { export function getLotteryResult(order_no) {
return authRequest({ url: '/api/app/lottery/result', method: 'GET', data: { order_no } }) return authRequest({ url: '/api/app/lottery/result', method: 'GET', data: { order_no } })
} }

View File

@ -17,7 +17,9 @@
"delay" : 0 "delay" : 0
}, },
/* */ /* */
"modules" : {}, "modules" : {
"Payment" : {}
},
/* */ /* */
"distribute" : { "distribute" : {
/* android */ /* android */
@ -37,7 +39,10 @@
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>", "<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>"
] ]
}, },
/* ios */ /* ios */
@ -45,7 +50,22 @@
"dSYMs" : false "dSYMs" : false
}, },
/* SDK */ /* SDK */
"sdkConfigs" : {} "sdkConfigs" : {
"payment" : {
"weixin" : {
"__platform__" : ["android", "ios"],
"appid" : "wx26ad074017e1e63f",
"UniversalLinks" : ""
}
},
"share" : {},
"oauth" : {
"weixin" : {
"appid" : "wx26ad074017e1e63f",
"UniversalLinks" : ""
}
}
}
} }
}, },
/* */ /* */

View File

@ -5,7 +5,7 @@
<view v-else-if="isOutOfStock" class="empty">商品库存不足由于市场价格存在波动请联系客服核实价格和补充库存</view> <view v-else-if="isOutOfStock" class="empty">商品库存不足由于市场价格存在波动请联系客服核实价格和补充库存</view>
<view v-else-if="detail.id" class="detail-wrap"> <view v-else-if="detail.id" class="detail-wrap">
<!-- 商品图片轮播 --> <!-- 商品图片轮播 -->
<swiper class="main-image-swiper" v-if="imageList.length > 0" circular autoplay interval="3000" duration="500"> <swiper v-if="imageList.length > 0" :key="'detail-' + swiperKey" class="main-image-swiper" :circular="swiperAutoplay" :autoplay="swiperAutoplay" interval="3000" duration="500">
<swiper-item v-for="(img, index) in imageList" :key="index"> <swiper-item v-for="(img, index) in imageList" :key="index">
<image class="main-image" :src="img" mode="aspectFill" @tap="previewImage(index)" /> <image class="main-image" :src="img" mode="aspectFill" @tap="previewImage(index)" />
</swiper-item> </swiper-item>
@ -45,13 +45,15 @@
<script setup> <script setup>
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app' import { onLoad, onShow, onHide, onUnload } from '@dcloudio/uni-app'
import { getProductDetail } from '../../api/appUser' import { getProductDetail } from '../../api/appUser'
import { redeemProductByPoints } from '../../utils/request.js' import { redeemProductByPoints } from '../../utils/request.js'
const detail = ref({}) const detail = ref({})
const loading = ref(false) const loading = ref(false)
const isOutOfStock = ref(false) const isOutOfStock = ref(false)
const swiperAutoplay = ref(true)
const swiperKey = ref(0)
// //
const imageList = computed(() => { const imageList = computed(() => {
@ -221,6 +223,19 @@ onLoad((opts) => {
const id = opts && opts.id const id = opts && opts.id
if (id) fetchDetail(id) if (id) fetchDetail(id)
}) })
onShow(() => {
swiperKey.value++
swiperAutoplay.value = true
})
onHide(() => {
swiperAutoplay.value = false
})
onUnload(() => {
swiperAutoplay.value = false
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -235,9 +235,9 @@
} }
], ],
"tabBar": { "tabBar": {
"custom": true, "custom": false,
"color": "#7A7E83", "color": "#7A7E83",
"selectedColor": "#007AFF", "selectedColor": "#FF6B00",
"backgroundColor": "#FFFFFF", "backgroundColor": "#FFFFFF",
"borderStyle": "black", "borderStyle": "black",
"list": [ "list": [

View File

@ -4,12 +4,12 @@
<view class="bg-decoration"></view> <view class="bg-decoration"></view>
<!-- 自定义 tabBar --> <!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO --> <!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao /> <customTabBarToutiao />
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<customTabBar />
<!-- #endif -->
<!-- 顶部 Tab --> <!-- 顶部 Tab -->
<view class="tabs glass-card"> <view class="tabs glass-card">
@ -258,12 +258,12 @@ import { getSynthesisRecipes, doSynthesis } from '@/api/synthesis.js'
import { vibrateShort } from '@/utils/vibrate.js' import { vibrateShort } from '@/utils/vibrate.js'
import { checkPhoneBound, checkPhoneBoundSync } from '@/utils/checkPhone.js' import { checkPhoneBound, checkPhoneBoundSync } from '@/utils/checkPhone.js'
import { executePaymentFlow } from '@/utils/payment.js' import { executePaymentFlow } from '@/utils/payment.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue' import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif // #endif
// #ifndef MP-TOUTIAO
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
const currentTab = ref(0) const currentTab = ref(0)
const aggregatedList = ref([]) const aggregatedList = ref([])

View File

@ -7,12 +7,12 @@
<view class="bg-decoration"></view> <view class="bg-decoration"></view>
<!-- 自定义 tabBar --> <!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO --> <!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao /> <customTabBarToutiao />
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<customTabBar />
<!-- #endif -->
<!-- 顶部导航栏 (搜索) --> <!-- 顶部导航栏 (搜索) -->
<view class="nav-header"> <view class="nav-header">
@ -23,7 +23,7 @@
<scroll-view class="main-content" scroll-y> <scroll-view class="main-content" scroll-y>
<!-- Banner 区域 (现代级浮动设计) --> <!-- Banner 区域 (现代级浮动设计) -->
<view class="banner-container"> <view class="banner-container">
<swiper class="banner-swiper" circular autoplay interval="5000" duration="600" :indicator-dots="false" @change="onBannerChange"> <swiper :key="'banner-' + swiperKey" class="banner-swiper" :current="bannerIndex" :circular="swiperAutoplay" :autoplay="swiperAutoplay" interval="5000" duration="600" :indicator-dots="false" @change="onBannerChange">
<swiper-item v-for="(b, index) in displayBanners" :key="b.id"> <swiper-item v-for="(b, index) in displayBanners" :key="b.id">
<view class="banner-card" :class="{ 'active': bannerIndex === index }"> <view class="banner-card" :class="{ 'active': bannerIndex === index }">
<image v-if="b.image" class="banner-image" :src="b.image" mode="aspectFit" @tap="onBannerTap(b)" /> <image v-if="b.image" class="banner-image" :src="b.image" mode="aspectFit" @tap="onBannerTap(b)" />
@ -45,7 +45,7 @@
<!-- 品牌动态栏 (极简风格) --> <!-- 品牌动态栏 (极简风格) -->
<view class="notice-bar-v2" @tap="onNoticeTap"> <view class="notice-bar-v2" @tap="onNoticeTap">
<view class="notice-icon">📢</view> <view class="notice-icon">📢</view>
<swiper class="notice-swiper" vertical circular autoplay interval="3500"> <swiper :key="'notice-' + swiperKey" class="notice-swiper" vertical :circular="swiperAutoplay" :autoplay="swiperAutoplay" interval="3500">
<swiper-item v-for="n in displayNotices" :key="n.id"> <swiper-item v-for="n in displayNotices" :key="n.id">
<view class="notice-item">{{ n.text }}</view> <view class="notice-item">{{ n.text }}</view>
</swiper-item> </swiper-item>
@ -145,22 +145,22 @@
import { authRequest, request } from '../../utils/request.js' import { authRequest, request } from '../../utils/request.js'
import SplashScreen from '@/components/SplashScreen.vue' import SplashScreen from '@/components/SplashScreen.vue'
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js' import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue' import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif // #endif
// #ifndef MP-TOUTIAO
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
export default { export default {
components: { components: {
SplashScreen SplashScreen
// #ifdef MP-WEIXIN
, customTabBar
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
, customTabBarToutiao , customTabBarToutiao
// #endif // #endif
// #ifndef MP-TOUTIAO
, customTabBar
// #endif
}, },
data() { data() {
return { return {
@ -169,7 +169,9 @@ export default {
activities: [], activities: [],
selectedGroupName: '', selectedGroupName: '',
bannerIndex: 0, bannerIndex: 0,
isHomeLoading: false isHomeLoading: false,
swiperAutoplay: true,
swiperKey: 0
} }
}, },
computed: { computed: {
@ -225,11 +227,21 @@ export default {
this.loadHomeData(true) this.loadHomeData(true)
}, },
onShow() { onShow() {
// onLoad/onShow this.swiperKey++
this.swiperAutoplay = true
if (this.activities.length === 0 && !this.isHomeLoading) { if (this.activities.length === 0 && !this.isHomeLoading) {
this.loadHomeData() this.loadHomeData()
} }
}, },
onHide() {
this.swiperAutoplay = false
},
onUnload() {
this.swiperAutoplay = false
},
beforeUnmount() {
this.swiperAutoplay = false
},
methods: { methods: {
onBannerChange(e) { onBannerChange(e) {
this.bannerIndex = e.detail.current this.bannerIndex = e.detail.current

View File

@ -93,7 +93,7 @@
<!-- #endif --> <!-- #endif -->
<!-- 短信登录 --> <!-- 短信登录 -->
<view v-else class="login-panel sms-panel"> <view v-if="loginMode === 'sms'" class="login-panel sms-panel">
<text class="panel-title">手机号验证码登录</text> <text class="panel-title">手机号验证码登录</text>
<text class="panel-desc">输入手机号获取验证码完成登录</text> <text class="panel-desc">输入手机号获取验证码完成登录</text>

View File

@ -4,12 +4,12 @@
<view class="bg-decoration"></view> <view class="bg-decoration"></view>
<!-- 自定义 tabBar --> <!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO --> <!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao /> <customTabBarToutiao />
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<customTabBar />
<!-- #endif -->
<!-- 头部区域 --> <!-- 头部区域 -->
<view class="header-section"> <view class="header-section">
@ -500,21 +500,21 @@ import {
getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinID, getPublicConfig getUserTasks, getTaskProgress, getInviteRecords, modifyUser, getUserProfile, bindDouyinID, getPublicConfig
} from '../../api/appUser.js' } from '../../api/appUser.js'
import { checkPhoneBoundSync } from '../../utils/checkPhone.js' import { checkPhoneBoundSync } from '../../utils/checkPhone.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue' import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif // #endif
// #ifndef MP-TOUTIAO
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
export default { export default {
components: { components: {
// #ifdef MP-WEIXIN
customTabBar,
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
customTabBarToutiao, customTabBarToutiao,
// #endif // #endif
// #ifndef MP-TOUTIAO
customTabBar
// #endif
}, },
data() { data() {
return { return {

View File

@ -3,12 +3,12 @@
<view class="bg-decoration"></view> <view class="bg-decoration"></view>
<!-- 自定义 tabBar --> <!-- 自定义 tabBar -->
<!-- #ifdef MP-WEIXIN -->
<customTabBar />
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO --> <!-- #ifdef MP-TOUTIAO -->
<customTabBarToutiao /> <customTabBarToutiao />
<!-- #endif --> <!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<customTabBar />
<!-- #endif -->
<!-- [NEW] 全新左右布局布局容器 --> <!-- [NEW] 全新左右布局布局容器 -->
<view class="shop-layout"> <view class="shop-layout">
@ -169,12 +169,12 @@ import { ref, watch, onUnmounted } from 'vue'
import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints, getProductCategories } from '../../api/appUser' import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints, getProductCategories } from '../../api/appUser'
import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js' import { checkPhoneBound, checkPhoneBoundSync } from '../../utils/checkPhone.js'
import { vibrateShort } from '@/utils/vibrate.js' import { vibrateShort } from '@/utils/vibrate.js'
// #ifdef MP-WEIXIN
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// #ifdef MP-TOUTIAO // #ifdef MP-TOUTIAO
import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue' import customTabBarToutiao from '@/components/app-tab-bar-toutiao.vue'
// #endif // #endif
// #ifndef MP-TOUTIAO
import customTabBar from '@/components/app-tab-bar.vue'
// #endif
// setup // setup

View File

@ -4,7 +4,7 @@
* 用于统一 一番赏无限赏对对碰 三种玩法的支付流程 * 用于统一 一番赏无限赏对对碰 三种玩法的支付流程
*/ */
import { createWechatOrder } from '../api/appUser' import { createWechatOrder, createWechatAppOrder } from '../api/appUser'
import { hasPhoneBound } from './checkPhone' import { hasPhoneBound } from './checkPhone'
/** /**
@ -17,6 +17,16 @@ export function extractOrderNo(res) {
return res.order_no || res.orderNo || res.data?.order_no || res.data?.orderNo || res.result?.order_no || res.result?.orderNo || null return res.order_no || res.orderNo || res.data?.order_no || res.data?.orderNo || res.result?.order_no || res.result?.orderNo || null
} }
/**
* 判断是否为 App 平台
*/
function isAppPlatform() {
// #ifdef APP-PLUS
return true
// #endif
return false
}
/** /**
* 执行微信支付流程 * 执行微信支付流程
* *
@ -30,6 +40,12 @@ export async function doWechatPayment({ orderNo, openid }) {
throw new Error('订单号不能为空') throw new Error('订单号不能为空')
} }
// App 端支付流程
if (isAppPlatform()) {
return doAppWechatPayment({ orderNo })
}
// 小程序端支付流程
const finalOpenid = openid || uni.getStorageSync('openid') const finalOpenid = openid || uni.getStorageSync('openid')
if (!finalOpenid) { if (!finalOpenid) {
throw new Error('缺少OpenID请重新登录') throw new Error('缺少OpenID请重新登录')
@ -64,6 +80,47 @@ export async function doWechatPayment({ orderNo, openid }) {
}) })
} }
/**
* App 端微信支付流程
*
* @param {Object} options
* @param {string} options.orderNo - 订单号
* @returns {Promise<void>}
*/
async function doAppWechatPayment({ orderNo }) {
// 1. 获取 APP 支付参数
const payRes = await createWechatAppOrder({ order_no: orderNo })
if (!payRes || !payRes.prepayid) {
throw new Error('获取支付参数失败')
}
// 2. 调起微信支付 (App 端使用 orderInfo 对象)
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'wxpay',
orderInfo: {
appid: payRes.appid,
partnerid: payRes.partnerid,
prepayid: payRes.prepayid,
package: payRes.package || 'Sign=WXPay',
noncestr: payRes.noncestr,
timestamp: payRes.timestamp,
sign: payRes.sign
},
success: resolve,
fail: (err) => {
if (err?.errMsg && String(err.errMsg).includes('cancel')) {
const cancelErr = new Error('支付已取消')
cancelErr.cancelled = true
reject(cancelErr)
} else {
reject(err)
}
}
})
})
}
/** /**
* 完整支付流程创建订单 + 支付 * 完整支付流程创建订单 + 支付
* *
@ -99,7 +156,6 @@ export async function executePaymentFlow({ createOrder, openid, onOrderCreated }
*/ */
export function checkLoginStatus() { export function checkLoginStatus() {
const token = uni.getStorageSync('token') const token = uni.getStorageSync('token')
const openid = uni.getStorageSync('openid')
if (!token) { if (!token) {
return { ok: false, message: '请先登录' } return { ok: false, message: '请先登录' }
@ -110,6 +166,12 @@ export function checkLoginStatus() {
return { ok: false, message: '请先绑定手机号' } return { ok: false, message: '请先绑定手机号' }
} }
// App 端不需要 openid
if (isAppPlatform()) {
return { ok: true }
}
const openid = uni.getStorageSync('openid')
if (!openid) { if (!openid) {
return { ok: false, message: '缺少OpenID请重新登录' } return { ok: false, message: '缺少OpenID请重新登录' }
} }

View File

@ -1,5 +1,5 @@
const BASE_URL = 'http://127.0.0.1:9991' //const BASE_URL = 'http://127.0.0.1:9991'
// const BASE_URL = 'https://kdy.1024tool.vip' const BASE_URL = 'https://kdy.1024tool.vip'
let authModalShown = false let authModalShown = false
function handleAuthExpired() { function handleAuthExpired() {