9d8dc7ee by lttnew
2 parents 5798c684 33f3f307
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="cn.fjdmy.uniapp.UniappProjectDataService">
<option name="basePath" value="$PROJECT_DIR$" />
<option name="generalBasePath" value="$PROJECT_DIR$" />
<option name="manifestPath" value="$PROJECT_DIR$/manifest.json" />
<option name="pagesPath" value="$PROJECT_DIR$/pages.json" />
<option name="scanNum" value="1" />
<option name="type" value="store" />
<option name="uniapp" value="true" />
<option name="uniappHx" value="true" />
<option name="vueVersion" value="3" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HtmlDeprecatedAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSEqualityComparisonWithCoercion" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="JSUnresolvedReference" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
</profile>
</component>
\ No newline at end of file
......@@ -10,12 +10,12 @@ import to from 'await-to-js'
/** 错误消息映射表 */
const ERROR_MESSAGES = {
USER_CANCEL: '支付已取消',
NETWORK_ERROR: '网络异常,请检查网络连接',
INVALID_PARAMS: '参数错误',
DECRYPT_FAILED: '数据解密失败',
PARSE_FAILED: '数据解析失败',
PAY_INFO_MISSING: '支付信息缺失'
USER_CANCEL: '支付已取消',
NETWORK_ERROR: '网络异常,请检查网络连接',
INVALID_PARAMS: '参数错误',
DECRYPT_FAILED: '数据解密失败',
PARSE_FAILED: '数据解析失败',
PAY_INFO_MISSING: '支付信息缺失'
}
/**
......@@ -27,68 +27,72 @@ const ERROR_MESSAGES = {
* @throws {Error} 支付过程中发生的错误
*/
async function minShengPay(orderId, encryptedData) {
uni.showLoading({
title: '生成支付...',
mask: true
})
// 参数校验
if (!orderId) {
console.error('minShengPay: orderId is required')
handlePaymentError(new Error(ERROR_MESSAGES.INVALID_PARAMS), null)
}
if (!encryptedData) {
handlePaymentError(new Error(ERROR_MESSAGES.INVALID_PARAMS), orderId)
}
// 1. 数据准备:将表单数据转换为 URL 编码格式
const encodedData = buildUrlEncodedData({
context: encryptedData
})
// 2. 请求支付凭证
const [reqErr, res] = await to(requestPaymentCredential(encodedData))
if (reqErr) {
handlePaymentError(reqErr, orderId)
}
// 3. 响应验证
if (!res?.data?.businessContext) {
handlePaymentError({
message: res?.data?.gateReturnMessage
}, orderId)
}
// 4. 解密并处理数据
const [decryptErr, decryptResult] = await to(decrypt({
bussinessContext: res.data.businessContext
}))
if (decryptErr || !decryptResult?.data) {
handlePaymentError(new Error(ERROR_MESSAGES.DECRYPT_FAILED), orderId)
}
// 5. 解析 JSON 数据
const parsedData = safeJsonParse(decryptResult.data)
if (!parsedData) {
handlePaymentError(new Error(ERROR_MESSAGES.PARSE_FAILED), orderId)
}
// 6. 验证支付信息
if (!parsedData.payInfo) {
handlePaymentError(new Error(ERROR_MESSAGES.PAY_INFO_MISSING), orderId)
}
// 7. 解析支付参数
const payParams = parsePayInfo(parsedData.payInfo)
uni.hideLoading()
// 8. 调起微信支付
const [payErr] = await to(invokeWechatPayment(payParams, orderId))
if (payErr) {
handlePaymentError(payErr, orderId)
}
uni.showLoading({
title: '生成支付...',
mask: true
})
// 参数校验
if (!orderId) {
console.error('minShengPay: orderId is required')
handlePaymentError(new Error(ERROR_MESSAGES.INVALID_PARAMS), null)
}
if (!encryptedData) {
handlePaymentError(new Error(ERROR_MESSAGES.INVALID_PARAMS), orderId)
}
// 1. 数据准备:将表单数据转换为 URL 编码格式
const encodedData = buildUrlEncodedData({
context: encryptedData
})
// 2. 请求支付凭证
const [reqErr, res] = await to(requestPaymentCredential(encodedData))
if (reqErr) {
handlePaymentError(reqErr, orderId)
}
// 3. 响应验证
if (!res?.data?.businessContext) {
handlePaymentError({
message: res?.data?.gateReturnMessage
}, orderId)
}
// 4. 解密并处理数据
const [decryptErr, decryptResult] = await to(decrypt({
bussinessContext: res.data.businessContext
}))
if (decryptErr || !decryptResult?.data) {
handlePaymentError(new Error(ERROR_MESSAGES.DECRYPT_FAILED), orderId)
}
// 5. 解析 JSON 数据
const parsedData = safeJsonParse(decryptResult.data)
if (!parsedData) {
handlePaymentError(new Error(ERROR_MESSAGES.PARSE_FAILED), orderId)
}
// 6. 验证支付信息
if (!parsedData.payInfo) {
handlePaymentError(new Error(ERROR_MESSAGES.PAY_INFO_MISSING), orderId)
}
// 7. 解析支付参数
const payParams = parsePayInfo(parsedData.payInfo)
uni.hideLoading()
// 8. 调起微信支付
const [payErr, paySuccess] = await to(invokeWechatPayment(payParams, orderId))
if (payErr) {
handlePaymentError(payErr, orderId)
}
if (paySuccess) {
return paySuccess
}
}
/**
......@@ -97,9 +101,9 @@ async function minShengPay(orderId, encryptedData) {
* @returns {string} URL 编码格式字符串
*/
function buildUrlEncodedData(data) {
return Object.entries(data)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
return Object.entries(data)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&')
}
/**
......@@ -109,14 +113,14 @@ function buildUrlEncodedData(data) {
* @returns {Promise<Object>} 支付凭证响应
*/
function requestPaymentCredential(encodedData) {
return uni.request({
url: config.payUrl,
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: encodedData
})
return uni.request({
url: config.payUrl,
method: 'POST',
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: encodedData
})
}
/**
......@@ -126,11 +130,11 @@ function requestPaymentCredential(encodedData) {
* @returns {Promise<Object>} 解密后的数据
*/
function decrypt(params) {
return request({
url: `/api/decrypt`,
method: 'post',
params
})
return request({
url: `/api/decrypt`,
method: 'post',
params
})
}
/**
......@@ -139,12 +143,12 @@ function decrypt(params) {
* @returns {Object|null} 解析后的对象,解析失败返回 null
*/
function safeJsonParse(jsonString) {
try {
return JSON.parse(jsonString)
} catch (e) {
console.error('JSON parse error:', e)
return null
}
try {
return JSON.parse(jsonString)
} catch (e) {
console.error('JSON parse error:', e)
return null
}
}
/**
......@@ -157,24 +161,24 @@ function safeJsonParse(jsonString) {
* parsePayInfo('appId=wx123|prepayId=abc|')
*/
function parsePayInfo(payInfoStr) {
if (!payInfoStr || typeof payInfoStr !== 'string') {
return {}
}
const result = {}
payInfoStr.split('|').forEach(item => {
if (!item) return
const index = item.indexOf('=')
if (index === -1) return
const key = item.substring(0, index)
const value = item.substring(index + 1)
result[key] = value
})
return result
if (!payInfoStr || typeof payInfoStr !== 'string') {
return {}
}
const result = {}
payInfoStr.split('|').forEach(item => {
if (!item) return
const index = item.indexOf('=')
if (index === -1) return
const key = item.substring(0, index)
const value = item.substring(index + 1)
result[key] = value
})
return result
}
/**
......@@ -190,44 +194,44 @@ function parsePayInfo(payInfoStr) {
* @returns {Promise<Object>} 支付结果
*/
function invokeWechatPayment(payParams, orderId) {
debugger
return new Promise((resolve, reject) => {
// 参数校验
const requiredFields = ['appId', 'nonceStr', 'prepayId', 'timeStamp', 'signType', 'paySign']
const missingFields = requiredFields.filter(field => !payParams?.[field])
if (missingFields.length > 0) {
reject(new Error(`缺少必要支付参数: ${missingFields.join(', ')}`))
return
}
uni.requestPayment({
appId: payParams.appId,
nonceStr: payParams.nonceStr,
package: `prepay_id=${payParams.prepayId}`,
timeStamp: payParams.timeStamp,
signType: payParams.signType,
paySign: payParams.paySign,
success: (res) => {
uni.showToast({
title: '支付成功',
duration: 2000,
complete: () => resolve(res)
})
},
fail: async (err) => {
debugger
// 用户取消支付
if (err.errMsg?.includes('cancel')) {
await handleUserCancel(orderId)
reject(new Error('USER_CANCEL'))
} else {
await handlePaymentFailure(orderId, err)
reject(err)
}
}
})
})
debugger
return new Promise((resolve, reject) => {
// 参数校验
const requiredFields = ['appId', 'nonceStr', 'prepayId', 'timeStamp', 'signType', 'paySign']
const missingFields = requiredFields.filter(field => !payParams?.[field])
if (missingFields.length > 0) {
reject(new Error(`缺少必要支付参数: ${missingFields.join(', ')}`))
return
}
uni.requestPayment({
appId: payParams.appId,
nonceStr: payParams.nonceStr,
package: `prepay_id=${payParams.prepayId}`,
timeStamp: payParams.timeStamp,
signType: payParams.signType,
paySign: payParams.paySign,
success: (res) => {
uni.showToast({
title: '支付成功',
duration: 2000,
complete: () => resolve(res)
})
},
fail: async (err) => {
debugger
// 用户取消支付
if (err.errMsg?.includes('cancel')) {
await handleUserCancel(orderId)
reject(new Error('USER_CANCEL'))
} else {
await handlePaymentFailure(orderId, err)
reject(err)
}
}
})
})
}
/**
......@@ -237,24 +241,24 @@ function invokeWechatPayment(payParams, orderId) {
* @returns {Promise<void>}
*/
async function handleUserCancel(orderId) {
const [err] = await to(request({
url: 'cancelOrder',
method: 'get',
params: {
orderId
}
}))
if (err) {
console.error('取消订单失败:', err)
return
}
uni.showToast({
title: '支付取消',
icon: 'none',
duration: 2000
})
const [err] = await to(request({
url: 'cancelOrder',
method: 'get',
params: {
orderId
}
}))
if (err) {
console.error('取消订单失败:', err)
return
}
uni.showToast({
title: '支付取消',
icon: 'none',
duration: 2000
})
}
/**
......@@ -265,8 +269,8 @@ async function handleUserCancel(orderId) {
* @returns {Promise<void>}
*/
async function handlePaymentFailure(orderId, error) {
console.error(`支付失败 [订单: ${orderId}]:`, error)
// 可在此处添加支付失败后的业务逻辑,如上报错误等
console.error(`支付失败 [订单: ${orderId}]:`, error)
// 可在此处添加支付失败后的业务逻辑,如上报错误等
}
/**
......@@ -276,21 +280,21 @@ async function handlePaymentFailure(orderId, error) {
* @throws {Error} 始终抛出传入的错误对象
*/
function handlePaymentError(error, orderId) {
uni.hideLoading()
const message = ERROR_MESSAGES[error?.message] || error?.message || '支付失败,请重试'
uni.showToast({
title: message,
icon: 'none'
})
// 记录错误日志,便于排查
console.error(`支付错误 [订单: ${orderId}]:`, error)
throw error
uni.hideLoading()
const message = ERROR_MESSAGES[error?.message] || error?.message || '支付失败,请重试'
uni.showToast({
title: message,
icon: 'none'
})
// 记录错误日志,便于排查
console.error(`支付错误 [订单: ${orderId}]:`, error)
throw error
}
export {
minShengPay
}
\ No newline at end of file
minShengPay
}
......
// dev
// const baseUrl_api = 'http://192.168.1.137:8787'
const baseUrl_api = 'http://tk001.wxjylt.com/stage-api'
const baseUrl_api = 'http://192.168.1.137:8787'
// const baseUrl_api = 'http://tk001.wxjylt.com/stage-api'
const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do'
// prod
......@@ -10,4 +10,4 @@ const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do'
export default {
baseUrl_api,
payUrl
}
\ No newline at end of file
}
......
<template>
<view :class="{ 'lock-scroll': popupShow }">
<view v-if="showDirectly&&directUnderFlag==0">
<view class="flexbox">
<view>
有效日期至 <text class="text-primary">{{form?.validityDate?.slice(0,10) }}</text>
</view>
<view>
<text v-if="activeStatus==0&&authenticationStatusa" class="text-danger">未激活</text>
<text v-else>
<text v-if="authenticationStatusa == 0 ||!authenticationStatusa" class="text-danger">未认证</text>
<text v-if="authenticationStatusa == 1" class="text-success">认证中</text>
<text v-if="authenticationStatusa == 2" class="text-success">已认证</text>
<text v-if="authenticationStatusa == 3" class="text-danger">认证未通过</text>
<text v-if="authenticationStatusa == 4" class="text-danger">即将过期</text>
<text v-if="authenticationStatusa == 5" class="text-danger">已过期</text>
</text>
</view>
</view>
<view class="flexbox" style="justify-content: flex-end;padding: 0 30rpx 40rpx;">
<button class="btn-red" style="margin: 0 20rpx 0 0;" size="mini"
v-if="activeStatus==0&&authenticationStatusa" @click="payTheFees">激活</button>
<view v-else>
<button class="btn-red" style="margin: 0 20rpx 0 0;" size="mini"
:disabled="auditStatus==1||auditStatus==2||form.isPoints==0"
@click="showApplyDialog">考点申请</button>
<button class="btn-red" style="margin: 0 20rpx 0 0;" size="mini" :disabled="btn"
@click="payTheFees">去缴费</button>
<button class="btn-red-kx" style="margin: 0 20rpx 0 0;" size="mini" v-if="form.deptType!=1"
@click="auditEditFN">审核详情</button>
</view>
</view>
</view>
<view class="mainbox">
<uni-list>
<uni-list-item v-if="authenticationStatusa != 1&&authenticationStatusa != 0&&authenticationStatusa != 3"
title="所属协会" :rightText="form.aname">
</uni-list-item>
<uni-list-item title="会员编号" v-if="form.menCode" :rightText="form.menCode" />
<uni-list-item title="机构名称" :rightText="form.name" />
<uni-list-item title="所属省份">
<template v-slot:footer>
<view class="frrr">
<uni-data-picker readonly :clear-icon="false" v-model="form.belongProvinceId"
:localdata="options">
</uni-data-picker>
</view>
</template>
</uni-list-item>
<uni-list-item title="社会信用代码"
v-if="authenticationStatusa != 1&&authenticationStatusa != 0&&authenticationStatusa != 3&&newResult||form.associateId&&form.associateId>0||activeStatus==1"
:rightText="form.creditCode" />
<uni-list-item v-if="form.certSiteContact" title="联系人" :rightText="form.certSiteContact" />
<uni-list-item v-else title="联系人" :rightText="form.contact" />
<uni-list-item v-if="form.certSiteTel" title="联系方式" :rightText="form.certSiteTel" />
<uni-list-item v-else title="联系方式" :rightText="form.phone" />
<uni-list-item title="认证地址">
<template v-slot:footer>
<view class="frrr">
<uni-data-picker readonly :clear-icon="false" v-if="form.certRegionId"
v-model="form.certRegionId" :localdata="options">
</uni-data-picker>
<uni-data-picker readonly :clear-icon="false" v-else-if="form.certCityId"
v-model="form.certCityId" :localdata="options">
</uni-data-picker>
<uni-data-picker readonly :clear-icon="false" v-else-if="form.certProvinceId"
v-model="form.certProvinceId" :localdata="options">
</uni-data-picker>
</view>
</template>
</uni-list-item>
<uni-list-item title="认证详细地址" :rightText="form.certAddress" />
<uni-list-item title="法人姓名" :rightText="form.certLegal||'--'" />
<uni-list-item v-if="form.deptType==6" title="是否为考点" :rightText="form.isPoints==0?'是':'否'" />
<uni-list-item title="法人身份证" clickable>
<template v-slot:footer>
<view v-if="form.legalIdcPhotoArr&&form.legalIdcPhotoArr?.length>0" class="frrr">
<image class="ylImage" mode="aspectFit" @click="showImage(form.legalIdcPhotoArr,index)"
v-for="(item,index) in form.legalIdcPhotoArr" :key="item" :src="item">
</image>
</view>
</template>
</uni-list-item>
<uni-list-item title="营业执照" clickable>
<template v-slot:footer>
<view class="frrr" @click="download(form.businessLicenseArr[0]?.url)"
v-if="form.businessLicenseArr&&form.businessLicenseArr?.length>0">
<text class="text-primary">{{form.businessLicenseArr[0]?.name}}</text>
</view>
</template>
</uni-list-item>
<uni-list-item title="机构照片" clickable>
<template v-slot:footer>
<view class="frrr">
<view v-if="form.picturesArr&&form.picturesArr?.length>0" class="photoBook"
@click="showImage(form.picturesArr,0)">
<image mode="aspectFit" class="ylImage" :src="form.picturesArr[0]">
</image>
<text>{{form.picturesArr?.length}}</text>
</view>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
<!-- 弹窗添加触摸事件拦截 -->
<uni-popup ref="applyPopup" type="center" @touchmove.stop.prevent="() => {}" @open="onPopupOpen"
@close="onPopupClose">
<view class="apply-dialog" @touchmove.stop.prevent="() => {}">
<view class="dialog-title">考点申请</view>
<view class="dialog-content">
<text class="remind">友情提示:非考点无法申请级位考试</text>
</view>
<view class="dialog-buttons">
<button class="btn-cancel" @click="closeApplyDialog">暂不申请</button>
<button class="btn-confirm" @click="goToApplyPage">立即申请</button>
</view>
</view>
</uni-popup>
<view class="height1"></view>
</view>
<view :class="{ 'lock-scroll': popupShow }">
<view v-if="showDirectly&&directUnderFlag==0">
<view class="flexbox">
<view>
有效日期至
<text class="text-primary">{{ form?.validityDate?.slice(0, 10) }}</text>
</view>
<view>
<text v-if="activeStatus==0&&authenticationStatusa" class="text-danger">未激活</text>
<text v-else>
<text v-if="authenticationStatusa == 0 ||!authenticationStatusa" class="text-danger">未认证</text>
<text v-if="authenticationStatusa == 1" class="text-success">认证中</text>
<text v-if="authenticationStatusa == 2" class="text-success">已认证</text>
<text v-if="authenticationStatusa == 3" class="text-danger">认证未通过</text>
<text v-if="authenticationStatusa == 4" class="text-danger">即将过期</text>
<text v-if="authenticationStatusa == 5" class="text-danger">已过期</text>
</text>
</view>
</view>
<view class="flexbox" style="justify-content: flex-end;padding: 0 30rpx 40rpx;">
<button v-if="activeStatus==0&&authenticationStatusa" class="btn-red" size="mini"
style="margin: 0 20rpx 0 0;" @click="payTheFees">激活
</button>
<view v-else>
<button :disabled="auditStatus==1||auditStatus==2||form.isPoints==0" class="btn-red" size="mini"
style="margin: 0 20rpx 0 0;"
@click="showApplyDialog">考点申请
</button>
<button :disabled="btn" class="btn-red" size="mini" style="margin: 0 20rpx 0 0;"
@click="payTheFees">去缴费
</button>
<button v-if="form.deptType!=1" class="btn-red-kx" size="mini" style="margin: 0 20rpx 0 0;"
@click="auditEditFN">审核详情
</button>
</view>
</view>
</view>
<view class="mainbox">
<uni-list>
<uni-list-item v-if="authenticationStatusa != 1&&authenticationStatusa != 0&&authenticationStatusa != 3"
:rightText="form.aname" title="所属协会">
</uni-list-item>
<uni-list-item v-if="form.menCode" :rightText="form.menCode" title="会员编号"/>
<uni-list-item :rightText="form.name" title="机构名称"/>
<uni-list-item title="所属省份">
<template v-slot:footer>
<view class="frrr">
<uni-data-picker v-model="form.belongProvinceId" :clear-icon="false" :localdata="options"
readonly>
</uni-data-picker>
</view>
</template>
</uni-list-item>
<uni-list-item
v-if="authenticationStatusa != 1&&authenticationStatusa != 0&&authenticationStatusa != 3&&newResult||form.associateId&&form.associateId>0||activeStatus==1"
:rightText="form.creditCode"
title="社会信用代码"/>
<uni-list-item v-if="form.certSiteContact" :rightText="form.certSiteContact" title="联系人"/>
<uni-list-item v-else :rightText="form.contact" title="联系人"/>
<uni-list-item v-if="form.certSiteTel" :rightText="form.certSiteTel" title="联系方式"/>
<uni-list-item v-else :rightText="form.phone" title="联系方式"/>
<uni-list-item title="认证地址">
<template v-slot:footer>
<view class="frrr">
<uni-data-picker v-if="form.certRegionId" v-model="form.certRegionId" :clear-icon="false"
:localdata="options" readonly>
</uni-data-picker>
<uni-data-picker v-else-if="form.certCityId" v-model="form.certCityId" :clear-icon="false"
:localdata="options" readonly>
</uni-data-picker>
<uni-data-picker v-else-if="form.certProvinceId" v-model="form.certProvinceId" :clear-icon="false"
:localdata="options" readonly>
</uni-data-picker>
</view>
</template>
</uni-list-item>
<uni-list-item :rightText="form.certAddress" title="认证详细地址"/>
<uni-list-item :rightText="form.certLegal||'--'" title="法人姓名"/>
<uni-list-item v-if="form.deptType==6" :rightText="form.isPoints==0?'是':'否'" title="是否为考点"/>
<uni-list-item clickable title="法人身份证">
<template v-slot:footer>
<view v-if="form.legalIdcPhotoArr&&form.legalIdcPhotoArr?.length>0" class="frrr">
<image v-for="(item,index) in form.legalIdcPhotoArr" :key="item" :src="item"
class="ylImage" mode="aspectFit" @click="showImage(form.legalIdcPhotoArr,index)">
</image>
</view>
</template>
</uni-list-item>
<uni-list-item clickable title="营业执照">
<template v-slot:footer>
<view v-if="form.businessLicenseArr&&form.businessLicenseArr?.length>0" class="frrr"
@click="download(form.businessLicenseArr[0]?.url)">
<text class="text-primary">{{ form.businessLicenseArr[0]?.name }}</text>
</view>
</template>
</uni-list-item>
<uni-list-item clickable title="机构照片">
<template v-slot:footer>
<view class="frrr">
<view v-if="form.picturesArr&&form.picturesArr?.length>0" class="photoBook"
@click="showImage(form.picturesArr,0)">
<image :src="form.picturesArr[0]" class="ylImage" mode="aspectFit">
</image>
<text>{{ form.picturesArr?.length }}</text>
</view>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
<!-- 弹窗添加触摸事件拦截 -->
<uni-popup ref="applyPopup" type="center" @close="onPopupClose" @open="onPopupOpen"
@touchmove.stop.prevent="() => {}">
<view class="apply-dialog" @touchmove.stop.prevent="() => {}">
<view class="dialog-title">考点申请</view>
<view class="dialog-content">
<text class="remind">友情提示:非考点无法申请级位考试</text>
</view>
<view class="dialog-buttons">
<button class="btn-cancel" @click="closeApplyDialog">暂不申请</button>
<button class="btn-confirm" @click="goToApplyPage">立即申请</button>
</view>
</view>
</uni-popup>
<view class="height1"></view>
</view>
</template>
<script setup>
import * as api from '@/common/api.js'
import config from '@/config.js'
import * as loginServer from '@/common/login.js';
import _ from 'underscore'
import {
ref,
onUnmounted
} from 'vue'
import {
onLoad,
onShow
} from '@dcloudio/uni-app'
const app = getApp()
const form = ref({
type: 1
})
const userType = ref()
const activeStatus = ref(0)
const directUnderFlag = ref(0)
const showDirectly = ref(true)
const authenticationStatusa = ref()
const result = ref(false)
const newResult = ref(false)
const btn = ref(false)
const type = ref(true)
const flag = ref(false)
const pr = ref({})
const applicationForMembership1 = ref({})
const options = ref([])
const applyPopup = ref(null)
// 新增:控制弹窗显示状态(用于锁定滚动)
const popupShow = ref(false)
// 考点审核状态 0 未提交 1 审核中 2 审核成功 3 审核失败
const auditStatus = ref(0)
onShow(() => {
init()
if (form.value.deptType != 1) { // 修复:原代码deptType未定义,改为form.value.deptType
getMyStatusAPI()
}
})
// 页面卸载时恢复滚动(防止异常锁死)
onUnmounted(() => {
uni.setPageScrollEnabled({
enabled: true
})
popupShow.value = false
})
function init() {
api.regionsList().then(res => {
options.value = res.data
})
api.getMyOwnMemberInfo().then(res => {
console.log(res)
userType.value = app.globalData.userType
newResult.value = res.data.newResult
result.value = res.data.result
authenticationStatusa.value = res.data.authenticationStatus
showDirectly.value = !res.data.memberInfo.associateId
activeStatus.value = res.data.memberInfo.activeStatus
pr.value = res.data.pr
directUnderFlag.value = res.data.memberInfo.directUnderFlag
if (authenticationStatusa.value == 0) {
btn.value = false
} else if (authenticationStatusa.value == 1) {
btn.value = true
} else {
btn.value = !result.value
}
// 认证信息
if (authenticationStatusa.value == 0 || authenticationStatusa.value == 3) {
type.value = false
}
// 至少审核通过一次
if (authenticationStatusa.value != 0) {
if (newResult.value) {
// 至少认证过一次
flag.value = true
}
}
if (!res.data.memberInfo) {
res.data.memberInfo = {}
}
if (!res.data.dept) {
res.data.dept = {}
}
form.value = {
...res.data.dept,
...res.data.memberInfo
}
// 入会材料
if (form.value.materials) {
form.value.materials1 = JSON.parse(form.value.materials)
}
// 入会申请书
if (form.value.applicationForMembership) {
form.value.applicationForMembership1 = JSON.parse(form.value.applicationForMembership)
}
applicationForMembership1.value = form.value.applicationForMembership || []
form.value.deptType = res.data.dept.deptType
if (form.value.businessLicense) {
form.value.businessLicenseArr = []
try {
form.value.businessLicenseArr = JSON.parse(form.value.businessLicense) || []
} catch (e) {
form.value.businessLicenseArr = [{
url: form.value.businessLicense,
name: '营业执照'
}]
}
console.log('营业执照', form.value.businessLicenseArr)
}
if (form.value.certLegalIdcPhoto && form.value.certLegalIdcPhoto != null) {
form.value.legalIdcPhotoArr = []
var arr = form.value.certLegalIdcPhoto?.split(',') || []
if (arr.length > 0) {
arr = _.map(arr, (p) => {
if (p.indexOf('http') == -1) {
console.log(p)
p = config.baseUrl_api + p
}
return p
})
form.value.legalIdcPhotoArr = arr
}
console.log('法人身份证', form.value.legalIdcPhotoArr)
}
if (form.value.certPictures) {
form.value.picturesArr = []
var arr = form.value.certPictures.split(',') || []
if (arr.length > 0) {
arr = _.map(arr, (p) => {
if (p.indexOf('http') == -1) {
p = config.baseUrl_api + p
}
return p
})
form.value.picturesArr = arr
}
console.log(form.value.picturesArr)
}
})
}
async function getMyStatusAPI() {
const {
data
} = await api.getMyStatus()
if (data && data.auditStatus) {
auditStatus.value = data.auditStatus
} else {
auditStatus.value = 0
}
}
// 新增:弹窗打开时锁定滚动
function onPopupOpen() {
popupShow.value = true
// 1. 小程序API锁定页面滚动
uni.setPageScrollEnabled({
enabled: false
})
// 延时兜底(防止API生效延迟)
setTimeout(() => {
uni.setPageScrollEnabled({
enabled: false
})
}, 100)
}
// 新增:弹窗关闭时恢复滚动
function onPopupClose() {
popupShow.value = false
// 恢复页面滚动
uni.setPageScrollEnabled({
enabled: true
})
setTimeout(() => {
uni.setPageScrollEnabled({
enabled: true
})
}, 100)
}
function showApplyDialog() {
applyPopup.value.open()
}
// 关闭申请弹窗
function closeApplyDialog() {
applyPopup.value.close()
}
// 跳转到考点申请页面
function goToApplyPage() {
closeApplyDialog()
uni.navigateTo({
url: `/myCenter/examPointApply?memId=${form.value.memId}`
})
}
function auditEditFN() {
uni.navigateTo({
url: `/myCenter/reviewList`
})
}
function showImage(arr, index) {
uni.previewImage({
urls: arr,
current: index,
success: function(res) {}
})
}
function download(url) {
console.log(url)
if (url.indexOf('.png') > -1 || url.indexOf('.jpg') > -1) {
if (url.indexOf('http') > -1) {
uni.previewImage({
urls: [url],
success: function(res) {}
})
} else {
uni.previewImage({
urls: [config.baseUrl_api + url],
success: function(res) {}
})
}
} else {
if (url.indexOf('http') > -1) {
goWebView(url)
} else {
goWebView(config.baseUrl_api + url)
}
}
}
function goWebView(url) {
url = url.replace("http://", "https://")
uni.showLoading({
title: '下载中'
});
uni.downloadFile({
url: url,
success: function(res) {
uni.hideLoading();
var filePath = res.tempFilePath;
uni.showLoading({
title: '正在打开'
});
uni.openDocument({
filePath: filePath,
showMenu: true,
success: function(res) {
uni.hideLoading();
},
fail: function(err) {
uni.hideLoading();
uni.showToast({
title: err,
icon: 'none',
duration: 2000
});
}
});
},
fail: function(error) {
uni.hideLoading();
uni.showToast({
title: `下载失败`,
icon: 'none',
duration: 2000
});
}
});
}
function payTheFees() {
if (!form.value.name) {
uni.showToast({
title: `请先完善单位信息`,
icon: 'none'
});
return; // 新增:防止无名称时跳转
}
uni.navigateTo({
url: `/myCenter/perfect`
})
}
import * as api from '@/common/api.js'
import config from '@/config.js'
import * as loginServer from '@/common/login.js';
import _ from 'underscore'
import {
ref,
onUnmounted
} from 'vue'
import {
onLoad,
onShow
} from '@dcloudio/uni-app'
const app = getApp()
const form = ref({
type: 1
})
const userType = ref()
const activeStatus = ref(0)
const directUnderFlag = ref(0)
const showDirectly = ref(true)
const authenticationStatusa = ref()
const result = ref(false)
const resultNoProvince = ref(false)
const newResult = ref(false)
const btn = ref(false)
const type = ref(true)
const flag = ref(false)
const pr = ref({})
const applicationForMembership1 = ref({})
const options = ref([])
const applyPopup = ref(null)
// 新增:控制弹窗显示状态(用于锁定滚动)
const popupShow = ref(false)
// 考点审核状态 0 未提交 1 审核中 2 审核成功 3 审核失败
const auditStatus = ref(0)
onShow(() => {
init()
if (form.value.deptType != 1) { // 修复:原代码deptType未定义,改为form.value.deptType
getMyStatusAPI()
}
})
// 页面卸载时恢复滚动(防止异常锁死)
onUnmounted(() => {
uni.setPageScrollEnabled({
enabled: true
})
popupShow.value = false
})
function init() {
api.regionsList().then(res => {
options.value = res.data
})
api.getMyOwnMemberInfo().then(res => {
console.log(res)
userType.value = app.globalData.userType
newResult.value = res.data.newResult
result.value = res.data.result
resultNoProvince.value = res.data.resultNoProvince2
authenticationStatusa.value = res.data.authenticationStatus
showDirectly.value = !res.data.memberInfo.associateId
activeStatus.value = res.data.memberInfo.activeStatus
pr.value = res.data.pr
directUnderFlag.value = res.data.memberInfo.directUnderFlag
if (authenticationStatusa.value == 0) {
btn.value = false
} else if (authenticationStatusa.value == 1) {
btn.value = true
} else {
// btn.value = !result.value
btn.value = !resultNoProvince.value
}
// 认证信息
if (authenticationStatusa.value == 0 || authenticationStatusa.value == 3) {
type.value = false
}
// 至少审核通过一次
if (authenticationStatusa.value != 0) {
if (newResult.value) {
// 至少认证过一次
flag.value = true
}
}
if (!res.data.memberInfo) {
res.data.memberInfo = {}
}
if (!res.data.dept) {
res.data.dept = {}
}
form.value = {
...res.data.dept,
...res.data.memberInfo
}
// 入会材料
if (form.value.materials) {
form.value.materials1 = JSON.parse(form.value.materials)
}
// 入会申请书
if (form.value.applicationForMembership) {
form.value.applicationForMembership1 = JSON.parse(form.value.applicationForMembership)
}
applicationForMembership1.value = form.value.applicationForMembership || []
form.value.deptType = res.data.dept.deptType
if (form.value.businessLicense) {
form.value.businessLicenseArr = []
try {
form.value.businessLicenseArr = JSON.parse(form.value.businessLicense) || []
} catch (e) {
form.value.businessLicenseArr = [{
url: form.value.businessLicense,
name: '营业执照'
}]
}
console.log('营业执照', form.value.businessLicenseArr)
}
if (form.value.certLegalIdcPhoto && form.value.certLegalIdcPhoto != null) {
form.value.legalIdcPhotoArr = []
var arr = form.value.certLegalIdcPhoto?.split(',') || []
if (arr.length > 0) {
arr = _.map(arr, (p) => {
if (p.indexOf('http') == -1) {
console.log(p)
p = config.baseUrl_api + p
}
return p
})
form.value.legalIdcPhotoArr = arr
}
console.log('法人身份证', form.value.legalIdcPhotoArr)
}
if (form.value.certPictures) {
form.value.picturesArr = []
var arr = form.value.certPictures.split(',') || []
if (arr.length > 0) {
arr = _.map(arr, (p) => {
if (p.indexOf('http') == -1) {
p = config.baseUrl_api + p
}
return p
})
form.value.picturesArr = arr
}
console.log(form.value.picturesArr)
}
})
}
async function getMyStatusAPI() {
const {
data
} = await api.getMyStatus()
if (data && data.auditStatus) {
auditStatus.value = data.auditStatus
} else {
auditStatus.value = 0
}
}
// 新增:弹窗打开时锁定滚动
function onPopupOpen() {
popupShow.value = true
// 1. 小程序API锁定页面滚动
uni.setPageScrollEnabled({
enabled: false
})
// 延时兜底(防止API生效延迟)
setTimeout(() => {
uni.setPageScrollEnabled({
enabled: false
})
}, 100)
}
// 新增:弹窗关闭时恢复滚动
function onPopupClose() {
popupShow.value = false
// 恢复页面滚动
uni.setPageScrollEnabled({
enabled: true
})
setTimeout(() => {
uni.setPageScrollEnabled({
enabled: true
})
}, 100)
}
function showApplyDialog() {
applyPopup.value.open()
}
// 关闭申请弹窗
function closeApplyDialog() {
applyPopup.value.close()
}
// 跳转到考点申请页面
function goToApplyPage() {
closeApplyDialog()
uni.navigateTo({
url: `/myCenter/examPointApply?memId=${form.value.memId}`
})
}
function auditEditFN() {
uni.navigateTo({
url: `/myCenter/reviewList`
})
}
function showImage(arr, index) {
uni.previewImage({
urls: arr,
current: index,
success: function (res) {
}
})
}
function download(url) {
console.log(url)
if (url.indexOf('.png') > -1 || url.indexOf('.jpg') > -1) {
if (url.indexOf('http') > -1) {
uni.previewImage({
urls: [url],
success: function (res) {
}
})
} else {
uni.previewImage({
urls: [config.baseUrl_api + url],
success: function (res) {
}
})
}
} else {
if (url.indexOf('http') > -1) {
goWebView(url)
} else {
goWebView(config.baseUrl_api + url)
}
}
}
function goWebView(url) {
url = url.replace("http://", "https://")
uni.showLoading({
title: '下载中'
});
uni.downloadFile({
url: url,
success: function (res) {
uni.hideLoading();
var filePath = res.tempFilePath;
uni.showLoading({
title: '正在打开'
});
uni.openDocument({
filePath: filePath,
showMenu: true,
success: function (res) {
uni.hideLoading();
},
fail: function (err) {
uni.hideLoading();
uni.showToast({
title: err,
icon: 'none',
duration: 2000
});
}
});
},
fail: function (error) {
uni.hideLoading();
uni.showToast({
title: `下载失败`,
icon: 'none',
duration: 2000
});
}
});
}
function payTheFees() {
if (!form.value.name) {
uni.showToast({
title: `请先完善单位信息`,
icon: 'none'
});
return; // 新增:防止无名称时跳转
}
uni.navigateTo({
url: `/myCenter/perfect`
})
}
</script>
<style scoped lang="scss">
// 新增:锁定滚动的核心样式
.lock-scroll {
position: fixed !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden !important;
height: 100vh !important;
}
.height1 {
height: 100rpx;
}
.photobox {
position: relative;
margin: 30rpx auto;
.photo {
width: 210rpx;
height: 280rpx;
background-color: #f4f4f4;
display: block;
margin: auto;
}
}
.ylImage {
width: 300rpx;
height: 200rpx;
display: block;
box-shadow: 0 0 10rpx #ddd;
border-radius: 8rpx;
}
.photoBook {
position: relative;
border-radius: 10rpx;
overflow: hidden;
&::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7));
}
text {
position: absolute;
z-index: 1;
font-size: 24rpx;
color: #fff;
bottom: 4rpx;
right: 8rpx;
}
}
.frrr {
width: 100%;
text-align: right;
text-align: right;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
:deep(.selected-list) {
font-size: 32rpx;
padding: 0;
}
:deep(.input-value) {
padding: 0;
}
:deep(.uni-list-item__extra-text) {
font-size: 32rpx;
color: #000;
}
:deep(.uni-list-item__extra) {
flex: 1 1 auto;
}
:deep(.uni-list-item__content) {
flex: 0 0 auto;
}
:deep(.uni-list-item__content-title) {
color: #999;
}
.flexbox {
padding: 30rpx;
background-color: #fff;
justify-content: space-between;
}
.mainbox {
margin: 30rpx;
}
.apply-dialog {
width: 530rpx;
background: #fff;
border-radius: 16rpx;
padding: 40rpx;
// 新增:禁止弹窗内部滚动
touch-action: none;
}
.dialog-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.dialog-content {
margin: 40rpx;
}
.remind {
color: #FF8124;
font-size: 26rpx;
margin-top: 40rpx;
}
.dialog-buttons {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
}
.btn-cancel {
width: 225rpx;
height: 80rpx;
line-height: 80rpx;
border: 1rpx solid #ddd;
border-radius: 40rpx;
background: #fff;
color: #333;
text-align: center;
font-size: 14px;
}
.btn-confirm {
width: 225rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
background: #C4121B;
font-size: 14px;
color: #fff;
text-align: center;
}
// 新增:给uni-popup蒙版添加禁止滚动样式
:deep(.uni-popup__mask) {
touch-action: none !important;
}
</style>
\ No newline at end of file
<style lang="scss" scoped>
// 新增:锁定滚动的核心样式
.lock-scroll {
position: fixed !important;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden !important;
height: 100vh !important;
}
.height1 {
height: 100rpx;
}
.photobox {
position: relative;
margin: 30rpx auto;
.photo {
width: 210rpx;
height: 280rpx;
background-color: #f4f4f4;
display: block;
margin: auto;
}
}
.ylImage {
width: 300rpx;
height: 200rpx;
display: block;
box-shadow: 0 0 10rpx #ddd;
border-radius: 8rpx;
}
.photoBook {
position: relative;
border-radius: 10rpx;
overflow: hidden;
&::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7));
}
text {
position: absolute;
z-index: 1;
font-size: 24rpx;
color: #fff;
bottom: 4rpx;
right: 8rpx;
}
}
.frrr {
width: 100%;
text-align: right;
text-align: right;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
:deep(.selected-list) {
font-size: 32rpx;
padding: 0;
}
:deep(.input-value) {
padding: 0;
}
:deep(.uni-list-item__extra-text) {
font-size: 32rpx;
color: #000;
}
:deep(.uni-list-item__extra) {
flex: 1 1 auto;
}
:deep(.uni-list-item__content) {
flex: 0 0 auto;
}
:deep(.uni-list-item__content-title) {
color: #999;
}
.flexbox {
padding: 30rpx;
background-color: #fff;
justify-content: space-between;
}
.mainbox {
margin: 30rpx;
}
.apply-dialog {
width: 530rpx;
background: #fff;
border-radius: 16rpx;
padding: 40rpx;
// 新增:禁止弹窗内部滚动
touch-action: none;
}
.dialog-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.dialog-content {
margin: 40rpx;
}
.remind {
color: #FF8124;
font-size: 26rpx;
margin-top: 40rpx;
}
.dialog-buttons {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
}
.btn-cancel {
width: 225rpx;
height: 80rpx;
line-height: 80rpx;
border: 1rpx solid #ddd;
border-radius: 40rpx;
background: #fff;
color: #333;
text-align: center;
font-size: 14px;
}
.btn-confirm {
width: 225rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
background: #C4121B;
font-size: 14px;
color: #fff;
text-align: center;
}
// 新增:给uni-popup蒙版添加禁止滚动样式
:deep(.uni-popup__mask) {
touch-action: none !important;
}
</style>
......
<template>
<view class="container">
<view class="content">
<view class="card">
<view class="yearRow">
<view class="label">缴费年限</view>
<view class="control">
<image class="icon" @click="minusYear" :src="config.baseUrl_api + '/fs/static/dd_02.png'" mode="widthFix"
v-if="form.renewYear > 1"></image>
<image class="icon" :src="config.baseUrl_api + '/fs/static/dd_02_g.png'" mode="widthFix" v-else></image>
<text class="num">{{ form.renewYear }}</text>
<image class="icon" :src="config.baseUrl_api + '/fs/static/btn_03.png'" mode="widthFix" @click="plusYear"
v-if="form.renewYear < 5"></image>
<image class="icon" :src="config.baseUrl_api + '/fs/static/btn_03_g.png'" mode="widthFix" v-else></image>
</view>
</view>
</view>
<view class="card ">
<!-- 费用合计 -->
<view class="row ">
<text class="label">费用合计</text>
<text class="value red">{{ (form.renewYear * memberFee).toFixed(2) }}</text>
</view>
<view class="hintRow" v-if="preferentialPolicy">
<text
class="hintText">温馨提示:根据中国跆协{{ preferentialData.name || '优惠' }}政策减免一年费用,每个单位在政策有效期内只享受一次</text>
</view>
</view>
<view class="payRow ">
<radio-group @change="onPayTypeChange">
<label class="radioItem">
<radio value="1" :checked="payType === '1'" class="custom-radio" />
<view class="payInfo">
<image class="icon" :src="config.baseUrl_api + '/fs/static/min.png'" mode="widthFix"></image>
<text>民生付</text>
</view>
</label>
</radio-group>
</view>
<view class="totalRow ">
<text class="label">支付费用合计</text>
<text class="value redBig">{{ memberTotalFee }}</text>
</view>
</view>
<view class="bottomBtn">
<view class="deductRow">
<text class="label">减免费用</text>
<text class="value red">-{{ memberFee.toFixed(2) }}</text>
</view>
<button class="payBtn" @click="handelPay" :loading="isPaying">立即支付 ¥{{ memberTotalFee }}</button>
</view>
</view>
<view class="container">
<view class="content">
<view class="card">
<view class="yearRow">
<view class="label">缴费年限</view>
<view class="control">
<image v-if="form.renewYear > 1" class="icon" mode="widthFix" :src="config.baseUrl_api + '/fs/static/slices/dd_02.png'"
@click="minusYear"></image>
<image v-else class="icon" mode="widthFix" :src="config.baseUrl_api + '/fs/static/slices/dd_02_g.png'"></image>
<text class="num">{{ form.renewYear }}</text>
<image v-if="form.renewYear < 5" class="icon" mode="widthFix" :src="config.baseUrl_api + '/fs/static/slices/btn_03.png'"
@click="plusYear"></image>
<image v-else class="icon" mode="widthFix" :src="config.baseUrl_api + '/fs/static/slices/btn_03_g.png'"></image>
</view>
</view>
</view>
<view class="card ">
<!-- 费用合计 -->
<view class="row ">
<text class="label">费用合计</text>
<text class="value red">{{ (form.renewYear * memberFee).toFixed(2) }}</text>
</view>
<view v-if="preferentialPolicy" class="hintRow">
<text
class="hintText">温馨提示:根据中国跆协{{ preferentialData.name || '优惠' }}政策减免一年费用,每个单位在政策有效期内只享受一次
</text>
</view>
</view>
<view class="payRow ">
<radio-group @change="onPayTypeChange">
<label class="radioItem">
<radio :checked="payType === '1'" class="custom-radio" value="1"/>
<view class="payInfo">
<image class="icon" mode="widthFix" :src="config.baseUrl_api + '/fs/static/slices/min.png'"></image>
<text>民生付</text>
</view>
</label>
</radio-group>
</view>
<view class="totalRow ">
<text class="label">支付费用合计</text>
<text class="value redBig">{{ memberTotalFee }}</text>
</view>
</view>
<view class="bottomBtn">
<view class="deductRow">
<text class="label">减免费用</text>
<text class="value red">-{{ memberFee.toFixed(2) }}</text>
</view>
<button :loading="isPaying" class="payBtn" @click="handelPay">立即支付 ¥{{ memberTotalFee }}</button>
</view>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue'
import {
onLoad
} from '@dcloudio/uni-app';
import to from 'await-to-js'
import * as api from '@/common/api.js'
import {
ref,
computed
} from 'vue'
import {
onLoad
} from '@dcloudio/uni-app';
import to from 'await-to-js'
import * as api from '@/common/api.js'
import {minShengPay} from '@/common/pay.js'
import config from '@/config.js'
const form = ref({
renewYear: 1
})
const memberFee = ref(0)
const preferentialPolicy = ref(false)
const preferentialData = ref({
name: '优惠'
})
const payType = ref('1')
const isPaying = ref(false)
const memberTotalFee = computed(() => {
if (preferentialPolicy.value) {
return (memberFee.value * form.value.renewYear - memberFee.value * 1).toFixed(2)
} else {
return (memberFee.value * form.value.renewYear).toFixed(2)
}
})
// 年限减
const minusYear = () => {
if (form.value.renewYear > 1) {
form.value.renewYear--
}
}
// 年限加
const plusYear = () => {
if (form.value.renewYear < 6) {
form.value.renewYear++
}
}
// 支付方式切换
const onPayTypeChange = (e) => {
payType.value = e.detail.value
}
// 支付操作
const handelPay = async () => {
if (memberTotalFee.value < 0) {
uni.showToast({
title: '支付金额异常',
icon: 'none'
})
return
}
// 显示 loading
uni.showLoading({
title: '支付中...',
mask: true
})
isPaying.value = true
// 创建订单
const [orderErr, orderRes] = await to(api.certifiedNew(form.value.renewYear))
if (orderErr) {
uni.hideLoading()
isPaying.value = false
// uni.showToast({
// title: '创建订单失败',
// icon: 'none'
// })
return
}
const data = orderRes.data
// 无需支付,直接成功
if (data.payFlag == 0) {
uni.hideLoading()
isPaying.value = false
uni.redirectTo({
url: `/myCenter/sucPay?orderId=${data.orderId}`
})
return
}
// 需要支付回调
if (data.orderId) {
await to(api.callBack2(data.orderId))
uni.hideLoading()
isPaying.value = false
uni.redirectTo({
url: `/myCenter/sucPay?orderId=${data.orderId}`
})
}
}
onLoad((option) => {
// 接收年限
form.value.renewYear = Number(option.renewYear || 1)
// 初始化获取费用和优惠
init()
})
// 初始化接口
async function init() {
uni.showLoading({
title: '加载中...'
})
const [err] = await to(Promise.all([
getMyMemberCertUnitFeeApi(),
canUseDiscountApi(),
getZtxDiscountPolicyApi()
]))
uni.hideLoading()
if (err) {
console.error('初始化失败:', err)
}
}
// 获取会员单价
async function getMyMemberCertUnitFeeApi() {
const [err, res] = await to(api.getMyMemberCertUnitFee())
if (!err && res.data) {
memberFee.value = Number(res.data || 1500)
}
}
// 是否可用优惠
async function canUseDiscountApi() {
const [err, res] = await to(api.canUseDiscount())
if (!err && res.data !== undefined) {
preferentialPolicy.value = res.data
}
}
// 获取优惠政策详情
async function getZtxDiscountPolicyApi() {
const [err, res] = await to(api.getZtxDiscountPolicy())
if (!err && res.data) {
preferentialData.value = res.data
}
}
const form = ref({
renewYear: 1
})
const memberFee = ref(0)
const preferentialPolicy = ref(false)
const preferentialData = ref({
name: '优惠'
})
const payType = ref('1')
const isPaying = ref(false)
const memberTotalFee = computed(() => {
if (preferentialPolicy.value) {
return (memberFee.value * form.value.renewYear - memberFee.value * 1).toFixed(2)
} else {
return (memberFee.value * form.value.renewYear).toFixed(2)
}
})
// 年限减
const minusYear = () => {
if (form.value.renewYear > 1) {
form.value.renewYear--
}
}
// 年限加
const plusYear = () => {
if (form.value.renewYear < 6) {
form.value.renewYear++
}
}
// 支付方式切换
const onPayTypeChange = (e) => {
payType.value = e.detail.value
}
// 支付操作
const handelPay = async () => {
if (memberTotalFee.value < 0) {
uni.showToast({
title: '支付金额异常',
icon: 'none'
})
return
}
// 显示 loading
uni.showLoading({
title: '支付中...',
mask: true
})
isPaying.value = true
// 创建订单
const [orderErr, orderRes] = await to(api.certifiedNew(form.value.renewYear))
if (orderErr) {
uni.hideLoading()
isPaying.value = false
// uni.showToast({
// title: '创建订单失败',
// icon: 'none'
// })
return
}
const data = orderRes.data
// 无需支付,直接成功
if (data.payFlag == 0) {
uni.hideLoading()
isPaying.value = false
uni.redirectTo({
url: `/myCenter/sucPay?orderId=${data.orderId}`
})
return
}
if (data.payResult.encryptedData) {
const res = minShengPay(data.orderId, data.payResult.encryptedData)
console.log(res)
}
// 需要支付回调
// if (data.orderId) {
// await to(api.callBack2(data.orderId))
// uni.hideLoading()
// isPaying.value = false
//
// uni.redirectTo({
// url: `/myCenter/sucPay?orderId=${data.orderId}`
// })
// }
}
onLoad((option) => {
// 接收年限
form.value.renewYear = Number(option.renewYear || 1)
// 初始化获取费用和优惠
init()
})
// 初始化接口
async function init() {
uni.showLoading({
title: '加载中...'
})
const [err] = await to(Promise.all([
getMyMemberCertUnitFeeApi(),
canUseDiscountApi(),
getZtxDiscountPolicyApi()
]))
uni.hideLoading()
if (err) {
console.error('初始化失败:', err)
}
}
// 获取会员单价
async function getMyMemberCertUnitFeeApi() {
const [err, res] = await to(api.getMyMemberCertUnitFee())
if (!err && res.data) {
memberFee.value = Number(res.data || 1500)
}
}
// 是否可用优惠
async function canUseDiscountApi() {
const [err, res] = await to(api.canUseDiscount())
if (!err && res.data !== undefined) {
preferentialPolicy.value = res.data
}
}
// 获取优惠政策详情
async function getZtxDiscountPolicyApi() {
const [err, res] = await to(api.getZtxDiscountPolicy())
if (!err && res.data) {
preferentialData.value = res.data
}
}
</script>
<style scoped>
/* 整体容器 */
.container {
min-height: 100vh;
background-color: #f7f7f7;
}
/* 内容区域 */
.content {
padding: 20rpx 20rpx 120rpx;
}
/* 卡片 */
.card {
background: #fff;
border-radius: 8rpx;
padding: 25rpx 20rpx;
margin-bottom: 20rpx;
}
/* 缴费年限行 */
.yearRow {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
}
.yearRow .label {
font-size: 28rpx;
color: #333;
}
.yearRow .control {
display: flex;
align-items: center;
}
.control image {
width: 50rpx;
height: 50rpx;
}
/* 加减按钮样式 */
.num-btn {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border: 1rpx solid #C4121B;
}
.num-btn.disabled {
border-color: #ccc;
}
.num-btn.disabled .btn-icon {
color: #ccc;
}
.btn-icon {
font-size: 24rpx;
color: #C4121B;
font-weight: bold;
}
.yearRow .num {
font-size: 28rpx;
color: #333;
min-width: 80rpx;
text-align: center;
margin: 0 10rpx;
}
/* 通用行 */
.row {
display: flex;
justify-content: space-between;
align-items: center;
}
.row .label {
font-size: 28rpx;
color: #333;
}
.row .value {
font-size: 30rpx;
color: #C4121B;
font-weight: 500;
}
/* 优惠提示 */
.hintRow {
display: flex;
align-items: flex-start;
font-size: 24rpx;
line-height: 1.4;
}
.hint-icon {
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #C4121B;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10rpx;
flex-shrink: 0;
margin-top: 2rpx;
}
.icon {
width: 30px;
}
.icon-check {
color: #fff;
font-size: 16rpx;
}
.hintRow .hintText {
color: #FF8124;
flex: 1;
margin-top: 10rpx;
}
/* 减免费用 */
.deductRow {
background: #fff;
padding: 20rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
border-radius: 8rpx;
}
.deductRow .label {
font-size: 28rpx;
color: #333;
}
.deductRow .value {
font-size: 30rpx;
color: #C4121B;
}
/* 支付方式行 */
.payRow {
background: #fff;
border-radius: 8rpx;
padding: 20rpx 20rpx;
margin-bottom: 20rpx;
}
.radioItem {
display: flex;
align-items: center;
}
/* 自定义红色单选框 */
::v-deep .custom-radio .wx-radio-input {
width: 30rpx;
height: 30rpx;
border-radius: 50%;
border: 2rpx solid #ccc;
}
::v-deep .custom-radio .wx-radio-input.wx-radio-input-checked {
border-color: #C4121B !important;
background: #C4121B !important;
}
.payInfo {
display: flex;
align-items: center;
margin-left: 15rpx;
}
.payInfo .icon {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.payInfo text {
font-size: 28rpx;
color: #333;
}
/* 总费用行(突出显示) */
.totalRow {
background: #fff;
border-radius: 8rpx;
padding: 20rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10rpx;
}
.totalRow .label {
font-size: 28rpx;
color: #333;
}
.redBig {
font-size: 32rpx;
color: #C4121B;
font-weight: bold;
}
/* 底部按钮 */
.bottomBtn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 20rpx;
background: #fff;
border-top: 1rpx solid #eee;
}
.payBtn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background-color: #C4121B;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
text-align: center;
border: none;
}
.payBtn[disabled] {
background-color: #ccc;
color: #999;
}
/* 通用红色文字 */
.red {
color: #C4121B;
}
</style>
\ No newline at end of file
/* 整体容器 */
.container {
min-height: 100vh;
background-color: #f7f7f7;
}
/* 内容区域 */
.content {
padding: 20rpx 20rpx 120rpx;
}
/* 卡片 */
.card {
background: #fff;
border-radius: 8rpx;
padding: 25rpx 20rpx;
margin-bottom: 20rpx;
}
/* 缴费年限行 */
.yearRow {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20rpx;
}
.yearRow .label {
font-size: 28rpx;
color: #333;
}
.yearRow .control {
display: flex;
align-items: center;
}
.control image {
width: 50rpx;
height: 50rpx;
}
/* 加减按钮样式 */
.num-btn {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
border: 1rpx solid #C4121B;
}
.num-btn.disabled {
border-color: #ccc;
}
.num-btn.disabled .btn-icon {
color: #ccc;
}
.btn-icon {
font-size: 24rpx;
color: #C4121B;
font-weight: bold;
}
.yearRow .num {
font-size: 28rpx;
color: #333;
min-width: 80rpx;
text-align: center;
margin: 0 10rpx;
}
/* 通用行 */
.row {
display: flex;
justify-content: space-between;
align-items: center;
}
.row .label {
font-size: 28rpx;
color: #333;
}
.row .value {
font-size: 30rpx;
color: #C4121B;
font-weight: 500;
}
/* 优惠提示 */
.hintRow {
display: flex;
align-items: flex-start;
font-size: 24rpx;
line-height: 1.4;
}
.hint-icon {
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #C4121B;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10rpx;
flex-shrink: 0;
margin-top: 2rpx;
}
.icon {
width: 30px;
}
.icon-check {
color: #fff;
font-size: 16rpx;
}
.hintRow .hintText {
color: #FF8124;
flex: 1;
margin-top: 10rpx;
}
/* 减免费用 */
.deductRow {
background: #fff;
padding: 20rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
border-radius: 8rpx;
}
.deductRow .label {
font-size: 28rpx;
color: #333;
}
.deductRow .value {
font-size: 30rpx;
color: #C4121B;
}
/* 支付方式行 */
.payRow {
background: #fff;
border-radius: 8rpx;
padding: 20rpx 20rpx;
margin-bottom: 20rpx;
}
.radioItem {
display: flex;
align-items: center;
}
/* 自定义红色单选框 */
::v-deep .custom-radio .wx-radio-input {
width: 30rpx;
height: 30rpx;
border-radius: 50%;
border: 2rpx solid #ccc;
}
::v-deep .custom-radio .wx-radio-input.wx-radio-input-checked {
border-color: #C4121B !important;
background: #C4121B !important;
}
.payInfo {
display: flex;
align-items: center;
margin-left: 15rpx;
}
.payInfo .icon {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.payInfo text {
font-size: 28rpx;
color: #333;
}
/* 总费用行(突出显示) */
.totalRow {
background: #fff;
border-radius: 8rpx;
padding: 20rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10rpx;
}
.totalRow .label {
font-size: 28rpx;
color: #333;
}
.redBig {
font-size: 32rpx;
color: #C4121B;
font-weight: bold;
}
/* 底部按钮 */
.bottomBtn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 20rpx;
background: #fff;
border-top: 1rpx solid #eee;
}
.payBtn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background-color: #C4121B;
color: #fff;
border-radius: 8rpx;
font-size: 32rpx;
text-align: center;
border: none;
}
.payBtn[disabled] {
background-color: #ccc;
color: #999;
}
/* 通用红色文字 */
.red {
color: #C4121B;
}
</style>
......
......@@ -109,7 +109,7 @@
const res = await api.goPay(rangeId.value)
if (res.data?.orderId) {
api.pcallBack2(res.data.orderId)
await api.pcallBack2(res.data.orderId)
uni.redirectTo({
url: `/myCenter/sucPay?rangeId=${rangeId.value}from=payOrder`
})
......@@ -251,4 +251,4 @@
color: #fff;
}
}
</style>
\ No newline at end of file
</style>
......
......@@ -350,6 +350,7 @@
};
}
})
onLoad(option => {
let userName = uni.getStorageSync('userName')
if (!userName) {
......@@ -463,8 +464,7 @@
// deptInfo.value = app.globalData.dept || {}
// app.globalData.deptInfo = res.dept || {}
console.log(43,res)
if (userType.value != '1' && app.globalData.authenticationStatus != '2' && app.globalData
.authenticationStatus != '4') {
if (userType.value != '1' && app.globalData.authenticationStatus != '2' && app.globalData.authenticationStatus != '4') {
// 注册引导
uni.navigateTo({
url: '/pages/index/perfect'
......@@ -544,7 +544,7 @@
});
}
</script>
<style scope lang="scss">
<style scoped lang="scss">
:deep(.uni-section) {
background-color: transparent !important;
}
......@@ -662,4 +662,5 @@
padding: 0 20rpx 0;
}
}
</style>
\ No newline at end of file
</style>
......
......@@ -84,7 +84,7 @@
<button
class="action-btn submit-btn"
@click.stop="commitFN(item)"
:disabled="item.auditStatus != 0">
:disabled="item.auditStatus != 0&&item.auditStatus != 9">
提交审核
</button>
</view>
......@@ -630,4 +630,4 @@ onUnmounted(() => {
border-radius:46rpx;
font-weight:600;
}
</style>
\ No newline at end of file
</style>
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!