Merge remote-tracking branch 'origin/master'

This commit is contained in:
SjS 2025-04-08 08:53:06 +08:00
commit f65f8d9349
19 changed files with 1729 additions and 87 deletions

44
src/api/bst/account.js Normal file
View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询收款账户列表
export function listAccount(query) {
return request({
url: '/bst/account/list',
method: 'get',
params: query
})
}
// 查询收款账户详细
export function getAccount(id) {
return request({
url: '/bst/account/' + id,
method: 'get'
})
}
// 新增收款账户
export function addAccount(data) {
return request({
url: '/bst/account',
method: 'post',
data: data
})
}
// 修改收款账户
export function updateAccount(data) {
return request({
url: '/bst/account',
method: 'put',
data: data
})
}
// 删除收款账户
export function delAccount(id) {
return request({
url: '/bst/account/' + id,
method: 'delete'
})
}

65
src/api/bst/withdraw.js Normal file
View File

@ -0,0 +1,65 @@
import request from '@/utils/request'
// 查询提现列表
export function listWithdraw(query) {
return request({
url: '/bst/withdraw/list',
method: 'get',
params: query
})
}
// 查询提现详细
export function getWithdraw(id) {
return request({
url: '/bst/withdraw/' + id,
method: 'get'
})
}
// 新增提现
export function addWithdraw(data) {
return request({
url: '/bst/withdraw',
method: 'post',
data: data
})
}
// 修改提现
export function updateWithdraw(data) {
return request({
url: '/bst/withdraw',
method: 'put',
data: data
})
}
// 删除提现
export function delWithdraw(id) {
return request({
url: '/bst/withdraw/' + id,
method: 'delete'
})
}
// 提现审核
export function verifyWithdraw(data) {
return request({
url: '/bst/withdraw/verify',
method: 'put',
data: data
})
}
// 查询提现服务费
export function calcWithdrawAmount(amount, userId) {
return request({
url: '/bst/withdraw/calcAmount',
method: 'get',
params: {
amount,
userId
}
})
}

View File

@ -12,3 +12,16 @@ export function getStat(query) {
params: query
})
}
/**
* 获取每日统计数据
* @param {Object} query 查询参数
* @returns {Promise} 返回每日统计数据
*/
export function getDailyAmount(query) {
return request({
url: '/dashboard/dailyAmount',
method: 'get',
params: query
})
}

View File

@ -1,7 +1,7 @@
<template>
<el-select
v-model="selectedValue"
placeholder="请选择"
<el-select
v-model="selectedValue"
placeholder="请选择"
filterable
:multiple="multiple"
:loading="loading"
@ -18,12 +18,14 @@
{{ isAllSelected ? '取消全选' : '全选' }}
</el-button>
</div>
<el-option
v-for="item in options"
:key="item[prop]"
:value="item[prop]"
:label="item[showProp]"
/>
<slot name="option" :options="options">
<el-option
v-for="item in options"
:key="item[prop]"
:value="item[prop]"
:label="item[showProp]"
/>
</slot>
<el-option v-if="isEmpty(value) && isEmpty(options)" :label="emptyText" disabled :value="null"></el-option>
</el-select>
</template>
@ -65,7 +67,7 @@ export default {
// 使API
if (this.loadApi) {
this.loadData();
}
}
// 使
else if (!isEmpty(this.initOptions)) {
this.options = this.initOptions;
@ -115,11 +117,11 @@ export default {
},
//
getOptions() {
console.log("getOptions", this.beforeGetOptions());
if (!this.beforeGetOptions()) {
return;
}
this.loading = true;
console.log("getOptions", this.query);
Object.assign(this.queryParams, this.query);
this.listApi(this.queryParams).then(res => {
this.options = res.rows;
@ -140,8 +142,8 @@ export default {
justify-content: flex-end;
align-items: center;
line-height: 1em;
text-align: center;
color: #8492a6;
font-size: 13px;
text-align: center;
color: #8492a6;
font-size: 13px;
}
</style>
</style>

View File

@ -0,0 +1,61 @@
<template>
<base-remote-select
prop="id"
show-prop="no"
:list-api="listAccount"
:value="value"
:query="query"
:multiple="multiple"
:init-options="initOptions"
:before-get-options="beforeGetOptions"
v-on="$listeners"
>
<template #option="scope">
<el-option
v-for="item in scope.options"
:key="item.id"
:value="item.id"
:label="label(item)"
/>
</template>
</base-remote-select>
</template>
<script>
import { listAccount } from '@/api/bst/account';
import { $remoteSelect } from '@/components/BaseRemoteSelect/mixins';
import BaseRemoteSelect from '@/components/BaseRemoteSelect';
import { AccountType } from '@/utils/enums';
import { dictLabel } from '@/utils';
export default {
name: 'AccountRemoteSelect',
dicts: ['account_type'],
mixins: [$remoteSelect],
components: {
BaseRemoteSelect
},
data() {
return {
AccountType,
}
},
methods: {
listAccount
},
computed: {
label() {
return (item) => {
if (AccountType.QR == item.type) {
return `收款二维码`;
}
if (AccountType.BANK == item.type) {
return `银行卡 ${item.bankName ? item.bankName : ''} (${item.no.slice(-4)})`;
} else {
return dictLabel(this.dict.type.account_type, item.type) + ` (${item.no.slice(-4)})`;
}
}
}
}
}
</script>

View File

@ -22,7 +22,7 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="登录账号" prop="userName">
<el-form-item label="账号" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入登录账号"
@ -30,22 +30,6 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input
v-model="queryParams.email"
placeholder="请输入邮箱"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
@ -74,11 +58,10 @@
</el-form-item>
</template>
<template #status="{row}">
<dict-tag :options="dict.type.user_status" :value="row.status" />
</template>
<template #isReal="{row}">
<boolean-tag :value="row.isReal" size="small"/>
<template #nickName="{row}">
{{row.nickName | dv}}
<dict-tag :options="dict.type.user_status" :value="row.status" size="mini" style="margin-left: 4px"/>
<boolean-tag :value="row.isReal" size="mini" true-text="已实名" false-text="未实名" style="margin-left: 4px"/>
</template>
<template #point="{row}">
{{ row.point | fix2 | dv }} %
@ -123,7 +106,7 @@ export default {
default: null,
},
// API
listApi: {
listApi: {
type: Function,
default: listUser
},
@ -164,14 +147,12 @@ export default {
//
columns: [
{key: 'userId', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'nickName', visible: true, label: '昵称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'phonenumber', visible: true, label: '手机', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'nickName', visible: true, label: '昵称', minWidth: "200", sortable: true, overflow: false, align: 'left', width: null},
{key: 'userName', visible: true, label: '账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'roles', visible: true, label: '角色', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'point', visible: true, label: '分成比例', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'email', visible: true, label: '邮箱', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'isReal', visible: true, label: '实名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
// {key: 'status', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
// {key: 'isReal', visible: true, label: '', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}
],
}
},

View File

@ -2,7 +2,7 @@
<el-dialog
:visible.sync="dialogVisible"
:title="title"
width="1080px"
width="1200px"
append-to-body
@open="init"
@close="handleClose"
@ -253,4 +253,4 @@ export default {
margin: 10px 0;
}
}
</style>
</style>

View File

@ -17,7 +17,7 @@ import store from './store';
import { getConfigKey } from '@/api/system/config';
import { getDicts } from '@/api/system/dict/data';
import { checkPermi, checkRole } from '@/utils/permission';
import { checkPermi, checkRole, isSysAdmin } from '@/utils/permission';
import { addDateRange, handleTree, parseTime, resetForm, selectDictLabel, selectDictLabels } from '@/utils/ruoyi';
import './assets/icons'; // icon
import './permission'; // permission control
@ -58,6 +58,7 @@ Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.checkPermi = checkPermi
Vue.prototype.checkRole = checkRole
Vue.prototype.isSysAdmin = isSysAdmin
// 全局组件挂载
Vue.component('DictTag', DictTag)

View File

@ -208,3 +208,26 @@ export const StatKeys = {
AREA_COUNT: "area_count", // 运营区数量
MODEL_COUNT: "model_count", // 型号数量
}
// 收款账户类型
export const AccountType = {
WX: "WX", // 线下微信
ALI: "ALI", // 线下支付宝
BANK: "BANK", // 线下银行卡
QR: "QR", // 线下收款二维码
}
// 提现状态
// 提现状态
export const WithdrawStatus = {
WAIT_VERIFY: "WAIT_VERIFY", // 审核中
PAYING: "PAYING", // 打款中
SUCCESS: "SUCCESS", // 已打款
REJECTED: "REJECTED", // 驳回
FAILED: "FAILED", // 打款失败
// 可审核的状态列表
canVerify() {
return [this.WAIT_VERIFY];
}
}

View File

@ -1,4 +1,4 @@
import store from '@/store'
import store from '@/store';
/**
* 字符权限校验
@ -44,4 +44,11 @@ export function checkRole(value) {
console.error(`need roles! Like checkRole="['admin','editor']"`)
return false
}
}
}
/**
* 是否系统管理员
*/
export function isSysAdmin() {
return checkRole(['sysAdmin'])
}

View File

@ -0,0 +1,173 @@
<template>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
width="500px"
append-to-body
:close-on-click-modal="false"
@open="handleOpen"
>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<form-col :span="span" label="所属用户" prop="userId" v-if="isSysAdmin">
<user-input v-model="form.userId" :text.sync="form.userName"/>
</form-col>
<form-col :span="span" label="类型" prop="type">
<el-select v-model="form.type" placeholder="请选择类型" style="width: 100%;">
<el-option
v-for="dict in dict.type.account_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</form-col>
<form-col :span="span" label="微信OpenId" prop="no" label-width="7em" v-if="AccountType.WX == form.type">
<el-input v-model="form.no" placeholder="请输入微信OpenId" />
</form-col>
<form-col :span="span" label="支付宝OpenId" prop="no" label-width="8em" v-if="AccountType.ALI == form.type">
<el-input v-model="form.no" placeholder="请输入支付宝OpenId" />
</form-col>
<form-col :span="span" label="银行卡号" prop="no" label-width="6em" v-if="AccountType.BANK == form.type">
<el-input v-model="form.no" placeholder="请输入银行卡号" />
</form-col>
<form-col :span="span" label="收款二维码" prop="no" label-width="7em" v-if="AccountType.QR == form.type">
<image-upload v-model="form.no" :limit="1"/>
</form-col>
<form-col :span="span" label="收款姓名" prop="name">
<el-input v-model="form.name" placeholder="请输入收款人姓名" />
</form-col>
<form-col :span="span" label="身份证号" prop="idCard">
<el-input v-model="form.idCard" placeholder="请输入身份证号" />
</form-col>
<form-col :span="span" label="手机号" prop="mobile">
<el-input v-model="form.mobile" placeholder="请输入手机号" />
</form-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { getAccount, addAccount, updateAccount } from "@/api/bst/account";
import FormCol from "@/components/FormCol/index.vue";
import UserInput from '@/components/Business/User/UserInput.vue';
import {AccountType} from '@/utils/enums'
export default {
name: 'AccountEditDialog',
components: { FormCol, UserInput },
dicts: ['account_type'],
props: {
visible: {
type: Boolean,
default: false
},
id: {
type: [String, Number],
default: null
},
initData: {
type: Object,
default: () => ({})
}
},
data() {
return {
AccountType,
span: 24,
title: '',
form: {},
rules: {
userId: [
{ required: true, message: "所属用户不能为空", trigger: "blur" }
],
type: [
{ required: true, message: "类型不能为空", trigger: "change" }
],
no: [
{ required: true, message: "账号不能为空", trigger: "blur" }
],
name: [
{ required: true, message: "收款人姓名不能为空", trigger: "blur" }
],
idCard: [
{ required: true, message: "身份证号不能为空", trigger: "blur" }
],
mobile: [
{ required: true, message: "手机号不能为空", trigger: "blur" }
]
}
}
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit('update:visible', val);
}
}
},
methods: {
handleOpen() {
if (this.id == null) {
this.reset();
this.title = "添加收款账户";
} else {
this.getDetail();
this.title = "修改收款账户";
}
},
reset() {
this.form = {
id: null,
userId: null,
type: null,
no: null,
name: null,
idCard: null,
mobile: null,
bankIcon: null,
bankName: null,
bankCardName: null,
bankType: null,
...this.initData
};
this.$nextTick(() => {
this.$refs.form && this.$refs.form.clearValidate();
});
},
getDetail() {
getAccount(this.id).then(response => {
this.form = response.data;
});
},
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
const promise = this.form.id != null ? updateAccount(this.form) : addAccount(this.form);
promise.then(response => {
this.$modal.msgSuccess(this.form.id != null ? "修改成功" : "新增成功");
this.dialogVisible = false;
this.$emit('success');
});
}
});
},
cancel() {
this.dialogVisible = false;
this.reset();
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,317 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="所属用户" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入所属用户"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.account_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="账号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入账号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入收款人姓名"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="身份证" prop="idCard">
<el-input
v-model="queryParams.idCard"
placeholder="请输入身份证号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="银行名称" prop="bankName">
<el-input
v-model="queryParams.bankName"
placeholder="请输入银行名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="卡面名称" prop="bankCardName">
<el-input
v-model="queryParams.bankCardName"
placeholder="请输入银行卡面名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-has-permi="['bst:account:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-has-permi="['bst:account:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-has-permi="['bst:account:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="accountList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'type'">
<dict-tag :options="dict.type.account_type" :value="d.row[column.key]"/>
</template>
<template v-else-if="column.key === 'no'">
<template v-if="d.row.type === AccountType.QR">
<image-preview :src="d.row.no" :width="50" :height="50"/>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-has-permi="['bst:account:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<account-edit-dialog
:visible.sync="dialogVisible"
:id="selectedId"
@success="handleDialogSuccess"
/>
</div>
</template>
<script>
import { listAccount, delAccount } from "@/api/bst/account";
import { $showColumns } from '@/utils/mixins';
import { AccountType } from '@/utils/enums';
import AccountEditDialog from './components/AccountEditDialog.vue';
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "Account",
mixins: [$showColumns],
dicts: ['account_type'],
components: { AccountEditDialog },
data() {
return {
AccountType,
span: 24,
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'userName', visible: true, label: '所属用户', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'type', visible: true, label: '类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'no', visible: true, label: '账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "180"},
{key: 'name', visible: true, label: '收款姓名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'idCard', visible: true, label: '身份证号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "180"},
{key: 'mobile', visible: true, label: '手机号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankName', visible: true, label: '银行名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankCardName', visible: true, label: '卡面名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankType', visible: true, label: '卡面类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
],
//
orderSorts: ['ascending', 'descending', null],
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
accountList: [],
defaultSort,
//
dialogVisible: false,
// ID
selectedId: null,
//
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: defaultSort.prop,
isAsc: defaultSort.order,
id: null,
userId: null,
type: null,
no: null,
name: null,
idCard: null,
mobile: null,
bankName: null,
bankCardName: null,
bankType: null,
}
};
},
created() {
this.getList();
},
methods: {
/** 当排序按钮被点击时触发 **/
onSortChange(column) {
if (column.order == null) {
this.queryParams.orderByColumn = defaultSort.prop;
this.queryParams.isAsc = defaultSort.order;
} else {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
}
this.getList();
},
/** 查询收款账户列表 */
getList() {
this.loading = true;
listAccount(this.queryParams).then(response => {
this.accountList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.selectedId = null;
this.dialogVisible = true;
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除收款账户编号为"' + ids + '"的数据项?').then(function() {
return delAccount(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('bst/account/export', {
...this.queryParams
}, `account_${new Date().getTime()}.xlsx`)
},
/** 弹窗成功回调 */
handleDialogSuccess() {
this.getList();
}
}
};
</script>

View File

@ -1,35 +1,250 @@
<template>
<el-card header="订单统计" shadow="never">
<el-card header="每日流水统计" shadow="never" v-loading="loading">
<el-date-picker
v-model="queryParams.dateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="yyyy-MM-dd"
@change="getDailyAmount"
size="mini"
:clearable="false"
:picker-options="DatePickerOptions.DEFAULT"
/>
<div ref="chart" :style="{width: width, height: height}"></div>
</el-card>
</template>
<script>
import { getOrderDailyAmount } from '@/api/dashboard/dashboardOrder'
import { getDailyAmount } from '@/api/dashboard/dashboard'
import { getLastDateStr } from '@/utils';
import * as echarts from 'echarts';
import $resize from '@/views/dashboard/mixins/resize';
import {DatePickerOptions} from '@/utils/constants';
export default {
name: "OrderDailyStat",
mixins: [$resize],
props: {
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
}
},
data() {
return {
DatePickerOptions,
loading: false,
orderDailyAmount: [],
queryParams: {},
dailyAmount: [],
queryParams: {
dateRange: [
getLastDateStr(7),
getLastDateStr(0)
]
},
chart: null
}
},
created() {
this.getOrderDailyAmount();
this.getDailyAmount();
},
mounted() {
this.initChart();
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose();
this.chart = null;
}
},
methods: {
getOrderDailyAmount() {
getDailyAmount() {
this.loading = true;
getOrderDailyAmount(this.orderQueryParams).then(res => {
this.orderDailyAmount = res.data;
getDailyAmount(this.queryParams).then(res => {
this.dailyAmount = res.data;
this.updateChart();
}).finally(() => {
this.loading = false;
})
},
initChart() {
this.chart = echarts.init(this.$refs.chart);
this.updateChart();
},
resizeChart() {
if (this.chart) {
this.chart.resize();
}
},
updateChart() {
if (!this.chart || !this.dailyAmount.length) return;
const dates = this.dailyAmount.map(item => item.date);
const orderCounts = this.dailyAmount.map(item => item.order?.count || 0);
const orderAmounts = this.dailyAmount.map(item => item.order?.payAmount || 0);
const bonusAmounts = this.dailyAmount.map(item => item.bonus?.amount || 0);
const orderRefunds = this.dailyAmount.map(item => item.orderRefund?.amount || 0);
const bonusRefunds = this.dailyAmount.map(item => item.bonusRefund?.amount || 0);
const orderNetAmounts = this.dailyAmount.map((item, index) =>
(item.order?.payAmount || 0) - (item.orderRefund?.amount || 0)
);
const bonusNetAmounts = this.dailyAmount.map((item, index) =>
(item.bonus?.amount || 0) - (item.bonusRefund?.amount || 0)
);
const option = {
color: [
'#409EFF', // -
'#67C23A', // 绿 -
'#F56C6C', // - 退
'#36CE9E', // 绿 -
'#E6A23C', // -
'#909399', // - 退
'#9B5EF0' // -
],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['订单数量', '订单金额', '订单退款', '订单实收', '分成金额', '分成退款', '分成实收'],
bottom: 0
},
grid: {
left: '3%',
right: '8%',
bottom: '10%',
top: '15%',
containLabel: true
},
xAxis: {
type: 'category',
data: dates,
axisLabel: {
interval: 'auto',
fontSize: 12,
},
boundaryGap: true
},
yAxis: [
{
type: 'value',
name: '金额',
position: 'left',
axisLabel: {
formatter: '{value} 元'
}
},
{
type: 'value',
name: '订单数量',
position: 'right',
axisLabel: {
formatter: '{value}'
}
}
],
series: [
{
name: '订单数量',
type: 'bar',
yAxisIndex: 1,
data: orderCounts,
itemStyle: {
opacity: 0.6
},
barWidth: '20%'
},
{
name: '订单金额',
type: 'line',
yAxisIndex: 0,
data: orderAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '订单退款',
type: 'line',
yAxisIndex: 0,
data: orderRefunds,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '订单实收',
type: 'line',
yAxisIndex: 0,
data: orderNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2
}
},
{
name: '分成金额',
type: 'line',
yAxisIndex: 0,
data: bonusAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '分成退款',
type: 'line',
yAxisIndex: 0,
data: bonusRefunds,
smooth: true,
symbol: 'circle',
symbolSize: 5,
lineStyle: {
width: 2
}
},
{
name: '分成实收',
type: 'line',
yAxisIndex: 0,
data: bonusNetAmounts,
smooth: true,
symbol: 'circle',
symbolSize: 6,
lineStyle: {
width: 2
}
}
]
};
this.chart.setOption(option);
}
}
}
</script>
<style lang="scss" scoped>
</style>
.el-date-picker {
margin-bottom: 20px;
}
</style>

View File

@ -1,48 +1,121 @@
<template>
<el-row :gutter="10">
<el-col :span="span">
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.order.payAmount - stat.orderRefund.amount"
label="订单实收"
icon="el-icon-money"
start-color="#FF4D4F"
end-color="#FF7A45"
icon="el-icon-bank-card"
start-color="#FF6F61"
end-color="#FF9F80"
sub-label="今日订单实收"
:sub-value="todayStat.order.payAmount - todayStat.orderRefund.amount"
:precision="2"
/>
</el-col>
<el-col :span="span">
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.order.count"
label="订单数量"
icon="el-icon-document"
start-color="#FF6F61"
end-color="#FF9F80"
sub-label="今日订单数量"
:sub-value="todayStat.order.count"
/>
</el-col>
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.area.count"
label="总收入"
icon="el-icon-wallet"
start-color="#69C0FF"
end-color="#40A9FF"
sub-label="今日收入"
:sub-value="stat.user.balance"
:precision="2"
/>
</el-col>
<el-col :span="span" class="stat-col" v-if="isSysAdmin()">
<statistics-card
:value="stat.user.balance"
label="商户余额"
icon="el-icon-wallet"
start-color="#69C0FF"
end-color="#40A9FF"
sub-label="待结算金额"
:sub-value="stat.user.balance"
:show-value-change="false"
:precision="2"
/>
</el-col>
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.device.count"
label="车辆总数"
icon="el-icon-bicycle"
start-color="#52C41A"
end-color="#73D13D"
start-color="#73D13D"
end-color="#A0D911"
sub-label="车型总数"
:sub-value="stat.model.count"
:show-value-change="false"
/>
</el-col>
<el-col :span="span">
<el-col :span="span" class="stat-col" v-if="isSysAdmin()">
<statistics-card
:value="stat.area.count"
label="运营区数量"
icon="el-icon-map-location"
start-color="#FFC069"
end-color="#FF9C6E"
sub-label="店铺数量"
:sub-value="stat.user.balance"
:show-value-change="false"
/>
</el-col>
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.user.count"
label="用户总数"
icon="el-icon-user"
start-color="#722ED1"
end-color="#EB2F96"
start-color="#9254DE"
end-color="#F759AB"
sub-label="今日新增"
:sub-value="todayStat.user.count"
/>
</el-col>
<el-col :span="span">
<el-col :span="span" class="stat-col">
<statistics-card
:value="stat.area.count"
label="运营区数量"
icon="el-icon-location"
start-color="#13C2C2"
end-color="#52C41A"
sub-label="商户余额"
label="累计提现"
icon="el-icon-money"
start-color="#FFC069"
end-color="#FF9C6E"
sub-label="审核中"
:sub-value="stat.user.balance"
:show-value-change="false"
:precision="2"
/>
</el-col>
<el-col :span="span" class="stat-col" v-if="!isSysAdmin()">
<statistics-card
:value="stat.area.count"
label="加盟商"
icon="el-icon-money"
start-color="#FFC069"
end-color="#FF9C6E"
sub-label="合伙人"
:sub-value="stat.user.balance"
:show-value-change="false"
/>
</el-col>
<el-col :span="span" class="stat-col" v-if="!isSysAdmin()">
<statistics-card
:value="stat.area.count"
label="用户投诉"
icon="el-icon-warning"
start-color="#FFC069"
end-color="#FF9C6E"
sub-label="故障反馈"
:sub-value="stat.user.balance"
:show-value-change="false"
/>
@ -76,5 +149,7 @@ export default {
</script>
<style lang="scss" scoped>
</style>
.stat-col {
margin-bottom: 10px;
}
</style>

View File

@ -28,6 +28,13 @@
</div>
<div class="unit"></div>
</div>
<div class="todo-item" @click="$router.push('/complaint/abnormal?status=1')">
<div class="label"><i class="el-icon-warning-outline"/> 待处理投诉信息</div>
<div class="value">
<count-to :start-val="0" :end-val="stat.abnormalCount" :duration="3000"/>
</div>
<div class="unit"></div>
</div>
</el-card>
</template>

View File

@ -4,25 +4,21 @@
<el-col :span="18">
<!-- 统计信息 -->
<stat :stat="stat" :today-stat="todayStat" />
<!-- 设备统计信息 -->
<device-stat :stat="stat" style="margin-top: 12px;"/>
<device-stat :stat="stat"/>
<el-row :gutter="gutter" style="margin-top:12px">
<el-col :span="16">
<el-col :span="24">
<order-daily-stat/>
</el-col>
<el-col :span="8">
<el-card header="提现" shadow="never">
待实现
</el-card>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<!-- 待办事项 -->
<todo-list :stat="stat"/>
<el-card style="margin-top: 12px;" header="订单排行" shadow="never">
待实现
</el-card>
@ -107,4 +103,4 @@ export default {
}
}
}
</script>
</script>

View File

@ -0,0 +1,153 @@
<template>
<el-dialog
title="提现申请"
:visible.sync="dialogVisible"
width="450px"
append-to-body
:close-on-click-modal="false"
@open="handleOpen"
>
<el-form ref="form" :model="form" :rules="rules" label-width="6em">
<el-form-item label="提现用户" prop="userId" v-if="isSysAdmin">
<user-input v-model="form.userId" :text.sync="form.userName" @change="handleUserChange"/>
</el-form-item>
<el-form-item label="提现金额" prop="amount">
<el-input-number
v-model="form.amount"
:precision="2"
:step="100"
:min="0"
controls-position="right"
placeholder="请输入提现金额"
style="width: calc(100% - 2em)"
@change="calcWithdrawAmount"
/>
</el-form-item>
<el-form-item label="提现账户" prop="accountId">
<account-remote-select v-model="form.accountId" style="width: 100%;" :query="accountQuery" :before-get-options="beforeGetAccountOptions"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm" :loading="loading"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { addWithdraw, calcWithdrawAmount } from "@/api/bst/withdraw";
import { AccountType } from "@/utils/enums";
import UserInput from "@/components/Business/User/UserInput";
import { mapGetters } from 'vuex';
import AccountRemoteSelect from "@/components/Business/Account/AccountRemoteSelect";
export default {
name: 'WithdrawAddDialog',
dicts: ['account_type', 'withdraw_service_type'],
components: {
UserInput,
AccountRemoteSelect
},
props: {
visible: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false,
AccountType,
form: {},
rules: {
amount: [
{ required: true, message: "提现金额不能为空", trigger: "blur" }
],
accountId: [
{ required: true, message: "提现账户不能为空", trigger: "blur" }
]
}
}
},
computed: {
...mapGetters(['userId', 'nickName']),
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit('update:visible', val);
}
},
//
accountQuery() {
return {
userId: this.form.userId
}
}
},
methods: {
handleUserChange(user) {
if (this.form.accountId != null) {
this.form.accountId = null;
this.$message.info("由于更换用户,请重新选择提现账户");
}
},
beforeGetAccountOptions() {
if (this.form.userId == null) {
this.$modal.msgError('请先选择用户');
return false;
}
return true;
},
calcWithdrawAmount() {
calcWithdrawAmount(this.form.amount, this.form.userId).then(response => {
this.form.serviceType = response.data.type;
this.form.servicePoint = response.data.point;
this.form.serviceCharge = response.data.serviceCharge;
});
},
handleOpen() {
this.reset();
},
reset() {
this.form = {
amount: null,
accountId: null,
userId: this.userId,
userName: this.nickName,
};
this.$nextTick(() => {
this.$refs.form && this.$refs.form.clearValidate();
});
},
submitForm() {
this.$refs.form.validate(valid => {
if (valid) {
this.loading = true;
addWithdraw(this.form).then(response => {
this.$modal.msgSuccess("提交成功");
this.dialogVisible = false;
this.$emit('success');
}).finally(() => {
this.loading = false;
});
}
});
},
cancel() {
this.dialogVisible = false;
this.reset();
}
}
}
</script>
<style lang="scss" scoped>
.el-divider {
margin: 16px 0;
}
</style>

View File

@ -0,0 +1,171 @@
<template>
<el-dialog
title="提现详情"
:visible.sync="dialogVisible"
width="700px"
append-to-body
@open="handleOpen"
>
<el-descriptions :column="2" border v-loading="loading" title="申请信息">
<el-descriptions-item label="提现单号" :span="2">
{{ detail.no }}
<dict-tag :options="dict.type.account_type" :value="detail.accountType" style="margin-left: 4px" size="small"/>
<dict-tag :options="dict.type.withdraw_status" :value="detail.status" style="margin-left: 4px" size="small"/>
</el-descriptions-item>
<el-descriptions-item label="申请时间" :span="2">{{ detail.createTime | dv}}</el-descriptions-item>
<el-descriptions-item label="用户">{{ detail.userName | dv}}</el-descriptions-item>
<el-descriptions-item label="申请金额">{{ detail.amount | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="到账金额">{{ detail.arrivalAmount | fix2 | dv }} </el-descriptions-item>
<el-descriptions-item label="服务费">
{{ detail.serviceCharge | fix2 | dv }}
<dict-tag :options="dict.type.withdraw_service_type" :value="detail.serviceType" size="mini" style="margin-left: 4px"/>
<template v-if="detail.servicePoint">{{ detail.servicePoint | fix2 | dv }} %</template>
</el-descriptions-item>
<el-descriptions-item label="账号" v-if="AccountType.QR != detail.accountType">{{ detail.accountNo | dv}}</el-descriptions-item>
<el-descriptions-item label="姓名">{{ detail.accountName | dv}}</el-descriptions-item>
<el-descriptions-item label="手机号">{{ detail.accountMobile | dv}}</el-descriptions-item>
<el-descriptions-item label="身份证号">{{ detail.accountIdCard | dv}}</el-descriptions-item>
<el-descriptions-item label="银行名称">{{ detail.bankName | dv}}</el-descriptions-item>
<el-descriptions-item label="卡面名称">{{ detail.bankCardName | dv}}</el-descriptions-item>
<el-descriptions-item label="二维码" :span="2" v-if="AccountType.QR == detail.accountType">
<image-preview :src="detail.no" :width="100" :height="100" />
</el-descriptions-item>
</el-descriptions>
<el-form ref="form" :model="form" :rules="rules" label-width="80px" v-if="canVerify">
<el-form-item label="审核意见" prop="remark">
<el-input
type="textarea"
v-model="form.remark"
:rows="3"
placeholder="请输入审核意见"
maxlength="200"
show-word-limit
/>
</el-form-item>
</el-form>
<el-descriptions :column="2" border v-else title="审核结果">
<el-descriptions-item label="审核时间">
{{detail.verifyTime | dv}}
</el-descriptions-item>
<el-descriptions-item label="审核人">
{{detail.verifyUserName | dv}}
</el-descriptions-item>
<el-descriptions-item label="审核意见" :span="2">
{{ detail.verifyRemark | dv}}
</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button type="success" plain @click="submitForm(true)" v-if="canVerify" icon="el-icon-check" :loading="submitLoading"> </el-button>
<el-button type="danger" plain @click="submitForm(false)" v-if="canVerify" icon="el-icon-close" :loading="submitLoading"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { getWithdraw, verifyWithdraw } from "@/api/bst/withdraw";
import { AccountType, WithdrawStatus } from "@/utils/enums";
export default {
name: 'WithdrawVerifyDialog',
dicts: ['account_type', 'withdraw_service_type', 'withdraw_status', 'withdraw_verify_result'],
props: {
visible: {
type: Boolean,
default: false
},
id: {
type: [String, Number],
default: null
}
},
data() {
return {
loading: false,
AccountType,
WithdrawStatus,
detail: {},
form: {
id: null,
pass: null,
remark: null
},
rules: {
},
submitLoading: false,
}
},
computed: {
canVerify() {
return WithdrawStatus.canVerify().includes(this.detail.status)
&& this.checkPermi(['bst:withdraw:verify']);
},
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit('update:visible', val);
}
}
},
methods: {
handleOpen() {
this.reset();
if (this.id != null) {
this.getDetail();
}
},
reset() {
this.detail = {};
this.form = {
id: null,
status: null,
verifyRemark: null
};
this.$nextTick(() => {
this.$refs.form && this.$refs.form.clearValidate();
});
},
getDetail() {
this.loading = true;
getWithdraw(this.id).then(response => {
this.detail = response.data;
this.form.id = response.data.id;
}).finally(() => {
this.loading = false;
});
},
submitForm(pass) {
this.$refs.form.validate(valid => {
if (valid) {
this.form.pass = pass;
this.$confirm(`确定要${pass ? '通过' : '驳回'}吗?`).then(() => {
this.submitLoading = true;
verifyWithdraw(this.form).then(response => {
this.$modal.msgSuccess("操作成功");
this.dialogVisible = false;
this.$emit('success');
}).finally(() => {
this.submitLoading = false;
});
});
}
});
},
cancel() {
this.dialogVisible = false;
this.reset();
}
}
}
</script>
<style lang="scss" scoped>
.el-descriptions {
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,338 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="账户类型" prop="accountType">
<el-select v-model="queryParams.accountType" placeholder="请选择账户类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.account_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="账号" prop="accountNo">
<el-input
v-model="queryParams.accountNo"
placeholder="请输入账号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="账号姓名" prop="accountName">
<el-input
v-model="queryParams.accountName"
placeholder="请输入账号姓名"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号" prop="accountMobile">
<el-input
v-model="queryParams.accountMobile"
placeholder="请输入账户手机号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="身份证号" prop="accountIdCard">
<el-input
v-model="queryParams.accountIdCard"
placeholder="请输入账户身份证号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="银行名称" prop="bankName">
<el-input
v-model="queryParams.bankName"
placeholder="请输入银行名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="卡面名称" prop="bankCardName">
<el-input
v-model="queryParams.bankCardName"
placeholder="请输入银行卡面名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="审核人" prop="verifyUserName">
<el-input
v-model="queryParams.verifyUserName"
placeholder="请输入审核人名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="审核意见" prop="verifyRemark">
<el-input
v-model="queryParams.verifyRemark"
placeholder="请输入审核意见"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="服务类型" prop="serviceType">
<el-select v-model="queryParams.serviceType" placeholder="请选择服务费类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.withdraw_service_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-has-permi="['bst:withdraw:add']"
>申请</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-has-permi="['bst:withdraw:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="withdrawList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="onSortChange">
<el-table-column type="selection" width="55" align="center" />
<template v-for="column of showColumns">
<el-table-column
:key="column.key"
:label="column.label"
:prop="column.key"
:align="column.align"
:min-width="column.minWidth"
:sort-orders="orderSorts"
:sortable="column.sortable"
:show-overflow-tooltip="column.overflow"
:width="column.width"
>
<template slot-scope="d">
<template v-if="column.key === 'id'">
{{d.row[column.key]}}
</template>
<template v-else-if="column.key === 'no'">
{{d.row.no | dv}}
<dict-tag :options="dict.type.account_type" :value="d.row.accountType" size="mini" style="margin-left: 4px"/>
<dict-tag :options="dict.type.withdraw_status" :value="d.row.status" size="mini" style="margin-left: 4px"/>
</template>
<template v-else-if="column.key === 'serviceCharge'">
{{d.row.serviceCharge | fix2 | dv}} <br/>
<dict-tag :options="dict.type.withdraw_service_type" :value="d.row.serviceType" size="mini" style="margin-left: 4px"/>
<template v-if="d.row.servicePoint">{{d.row.servicePoint | fix2 | dv}} %</template>
</template>
<template v-else-if="['amount', 'arrivalAmount'].includes(column.key)">
{{d.row[column.key] | fix2 | dv}}
</template>
<template v-else>
{{d.row[column.key]}}
</template>
</template>
</el-table-column>
</template>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
v-has-permi="['bst:withdraw:query']"
>详情 / 审核</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<withdraw-verify-dialog
:visible.sync="verifyDialogVisible"
:id="selectedId"
@success="getList"
/>
<withdraw-add-dialog
:visible.sync="addDialogVisible"
@success="getList"
/>
</div>
</template>
<script>
import { listWithdraw} from "@/api/bst/withdraw";
import { $showColumns } from '@/utils/mixins';
import FormCol from "@/components/FormCol/index.vue";
import WithdrawVerifyDialog from '@/views/bst/withdraw/components/WithdrawVerifyDialog.vue';
import WithdrawAddDialog from '@/views/bst/withdraw/components/WithdrawAddDialog.vue';
//
const defaultSort = {
prop: "createTime",
order: "descending"
}
export default {
name: "Withdraw",
mixins: [$showColumns],
dicts: ['account_type', 'withdraw_service_type', 'withdraw_status'],
components: {FormCol, WithdrawVerifyDialog, WithdrawAddDialog},
data() {
return {
span: 24,
selectedId: null,
//
columns: [
{key: 'id', visible: false, label: 'ID', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
{key: 'no', visible: true, label: "提现单号", minWidth: "180", sortable: true, overflow: false, align: 'left', width: null},
{key: 'userName', visible: true, label: '用户', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'amount', visible: true, label: '申请金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'arrivalAmount', visible: true, label: '到账金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'serviceCharge', visible: true, label: '服务费', minWidth: null, sortable: true, overflow: false, align: 'center', width: "150"},
{key: 'accountNo', visible: true, label: '账号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "200"},
{key: 'accountName', visible: false, label: '姓名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'accountMobile', visible: false, label: '手机号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'accountIdCard', visible: false, label: '身份证号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankName', visible: false, label: '银行', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankCardName', visible: false, label: '卡名', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'bankType', visible: false, label: '卡类型', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'verifyUserName', visible: true, label: '审核人', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'verifyTime', visible: true, label: '审核时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'verifyRemark', visible: true, label: '审核意见', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
{key: 'createTime', visible: true, label: '申请时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
],
//
orderSorts: ['ascending', 'descending', null],
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
withdrawList: [],
//
verifyDialogVisible: false,
addDialogVisible: false,
defaultSort,
//
queryParams: {
pageNum: 1,
pageSize: 20,
orderByColumn: defaultSort.prop,
isAsc: defaultSort.order,
id: null,
userId: null,
accountId: null,
accountType: null,
accountNo: null,
accountName: null,
accountMobile: null,
accountIdCard: null,
bankName: null,
bankCardName: null,
bankType: null,
verifyUserId: null,
verifyRemark: null,
serviceType: null,
}
};
},
created() {
this.getList();
},
methods: {
handleView(row) {
this.selectedId = row.id;
this.verifyDialogVisible = true;
},
/** 当排序按钮被点击时触发 **/
onSortChange(column) {
if (column.order == null) {
this.queryParams.orderByColumn = defaultSort.prop;
this.queryParams.isAsc = defaultSort.order;
} else {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
}
this.getList();
},
/** 查询提现列表 */
getList() {
this.loading = true;
listWithdraw(this.queryParams).then(response => {
this.withdrawList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.addDialogVisible = true;
},
/** 导出按钮操作 */
handleExport() {
this.download('bst/withdraw/export', {
...this.queryParams
}, `withdraw_${new Date().getTime()}.xlsx`)
}
}
};
</script>