20261008
This commit is contained in:
@@ -0,0 +1,574 @@
|
||||
<template>
|
||||
<view class="page-body">
|
||||
<view class="overview-card">
|
||||
<view class="overview-header">
|
||||
<view class="summary-main">
|
||||
<view class="summary-label">总余额</view>
|
||||
<view class="summary-amount">¥{{ formatMoney(totalBalance) }}</view>
|
||||
<view class="summary-time" v-if="balanceInfo.updateTime">最近更新时间:{{ balanceInfo.updateTime }}</view>
|
||||
</view>
|
||||
<el-button type="text" class="toggle-button" @click="toggleMerchantList">
|
||||
{{ merchantExpanded ? "收起明细" : "展开明细" }}
|
||||
</el-button>
|
||||
</view>
|
||||
<view class="merchant-list" v-show="merchantExpanded">
|
||||
<view class="merchant-row" v-for="item in balanceInfoList" :key="item.accNo">
|
||||
<view class="merchant-info">
|
||||
<view class="merchant-name">{{ item.merchantName }}</view>
|
||||
<view class="merchant-meta">{{ item.accNo }}</view>
|
||||
<view class="merchant-meta" v-if="item.updateTime">更新时间:{{ item.updateTime }}</view>
|
||||
</view>
|
||||
<view class="merchant-side">
|
||||
<view class="merchant-balance">¥{{ formatMoney(item.balance) }}</view>
|
||||
<view class="summary-actions">
|
||||
<el-button size="small" :loading="balanceQuery[item.accNo]" @click="queryBalance(item)">查询余额</el-button>
|
||||
<el-button type="warning" size="small" icon="el-icon-wallet"
|
||||
:disabled="Number(item.balance || 0) <= 0"
|
||||
@click="openWithdrawDialog(item)">提现</el-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<vk-data-table-query v-model="queryForm1.formData" :columns="queryForm1.columns"
|
||||
@search="search"></vk-data-table-query>
|
||||
<vk-data-table ref="table1" :action="table1.action" :columns="table1.columns" :query-form-param="queryForm1"
|
||||
:pagination="true"
|
||||
@current-change="currentChange"
|
||||
@selection-change="selectionChange">
|
||||
<template v-slot:action="{ row }">
|
||||
<el-button v-if="row.srcReqId" type="primary" size="mini" @click="queryActionLog(row)">查询状态</el-button>
|
||||
</template>
|
||||
</vk-data-table>
|
||||
|
||||
<el-dialog title="提现" :visible.sync="withdrawDialog.show" width="520px" :close-on-click-modal="false">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="提现企业">
|
||||
<view class="withdraw-company">{{ withdrawDialog.form.merchantName || "-" }}</view>
|
||||
</el-form-item>
|
||||
<el-form-item label="提现账号">
|
||||
<view class="withdraw-company">{{ withdrawDialog.form.merchantId || "-" }}</view>
|
||||
</el-form-item>
|
||||
<el-form-item label="当前余额">
|
||||
<view class="withdraw-balance">¥{{ formatMoney(withdrawDialog.form.balance) }}</view>
|
||||
</el-form-item>
|
||||
<el-form-item label="提现金额" required>
|
||||
<el-input-number v-model="withdrawDialog.form.amount" :min="0" :precision="2" :step="100"
|
||||
controls-position="right" style="width: 100%;"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="说明">
|
||||
<el-input v-model="withdrawDialog.form.description" type="textarea" :rows="4" maxlength="100"
|
||||
show-word-limit placeholder="请输入提现说明"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template v-slot:footer>
|
||||
<el-button @click="withdrawDialog.show = false">取消</el-button>
|
||||
<el-button type="primary" :loading="withdrawDialog.loading" @click="submitWithdraw">确认提现</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
var that;
|
||||
var vk = uni.vk;
|
||||
|
||||
const typeData = [
|
||||
{ value: "income", label: "收入" },
|
||||
{ value: "expense", label: "支出" }
|
||||
];
|
||||
|
||||
const merchantOptions = [
|
||||
{ value: "zg000002466577", accNo: "zg000002466577", label: "广西金久信电子商务有限公司" },
|
||||
{ value: "zg000002460927", accNo: "zg000002460927", label: "南宁亿利通钢管有限公司" },
|
||||
{ value: "zg000002494918", accNo: "zg000002494918", label: "广西冀旺贸易有限公司" },
|
||||
{ value: "zg000002459804", accNo: "zg000002459804", label: "广西金久信电子商务有限公司" }
|
||||
];
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
totalBalance() {
|
||||
return this.balanceInfoList.reduce((total, item) => {
|
||||
return total + Number(item.balance || 0);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
data: {},
|
||||
merchantOptions,
|
||||
balanceInfo: {
|
||||
balance: 0,
|
||||
updateTime: ""
|
||||
},
|
||||
merchantExpanded: true,
|
||||
balanceInfoList: merchantOptions.map(item => ({
|
||||
accNo: item.accNo,
|
||||
merchantName: item.label,
|
||||
balance: 0,
|
||||
updateTime: ""
|
||||
})),
|
||||
table1: {
|
||||
action: "admin/finance/balance/sys/getList",
|
||||
columns: [
|
||||
{
|
||||
key: "description",
|
||||
title: "说明",
|
||||
type: "text",
|
||||
align: "left",
|
||||
minWidth: 240
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
title: "类型",
|
||||
type: "select",
|
||||
width: 120,
|
||||
data: typeData
|
||||
},
|
||||
{
|
||||
key: "amount",
|
||||
title: "金额",
|
||||
type: "text",
|
||||
width: 140,
|
||||
formatter: (val, row) => {
|
||||
const sign = row.type === "income" ? "+" : "-";
|
||||
return `${sign}¥${that.formatMoney(val)}`;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "logTime",
|
||||
title: "时间",
|
||||
type: "time",
|
||||
width: 180,
|
||||
sortable: "custom"
|
||||
},
|
||||
{
|
||||
key: "_add_time",
|
||||
title: "创建时间",
|
||||
type: "time",
|
||||
width: 180,
|
||||
sortable: "custom"
|
||||
},
|
||||
{
|
||||
key: "status",
|
||||
title: "状态",
|
||||
type: "text",
|
||||
width: 120,
|
||||
formatter: (val) => {
|
||||
return that.formatStatus(val);
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "action",
|
||||
title: "操作",
|
||||
type: "html",
|
||||
width: 140
|
||||
}
|
||||
],
|
||||
multipleSelection: [],
|
||||
selectItem: ""
|
||||
},
|
||||
queryForm1: {
|
||||
formData: {},
|
||||
columns: [
|
||||
{
|
||||
key: "type",
|
||||
title: "类型",
|
||||
type: "select",
|
||||
mode: "=",
|
||||
data: typeData
|
||||
},
|
||||
{
|
||||
key: "logTime",
|
||||
title: "时间",
|
||||
type: "datetimerange",
|
||||
width: 380,
|
||||
mode: "[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
withdrawDialog: {
|
||||
show: false,
|
||||
loading: false,
|
||||
form: {
|
||||
merchantId: "",
|
||||
merchantName: "",
|
||||
balance: 0,
|
||||
amount: 0,
|
||||
description: ""
|
||||
}
|
||||
},
|
||||
balanceQuery: merchantOptions.reduce((map, item) => {
|
||||
map[item.accNo] = false;
|
||||
return map;
|
||||
}, {})
|
||||
};
|
||||
},
|
||||
onLoad(options = {}) {
|
||||
that = this;
|
||||
vk = that.vk;
|
||||
that.options = options;
|
||||
that.init(options);
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
that.getBalanceSummary();
|
||||
},
|
||||
search() {
|
||||
that.$refs.table1.search();
|
||||
that.getBalanceSummary();
|
||||
},
|
||||
refresh() {
|
||||
that.$refs.table1.refresh();
|
||||
that.getBalanceSummary();
|
||||
},
|
||||
toggleMerchantList() {
|
||||
that.merchantExpanded = !that.merchantExpanded;
|
||||
},
|
||||
currentChange(val) {
|
||||
that.table1.selectItem = val;
|
||||
},
|
||||
selectionChange(list) {
|
||||
that.table1.multipleSelection = list;
|
||||
},
|
||||
async getBalanceSummary() {
|
||||
const { data = {} } = await vk.callFunction({
|
||||
url: "admin/finance/balance/sys/getSummary",
|
||||
data: {}
|
||||
});
|
||||
that.balanceInfo = {
|
||||
balance: 0,
|
||||
updateTime: data.updateTime || ""
|
||||
};
|
||||
const serverList = Array.isArray(data.balanceInfoList) ? data.balanceInfoList : [];
|
||||
const serverMap = serverList.reduce((map, item) => {
|
||||
map[item.accNo] = item;
|
||||
return map;
|
||||
}, {});
|
||||
that.balanceInfoList = merchantOptions.map(item => {
|
||||
const current = serverMap[item.accNo] || {};
|
||||
return {
|
||||
accNo: item.accNo,
|
||||
merchantName: current.merchantName || item.label,
|
||||
balance: Number(current.balance || 0),
|
||||
updateTime: current.updateTime || ""
|
||||
};
|
||||
});
|
||||
},
|
||||
async queryBalance(item) {
|
||||
const accNo = item && item.accNo;
|
||||
if (!accNo) {
|
||||
vk.toast("未配置提现账号");
|
||||
return;
|
||||
}
|
||||
that.balanceQuery[accNo] = true;
|
||||
try {
|
||||
await vk.callFunction({
|
||||
url: "admin/finance/balance/sys/getInfo",
|
||||
data: {
|
||||
accNo
|
||||
}
|
||||
});
|
||||
await that.getBalanceSummary();
|
||||
vk.toast(`${item.merchantName}余额已更新`);
|
||||
} finally {
|
||||
that.balanceQuery[accNo] = false;
|
||||
}
|
||||
},
|
||||
openWithdrawDialog(item) {
|
||||
if (Number(item.balance || 0) <= 0) {
|
||||
vk.toast("当前企业余额小于等于0,无法提现");
|
||||
return;
|
||||
}
|
||||
that.withdrawDialog.form = {
|
||||
merchantId: item.accNo,
|
||||
merchantName: item.merchantName,
|
||||
balance: Number(item.balance || 0),
|
||||
amount: 0,
|
||||
description: ""
|
||||
};
|
||||
that.withdrawDialog.show = true;
|
||||
},
|
||||
async queryActionLog(row) {
|
||||
const accNo = String(row && (row.merchantId || row.accNo) || "").trim();
|
||||
const reqJournalNo = String(row && row.srcReqId || "").trim();
|
||||
const reqDate = that.formatReqDate(row && row._add_time);
|
||||
if (!accNo) {
|
||||
vk.toast("账号不能为空");
|
||||
return;
|
||||
}
|
||||
if (!reqJournalNo) {
|
||||
vk.toast("srcReqId不能为空");
|
||||
return;
|
||||
}
|
||||
if (!reqDate) {
|
||||
vk.toast("日期格式不正确");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await vk.request({
|
||||
method: "POST",
|
||||
url: "http://jjx-union-pay.gxwebsoft.com/api/union-pay-jjx/getActionLog",
|
||||
header: {
|
||||
"content-type": "application/json; charset=utf-8"
|
||||
},
|
||||
data: {
|
||||
accNo,
|
||||
reqDate,
|
||||
reqJournalNo
|
||||
},
|
||||
timeout: 60000
|
||||
});
|
||||
const code = Number(res && res.code);
|
||||
const success = res && (
|
||||
code === 0 ||
|
||||
code === 200 ||
|
||||
res.success === true ||
|
||||
(typeof res.code === "undefined" && !res.msg && !res.message)
|
||||
);
|
||||
if (!success) {
|
||||
throw new Error(
|
||||
(res && (res.msg || res.message)) ||
|
||||
(res && res.content && (res.content.msg || res.content.message)) ||
|
||||
"查询状态失败"
|
||||
);
|
||||
}
|
||||
const status = that.getActionStatusValue(res);
|
||||
const statusText = that.formatStatus(status);
|
||||
if (status !== "" && row && row._id) {
|
||||
row.status = status;
|
||||
}
|
||||
vk.toast(statusText || "未识别到状态");
|
||||
console.log("getActionLog", res);
|
||||
} catch (err) {
|
||||
vk.toast((err && err.message) || "查询状态失败");
|
||||
}
|
||||
},
|
||||
async submitWithdraw() {
|
||||
const { amount, description, merchantId, balance } = that.withdrawDialog.form;
|
||||
if (!merchantId) {
|
||||
vk.toast("提现账号不能为空");
|
||||
return;
|
||||
}
|
||||
if (!amount || Number(amount) <= 0) {
|
||||
vk.toast("提现金额必须大于0");
|
||||
return;
|
||||
}
|
||||
if (Number(balance || 0) <= 0) {
|
||||
vk.toast("当前企业余额小于等于0,无法提现");
|
||||
return;
|
||||
}
|
||||
if (Number(amount) > Number(balance || 0)) {
|
||||
vk.toast("提现金额不能大于当前企业余额");
|
||||
return;
|
||||
}
|
||||
that.withdrawDialog.loading = true;
|
||||
try {
|
||||
await vk.callFunction({
|
||||
url: "admin/finance/balance/sys/withdraw",
|
||||
data: {
|
||||
merchantId,
|
||||
amount: Number(amount),
|
||||
description
|
||||
}
|
||||
});
|
||||
that.withdrawDialog.show = false;
|
||||
that.refresh();
|
||||
vk.toast("提现成功");
|
||||
} finally {
|
||||
that.withdrawDialog.loading = false;
|
||||
}
|
||||
},
|
||||
formatMoney(value) {
|
||||
const amount = Number(value || 0);
|
||||
return amount.toFixed(2);
|
||||
},
|
||||
formatReqDate(value) {
|
||||
const raw = value || "";
|
||||
const date = typeof raw === "number"
|
||||
? new Date(raw)
|
||||
: new Date(String(raw).replace(/-/g, "/"));
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return "";
|
||||
}
|
||||
return vk.pubfn.timeFormat(date, "yyyyMMdd");
|
||||
},
|
||||
getActionStatusValue(res) {
|
||||
const orderSet = this.pickOrderSet(res);
|
||||
if (!orderSet) {
|
||||
return "";
|
||||
}
|
||||
let orderList = [];
|
||||
try {
|
||||
orderList = JSON.parse(orderSet);
|
||||
} catch (err) {
|
||||
console.log("orderSet parse error", err, orderSet);
|
||||
return "";
|
||||
}
|
||||
if (!Array.isArray(orderList) || !orderList.length) {
|
||||
return "";
|
||||
}
|
||||
const firstOrder = orderList[0] || {};
|
||||
const status = Number(firstOrder.status);
|
||||
return Number.isFinite(status) ? status : "";
|
||||
},
|
||||
formatStatus(status) {
|
||||
const statusMap = {
|
||||
1: "处理中",
|
||||
2: "成功",
|
||||
3: "处理失败",
|
||||
5: "退票",
|
||||
6: "退票重提"
|
||||
};
|
||||
return statusMap[Number(status)] || "";
|
||||
},
|
||||
pickOrderSet(res) {
|
||||
const candidates = [
|
||||
res && res.orderSet,
|
||||
res && res.data && res.data.orderSet,
|
||||
res && res.info && res.info.orderSet,
|
||||
res && res.content && res.content.orderSet,
|
||||
res && res.data && Array.isArray(res.data) && res.data[0] && res.data[0].orderSet,
|
||||
res && res.list && Array.isArray(res.list) && res.list[0] && res.list[0].orderSet,
|
||||
res && res.rows && Array.isArray(res.rows) && res.rows[0] && res.rows[0].orderSet,
|
||||
res && res.data && res.data.list && Array.isArray(res.data.list) && res.data.list[0] && res.data.list[0].orderSet,
|
||||
res && res.data && res.data.rows && Array.isArray(res.data.rows) && res.data.rows[0] && res.data.rows[0].orderSet
|
||||
];
|
||||
for (let i = 0; i < candidates.length; i++) {
|
||||
if (typeof candidates[i] === "string" && candidates[i]) {
|
||||
return candidates[i];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-body {
|
||||
.overview-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 24rpx 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background: linear-gradient(135deg, #fff7e6 0%, #fff1d6 100%);
|
||||
border: 1px solid #f7d8a8;
|
||||
}
|
||||
|
||||
.overview-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 24rpx;
|
||||
padding-bottom: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border-bottom: 1px solid rgba(194, 106, 0, 0.12);
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.merchant-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.merchant-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24rpx;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid rgba(194, 106, 0, 0.12);
|
||||
}
|
||||
|
||||
.merchant-row:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.merchant-info {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.merchant-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.summary-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.summary-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
font-size: 26rpx;
|
||||
color: #8c6b2f;
|
||||
}
|
||||
|
||||
.merchant-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #8c6b2f;
|
||||
}
|
||||
|
||||
.merchant-meta {
|
||||
font-size: 24rpx;
|
||||
color: #9f8252;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.summary-amount {
|
||||
font-size: 52rpx;
|
||||
line-height: 1.1;
|
||||
font-weight: 700;
|
||||
color: #c26a00;
|
||||
}
|
||||
|
||||
.merchant-balance {
|
||||
font-size: 34rpx;
|
||||
line-height: 1.1;
|
||||
font-weight: 700;
|
||||
color: #c26a00;
|
||||
}
|
||||
|
||||
.summary-time {
|
||||
font-size: 24rpx;
|
||||
color: #9f8252;
|
||||
}
|
||||
|
||||
.withdraw-balance {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #c26a00;
|
||||
}
|
||||
|
||||
.withdraw-company {
|
||||
color: #8c6b2f;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user