restore: 恢复橙色逍遥梦UI版本(2ea2860)到主分支
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,484 +1,440 @@
|
||||
// pages/withdraw/withdraw.js
|
||||
// 子组件版本 - 完整代码,仅适配生命周期,业务逻辑不动
|
||||
|
||||
// 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 PAGE_SIZE = 10;
|
||||
let lastPullDownTime = 0;
|
||||
const PULL_DOWN_INTERVAL = 2000;
|
||||
|
||||
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({
|
||||
data: {
|
||||
imgUrls: {
|
||||
pageBg: '',
|
||||
cardBg: '',
|
||||
iconWechat: '',
|
||||
iconAlipay: '',
|
||||
iconRecord: '',
|
||||
iconRefresh: '',
|
||||
},
|
||||
assetList: [],
|
||||
totalAmount: '0.00',
|
||||
selectedAsset: null,
|
||||
txfangshi: null,
|
||||
txdianhua: '',
|
||||
txzh: '',
|
||||
txtupian: '',
|
||||
ossImageUrl: '',
|
||||
showTixianModal: false,
|
||||
tixianAmount: '',
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
currentRate: '0.00',
|
||||
recordList: [],
|
||||
page: 1,
|
||||
nomore: false,
|
||||
loading: false,
|
||||
isRefreshing: false,
|
||||
canloadmore: true,
|
||||
showSkfsModal: false,
|
||||
tempTxfangshi: null,
|
||||
tempTxPhone: '',
|
||||
tempTxAccount: '',
|
||||
tempTxImage: '',
|
||||
choosingImage: false,
|
||||
showModifyModal: false,
|
||||
modifyingRecord: null,
|
||||
modifyTxfangshi: null,
|
||||
modifyTxPhone: '',
|
||||
modifyTxAccount: '',
|
||||
modifyTxImage: '',
|
||||
modifyImageUrl: '',
|
||||
showFailModal: false,
|
||||
currentFailReason: '',
|
||||
isLoading: false,
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.initImageUrls();
|
||||
this.loadAllAssets();
|
||||
this.loadWithdrawMethod();
|
||||
this.loadWithdrawRecords(true);
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this.registerNotification();
|
||||
PopupService.checkAndShow(this, 'tixian');
|
||||
},
|
||||
hide() {
|
||||
const popup = this.selectComponent('#popupNotice');
|
||||
popup?.cleanup?.();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
if (this.data.isRefreshing) {
|
||||
wx.stopPullDownRefresh();
|
||||
return;
|
||||
}
|
||||
this.setData({ isRefreshing: true });
|
||||
this.loadWithdrawRecords(true).then(() => {
|
||||
wx.stopPullDownRefresh();
|
||||
this.setData({ isRefreshing: false });
|
||||
}).catch(() => {
|
||||
wx.stopPullDownRefresh();
|
||||
this.setData({ isRefreshing: false });
|
||||
});
|
||||
},
|
||||
|
||||
// 底部按钮加载更多
|
||||
loadMoreRecords() {
|
||||
if (this.data.nomore) {
|
||||
wx.showToast({ title: '没有更多记录了', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (this.data.loading) return;
|
||||
this.loadWithdrawRecords();
|
||||
},
|
||||
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
pageBg: `${imgDir}page_bg.png`,
|
||||
cardBg: `${imgDir}card_bg.png`,
|
||||
iconWechat: `${imgDir}icon_wechat.png`,
|
||||
iconAlipay: `${imgDir}icon_alipay.png`,
|
||||
iconRecord: `${imgDir}icon_record.png`,
|
||||
iconRefresh: `${imgDir}icon_refresh.png`,
|
||||
assetTileBg: `${imgDir}asset_tile_bg.png`,
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async loadAllAssets() {
|
||||
this.setData({ isLoading: true });
|
||||
try {
|
||||
const res = await request({ url: '/yonghu/tixianzichan', method: 'POST' });
|
||||
if (res?.data?.code === 200) {
|
||||
const data = res.data.data;
|
||||
const assets = [];
|
||||
if (data.dashou_yue && parseFloat(data.dashou_yue) > 0) {
|
||||
assets.push({ type: 'dashou_yue', label: '接单员佣金', amount: data.dashou_yue, rate: data.dashou_rate || 0 });
|
||||
}
|
||||
if (data.dashou_yajin && parseFloat(data.dashou_yajin) > 0) {
|
||||
assets.push({ type: 'dashou_yajin', label: '接单员保证金', amount: data.dashou_yajin, rate: data.dashou_yajin_rate || 0 });
|
||||
}
|
||||
if (data.shangjia_yue && parseFloat(data.shangjia_yue) > 0) {
|
||||
assets.push({ type: 'shangjia_yue', label: '商家余额', amount: data.shangjia_yue, rate: data.shangjia_rate || 0 });
|
||||
}
|
||||
if (data.guanshi_fenyong && parseFloat(data.guanshi_fenyong) > 0) {
|
||||
assets.push({ type: 'guanshi_fenyong', label: '管事分红', amount: data.guanshi_fenyong, rate: data.guanshi_rate || 0 });
|
||||
}
|
||||
if (data.zuzhang_fenyong && parseFloat(data.zuzhang_fenyong) > 0) {
|
||||
assets.push({ type: 'zuzhang_fenyong', label: '组长分红', amount: data.zuzhang_fenyong, rate: data.zuzhang_rate || 0 });
|
||||
}
|
||||
if (data.kaoheguan_fenyong && parseFloat(data.kaoheguan_fenyong) > 0) {
|
||||
assets.push({ type: 'kaoheguan_fenyong', label: '考核官分佣', amount: data.kaoheguan_fenyong, rate: data.kaoheguan_rate || 0 });
|
||||
}
|
||||
let total = 0;
|
||||
assets.forEach(item => { total += parseFloat(item.amount); });
|
||||
this.setData({ assetList: assets, totalAmount: total.toFixed(2), isLoading: false });
|
||||
// 缓存费率
|
||||
wx.setStorageSync('dashouRate', data.dashou_rate || 0);
|
||||
wx.setStorageSync('dashou_yajin_rate', data.dashou_yajin_rate || 0);
|
||||
wx.setStorageSync('shangjia_rate', data.shangjia_rate || 0);
|
||||
wx.setStorageSync('guanshi_rate', data.guanshi_rate || 0);
|
||||
wx.setStorageSync('zuzhang_rate', data.zuzhang_rate || 0);
|
||||
wx.setStorageSync('kaoheguan_rate', data.kaoheguan_rate || 0);
|
||||
} else {
|
||||
throw new Error(res?.data?.msg || '获取资产失败');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
wx.showToast({ title: '加载失败', icon: 'none' });
|
||||
this.setData({ isLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
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) {
|
||||
this.setData({ txzh, txtupian, txfangshi, txdianhua, ossImageUrl: app.globalData.ossImageUrl || '' });
|
||||
} else {
|
||||
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) {}
|
||||
}
|
||||
},
|
||||
|
||||
onSelectAsset(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const asset = this.data.assetList[index];
|
||||
if (!asset || parseFloat(asset.amount) <= 0) {
|
||||
wx.showToast({ title: '无可提现金额', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({
|
||||
selectedAsset: asset,
|
||||
showTixianModal: true,
|
||||
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',
|
||||
currentRate: asset.rate
|
||||
});
|
||||
showTixianModal: false,
|
||||
submitting: false,
|
||||
txfangshi: null,
|
||||
txdianhua: '',
|
||||
txzh: '',
|
||||
txtupian: '',
|
||||
showSkfsModal: false,
|
||||
tempTxfangshi: null,
|
||||
tempTxPhone: '',
|
||||
tempTxAccount: '',
|
||||
tempTxImage: '',
|
||||
choosingImage: false,
|
||||
},
|
||||
|
||||
onAmountInput(e) {
|
||||
let val = e.detail.value;
|
||||
if (val && !/^\d*\.?\d{0,2}$/.test(val)) return;
|
||||
this.setData({ tixianAmount: val });
|
||||
if (val && parseFloat(val) > 0) {
|
||||
const amount = parseFloat(val);
|
||||
const rate = parseFloat(this.data.selectedAsset.rate) || 0;
|
||||
const fee = amount * rate;
|
||||
const actual = amount - fee;
|
||||
this.setData({ shouxufei: fee.toFixed(2), shijidaozhang: actual.toFixed(2) });
|
||||
} else {
|
||||
this.setData({ shouxufei: '0.00', shijidaozhang: '0.00' });
|
||||
}
|
||||
attached() {
|
||||
this.initImageUrls();
|
||||
this.loadAllAssets();
|
||||
this.loadWithdrawMethod();
|
||||
},
|
||||
|
||||
onQuickAmount(e) {
|
||||
const val = e.currentTarget.dataset.value;
|
||||
this.setData({ tixianAmount: val.toString() });
|
||||
this.onAmountInput({ detail: { value: val.toString() } });
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this.registerNotification();
|
||||
this.loadAllAssets();
|
||||
PopupService.checkAndShow(this, 'tixian');
|
||||
},
|
||||
hide() {
|
||||
const popup = this.selectComponent('#popupNotice');
|
||||
popup?.cleanup?.();
|
||||
},
|
||||
},
|
||||
|
||||
async onConfirmWithdraw() {
|
||||
const { selectedAsset, tixianAmount, txfangshi, txzh, txtupian, txdianhua } = 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; }
|
||||
if (!txfangshi || (!txzh && !txtupian)) {
|
||||
wx.showToast({ title: '请先设置收款方式', icon: 'none' });
|
||||
this.setData({ showTixianModal: false });
|
||||
this.onSetSkfs();
|
||||
return;
|
||||
}
|
||||
let leixing = 1;
|
||||
switch (selectedAsset.type) {
|
||||
case 'dashou_yue': leixing = 1; break;
|
||||
case 'dashou_yajin': leixing = 5; break;
|
||||
case 'shangjia_yue': leixing = 6; break;
|
||||
case 'guanshi_fenyong': leixing = 2; break;
|
||||
case 'zuzhang_fenyong': leixing = 3; break;
|
||||
case 'kaoheguan_fenyong': leixing = 4; break;
|
||||
}
|
||||
let txskfs = 0;
|
||||
if (txzh && txtupian) txskfs = 3;
|
||||
else if (txzh) txskfs = 1;
|
||||
else if (txtupian) txskfs = 2;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixian',
|
||||
method: 'POST',
|
||||
data: { leixing, jine: amount.toFixed(2), fangshi: txfangshi, txskfs }
|
||||
});
|
||||
if (res?.data?.code === 0) {
|
||||
const newAssetList = this.data.assetList.map(item => {
|
||||
if (item.type === selectedAsset.type) {
|
||||
const newAmount = (parseFloat(item.amount) - amount).toFixed(2);
|
||||
return { ...item, amount: newAmount };
|
||||
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(),
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
let newTotal = 0;
|
||||
newAssetList.forEach(item => { newTotal += parseFloat(item.amount); });
|
||||
this.setData({ assetList: newAssetList, totalAmount: newTotal.toFixed(2), showTixianModal: false, selectedAsset: null });
|
||||
this.loadWithdrawRecords(true);
|
||||
wx.showToast({ title: '提现申请已提交', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: res?.data?.msg || '提现失败', icon: 'none' });
|
||||
}
|
||||
} catch (err) {
|
||||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
onCloseTixianModal() {
|
||||
this.setData({ showTixianModal: false, selectedAsset: null, tixianAmount: '' });
|
||||
},
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
iconWechat: `${imgDir}icon_wechat.png`,
|
||||
iconAlipay: `${imgDir}icon_alipay.png`,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
onSetSkfs() {
|
||||
this.setData({
|
||||
showSkfsModal: true,
|
||||
tempTxfangshi: this.data.txfangshi,
|
||||
tempTxPhone: this.data.txdianhua,
|
||||
tempTxAccount: this.data.txzh,
|
||||
tempTxImage: ''
|
||||
});
|
||||
},
|
||||
/** 顶部展示:不含保证金的可提现合计 */
|
||||
calcDisplayTotal(assets) {
|
||||
let total = 0;
|
||||
(assets || []).forEach((item) => {
|
||||
if (item.type === 'dashou_yajin') return;
|
||||
total += parseFloat(item.amount) || 0;
|
||||
});
|
||||
return total;
|
||||
},
|
||||
|
||||
onSelectFangshi(e) {
|
||||
this.setData({ tempTxfangshi: e.currentTarget.dataset.fangshi });
|
||||
},
|
||||
hasAnyWithdrawable(assets) {
|
||||
return (assets || []).some((item) => parseFloat(item.amount) > 0);
|
||||
},
|
||||
|
||||
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) { wx.showToast({ title: '请上传微信收款码', icon: 'none' }); return; }
|
||||
if (tempTxfangshi == 2 && !tempTxAccount && !tempTxImage) {
|
||||
wx.showToast({ title: '请填写支付宝账号或上传收款码', icon: 'none' }); return;
|
||||
}
|
||||
const formData = { txdianhua: tempTxPhone, txzh: tempTxAccount || '' };
|
||||
try {
|
||||
const res = await upload({ url: '/yonghu/sksc', formData, 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 || '', showSkfsModal: false
|
||||
});
|
||||
wx.setStorageSync('txfangshi', tempTxfangshi);
|
||||
wx.setStorageSync('txdianhua', tempTxPhone);
|
||||
wx.setStorageSync('txzh', data.txzh || '');
|
||||
wx.setStorageSync('txtupian', 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 }); },
|
||||
|
||||
async loadWithdrawRecords(refresh = false) {
|
||||
const now = Date.now();
|
||||
if (now - lastPullDownTime < PULL_DOWN_INTERVAL && !refresh) return;
|
||||
if (this.data.loading || this.data.isRefreshing) return;
|
||||
const page = refresh ? 1 : this.data.page;
|
||||
if (this.data.nomore && !refresh) return;
|
||||
this.setData({ loading: true, isRefreshing: refresh });
|
||||
lastPullDownTime = now;
|
||||
try {
|
||||
const res = await request({ url: '/yonghu/tixianjiluhq', method: 'POST', data: { page, limit: PAGE_SIZE } });
|
||||
if (res?.data?.code === 0) {
|
||||
const list = (res.data.data.list || []).map(item => ({
|
||||
...item,
|
||||
statusText: this.getStatusText(item.zhuangtai),
|
||||
statusColor: this.getStatusColor(item.zhuangtai)
|
||||
}));
|
||||
const newList = refresh ? list : [...this.data.recordList, ...list];
|
||||
const hasMore = res.data.data.has_more === true;
|
||||
this.setData({
|
||||
recordList: newList, page: page + 1, nomore: !hasMore, canloadmore: hasMore,
|
||||
loading: false, isRefreshing: false
|
||||
});
|
||||
} else {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
} catch (err) {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
},
|
||||
|
||||
onModifyRecord(e) {
|
||||
const record = e.currentTarget.dataset.record;
|
||||
if (parseInt(record.zhuangtai) !== 1) {
|
||||
wx.showToast({ title: '只有审核中的记录可修改', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({
|
||||
modifyingRecord: record,
|
||||
modifyTxfangshi: record.fangshi,
|
||||
modifyTxPhone: record.txdianhua || '',
|
||||
modifyTxAccount: record.txzh || '',
|
||||
modifyTxImage: '',
|
||||
modifyImageUrl: record.txtupian ? (app.globalData.ossImageUrl + record.txtupian) : '',
|
||||
showModifyModal: true
|
||||
});
|
||||
},
|
||||
|
||||
onSelectModifyFangshi(e) { this.setData({ modifyTxfangshi: e.currentTarget.dataset.fangshi }); },
|
||||
onModifyPhoneInput(e) { this.setData({ modifyTxPhone: e.detail.value }); },
|
||||
onModifyAccountInput(e) { this.setData({ modifyTxAccount: e.detail.value }); },
|
||||
|
||||
onChooseModifyImage() {
|
||||
if (this.data.choosingImage) return;
|
||||
this.setData({ choosingImage: true });
|
||||
wx.chooseMedia({
|
||||
count: 1, mediaType: ['image'],
|
||||
success: (res) => { this.setData({ modifyTxImage: res.tempFiles[0].tempFilePath }); },
|
||||
complete: () => { this.setData({ choosingImage: false }); }
|
||||
});
|
||||
},
|
||||
|
||||
onPreviewModifyImage() {
|
||||
if (this.data.modifyTxImage) wx.previewImage({ urls: [this.data.modifyTxImage] });
|
||||
else if (this.data.modifyImageUrl) wx.previewImage({ urls: [this.data.modifyImageUrl] });
|
||||
},
|
||||
|
||||
onDeleteModifyImage() { this.setData({ modifyTxImage: '' }); },
|
||||
|
||||
async onConfirmModify() {
|
||||
const { modifyTxfangshi, modifyTxPhone, modifyTxAccount, modifyTxImage, modifyingRecord } = this.data;
|
||||
if (!modifyTxfangshi) { wx.showToast({ title: '请选择提现方式', icon: 'none' }); return; }
|
||||
if (!modifyTxPhone) { wx.showToast({ title: '请输入收款人电话', icon: 'none' }); return; }
|
||||
if (modifyTxfangshi == 1 && !modifyTxImage) { wx.showToast({ title: '请上传微信收款码', icon: 'none' }); return; }
|
||||
if (modifyTxfangshi == 2 && !modifyTxAccount && !modifyTxImage) {
|
||||
wx.showToast({ title: '请填写支付宝账号或上传收款码', icon: 'none' }); return;
|
||||
}
|
||||
const formData = { tixian_id: modifyingRecord.id, fangshi: modifyTxfangshi, txdianhua: modifyTxPhone, txzh: modifyTxAccount || '' };
|
||||
try {
|
||||
const res = await upload({ url: '/yonghu/yonghutxshxg', formData, filePath: modifyTxImage || null, fileName: 'file' });
|
||||
if (res?.data?.code === 0) {
|
||||
const data = res.data.data;
|
||||
const newList = this.data.recordList.map(item => {
|
||||
if (item.id === modifyingRecord.id) {
|
||||
return { ...item, fangshi: modifyTxfangshi, txdianhua: modifyTxPhone, txzh: modifyTxAccount || '', txtupian: data.txtupian || modifyingRecord.txtupian };
|
||||
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];
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setData({ recordList: newList, showModifyModal: false, modifyingRecord: null });
|
||||
wx.showToast({ title: '修改成功', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: res?.data?.msg || '修改失败', icon: 'none' });
|
||||
}
|
||||
} catch (err) {
|
||||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||||
}
|
||||
},
|
||||
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);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onCloseModifyModal() { this.setData({ showModifyModal: false, modifyingRecord: null }); },
|
||||
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);
|
||||
},
|
||||
|
||||
onViewFailReason(e) {
|
||||
const record = e.currentTarget.dataset.record;
|
||||
const reason = record.fail_reason || record.shibaiyuanyin || '暂无详细信息';
|
||||
this.setData({ currentFailReason: reason, showFailModal: true });
|
||||
},
|
||||
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);
|
||||
|
||||
onCloseFailModal() { this.setData({ showFailModal: false }); },
|
||||
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: [] });
|
||||
}
|
||||
},
|
||||
|
||||
getStatusText(zhuangtai) {
|
||||
const s = parseInt(zhuangtai);
|
||||
if (s === 1) return '审核中';
|
||||
if (s === 2) return '成功';
|
||||
if (s === 3) return '失败';
|
||||
return '未知';
|
||||
},
|
||||
getStatusColor(zhuangtai) {
|
||||
const s = parseInt(zhuangtai);
|
||||
if (s === 1) return '#F5A623';
|
||||
if (s === 2) return '#2ED158';
|
||||
if (s === 3) return '#FF4D4F';
|
||||
return '#999';
|
||||
},
|
||||
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 */ }
|
||||
},
|
||||
|
||||
registerNotification() {
|
||||
const comp = this.selectComponent('#global-notification');
|
||||
if (comp?.showNotification) {
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => comp.showNotification(data),
|
||||
hide: () => comp.hideNotification()
|
||||
};
|
||||
}
|
||||
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() {},
|
||||
},
|
||||
stopPropagation() {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,133 +1,115 @@
|
||||
<!-- pages/withdraw/withdraw.wxml -->
|
||||
<!-- 最终版:资产卡片添加背景图,微调模糊 -->
|
||||
|
||||
<view class="app">
|
||||
<!-- 页面背景(全局模糊降低) -->
|
||||
<image class="global-bg" src="{{imgUrls.pageBg}}" mode="aspectFill" />
|
||||
|
||||
<!-- 资产区域 -->
|
||||
<view class="assets-section">
|
||||
<view class="main-card" style="background-image: url('{{imgUrls.cardBg}}'); background-size: cover;">
|
||||
<!-- 总余额 -->
|
||||
<view class="balance-wrap">
|
||||
<text class="balance-label">可提总余额</text>
|
||||
<text class="balance-value">¥{{totalAmount}}</text>
|
||||
</view>
|
||||
|
||||
<!-- 内部分隔线 -->
|
||||
<view class="inner-divider"></view>
|
||||
|
||||
<!-- 左右滑动提示 -->
|
||||
<text class="assets-hint">← 左右滑动查看更多资产 →</text>
|
||||
|
||||
<!-- 资产横向滚动区 -->
|
||||
<scroll-view class="assets-scroll" scroll-x="true" show-scrollbar="{{false}}" enhanced>
|
||||
<view class="assets-track">
|
||||
<block wx:for="{{assetList}}" wx:key="index">
|
||||
<!-- 每个资产卡片加上自己的背景图 -->
|
||||
<view class="asset-tile" bindtap="onSelectAsset" data-index="{{index}}" style="background-image: url('{{imgUrls.assetTileBg}}'); background-size: cover; background-position: center;">
|
||||
<text class="asset-name">{{item.label}}</text>
|
||||
<text class="asset-balance">¥{{item.amount}}</text>
|
||||
<text class="asset-fee">费率 {{item.rate}}%</text>
|
||||
</view>
|
||||
</block>
|
||||
<view wx:if="{{assetList.length === 0 && !isLoading}}" class="assets-empty">暂无可用资金</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 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>
|
||||
|
||||
<!-- 层次分隔线 -->
|
||||
<view class="divider-line"></view>
|
||||
<text class="method-setting" bindtap="onSetSkfs">设置收款方式</text>
|
||||
</view>
|
||||
|
||||
<!-- 提现记录区 -->
|
||||
<view class="history-section">
|
||||
<view class="history-header">
|
||||
<text class="history-title">提现记录</text>
|
||||
<text class="history-settings" bindtap="onSetSkfs">收款方式</text>
|
||||
</view>
|
||||
<scroll-view class="history-scroll" scroll-y enable-back-to-top bindscrolltolower="onLoadMoreFromScroll">
|
||||
<view wx:for="{{recordList}}" wx:key="index" class="history-item">
|
||||
<view class="history-info">
|
||||
<text class="history-amount">¥{{item.jine}}</text>
|
||||
<text class="history-time">{{item.create}}</text>
|
||||
</view>
|
||||
<view class="history-detail">
|
||||
<text class="history-method">{{item.fangshi == 1 ? '微信' : '支付宝'}}</text>
|
||||
<text class="history-type">{{item.leixing == 1 ? '佣金' : (item.leixing == 2 ? '分红' : (item.leixing == 3 ? '组长' : (item.leixing == 4 ? '考核官' : '保证金')))}}</text>
|
||||
</view>
|
||||
<view class="history-status">
|
||||
<view wx:if="{{item.zhuangtai == 1}}" class="status-badge status-wait" bindtap="onModifyRecord" data-record="{{item}}">{{item.statusText}} ✏修改</view>
|
||||
<view wx:elif="{{item.zhuangtai == 3}}" class="status-badge status-fail">
|
||||
{{item.statusText}}
|
||||
<text class="fail-link" bindtap="onViewFailReason" data-record="{{item}}">详情</text>
|
||||
</view>
|
||||
<view wx:else class="status-badge status-done">{{item.statusText}}</view>
|
||||
</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>
|
||||
<view wx:if="{{loading}}" class="load-tip">加载中...</view>
|
||||
<view wx:if="{{nomore && recordList.length > 0}}" class="more-tip">—— 没有更多了 ——</view>
|
||||
<view wx:if="{{!nomore && recordList.length > 0}}" class="load-more-btn" bindtap="loadMoreRecords">加载更多记录</view>
|
||||
</scroll-view>
|
||||
<text wx:if="{{!selectedAsset}}" class="account-warn">请先选择上方提现账户</text>
|
||||
<text wx:else class="account-ok">当前:{{selectedAsset.label}}</text>
|
||||
</view>
|
||||
|
||||
<view class="safe-bottom"></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-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.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="amount-row"><text>金额</text><input type="digit" placeholder="0.00" value="{{tixianAmount}}" bindinput="onAmountInput" /></view>
|
||||
<view class="quick-row"><view wx:for="{{[100,200,500,1000]}}" wx:key="item" class="quick-chip" data-value="{{item}}" bindtap="onQuickAmount">¥{{item}}</view></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="method-row"><text>收款方式 {{txfangshi == 1 ? '微信' : (txfangshi == 2 ? '支付宝' : '未设置')}}</text><text class="link-text" bindtap="onSetSkfs">更换</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 class="modal-footer"><view class="modal-btn cancel" bindtap="onCloseTixianModal">取消</view><view class="modal-btn confirm" bindtap="onConfirmWithdraw">确认</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">
|
||||
<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>
|
||||
<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 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>
|
||||
|
||||
<!-- 修改审核中记录弹窗 -->
|
||||
<view wx:if="{{showModifyModal}}" class="modal-mask" bindtap="onCloseModifyModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">修改信息</view>
|
||||
<view class="modal-body">
|
||||
<view class="toggle-row"><view class="toggle-item {{modifyTxfangshi == 1 ? 'active' : ''}}" bindtap="onSelectModifyFangshi" data-fangshi="1">微信</view><view class="toggle-item {{modifyTxfangshi == 2 ? 'active' : ''}}" bindtap="onSelectModifyFangshi" data-fangshi="2">支付宝</view></view>
|
||||
<input class="field-input" placeholder="电话" value="{{modifyTxPhone}}" bindinput="onModifyPhoneInput" />
|
||||
<view wx:if="{{modifyTxfangshi == 2}}"><input class="field-input" placeholder="支付宝账号" value="{{modifyTxAccount}}" bindinput="onModifyAccountInput" /></view>
|
||||
<view class="upload-wrap"><view wx:if="{{modifyImageUrl}}" class="current-img"><image src="{{modifyImageUrl}}" mode="aspectFill" bindtap="onPreviewModifyImage" /></view><view class="upload-trigger" bindtap="onChooseModifyImage">+ 上传新图片</view><view wx:if="{{modifyTxImage}}" class="image-preview"><image src="{{modifyTxImage}}" mode="aspectFill" /><view class="image-actions"><text bindtap="onPreviewModifyImage">预览</text><text bindtap="onDeleteModifyImage">删除</text></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 class="modal-footer"><view class="modal-btn cancel" bindtap="onCloseModifyModal">取消</view><view class="modal-btn confirm" bindtap="onConfirmModify">确认</view></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 失败原因弹窗 -->
|
||||
<view wx:if="{{showFailModal}}" class="modal-mask" bindtap="onCloseFailModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">失败原因</view>
|
||||
<view class="modal-body">{{currentFailReason}}</view>
|
||||
<view class="modal-footer"><view class="modal-btn confirm" bindtap="onCloseFailModal">知道了</view></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
<popup-notice id="popupNotice" />
|
||||
<popup-notice id="popupNotice" />
|
||||
|
||||
@@ -1,424 +1,85 @@
|
||||
/* pages/withdraw/withdraw.wxss - 终极优化版 */
|
||||
@import '../mode2/mode2.wxss';
|
||||
|
||||
page {
|
||||
background-color: #f5f7fb;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding: 0 24rpx 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 页面背景模糊极低,不影响阅读 */
|
||||
.global-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
opacity: 0.1;
|
||||
object-fit: cover;
|
||||
filter: blur(1rpx);
|
||||
}
|
||||
|
||||
/* 资产区域整体与顶部保持间距 */
|
||||
.assets-section {
|
||||
margin-top: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 主卡片玻璃质感 - 模糊加重避免抢眼,同时文字对比加强 */
|
||||
.main-card {
|
||||
background: rgba(248, 250, 252, 0.88); /* 稍微降低透明度,让背景更柔和 */
|
||||
backdrop-filter: blur(28rpx); /* 增强模糊,不抢眼 */
|
||||
-webkit-backdrop-filter: blur(28rpx);
|
||||
border-radius: 48rpx;
|
||||
padding: 30rpx 28rpx 24rpx; /* 稍微缩小高度 */
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.04);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.4);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* 总余额 - 字体加深加粗,增加阴影提高可读性 */
|
||||
.balance-wrap {
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx; /* 减小间距,让卡片更紧凑 */
|
||||
}
|
||||
.balance-label {
|
||||
font-size: 28rpx;
|
||||
color: #0f172a; /* 更深色 */
|
||||
letter-spacing: 1px;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
font-weight: 700; /* 加粗 */
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.8);
|
||||
}
|
||||
.balance-value {
|
||||
font-size: 68rpx;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
font-family: 'DIN', monospace;
|
||||
letter-spacing: -1rpx;
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
/* 内部分隔线(横杠)- 明显且保持层次 */
|
||||
.inner-divider {
|
||||
width: 60%;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #64748b, #64748b, transparent); /* 加深颜色 */
|
||||
margin: 0 auto 20rpx auto;
|
||||
border-radius: 2rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* 左右滑动提示 - 字体明显 */
|
||||
.assets-hint {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #334155; /* 深灰 */
|
||||
margin-bottom: 14rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.assets-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.assets-track {
|
||||
display: inline-flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
/* 资产小卡片 - 背景半透模糊,字体深色加粗 */
|
||||
.asset-tile {
|
||||
width: 170rpx;
|
||||
background: rgba(255, 255, 255, 0.75); /* 稍微提高透明度,让模糊背景透出 */
|
||||
backdrop-filter: blur(8rpx); /* 自身轻微模糊,不抢眼 */
|
||||
border-radius: 28rpx;
|
||||
padding: 18rpx 12rpx;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.02);
|
||||
transition: all 0.2s;
|
||||
white-space: normal;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.asset-tile:active {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.asset-name {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700; /* 加粗 */
|
||||
color: #1e293b; /* 深色 */
|
||||
margin-bottom: 10rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.5);
|
||||
}
|
||||
.asset-balance {
|
||||
font-size: 28rpx;
|
||||
font-weight: 800; /* 加粗 */
|
||||
color: #2d6a4f;
|
||||
font-family: monospace;
|
||||
margin-bottom: 6rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.asset-fee {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600; /* 加粗并加深 */
|
||||
color: #475569;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.assets-empty {
|
||||
width: 400rpx;
|
||||
text-align: center;
|
||||
color: #a0abb9;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
/* 外部层次分隔线 - 保持不变,保留分层 */
|
||||
.divider-line {
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #cbd5e1, #cbd5e1, transparent);
|
||||
margin: 16rpx 0 20rpx;
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* 提现记录区 - 无改动,自然贴底 */
|
||||
.history-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 0 8rpx 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.history-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
}
|
||||
.history-settings {
|
||||
font-size: 28rpx;
|
||||
color: #3b82f6;
|
||||
}
|
||||
.history-scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 28rpx 0;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.history-info {
|
||||
width: 160rpx;
|
||||
}
|
||||
.history-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
display: block;
|
||||
}
|
||||
.history-time {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-detail {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.history-method {
|
||||
font-size: 30rpx;
|
||||
color: #334155;
|
||||
display: block;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
.history-type {
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-status {
|
||||
text-align: right;
|
||||
}
|
||||
.status-badge {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
padding: 6rpx 14rpx;
|
||||
border-radius: 30rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
.status-wait {
|
||||
color: #f59e0b;
|
||||
background: rgba(245,158,11,0.1);
|
||||
}
|
||||
.status-done {
|
||||
color: #10b981;
|
||||
background: rgba(16,185,129,0.1);
|
||||
}
|
||||
.status-fail {
|
||||
color: #ef4444;
|
||||
background: rgba(239,68,68,0.1);
|
||||
}
|
||||
.fail-link {
|
||||
margin-left: 8rpx;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.load-tip, .more-tip {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.load-more-btn {
|
||||
margin: 16rpx 0 20rpx;
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
background: rgba(255,255,255,0.7);
|
||||
backdrop-filter: blur(8rpx);
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
color: #3b82f6;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
}
|
||||
.load-more-btn:active {
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.safe-bottom {
|
||||
height: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ========== 弹窗样式(完整保留) ========== */
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.modal-dialog {
|
||||
width: 600rpx;
|
||||
background: rgba(255,255,255,0.96);
|
||||
backdrop-filter: blur(20rpx);
|
||||
border-radius: 48rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20rpx 40rpx rgba(0,0,0,0.1);
|
||||
border: 1rpx solid rgba(255,255,255,0.6);
|
||||
}
|
||||
.modal-header {
|
||||
padding: 36rpx 32rpx 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-body {
|
||||
padding: 32rpx;
|
||||
}
|
||||
.info-row, .amount-row, .method-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.amount-row input {
|
||||
border: 1rpx solid rgba(0,0,0,0.1);
|
||||
border-radius: 28rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
width: 260rpx;
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.quick-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin: 24rpx 0;
|
||||
}
|
||||
.quick-chip {
|
||||
flex: 1;
|
||||
background: rgba(241,245,249,0.8);
|
||||
text-align: center;
|
||||
padding: 12rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: rgba(248,250,252,0.8);
|
||||
padding: 20rpx;
|
||||
border-radius: 28rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.link-text {
|
||||
color: #3b82f6;
|
||||
}
|
||||
.toggle-row {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
.toggle-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 20rpx;
|
||||
border: 1rpx solid rgba(0,0,0,0.08);
|
||||
border-radius: 30rpx;
|
||||
background: rgba(255,255,255,0.8);
|
||||
}
|
||||
.toggle-item.active {
|
||||
border-color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
}
|
||||
.field-input {
|
||||
width: 100%;
|
||||
border: 1rpx solid rgba(0,0,0,0.08);
|
||||
border-radius: 28rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-sizing: border-box;
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.upload-trigger {
|
||||
background: rgba(241,245,249,0.8);
|
||||
border: 1rpx dashed #cbd5e1;
|
||||
border-radius: 28rpx;
|
||||
padding: 28rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.image-preview {
|
||||
margin-top: 16rpx;
|
||||
position: relative;
|
||||
}
|
||||
.image-preview image {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border-radius: 28rpx;
|
||||
}
|
||||
.image-actions {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
background: rgba(0,0,0,0.6);
|
||||
padding: 12rpx;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
color: white;
|
||||
border-bottom-left-radius: 28rpx;
|
||||
border-bottom-right-radius: 28rpx;
|
||||
}
|
||||
.current-img {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.current-img image {
|
||||
width: 100%;
|
||||
height: 140rpx;
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
border-top: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.modal-btn.cancel {
|
||||
color: #8f9bb3;
|
||||
border-right: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn.confirm {
|
||||
color: #3b82f6;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
// pages/withdraw/components/mode2/mode2.js
|
||||
// UI 与 mode1 完全一致,业务逻辑为自动打款审核收款
|
||||
// pages/withdraw/components/mode2/mode2.js — 自动打款纯提现
|
||||
import request from '../../../../utils/request.js';
|
||||
import PopupService from '../../../../services/popupService.js';
|
||||
|
||||
const app = getApp();
|
||||
const yemianshuju = 5;
|
||||
let lastPullDownTime = 0;
|
||||
const PULL_DOWN_INTERVAL = 2000;
|
||||
|
||||
const TX_STATUS = {
|
||||
SHENHEZHONG: 1,
|
||||
TIXIAN_CHENGGONG: 2,
|
||||
TIXIAN_SHIBAI: 3,
|
||||
SHENHE_CHENGGONG: 4,
|
||||
SHENHE_SHIBAI: 5,
|
||||
DAI_SHOUKUAN: 6,
|
||||
};
|
||||
|
||||
const ASSET_CONFIG = {
|
||||
dashou_yue: { leixing: 1, label: '接单员佣金' },
|
||||
@@ -26,58 +13,41 @@ const ASSET_CONFIG = {
|
||||
shangjia_yue: { leixing: 6, label: '商家余额' },
|
||||
};
|
||||
|
||||
const LEIXING_LABEL = {
|
||||
1: '接单员佣金', 2: '管事分红', 3: '组长分红',
|
||||
4: '考核官分佣', 5: '接单员保证金', 6: '商家余额',
|
||||
/** 页面入参 from 与资产 type 映射 */
|
||||
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: {
|
||||
pageBg: '', cardBg: '', assetTileBg: '',
|
||||
},
|
||||
imgUrls: { iconWechat: '' },
|
||||
assetList: [],
|
||||
displayAssetList: [],
|
||||
totalAmount: '0.00',
|
||||
canWithdraw: false,
|
||||
selectedAsset: null,
|
||||
isLoadingAssets: false,
|
||||
tixianleixing: null,
|
||||
tixianjine: '',
|
||||
currentRate: '0.00',
|
||||
feeRateText: '--',
|
||||
showTixian: false,
|
||||
recordList: [],
|
||||
page: 1,
|
||||
loading: false,
|
||||
nomore: false,
|
||||
canloadmore: true,
|
||||
isRefreshing: false,
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
currentTixianId: null,
|
||||
submitting: false,
|
||||
mchId: '',
|
||||
currentStatusFilter: 0,
|
||||
statusTabs: [
|
||||
{ value: 0, label: '全部' },
|
||||
{ value: 1, label: '审核中' },
|
||||
{ value: 6, label: '待收款' },
|
||||
{ value: 4, label: '审核成功' },
|
||||
{ value: 5, label: '审核失败' },
|
||||
{ value: 2, label: '提现成功' },
|
||||
{ value: 3, label: '提现失败' },
|
||||
],
|
||||
hasPendingCollect: false,
|
||||
showCollectConfirm: false,
|
||||
collectConfirmRecord: null,
|
||||
showDetailModal: false,
|
||||
detailTitle: '',
|
||||
detailContent: '',
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.initImageUrls();
|
||||
this.chushihuashuju();
|
||||
}
|
||||
this.loadAllAssets();
|
||||
},
|
||||
},
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
@@ -88,7 +58,7 @@ Component({
|
||||
hide() {
|
||||
const popupComp = this.selectComponent('#popupNotice');
|
||||
if (popupComp && popupComp.cleanup) popupComp.cleanup();
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
registerNotificationComponent() {
|
||||
@@ -96,127 +66,11 @@ Component({
|
||||
if (notificationComp && notificationComp.showNotification) {
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => notificationComp.showNotification(data),
|
||||
hide: () => notificationComp.hideNotification()
|
||||
hide: () => notificationComp.hideNotification(),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
pageBg: `${imgDir}page_bg.png`,
|
||||
cardBg: `${imgDir}card_bg.png`,
|
||||
assetTileBg: `${imgDir}asset_tile_bg.png`,
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
parseZhuangtai(item) {
|
||||
const raw = item.zhuangtai ?? item.status ?? item.state;
|
||||
const n = parseInt(raw, 10);
|
||||
return Number.isNaN(n) ? -1 : n;
|
||||
},
|
||||
|
||||
/** 规范化列表字段(兼容后端多种命名 / 嵌套 audit) */
|
||||
normalizeRecordFields(item) {
|
||||
const audit = item.audit || item.shenhe || item.shenhe_info || {};
|
||||
const shenheJiluId = item.shenhe_jilu_id ?? item.shenheJiluId
|
||||
?? item.audit_id ?? item.shenheid ?? audit.id ?? audit.shenhe_jilu_id ?? null;
|
||||
const shenheDanhao = String(
|
||||
item.shenhe_danhao || item.shenheDanhao || item.audit_shenhe_danhao
|
||||
|| audit.shenhe_danhao || audit.danhao || ''
|
||||
).trim();
|
||||
const tixianjiluId = item.tixianjilu_id ?? item.tixianjiluId ?? item.id ?? null;
|
||||
const zhuangtai = this.parseZhuangtai(item);
|
||||
return {
|
||||
...item,
|
||||
zhuangtai: zhuangtai >= 0 ? zhuangtai : item.zhuangtai,
|
||||
shenhe_jilu_id: shenheJiluId,
|
||||
shenhe_danhao: shenheDanhao,
|
||||
tixianjilu_id: tixianjiluId,
|
||||
};
|
||||
},
|
||||
|
||||
hasAuditJiluId(item) {
|
||||
const id = item.shenhe_jilu_id;
|
||||
return id !== null && id !== undefined && id !== '' && id !== 0 && id !== '0';
|
||||
},
|
||||
|
||||
hasShenheDanhao(item) {
|
||||
return !!(item.shenhe_danhao && String(item.shenhe_danhao).trim());
|
||||
},
|
||||
|
||||
isNewAuditRecord(item) {
|
||||
return this.hasAuditJiluId(item) && this.hasShenheDanhao(item);
|
||||
},
|
||||
|
||||
/** 待收款是否可点击:状态6 + 审核记录ID + 审核单号 缺一不可 */
|
||||
canCollectRecord(item) {
|
||||
return this.parseZhuangtai(item) === TX_STATUS.DAI_SHOUKUAN
|
||||
&& this.hasAuditJiluId(item)
|
||||
&& this.hasShenheDanhao(item);
|
||||
},
|
||||
|
||||
getLeixingLabel(leixing) {
|
||||
return LEIXING_LABEL[parseInt(leixing)] || '提现';
|
||||
},
|
||||
|
||||
getStatusBadgeClass(status) {
|
||||
switch (parseInt(status)) {
|
||||
case TX_STATUS.SHENHEZHONG: return 'status-wait';
|
||||
case TX_STATUS.TIXIAN_CHENGGONG:
|
||||
case TX_STATUS.SHENHE_CHENGGONG: return 'status-done';
|
||||
case TX_STATUS.DAI_SHOUKUAN: return 'status-pending';
|
||||
case TX_STATUS.TIXIAN_SHIBAI:
|
||||
case TX_STATUS.SHENHE_SHIBAI: return 'status-fail';
|
||||
default: return 'status-wait';
|
||||
}
|
||||
},
|
||||
|
||||
processRecordItem(item) {
|
||||
item = this.normalizeRecordFields(item);
|
||||
const isNew = this.isNewAuditRecord(item);
|
||||
const status = this.parseZhuangtai(item);
|
||||
let statusText = '未知';
|
||||
let canCollect = false;
|
||||
let canShowDetail = false;
|
||||
let detailReason = '';
|
||||
|
||||
switch (status) {
|
||||
case TX_STATUS.SHENHEZHONG: statusText = '审核中'; break;
|
||||
case TX_STATUS.TIXIAN_CHENGGONG: statusText = '提现成功'; break;
|
||||
case TX_STATUS.TIXIAN_SHIBAI:
|
||||
statusText = '提现失败';
|
||||
if (item.fail_reason || item.bhliyou) {
|
||||
canShowDetail = true;
|
||||
detailReason = item.fail_reason || item.bhliyou;
|
||||
}
|
||||
break;
|
||||
case TX_STATUS.SHENHE_CHENGGONG: statusText = '审核成功'; break;
|
||||
case TX_STATUS.SHENHE_SHIBAI:
|
||||
statusText = '审核失败';
|
||||
if (item.bhliyou) { canShowDetail = true; detailReason = item.bhliyou; }
|
||||
break;
|
||||
case TX_STATUS.DAI_SHOUKUAN:
|
||||
statusText = '待收款';
|
||||
canCollect = this.canCollectRecord(item);
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
isNewAudit: isNew,
|
||||
leixingLabel: this.getLeixingLabel(item.leixing),
|
||||
statusText,
|
||||
statusBadgeClass: this.getStatusBadgeClass(status),
|
||||
canCollect,
|
||||
canShowDetail,
|
||||
detailReason,
|
||||
};
|
||||
},
|
||||
|
||||
gengxinYue(data, leixing) {
|
||||
if (!data) return;
|
||||
if (data.new_yongjin !== undefined && data.new_yongjin !== null) {
|
||||
@@ -239,51 +93,79 @@ Component({
|
||||
}
|
||||
},
|
||||
|
||||
updatePendingCollectFlag(list) {
|
||||
const hasPending = (list || []).some(item => item.canCollect);
|
||||
if (hasPending !== this.data.hasPendingCollect) {
|
||||
this.setData({ hasPendingCollect: hasPending });
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
iconWechat: `${imgDir}icon_wechat.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.tixianleixing = selected.leixing;
|
||||
patch.feeRateText = selected.rateText;
|
||||
}
|
||||
if (opts.amount && parseFloat(opts.amount) > 0) {
|
||||
const amt = parseFloat(opts.amount);
|
||||
const max = selected ? parseFloat(selected.amount) : amt;
|
||||
patch.tixianjine = Math.min(amt, max).toFixed(2);
|
||||
}
|
||||
if (Object.keys(patch).length) {
|
||||
this.setData(patch, () => {
|
||||
this.recalcFee(this.data.tixianjine, this.data.selectedAsset);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/** 微信确认收款成功后,本地先把对应记录标为「提现成功」 */
|
||||
markLocalRecordWithdrawSuccess(record) {
|
||||
if (!record) return;
|
||||
const matchId = String(record.tixianjilu_id || record.id || '');
|
||||
const matchDanhao = String(record.shenhe_danhao || '').trim();
|
||||
if (!matchId && !matchDanhao) return;
|
||||
|
||||
const newList = (this.data.recordList || []).map((item) => {
|
||||
const itemId = String(item.tixianjilu_id || item.id || '');
|
||||
const itemDanhao = String(item.shenhe_danhao || '').trim();
|
||||
const isMatch = (matchId && itemId === matchId)
|
||||
|| (matchDanhao && itemDanhao === matchDanhao);
|
||||
if (!isMatch) return item;
|
||||
return this.processRecordItem({
|
||||
...item,
|
||||
zhuangtai: TX_STATUS.TIXIAN_CHENGGONG,
|
||||
});
|
||||
});
|
||||
this.setData({ recordList: newList });
|
||||
this.updatePendingCollectFlag(newList);
|
||||
},
|
||||
|
||||
async finishWxCollectSuccess(record) {
|
||||
this.markLocalRecordWithdrawSuccess(record);
|
||||
await this.loadAllAssets();
|
||||
await this.huoquJilu(true, true);
|
||||
// 后端若尚未落库,刷新后仍可能显示待收款,再覆盖一次本地成功态
|
||||
this.markLocalRecordWithdrawSuccess(record);
|
||||
PopupService.checkAndShow(this, 'tixianchenggong');
|
||||
wx.showToast({
|
||||
title: '提现成功',
|
||||
icon: 'success',
|
||||
duration: 3000,
|
||||
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 jine = this.data.tixianjine;
|
||||
const max = parseFloat(asset.amount);
|
||||
if (jine && parseFloat(jine) > max) {
|
||||
jine = asset.amount;
|
||||
}
|
||||
this.setData({
|
||||
selectedAsset: asset,
|
||||
tixianleixing: asset.leixing,
|
||||
tixianjine: jine,
|
||||
});
|
||||
this.recalcFee(jine, asset);
|
||||
},
|
||||
|
||||
async loadAllAssets() {
|
||||
this.setData({ isLoadingAssets: true });
|
||||
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) {
|
||||
@@ -298,6 +180,7 @@ Component({
|
||||
label: cfg.label,
|
||||
amount: parseFloat(amount).toFixed(2),
|
||||
rate: rate || 0,
|
||||
rateText: this.formatRatePercent(rate || 0),
|
||||
});
|
||||
};
|
||||
pushAsset('dashou_yue', data.dashou_yue, data.dashou_rate);
|
||||
@@ -307,63 +190,114 @@ Component({
|
||||
pushAsset('zuzhang_fenyong', data.zuzhang_fenyong, data.zuzhang_rate);
|
||||
pushAsset('kaoheguan_fenyong', data.kaoheguan_fenyong, data.kaoheguan_rate);
|
||||
|
||||
let total = 0;
|
||||
assets.forEach(item => { total += parseFloat(item.amount); });
|
||||
this.setData({ assetList: assets, totalAmount: total.toFixed(2), isLoadingAssets: false });
|
||||
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.tixianjine, null);
|
||||
}
|
||||
} else {
|
||||
throw new Error(res?.data?.msg || '获取资产失败');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('loadAllAssets', err);
|
||||
this.setData({ isLoadingAssets: false });
|
||||
this.setData({ isLoadingAssets: false, totalAmount: '0.00', canWithdraw: false, assetList: [] });
|
||||
}
|
||||
},
|
||||
|
||||
chushihuashuju() {
|
||||
this.loadAllAssets();
|
||||
this.huoquJilu(true);
|
||||
formatRatePercent(rate) {
|
||||
const r = parseFloat(rate) || 0;
|
||||
if (r <= 1 && r > 0) return `${(r * 100).toFixed(0)}%`;
|
||||
return `${r}%`;
|
||||
},
|
||||
|
||||
/** 点击资产卡片(与 mode1 一致) */
|
||||
onSelectAsset(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const asset = this.data.assetList[index];
|
||||
if (!asset || parseFloat(asset.amount) <= 0) {
|
||||
wx.showToast({ title: '无可提现金额', icon: 'none' });
|
||||
recalcFee(amountStr, asset) {
|
||||
const amount = parseFloat(amountStr);
|
||||
if (!amountStr || isNaN(amount) || amount <= 0 || !asset) {
|
||||
this.setData({
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
feeRateText: asset ? this.formatRatePercent(asset.rate) : this.data.feeRateText,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const rate = parseFloat(asset.rate) || 0;
|
||||
const fee = amount * rate;
|
||||
const actual = amount - fee;
|
||||
this.setData({
|
||||
selectedAsset: asset,
|
||||
tixianleixing: asset.leixing,
|
||||
currentRate: asset.rate,
|
||||
tixianjine: '',
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
showTixian: true,
|
||||
shouxufei: fee.toFixed(2),
|
||||
shijidaozhang: actual.toFixed(2),
|
||||
feeRateText: this.formatRatePercent(rate),
|
||||
currentRate: this.formatRatePercent(rate),
|
||||
});
|
||||
},
|
||||
|
||||
onJineInput(e) {
|
||||
this.setData({ tixianjine: e.detail.value, shouxufei: '0.00', shijidaozhang: '0.00' });
|
||||
const val = e.detail.value;
|
||||
this.setData({ tixianjine: val });
|
||||
this.recalcFee(val, this.data.selectedAsset);
|
||||
},
|
||||
|
||||
onQuickAmountTap(e) {
|
||||
const value = e.currentTarget.dataset.value;
|
||||
this.setData({ tixianjine: value.toString(), shouxufei: '0.00', shijidaozhang: '0.00' });
|
||||
onWithdrawAll() {
|
||||
const { selectedAsset } = this.data;
|
||||
if (!selectedAsset) {
|
||||
wx.showToast({ title: '请先选择提现账户', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const max = selectedAsset.amount;
|
||||
this.setData({ tixianjine: max });
|
||||
this.recalcFee(max, selectedAsset);
|
||||
},
|
||||
|
||||
onStatusFilterTap(e) {
|
||||
const value = parseInt(e.currentTarget.dataset.value);
|
||||
if (value === this.data.currentStatusFilter) return;
|
||||
this.setData({ currentStatusFilter: value });
|
||||
this.huoquJilu(true);
|
||||
onTapWithdraw() {
|
||||
if (this.data.submitting) return;
|
||||
if (!this.hasAnyWithdrawable(this.data.assetList)) {
|
||||
wx.showToast({ title: '暂无可提现余额', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const { selectedAsset, tixianjine } = this.data;
|
||||
if (!selectedAsset) {
|
||||
wx.showToast({ title: '请先选择要提现的账户', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const jineValue = parseFloat(tixianjine);
|
||||
if (!tixianjine || isNaN(jineValue) || jineValue <= 0) {
|
||||
wx.showToast({ title: '请输入有效金额', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (jineValue <= 0.1) {
|
||||
wx.showToast({ title: '提现金额须大于0.1元', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (jineValue > parseFloat(selectedAsset.amount)) {
|
||||
wx.showToast({ title: `超过${selectedAsset.label}可提余额`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.applyIdentityAndConfirm(selectedAsset);
|
||||
},
|
||||
|
||||
applyIdentityAndConfirm(asset) {
|
||||
this.recalcFee(this.data.tixianjine, asset);
|
||||
this.setData({
|
||||
selectedAsset: asset,
|
||||
tixianleixing: asset.leixing,
|
||||
currentRate: this.formatRatePercent(asset.rate),
|
||||
showTixian: true,
|
||||
});
|
||||
},
|
||||
|
||||
async onConfirmTixian() {
|
||||
if (this.data.submitting) return;
|
||||
const { tixianleixing, tixianjine, selectedAsset } = this.data;
|
||||
if (!tixianleixing || !selectedAsset) {
|
||||
wx.showToast({ title: '请选择提现类型', icon: 'none' });
|
||||
wx.showToast({ title: '请选择提现身份', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const jineValue = parseFloat(tixianjine);
|
||||
@@ -372,7 +306,7 @@ Component({
|
||||
return;
|
||||
}
|
||||
if (jineValue > parseFloat(selectedAsset.amount)) {
|
||||
wx.showToast({ title: `超过可提${selectedAsset.label}`, icon: 'none' });
|
||||
wx.showToast({ title: `超过${selectedAsset.label}可提余额`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -381,24 +315,30 @@ Component({
|
||||
const res = await request({
|
||||
url: '/yonghu/zddksh',
|
||||
method: 'POST',
|
||||
data: { leixing: tixianleixing, jine: jineValue.toFixed(2) }
|
||||
data: { leixing: tixianleixing, jine: jineValue.toFixed(2) },
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data || {};
|
||||
this.gengxinYue(data, tixianleixing);
|
||||
if (data.shouxufei !== undefined) {
|
||||
this.setData({
|
||||
shouxufei: parseFloat(data.shouxufei || 0).toFixed(2),
|
||||
shijidaozhang: parseFloat(data.shijidaozhang || 0).toFixed(2),
|
||||
});
|
||||
}
|
||||
this.setData({ showTixian: false, submitting: false, selectedAsset: null });
|
||||
this.setData({
|
||||
showTixian: false,
|
||||
submitting: false,
|
||||
selectedAsset: null,
|
||||
tixianjine: '',
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
});
|
||||
await this.loadAllAssets();
|
||||
this.huoquJilu(true);
|
||||
wx.showModal({
|
||||
title: '申请已提交',
|
||||
content: '您的提现申请已提交,请等待后台审核。审核通过后,请在本页「提现记录」中点击「收款」按钮,主动确认后才能到账微信零钱。',
|
||||
showCancel: false,
|
||||
title: '申请成功',
|
||||
content: '提现申请已提交,请前往「提现记录」查看进度;审核通过后可在该页点击「收款」确认到账。',
|
||||
confirmText: '查看提现记录',
|
||||
cancelText: '知道了',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.navigateTo({ url: '/pages/withdraw/withdraw-records' });
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
wx.showModal({ title: '提现申请失败', content: res.data?.msg || '未知错误', showCancel: false });
|
||||
@@ -410,233 +350,20 @@ Component({
|
||||
}
|
||||
},
|
||||
|
||||
onCollectTap(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const record = this.data.recordList[index];
|
||||
if (!record) return;
|
||||
if (this.parseZhuangtai(record) !== TX_STATUS.DAI_SHOUKUAN) {
|
||||
wx.showToast({ title: '当前状态不可收款', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!this.hasShenheDanhao(record) || !this.hasAuditJiluId(record)) {
|
||||
wx.showToast({ title: '审核信息不完整,请刷新后重试', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
onCloseTixian() {
|
||||
if (this.data.submitting) {
|
||||
wx.showToast({ title: '正在处理中,请稍后', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({ showCollectConfirm: true, collectConfirmRecord: record });
|
||||
},
|
||||
|
||||
onCloseCollectConfirm() {
|
||||
if (this.data.submitting) return;
|
||||
this.setData({ showCollectConfirm: false, collectConfirmRecord: null });
|
||||
},
|
||||
|
||||
async onConfirmCollect() {
|
||||
if (this.data.submitting) return;
|
||||
let record = this.data.collectConfirmRecord;
|
||||
if (!record) return;
|
||||
|
||||
if (!this.canCollectRecord(record)) {
|
||||
await this.huoquJilu(true, true);
|
||||
const refreshed = (this.data.recordList || []).find(
|
||||
r => String(r.id) === String(record.id)
|
||||
|| String(r.tixianjilu_id) === String(record.tixianjilu_id)
|
||||
);
|
||||
if (refreshed) record = refreshed;
|
||||
}
|
||||
if (!this.canCollectRecord(record)) {
|
||||
wx.showModal({
|
||||
title: '暂时无法收款',
|
||||
content: '缺少审核单号或审核记录ID,请下拉刷新后重试。仍不行请联系客服。',
|
||||
showCancel: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ showCollectConfirm: false, submitting: true, collectConfirmRecord: record });
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixiansq',
|
||||
method: 'POST',
|
||||
data: {
|
||||
shenhe_danhao: record.shenhe_danhao,
|
||||
shenhe_jilu_id: record.shenhe_jilu_id || '',
|
||||
tixianjilu_id: record.tixianjilu_id || record.id || '',
|
||||
leixing: record.leixing,
|
||||
}
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data;
|
||||
this.setData({
|
||||
currentTixianId: data.tixian_id,
|
||||
mchId: data.mch_id || '',
|
||||
collectConfirmRecord: record,
|
||||
});
|
||||
this.tiaoqiWeixinQueRen(data.package_info);
|
||||
} else {
|
||||
wx.showModal({ title: '收款失败', content: res.data?.msg || '无法发起收款,请稍后重试', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
}
|
||||
} catch (err) {
|
||||
wx.showModal({ title: '网络错误', content: '网络连接失败,请稍后重试', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
}
|
||||
},
|
||||
|
||||
tiaoqiWeixinQueRen(packageInfo) {
|
||||
const appId = app.globalData.appId;
|
||||
const mchId = this.data.mchId;
|
||||
if (!appId || !mchId) {
|
||||
wx.showModal({ title: '配置错误', content: '无法调起收款,请联系客服', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
return;
|
||||
}
|
||||
wx.requestMerchantTransfer({
|
||||
appId, mchId, package: packageInfo,
|
||||
success: () => { this.tongzhiHouduanQueRen(1); },
|
||||
fail: () => {
|
||||
this.tongzhiHouduanQueRen(0);
|
||||
wx.showModal({
|
||||
title: '确认收款失败',
|
||||
content: '微信收款确认失败,您可在记录中再次点击「收款」重试。',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async tongzhiHouduanQueRen(result) {
|
||||
if (!this.data.currentTixianId) {
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
return;
|
||||
}
|
||||
const record = this.data.collectConfirmRecord;
|
||||
const wxConfirmed = result === 1;
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixianqr',
|
||||
method: 'POST',
|
||||
data: {
|
||||
tixian_id: this.data.currentTixianId,
|
||||
result: result,
|
||||
shenhe_danhao: record ? record.shenhe_danhao : '',
|
||||
shenhe_jilu_id: record ? (record.shenhe_jilu_id || '') : '',
|
||||
tixianjilu_id: record ? (record.tixianjilu_id || record.id || '') : '',
|
||||
leixing: record ? record.leixing : '',
|
||||
}
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data || {};
|
||||
this.gengxinYue(data, record ? record.leixing : null);
|
||||
}
|
||||
|
||||
// 微信已确认收款:不论 tixianqr 返回什么,都刷新列表,不弹系统异常
|
||||
if (wxConfirmed) {
|
||||
await this.finishWxCollectSuccess(record);
|
||||
} else if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
await this.loadAllAssets();
|
||||
this.huoquJilu(true);
|
||||
wx.showToast({
|
||||
title: '收款已取消',
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
});
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '确认状态失败',
|
||||
content: res.data?.msg || '操作失败',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (wxConfirmed) {
|
||||
await this.finishWxCollectSuccess(record);
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '网络错误',
|
||||
content: '网络连接失败',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
this.setData({ submitting: false, currentTixianId: null, collectConfirmRecord: null });
|
||||
}
|
||||
},
|
||||
|
||||
onViewDetail(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const record = this.data.recordList[index];
|
||||
if (!record || !record.canShowDetail) return;
|
||||
const status = parseInt(record.zhuangtai);
|
||||
let detailTitle = '失败原因';
|
||||
if (status === TX_STATUS.SHENHE_SHIBAI) detailTitle = '审核失败原因';
|
||||
else if (status === TX_STATUS.TIXIAN_SHIBAI) detailTitle = '提现失败原因';
|
||||
this.setData({
|
||||
showDetailModal: true,
|
||||
detailTitle,
|
||||
detailContent: record.detailReason || '暂无详细信息',
|
||||
showTixian: false,
|
||||
selectedAsset: null,
|
||||
tixianleixing: null,
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
});
|
||||
},
|
||||
|
||||
onCloseDetailModal() {
|
||||
this.setData({ showDetailModal: false, detailTitle: '', detailContent: '' });
|
||||
},
|
||||
|
||||
onCloseTixian() {
|
||||
if (this.data.submitting) { wx.showToast({ title: '正在处理中,请稍后', icon: 'none' }); return; }
|
||||
this.setData({
|
||||
showTixian: false, selectedAsset: null, tixianleixing: null,
|
||||
tixianjine: '', shouxufei: '0.00', shijidaozhang: '0.00', submitting: false,
|
||||
});
|
||||
},
|
||||
|
||||
async huoquJilu(fresh = false, force = false) {
|
||||
const now = Date.now();
|
||||
if (!force && now - lastPullDownTime < 2000 && !fresh) return;
|
||||
if (!force && (this.data.loading || this.data.isRefreshing)) return;
|
||||
const page = fresh ? 1 : this.data.page;
|
||||
if (fresh) this.setData({ nomore: false, canloadmore: true, isRefreshing: true });
|
||||
if (this.data.nomore && !fresh) return;
|
||||
this.setData({ loading: true });
|
||||
lastPullDownTime = now;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixianjiluhq',
|
||||
method: 'POST',
|
||||
data: { page, limit: yemianshuju, mode: 2, zhuangtai: this.data.currentStatusFilter }
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data;
|
||||
const processedList = (data.list || []).map(item => this.processRecordItem(item));
|
||||
const newList = fresh ? processedList : [...this.data.recordList, ...processedList];
|
||||
this.setData({
|
||||
recordList: newList,
|
||||
page: page + 1,
|
||||
nomore: !(data.has_more === true),
|
||||
canloadmore: data.has_more === true,
|
||||
loading: false,
|
||||
isRefreshing: false,
|
||||
});
|
||||
this.updatePendingCollectFlag(newList);
|
||||
} else {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
} catch (err) {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.canloadmore && !this.data.nomore && !this.data.loading && !this.data.isRefreshing) {
|
||||
const now = Date.now();
|
||||
if (now - lastPullDownTime >= PULL_DOWN_INTERVAL) this.huoquJilu();
|
||||
}
|
||||
},
|
||||
|
||||
stopPropagation() {}
|
||||
}
|
||||
stopPropagation() {},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,113 +1,91 @@
|
||||
<!-- mode2 自动打款 - UI 与 mode1 手动提现完全一致,逻辑为自动审核收款 -->
|
||||
<view class="app">
|
||||
<image class="global-bg" src="{{imgUrls.pageBg}}" mode="aspectFill" />
|
||||
|
||||
<!-- 资产区域(与 mode1 相同) -->
|
||||
<view class="assets-section">
|
||||
<view class="main-card" style="background-image: url('{{imgUrls.cardBg}}'); background-size: cover;">
|
||||
<view class="balance-wrap">
|
||||
<text class="balance-label">可提总余额</text>
|
||||
<text class="balance-value">¥{{totalAmount}}</text>
|
||||
</view>
|
||||
<view class="inner-divider"></view>
|
||||
<text class="assets-hint">← 左右滑动查看更多资产 →</text>
|
||||
<scroll-view class="assets-scroll" scroll-x="true" show-scrollbar="{{false}}" enhanced>
|
||||
<view class="assets-track">
|
||||
<block wx:for="{{assetList}}" wx:key="type">
|
||||
<view
|
||||
class="asset-tile"
|
||||
bindtap="onSelectAsset"
|
||||
data-index="{{index}}"
|
||||
style="background-image: url('{{imgUrls.assetTileBg}}'); background-size: cover; background-position: center;"
|
||||
>
|
||||
<text class="asset-name">{{item.label}}</text>
|
||||
<text class="asset-balance">¥{{item.amount}}</text>
|
||||
<text class="asset-fee">费率 {{item.rate}}%</text>
|
||||
</view>
|
||||
</block>
|
||||
<view wx:if="{{assetList.length === 0 && !isLoadingAssets}}" class="assets-empty">暂无可用资金</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- mode2 自动打款 - 参考逍遥梦样式(仅微信零钱) -->
|
||||
<view class="ref-page">
|
||||
<!-- 提现方式:仅微信 -->
|
||||
<view class="method-card">
|
||||
<view class="method-tab method-tab--active">
|
||||
<image class="method-tab-icon" src="{{imgUrls.iconWechat}}" mode="aspectFit" />
|
||||
<text class="method-tab-text">微信零钱</text>
|
||||
<view class="method-tab-line"></view>
|
||||
</view>
|
||||
<view class="divider-line"></view>
|
||||
</view>
|
||||
|
||||
<!-- 提现记录区(mode1 布局 + 自动打款筛选/收款) -->
|
||||
<view class="history-section">
|
||||
<view class="history-header">
|
||||
<text class="history-title">提现记录</text>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{hasPendingCollect}}" class="pending-tip">
|
||||
您有审核通过的提现待收款,请点击「收款」按钮,在微信中主动确认后才能到账。
|
||||
</view>
|
||||
|
||||
<scroll-view class="filter-scroll" scroll-x show-scrollbar="{{false}}">
|
||||
<view class="filter-track">
|
||||
<view
|
||||
wx:for="{{statusTabs}}"
|
||||
wx:key="value"
|
||||
class="filter-chip {{currentStatusFilter == item.value ? 'active' : ''}}"
|
||||
bindtap="onStatusFilterTap"
|
||||
data-value="{{item.value}}"
|
||||
>{{item.label}}</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>
|
||||
|
||||
<scroll-view class="history-scroll" scroll-y enable-back-to-top bindscrolltolower="onReachBottom">
|
||||
<view wx:for="{{recordList}}" wx:key="index" class="history-item">
|
||||
<view class="history-info">
|
||||
<text class="history-amount">¥{{item.jine}}</text>
|
||||
<text class="history-time">{{item.create}}</text>
|
||||
</view>
|
||||
<view class="history-detail">
|
||||
<text class="history-method">微信零钱</text>
|
||||
<text class="history-type">{{item.leixingLabel}}</text>
|
||||
</view>
|
||||
<view class="history-status">
|
||||
<!-- 待收款:整块可点击 → 弹出确认收款弹窗 → 用户确认后才请求后端 -->
|
||||
<view
|
||||
wx:if="{{item.canCollect}}"
|
||||
class="status-badge status-pending collect-tappable"
|
||||
bindtap="onCollectTap"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
<text>{{item.statusText}}</text>
|
||||
<text class="collect-sub">点击收款</text>
|
||||
</view>
|
||||
<view wx:elif="{{item.canShowDetail}}" class="status-badge status-fail">
|
||||
{{item.statusText}}
|
||||
<text class="fail-link" bindtap="onViewDetail" data-index="{{index}}">详情</text>
|
||||
</view>
|
||||
<view wx:else class="status-badge {{item.statusBadgeClass}}">{{item.statusText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{loading}}" class="load-tip">加载中...</view>
|
||||
<view wx:if="{{nomore && recordList.length > 0}}" class="more-tip">—— 没有更多了 ——</view>
|
||||
<view wx:if="{{!nomore && recordList.length > 0}}" class="load-more-btn" bindtap="onReachBottom">加载更多记录</view>
|
||||
<view wx:if="{{recordList.length === 0 && !loading}}" class="load-tip">暂无提现记录</view>
|
||||
</scroll-view>
|
||||
<text wx:if="{{!selectedAsset}}" class="account-warn">请先选择上方提现账户</text>
|
||||
<text wx:else class="account-ok">当前:{{selectedAsset.label}}</text>
|
||||
</view>
|
||||
|
||||
<view class="safe-bottom"></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="{{tixianjine}}"
|
||||
bindinput="onJineInput"
|
||||
/>
|
||||
<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>
|
||||
|
||||
<!-- 申请提现弹窗(mode1 样式,无收款方式) -->
|
||||
<!-- 确认提现弹窗 -->
|
||||
<view wx:if="{{showTixian}}" class="modal-mask" bindtap="onCloseTixian">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">申请提现</view>
|
||||
<view class="modal-header">确认提现</view>
|
||||
<view class="modal-body">
|
||||
<view class="auto-tip">提交后需等待审核,审核通过后请在本页点击「收款」确认到账</view>
|
||||
<view class="info-row"><text>项目</text><text>{{selectedAsset.label}}</text></view>
|
||||
<view class="auto-tip">提交后需等待审核,审核通过后请在「提现记录」中点击「收款」确认到账</view>
|
||||
<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="amount-row">
|
||||
<text>金额</text>
|
||||
<input type="digit" placeholder="0.00" value="{{tixianjine}}" bindinput="onJineInput" />
|
||||
</view>
|
||||
<view class="quick-row">
|
||||
<view wx:for="{{[100,200,500,1000]}}" wx:key="item" class="quick-chip" data-value="{{item}}" bindtap="onQuickAmountTap">¥{{item}}</view>
|
||||
</view>
|
||||
<view class="info-row"><text>费率</text><text>{{currentRate}}</text></view>
|
||||
<view class="info-row"><text>提现金额</text><text>¥{{tixianjine}}</text></view>
|
||||
<view class="fee-row">
|
||||
<text>手续费 ¥{{shouxufei}}</text>
|
||||
<text>到账 ¥{{shijidaozhang}}</text>
|
||||
@@ -120,33 +98,5 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 收款确认弹窗 -->
|
||||
<view wx:if="{{showCollectConfirm}}" class="modal-mask" bindtap="onCloseCollectConfirm">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">确认收款</view>
|
||||
<view class="modal-body">
|
||||
<view class="auto-tip">审核已通过,{{collectConfirmRecord.leixingLabel}} ¥{{collectConfirmRecord.jine}}</view>
|
||||
<view>请点击「去收款」,然后在微信弹窗中主动确认,资金才会打入您的微信零钱。</view>
|
||||
<view class="warn-tip" wx:if="{{collectConfirmRecord.shenhe_danhao}}">审核单号:{{collectConfirmRecord.shenhe_danhao}}</view>
|
||||
<view class="warn-tip">注意:审核通过≠已到账,必须您本人点击确认才能完成收款!</view>
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel" bindtap="onCloseCollectConfirm">稍后再说</view>
|
||||
<view class="modal-btn confirm" bindtap="onConfirmCollect">{{submitting ? '处理中...' : '去收款'}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 失败/驳回详情弹窗 -->
|
||||
<view wx:if="{{showDetailModal}}" class="modal-mask" bindtap="onCloseDetailModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">{{detailTitle}}</view>
|
||||
<view class="modal-body">{{detailContent}}</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn confirm" bindtap="onCloseDetailModal">知道了</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
<popup-notice id="popupNotice" />
|
||||
|
||||
@@ -1,408 +1,325 @@
|
||||
/* mode2 自动打款 - UI 完全复用 mode1 样式 */
|
||||
|
||||
page {
|
||||
background-color: #f5f7fb;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding: 0 24rpx 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.global-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
opacity: 0.1;
|
||||
object-fit: cover;
|
||||
filter: blur(1rpx);
|
||||
}
|
||||
|
||||
.assets-section {
|
||||
margin-top: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.main-card {
|
||||
background: rgba(248, 250, 252, 0.88);
|
||||
backdrop-filter: blur(28rpx);
|
||||
-webkit-backdrop-filter: blur(28rpx);
|
||||
border-radius: 48rpx;
|
||||
padding: 30rpx 28rpx 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.04);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.4);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.balance-wrap {
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.balance-label {
|
||||
font-size: 28rpx;
|
||||
color: #0f172a;
|
||||
letter-spacing: 1px;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
font-weight: 700;
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.8);
|
||||
}
|
||||
.balance-value {
|
||||
font-size: 68rpx;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
font-family: 'DIN', monospace;
|
||||
letter-spacing: -1rpx;
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
.inner-divider {
|
||||
width: 60%;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #64748b, #64748b, transparent);
|
||||
margin: 0 auto 20rpx auto;
|
||||
border-radius: 2rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.assets-hint {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #334155;
|
||||
margin-bottom: 14rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.assets-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.assets-track {
|
||||
display: inline-flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.asset-tile {
|
||||
width: 170rpx;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
backdrop-filter: blur(8rpx);
|
||||
border-radius: 28rpx;
|
||||
padding: 18rpx 12rpx;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.02);
|
||||
transition: all 0.2s;
|
||||
white-space: normal;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.asset-tile:active {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.asset-name {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 10rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.5);
|
||||
}
|
||||
.asset-balance {
|
||||
font-size: 28rpx;
|
||||
font-weight: 800;
|
||||
color: #2d6a4f;
|
||||
font-family: monospace;
|
||||
margin-bottom: 6rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.asset-fee {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.assets-empty {
|
||||
width: 400rpx;
|
||||
text-align: center;
|
||||
color: #a0abb9;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #cbd5e1, #cbd5e1, transparent);
|
||||
margin: 16rpx 0 20rpx;
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.history-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 0 8rpx 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.history-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
}
|
||||
.history-scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 28rpx 0;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.history-info { width: 160rpx; }
|
||||
.history-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
display: block;
|
||||
}
|
||||
.history-time {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-detail {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.history-method {
|
||||
font-size: 30rpx;
|
||||
color: #334155;
|
||||
display: block;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
.history-type {
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-status { text-align: right; }
|
||||
|
||||
.status-badge {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
padding: 6rpx 14rpx;
|
||||
border-radius: 30rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
.status-wait {
|
||||
color: #f59e0b;
|
||||
background: rgba(245,158,11,0.1);
|
||||
}
|
||||
.status-done {
|
||||
color: #10b981;
|
||||
background: rgba(16,185,129,0.1);
|
||||
}
|
||||
.status-fail {
|
||||
color: #ef4444;
|
||||
background: rgba(239,68,68,0.1);
|
||||
}
|
||||
.status-pending {
|
||||
color: #3b82f6;
|
||||
background: rgba(59,130,246,0.1);
|
||||
}
|
||||
.fail-link {
|
||||
margin-left: 8rpx;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.collect-tappable {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
padding: 10rpx 18rpx;
|
||||
cursor: pointer;
|
||||
border: 2rpx solid rgba(59,130,246,0.35);
|
||||
box-shadow: 0 4rpx 12rpx rgba(59,130,246,0.15);
|
||||
}
|
||||
.collect-tappable:active {
|
||||
transform: scale(0.97);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.collect-sub {
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #1d4ed8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.load-tip, .more-tip {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.load-more-btn {
|
||||
margin: 16rpx 0 20rpx;
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
background: rgba(255,255,255,0.7);
|
||||
backdrop-filter: blur(8rpx);
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
color: #3b82f6;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
}
|
||||
.load-more-btn:active { background: rgba(255,255,255,0.9); }
|
||||
.safe-bottom { height: 12rpx; flex-shrink: 0; }
|
||||
|
||||
/* 自动打款专属(少量追加) */
|
||||
.pending-tip {
|
||||
margin: 0 8rpx 16rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #1d4ed8;
|
||||
background: rgba(59,130,246,0.08);
|
||||
border-radius: 20rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.filter-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.filter-track {
|
||||
display: inline-flex;
|
||||
gap: 12rpx;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
.filter-chip {
|
||||
flex-shrink: 0;
|
||||
padding: 10rpx 22rpx;
|
||||
font-size: 24rpx;
|
||||
color: #64748b;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius: 30rpx;
|
||||
border: 1rpx solid rgba(0,0,0,0.06);
|
||||
}
|
||||
.filter-chip.active {
|
||||
color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
.auto-tip {
|
||||
font-size: 24rpx;
|
||||
color: #3b82f6;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.warn-tip {
|
||||
font-size: 24rpx;
|
||||
color: #f59e0b;
|
||||
margin-top: 16rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 弹窗(与 mode1 一致) */
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.modal-dialog {
|
||||
width: 600rpx;
|
||||
background: rgba(255,255,255,0.96);
|
||||
backdrop-filter: blur(20rpx);
|
||||
border-radius: 48rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20rpx 40rpx rgba(0,0,0,0.1);
|
||||
border: 1rpx solid rgba(255,255,255,0.6);
|
||||
}
|
||||
.modal-header {
|
||||
padding: 36rpx 32rpx 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-body {
|
||||
padding: 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #334155;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.info-row, .amount-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.amount-row input {
|
||||
border: 1rpx solid rgba(0,0,0,0.1);
|
||||
border-radius: 28rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
width: 260rpx;
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.quick-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin: 24rpx 0;
|
||||
}
|
||||
.quick-chip {
|
||||
flex: 1;
|
||||
background: rgba(241,245,249,0.8);
|
||||
text-align: center;
|
||||
padding: 12rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: rgba(248,250,252,0.8);
|
||||
padding: 20rpx;
|
||||
border-radius: 28rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
border-top: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.modal-btn.cancel {
|
||||
color: #8f9bb3;
|
||||
border-right: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn.confirm { color: #3b82f6; }
|
||||
|
||||
background: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.ref-page {
|
||||
min-height: 100vh;
|
||||
padding: 24rpx 24rpx 48rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 提现方式 Tab */
|
||||
.method-card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.method-tab {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 28rpx 16rpx 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.method-tab-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.method-tab-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.method-tab-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 80rpx;
|
||||
height: 6rpx;
|
||||
background: #FFD54F;
|
||||
border-radius: 3rpx;
|
||||
}
|
||||
|
||||
/* 账户选择 */
|
||||
.account-card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx 16rpx 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.account-scroll {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.account-chip {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16rpx 24rpx;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f8f8f8;
|
||||
border: 2rpx solid transparent;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
|
||||
.account-chip--active {
|
||||
background: #fffbeb;
|
||||
border-color: #FFD54F;
|
||||
}
|
||||
|
||||
.account-chip--disabled {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.chip-label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.chip-amount {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.account-warn {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #ff8c00;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
|
||||
.account-ok {
|
||||
display: block;
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
|
||||
/* 金额卡片 */
|
||||
.amount-card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 32rpx 28rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.avail-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.avail-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.avail-symbol {
|
||||
font-size: 28rpx;
|
||||
color: #ff8c00;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.avail-amount {
|
||||
font-size: 32rpx;
|
||||
color: #ff8c00;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.input-symbol {
|
||||
font-size: 64rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
line-height: 1;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.amount-input {
|
||||
flex: 1;
|
||||
font-size: 56rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
height: 80rpx;
|
||||
min-height: 80rpx;
|
||||
}
|
||||
|
||||
.amount-placeholder {
|
||||
color: #ccc;
|
||||
font-size: 40rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.withdraw-all {
|
||||
font-size: 28rpx;
|
||||
color: #ff8c00;
|
||||
padding: 8rpx 0 8rpx 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.input-divider {
|
||||
height: 1rpx;
|
||||
background: #eee;
|
||||
margin: 16rpx 0 20rpx;
|
||||
}
|
||||
|
||||
.fee-tip {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.fee-highlight {
|
||||
color: #ff8c00;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 确认按钮 */
|
||||
.submit-wrap {
|
||||
padding: 0 8rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
background: linear-gradient(90deg, #FFD54F 0%, #FFB300 100%);
|
||||
border-radius: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
box-shadow: 0 8rpx 20rpx rgba(255, 179, 0, 0.35);
|
||||
}
|
||||
|
||||
.confirm-btn:active {
|
||||
opacity: 0.92;
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
.confirm-btn--disabled {
|
||||
background: linear-gradient(90deg, #e0e0e0, #bdbdbd);
|
||||
box-shadow: none;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 须知 */
|
||||
.notice-box {
|
||||
background: #ebebeb;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx 28rpx 32rpx;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.notice-item {
|
||||
font-size: 26rpx;
|
||||
color: #555;
|
||||
line-height: 1.7;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
/* 确认弹窗 */
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 620rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 32rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.auto-tip {
|
||||
font-size: 24rpx;
|
||||
color: #ff8c00;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: #fff8e1;
|
||||
padding: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-top: 16rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.modal-btn.cancel {
|
||||
color: #999;
|
||||
border-right: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.modal-btn.confirm {
|
||||
color: #ff8c00;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
243
pages/withdraw/components/record-mode1/record-mode1.js
Normal file
243
pages/withdraw/components/record-mode1/record-mode1.js
Normal file
@@ -0,0 +1,243 @@
|
||||
// pages/withdraw/components/record-mode1/record-mode1.js
|
||||
// 子组件版本 - 完整代码,仅适配生命周期,业务逻辑不动
|
||||
|
||||
import request from '../../../../utils/request.js';
|
||||
import upload from '../../../../utils/upload.js';
|
||||
import PopupService from '../../../../services/popupService.js';
|
||||
|
||||
const app = getApp();
|
||||
const PAGE_SIZE = 10;
|
||||
let lastPullDownTime = 0;
|
||||
const PULL_DOWN_INTERVAL = 2000;
|
||||
|
||||
Component({
|
||||
data: {
|
||||
imgUrls: {
|
||||
pageBg: '',
|
||||
cardBg: '',
|
||||
iconWechat: '',
|
||||
iconAlipay: '',
|
||||
iconRecord: '',
|
||||
iconRefresh: '',
|
||||
},
|
||||
assetList: [],
|
||||
totalAmount: '0.00',
|
||||
selectedAsset: null,
|
||||
txfangshi: null,
|
||||
txdianhua: '',
|
||||
txzh: '',
|
||||
txtupian: '',
|
||||
ossImageUrl: '',
|
||||
showTixianModal: false,
|
||||
tixianAmount: '',
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
currentRate: '0.00',
|
||||
recordList: [],
|
||||
page: 1,
|
||||
nomore: false,
|
||||
loading: false,
|
||||
isRefreshing: false,
|
||||
canloadmore: true,
|
||||
showSkfsModal: false,
|
||||
tempTxfangshi: null,
|
||||
tempTxPhone: '',
|
||||
tempTxAccount: '',
|
||||
tempTxImage: '',
|
||||
choosingImage: false,
|
||||
showModifyModal: false,
|
||||
modifyingRecord: null,
|
||||
modifyTxfangshi: null,
|
||||
modifyTxPhone: '',
|
||||
modifyTxAccount: '',
|
||||
modifyTxImage: '',
|
||||
modifyImageUrl: '',
|
||||
showFailModal: false,
|
||||
currentFailReason: '',
|
||||
isLoading: false,
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.initImageUrls();
|
||||
this.loadWithdrawRecords(true);
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this.registerNotification();
|
||||
PopupService.checkAndShow(this, 'tixian');
|
||||
},
|
||||
hide() {
|
||||
const popup = this.selectComponent('#popupNotice');
|
||||
popup?.cleanup?.();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onPullDownRefresh() {
|
||||
return this.loadWithdrawRecords(true);
|
||||
},
|
||||
|
||||
onLoadMoreFromScroll() {
|
||||
this.loadMoreRecords();
|
||||
},
|
||||
|
||||
loadMoreRecords() {
|
||||
if (this.data.nomore) {
|
||||
wx.showToast({ title: '没有更多记录了', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (this.data.loading) return;
|
||||
this.loadWithdrawRecords();
|
||||
},
|
||||
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
pageBg: `${imgDir}page_bg.png`,
|
||||
cardBg: `${imgDir}card_bg.png`,
|
||||
iconWechat: `${imgDir}icon_wechat.png`,
|
||||
iconAlipay: `${imgDir}icon_alipay.png`,
|
||||
iconRecord: `${imgDir}icon_record.png`,
|
||||
iconRefresh: `${imgDir}icon_refresh.png`,
|
||||
assetTileBg: `${imgDir}asset_tile_bg.png`,
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async loadWithdrawRecords(refresh = false) {
|
||||
const now = Date.now();
|
||||
if (now - lastPullDownTime < PULL_DOWN_INTERVAL && !refresh) return;
|
||||
if (this.data.loading || this.data.isRefreshing) return;
|
||||
const page = refresh ? 1 : this.data.page;
|
||||
if (this.data.nomore && !refresh) return;
|
||||
this.setData({ loading: true, isRefreshing: refresh });
|
||||
lastPullDownTime = now;
|
||||
try {
|
||||
const res = await request({ url: '/yonghu/tixianjiluhq', method: 'POST', data: { page, limit: PAGE_SIZE } });
|
||||
if (res?.data?.code === 0) {
|
||||
const list = (res.data.data.list || []).map(item => ({
|
||||
...item,
|
||||
statusText: this.getStatusText(item.zhuangtai),
|
||||
statusColor: this.getStatusColor(item.zhuangtai)
|
||||
}));
|
||||
const newList = refresh ? list : [...this.data.recordList, ...list];
|
||||
const hasMore = res.data.data.has_more === true;
|
||||
this.setData({
|
||||
recordList: newList, page: page + 1, nomore: !hasMore, canloadmore: hasMore,
|
||||
loading: false, isRefreshing: false
|
||||
});
|
||||
} else {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
} catch (err) {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
},
|
||||
|
||||
onModifyRecord(e) {
|
||||
const record = e.currentTarget.dataset.record;
|
||||
if (parseInt(record.zhuangtai) !== 1) {
|
||||
wx.showToast({ title: '只有审核中的记录可修改', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({
|
||||
modifyingRecord: record,
|
||||
modifyTxfangshi: record.fangshi,
|
||||
modifyTxPhone: record.txdianhua || '',
|
||||
modifyTxAccount: record.txzh || '',
|
||||
modifyTxImage: '',
|
||||
modifyImageUrl: record.txtupian ? (app.globalData.ossImageUrl + record.txtupian) : '',
|
||||
showModifyModal: true
|
||||
});
|
||||
},
|
||||
|
||||
onSelectModifyFangshi(e) { this.setData({ modifyTxfangshi: e.currentTarget.dataset.fangshi }); },
|
||||
onModifyPhoneInput(e) { this.setData({ modifyTxPhone: e.detail.value }); },
|
||||
onModifyAccountInput(e) { this.setData({ modifyTxAccount: e.detail.value }); },
|
||||
|
||||
onChooseModifyImage() {
|
||||
if (this.data.choosingImage) return;
|
||||
this.setData({ choosingImage: true });
|
||||
wx.chooseMedia({
|
||||
count: 1, mediaType: ['image'],
|
||||
success: (res) => { this.setData({ modifyTxImage: res.tempFiles[0].tempFilePath }); },
|
||||
complete: () => { this.setData({ choosingImage: false }); }
|
||||
});
|
||||
},
|
||||
|
||||
onPreviewModifyImage() {
|
||||
if (this.data.modifyTxImage) wx.previewImage({ urls: [this.data.modifyTxImage] });
|
||||
else if (this.data.modifyImageUrl) wx.previewImage({ urls: [this.data.modifyImageUrl] });
|
||||
},
|
||||
|
||||
onDeleteModifyImage() { this.setData({ modifyTxImage: '' }); },
|
||||
|
||||
async onConfirmModify() {
|
||||
const { modifyTxfangshi, modifyTxPhone, modifyTxAccount, modifyTxImage, modifyingRecord } = this.data;
|
||||
if (!modifyTxfangshi) { wx.showToast({ title: '请选择提现方式', icon: 'none' }); return; }
|
||||
if (!modifyTxPhone) { wx.showToast({ title: '请输入收款人电话', icon: 'none' }); return; }
|
||||
if (modifyTxfangshi == 1 && !modifyTxImage) { wx.showToast({ title: '请上传微信收款码', icon: 'none' }); return; }
|
||||
if (modifyTxfangshi == 2 && !modifyTxAccount && !modifyTxImage) {
|
||||
wx.showToast({ title: '请填写支付宝账号或上传收款码', icon: 'none' }); return;
|
||||
}
|
||||
const formData = { tixian_id: modifyingRecord.id, fangshi: modifyTxfangshi, txdianhua: modifyTxPhone, txzh: modifyTxAccount || '' };
|
||||
try {
|
||||
const res = await upload({ url: '/yonghu/yonghutxshxg', formData, filePath: modifyTxImage || null, fileName: 'file' });
|
||||
if (res?.data?.code === 0) {
|
||||
const data = res.data.data;
|
||||
const newList = this.data.recordList.map(item => {
|
||||
if (item.id === modifyingRecord.id) {
|
||||
return { ...item, fangshi: modifyTxfangshi, txdianhua: modifyTxPhone, txzh: modifyTxAccount || '', txtupian: data.txtupian || modifyingRecord.txtupian };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
this.setData({ recordList: newList, showModifyModal: false, modifyingRecord: null });
|
||||
wx.showToast({ title: '修改成功', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: res?.data?.msg || '修改失败', icon: 'none' });
|
||||
}
|
||||
} catch (err) {
|
||||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
onCloseModifyModal() { this.setData({ showModifyModal: false, modifyingRecord: null }); },
|
||||
|
||||
onViewFailReason(e) {
|
||||
const record = e.currentTarget.dataset.record;
|
||||
const reason = record.fail_reason || record.shibaiyuanyin || '暂无详细信息';
|
||||
this.setData({ currentFailReason: reason, showFailModal: true });
|
||||
},
|
||||
|
||||
onCloseFailModal() { this.setData({ showFailModal: false }); },
|
||||
|
||||
getStatusText(zhuangtai) {
|
||||
const s = parseInt(zhuangtai);
|
||||
if (s === 1) return '审核中';
|
||||
if (s === 2) return '成功';
|
||||
if (s === 3) return '失败';
|
||||
return '未知';
|
||||
},
|
||||
getStatusColor(zhuangtai) {
|
||||
const s = parseInt(zhuangtai);
|
||||
if (s === 1) return '#F5A623';
|
||||
if (s === 2) return '#2ED158';
|
||||
if (s === 3) return '#FF4D4F';
|
||||
return '#999';
|
||||
},
|
||||
|
||||
registerNotification() {
|
||||
const comp = this.selectComponent('#global-notification');
|
||||
if (comp?.showNotification) {
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => comp.showNotification(data),
|
||||
hide: () => comp.hideNotification()
|
||||
};
|
||||
}
|
||||
},
|
||||
stopPropagation() {}
|
||||
}
|
||||
});
|
||||
7
pages/withdraw/components/record-mode1/record-mode1.json
Normal file
7
pages/withdraw/components/record-mode1/record-mode1.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"global-notification": "/components/global-notification/global-notification",
|
||||
"popup-notice": "/components/popup-notice/popup-notice"
|
||||
}
|
||||
}
|
||||
60
pages/withdraw/components/record-mode1/record-mode1.wxml
Normal file
60
pages/withdraw/components/record-mode1/record-mode1.wxml
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- record-mode1:仅提现记录(收款码手动审核) -->
|
||||
<view class="app">
|
||||
<image class="global-bg" src="{{imgUrls.pageBg}}" mode="aspectFill" />
|
||||
|
||||
<view class="history-section history-section--full">
|
||||
<view class="history-header">
|
||||
<text class="history-title">提现记录</text>
|
||||
</view>
|
||||
<scroll-view class="history-scroll" scroll-y enable-back-to-top bindscrolltolower="onLoadMoreFromScroll">
|
||||
<view wx:for="{{recordList}}" wx:key="index" class="history-item">
|
||||
<view class="history-info">
|
||||
<text class="history-amount">¥{{item.jine}}</text>
|
||||
<text class="history-time">{{item.create}}</text>
|
||||
</view>
|
||||
<view class="history-detail">
|
||||
<text class="history-method">{{item.fangshi == 1 ? '微信' : '支付宝'}}</text>
|
||||
<text class="history-type">{{item.leixing == 1 ? '佣金' : (item.leixing == 2 ? '分红' : (item.leixing == 3 ? '组长' : (item.leixing == 4 ? '考核官' : '保证金')))}}</text>
|
||||
</view>
|
||||
<view class="history-status">
|
||||
<view wx:if="{{item.zhuangtai == 1}}" class="status-badge status-wait" bindtap="onModifyRecord" data-record="{{item}}">{{item.statusText}} ✏修改</view>
|
||||
<view wx:elif="{{item.zhuangtai == 3}}" class="status-badge status-fail">
|
||||
{{item.statusText}}
|
||||
<text class="fail-link" bindtap="onViewFailReason" data-record="{{item}}">详情</text>
|
||||
</view>
|
||||
<view wx:else class="status-badge status-done">{{item.statusText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{loading}}" class="load-tip">加载中...</view>
|
||||
<view wx:if="{{nomore && recordList.length > 0}}" class="more-tip">—— 没有更多了 ——</view>
|
||||
<view wx:if="{{!nomore && recordList.length > 0}}" class="load-more-btn" bindtap="loadMoreRecords">加载更多记录</view>
|
||||
<view wx:if="{{recordList.length === 0 && !loading}}" class="load-tip">暂无提现记录</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="safe-bottom"></view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{showModifyModal}}" class="modal-mask" bindtap="onCloseModifyModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">修改信息</view>
|
||||
<view class="modal-body">
|
||||
<view class="toggle-row"><view class="toggle-item {{modifyTxfangshi == 1 ? 'active' : ''}}" bindtap="onSelectModifyFangshi" data-fangshi="1">微信</view><view class="toggle-item {{modifyTxfangshi == 2 ? 'active' : ''}}" bindtap="onSelectModifyFangshi" data-fangshi="2">支付宝</view></view>
|
||||
<input class="field-input" placeholder="电话" value="{{modifyTxPhone}}" bindinput="onModifyPhoneInput" />
|
||||
<view wx:if="{{modifyTxfangshi == 2}}"><input class="field-input" placeholder="支付宝账号" value="{{modifyTxAccount}}" bindinput="onModifyAccountInput" /></view>
|
||||
<view class="upload-wrap"><view wx:if="{{modifyImageUrl}}" class="current-img"><image src="{{modifyImageUrl}}" mode="aspectFill" bindtap="onPreviewModifyImage" /></view><view class="upload-trigger" bindtap="onChooseModifyImage">+ 上传新图片</view><view wx:if="{{modifyTxImage}}" class="image-preview"><image src="{{modifyTxImage}}" mode="aspectFill" /><view class="image-actions"><text bindtap="onPreviewModifyImage">预览</text><text bindtap="onDeleteModifyImage">删除</text></view></view></view>
|
||||
</view>
|
||||
<view class="modal-footer"><view class="modal-btn cancel" bindtap="onCloseModifyModal">取消</view><view class="modal-btn confirm" bindtap="onConfirmModify">确认</view></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{showFailModal}}" class="modal-mask" bindtap="onCloseFailModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">失败原因</view>
|
||||
<view class="modal-body">{{currentFailReason}}</view>
|
||||
<view class="modal-footer"><view class="modal-btn confirm" bindtap="onCloseFailModal">知道了</view></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
<popup-notice id="popupNotice" />
|
||||
67
pages/withdraw/components/record-mode1/record-mode1.wxss
Normal file
67
pages/withdraw/components/record-mode1/record-mode1.wxss
Normal file
@@ -0,0 +1,67 @@
|
||||
@import "../record-mode2/record-mode2.wxss";
|
||||
|
||||
.history-section--full {
|
||||
flex: 1;
|
||||
min-height: calc(100vh - 48rpx);
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.history-section--full .history-scroll {
|
||||
height: calc(100vh - 200rpx);
|
||||
}
|
||||
|
||||
.toggle-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.toggle-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f1f5f9;
|
||||
font-size: 28rpx;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.toggle-item.active {
|
||||
background: #eff6ff;
|
||||
color: #3b82f6;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.field-input {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 20rpx;
|
||||
border: 1rpx solid #e2e8f0;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.upload-trigger {
|
||||
padding: 40rpx;
|
||||
text-align: center;
|
||||
border: 2rpx dashed #cbd5e1;
|
||||
border-radius: 12rpx;
|
||||
color: #64748b;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.image-preview image {
|
||||
width: 100%;
|
||||
height: 240rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.image-actions {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
justify-content: center;
|
||||
margin-top: 12rpx;
|
||||
font-size: 26rpx;
|
||||
color: #3b82f6;
|
||||
}
|
||||
513
pages/withdraw/components/record-mode2/record-mode2.js
Normal file
513
pages/withdraw/components/record-mode2/record-mode2.js
Normal file
@@ -0,0 +1,513 @@
|
||||
// pages/withdraw/components/record-mode2/record-mode2.js
|
||||
// UI 与 mode1 完全一致,业务逻辑为自动打款审核收款
|
||||
import request from '../../../../utils/request.js';
|
||||
import PopupService from '../../../../services/popupService.js';
|
||||
|
||||
const app = getApp();
|
||||
const yemianshuju = 5;
|
||||
let lastPullDownTime = 0;
|
||||
const PULL_DOWN_INTERVAL = 2000;
|
||||
|
||||
const TX_STATUS = {
|
||||
SHENHEZHONG: 1,
|
||||
TIXIAN_CHENGGONG: 2,
|
||||
TIXIAN_SHIBAI: 3,
|
||||
SHENHE_CHENGGONG: 4,
|
||||
SHENHE_SHIBAI: 5,
|
||||
DAI_SHOUKUAN: 6,
|
||||
};
|
||||
|
||||
const ASSET_CONFIG = {
|
||||
dashou_yue: { leixing: 1, label: '接单员佣金' },
|
||||
guanshi_fenyong: { leixing: 2, label: '管事分红' },
|
||||
zuzhang_fenyong: { leixing: 3, label: '组长分红' },
|
||||
kaoheguan_fenyong: { leixing: 4, label: '考核官分佣' },
|
||||
dashou_yajin: { leixing: 5, label: '接单员保证金' },
|
||||
shangjia_yue: { leixing: 6, label: '商家余额' },
|
||||
};
|
||||
|
||||
const LEIXING_LABEL = {
|
||||
1: '接单员佣金', 2: '管事分红', 3: '组长分红',
|
||||
4: '考核官分佣', 5: '接单员保证金', 6: '商家余额',
|
||||
};
|
||||
|
||||
Component({
|
||||
properties: { options: { type: Object, value: {} } },
|
||||
data: {
|
||||
imgUrls: {
|
||||
pageBg: '', cardBg: '', assetTileBg: '',
|
||||
},
|
||||
assetList: [],
|
||||
totalAmount: '0.00',
|
||||
selectedAsset: null,
|
||||
isLoadingAssets: false,
|
||||
tixianleixing: null,
|
||||
tixianjine: '',
|
||||
currentRate: '0.00',
|
||||
showTixian: false,
|
||||
recordList: [],
|
||||
page: 1,
|
||||
loading: false,
|
||||
nomore: false,
|
||||
canloadmore: true,
|
||||
isRefreshing: false,
|
||||
shouxufei: '0.00',
|
||||
shijidaozhang: '0.00',
|
||||
currentTixianId: null,
|
||||
submitting: false,
|
||||
mchId: '',
|
||||
currentStatusFilter: 0,
|
||||
statusTabs: [
|
||||
{ value: 0, label: '全部' },
|
||||
{ value: 1, label: '审核中' },
|
||||
{ value: 6, label: '待收款' },
|
||||
{ value: 4, label: '审核成功' },
|
||||
{ value: 5, label: '审核失败' },
|
||||
{ value: 2, label: '提现成功' },
|
||||
{ value: 3, label: '提现失败' },
|
||||
],
|
||||
hasPendingCollect: false,
|
||||
showCollectConfirm: false,
|
||||
collectConfirmRecord: null,
|
||||
showDetailModal: false,
|
||||
detailTitle: '',
|
||||
detailContent: '',
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.initImageUrls();
|
||||
this.huoquJilu(true);
|
||||
}
|
||||
},
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this.registerNotificationComponent();
|
||||
PopupService.checkAndShow(this, 'tixian');
|
||||
},
|
||||
hide() {
|
||||
const popupComp = this.selectComponent('#popupNotice');
|
||||
if (popupComp && popupComp.cleanup) popupComp.cleanup();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
registerNotificationComponent() {
|
||||
const notificationComp = this.selectComponent('#global-notification');
|
||||
if (notificationComp && notificationComp.showNotification) {
|
||||
app.globalData.globalNotification = {
|
||||
show: (data) => notificationComp.showNotification(data),
|
||||
hide: () => notificationComp.hideNotification()
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
initImageUrls() {
|
||||
const ossBase = app.globalData.ossImageUrl || '';
|
||||
const imgDir = `${ossBase}beijing/tixian/`;
|
||||
this.setData({
|
||||
imgUrls: {
|
||||
pageBg: `${imgDir}page_bg.png`,
|
||||
cardBg: `${imgDir}card_bg.png`,
|
||||
assetTileBg: `${imgDir}asset_tile_bg.png`,
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
parseZhuangtai(item) {
|
||||
const raw = item.zhuangtai ?? item.status ?? item.state;
|
||||
const n = parseInt(raw, 10);
|
||||
return Number.isNaN(n) ? -1 : n;
|
||||
},
|
||||
|
||||
/** 规范化列表字段(兼容后端多种命名 / 嵌套 audit) */
|
||||
normalizeRecordFields(item) {
|
||||
const audit = item.audit || item.shenhe || item.shenhe_info || {};
|
||||
const shenheJiluId = item.shenhe_jilu_id ?? item.shenheJiluId
|
||||
?? item.audit_id ?? item.shenheid ?? audit.id ?? audit.shenhe_jilu_id ?? null;
|
||||
const shenheDanhao = String(
|
||||
item.shenhe_danhao || item.shenheDanhao || item.audit_shenhe_danhao
|
||||
|| audit.shenhe_danhao || audit.danhao || ''
|
||||
).trim();
|
||||
const tixianjiluId = item.tixianjilu_id ?? item.tixianjiluId ?? item.id ?? null;
|
||||
const zhuangtai = this.parseZhuangtai(item);
|
||||
return {
|
||||
...item,
|
||||
zhuangtai: zhuangtai >= 0 ? zhuangtai : item.zhuangtai,
|
||||
shenhe_jilu_id: shenheJiluId,
|
||||
shenhe_danhao: shenheDanhao,
|
||||
tixianjilu_id: tixianjiluId,
|
||||
};
|
||||
},
|
||||
|
||||
hasAuditJiluId(item) {
|
||||
const id = item.shenhe_jilu_id;
|
||||
return id !== null && id !== undefined && id !== '' && id !== 0 && id !== '0';
|
||||
},
|
||||
|
||||
hasShenheDanhao(item) {
|
||||
return !!(item.shenhe_danhao && String(item.shenhe_danhao).trim());
|
||||
},
|
||||
|
||||
isNewAuditRecord(item) {
|
||||
return this.hasAuditJiluId(item) && this.hasShenheDanhao(item);
|
||||
},
|
||||
|
||||
/** 待收款是否可点击:状态6 + 审核记录ID + 审核单号 缺一不可 */
|
||||
canCollectRecord(item) {
|
||||
return this.parseZhuangtai(item) === TX_STATUS.DAI_SHOUKUAN
|
||||
&& this.hasAuditJiluId(item)
|
||||
&& this.hasShenheDanhao(item);
|
||||
},
|
||||
|
||||
getLeixingLabel(leixing) {
|
||||
return LEIXING_LABEL[parseInt(leixing)] || '提现';
|
||||
},
|
||||
|
||||
getStatusBadgeClass(status) {
|
||||
switch (parseInt(status)) {
|
||||
case TX_STATUS.SHENHEZHONG: return 'status-wait';
|
||||
case TX_STATUS.TIXIAN_CHENGGONG:
|
||||
case TX_STATUS.SHENHE_CHENGGONG: return 'status-done';
|
||||
case TX_STATUS.DAI_SHOUKUAN: return 'status-pending';
|
||||
case TX_STATUS.TIXIAN_SHIBAI:
|
||||
case TX_STATUS.SHENHE_SHIBAI: return 'status-fail';
|
||||
default: return 'status-wait';
|
||||
}
|
||||
},
|
||||
|
||||
processRecordItem(item) {
|
||||
item = this.normalizeRecordFields(item);
|
||||
const isNew = this.isNewAuditRecord(item);
|
||||
const status = this.parseZhuangtai(item);
|
||||
let statusText = '未知';
|
||||
let canCollect = false;
|
||||
let canShowDetail = false;
|
||||
let detailReason = '';
|
||||
|
||||
switch (status) {
|
||||
case TX_STATUS.SHENHEZHONG: statusText = '审核中'; break;
|
||||
case TX_STATUS.TIXIAN_CHENGGONG: statusText = '提现成功'; break;
|
||||
case TX_STATUS.TIXIAN_SHIBAI:
|
||||
statusText = '提现失败';
|
||||
if (item.fail_reason || item.bhliyou) {
|
||||
canShowDetail = true;
|
||||
detailReason = item.fail_reason || item.bhliyou;
|
||||
}
|
||||
break;
|
||||
case TX_STATUS.SHENHE_CHENGGONG: statusText = '审核成功'; break;
|
||||
case TX_STATUS.SHENHE_SHIBAI:
|
||||
statusText = '审核失败';
|
||||
if (item.bhliyou) { canShowDetail = true; detailReason = item.bhliyou; }
|
||||
break;
|
||||
case TX_STATUS.DAI_SHOUKUAN:
|
||||
statusText = '待收款';
|
||||
canCollect = this.canCollectRecord(item);
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
isNewAudit: isNew,
|
||||
leixingLabel: this.getLeixingLabel(item.leixing),
|
||||
statusText,
|
||||
statusBadgeClass: this.getStatusBadgeClass(status),
|
||||
canCollect,
|
||||
canShowDetail,
|
||||
detailReason,
|
||||
};
|
||||
},
|
||||
|
||||
gengxinYue(data, leixing) {
|
||||
if (!data) return;
|
||||
if (data.new_yongjin !== undefined && data.new_yongjin !== null) {
|
||||
app.globalData.yongjin = data.new_yongjin;
|
||||
}
|
||||
if (data.new_fenyong !== undefined && data.new_fenyong !== null) {
|
||||
app.globalData.guanshi.fenyongtixian = data.new_fenyong;
|
||||
}
|
||||
if (data.new_yajin !== undefined && data.new_yajin !== null) {
|
||||
app.globalData.yajin = data.new_yajin;
|
||||
}
|
||||
if (data.new_shangjia_yue !== undefined && data.new_shangjia_yue !== null) {
|
||||
if (app.globalData.shangjia) app.globalData.shangjia.sjyue = data.new_shangjia_yue;
|
||||
}
|
||||
if (data.current_rate !== undefined && leixing) {
|
||||
const rate = parseFloat(data.current_rate);
|
||||
const rateKeyMap = { 1: 'dashouRate', 5: 'dashou_yajin_rate', 6: 'shangjia_rate', 2: 'guanshi_rate', 3: 'zuzhang_rate', 4: 'kaoheguan_rate' };
|
||||
const key = rateKeyMap[leixing];
|
||||
if (key) wx.setStorageSync(key, rate);
|
||||
}
|
||||
},
|
||||
|
||||
updatePendingCollectFlag(list) {
|
||||
const hasPending = (list || []).some(item => item.canCollect);
|
||||
if (hasPending !== this.data.hasPendingCollect) {
|
||||
this.setData({ hasPendingCollect: hasPending });
|
||||
}
|
||||
},
|
||||
|
||||
/** 微信确认收款成功后,本地先把对应记录标为「提现成功」 */
|
||||
markLocalRecordWithdrawSuccess(record) {
|
||||
if (!record) return;
|
||||
const matchId = String(record.tixianjilu_id || record.id || '');
|
||||
const matchDanhao = String(record.shenhe_danhao || '').trim();
|
||||
if (!matchId && !matchDanhao) return;
|
||||
|
||||
const newList = (this.data.recordList || []).map((item) => {
|
||||
const itemId = String(item.tixianjilu_id || item.id || '');
|
||||
const itemDanhao = String(item.shenhe_danhao || '').trim();
|
||||
const isMatch = (matchId && itemId === matchId)
|
||||
|| (matchDanhao && itemDanhao === matchDanhao);
|
||||
if (!isMatch) return item;
|
||||
return this.processRecordItem({
|
||||
...item,
|
||||
zhuangtai: TX_STATUS.TIXIAN_CHENGGONG,
|
||||
});
|
||||
});
|
||||
this.setData({ recordList: newList });
|
||||
this.updatePendingCollectFlag(newList);
|
||||
},
|
||||
|
||||
async finishWxCollectSuccess(record) {
|
||||
this.markLocalRecordWithdrawSuccess(record);
|
||||
await this.huoquJilu(true, true);
|
||||
this.markLocalRecordWithdrawSuccess(record);
|
||||
PopupService.checkAndShow(this, 'tixianchenggong');
|
||||
wx.showToast({
|
||||
title: '提现成功',
|
||||
icon: 'success',
|
||||
duration: 3000,
|
||||
});
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
return this.huoquJilu(true, true);
|
||||
},
|
||||
|
||||
onStatusFilterTap(e) {
|
||||
const value = parseInt(e.currentTarget.dataset.value, 10);
|
||||
if (value === this.data.currentStatusFilter) return;
|
||||
this.setData({ currentStatusFilter: value });
|
||||
this.huoquJilu(true);
|
||||
},
|
||||
|
||||
onCollectTap(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const record = this.data.recordList[index];
|
||||
if (!record) return;
|
||||
if (this.parseZhuangtai(record) !== TX_STATUS.DAI_SHOUKUAN) {
|
||||
wx.showToast({ title: '当前状态不可收款', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!this.hasShenheDanhao(record) || !this.hasAuditJiluId(record)) {
|
||||
wx.showToast({ title: '审核信息不完整,请刷新后重试', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (this.data.submitting) {
|
||||
wx.showToast({ title: '正在处理中,请稍后', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({ showCollectConfirm: true, collectConfirmRecord: record });
|
||||
},
|
||||
|
||||
onCloseCollectConfirm() {
|
||||
if (this.data.submitting) return;
|
||||
this.setData({ showCollectConfirm: false, collectConfirmRecord: null });
|
||||
},
|
||||
|
||||
async onConfirmCollect() {
|
||||
if (this.data.submitting) return;
|
||||
let record = this.data.collectConfirmRecord;
|
||||
if (!record) return;
|
||||
|
||||
if (!this.canCollectRecord(record)) {
|
||||
await this.huoquJilu(true, true);
|
||||
const refreshed = (this.data.recordList || []).find(
|
||||
r => String(r.id) === String(record.id)
|
||||
|| String(r.tixianjilu_id) === String(record.tixianjilu_id)
|
||||
);
|
||||
if (refreshed) record = refreshed;
|
||||
}
|
||||
if (!this.canCollectRecord(record)) {
|
||||
wx.showModal({
|
||||
title: '暂时无法收款',
|
||||
content: '缺少审核单号或审核记录ID,请下拉刷新后重试。仍不行请联系客服。',
|
||||
showCancel: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ showCollectConfirm: false, submitting: true, collectConfirmRecord: record });
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixiansq',
|
||||
method: 'POST',
|
||||
data: {
|
||||
shenhe_danhao: record.shenhe_danhao,
|
||||
shenhe_jilu_id: record.shenhe_jilu_id || '',
|
||||
tixianjilu_id: record.tixianjilu_id || record.id || '',
|
||||
leixing: record.leixing,
|
||||
}
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data;
|
||||
this.setData({
|
||||
currentTixianId: data.tixian_id,
|
||||
mchId: data.mch_id || '',
|
||||
collectConfirmRecord: record,
|
||||
});
|
||||
this.tiaoqiWeixinQueRen(data.package_info);
|
||||
} else {
|
||||
wx.showModal({ title: '收款失败', content: res.data?.msg || '无法发起收款,请稍后重试', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
}
|
||||
} catch (err) {
|
||||
wx.showModal({ title: '网络错误', content: '网络连接失败,请稍后重试', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
}
|
||||
},
|
||||
|
||||
tiaoqiWeixinQueRen(packageInfo) {
|
||||
const appId = app.globalData.appId;
|
||||
const mchId = this.data.mchId;
|
||||
if (!appId || !mchId) {
|
||||
wx.showModal({ title: '配置错误', content: '无法调起收款,请联系客服', showCancel: false });
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
return;
|
||||
}
|
||||
wx.requestMerchantTransfer({
|
||||
appId, mchId, package: packageInfo,
|
||||
success: () => { this.tongzhiHouduanQueRen(1); },
|
||||
fail: () => {
|
||||
this.tongzhiHouduanQueRen(0);
|
||||
wx.showModal({
|
||||
title: '确认收款失败',
|
||||
content: '微信收款确认失败,您可在记录中再次点击「收款」重试。',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async tongzhiHouduanQueRen(result) {
|
||||
if (!this.data.currentTixianId) {
|
||||
this.setData({ submitting: false, collectConfirmRecord: null });
|
||||
return;
|
||||
}
|
||||
const record = this.data.collectConfirmRecord;
|
||||
const wxConfirmed = result === 1;
|
||||
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixianqr',
|
||||
method: 'POST',
|
||||
data: {
|
||||
tixian_id: this.data.currentTixianId,
|
||||
result: result,
|
||||
shenhe_danhao: record ? record.shenhe_danhao : '',
|
||||
shenhe_jilu_id: record ? (record.shenhe_jilu_id || '') : '',
|
||||
tixianjilu_id: record ? (record.tixianjilu_id || record.id || '') : '',
|
||||
leixing: record ? record.leixing : '',
|
||||
}
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data || {};
|
||||
this.gengxinYue(data, record ? record.leixing : null);
|
||||
}
|
||||
|
||||
// 微信已确认收款:不论 tixianqr 返回什么,都刷新列表,不弹系统异常
|
||||
if (wxConfirmed) {
|
||||
await this.finishWxCollectSuccess(record);
|
||||
} else if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
this.huoquJilu(true);
|
||||
wx.showToast({
|
||||
title: '收款已取消',
|
||||
icon: 'none',
|
||||
duration: 3000,
|
||||
});
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '确认状态失败',
|
||||
content: res.data?.msg || '操作失败',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
if (wxConfirmed) {
|
||||
await this.finishWxCollectSuccess(record);
|
||||
} else {
|
||||
wx.showModal({
|
||||
title: '网络错误',
|
||||
content: '网络连接失败',
|
||||
showCancel: false,
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
this.setData({ submitting: false, currentTixianId: null, collectConfirmRecord: null });
|
||||
}
|
||||
},
|
||||
|
||||
onViewDetail(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const record = this.data.recordList[index];
|
||||
if (!record || !record.canShowDetail) return;
|
||||
const status = parseInt(record.zhuangtai);
|
||||
let detailTitle = '失败原因';
|
||||
if (status === TX_STATUS.SHENHE_SHIBAI) detailTitle = '审核失败原因';
|
||||
else if (status === TX_STATUS.TIXIAN_SHIBAI) detailTitle = '提现失败原因';
|
||||
this.setData({
|
||||
showDetailModal: true,
|
||||
detailTitle,
|
||||
detailContent: record.detailReason || '暂无详细信息',
|
||||
});
|
||||
},
|
||||
|
||||
onCloseDetailModal() {
|
||||
this.setData({ showDetailModal: false, detailTitle: '', detailContent: '' });
|
||||
},
|
||||
|
||||
async huoquJilu(fresh = false, force = false) {
|
||||
const now = Date.now();
|
||||
if (!force && now - lastPullDownTime < 2000 && !fresh) return;
|
||||
if (!force && (this.data.loading || this.data.isRefreshing)) return;
|
||||
const page = fresh ? 1 : this.data.page;
|
||||
if (fresh) this.setData({ nomore: false, canloadmore: true, isRefreshing: true });
|
||||
if (this.data.nomore && !fresh) return;
|
||||
this.setData({ loading: true });
|
||||
lastPullDownTime = now;
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/tixianjiluhq',
|
||||
method: 'POST',
|
||||
data: { page, limit: yemianshuju, mode: 2, zhuangtai: this.data.currentStatusFilter }
|
||||
});
|
||||
if (res.statusCode === 200 && res.data && res.data.code === 0) {
|
||||
const data = res.data.data;
|
||||
const processedList = (data.list || []).map(item => this.processRecordItem(item));
|
||||
const newList = fresh ? processedList : [...this.data.recordList, ...processedList];
|
||||
this.setData({
|
||||
recordList: newList,
|
||||
page: page + 1,
|
||||
nomore: !(data.has_more === true),
|
||||
canloadmore: data.has_more === true,
|
||||
loading: false,
|
||||
isRefreshing: false,
|
||||
});
|
||||
this.updatePendingCollectFlag(newList);
|
||||
} else {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
} catch (err) {
|
||||
this.setData({ loading: false, isRefreshing: false });
|
||||
}
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.canloadmore && !this.data.nomore && !this.data.loading && !this.data.isRefreshing) {
|
||||
const now = Date.now();
|
||||
if (now - lastPullDownTime >= PULL_DOWN_INTERVAL) this.huoquJilu();
|
||||
}
|
||||
},
|
||||
|
||||
stopPropagation() {}
|
||||
}
|
||||
});
|
||||
7
pages/withdraw/components/record-mode2/record-mode2.json
Normal file
7
pages/withdraw/components/record-mode2/record-mode2.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"global-notification": "/components/global-notification/global-notification",
|
||||
"popup-notice": "/components/popup-notice/popup-notice"
|
||||
}
|
||||
}
|
||||
90
pages/withdraw/components/record-mode2/record-mode2.wxml
Normal file
90
pages/withdraw/components/record-mode2/record-mode2.wxml
Normal file
@@ -0,0 +1,90 @@
|
||||
<!-- record-mode2:仅提现记录(自动打款) -->
|
||||
<view class="app">
|
||||
<image class="global-bg" src="{{imgUrls.pageBg}}" mode="aspectFill" />
|
||||
|
||||
<view class="history-section history-section--full">
|
||||
<view class="history-header">
|
||||
<text class="history-title">提现记录</text>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{hasPendingCollect}}" class="pending-tip">
|
||||
您有审核通过的提现待收款,请点击「收款」按钮,在微信中主动确认后才能到账。
|
||||
</view>
|
||||
|
||||
<scroll-view class="filter-scroll" scroll-x show-scrollbar="{{false}}">
|
||||
<view class="filter-track">
|
||||
<view
|
||||
wx:for="{{statusTabs}}"
|
||||
wx:key="value"
|
||||
class="filter-chip {{currentStatusFilter == item.value ? 'active' : ''}}"
|
||||
bindtap="onStatusFilterTap"
|
||||
data-value="{{item.value}}"
|
||||
>{{item.label}}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<scroll-view class="history-scroll" scroll-y enable-back-to-top bindscrolltolower="onReachBottom">
|
||||
<view wx:for="{{recordList}}" wx:key="index" class="history-item">
|
||||
<view class="history-info">
|
||||
<text class="history-amount">¥{{item.jine}}</text>
|
||||
<text class="history-time">{{item.create}}</text>
|
||||
</view>
|
||||
<view class="history-detail">
|
||||
<text class="history-method">微信零钱</text>
|
||||
<text class="history-type">{{item.leixingLabel}}</text>
|
||||
</view>
|
||||
<view class="history-status">
|
||||
<view
|
||||
wx:if="{{item.canCollect}}"
|
||||
class="status-badge status-pending collect-tappable"
|
||||
bindtap="onCollectTap"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
<text>{{item.statusText}}</text>
|
||||
<text class="collect-sub">点击收款</text>
|
||||
</view>
|
||||
<view wx:elif="{{item.canShowDetail}}" class="status-badge status-fail">
|
||||
{{item.statusText}}
|
||||
<text class="fail-link" bindtap="onViewDetail" data-index="{{index}}">详情</text>
|
||||
</view>
|
||||
<view wx:else class="status-badge {{item.statusBadgeClass}}">{{item.statusText}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{loading}}" class="load-tip">加载中...</view>
|
||||
<view wx:if="{{nomore && recordList.length > 0}}" class="more-tip">—— 没有更多了 ——</view>
|
||||
<view wx:if="{{!nomore && recordList.length > 0}}" class="load-more-btn" bindtap="onReachBottom">加载更多记录</view>
|
||||
<view wx:if="{{recordList.length === 0 && !loading}}" class="load-tip">暂无提现记录</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="safe-bottom"></view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{showCollectConfirm}}" class="modal-mask" bindtap="onCloseCollectConfirm">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">确认收款</view>
|
||||
<view class="modal-body">
|
||||
<view class="auto-tip">审核已通过,{{collectConfirmRecord.leixingLabel}} ¥{{collectConfirmRecord.jine}}</view>
|
||||
<view>请点击「去收款」,然后在微信弹窗中主动确认,资金才会打入您的微信零钱。</view>
|
||||
<view class="warn-tip" wx:if="{{collectConfirmRecord.shenhe_danhao}}">审核单号:{{collectConfirmRecord.shenhe_danhao}}</view>
|
||||
<view class="warn-tip">注意:审核通过≠已到账,必须您本人点击确认才能完成收款!</view>
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel" bindtap="onCloseCollectConfirm">稍后再说</view>
|
||||
<view class="modal-btn confirm" bindtap="onConfirmCollect">{{submitting ? '处理中...' : '去收款'}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{showDetailModal}}" class="modal-mask" bindtap="onCloseDetailModal">
|
||||
<view class="modal-dialog" catchtap="stopPropagation">
|
||||
<view class="modal-header">{{detailTitle}}</view>
|
||||
<view class="modal-body">{{detailContent}}</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn confirm" bindtap="onCloseDetailModal">知道了</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
<popup-notice id="popupNotice" />
|
||||
416
pages/withdraw/components/record-mode2/record-mode2.wxss
Normal file
416
pages/withdraw/components/record-mode2/record-mode2.wxss
Normal file
@@ -0,0 +1,416 @@
|
||||
/* mode2 自动打款 - UI 完全复用 mode1 样式 */
|
||||
|
||||
page {
|
||||
background-color: #f5f7fb;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
padding: 0 24rpx 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.global-bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
opacity: 0.1;
|
||||
object-fit: cover;
|
||||
filter: blur(1rpx);
|
||||
}
|
||||
|
||||
.assets-section {
|
||||
margin-top: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.main-card {
|
||||
background: rgba(248, 250, 252, 0.88);
|
||||
backdrop-filter: blur(28rpx);
|
||||
-webkit-backdrop-filter: blur(28rpx);
|
||||
border-radius: 48rpx;
|
||||
padding: 30rpx 28rpx 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.04);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.4);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.balance-wrap {
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.balance-label {
|
||||
font-size: 28rpx;
|
||||
color: #0f172a;
|
||||
letter-spacing: 1px;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
font-weight: 700;
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.8);
|
||||
}
|
||||
.balance-value {
|
||||
font-size: 68rpx;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
font-family: 'DIN', monospace;
|
||||
letter-spacing: -1rpx;
|
||||
text-shadow: 0 1rpx 2rpx rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
.inner-divider {
|
||||
width: 60%;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #64748b, #64748b, transparent);
|
||||
margin: 0 auto 20rpx auto;
|
||||
border-radius: 2rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.assets-hint {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #334155;
|
||||
margin-bottom: 14rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.assets-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.assets-track {
|
||||
display: inline-flex;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.asset-tile {
|
||||
width: 170rpx;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
backdrop-filter: blur(8rpx);
|
||||
border-radius: 28rpx;
|
||||
padding: 18rpx 12rpx;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.02);
|
||||
transition: all 0.2s;
|
||||
white-space: normal;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.asset-tile:active {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.asset-name {
|
||||
font-size: 24rpx;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
margin-bottom: 10rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.5);
|
||||
}
|
||||
.asset-balance {
|
||||
font-size: 28rpx;
|
||||
font-weight: 800;
|
||||
color: #2d6a4f;
|
||||
font-family: monospace;
|
||||
margin-bottom: 6rpx;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.asset-fee {
|
||||
font-size: 20rpx;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
text-shadow: 0 1rpx 1rpx rgba(255,255,255,0.3);
|
||||
}
|
||||
.assets-empty {
|
||||
width: 400rpx;
|
||||
text-align: center;
|
||||
color: #a0abb9;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, #cbd5e1, #cbd5e1, transparent);
|
||||
margin: 16rpx 0 20rpx;
|
||||
width: 80%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.history-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
.history-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 0 8rpx 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.history-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
}
|
||||
.history-scroll {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 28rpx 0;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.history-info { width: 160rpx; }
|
||||
.history-amount {
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
display: block;
|
||||
}
|
||||
.history-time {
|
||||
font-size: 22rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-detail {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.history-method {
|
||||
font-size: 30rpx;
|
||||
color: #334155;
|
||||
display: block;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
.history-type {
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.history-status { text-align: right; }
|
||||
|
||||
.status-badge {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
padding: 6rpx 14rpx;
|
||||
border-radius: 30rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
.status-wait {
|
||||
color: #f59e0b;
|
||||
background: rgba(245,158,11,0.1);
|
||||
}
|
||||
.status-done {
|
||||
color: #10b981;
|
||||
background: rgba(16,185,129,0.1);
|
||||
}
|
||||
.status-fail {
|
||||
color: #ef4444;
|
||||
background: rgba(239,68,68,0.1);
|
||||
}
|
||||
.status-pending {
|
||||
color: #3b82f6;
|
||||
background: rgba(59,130,246,0.1);
|
||||
}
|
||||
.fail-link {
|
||||
margin-left: 8rpx;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.collect-tappable {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
padding: 10rpx 18rpx;
|
||||
cursor: pointer;
|
||||
border: 2rpx solid rgba(59,130,246,0.35);
|
||||
box-shadow: 0 4rpx 12rpx rgba(59,130,246,0.15);
|
||||
}
|
||||
.collect-tappable:active {
|
||||
transform: scale(0.97);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.collect-sub {
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #1d4ed8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.load-tip, .more-tip {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #94a3b8;
|
||||
}
|
||||
.load-more-btn {
|
||||
margin: 16rpx 0 20rpx;
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
background: rgba(255,255,255,0.7);
|
||||
backdrop-filter: blur(8rpx);
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
color: #3b82f6;
|
||||
border: 1rpx solid rgba(255,255,255,0.5);
|
||||
}
|
||||
.load-more-btn:active { background: rgba(255,255,255,0.9); }
|
||||
.history-section--full {
|
||||
flex: 1;
|
||||
min-height: calc(100vh - 48rpx);
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.history-section--full .history-scroll {
|
||||
height: calc(100vh - 280rpx);
|
||||
}
|
||||
|
||||
/* 自动打款专属(少量追加) */
|
||||
.pending-tip {
|
||||
margin: 0 8rpx 16rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #1d4ed8;
|
||||
background: rgba(59,130,246,0.08);
|
||||
border-radius: 20rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.filter-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
.filter-track {
|
||||
display: inline-flex;
|
||||
gap: 12rpx;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
.filter-chip {
|
||||
flex-shrink: 0;
|
||||
padding: 10rpx 22rpx;
|
||||
font-size: 24rpx;
|
||||
color: #64748b;
|
||||
background: rgba(255,255,255,0.8);
|
||||
border-radius: 30rpx;
|
||||
border: 1rpx solid rgba(0,0,0,0.06);
|
||||
}
|
||||
.filter-chip.active {
|
||||
color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
.auto-tip {
|
||||
font-size: 24rpx;
|
||||
color: #3b82f6;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.warn-tip {
|
||||
font-size: 24rpx;
|
||||
color: #f59e0b;
|
||||
margin-top: 16rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 弹窗(与 mode1 一致) */
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.modal-dialog {
|
||||
width: 600rpx;
|
||||
background: rgba(255,255,255,0.96);
|
||||
backdrop-filter: blur(20rpx);
|
||||
border-radius: 48rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20rpx 40rpx rgba(0,0,0,0.1);
|
||||
border: 1rpx solid rgba(255,255,255,0.6);
|
||||
}
|
||||
.modal-header {
|
||||
padding: 36rpx 32rpx 20rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 700;
|
||||
border-bottom: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-body {
|
||||
padding: 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #334155;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.info-row, .amount-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.amount-row input {
|
||||
border: 1rpx solid rgba(0,0,0,0.1);
|
||||
border-radius: 28rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
width: 260rpx;
|
||||
background: rgba(255,255,255,0.9);
|
||||
}
|
||||
.quick-row {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
margin: 24rpx 0;
|
||||
}
|
||||
.quick-chip {
|
||||
flex: 1;
|
||||
background: rgba(241,245,249,0.8);
|
||||
text-align: center;
|
||||
padding: 12rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: rgba(248,250,252,0.8);
|
||||
padding: 20rpx;
|
||||
border-radius: 28rpx;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
border-top: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 28rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.modal-btn.cancel {
|
||||
color: #8f9bb3;
|
||||
border-right: 1rpx solid rgba(0,0,0,0.05);
|
||||
}
|
||||
.modal-btn.confirm { color: #3b82f6; }
|
||||
|
||||
Reference in New Issue
Block a user