509 lines
20 KiB
Vue
509 lines
20 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||
<template #left>
|
||
<table-search-date ref="searchDateRef" v-model:dateRange="dateRange" @dateChange="handleQuery" v-model:operateTimeType="operateTimeType"></table-search-date>
|
||
<TenantSelect ref="tenantSelectRef" v-model="queryParams.tenantKey" :placeholder="t('请选择商户账号')" style="width: 300px" />
|
||
<el-form-item :label="t('状态')" prop="status">
|
||
<CustomSelect v-model="queryParams.status" :options="tenantStatusArr" placeholder="请选择状态" style="width: 200px" />
|
||
</el-form-item>
|
||
|
||
</template>
|
||
<template #right>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleAdd" v-hasPermi="['super:order:charge']">{{ t('充值') }}</el-button>
|
||
</el-form-item>
|
||
</template>
|
||
</table-search-card>
|
||
|
||
<el-table v-loading="loading" class="c-table-main" :data="agentList" border>
|
||
<!-- <el-table-column type="selection" width="55" align="center" /> -->
|
||
<el-table-column :label="t('订单号')" min-width="160" align="center" prop="orderId" />
|
||
<el-table-column :label="t('商户账号')" align="center" prop="tenantKey" min-width="150" />
|
||
<!-- <el-table-column :label="t('前缀')" width="100" align="center" prop="tenantSn" /> -->
|
||
<el-table-column :label="t('平台币种')" align="center" prop="currencyCode" />
|
||
<el-table-column :label="t('汇率')" width="100" align="center" prop="exchangeRate" >
|
||
<template #default="{row}">
|
||
<span v-if="row.exchangeRate">{{ row.exchangeRate }}</span>
|
||
<span v-else>--</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('充值前额度')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
{{ row.balanceBefore?row.balanceBefore:'--' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('充值额度')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
{{ row.accountBalance?row.accountBalance:'--' }}
|
||
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('充值后额度')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
{{ row.balanceAfter?row.balanceAfter:'--' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('实付USDT')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
{{ row.payAmount?row.payAmount:'--' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('币种协议')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
<span v-if="row.currencyAgreement == 0">USDT-TRC20</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('类别')" align="center" prop="tenantType">
|
||
<template #default="{row}">
|
||
<span v-if="row.status == 0" class="text-danger">待支付</span>
|
||
<span v-if="row.status == 1" class="text-warning">待系统确认</span>
|
||
<span v-if="row.status == 2" class="text-navy">支付成功</span>
|
||
<span v-if="row.status == 3" class="text-danger">后台取消</span>
|
||
<span v-if="row.status == 4" class="text-danger">超时取消</span>
|
||
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('创建时间')" align="center" prop="createTime" min-width="180">
|
||
<template #default="scope">{{ parseTime(scope.row.createTime) }}</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
|
||
<template #default="{row}">
|
||
<el-button v-if="row.status == 0" link v-hasPermi="['super:order:confirm']" type="primary" @click="confirmPayment(row)" >{{ t('确认支付') }}</el-button>
|
||
<el-button v-if="row.status == 1 || row.status == 0" link v-hasPermi="['super:order:cancel']" type="primary" @click="forcedCancel(row)" >{{ t('取消充值') }}</el-button>
|
||
<el-button v-if="row.status == 1" link v-hasPermi="['super:order:refresh']" type="primary" @click="refreshStatus(row)" >{{ t('刷新状态') }}</el-button>
|
||
<el-button v-if="row.status == 1 || row.status == 0" link type="primary" v-hasPermi="['super:order:income']" @click="forcedDeposit(row)" >{{ t('强制入款') }}</el-button>
|
||
<span v-else>--</span>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<pagination
|
||
v-show="total > 0"
|
||
:total="total"
|
||
v-model:page="queryParams.pageNum"
|
||
v-model:limit="queryParams.pageSize"
|
||
@pagination="getList"
|
||
/>
|
||
|
||
<!-- 添加或修改定时任务对话框 -->
|
||
<el-dialog :title="t('额度充值')" modal-class="topMaing1" align-center v-model="open" width="520px">
|
||
<el-form ref="agentRef" :model="formAll" :rules="rules" label-width="120px">
|
||
<el-form-item :label="t('充值币种')" prop="currencyCode">
|
||
<CustomSelect v-model="formAll.currencyCode" @change="handleCurrencyCodeChange" :options="sys_job_group" placeholder="请选择币种" />
|
||
</el-form-item>
|
||
<el-form-item :label="t('充值额度')" prop="amount">
|
||
<el-input-number v-model="formAll.amount" :min="resultObj.initChargeQuota" :step="resultObj.initChargeQuota"></el-input-number>
|
||
</el-form-item>
|
||
<el-form-item :label="t('币种协议')" prop="currencyAgreement">
|
||
<CustomSelect v-model="formAll.currencyAgreement" :options="usdtSelect" placeholder="请选择币种协议" />
|
||
</el-form-item>
|
||
<!-- <el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||
<el-input v-model="formAll.googleCode" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
||
</el-form-item> -->
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
|
||
<el-button @click="cancel">{{ t('取 消') }}</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 充值二维码 -->
|
||
<el-dialog modal-class="topMaing1" align-center v-model="codeOpen" width="520px">
|
||
<template #title>
|
||
<div style="width: 100%;text-align: center;">
|
||
{{ t('额度充值') }}
|
||
</div>
|
||
</template>
|
||
<div style="width: 100%; text-align: center;">
|
||
<div style="margin-bottom: 20px;"><span style="color: #409EFF;">应付USDT-TRC20:</span><span style="color: red;">{{ codeItem.payAmount }}</span></div>
|
||
<div><img style="width: 270px;" :src="codeItem.walletQrCode"/></div>
|
||
<div>过期时间:<span style="color: red;">{{ parseTime(codeItem.cancelTime) }}</span></div>
|
||
<div style="width: 100%;display: flex; justify-content: center;margin-top: 20px;">
|
||
<el-input v-model="codeItem.walletAddress" style="width: 280px;margin-right: 20px;" disabled />
|
||
<el-button type="primary" @click="handleCopy(codeItem.walletAddress)">{{ t('复制') }}</el-button>
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<div class="dialog-footer" style="width: 100%;text-align: center;">
|
||
<!-- <el-button type="primary" @click="submitForm">{{ t('确 定') }}</el-button> -->
|
||
<el-button @click="codeOpen = false">{{ t('关 闭') }}</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 确认支付 -->
|
||
<el-dialog modal-class="topMaing1" align-center v-model="paymentOpen" width="620px">
|
||
<template #title>
|
||
<div style="width: 100%;text-align: center;">
|
||
{{ t('确认支付') }}
|
||
</div>
|
||
</template>
|
||
<el-alert :title="t('注意事项:每个钱包转账成功后,都会有如下的txid(哈希id),请填写正确的id,以下是OKX的txid获取方式,其他钱包类似。')" :closable="false" type="warning" />
|
||
<div style="width: 100%;text-align: center;">
|
||
<img style="width: 100%;" src="@/assets/images/pay1.png"/>
|
||
</div>
|
||
<el-form ref="agentRef" :model="formAll" :rules="rules" label-width="120px">
|
||
<el-form-item :label="t('区块链交易ID')" prop="txid">
|
||
<el-input v-model="formAll.txid" :placeholder="t('请输入区块链交易ID')" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer" style="width: 100%;text-align: center;">
|
||
<el-button type="primary" @click="submitFormPay" :loading="loadingButton">{{ t('确 定') }}</el-button>
|
||
<el-button @click="paymentOpen = false">{{ t('取 消') }}</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
|
||
<!-- 详情 -->
|
||
<el-dialog :title="t('成本比例')" align-center v-model="openView" width="820px" append-to-body>
|
||
<el-form :model="form" :rules="rules" label-width="120px">
|
||
<el-form-item :label="t('商户账号')" prop="account">
|
||
<el-input :disabled="openView" v-model="form.account" :placeholder="t('请输入商户账号')" />
|
||
</el-form-item>
|
||
<el-form-item :label="t('商户模式')" prop="tenantType">
|
||
<el-radio-group v-model="form.tenantType" :disabled="openView">
|
||
<el-radio-button v-for="item in ff_tenant_type" :key="item.value" :value="item.value">{{ item.label }}</el-radio-button>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item :label="t('买分比例')" >
|
||
<el-input :disabled="openView" v-model="form.scoreRatio" placeholder="" />
|
||
</el-form-item>
|
||
<div class="label-scoreRatio">
|
||
<span>{{ t('平台比例') }}</span>
|
||
<div>
|
||
<el-button type="danger" :disabled="openView">-0.5</el-button>
|
||
<el-button type="primary" :disabled="openView">+0.5</el-button>
|
||
</div>
|
||
</div>
|
||
<el-table :data="form.tenantAgentPlatforms" class="scoreRatioTable">
|
||
<el-table-column :label="t('平台')" align="center" prop="platformCode" />
|
||
<el-table-column :label="t('币种')" align="center" prop="currencyCode" />
|
||
<el-table-column :label="t('成本比例(%)')" align="center" prop="cost">
|
||
<template #default="scope">
|
||
{{ scope.row.cost }}%
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="t('商户通用比例(%)')" align="center" prop="useCost">
|
||
<template #default="scope">
|
||
{{ scope.row.useCost }}%
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="openView = false">{{ t('关 闭') }}</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup name="Agent">
|
||
import { selectPlatform } from "@/api/agent";
|
||
import { superOrderList,getSuperAgentInf,superOrderCreate,superOrderCancel,superOrderConfirm,superOrderRefresh } from "@/api/super/order";
|
||
import { getLocalStorage } from "@/utils/auth";
|
||
import CustomSelect from '@/components/CustomSelect'
|
||
import TableSearchDate from '@/components/TableSearchDate'
|
||
import Crontab from '@/components/Crontab'
|
||
import TenantSelect from '@/components/TenantSelect';
|
||
import { parseTime } from '@/utils/ruoyi'; // 时间格式化
|
||
import { nextTick, onMounted } from "vue";
|
||
const router = useRouter();
|
||
const { proxy } = getCurrentInstance();
|
||
const { ff_tenant_type, ff_tenant_status } = proxy.useDict("ff_tenant_type", "ff_tenant_status");
|
||
|
||
|
||
const agentList = ref([]);
|
||
const open = ref(false);
|
||
const loading = ref(true);
|
||
const showSearch = ref(true);
|
||
const ids = ref([]);
|
||
const single = ref(true);
|
||
const multiple = ref(true);
|
||
const total = ref(0);
|
||
const title = ref("");
|
||
const openView = ref(false);
|
||
const openCron = ref(false);
|
||
const expression = ref("");
|
||
const tenantAgentPlatforms = ref([]);
|
||
const dateRange = ref([]),operateTimeType = ref("day");
|
||
const loadingButton = ref(false);
|
||
const formAll = reactive({
|
||
currencyAgreement:'0',
|
||
});
|
||
const data = reactive({
|
||
form: {},
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
orderByColumn:'tro.createTime',
|
||
isAsc:'desc',
|
||
tenantKey: "",
|
||
status:''
|
||
},
|
||
rules: {
|
||
account: [{ required: true, message: proxy.t('商户账号不能为空'), trigger: "blur" }],
|
||
password: [{ required: true, message: proxy.t('密码不能为空'), trigger: "blur" }],
|
||
scoreRatio: [{ required: true, message: proxy.t('买分比例不能为空'), trigger: "blur" }],
|
||
currencyCode:[{ required: true, message: proxy.t('币种不能为空'), trigger: "change" }],
|
||
amount: [{ required: true, message: proxy.t('充值额度不能为空'), trigger: "change" }],
|
||
currencyAgreement:[
|
||
{ required: true, message: proxy.t('币种协议'), trigger: "change" }
|
||
],
|
||
googleCode:[{ required: true, message: proxy.t('谷歌验证码不能为空'), trigger: "change" }],
|
||
tenantType: [{ required: true, message: proxy.t('商户模式不能为空'), trigger: "change" }],
|
||
txid: [{ required: true, message: proxy.t('区块链交易ID不能为空'), trigger: "change" }],
|
||
}
|
||
});
|
||
|
||
const { queryParams, form, rules } = toRefs(data);
|
||
|
||
/** 查询列表 */
|
||
function getList() {
|
||
loading.value = true;
|
||
superOrderList(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
|
||
agentList.value = response.rows;
|
||
total.value = response.total;
|
||
loading.value = false;
|
||
});
|
||
}
|
||
const tenantStatusArr = ref([
|
||
{ label: '待支付', value: '0' },
|
||
{ label: '待系统确认', value: '1' },
|
||
{ label: '支付成功', value: '2' },
|
||
{ label: '后台取消', value: '3' },
|
||
{ label: '超时取消', value: '4' },
|
||
]);
|
||
/** 任务组名字典翻译 */
|
||
function jobGroupFormat(row, column) {
|
||
return proxy.selectDictLabel(sys_job_group.value, row.jobGroup);
|
||
}
|
||
const sys_job_group = ref([]);
|
||
const showLoding1 = ref(true);
|
||
const getsuperCommonCurrencySelect = async () => {
|
||
showLoding1.value = false;
|
||
let response = getLocalStorage('currencySelect');
|
||
sys_job_group.value = response.map(item => {
|
||
return { ...item, label:`${item.currencyName}(${item.currencyCode})`, value: item.currencyCode }
|
||
})
|
||
formAll.currencyCode = sys_job_group.value[0].currencyCode;
|
||
formAll.amount = sys_job_group.value[0].initChargeQuota;
|
||
resultObj.value = sys_job_group.value[0];
|
||
nextTick(() => {
|
||
showLoding1.value = true;
|
||
})
|
||
}
|
||
const resultObj = ref({});
|
||
const usdtSelect = ref([
|
||
{ label: 'USDT-TRC20', value: '0' },
|
||
]);
|
||
const handleCurrencyCodeChange = (value) => {
|
||
const result = sys_job_group.value.find(item => item.currencyCode == value);
|
||
resultObj.value = result;
|
||
formAll.amount = result.initChargeQuota;
|
||
}
|
||
/** 取消按钮 */
|
||
function cancel() {
|
||
open.value = false;
|
||
loadingButton.value = false;
|
||
reset();
|
||
}
|
||
|
||
/** 表单重置 */
|
||
function reset() {
|
||
form.value = {
|
||
account: "",
|
||
password: "",
|
||
scoreRatio: 1,
|
||
tenantType: 1,
|
||
tenantAgentPlatforms: [],
|
||
};
|
||
proxy.resetForm("agentRef");
|
||
}
|
||
|
||
/** 搜索按钮操作 */
|
||
function handleQuery() {
|
||
queryParams.value.pageNum = 1;
|
||
getList();
|
||
}
|
||
const searchDateRef = ref(null);
|
||
|
||
/** 重置按钮操作 */
|
||
function resetQuery() {
|
||
dateRange.value = [];
|
||
operateTimeType.value = "day";
|
||
proxy.resetForm("queryRef");
|
||
searchDateRef.value.timeTypeChange(operateTimeType.value)
|
||
}
|
||
//取消订单
|
||
const forcedCancel = (row) => {
|
||
proxy.$modal.confirm(proxy.t('确认此操作?')).then(() => {
|
||
return superOrderCancel(row.id);
|
||
}).then(() => {
|
||
getList();
|
||
proxy.$modal.msgSuccess(proxy.t('取消成功'));
|
||
}).catch(() => { });
|
||
|
||
};
|
||
//强制入款
|
||
const forcedDeposit = (row) => {
|
||
proxy.$prompt('请输入谷歌验证码', "提示", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
closeOnClickModal: false,
|
||
inputValidator: (value) => {
|
||
if (!value) {
|
||
return '验证码不能为空';
|
||
}
|
||
return true;
|
||
}
|
||
}).then(({ value }) => {
|
||
getSuperAgentInf(row.id,value).then(res => {
|
||
getList();
|
||
proxy.$modal.msgSuccess(proxy.t('入款成功'));
|
||
})
|
||
|
||
}).catch(() => {});
|
||
}
|
||
const paymentOpen = ref(false);
|
||
const confirmPayment = (row) => {
|
||
paymentOpen.value = true;
|
||
formAll.id = row.id;
|
||
};
|
||
const refreshStatus = (row) => {
|
||
proxy.$modal.confirm(proxy.t('确认此操作?')).then(() => {
|
||
return superOrderRefresh(row.id);
|
||
}).then(() => {
|
||
getList();
|
||
proxy.$modal.msgSuccess(proxy.t('刷新成功'));
|
||
}).catch(() => {
|
||
|
||
});
|
||
};
|
||
/** 获取平台利润 */
|
||
function getSelectPlatform() {
|
||
selectPlatform().then(response => {
|
||
form.value.tenantAgentPlatforms = response.data;
|
||
tenantAgentPlatforms.value = JSON.parse(JSON.stringify(response.data));
|
||
});
|
||
}
|
||
|
||
/** 新增按钮操作 */
|
||
function handleAdd() {
|
||
reset();
|
||
// getSelectPlatform();
|
||
open.value = true;
|
||
title.value = proxy.t('添加商户');
|
||
}
|
||
|
||
const codeOpen = ref(false);
|
||
const codeItem = ref({});
|
||
|
||
const submitFormPay = () => {
|
||
proxy.$refs["agentRef"].validate(valid => {
|
||
if (valid) {
|
||
loadingButton.value = true;
|
||
let obj = {
|
||
id:formAll.id,
|
||
txid: formAll.txid
|
||
}
|
||
superOrderConfirm(obj).then(response => {
|
||
loadingButton.value = false;
|
||
proxy.$modal.msgSuccess(proxy.t('确认成功'));
|
||
paymentOpen.value = false;
|
||
getList();
|
||
});
|
||
|
||
}
|
||
})
|
||
};
|
||
|
||
/** 提交按钮 */
|
||
function submitForm() {
|
||
proxy.$refs["agentRef"].validate(valid => {
|
||
if (valid) {
|
||
loadingButton.value = true;
|
||
proxy.$modal.confirm(proxy.t('确认是否继续充值?')).then(() => {
|
||
superOrderCreate(formAll).then(response => {
|
||
proxy.$modal.msgSuccess(proxy.t('创建成功'));
|
||
open.value = false;
|
||
loadingButton.value = false;
|
||
codeOpen.value = true;
|
||
codeItem.value = response.data;
|
||
getList();
|
||
});
|
||
}).catch(() => {
|
||
loadingButton.value = false;
|
||
});
|
||
|
||
}
|
||
});
|
||
}
|
||
const handleCopy = async(text) => {
|
||
// 支持现代 API:需 HTTPS 或 localhost
|
||
if (navigator.clipboard && window.isSecureContext) {
|
||
proxy.$modal.msgSuccess('复制成功');
|
||
return navigator.clipboard.writeText(text);
|
||
}
|
||
|
||
// fallback:兼容 HTTP、老浏览器、iframe 等环境
|
||
return new Promise((resolve, reject) => {
|
||
try {
|
||
const textarea = document.createElement('textarea');
|
||
textarea.value = text;
|
||
|
||
// 设置样式防跳动
|
||
textarea.style.position = 'fixed';
|
||
textarea.style.top = '-9999px';
|
||
textarea.style.left = '-9999px';
|
||
textarea.setAttribute("readonly", true);
|
||
document.body.appendChild(textarea);
|
||
textarea.select();
|
||
|
||
const success = document.execCommand("copy");
|
||
copyTextSuccess();
|
||
document.body.removeChild(textarea);
|
||
|
||
success ? resolve() : reject(new Error("execCommand copy failed"));
|
||
} catch (err) {
|
||
reject(err);
|
||
}
|
||
});
|
||
}
|
||
//初始化
|
||
onMounted(() => {
|
||
getsuperCommonCurrencySelect();
|
||
getList();
|
||
})
|
||
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.label-scoreRatio{
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 10px;
|
||
span{
|
||
width: 120px;
|
||
text-align: right;
|
||
font-weight: 700;
|
||
padding-right: 12px;
|
||
}
|
||
}
|
||
.scoreRatioTable{
|
||
width: calc(100% - 120px);
|
||
margin-left: 120px;
|
||
}
|
||
:deep(.topMaing1 .el-dialog:not(.is-fullscreen)) {
|
||
margin-top: auto !important;
|
||
}
|
||
</style>
|
||
|