checkpoint: 冻结资金开工前龙先生小程序本地备份(不推远程)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-26 18:39:32 +08:00
parent 09df206fd8
commit 16eecd1278
53 changed files with 2057 additions and 1116 deletions

View File

@@ -1,440 +1,440 @@
// pages/withdraw/components/mode1/mode1.js — 收款码手动审核纯提现
import request from '../../../../utils/request.js';
import upload from '../../../../utils/upload.js';
import PopupService from '../../../../services/popupService.js';
const app = getApp();
const ASSET_TYPES = {
dashou_yue: { leixing: 1, label: '接单员佣金' },
dashou_yajin: { leixing: 5, label: '接单员保证金' },
shangjia_yue: { leixing: 6, label: '商家余额' },
guanshi_fenyong: { leixing: 2, label: '管事分红' },
zuzhang_fenyong: { leixing: 3, label: '组长分红' },
kaoheguan_fenyong: { leixing: 4, label: '考核官分佣' },
};
const FROM_ASSET_MAP = {
dashou: 'dashou_yue',
guanshi: 'guanshi_fenyong',
zuzhang: 'zuzhang_fenyong',
kaoheguan: 'kaoheguan_fenyong',
kaohe: 'kaoheguan_fenyong',
shangjia: 'shangjia_yue',
yajin: 'dashou_yajin',
};
Component({
properties: { options: { type: Object, value: {} } },
data: {
imgUrls: { iconWechat: '', iconAlipay: '' },
assetList: [],
displayAssetList: [],
totalAmount: '0.00',
canWithdraw: false,
isLoadingAssets: false,
selectedAsset: null,
tixianAmount: '',
feeRateText: '--',
currentRate: '0%',
shouxufei: '0.00',
shijidaozhang: '0.00',
showTixianModal: false,
submitting: false,
txfangshi: null,
txdianhua: '',
txzh: '',
txtupian: '',
showSkfsModal: false,
tempTxfangshi: null,
tempTxPhone: '',
tempTxAccount: '',
tempTxImage: '',
choosingImage: false,
},
attached() {
this.initImageUrls();
this.loadAllAssets();
this.loadWithdrawMethod();
},
pageLifetimes: {
show() {
this.registerNotification();
this.loadAllAssets();
PopupService.checkAndShow(this, 'tixian');
},
hide() {
const popup = this.selectComponent('#popupNotice');
popup?.cleanup?.();
},
},
methods: {
formatRatePercent(rate) {
const r = parseFloat(rate) || 0;
if (r <= 1 && r > 0) return `${(r * 100).toFixed(0)}%`;
return `${r}%`;
},
registerNotification() {
const comp = this.selectComponent('#global-notification');
if (comp?.showNotification) {
app.globalData.globalNotification = {
show: (data) => comp.showNotification(data),
hide: () => comp.hideNotification(),
};
}
},
initImageUrls() {
const ossBase = app.globalData.ossImageUrl || '';
const imgDir = `${ossBase}beijing/tixian/`;
this.setData({
imgUrls: {
iconWechat: `${imgDir}icon_wechat.png`,
iconAlipay: `${imgDir}icon_alipay.png`,
},
});
},
/** 顶部展示:不含保证金的可提现合计 */
calcDisplayTotal(assets) {
let total = 0;
(assets || []).forEach((item) => {
if (item.type === 'dashou_yajin') return;
total += parseFloat(item.amount) || 0;
});
return total;
},
hasAnyWithdrawable(assets) {
return (assets || []).some((item) => parseFloat(item.amount) > 0);
},
applyRouteOptions(assets) {
const opts = this.properties.options || {};
const fromKey = FROM_ASSET_MAP[opts.from];
let selected = null;
if (fromKey) {
selected = assets.find((a) => a.type === fromKey) || null;
} else if (assets.length === 1) {
selected = assets[0];
}
const patch = {};
if (selected) {
patch.selectedAsset = selected;
patch.feeRateText = selected.rateText;
}
if (opts.amount && parseFloat(opts.amount) > 0) {
const amt = parseFloat(opts.amount);
const max = selected ? parseFloat(selected.amount) : amt;
patch.tixianAmount = Math.min(amt, max).toFixed(2);
}
if (Object.keys(patch).length) {
this.setData(patch, () => {
this.recalcFee(this.data.tixianAmount, this.data.selectedAsset);
});
}
},
onSelectAsset(e) {
const index = e.currentTarget.dataset.index;
const asset = this.data.displayAssetList[index];
if (!asset || parseFloat(asset.amount) <= 0) {
wx.showToast({ title: '该账户无可提余额', icon: 'none' });
return;
}
let amount = this.data.tixianAmount;
const max = parseFloat(asset.amount);
if (amount && parseFloat(amount) > max) {
amount = asset.amount;
}
this.setData({ selectedAsset: asset, tixianAmount: amount });
this.recalcFee(amount, asset);
},
async loadAllAssets() {
this.setData({ isLoadingAssets: true, totalAmount: '0.00', canWithdraw: false, assetList: [] });
try {
const res = await request({ url: '/yonghu/tixianzichan', method: 'POST' });
if (res?.data?.code === 200 || res?.data?.code === 0) {
const data = res.data.data || {};
const assets = [];
const push = (type, amount, rate) => {
const cfg = ASSET_TYPES[type];
if (!cfg || !amount || parseFloat(amount) <= 0) return;
assets.push({
type,
leixing: cfg.leixing,
label: cfg.label,
amount: parseFloat(amount).toFixed(2),
rate: rate || 0,
rateText: this.formatRatePercent(rate || 0),
});
};
push('dashou_yue', data.dashou_yue, data.dashou_rate);
push('dashou_yajin', data.dashou_yajin, data.dashou_yajin_rate);
push('shangjia_yue', data.shangjia_yue, data.shangjia_rate);
push('guanshi_fenyong', data.guanshi_fenyong, data.guanshi_rate);
push('zuzhang_fenyong', data.zuzhang_fenyong, data.zuzhang_rate);
push('kaoheguan_fenyong', data.kaoheguan_fenyong, data.kaoheguan_rate);
const displayTotal = this.calcDisplayTotal(assets);
const firstRate = assets.find((a) => a.type !== 'dashou_yajin')?.rate || 0;
this.setData({
assetList: assets,
displayAssetList: assets,
totalAmount: displayTotal.toFixed(2),
canWithdraw: this.hasAnyWithdrawable(assets),
isLoadingAssets: false,
feeRateText: displayTotal > 0 ? this.formatRatePercent(firstRate) : '--',
}, () => this.applyRouteOptions(assets));
if (!this.data.selectedAsset) {
this.recalcFee(this.data.tixianAmount, null);
}
} else {
throw new Error(res?.data?.msg || '获取资产失败');
}
} catch (err) {
console.error('loadAllAssets', err);
this.setData({ isLoadingAssets: false, totalAmount: '0.00', canWithdraw: false, assetList: [] });
}
},
async loadWithdrawMethod() {
const txzh = wx.getStorageSync('txzh') || '';
const txtupian = wx.getStorageSync('txtupian') || '';
const txfangshi = wx.getStorageSync('txfangshi') || null;
const txdianhua = wx.getStorageSync('txdianhua') || '';
if (txzh || txtupian || txfangshi) {
this.setData({ txzh, txtupian, txfangshi, txdianhua });
return;
}
try {
const res = await request({ url: '/yonghu/tixianhq', method: 'POST' });
if (res?.data?.code === 0) {
const data = res.data.data;
this.setData({
txzh: data.txzh || '',
txtupian: data.txtupian || '',
txfangshi: data.txfangshi || null,
txdianhua: data.txdianhua || '',
});
wx.setStorageSync('txzh', data.txzh || '');
wx.setStorageSync('txtupian', data.txtupian || '');
wx.setStorageSync('txfangshi', data.txfangshi || null);
wx.setStorageSync('txdianhua', data.txdianhua || '');
}
} catch (err) { /* ignore */ }
},
recalcFee(amountStr, asset) {
const amount = parseFloat(amountStr);
if (!amountStr || isNaN(amount) || amount <= 0 || !asset) {
this.setData({
shouxufei: '0.00',
shijidaozhang: '0.00',
feeRateText: asset ? asset.rateText : this.data.feeRateText,
});
return;
}
const rate = parseFloat(asset.rate) || 0;
const fee = amount * rate;
this.setData({
shouxufei: fee.toFixed(2),
shijidaozhang: (amount - fee).toFixed(2),
feeRateText: asset.rateText,
currentRate: asset.rateText,
});
},
onAmountInput(e) {
let val = e.detail.value;
if (val && !/^\d*\.?\d{0,2}$/.test(val)) return;
this.setData({ tixianAmount: val });
this.recalcFee(val, this.data.selectedAsset);
},
onWithdrawAll() {
const { selectedAsset } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请先选择提现账户', icon: 'none' });
return;
}
const max = selectedAsset.amount;
this.setData({ tixianAmount: max });
this.recalcFee(max, selectedAsset);
},
onTapWithdraw() {
if (this.data.submitting) return;
if (!this.hasAnyWithdrawable(this.data.assetList)) {
wx.showToast({ title: '暂无可提现余额', icon: 'none' });
return;
}
const { selectedAsset, tixianAmount } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请先选择要提现的账户', icon: 'none' });
return;
}
const amount = parseFloat(tixianAmount);
if (isNaN(amount) || amount <= 0) {
wx.showToast({ title: '请输入有效金额', icon: 'none' });
return;
}
if (amount > parseFloat(selectedAsset.amount)) {
wx.showToast({ title: `超过${selectedAsset.label}可提余额`, icon: 'none' });
return;
}
const { txfangshi, txzh, txtupian } = this.data;
if (!txfangshi || (!txzh && !txtupian)) {
wx.showToast({ title: '请先设置收款方式', icon: 'none' });
this.onSetSkfs();
return;
}
this.applyIdentityAndConfirm(selectedAsset);
},
applyIdentityAndConfirm(asset) {
this.recalcFee(this.data.tixianAmount, asset);
this.setData({ selectedAsset: asset, showTixianModal: true });
},
async onConfirmWithdraw() {
const { selectedAsset, tixianAmount, txfangshi, txzh, txtupian } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请选择提现身份', icon: 'none' });
return;
}
const amount = parseFloat(tixianAmount);
if (isNaN(amount) || amount <= 0) {
wx.showToast({ title: '请输入有效金额', icon: 'none' });
return;
}
if (amount > parseFloat(selectedAsset.amount)) {
wx.showToast({ title: '超过可提余额', icon: 'none' });
return;
}
const leixing = selectedAsset.leixing;
let txskfs = 0;
if (txzh && txtupian) txskfs = 3;
else if (txzh) txskfs = 1;
else if (txtupian) txskfs = 2;
this.setData({ submitting: true });
try {
const res = await request({
url: '/yonghu/tixian',
method: 'POST',
data: { leixing, jine: amount.toFixed(2), fangshi: txfangshi, txskfs },
});
if (res?.data?.code === 0) {
this.setData({
showTixianModal: false,
selectedAsset: null,
tixianAmount: '',
submitting: false,
});
await this.loadAllAssets();
wx.showModal({
title: '申请成功',
content: '提现申请已提交,请前往「提现记录」查看审核进度。',
confirmText: '查看提现记录',
cancelText: '知道了',
success: (res) => {
if (res.confirm) {
wx.navigateTo({ url: '/pages/withdraw/withdraw-records' });
}
},
});
} else {
wx.showToast({ title: res?.data?.msg || '提现失败', icon: 'none' });
this.setData({ submitting: false });
}
} catch (err) {
wx.showToast({ title: '网络错误', icon: 'none' });
this.setData({ submitting: false });
}
},
onCloseTixianModal() {
if (this.data.submitting) return;
this.setData({ showTixianModal: false, selectedAsset: null });
},
onSetSkfs() {
this.setData({
showSkfsModal: true,
tempTxfangshi: this.data.txfangshi,
tempTxPhone: this.data.txdianhua,
tempTxAccount: this.data.txzh,
tempTxImage: '',
});
},
onSelectFangshi(e) { this.setData({ tempTxfangshi: e.currentTarget.dataset.fangshi }); },
onPhoneInput(e) { this.setData({ tempTxPhone: e.detail.value }); },
onAccountInput(e) { this.setData({ tempTxAccount: e.detail.value }); },
onChooseImage() {
if (this.data.choosingImage) return;
this.setData({ choosingImage: true });
wx.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => { this.setData({ tempTxImage: res.tempFiles[0].tempFilePath }); },
complete: () => { this.setData({ choosingImage: false }); },
});
},
onPreviewImage() {
if (this.data.tempTxImage) wx.previewImage({ urls: [this.data.tempTxImage] });
},
onDeleteImage() { this.setData({ tempTxImage: '' }); },
async onConfirmSkfs() {
const { tempTxfangshi, tempTxPhone, tempTxAccount, tempTxImage } = this.data;
if (!tempTxfangshi) { wx.showToast({ title: '请选择提现方式', icon: 'none' }); return; }
if (!tempTxPhone) { wx.showToast({ title: '请输入收款人电话', icon: 'none' }); return; }
if (tempTxfangshi == 1 && !tempTxImage && !this.data.txtupian) {
wx.showToast({ title: '请上传微信收款码', icon: 'none' }); return;
}
if (tempTxfangshi == 2 && !tempTxAccount && !tempTxImage && !this.data.txzh) {
wx.showToast({ title: '请填写支付宝账号或上传收款码', icon: 'none' }); return;
}
try {
const res = await upload({
url: '/yonghu/sksc',
formData: { txdianhua: tempTxPhone, txzh: tempTxAccount || '' },
filePath: tempTxImage || null,
fileName: 'file',
});
if (res?.data?.code === 0) {
const data = res.data.data;
this.setData({
txfangshi: tempTxfangshi,
txdianhua: tempTxPhone,
txzh: data.txzh || '',
txtupian: data.txtupian || this.data.txtupian,
showSkfsModal: false,
});
wx.setStorageSync('txfangshi', tempTxfangshi);
wx.setStorageSync('txdianhua', tempTxPhone);
wx.setStorageSync('txzh', data.txzh || '');
wx.setStorageSync('txtupian', data.txtupian || this.data.txtupian);
wx.showToast({ title: '设置成功', icon: 'success' });
} else {
wx.showToast({ title: res?.data?.msg || '保存失败', icon: 'none' });
}
} catch (err) {
wx.showToast({ title: '网络错误', icon: 'none' });
}
},
onCloseSkfsModal() { this.setData({ showSkfsModal: false }); },
stopPropagation() {},
},
});
// pages/withdraw/components/mode1/mode1.js — 收款码手动审核纯提现
import request from '../../../../utils/request.js';
import upload from '../../../../utils/upload.js';
import PopupService from '../../../../services/popupService.js';
const app = getApp();
const ASSET_TYPES = {
dashou_yue: { leixing: 1, label: '接单员佣金' },
dashou_yajin: { leixing: 5, label: '接单员保证金' },
shangjia_yue: { leixing: 6, label: '商家余额' },
guanshi_fenyong: { leixing: 2, label: '管事分红' },
zuzhang_fenyong: { leixing: 3, label: '组长分红' },
kaoheguan_fenyong: { leixing: 4, label: '考核官分佣' },
};
const FROM_ASSET_MAP = {
dashou: 'dashou_yue',
guanshi: 'guanshi_fenyong',
zuzhang: 'zuzhang_fenyong',
kaoheguan: 'kaoheguan_fenyong',
kaohe: 'kaoheguan_fenyong',
shangjia: 'shangjia_yue',
yajin: 'dashou_yajin',
};
Component({
properties: { options: { type: Object, value: {} } },
data: {
imgUrls: { iconWechat: '', iconAlipay: '' },
assetList: [],
displayAssetList: [],
totalAmount: '0.00',
canWithdraw: false,
isLoadingAssets: false,
selectedAsset: null,
tixianAmount: '',
feeRateText: '--',
currentRate: '0%',
shouxufei: '0.00',
shijidaozhang: '0.00',
showTixianModal: false,
submitting: false,
txfangshi: null,
txdianhua: '',
txzh: '',
txtupian: '',
showSkfsModal: false,
tempTxfangshi: null,
tempTxPhone: '',
tempTxAccount: '',
tempTxImage: '',
choosingImage: false,
},
attached() {
this.initImageUrls();
this.loadAllAssets();
this.loadWithdrawMethod();
},
pageLifetimes: {
show() {
this.registerNotification();
this.loadAllAssets();
PopupService.checkAndShow(this, 'tixian');
},
hide() {
const popup = this.selectComponent('#popupNotice');
popup?.cleanup?.();
},
},
methods: {
formatRatePercent(rate) {
const r = parseFloat(rate) || 0;
if (r <= 1 && r > 0) return `${(r * 100).toFixed(0)}%`;
return `${r}%`;
},
registerNotification() {
const comp = this.selectComponent('#global-notification');
if (comp?.showNotification) {
app.globalData.globalNotification = {
show: (data) => comp.showNotification(data),
hide: () => comp.hideNotification(),
};
}
},
initImageUrls() {
const ossBase = app.globalData.ossImageUrl || '';
const imgDir = `${ossBase}beijing/tixian/`;
this.setData({
imgUrls: {
iconWechat: `${imgDir}icon_wechat.png`,
iconAlipay: `${imgDir}icon_alipay.png`,
},
});
},
/** 顶部展示:不含保证金的可提现合计 */
calcDisplayTotal(assets) {
let total = 0;
(assets || []).forEach((item) => {
if (item.type === 'dashou_yajin') return;
total += parseFloat(item.amount) || 0;
});
return total;
},
hasAnyWithdrawable(assets) {
return (assets || []).some((item) => parseFloat(item.amount) > 0);
},
applyRouteOptions(assets) {
const opts = this.properties.options || {};
const fromKey = FROM_ASSET_MAP[opts.from];
let selected = null;
if (fromKey) {
selected = assets.find((a) => a.type === fromKey) || null;
} else if (assets.length === 1) {
selected = assets[0];
}
const patch = {};
if (selected) {
patch.selectedAsset = selected;
patch.feeRateText = selected.rateText;
}
if (opts.amount && parseFloat(opts.amount) > 0) {
const amt = parseFloat(opts.amount);
const max = selected ? parseFloat(selected.amount) : amt;
patch.tixianAmount = Math.min(amt, max).toFixed(2);
}
if (Object.keys(patch).length) {
this.setData(patch, () => {
this.recalcFee(this.data.tixianAmount, this.data.selectedAsset);
});
}
},
onSelectAsset(e) {
const index = e.currentTarget.dataset.index;
const asset = this.data.displayAssetList[index];
if (!asset || parseFloat(asset.amount) <= 0) {
wx.showToast({ title: '该账户无可提余额', icon: 'none' });
return;
}
let amount = this.data.tixianAmount;
const max = parseFloat(asset.amount);
if (amount && parseFloat(amount) > max) {
amount = asset.amount;
}
this.setData({ selectedAsset: asset, tixianAmount: amount });
this.recalcFee(amount, asset);
},
async loadAllAssets() {
this.setData({ isLoadingAssets: true, totalAmount: '0.00', canWithdraw: false, assetList: [] });
try {
const res = await request({ url: '/yonghu/tixianzichan', method: 'POST' });
if (res?.data?.code === 200 || res?.data?.code === 0) {
const data = res.data.data || {};
const assets = [];
const push = (type, amount, rate) => {
const cfg = ASSET_TYPES[type];
if (!cfg || !amount || parseFloat(amount) <= 0) return;
assets.push({
type,
leixing: cfg.leixing,
label: cfg.label,
amount: parseFloat(amount).toFixed(2),
rate: rate || 0,
rateText: this.formatRatePercent(rate || 0),
});
};
push('dashou_yue', data.dashou_yue, data.dashou_rate);
push('dashou_yajin', data.dashou_yajin, data.dashou_yajin_rate);
push('shangjia_yue', data.shangjia_yue, data.shangjia_rate);
push('guanshi_fenyong', data.guanshi_fenyong, data.guanshi_rate);
push('zuzhang_fenyong', data.zuzhang_fenyong, data.zuzhang_rate);
push('kaoheguan_fenyong', data.kaoheguan_fenyong, data.kaoheguan_rate);
const displayTotal = this.calcDisplayTotal(assets);
const firstRate = assets.find((a) => a.type !== 'dashou_yajin')?.rate || 0;
this.setData({
assetList: assets,
displayAssetList: assets,
totalAmount: displayTotal.toFixed(2),
canWithdraw: this.hasAnyWithdrawable(assets),
isLoadingAssets: false,
feeRateText: displayTotal > 0 ? this.formatRatePercent(firstRate) : '--',
}, () => this.applyRouteOptions(assets));
if (!this.data.selectedAsset) {
this.recalcFee(this.data.tixianAmount, null);
}
} else {
throw new Error(res?.data?.msg || '获取资产失败');
}
} catch (err) {
console.error('loadAllAssets', err);
this.setData({ isLoadingAssets: false, totalAmount: '0.00', canWithdraw: false, assetList: [] });
}
},
async loadWithdrawMethod() {
const txzh = wx.getStorageSync('txzh') || '';
const txtupian = wx.getStorageSync('txtupian') || '';
const txfangshi = wx.getStorageSync('txfangshi') || null;
const txdianhua = wx.getStorageSync('txdianhua') || '';
if (txzh || txtupian || txfangshi) {
this.setData({ txzh, txtupian, txfangshi, txdianhua });
return;
}
try {
const res = await request({ url: '/yonghu/tixianhq', method: 'POST' });
if (res?.data?.code === 0) {
const data = res.data.data;
this.setData({
txzh: data.txzh || '',
txtupian: data.txtupian || '',
txfangshi: data.txfangshi || null,
txdianhua: data.txdianhua || '',
});
wx.setStorageSync('txzh', data.txzh || '');
wx.setStorageSync('txtupian', data.txtupian || '');
wx.setStorageSync('txfangshi', data.txfangshi || null);
wx.setStorageSync('txdianhua', data.txdianhua || '');
}
} catch (err) { /* ignore */ }
},
recalcFee(amountStr, asset) {
const amount = parseFloat(amountStr);
if (!amountStr || isNaN(amount) || amount <= 0 || !asset) {
this.setData({
shouxufei: '0.00',
shijidaozhang: '0.00',
feeRateText: asset ? asset.rateText : this.data.feeRateText,
});
return;
}
const rate = parseFloat(asset.rate) || 0;
const fee = amount * rate;
this.setData({
shouxufei: fee.toFixed(2),
shijidaozhang: (amount - fee).toFixed(2),
feeRateText: asset.rateText,
currentRate: asset.rateText,
});
},
onAmountInput(e) {
let val = e.detail.value;
if (val && !/^\d*\.?\d{0,2}$/.test(val)) return;
this.setData({ tixianAmount: val });
this.recalcFee(val, this.data.selectedAsset);
},
onWithdrawAll() {
const { selectedAsset } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请先选择提现账户', icon: 'none' });
return;
}
const max = selectedAsset.amount;
this.setData({ tixianAmount: max });
this.recalcFee(max, selectedAsset);
},
onTapWithdraw() {
if (this.data.submitting) return;
if (!this.hasAnyWithdrawable(this.data.assetList)) {
wx.showToast({ title: '暂无可提现余额', icon: 'none' });
return;
}
const { selectedAsset, tixianAmount } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请先选择要提现的账户', icon: 'none' });
return;
}
const amount = parseFloat(tixianAmount);
if (isNaN(amount) || amount <= 0) {
wx.showToast({ title: '请输入有效金额', icon: 'none' });
return;
}
if (amount > parseFloat(selectedAsset.amount)) {
wx.showToast({ title: `超过${selectedAsset.label}可提余额`, icon: 'none' });
return;
}
const { txfangshi, txzh, txtupian } = this.data;
if (!txfangshi || (!txzh && !txtupian)) {
wx.showToast({ title: '请先设置收款方式', icon: 'none' });
this.onSetSkfs();
return;
}
this.applyIdentityAndConfirm(selectedAsset);
},
applyIdentityAndConfirm(asset) {
this.recalcFee(this.data.tixianAmount, asset);
this.setData({ selectedAsset: asset, showTixianModal: true });
},
async onConfirmWithdraw() {
const { selectedAsset, tixianAmount, txfangshi, txzh, txtupian } = this.data;
if (!selectedAsset) {
wx.showToast({ title: '请选择提现身份', icon: 'none' });
return;
}
const amount = parseFloat(tixianAmount);
if (isNaN(amount) || amount <= 0) {
wx.showToast({ title: '请输入有效金额', icon: 'none' });
return;
}
if (amount > parseFloat(selectedAsset.amount)) {
wx.showToast({ title: '超过可提余额', icon: 'none' });
return;
}
const leixing = selectedAsset.leixing;
let txskfs = 0;
if (txzh && txtupian) txskfs = 3;
else if (txzh) txskfs = 1;
else if (txtupian) txskfs = 2;
this.setData({ submitting: true });
try {
const res = await request({
url: '/yonghu/tixian',
method: 'POST',
data: { leixing, jine: amount.toFixed(2), fangshi: txfangshi, txskfs },
});
if (res?.data?.code === 0) {
this.setData({
showTixianModal: false,
selectedAsset: null,
tixianAmount: '',
submitting: false,
});
await this.loadAllAssets();
wx.showModal({
title: '申请成功',
content: '提现申请已提交,请前往「提现记录」查看审核进度。',
confirmText: '查看提现记录',
cancelText: '知道了',
success: (res) => {
if (res.confirm) {
wx.navigateTo({ url: '/pages/withdraw/withdraw-records' });
}
},
});
} else {
wx.showToast({ title: res?.data?.msg || '提现失败', icon: 'none' });
this.setData({ submitting: false });
}
} catch (err) {
wx.showToast({ title: '网络错误', icon: 'none' });
this.setData({ submitting: false });
}
},
onCloseTixianModal() {
if (this.data.submitting) return;
this.setData({ showTixianModal: false, selectedAsset: null });
},
onSetSkfs() {
this.setData({
showSkfsModal: true,
tempTxfangshi: this.data.txfangshi,
tempTxPhone: this.data.txdianhua,
tempTxAccount: this.data.txzh,
tempTxImage: '',
});
},
onSelectFangshi(e) { this.setData({ tempTxfangshi: e.currentTarget.dataset.fangshi }); },
onPhoneInput(e) { this.setData({ tempTxPhone: e.detail.value }); },
onAccountInput(e) { this.setData({ tempTxAccount: e.detail.value }); },
onChooseImage() {
if (this.data.choosingImage) return;
this.setData({ choosingImage: true });
wx.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => { this.setData({ tempTxImage: res.tempFiles[0].tempFilePath }); },
complete: () => { this.setData({ choosingImage: false }); },
});
},
onPreviewImage() {
if (this.data.tempTxImage) wx.previewImage({ urls: [this.data.tempTxImage] });
},
onDeleteImage() { this.setData({ tempTxImage: '' }); },
async onConfirmSkfs() {
const { tempTxfangshi, tempTxPhone, tempTxAccount, tempTxImage } = this.data;
if (!tempTxfangshi) { wx.showToast({ title: '请选择提现方式', icon: 'none' }); return; }
if (!tempTxPhone) { wx.showToast({ title: '请输入收款人电话', icon: 'none' }); return; }
if (tempTxfangshi == 1 && !tempTxImage && !this.data.txtupian) {
wx.showToast({ title: '请上传微信收款码', icon: 'none' }); return;
}
if (tempTxfangshi == 2 && !tempTxAccount && !tempTxImage && !this.data.txzh) {
wx.showToast({ title: '请填写支付宝账号或上传收款码', icon: 'none' }); return;
}
try {
const res = await upload({
url: '/yonghu/sksc',
formData: { txdianhua: tempTxPhone, txzh: tempTxAccount || '' },
filePath: tempTxImage || null,
fileName: 'file',
});
if (res?.data?.code === 0) {
const data = res.data.data;
this.setData({
txfangshi: tempTxfangshi,
txdianhua: tempTxPhone,
txzh: data.txzh || '',
txtupian: data.txtupian || this.data.txtupian,
showSkfsModal: false,
});
wx.setStorageSync('txfangshi', tempTxfangshi);
wx.setStorageSync('txdianhua', tempTxPhone);
wx.setStorageSync('txzh', data.txzh || '');
wx.setStorageSync('txtupian', data.txtupian || this.data.txtupian);
wx.showToast({ title: '设置成功', icon: 'success' });
} else {
wx.showToast({ title: res?.data?.msg || '保存失败', icon: 'none' });
}
} catch (err) {
wx.showToast({ title: '网络错误', icon: 'none' });
}
},
onCloseSkfsModal() { this.setData({ showSkfsModal: false }); },
stopPropagation() {},
},
});

View File

@@ -1,115 +1,115 @@
<!-- mode1 收款码手动审核 - 参考逍遥梦样式 -->
<view class="ref-page">
<view class="method-card method-card--row">
<view class="method-tab method-tab--active">
<image wx:if="{{txfangshi == 1}}" class="method-tab-icon" src="{{imgUrls.iconWechat}}" mode="aspectFit" />
<image wx:elif="{{txfangshi == 2}}" class="method-tab-icon" src="{{imgUrls.iconAlipay}}" mode="aspectFit" />
<view wx:else class="method-tab-icon method-tab-icon--placeholder"></view>
<text class="method-tab-text">{{txfangshi == 1 ? '微信零钱' : (txfangshi == 2 ? '收款码' : '请先设置收款')}}</text>
<view class="method-tab-line"></view>
</view>
<text class="method-setting" bindtap="onSetSkfs">设置收款方式</text>
</view>
<view class="account-card" wx:if="{{displayAssetList.length > 0}}">
<scroll-view scroll-x enable-flex class="account-scroll" show-scrollbar="{{false}}">
<view
wx:for="{{displayAssetList}}"
wx:key="type"
class="account-chip {{selectedAsset.type === item.type ? 'account-chip--active' : ''}} {{item.amount <= 0 ? 'account-chip--disabled' : ''}}"
bindtap="onSelectAsset"
data-index="{{index}}"
>
<text class="chip-label">{{item.label}}</text>
<text class="chip-amount">¥{{item.amount}}</text>
</view>
</scroll-view>
<text wx:if="{{!selectedAsset}}" class="account-warn">请先选择上方提现账户</text>
<text wx:else class="account-ok">当前:{{selectedAsset.label}}</text>
</view>
<view class="amount-card">
<view class="avail-row">
<text class="avail-label">当前可提现:</text>
<text class="avail-symbol">¥</text>
<text class="avail-amount">{{selectedAsset ? selectedAsset.amount : totalAmount}}</text>
</view>
<view class="input-row">
<text class="input-symbol">¥</text>
<input
class="amount-input"
type="digit"
placeholder="请输入金额"
placeholder-class="amount-placeholder"
value="{{tixianAmount}}"
bindinput="onAmountInput"
/>
<text class="withdraw-all" bindtap="onWithdrawAll">全部提现</text>
</view>
<view class="input-divider"></view>
<view class="fee-tip">
<text>提示:提现手续费</text>
<text class="fee-highlight">{{feeRateText}}</text>
<text>。</text>
</view>
</view>
<view class="submit-wrap">
<view class="confirm-btn {{canWithdraw && !submitting ? '' : 'confirm-btn--disabled'}}" bindtap="onTapWithdraw">
<text wx:if="{{submitting}}">处理中...</text>
<text wx:else>确认提现</text>
</view>
</view>
<view class="notice-box">
<view class="notice-title">📢 提现须知</view>
<view class="notice-item">🕒 提交后将进入人工审核,请耐心等待</view>
<view class="notice-item">📌 审核结果可在「提现记录」中查看</view>
<view class="notice-item">💰 每笔只能从单个账户提现,请先选择对应账户</view>
<view class="notice-item">✅ 请确保收款方式与收款码正确后再提交</view>
<view class="notice-item">🎧 如有疑问请联系客服核实处理</view>
</view>
</view>
<view wx:if="{{showTixianModal}}" class="modal-mask" bindtap="onCloseTixianModal">
<view class="modal-dialog" catchtap="stopPropagation">
<view class="modal-header">确认提现</view>
<view class="modal-body">
<view class="info-row"><text>身份</text><text>{{selectedAsset.label}}</text></view>
<view class="info-row"><text>可提</text><text>¥{{selectedAsset.amount}}</text></view>
<view class="info-row"><text>费率</text><text>{{currentRate}}</text></view>
<view class="info-row"><text>提现金额</text><text>¥{{tixianAmount}}</text></view>
<view class="fee-row"><text>手续费 ¥{{shouxufei}}</text><text>到账 ¥{{shijidaozhang}}</text></view>
<view class="info-row"><text>收款</text><text>{{txfangshi == 1 ? '微信' : (txfangshi == 2 ? '支付宝' : '未设置')}}</text></view>
</view>
<view class="modal-footer">
<view class="modal-btn cancel" bindtap="onCloseTixianModal">取消</view>
<view class="modal-btn confirm" bindtap="onConfirmWithdraw">{{submitting ? '处理中' : '提交申请'}}</view>
</view>
</view>
</view>
<view wx:if="{{showSkfsModal}}" class="modal-mask" bindtap="onCloseSkfsModal">
<view class="modal-dialog" catchtap="stopPropagation">
<view class="modal-header">收款方式</view>
<view class="modal-body skfs-body">
<view class="toggle-row">
<view class="toggle-item {{tempTxfangshi == 1 ? 'active' : ''}}" bindtap="onSelectFangshi" data-fangshi="1">微信</view>
<view class="toggle-item {{tempTxfangshi == 2 ? 'active' : ''}}" bindtap="onSelectFangshi" data-fangshi="2">支付宝</view>
</view>
<input class="field-input" placeholder="手机号" value="{{tempTxPhone}}" bindinput="onPhoneInput" />
<view wx:if="{{tempTxfangshi == 2}}"><input class="field-input" placeholder="支付宝账号" value="{{tempTxAccount}}" bindinput="onAccountInput" /></view>
<view class="upload-wrap">
<view wx:if="{{!tempTxImage}}" class="upload-trigger" bindtap="onChooseImage">+ 上传收款码</view>
<view wx:else class="image-preview"><image src="{{tempTxImage}}" mode="aspectFill" /><view class="image-actions"><text bindtap="onPreviewImage">预览</text><text bindtap="onDeleteImage">删除</text></view></view>
</view>
</view>
<view class="modal-footer">
<view class="modal-btn cancel" bindtap="onCloseSkfsModal">取消</view>
<view class="modal-btn confirm" bindtap="onConfirmSkfs">保存</view>
</view>
</view>
</view>
<global-notification id="global-notification" />
<popup-notice id="popupNotice" />
<!-- mode1 收款码手动审核 - 参考逍遥梦样式 -->
<view class="ref-page">
<view class="method-card method-card--row">
<view class="method-tab method-tab--active">
<image wx:if="{{txfangshi == 1}}" class="method-tab-icon" src="{{imgUrls.iconWechat}}" mode="aspectFit" />
<image wx:elif="{{txfangshi == 2}}" class="method-tab-icon" src="{{imgUrls.iconAlipay}}" mode="aspectFit" />
<view wx:else class="method-tab-icon method-tab-icon--placeholder"></view>
<text class="method-tab-text">{{txfangshi == 1 ? '微信零钱' : (txfangshi == 2 ? '收款码' : '请先设置收款')}}</text>
<view class="method-tab-line"></view>
</view>
<text class="method-setting" bindtap="onSetSkfs">设置收款方式</text>
</view>
<view class="account-card" wx:if="{{displayAssetList.length > 0}}">
<scroll-view scroll-x enable-flex class="account-scroll" show-scrollbar="{{false}}">
<view
wx:for="{{displayAssetList}}"
wx:key="type"
class="account-chip {{selectedAsset.type === item.type ? 'account-chip--active' : ''}} {{item.amount <= 0 ? 'account-chip--disabled' : ''}}"
bindtap="onSelectAsset"
data-index="{{index}}"
>
<text class="chip-label">{{item.label}}</text>
<text class="chip-amount">¥{{item.amount}}</text>
</view>
</scroll-view>
<text wx:if="{{!selectedAsset}}" class="account-warn">请先选择上方提现账户</text>
<text wx:else class="account-ok">当前:{{selectedAsset.label}}</text>
</view>
<view class="amount-card">
<view class="avail-row">
<text class="avail-label">当前可提现:</text>
<text class="avail-symbol">¥</text>
<text class="avail-amount">{{selectedAsset ? selectedAsset.amount : totalAmount}}</text>
</view>
<view class="input-row">
<text class="input-symbol">¥</text>
<input
class="amount-input"
type="digit"
placeholder="请输入金额"
placeholder-class="amount-placeholder"
value="{{tixianAmount}}"
bindinput="onAmountInput"
/>
<text class="withdraw-all" bindtap="onWithdrawAll">全部提现</text>
</view>
<view class="input-divider"></view>
<view class="fee-tip">
<text>提示:提现手续费</text>
<text class="fee-highlight">{{feeRateText}}</text>
<text>。</text>
</view>
</view>
<view class="submit-wrap">
<view class="confirm-btn {{canWithdraw && !submitting ? '' : 'confirm-btn--disabled'}}" bindtap="onTapWithdraw">
<text wx:if="{{submitting}}">处理中...</text>
<text wx:else>确认提现</text>
</view>
</view>
<view class="notice-box">
<view class="notice-title">📢 提现须知</view>
<view class="notice-item">🕒 提交后将进入人工审核,请耐心等待</view>
<view class="notice-item">📌 审核结果可在「提现记录」中查看</view>
<view class="notice-item">💰 每笔只能从单个账户提现,请先选择对应账户</view>
<view class="notice-item">✅ 请确保收款方式与收款码正确后再提交</view>
<view class="notice-item">🎧 如有疑问请联系客服核实处理</view>
</view>
</view>
<view wx:if="{{showTixianModal}}" class="modal-mask" bindtap="onCloseTixianModal">
<view class="modal-dialog" catchtap="stopPropagation">
<view class="modal-header">确认提现</view>
<view class="modal-body">
<view class="info-row"><text>身份</text><text>{{selectedAsset.label}}</text></view>
<view class="info-row"><text>可提</text><text>¥{{selectedAsset.amount}}</text></view>
<view class="info-row"><text>费率</text><text>{{currentRate}}</text></view>
<view class="info-row"><text>提现金额</text><text>¥{{tixianAmount}}</text></view>
<view class="fee-row"><text>手续费 ¥{{shouxufei}}</text><text>到账 ¥{{shijidaozhang}}</text></view>
<view class="info-row"><text>收款</text><text>{{txfangshi == 1 ? '微信' : (txfangshi == 2 ? '支付宝' : '未设置')}}</text></view>
</view>
<view class="modal-footer">
<view class="modal-btn cancel" bindtap="onCloseTixianModal">取消</view>
<view class="modal-btn confirm" bindtap="onConfirmWithdraw">{{submitting ? '处理中' : '提交申请'}}</view>
</view>
</view>
</view>
<view wx:if="{{showSkfsModal}}" class="modal-mask" bindtap="onCloseSkfsModal">
<view class="modal-dialog" catchtap="stopPropagation">
<view class="modal-header">收款方式</view>
<view class="modal-body skfs-body">
<view class="toggle-row">
<view class="toggle-item {{tempTxfangshi == 1 ? 'active' : ''}}" bindtap="onSelectFangshi" data-fangshi="1">微信</view>
<view class="toggle-item {{tempTxfangshi == 2 ? 'active' : ''}}" bindtap="onSelectFangshi" data-fangshi="2">支付宝</view>
</view>
<input class="field-input" placeholder="手机号" value="{{tempTxPhone}}" bindinput="onPhoneInput" />
<view wx:if="{{tempTxfangshi == 2}}"><input class="field-input" placeholder="支付宝账号" value="{{tempTxAccount}}" bindinput="onAccountInput" /></view>
<view class="upload-wrap">
<view wx:if="{{!tempTxImage}}" class="upload-trigger" bindtap="onChooseImage">+ 上传收款码</view>
<view wx:else class="image-preview"><image src="{{tempTxImage}}" mode="aspectFill" /><view class="image-actions"><text bindtap="onPreviewImage">预览</text><text bindtap="onDeleteImage">删除</text></view></view>
</view>
</view>
<view class="modal-footer">
<view class="modal-btn cancel" bindtap="onCloseSkfsModal">取消</view>
<view class="modal-btn confirm" bindtap="onConfirmSkfs">保存</view>
</view>
</view>
</view>
<global-notification id="global-notification" />
<popup-notice id="popupNotice" />

View File

@@ -1,85 +1,85 @@
@import '../mode2/mode2.wxss';
.method-card--row {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 24rpx;
}
.method-setting {
font-size: 26rpx;
color: #ff8c00;
flex-shrink: 0;
padding: 16rpx 8rpx;
}
.method-tab-icon--placeholder {
background: #e0e0e0;
border-radius: 8rpx;
}
.skfs-body .toggle-row {
display: flex;
gap: 16rpx;
margin-bottom: 24rpx;
}
.toggle-item {
flex: 1;
text-align: center;
padding: 20rpx;
border-radius: 12rpx;
background: #f5f5f5;
font-size: 28rpx;
color: #666;
}
.toggle-item.active {
background: #fff8e1;
color: #ff8c00;
font-weight: 600;
border: 2rpx solid #FFD54F;
}
.field-input {
width: 100%;
box-sizing: border-box;
padding: 24rpx;
margin-bottom: 16rpx;
background: #f8f8f8;
border-radius: 12rpx;
font-size: 28rpx;
}
.upload-wrap {
margin-top: 16rpx;
}
.upload-trigger {
padding: 48rpx;
text-align: center;
border: 2rpx dashed #ddd;
border-radius: 12rpx;
color: #999;
font-size: 28rpx;
}
.image-preview {
position: relative;
}
.image-preview image {
width: 100%;
height: 320rpx;
border-radius: 12rpx;
}
.image-actions {
display: flex;
justify-content: center;
gap: 32rpx;
margin-top: 16rpx;
font-size: 28rpx;
color: #ff8c00;
}
@import '../mode2/mode2.wxss';
.method-card--row {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 24rpx;
}
.method-setting {
font-size: 26rpx;
color: #ff8c00;
flex-shrink: 0;
padding: 16rpx 8rpx;
}
.method-tab-icon--placeholder {
background: #e0e0e0;
border-radius: 8rpx;
}
.skfs-body .toggle-row {
display: flex;
gap: 16rpx;
margin-bottom: 24rpx;
}
.toggle-item {
flex: 1;
text-align: center;
padding: 20rpx;
border-radius: 12rpx;
background: #f5f5f5;
font-size: 28rpx;
color: #666;
}
.toggle-item.active {
background: #fff8e1;
color: #ff8c00;
font-weight: 600;
border: 2rpx solid #FFD54F;
}
.field-input {
width: 100%;
box-sizing: border-box;
padding: 24rpx;
margin-bottom: 16rpx;
background: #f8f8f8;
border-radius: 12rpx;
font-size: 28rpx;
}
.upload-wrap {
margin-top: 16rpx;
}
.upload-trigger {
padding: 48rpx;
text-align: center;
border: 2rpx dashed #ddd;
border-radius: 12rpx;
color: #999;
font-size: 28rpx;
}
.image-preview {
position: relative;
}
.image-preview image {
width: 100%;
height: 320rpx;
border-radius: 12rpx;
}
.image-actions {
display: flex;
justify-content: center;
gap: 32rpx;
margin-top: 16rpx;
font-size: 28rpx;
color: #ff8c00;
}