删除不再使用的文件和配置,优化项目结构以提升可维护性;新增环境变量配置示例,更新 Docker 和部署相关文件以支持灵活的端口设置;重构数据库连接逻辑,增强错误处理和配置管理,确保更好的兼容性和稳定性。
This commit is contained in:
@@ -1,211 +0,0 @@
|
||||
// miniprogram/utils/payment.js
|
||||
// 微信支付工具类
|
||||
|
||||
const app = getApp()
|
||||
|
||||
/**
|
||||
* 发起微信支付
|
||||
* @param {Object} options - 支付选项
|
||||
* @param {String} options.orderId - 订单ID
|
||||
* @param {Number} options.amount - 支付金额(元)
|
||||
* @param {String} options.description - 商品描述
|
||||
* @param {Function} options.success - 成功回调
|
||||
* @param {Function} options.fail - 失败回调
|
||||
*/
|
||||
function wxPay(options) {
|
||||
const { orderId, amount, description, success, fail } = options
|
||||
|
||||
wx.showLoading({
|
||||
title: '正在支付...',
|
||||
mask: true
|
||||
})
|
||||
|
||||
// 1. 调用后端创建支付订单
|
||||
wx.request({
|
||||
url: `${app.globalData.apiBase}/payment/create`,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||||
},
|
||||
data: {
|
||||
orderId,
|
||||
amount,
|
||||
description,
|
||||
paymentMethod: 'wechat'
|
||||
},
|
||||
success: (res) => {
|
||||
wx.hideLoading()
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
const paymentData = res.data
|
||||
|
||||
// 2. 调起微信支付
|
||||
wx.requestPayment({
|
||||
timeStamp: paymentData.timeStamp,
|
||||
nonceStr: paymentData.nonceStr,
|
||||
package: paymentData.package,
|
||||
signType: paymentData.signType || 'RSA',
|
||||
paySign: paymentData.paySign,
|
||||
success: (payRes) => {
|
||||
console.log('支付成功', payRes)
|
||||
|
||||
// 3. 通知后端支付成功
|
||||
notifyPaymentSuccess(orderId, paymentData.prepayId)
|
||||
|
||||
wx.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
success && success(payRes)
|
||||
},
|
||||
fail: (payErr) => {
|
||||
console.error('支付失败', payErr)
|
||||
|
||||
if (payErr.errMsg.indexOf('cancel') !== -1) {
|
||||
wx.showToast({
|
||||
title: '支付已取消',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
fail && fail(payErr)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: res.data.message || '创建订单失败',
|
||||
icon: 'none'
|
||||
})
|
||||
fail && fail(res)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
wx.hideLoading()
|
||||
console.error('请求失败', err)
|
||||
|
||||
wx.showToast({
|
||||
title: '网络请求失败',
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
fail && fail(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知后端支付成功
|
||||
* @param {String} orderId
|
||||
* @param {String} prepayId
|
||||
*/
|
||||
function notifyPaymentSuccess(orderId, prepayId) {
|
||||
wx.request({
|
||||
url: `${app.globalData.apiBase}/payment/notify`,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||||
},
|
||||
data: {
|
||||
orderId,
|
||||
prepayId,
|
||||
status: 'success'
|
||||
},
|
||||
success: (res) => {
|
||||
console.log('支付通知成功', res)
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('支付通知失败', err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单状态
|
||||
* @param {String} orderId
|
||||
* @param {Function} callback
|
||||
*/
|
||||
function queryOrderStatus(orderId, callback) {
|
||||
wx.request({
|
||||
url: `${app.globalData.apiBase}/payment/query`,
|
||||
method: 'GET',
|
||||
header: {
|
||||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||||
},
|
||||
data: { orderId },
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
callback && callback(true, res.data)
|
||||
} else {
|
||||
callback && callback(false, null)
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
callback && callback(false, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买完整电子书
|
||||
* @param {Function} success
|
||||
* @param {Function} fail
|
||||
*/
|
||||
function purchaseFullBook(success, fail) {
|
||||
// 计算动态价格:9.9 + (天数 * 1元)
|
||||
const basePrice = 9.9
|
||||
const startDate = new Date('2025-01-01') // 书籍上架日期
|
||||
const today = new Date()
|
||||
const daysPassed = Math.floor((today - startDate) / (1000 * 60 * 60 * 24))
|
||||
const currentPrice = basePrice + daysPassed
|
||||
|
||||
const orderId = `ORDER_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||
|
||||
wxPay({
|
||||
orderId,
|
||||
amount: currentPrice,
|
||||
description: 'Soul派对·创业实验 完整版',
|
||||
success: (res) => {
|
||||
// 更新本地购买状态
|
||||
updatePurchaseStatus(true)
|
||||
success && success(res)
|
||||
},
|
||||
fail
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新购买状态
|
||||
* @param {Boolean} isPurchased
|
||||
*/
|
||||
function updatePurchaseStatus(isPurchased) {
|
||||
const userInfo = app.getUserInfo()
|
||||
if (userInfo) {
|
||||
userInfo.isPurchased = isPurchased
|
||||
wx.setStorageSync('userInfo', userInfo)
|
||||
app.globalData.userInfo = userInfo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否已购买
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function checkPurchaseStatus() {
|
||||
const userInfo = app.getUserInfo()
|
||||
return userInfo ? userInfo.isPurchased : false
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
wxPay,
|
||||
queryOrderStatus,
|
||||
purchaseFullBook,
|
||||
checkPurchaseStatus,
|
||||
updatePurchaseStatus
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
/**
|
||||
* Soul创业实验 - 工具函数
|
||||
*/
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = date => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
|
||||
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
|
||||
}
|
||||
|
||||
const formatNumber = n => {
|
||||
n = n.toString()
|
||||
return n[1] ? n : `0${n}`
|
||||
}
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = date => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
return `${year}-${formatNumber(month)}-${formatNumber(day)}`
|
||||
}
|
||||
|
||||
// 格式化金额
|
||||
const formatMoney = (amount, decimals = 2) => {
|
||||
return Number(amount).toFixed(decimals)
|
||||
}
|
||||
|
||||
// 防抖函数
|
||||
const debounce = (fn, delay = 300) => {
|
||||
let timer = null
|
||||
return function (...args) {
|
||||
if (timer) clearTimeout(timer)
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(this, args)
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
|
||||
// 节流函数
|
||||
const throttle = (fn, delay = 300) => {
|
||||
let last = 0
|
||||
return function (...args) {
|
||||
const now = Date.now()
|
||||
if (now - last >= delay) {
|
||||
fn.apply(this, args)
|
||||
last = now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 生成唯一ID
|
||||
const generateId = () => {
|
||||
return 'id_' + Date.now().toString(36) + Math.random().toString(36).substr(2)
|
||||
}
|
||||
|
||||
// 检查手机号格式
|
||||
const isValidPhone = phone => {
|
||||
return /^1[3-9]\d{9}$/.test(phone)
|
||||
}
|
||||
|
||||
// 检查微信号格式
|
||||
const isValidWechat = wechat => {
|
||||
return wechat && wechat.length >= 6 && wechat.length <= 20
|
||||
}
|
||||
|
||||
// 深拷贝
|
||||
const deepClone = obj => {
|
||||
if (obj === null || typeof obj !== 'object') return obj
|
||||
if (obj instanceof Date) return new Date(obj)
|
||||
if (obj instanceof Array) return obj.map(item => deepClone(item))
|
||||
if (obj instanceof Object) {
|
||||
const copy = {}
|
||||
Object.keys(obj).forEach(key => {
|
||||
copy[key] = deepClone(obj[key])
|
||||
})
|
||||
return copy
|
||||
}
|
||||
}
|
||||
|
||||
// 获取URL参数
|
||||
const getQueryParams = url => {
|
||||
const params = {}
|
||||
const queryString = url.split('?')[1]
|
||||
if (queryString) {
|
||||
queryString.split('&').forEach(pair => {
|
||||
const [key, value] = pair.split('=')
|
||||
params[decodeURIComponent(key)] = decodeURIComponent(value || '')
|
||||
})
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
// 存储操作
|
||||
const storage = {
|
||||
get(key) {
|
||||
try {
|
||||
return wx.getStorageSync(key)
|
||||
} catch (e) {
|
||||
console.error('获取存储失败:', e)
|
||||
return null
|
||||
}
|
||||
},
|
||||
set(key, value) {
|
||||
try {
|
||||
wx.setStorageSync(key, value)
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('设置存储失败:', e)
|
||||
return false
|
||||
}
|
||||
},
|
||||
remove(key) {
|
||||
try {
|
||||
wx.removeStorageSync(key)
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('删除存储失败:', e)
|
||||
return false
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
try {
|
||||
wx.clearStorageSync()
|
||||
return true
|
||||
} catch (e) {
|
||||
console.error('清除存储失败:', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 显示Toast
|
||||
const showToast = (title, icon = 'none', duration = 2000) => {
|
||||
wx.showToast({ title, icon, duration })
|
||||
}
|
||||
|
||||
// 显示Loading
|
||||
const showLoading = (title = '加载中...') => {
|
||||
wx.showLoading({ title, mask: true })
|
||||
}
|
||||
|
||||
// 隐藏Loading
|
||||
const hideLoading = () => {
|
||||
wx.hideLoading()
|
||||
}
|
||||
|
||||
// 显示确认框
|
||||
const showConfirm = (title, content) => {
|
||||
return new Promise((resolve) => {
|
||||
wx.showModal({
|
||||
title,
|
||||
content,
|
||||
success: res => resolve(res.confirm)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatTime,
|
||||
formatDate,
|
||||
formatMoney,
|
||||
formatNumber,
|
||||
debounce,
|
||||
throttle,
|
||||
generateId,
|
||||
isValidPhone,
|
||||
isValidWechat,
|
||||
deepClone,
|
||||
getQueryParams,
|
||||
storage,
|
||||
showToast,
|
||||
showLoading,
|
||||
hideLoading,
|
||||
showConfirm
|
||||
}
|
||||
Reference in New Issue
Block a user