From e5ef46734b138d88ce7e0c152d5e0063118ec4e3 Mon Sep 17 00:00:00 2001 From: cuiyouliang <799699717@qq.com> Date: Tue, 2 Sep 2025 14:49:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A0=E7=BB=88=E8=A1=97=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E9=A1=B9=E7=9B=AE=E5=AF=B9=E6=8E=A5?= =?UTF-8?q?=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/dev.js | 2 +- config/prod.js | 28 +------ project.private.config.json | 14 +++- src/api/home.js | 8 +- src/api/request.js | 17 +---- src/app.js | 22 +----- src/hooks/useScrollLoad.js | 48 ------------ src/pages/index/index.jsx | 107 ++++++++++++++++----------- src/pages/index/index.less | 71 ++---------------- src/utils/globalData.js | 9 --- src/utils/userInfo.js | 80 -------------------- src/utils/util.js | 141 +++--------------------------------- 12 files changed, 104 insertions(+), 443 deletions(-) delete mode 100644 src/hooks/useScrollLoad.js delete mode 100644 src/utils/globalData.js delete mode 100644 src/utils/userInfo.js diff --git a/config/dev.js b/config/dev.js index 34f9095..08ebdcc 100644 --- a/config/dev.js +++ b/config/dev.js @@ -1,7 +1,7 @@ export default { env: { NODE_ENV: JSON.stringify('development'), - baseApiUrl: JSON.stringify(''), + baseApiUrl: JSON.stringify('http://192.168.1.65:8880'), name: JSON.stringify('test'), appId: JSON.stringify('wx87a5db19138da60d'), }, diff --git a/config/prod.js b/config/prod.js index f5caa60..1fdcc09 100644 --- a/config/prod.js +++ b/config/prod.js @@ -3,7 +3,7 @@ export default { env: { NODE_ENV: JSON.stringify('production'), - baseApiUrl: JSON.stringify(''), + baseApiUrl: JSON.stringify('http://192.168.1.65:8880'), name: JSON.stringify('production'), appId: JSON.stringify('wx87a5db19138da60d'), }, @@ -15,31 +15,5 @@ export default { filename => /node_modules\/(?!(@babel|core-js|style-loader|css-loader|react|react-dom))/.test(filename) ] }, - /** - * WebpackChain 插件配置 - * @docs https://github.com/neutrinojs/webpack-chain - */ - // webpackChain (chain) { - // /** - // * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。 - // * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer - // */ - // chain.plugin('analyzer') - // .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, []) - // /** - // * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。 - // * @docs https://github.com/chrisvfritz/prerender-spa-plugin - // */ - // const path = require('path') - // const Prerender = require('prerender-spa-plugin') - // const staticDir = path.join(__dirname, '..', 'dist') - // chain - // .plugin('prerender') - // .use(new Prerender({ - // staticDir, - // routes: [ '/pages/index/index' ], - // postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') }) - // })) - // } } } diff --git a/project.private.config.json b/project.private.config.json index 7a1f20b..76bc936 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -20,5 +20,17 @@ "bigPackageSizeSupport": true }, "libVersion": "3.8.9", - "condition": {} + "condition": { + "miniprogram": { + "list": [ + { + "name": "pages/index/index", + "pathName": "pages/index/index", + "query": "", + "scene": null, + "launchMode": "default" + } + ] + } + } } \ No newline at end of file diff --git a/src/api/home.js b/src/api/home.js index ce73e75..c4ece91 100644 --- a/src/api/home.js +++ b/src/api/home.js @@ -1,8 +1,6 @@ import { RequestMini } from './request'; -/***********首页相关api****************/ - -// 首页 -export function homePageInfoList(data) { - return RequestMini.request('/v1/xxx', data); +// 下单支付获取支付参数 +export function getPrepayParams(data) { + return RequestMini.request('/trans/easypay/trade', data); } diff --git a/src/api/request.js b/src/api/request.js index 9ab3e03..27a115a 100644 --- a/src/api/request.js +++ b/src/api/request.js @@ -1,6 +1,4 @@ import Taro from '@tarojs/taro'; -import { getToken, removeToken, removeUserInfo } from '../utils/util'; - function Request(baseApiUrl) { this.baseApiUrl = baseApiUrl; //后端接口域名 } @@ -20,7 +18,6 @@ Request.prototype.request = function (url, data = {}, options = {}) { data = filterDataNull(data); return new Promise(async (resolve, reject) => { - let token = getToken() || ''; let timestamp = parseInt(+new Date() / 1000); const requestData = { ...data, @@ -32,8 +29,6 @@ Request.prototype.request = function (url, data = {}, options = {}) { //如果是GET,GET自动让数据成为query String,其他方法需要让options.data转化为字符串 header: { 'Content-Type': 'application/json; charset=UTF-8', - // token: token, - Authorization: `Bearer ${token}`, timestamp, }, timeout: 300000, @@ -46,18 +41,8 @@ Request.prototype.request = function (url, data = {}, options = {}) { } console.log('接口=>>>>>>>>>>>>>>>>', requestConf); //监听成功后的操作 - if (response.data.code === 0) { + if (response.data.code === 200) { resolve(response.data); - } else if ( response.data.code === 3 || response.data.code === 4 ) { - Taro.showToast({ - title: response.data.msg || '当前登录用户状态已失效,请重新登陆!', - icon: 'error', - }); - removeUserInfo(); - removeToken(); - Taro.reLaunch({ - url: '/pages/index/index', - }); } else { Taro.showToast({ title: response.data.msg || '抱歉服务器出小差了!', diff --git a/src/app.js b/src/app.js index 7b5ac5f..b526b8c 100644 --- a/src/app.js +++ b/src/app.js @@ -1,30 +1,10 @@ -import Taro, { useLaunch } from '@tarojs/taro'; +import { useLaunch } from '@tarojs/taro'; import { View } from '@tarojs/components'; -import { setGlobalData } from './utils/globalData'; import './app.less' function App({ children }) { useLaunch(async () => { - setCustomNav(); }); - - // 自定义导航 - const setCustomNav = () => { - const MenuButton = Taro.getMenuButtonBoundingClientRect(); - const res = Taro.getWindowInfo(); - let statusBarHeight = res.statusBarHeight; - const contentPaddingLeft = res.windowWidth - MenuButton.right; - const navHeight = statusBarHeight + MenuButton.height + (MenuButton.top - statusBarHeight) * 2; //导航高度 - setGlobalData('customNav', { - height: navHeight, - menuButtonTop: MenuButton.top, - menuButtonHeight: MenuButton.height, - menuButtonWidth: MenuButton.width, - contentPaddingLeft, - statusBarHeight, - }); - - }; // children 是将要会渲染的页面 return {children} diff --git a/src/hooks/useScrollLoad.js b/src/hooks/useScrollLoad.js deleted file mode 100644 index 1312b59..0000000 --- a/src/hooks/useScrollLoad.js +++ /dev/null @@ -1,48 +0,0 @@ -import { useState, useEffect, useRef } from "react"; -import Taro from "@tarojs/taro"; - -export default function useScrollLoad(fetchFn, dataKey = 'data_list') { - const [list, setList] = useState([]); - const next_cursor = useRef("0"); - const [loading, setLoading] = useState(false); - const [noMore, setNoMore] = useState(false); - - const loadData = async (cursor) => { - if (loading || noMore) return; - - setLoading(true); - try { - const { data = {} } = await fetchFn({ next_cursor: cursor }); - setList((prev) => [...prev, ...((data ? data[dataKey] : []) || [])]); - next_cursor.current = data?.next_cursor; - if (!data?.has_more) { - setNoMore(true); - } - } catch (error) { - Taro.showToast({ title: "加载失败", icon: "none" }); - } finally { - setLoading(false); - } - }; - - const refresh = () => { - setList([]); - (next_cursor.current = "0"), setNoMore(false); - loadData("0"); - }; - - useEffect(() => { - const userToken = Taro.getStorageSync("token"); - if (userToken) { - loadData("0"); - } - }, []); - - return { - list, - loading, - noMore, - loadMore: () => loadData(next_cursor.current), - refresh, - }; -} diff --git a/src/pages/index/index.jsx b/src/pages/index/index.jsx index ad606fd..b11a9cd 100644 --- a/src/pages/index/index.jsx +++ b/src/pages/index/index.jsx @@ -1,51 +1,76 @@ -import { View, Text, Image } from '@tarojs/components' -import { useState} from 'react' +import { useState, useEffect} from 'react' +import { View, Button } from '@tarojs/components' +import Taro, { useRouter } from '@tarojs/taro'; +import {requestWeixinPay} from '../../utils/util' +import {getPrepayParams} from "../../api/home"; import './index.less' export default function Index () { - // 切换tab - const [courseList, setCourseList] = useState( - [{ - id:1, - name:'第一节课', - characters:'课程简介', - price:'免费', - bgUrl:'https://lilishop-oss.oss-cn-beijing.aliyuncs.com/9e65ef7e8657491fab18b3595e48dfde.png' - }, - { - id:2, - name:'第二节课', - characters:'课程简介', - price:'免费', - bgUrl:'https://lilishop-oss.oss-cn-beijing.aliyuncs.com/8e33ab68ef734558bdc158d6b1b1451f.png' - } - ] - ); - const goDetailPage =()=>{ + const pageRouter = useRouter() // { path: '', params: { ... } } + const [paySuccess, setPaySuccess] = useState(false); - } - const renderIndexCourseList = ()=>{ - return courseList.map(item=>{ - return( - - - - - - {item.name} - {item.characters} - 免费 - - - ) - }) - } + useEffect(()=>{ + setPaySuccess(false) + const {params:{ id}} = pageRouter + if(id){ // url有订单ID才去拉起支付 + initLogin() + } + },[]) + + // 开始获取code去拉起支付 + const initLogin = () => { + Taro.login({ + force: true, + success: async (res) => { + if(res.errMsg == 'login:ok'){ + getPayParams(res.code) + } else { + Taro.showToast({ + icon: 'error', + title: '获取code登录失败', + }) + } + }, + fail: (err)=>{ + Taro.showToast({ + icon: 'error', + title: '获取code登录失败', + }) + } + }) + } + const getPayParams =(code)=>{ + const {params:{ id}} = pageRouter + const params = { + orderId: id, + payType: "WE_CHAT_MINI_APP", + wxLoginCode: code, + } + getPrepayParams(params).then(res => { + const {wxPrePayParamInfo} = res.data || {} + if(wxPrePayParamInfo){ + requestWeixinPay(wxPrePayParamInfo).then(()=>{ + setPaySuccess(true) + }).catch((err)=>{ + Taro.showToast({ + icon: 'error', + title: `${err}` || '支付失败', + }) + }) + } + }).catch(() => { + + }) + } return ( - { - renderIndexCourseList() + {paySuccess? + + 恭喜您支付成功! + + + :null } - 更多课程敬请期待~ ) diff --git a/src/pages/index/index.less b/src/pages/index/index.less index aaf8273..dcc34f2 100644 --- a/src/pages/index/index.less +++ b/src/pages/index/index.less @@ -1,76 +1,21 @@ .main { width: 375px; + display: flex; + align-items: center; + justify-content: center; margin: 0 auto; min-height: 100vh; background: #f5f0eb; min-height: 100vh; box-sizing: border-box; - .product-card { - width: 100%; - height: 110px; - display: flex; - align-items: center; - justify-content: space-around; - padding-top: 15px; - padding-bottom: 15px; - .image-container { - width: 100px; - height: 30px; - Image { - width: 100%; - height: 100%; - } - } - - .context { - margin-left: 45px; - display: flex; - flex-direction: column; - flex: 1; - position: relative; - } - - .title-top { - font-size: 17px; - color: #303030; - font-weight: bold; - line-height: 33px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - width: 180px; - margin-right: 25px; - } - - .con-center { - font-size: 13px; - color: #606060; - line-height: 22.5px; - overflow: hidden; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - width: 180px; - margin-right: 25px; - margin-bottom: 5px; - } - - .price { - font-size: 18px; - color: rgb(240, 30, 30); - font-weight: bold; - /* position: absolute; - left: 0; - bottom: 7px;*/ + .success-container{ + .success-info{ + margin-bottom: 20px; + font-size: 20px; } } - .coming { - text-align: center; - color: #666; - font-size: 14px; - margin-top: 20px; - margin-bottom: 25px; - } + } diff --git a/src/utils/globalData.js b/src/utils/globalData.js deleted file mode 100644 index da43e22..0000000 --- a/src/utils/globalData.js +++ /dev/null @@ -1,9 +0,0 @@ -const globalData = {} - -export function setGlobalData(key, val) { - globalData[key] = val -} - -export function getGlobalData(key) { - return globalData[key] -} diff --git a/src/utils/userInfo.js b/src/utils/userInfo.js deleted file mode 100644 index b752f86..0000000 --- a/src/utils/userInfo.js +++ /dev/null @@ -1,80 +0,0 @@ -import Taro from '@tarojs/taro'; -import { weChatMiniLogin } from '../api/user'; -import {setToken, setUserInfo} from "./util"; - -// 开始获取code去登录 -const initLogin = (params,maxCount = 2) => { - return new Promise((resolve, reject) =>{ - Taro.login({ - force: true, - success: async (res) => { - try{ - if(res.errMsg == 'login:ok'){ - resolve(await doLogin({...res,...params})); - } else { - reject(res); - } - } catch (err) { - reject(err); - } - }, - fail: (err)=>{ - maxCount <= 1? reject(err) : initLogin(params,maxCount-1); - } - }) - }) -} -// 登录 获取用户信息 -const doLogin = (resData) => { - return new Promise((resolve, reject) => { - weChatMiniLogin({ - wechat_token: resData.code, - appId: process.env.appId, - nickname: resData.nickname, - avatar_url: resData.avatar_url, - }).then(res => { - // 缓存用户信息 - Taro.setStorageSync('userInfo', res.data); - setToken(res?.data?.session_token||''); - resolve(res.data); - }).catch(err => { - reject(err) - }) - }) -} -// 登录且返回用户信息 -export const userLogin = async (params)=> { - // 全局事件池 - Taro.userInfoPoolList = Taro.userInfoPoolList || []; - const userInfo = Taro.getStorageSync('userInfo') || {} - return new Promise((resolve, reject) => { - /*const LOGIN_TIME = Taro.getStorageSync('LOGIN_TIME'); - const NEW_TIME = +new Date().getTime();*/ - // if (userInfo.token && !!LOGIN_TIME && ((NEW_TIME - LOGIN_TIME) < 1000*60*60*24)) { // 登录时效性为1天 - if (userInfo.token) { // 登录时效性为1天 - // 有token直接执行 - resolve(userInfo); - } else { - Taro.userInfoPoolList.push({ - resolve, - reject - }); - if (!Taro.isUserInfo) { - Taro.isUserInfo = true; - initLogin(params).then((data) => { - Taro.userInfoPoolList.forEach((item) => { - item.resolve && item.resolve(data); - }); - }).catch((error) => { - // 登陆接口失败遍历执行reject - Taro.userInfoPoolList.forEach((item) => { - item.reject && item.reject(error); - }); - }).finally(() => { - Taro.isUserInfo = false; - Taro.userInfoPoolList = []; - }); - } - } - }) -} diff --git a/src/utils/util.js b/src/utils/util.js index 4757a2b..1f5a777 100644 --- a/src/utils/util.js +++ b/src/utils/util.js @@ -1,30 +1,5 @@ import Taro from '@tarojs/taro'; -// 随机字符串 -export const randomString = (length = 32) => { - const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - let result = ''; - for (let i = length; i > 0; ) { - result += chars[Math.floor(Math.random() * chars.length)]; - i -= 1; - } - return result; -}; -// 深度拷贝 -export const deepClone = source => { - if (!source && typeof source !== 'object') { - throw new Error('error arguments', 'deepClone'); - } - const targetObj = source.constructor === Array ? [] : {}; - Object.keys(source).forEach(keys => { - if (source[keys] && typeof source[keys] === 'object') { - targetObj[keys] = deepClone(source[keys]); - } else { - targetObj[keys] = source[keys]; - } - }); - return targetObj; -}; // 本地存储 const setStorageSync = (key, value) => { Taro.setStorageSync(key, value); @@ -73,22 +48,6 @@ export const removeToken = () => { return removeStorageSync('token'); }; -// 判断是否是微信小程序 -export const isWeapp = () => { - return true; -}; - -// 是否小程序webview -export const isMiniWebview = () => { - return (window.__wxjs_environment && window.__wxjs_environment === 'miniprogram') || navigator.userAgent.toLowerCase().includes('miniprogram') -}; - -/* - * 判断当前设备类型是否为ios - **/ -export const isApp = () => { - return isAndroid() || isIos(); -}; /* * 判断当前设备类型是否为Android @@ -110,103 +69,23 @@ export const isIos = () => { }; - -// 获取剪贴板 -export const getClipCopy = callback => { - Taro.getClipboardData({ - success: function (res) { - Taro.showToast({ - title: toastText || '复制成功', - icon: 'none', - }); - if (callback && typeof callback === 'function') { - callback(res.data); - } - }, - fail: () => { - Taro.showToast({ - title: '获取剪贴板内容失败', - icon: 'error', - }); - }, - }); -}; - - -// 节流函数 在delay ms内 只触发一次,从而提升性能, -// 如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。 -export const throttle = (fn, gapTime = 1500) => { - let _lastTime = null; - // 返回新的函数 - return function () { - let _nowTime = +new Date(); - if (_nowTime - _lastTime > gapTime || !_lastTime) { - fn.apply(this, arguments); //将this和参数传给原函数 - _lastTime = _nowTime; - } - }; -}; -// 防抖函数 -// 基于上述场景,首先提出第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后: - -// 如果在200ms内没有再次触发滚动事件,那么就执行函数 -// 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时 -export const debounce = (fn, delay = 300) => { - let timer = null; // 借助闭包 - return function () { - if (timer) { - clearTimeout(timer); - } - timer = setTimeout(fn, delay); // 简化写法 - }; -}; - -/** - * 将分转换为元,保留两位小数 - * @param {number} fen 金额(分) - * @returns {string} 金额(元),保留两位小数 - */ -export const fenToYuan =(fen)=> { - // 确保输入是数字 - // eslint-disable-next-line no-restricted-globals - if (typeof fen !== 'number' || isNaN(fen)) { - return '0.00' - throw new Error('输入必须是一个有效的数字'); - } - - // 分转换为元并保留两位小数 - const yuan = (fen / 100).toFixed(2); - - return yuan; -} - - // 拉起支付 -export const requestWeixinPay = (payParams,successCallBack,failCallBack) => { +export const requestWeixinPay = (payParams) => { return new Promise((resolve, reject) =>{ Taro.requestPayment({ - timeStamp: payParams.time_stamp || "", - nonceStr: payParams.nonce_str || "", - package: payParams.package || "", - signType: payParams.sign_type, - paySign: payParams.pay_sign || "", - success: function () { - resolve() + timeStamp: payParams.timeStamp || "", + nonceStr: payParams.nonceStr || "", + package: `prepay_id=${payParams.prepayId}` || "", + signType: payParams.signType || "", + paySign: payParams.paySign || "", + success: function (res) { + resolve(res) }, - fail: function (res) { - reject() + fail: function (err) { + reject(err) }, }); }) }; -// 随机生成某区间的数值不重复 -export const generateRandomNumbers = (length = 10) => { - const arr = Array.from({ length: length }, (_, i) => i + 1); // 创建1-20的数组 - for (let i = arr.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); // 随机索引 [0, i] - [arr[i], arr[j]] = [arr[j], arr[i]]; // 交换元素 - } - return arr; -}