BUG修复,及部分页面增加按钮权限
This commit is contained in:
parent
adcbbb6752
commit
2f54ebef78
|
|
@ -416,6 +416,7 @@ const handleSubmit = async () => {
|
|||
try {
|
||||
await editCustomerApi({ ...params, point_diffs_json: JSON.stringify(marginRatioJSON) })
|
||||
dialogVisible.value = false
|
||||
await getCustomerList(userId.value)
|
||||
} catch (err) {
|
||||
console.log('提交失败:', err)
|
||||
}
|
||||
|
|
@ -428,6 +429,7 @@ const handleSubmit = async () => {
|
|||
fee_handling_percent: commissionRatioForm.value.commissionRatio,
|
||||
})
|
||||
dialogVisible.value = false
|
||||
await getCustomerList(userId.value)
|
||||
} catch (err) {
|
||||
console.log('提交失败:', err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="deposit-channel">
|
||||
<div class="bar">
|
||||
<el-button type="primary" @click="handleAdd">添加</el-button>
|
||||
<el-button type="primary" @click="handleEdit">编辑</el-button>
|
||||
<el-button type="danger" @click="handleDelete">删除</el-button>
|
||||
<el-button type="primary" @click="handleAdd" v-auth="'channel_createChannel'">添加</el-button>
|
||||
<el-button type="primary" @click="handleEdit" v-auth="'channel_editChannel'">编辑</el-button>
|
||||
<el-button type="danger" @click="handleDelete" v-auth="'channel_delChannel'">删除</el-button>
|
||||
</div>
|
||||
<DepositChannelTable
|
||||
ref="tableRef"
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@
|
|||
>
|
||||
<template #button>
|
||||
<!-- 审核动作先保留按钮交互,后续可直接接接口 -->
|
||||
<el-button type="danger" plain @click="handleReject">驳回</el-button>
|
||||
<el-button type="success" @click="handleApprove">通过</el-button>
|
||||
<el-button type="danger" plain @click="handleReject" v-auth="'user_reviewRechargeOrder'"
|
||||
>驳回</el-button
|
||||
>
|
||||
<el-button type="success" @click="handleApprove" v-auth="'user_reviewRechargeOrder'"
|
||||
>通过</el-button
|
||||
>
|
||||
<el-button type="primary" plain @click="handleExport">导出</el-button>
|
||||
</template>
|
||||
</RechangeSearch>
|
||||
|
|
|
|||
|
|
@ -1,77 +1,125 @@
|
|||
<template>
|
||||
<div class="transfer">
|
||||
<div class="title">转账</div>
|
||||
<el-card class="transfer-card">
|
||||
<div class="transfer-item">1.佣金钱包转出时,需要管理员审核通过后才能转账成功。其余内部转账操作无需通过管理员审核,如发现对应账号没有收到转账资金,请于客服人员联系。</div>
|
||||
<div class="transfer-item">2.如转出账号与转入账号的货币单位不同,系统将按照当日汇率进行换算</div>
|
||||
<div class="transfer-item">3.若有在途订单时进行了MT账号的转出操作,因浮动盈亏影响,可能会导致转出失败</div>
|
||||
<div class="transfer-item">4.第三方转账只支持钱包之间转账,且会转到对方主钱包(佣金钱包不允许转入),需要管理员审核通过后才能转账成功</div>
|
||||
</el-card>
|
||||
<div class="transfer-type">
|
||||
<div class="type-title">转账类型</div>
|
||||
<div class="tab">
|
||||
<el-button :type="transferType === 'internal' ? 'primary' : 'default'"
|
||||
@click="handleTransferTabClick('internal')">内部转账</el-button>
|
||||
<el-button :type="transferType === 'external' ? 'primary' : 'default'"
|
||||
@click="handleTransferTabClick('external')">第三方转账</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="transfer-form">
|
||||
<div class="external-item" v-if="transferType === 'external'">
|
||||
<div class="externa-title">转出账号: 主钱包</div>
|
||||
<el-card class="external-card">
|
||||
<el-icon>
|
||||
<svg t="1774503695687" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="2732" width="200" height="200">
|
||||
<path
|
||||
d="M512.54 156.23a353.21 353.21 0 1 1-138 27.83 352.25 352.25 0 0 1 138-27.83m0-60C283.61 96.23 98 281.81 98 510.74s185.61 414.51 414.54 414.51 414.51-185.58 414.51-414.51S741.47 96.23 512.54 96.23z"
|
||||
p-id="2733"></path>
|
||||
<path
|
||||
d="M512 478a29.89 29.89 0 0 1-21.13-8.71l-133-132a30 30 0 1 1 42.26-42.58l133 132A30 30 0 0 1 512 478z"
|
||||
p-id="2734"></path>
|
||||
<path
|
||||
d="M512 478a30 30 0 0 1-21.21-51.21l128-128a30 30 0 0 1 42.42 42.42l-128 128A29.88 29.88 0 0 1 512 478z"
|
||||
p-id="2735"></path>
|
||||
<path
|
||||
d="M660 529H366a30 30 0 0 1 0-60h294a30 30 0 0 1 0 60z m0 95H366a30 30 0 0 1 0-60h294a30 30 0 0 1 0 60z"
|
||||
p-id="2736"></path>
|
||||
<path d="M512 776a30 30 0 0 1-30-30V448a30 30 0 0 1 60 0v298a30 30 0 0 1-30 30z"
|
||||
p-id="2737"></path>
|
||||
</svg>
|
||||
</el-icon>
|
||||
<div class="money">
|
||||
<span>USD</span>
|
||||
<span>{{ transferForm.MaxOutAmount }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<TransferForm :key="transferType" class="transfer-main-form" :form-data="transferForm" :form-rules="transferFormRules"
|
||||
:form-items="transferFormItemOptions" :options-map="transferFormOptionsMap" ref="mainTransferFormRef">
|
||||
</TransferForm>
|
||||
<div class="transfer-type verify" v-if="transferType === 'external'">
|
||||
<div class="type-title">验证方式</div>
|
||||
<div class="tab">
|
||||
<el-button :type="verifyType === 'email' ? 'primary' : 'default'"
|
||||
@click="handleVerifyTabClick('email')">邮箱验证</el-button>
|
||||
<el-button :type="verifyType === 'phone' ? 'primary' : 'default'"
|
||||
@click="handleVerifyTabClick('phone')">手机号验证</el-button>
|
||||
</div>
|
||||
<div class="username">{{ verifyType === "email" ? userInfo.email : userInfo.phone }}</div>
|
||||
<el-form class="verify-form" :model="transferForm" :rules="transferFormRules" ref="verifyFormRef">
|
||||
<el-form-item prop="code">
|
||||
<el-input v-model="transferForm.code" style="max-width: 300px" placeholder="请输入验证码">
|
||||
|
||||
</el-input>
|
||||
<el-button type="primary" @click="handleSendCode" :disabled="sendState.isCounting">{{
|
||||
sendState.isCounting ? `${sendState.countdown}s后重新获取` : '发送验证码' }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
<el-button type="primary" @click="handleSubmit">提交转账</el-button>
|
||||
</div>
|
||||
|
||||
<div class="transfer">
|
||||
<div class="title">转账</div>
|
||||
<el-card class="transfer-card">
|
||||
<div class="transfer-item">
|
||||
1.佣金钱包转出时,需要管理员审核通过后才能转账成功。其余内部转账操作无需通过管理员审核,如发现对应账号没有收到转账资金,请于客服人员联系。
|
||||
</div>
|
||||
<div class="transfer-item">
|
||||
2.如转出账号与转入账号的货币单位不同,系统将按照当日汇率进行换算
|
||||
</div>
|
||||
<div class="transfer-item">
|
||||
3.若有在途订单时进行了MT账号的转出操作,因浮动盈亏影响,可能会导致转出失败
|
||||
</div>
|
||||
<div class="transfer-item">
|
||||
4.第三方转账只支持钱包之间转账,且会转到对方主钱包(佣金钱包不允许转入),需要管理员审核通过后才能转账成功
|
||||
</div>
|
||||
</el-card>
|
||||
<div class="transfer-type">
|
||||
<div class="type-title">转账类型</div>
|
||||
<div class="tab">
|
||||
<el-button
|
||||
:type="transferType === 'internal' ? 'primary' : 'default'"
|
||||
@click="handleTransferTabClick('internal')"
|
||||
>内部转账</el-button
|
||||
>
|
||||
<el-button
|
||||
:type="transferType === 'external' ? 'primary' : 'default'"
|
||||
@click="handleTransferTabClick('external')"
|
||||
>第三方转账</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="transfer-form">
|
||||
<div class="external-item" v-if="transferType === 'external'">
|
||||
<div class="externa-title">转出账号: 主钱包</div>
|
||||
<el-card class="external-card">
|
||||
<el-icon>
|
||||
<svg
|
||||
t="1774503695687"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2732"
|
||||
width="200"
|
||||
height="200"
|
||||
>
|
||||
<path
|
||||
d="M512.54 156.23a353.21 353.21 0 1 1-138 27.83 352.25 352.25 0 0 1 138-27.83m0-60C283.61 96.23 98 281.81 98 510.74s185.61 414.51 414.54 414.51 414.51-185.58 414.51-414.51S741.47 96.23 512.54 96.23z"
|
||||
p-id="2733"
|
||||
></path>
|
||||
<path
|
||||
d="M512 478a29.89 29.89 0 0 1-21.13-8.71l-133-132a30 30 0 1 1 42.26-42.58l133 132A30 30 0 0 1 512 478z"
|
||||
p-id="2734"
|
||||
></path>
|
||||
<path
|
||||
d="M512 478a30 30 0 0 1-21.21-51.21l128-128a30 30 0 0 1 42.42 42.42l-128 128A29.88 29.88 0 0 1 512 478z"
|
||||
p-id="2735"
|
||||
></path>
|
||||
<path
|
||||
d="M660 529H366a30 30 0 0 1 0-60h294a30 30 0 0 1 0 60z m0 95H366a30 30 0 0 1 0-60h294a30 30 0 0 1 0 60z"
|
||||
p-id="2736"
|
||||
></path>
|
||||
<path
|
||||
d="M512 776a30 30 0 0 1-30-30V448a30 30 0 0 1 60 0v298a30 30 0 0 1-30 30z"
|
||||
p-id="2737"
|
||||
></path>
|
||||
</svg>
|
||||
</el-icon>
|
||||
<div class="money">
|
||||
<span>USD</span>
|
||||
<span>{{ transferForm.MaxOutAmount }}</span>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<TransferForm
|
||||
:key="transferType"
|
||||
class="transfer-main-form"
|
||||
:form-data="transferForm"
|
||||
:form-rules="transferFormRules"
|
||||
:form-items="transferFormItemOptions"
|
||||
:options-map="transferFormOptionsMap"
|
||||
ref="mainTransferFormRef"
|
||||
>
|
||||
</TransferForm>
|
||||
<div class="transfer-type verify" v-if="transferType === 'external'">
|
||||
<div class="type-title">验证方式</div>
|
||||
<div class="tab">
|
||||
<el-button
|
||||
:type="verifyType === 'email' ? 'primary' : 'default'"
|
||||
@click="handleVerifyTabClick('email')"
|
||||
>邮箱验证</el-button
|
||||
>
|
||||
<el-button
|
||||
:type="verifyType === 'phone' ? 'primary' : 'default'"
|
||||
@click="handleVerifyTabClick('phone')"
|
||||
>手机号验证</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="username">{{ verifyType === 'email' ? userInfo.email : userInfo.phone }}</div>
|
||||
<el-form
|
||||
class="verify-form"
|
||||
:model="transferForm"
|
||||
:rules="transferFormRules"
|
||||
ref="verifyFormRef"
|
||||
>
|
||||
<el-form-item prop="code">
|
||||
<el-input
|
||||
v-model="transferForm.code"
|
||||
style="max-width: 300px"
|
||||
placeholder="请输入验证码"
|
||||
>
|
||||
</el-input>
|
||||
<el-button type="primary" @click="handleSendCode" :disabled="sendState.isCounting">{{
|
||||
sendState.isCounting ? `${sendState.countdown}s后重新获取` : '发送验证码'
|
||||
}}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-button type="primary" @click="handleSubmit" v-auth="'user_transfer'">提交转账</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
//组件
|
||||
|
|
@ -87,7 +135,6 @@ import { getTransferWalletOptionsApi, transferApi } from '@/api/modules/funding/
|
|||
//方法
|
||||
import { getStorage } from '@/utils/storage'
|
||||
|
||||
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
const userStore = useUserStore()
|
||||
import { sendCaptcha, initCaptchaState, clearCaptchaTimer } from '@/utils/sendCaptcha'
|
||||
|
|
@ -101,14 +148,14 @@ const transferType = ref('internal')
|
|||
* @description 创建默认转账表单数据
|
||||
*/
|
||||
const createDefaultTransferForm = () => ({
|
||||
transferOutAccount: -1,
|
||||
transferInAccount: '',
|
||||
transferAmount: '',
|
||||
remark: '',
|
||||
// 最大可转账金额
|
||||
MaxOutAmount: '',
|
||||
type: '',
|
||||
code: ''
|
||||
transferOutAccount: -1,
|
||||
transferInAccount: '',
|
||||
transferAmount: '',
|
||||
remark: '',
|
||||
// 最大可转账金额
|
||||
MaxOutAmount: '',
|
||||
type: '',
|
||||
code: '',
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
@ -120,11 +167,29 @@ const transferForm = ref(createDefaultTransferForm())
|
|||
*/
|
||||
const mainTransferFormRef = ref()
|
||||
const verifyFormRef = ref()
|
||||
const transferFormItemOptions = computed(() => transferType.value === 'internal' ? internalFormItem : externalFormItem)
|
||||
const transferFormItemOptions = computed(() =>
|
||||
transferType.value === 'internal' ? internalFormItem : externalFormItem,
|
||||
)
|
||||
|
||||
watch(
|
||||
() => transferForm.value.transferOutAccount,
|
||||
(val) => {
|
||||
console.log(
|
||||
'transferForm.value.transferOutAccount',
|
||||
val,
|
||||
transferFormOptionsMap.value.transferOutAccount,
|
||||
)
|
||||
transferForm.value.transferInAccount = null
|
||||
transferFormOptionsMap.value.transferInAccount =
|
||||
transferFormOptionsMap.value.transferOutAccount.filter((item: any) => item.value !== val)
|
||||
},
|
||||
{ inmediate: true, deep: true },
|
||||
)
|
||||
|
||||
const transferFormRules = ref(rules(transferForm.value))
|
||||
const transferFormOptionsMap = ref({
|
||||
transferOutAccount: [],
|
||||
transferInAccount: [],
|
||||
transferOutAccount: [],
|
||||
transferInAccount: [],
|
||||
}) as any
|
||||
|
||||
/**
|
||||
|
|
@ -136,13 +201,13 @@ const verifyType = ref('email')
|
|||
|
||||
// 发送验证码
|
||||
const sendState = ref<any>({
|
||||
isCounting: false,
|
||||
countdown: 0,
|
||||
isCounting: false,
|
||||
countdown: 0,
|
||||
})
|
||||
|
||||
//初始化验证码倒计时状态
|
||||
const emailCaptchaState = initCaptchaState('email'); // 邮箱专属
|
||||
const phoneCaptchaState = initCaptchaState('phone'); // 手机专属
|
||||
const emailCaptchaState = initCaptchaState('email') // 邮箱专属
|
||||
const phoneCaptchaState = initCaptchaState('phone') // 手机专属
|
||||
|
||||
// 邮箱验证码状态
|
||||
const { isCounting: emailIsCounting, countdown: emailCountdown } = emailCaptchaState
|
||||
|
|
@ -150,154 +215,145 @@ const { isCounting: emailIsCounting, countdown: emailCountdown } = emailCaptchaS
|
|||
// 手机验证码状态
|
||||
const { isCounting: phoneIsCounting, countdown: phoneCountdown } = phoneCaptchaState
|
||||
|
||||
|
||||
// 统一更新sendState的方法
|
||||
const updateSendState = (type: string) => {
|
||||
if (type === 'email') {
|
||||
sendState.value = {
|
||||
isCounting: emailIsCounting,
|
||||
countdown: emailCountdown
|
||||
}
|
||||
} else {
|
||||
sendState.value = {
|
||||
isCounting: phoneIsCounting,
|
||||
countdown: phoneCountdown
|
||||
}
|
||||
if (type === 'email') {
|
||||
sendState.value = {
|
||||
isCounting: emailIsCounting,
|
||||
countdown: emailCountdown,
|
||||
}
|
||||
} else {
|
||||
sendState.value = {
|
||||
isCounting: phoneIsCounting,
|
||||
countdown: phoneCountdown,
|
||||
}
|
||||
}
|
||||
}
|
||||
// 初始化时根据当前activeTab更新sendState(避免刷新后丢失)
|
||||
const initSendState = () => {
|
||||
const currentType = verifyType.value === 'email' ? 'email' : 'phone'
|
||||
updateSendState(currentType)
|
||||
const currentType = verifyType.value === 'email' ? 'email' : 'phone'
|
||||
updateSendState(currentType)
|
||||
}
|
||||
onMounted(() => {
|
||||
// 页面加载时立即执行,恢复倒计时
|
||||
initSendState()
|
||||
// 页面加载时立即执行,恢复倒计时
|
||||
initSendState()
|
||||
})
|
||||
// 监听verifyType变化,同步sendState
|
||||
watch(
|
||||
verifyType,
|
||||
(newTab, oldTab) => {
|
||||
verifyType.value = newTab;
|
||||
console.log('verifyType.value', verifyType.value);
|
||||
// 只有“主动切换tab”(oldTab有值)时才处理,初始化时(oldTab为undefined)不触发
|
||||
if (oldTab === undefined) return
|
||||
verifyType,
|
||||
(newTab, oldTab) => {
|
||||
verifyType.value = newTab
|
||||
console.log('verifyType.value', verifyType.value)
|
||||
// 只有“主动切换tab”(oldTab有值)时才处理,初始化时(oldTab为undefined)不触发
|
||||
if (oldTab === undefined) return
|
||||
|
||||
if (newTab === 'email' || newTab === 'phone') {
|
||||
// 主动切换到邮箱/手机页时,同步当前类型的倒计时状态(不再无脑重置)
|
||||
updateSendState(newTab)
|
||||
} else if (newTab === 'code') {
|
||||
// 切换到验证码页时,根据存储的类型更新状态
|
||||
const currentType: string = getStorage('forgotType', 'session') || 'email'
|
||||
updateSendState(currentType)
|
||||
}
|
||||
},
|
||||
{ immediate: false } // 关键:关闭立即执行,避免刷新时触发
|
||||
if (newTab === 'email' || newTab === 'phone') {
|
||||
// 主动切换到邮箱/手机页时,同步当前类型的倒计时状态(不再无脑重置)
|
||||
updateSendState(newTab)
|
||||
} else if (newTab === 'code') {
|
||||
// 切换到验证码页时,根据存储的类型更新状态
|
||||
const currentType: string = getStorage('forgotType', 'session') || 'email'
|
||||
updateSendState(currentType)
|
||||
}
|
||||
},
|
||||
{ immediate: false }, // 关键:关闭立即执行,避免刷新时触发
|
||||
)
|
||||
|
||||
// 定义发送验证码接口
|
||||
const sendCodeApi = async () => {
|
||||
// 发送验证码参数
|
||||
const sendParams = {
|
||||
email: userInfo.email,
|
||||
mobile: userInfo.mobile,
|
||||
reg_type: verifyType.value === 'email' ? 1 : 2,
|
||||
type: 'resetPass_code'
|
||||
}
|
||||
return userStore.sendCode(sendParams)
|
||||
// 发送验证码参数
|
||||
const sendParams = {
|
||||
email: userInfo.email,
|
||||
mobile: userInfo.mobile,
|
||||
reg_type: verifyType.value === 'email' ? 1 : 2,
|
||||
type: 'resetPass_code',
|
||||
}
|
||||
return userStore.sendCode(sendParams)
|
||||
}
|
||||
|
||||
//发送验证码
|
||||
const handleSendCode = async () => {
|
||||
const currentType = verifyType.value;
|
||||
// 确定类型:手机/邮箱
|
||||
const type: string = currentType || 'email';
|
||||
const currentType = verifyType.value
|
||||
// 确定类型:手机/邮箱
|
||||
const type: string = currentType || 'email'
|
||||
|
||||
if (type === 'phone') {
|
||||
// 场景1:发送手机验证码
|
||||
if (!userInfo.phone) {
|
||||
ElMessage.error('请先绑定手机号');
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行发送
|
||||
await sendCaptcha(
|
||||
type,
|
||||
userInfo.phone,
|
||||
phoneCaptchaState,
|
||||
() => sendCodeApi()
|
||||
);
|
||||
updateSendState(type);
|
||||
|
||||
} else {
|
||||
// 场景2:发送邮箱验证码
|
||||
if (!userInfo.email) {
|
||||
ElMessage.error('请先绑定邮箱');
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行发送
|
||||
await sendCaptcha(
|
||||
type,
|
||||
userInfo.email,
|
||||
emailCaptchaState,
|
||||
() => sendCodeApi()
|
||||
);
|
||||
updateSendState(type);
|
||||
if (type === 'phone') {
|
||||
// 场景1:发送手机验证码
|
||||
if (!userInfo.phone) {
|
||||
ElMessage.error('请先绑定手机号')
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
// 执行发送
|
||||
await sendCaptcha(type, userInfo.phone, phoneCaptchaState, () => sendCodeApi())
|
||||
updateSendState(type)
|
||||
} else {
|
||||
// 场景2:发送邮箱验证码
|
||||
if (!userInfo.email) {
|
||||
ElMessage.error('请先绑定邮箱')
|
||||
return
|
||||
}
|
||||
|
||||
// 执行发送
|
||||
await sendCaptcha(type, userInfo.email, emailCaptchaState, () => sendCodeApi())
|
||||
updateSendState(type)
|
||||
}
|
||||
}
|
||||
|
||||
// 组件卸载时清除定时器(关键:防止内存泄漏)
|
||||
onUnmounted(() => {
|
||||
clearCaptchaTimer(emailCaptchaState);
|
||||
clearCaptchaTimer(phoneCaptchaState);
|
||||
});
|
||||
clearCaptchaTimer(emailCaptchaState)
|
||||
clearCaptchaTimer(phoneCaptchaState)
|
||||
})
|
||||
/**
|
||||
* @description 监听transferOutAccount变化,获取对应的MaxAmount
|
||||
*/
|
||||
watch(
|
||||
[
|
||||
() => transferForm.value.transferOutAccount,
|
||||
() => transferFormOptionsMap.value.transferOutAccount
|
||||
],
|
||||
([newVal]) => {
|
||||
if (!newVal || !transferFormOptionsMap.value.transferOutAccount.length) return
|
||||
[
|
||||
() => transferForm.value.transferOutAccount,
|
||||
() => transferFormOptionsMap.value.transferOutAccount,
|
||||
],
|
||||
([newVal]) => {
|
||||
if (!newVal || !transferFormOptionsMap.value.transferOutAccount.length) return
|
||||
|
||||
const item = transferFormOptionsMap.value.transferOutAccount.find(
|
||||
(item: any) => item.value === newVal
|
||||
)
|
||||
transferForm.value.MaxOutAmount = item?.amount || 0
|
||||
},
|
||||
{ immediate: true }
|
||||
const item = transferFormOptionsMap.value.transferOutAccount.find(
|
||||
(item: any) => item.value === newVal,
|
||||
)
|
||||
transferForm.value.MaxOutAmount = item?.amount || 0
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
/**
|
||||
* @description 统一获取数据
|
||||
*/
|
||||
const getTransferWalletOptions = async () => {
|
||||
const data: any = await getTransferWalletOptionsApi()
|
||||
transferFormOptionsMap.value.transferOutAccount = data
|
||||
transferFormOptionsMap.value.transferInAccount = data
|
||||
const data: any = await getTransferWalletOptionsApi()
|
||||
transferFormOptionsMap.value.transferOutAccount = data
|
||||
transferFormOptionsMap.value.transferInAccount = data.filter((item: any) => item.value !== -1)
|
||||
}
|
||||
/**
|
||||
* @description 页面加载完成需要渲染的数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getTransferWalletOptions()
|
||||
getTransferWalletOptions()
|
||||
})
|
||||
|
||||
// 获取默认主钱包最大可转金额,切换标签或提交成功后用于恢复初始展示。
|
||||
const getDefaultMaxOutAmount = () => {
|
||||
return transferFormOptionsMap.value.transferOutAccount.find((item: any) => item.value === -1)?.amount || ''
|
||||
return (
|
||||
transferFormOptionsMap.value.transferOutAccount.find((item: any) => item.value === -1)
|
||||
?.amount || ''
|
||||
)
|
||||
}
|
||||
|
||||
// 重置转账表单:切换内部/第三方转账时清空所有输入框。
|
||||
const resetTransferForm = async () => {
|
||||
Object.assign(transferForm.value, createDefaultTransferForm(), {
|
||||
MaxOutAmount: getDefaultMaxOutAmount(),
|
||||
})
|
||||
Object.assign(transferForm.value, createDefaultTransferForm(), {
|
||||
MaxOutAmount: getDefaultMaxOutAmount(),
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
verifyFormRef.value?.clearValidate?.()
|
||||
await nextTick()
|
||||
verifyFormRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -305,153 +361,155 @@ const resetTransferForm = async () => {
|
|||
* @param type 转账类型
|
||||
*/
|
||||
const handleTransferTabClick = async (type: string) => {
|
||||
// 只有内部/第三方转账类型真的发生切换时,才清空当前表单内容。
|
||||
if (transferType.value === type) return
|
||||
// 只有内部/第三方转账类型真的发生切换时,才清空当前表单内容。
|
||||
if (transferType.value === type) return
|
||||
|
||||
transferType.value = type
|
||||
await resetTransferForm()
|
||||
transferType.value = type
|
||||
await resetTransferForm()
|
||||
}
|
||||
/**
|
||||
* @description 切换验证方式
|
||||
* @param type 验证方式
|
||||
*/
|
||||
const handleVerifyTabClick = (type: string) => {
|
||||
verifyType.value = type
|
||||
verifyType.value = type
|
||||
}
|
||||
|
||||
const handleVerifyParams = (type: string) => {
|
||||
if (type === 'external') {
|
||||
if (verifyType.value === 'email') {
|
||||
return userInfo.email
|
||||
} else {
|
||||
return userInfo.phone
|
||||
}
|
||||
if (type === 'external') {
|
||||
if (verifyType.value === 'email') {
|
||||
return userInfo.email
|
||||
} else {
|
||||
return '1'
|
||||
return userInfo.phone
|
||||
}
|
||||
} else {
|
||||
return transferForm.value.transferInAccount
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 提交转账表单
|
||||
*/
|
||||
const handleSubmit = async () => {
|
||||
await mainTransferFormRef.value?.validate?.()
|
||||
await mainTransferFormRef.value?.validate?.()
|
||||
|
||||
if (transferType.value === 'external') {
|
||||
await verifyFormRef.value?.validate?.()
|
||||
}
|
||||
if (transferType.value === 'external') {
|
||||
await verifyFormRef.value?.validate?.()
|
||||
}
|
||||
|
||||
const params = {
|
||||
type: transferType.value === 'internal' ? '1' : '2',
|
||||
from: String(transferForm.value.transferOutAccount),
|
||||
to: handleVerifyParams(transferType.value),
|
||||
amount: transferForm.value.transferAmount,
|
||||
verify_type: '',
|
||||
verify_code: '',
|
||||
description: transferForm.value.remark,
|
||||
}
|
||||
console.log(params)
|
||||
const params = {
|
||||
type: transferType.value === 'internal' ? '1' : '2',
|
||||
from: String(transferForm.value.transferOutAccount) + '',
|
||||
to: handleVerifyParams(transferType.value) + '',
|
||||
amount: transferForm.value.transferAmount,
|
||||
verify_type: '',
|
||||
verify_code: '',
|
||||
description: transferForm.value.remark,
|
||||
}
|
||||
console.log(params)
|
||||
|
||||
if (transferType.value === 'internal') {
|
||||
await transferApi(params)
|
||||
} else {
|
||||
await transferApi({ ...params, verify_type: verifyType.value === 'email' ? '1' : '2', verify_code: transferForm.value.code })
|
||||
}
|
||||
if (transferType.value === 'internal') {
|
||||
await transferApi(params)
|
||||
} else {
|
||||
await transferApi({
|
||||
...params,
|
||||
verify_type: verifyType.value === 'email' ? '1' : '2',
|
||||
verify_code: transferForm.value.code,
|
||||
})
|
||||
}
|
||||
|
||||
await resetTransferForm()
|
||||
await resetTransferForm()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.transfer {
|
||||
.title {
|
||||
margin-bottom: 10px;
|
||||
.title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.transfer-card {
|
||||
background: rgb(160, 207, 255, 0.5);
|
||||
margin-bottom: 10px;
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.transfer-card {
|
||||
background: rgb(160, 207, 255, 0.5);
|
||||
.transfer-item {
|
||||
line-height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-type {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.type-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-form) {
|
||||
.el-form-item {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-form {
|
||||
// 主转账表单的错误提示改为占位展示,避免长校验文案跑到“备注”下面。
|
||||
:deep(.transfer-main-form .el-form-item) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.transfer-main-form .el-form-item__error) {
|
||||
position: static;
|
||||
padding-top: 4px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.external-item {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.externa-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.external-card {
|
||||
width: fit-content;
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.transfer-item {
|
||||
line-height: 35px;
|
||||
.el-icon {
|
||||
color: #409eff;
|
||||
font-size: 34px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.money {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-type {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.type-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.verify {
|
||||
.tab,
|
||||
.username {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-form) {
|
||||
.el-form-item {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-form {
|
||||
// 主转账表单的错误提示改为占位展示,避免长校验文案跑到“备注”下面。
|
||||
:deep(.transfer-main-form .el-form-item) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.transfer-main-form .el-form-item__error) {
|
||||
position: static;
|
||||
padding-top: 4px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.external-item {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.externa-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.external-card {
|
||||
width: fit-content;
|
||||
|
||||
:deep(.el-card__body) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
color: #409eff;
|
||||
font-size: 34px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.money {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.verify {
|
||||
|
||||
.tab,
|
||||
.username {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.verify-form {
|
||||
.el-form-item {
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
.verify-form {
|
||||
.el-form-item {
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -97,7 +97,13 @@
|
|||
<el-card class="account">
|
||||
<h3 class="account-title">
|
||||
个人账户
|
||||
<el-button type="primary" size="small" @click="handleAddSubAccount">添加子账户</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleAddSubAccount"
|
||||
v-auth="'user_createAccount'"
|
||||
>添加子账户</el-button
|
||||
>
|
||||
</h3>
|
||||
<div class="account-list">
|
||||
<div class="list" v-for="item in accountList" :key="item.id">
|
||||
|
|
|
|||
|
|
@ -2,11 +2,21 @@
|
|||
<div class="mould-fee">
|
||||
<header>
|
||||
<div class="header-actions">
|
||||
<el-button type="primary" @click="addFee">添加模板</el-button>
|
||||
<el-button type="primary" @click="editFee">编辑模板</el-button>
|
||||
<el-button type="primary" @click="changeStatus(1)">启用模板</el-button>
|
||||
<el-button type="danger" @click="changeStatus(2)">禁用模板</el-button>
|
||||
<el-button type="primary" @click="editFeeDetail">编辑模板详情</el-button>
|
||||
<el-button type="primary" @click="addFee" v-auth="'feeHandl_createFeeSetting'"
|
||||
>添加模板</el-button
|
||||
>
|
||||
<el-button type="primary" @click="editFee" v-auth="'feeHandl_editFeeSetting'"
|
||||
>编辑模板</el-button
|
||||
>
|
||||
<el-button type="primary" @click="changeStatus(1)" v-auth="'feeHandl_editFeeSetting'"
|
||||
>启用模板</el-button
|
||||
>
|
||||
<el-button type="danger" @click="changeStatus(2)" v-auth="'feeHandl_editFeeSetting'"
|
||||
>禁用模板</el-button
|
||||
>
|
||||
<el-button type="primary" @click="editFeeDetail" v-auth="'feeHandl_setFeeSettingDetail'"
|
||||
>编辑模板详情</el-button
|
||||
>
|
||||
</div>
|
||||
</header>
|
||||
<div class="table-container">
|
||||
|
|
@ -90,7 +100,6 @@ import {
|
|||
import Form from '@/components/common/Form.vue'
|
||||
import { formDataList, formRulesList } from './option.ts'
|
||||
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitleType = ref(1)
|
||||
const formData = ref({
|
||||
|
|
|
|||
|
|
@ -2,9 +2,27 @@
|
|||
<div class="risk">
|
||||
<div class="bar">
|
||||
<span>风控管理</span>
|
||||
<el-button type="primary" @click="handleAddRisk">添加</el-button>
|
||||
<el-button type="primary" @click="handleModifyRisk">修改</el-button>
|
||||
<el-button type="danger" @click="handleRiskStatus">停用</el-button>
|
||||
<el-button type="primary" @click="handleAddRisk" v-auth="'riskControl_createRiskControl'"
|
||||
>添加</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleModifyRisk"
|
||||
v-auth="'riskControl_editRiskControlSetting'"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="handleChangeStatus(2)"
|
||||
v-auth="'riskControl_editRiskControlSetting'"
|
||||
>停用</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleChangeStatus(1)"
|
||||
v-auth="'riskControl_editRiskControlSetting'"
|
||||
>启用</el-button
|
||||
>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="risk-table-content">
|
||||
|
|
@ -243,10 +261,10 @@ const handleModifyRisk = () => {
|
|||
} as any
|
||||
}
|
||||
|
||||
const handleRiskStatus = async () => {
|
||||
const handleChangeStatus = async (status) => {
|
||||
dialogTitle.value = '停用'
|
||||
dialogType.value = 'status'
|
||||
await editRiskApi({ ...selectedRow.value, status: 2 })
|
||||
await editRiskApi({ ...selectedRow.value, status: status })
|
||||
getRiskList()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,18 @@ import { getTransferDetailListApi } from '@/api/modules/funding/transferDetail'
|
|||
|
||||
// 导出表格
|
||||
import { exportToExcel } from '@/utils/exportToExcel'
|
||||
|
||||
import { getRecentSevenDays } from '@/utils/handleTime.ts'
|
||||
|
||||
const initTime = getRecentSevenDays()
|
||||
|
||||
/**
|
||||
* @description: 定义搜索数据
|
||||
*/
|
||||
const searchForm = ref({
|
||||
transferAccount: '',
|
||||
type: '',
|
||||
transferTime: '',
|
||||
transferTime: [initTime.start, initTime.end],
|
||||
})
|
||||
const searchOptions = ref(search)
|
||||
/**
|
||||
|
|
@ -66,6 +71,7 @@ const total = ref(0)
|
|||
/**
|
||||
* @description: 定义公共请求数据方法
|
||||
*/
|
||||
|
||||
const getTransferDetailList = async () => {
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
v-if="row.role_id === 5"
|
||||
type="primary"
|
||||
size="small"
|
||||
v-auth="'agent_getSelfVarietyPointDiffConfig'"
|
||||
@click="handleMarginRatio(row)"
|
||||
>
|
||||
修改
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
type="primary"
|
||||
size="small"
|
||||
@click="handleCommissionRatio(row)"
|
||||
v-auth="'agent_editAgent'"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,15 @@
|
|||
@reset="handleReset"
|
||||
>
|
||||
<template #button="{ form }">
|
||||
<el-button type="primary" @click="handleAddMarket()"> 添加 </el-button>
|
||||
<el-button type="primary" :disabled="!selectedRow" @click="handleEditMarket()">
|
||||
<el-button type="primary" @click="handleAddMarket()" v-auth="'agent_createAgen'">
|
||||
添加
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!selectedRow"
|
||||
v-auth="'agent_editAgent'"
|
||||
@click="handleEditMarket()"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,68 +1,97 @@
|
|||
<template>
|
||||
<div class="client">
|
||||
<!-- 搜索组件 -->
|
||||
<ClientSearch :search-form="clientSearchForm" :search-options="clientSearchOptions" @search="handleSearch"
|
||||
@reset="handleReset">
|
||||
<template #button="{ form }">
|
||||
<el-button type="primary" @click="handleAdd()">
|
||||
添加客户
|
||||
</el-button>
|
||||
</template>
|
||||
</ClientSearch>
|
||||
<div class="client">
|
||||
<!-- 搜索组件 -->
|
||||
<ClientSearch
|
||||
:search-form="clientSearchForm"
|
||||
:search-options="clientSearchOptions"
|
||||
@search="handleSearch"
|
||||
@reset="handleReset"
|
||||
>
|
||||
<template #button="{ form }">
|
||||
<el-button type="primary" @click="handleAdd()" v-auth="'user_createUser'">
|
||||
添加客户
|
||||
</el-button>
|
||||
</template>
|
||||
</ClientSearch>
|
||||
|
||||
<!-- 表格组件 -->
|
||||
<ClientTable :table-data="clientTree" :columns="clientTableColumns">
|
||||
<template #status="{ row }">
|
||||
{{row.status === 1 ? '正常' : '禁用'}}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button type="primary" size="small" @click="handleChange(row)">
|
||||
修改
|
||||
</el-button>
|
||||
</template>
|
||||
</ClientTable>
|
||||
<!-- 分页组件 -->
|
||||
<ClientPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
|
||||
@pagination-change="handlePaginationChange" />
|
||||
</div>
|
||||
<!-- 客户弹窗 -->
|
||||
<ClientDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
|
||||
@cancel="handleCancel" @close="handleClose">
|
||||
<ClientForm :form-data="clientForm" :form-rules="clientFormRules" :form-items="clientFormOptions"
|
||||
:options-map="clientFormOptionsMap" ref="clientFormRef">
|
||||
<template #phoneOrEmail="{ formData }" style="margin-left: 0;">
|
||||
<div class="phone-email">
|
||||
<div class="tab-btn">
|
||||
<el-button :type="activeTab === 'email' ? 'primary' : 'default'" size="small"
|
||||
@click="activeTab = 'email'">
|
||||
邮箱
|
||||
</el-button>
|
||||
<el-button :type="activeTab === 'phone' ? 'primary' : 'default'" size="small"
|
||||
@click="activeTab = 'phone'">
|
||||
手机号
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="group">
|
||||
<el-form-item prop="email" v-if="activeTab === 'email'">
|
||||
<el-input v-model="clientForm.email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="phone" class="phone-item" v-if="activeTab === 'phone'">
|
||||
<el-select v-model="clientForm.countryCode" placeholder="请选择国家区号">
|
||||
<el-option v-for="item in countryOptions" :key="item.code" :label="item.code"
|
||||
:value="item.code">
|
||||
<div class="country-option">
|
||||
<span class="country-name">{{ item.name }}</span>
|
||||
<span class="country-code">{{ item.code }}</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input v-model="clientForm.phone" placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ClientForm>
|
||||
</ClientDialog>
|
||||
<!-- 表格组件 -->
|
||||
<ClientTable :table-data="clientTree" :columns="clientTableColumns">
|
||||
<template #status="{ row }">
|
||||
{{ row.status === 1 ? '正常' : '禁用' }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button type="primary" size="small" @click="handleChange(row)" v-anth="'user_editUser'">
|
||||
修改
|
||||
</el-button>
|
||||
</template>
|
||||
</ClientTable>
|
||||
<!-- 分页组件 -->
|
||||
<ClientPagination
|
||||
v-model="currentPage"
|
||||
v-model:pageSizeValue="pageSize"
|
||||
:total="total"
|
||||
@pagination-change="handlePaginationChange"
|
||||
/>
|
||||
</div>
|
||||
<!-- 客户弹窗 -->
|
||||
<ClientDialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
:type="dialogType"
|
||||
@confirm="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
@close="handleClose"
|
||||
>
|
||||
<ClientForm
|
||||
:form-data="clientForm"
|
||||
:form-rules="clientFormRules"
|
||||
:form-items="clientFormOptions"
|
||||
:options-map="clientFormOptionsMap"
|
||||
ref="clientFormRef"
|
||||
>
|
||||
<template #phoneOrEmail="{ formData }" style="margin-left: 0">
|
||||
<div class="phone-email">
|
||||
<div class="tab-btn">
|
||||
<el-button
|
||||
:type="activeTab === 'email' ? 'primary' : 'default'"
|
||||
size="small"
|
||||
@click="activeTab = 'email'"
|
||||
>
|
||||
邮箱
|
||||
</el-button>
|
||||
<el-button
|
||||
:type="activeTab === 'phone' ? 'primary' : 'default'"
|
||||
size="small"
|
||||
@click="activeTab = 'phone'"
|
||||
>
|
||||
手机号
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="group">
|
||||
<el-form-item prop="email" v-if="activeTab === 'email'">
|
||||
<el-input v-model="clientForm.email" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="phone" class="phone-item" v-if="activeTab === 'phone'">
|
||||
<el-select v-model="clientForm.countryCode" placeholder="请选择国家区号">
|
||||
<el-option
|
||||
v-for="item in countryOptions"
|
||||
:key="item.code"
|
||||
:label="item.code"
|
||||
:value="item.code"
|
||||
>
|
||||
<div class="country-option">
|
||||
<span class="country-name">{{ item.name }}</span>
|
||||
<span class="country-code">{{ item.code }}</span>
|
||||
</div>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input v-model="clientForm.phone" placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</ClientForm>
|
||||
</ClientDialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
@ -73,10 +102,23 @@ import ClientPagination from '@/components/common/Pagination.vue'
|
|||
import ClientDialog from '@/components/common/Dialog.vue'
|
||||
import ClientForm from '@/components/common/Form.vue'
|
||||
// 接口
|
||||
import { getClientListApi, getFeeTemplateOptionsApi, getRiskTemplateOptionsApi, getAgentOptionsApi, createClientApi, editClientApi } from '@/api/modules/account/client'
|
||||
import {
|
||||
getClientListApi,
|
||||
getFeeTemplateOptionsApi,
|
||||
getRiskTemplateOptionsApi,
|
||||
getAgentOptionsApi,
|
||||
createClientApi,
|
||||
editClientApi,
|
||||
} from '@/api/modules/account/client'
|
||||
|
||||
// 配置
|
||||
import { clientSearch, clientAddFormItem, clientChangeFormItem, countryOptions, clientTableColumns } from './options'
|
||||
import {
|
||||
clientSearch,
|
||||
clientAddFormItem,
|
||||
clientChangeFormItem,
|
||||
countryOptions,
|
||||
clientTableColumns,
|
||||
} from './options'
|
||||
import { rules } from './rules'
|
||||
|
||||
/**
|
||||
|
|
@ -84,10 +126,10 @@ import { rules } from './rules'
|
|||
*/
|
||||
const clientSearchOptions = ref(clientSearch)
|
||||
const clientSearchForm = ref({
|
||||
username: '',
|
||||
status: 1,
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
username: '',
|
||||
status: 1,
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
@ -112,6 +154,160 @@ const dialogType = ref('add')
|
|||
* @description 定义dialog中form的数据
|
||||
*/
|
||||
const clientForm = ref({
|
||||
//手续费模板
|
||||
feeTemplate: '',
|
||||
//风控模板
|
||||
riskTemplate: '',
|
||||
//所属上级名
|
||||
agentUsername: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
countryCode: '+86',
|
||||
//是否升级
|
||||
isUpgrade: 1,
|
||||
//是否变更客户名
|
||||
userName: '',
|
||||
status: 1,
|
||||
})
|
||||
|
||||
// 定义客户表单配置
|
||||
const clientFormRef = ref()
|
||||
const clientFormRules = ref(rules())
|
||||
// 定义客户表单选项是否已获取
|
||||
const optionsFetched = ref(false)
|
||||
const useId = ref('')
|
||||
const clientFormOptions = computed(() => {
|
||||
return dialogType.value === 'add' ? clientAddFormItem : clientChangeFormItem
|
||||
})
|
||||
const clientFormOptionsMap = ref<any>({
|
||||
feeTemplate: [],
|
||||
riskTemplate: [],
|
||||
agentUsername: [],
|
||||
isUpgrade: [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 2 },
|
||||
],
|
||||
status: [
|
||||
{ label: '正常', value: 1 },
|
||||
{ label: '禁用', value: 2 },
|
||||
],
|
||||
})
|
||||
// 定义客户表单选项切换
|
||||
const activeTab = ref('email')
|
||||
|
||||
/**
|
||||
* @description 统一数据处理方法
|
||||
*/
|
||||
// 映射对象为数组通用方法
|
||||
const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||
return Object.entries(obj).map(([label, value]) => ({
|
||||
label, // 模板/代理名称
|
||||
value, // 模板/代理ID
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 统一获取数据方法
|
||||
*/
|
||||
const getClientList = async () => {
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
page_size: pageSize.value,
|
||||
username: clientSearchForm.value.username,
|
||||
status: clientSearchForm.value.status || '',
|
||||
reg_start_time:
|
||||
clientSearchForm.value.startDateTime.length > 0
|
||||
? `${clientSearchForm.value.startDateTime} 0:00:00`
|
||||
: '',
|
||||
reg_end_time:
|
||||
clientSearchForm.value.endDateTime.length > 0
|
||||
? `${clientSearchForm.value.endDateTime} 23:59:59`
|
||||
: '',
|
||||
}
|
||||
const data = await getClientListApi(params)
|
||||
// 处理表格数据
|
||||
clientTree.value = data.data.map((item) => ({
|
||||
...item,
|
||||
//注册时间
|
||||
createdTime: item.created_at,
|
||||
// 映射所属代理用户名
|
||||
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
|
||||
}))
|
||||
//分页数据
|
||||
total.value = Number(data.total)
|
||||
currentPage.value = Number(data.current_page)
|
||||
pageSize.value = Number(data.per_page)
|
||||
}
|
||||
|
||||
// 获取客户表单选项
|
||||
const getOptions = async () => {
|
||||
// 已获取过选项则直接返回,避免重复请求
|
||||
if (optionsFetched.value) return
|
||||
|
||||
try {
|
||||
const [agentRes, feeTemplateRes, riskTemplateRes] = await Promise.all([
|
||||
getAgentOptionsApi(),
|
||||
getFeeTemplateOptionsApi(),
|
||||
getRiskTemplateOptionsApi(),
|
||||
])
|
||||
|
||||
// label=名称,value=ID
|
||||
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(
|
||||
agentRes as Record<string, string>,
|
||||
)
|
||||
clientFormOptionsMap.value.feeTemplate = mapObjectToOptions(
|
||||
feeTemplateRes as Record<string, string>,
|
||||
)
|
||||
clientFormOptionsMap.value.riskTemplate = mapObjectToOptions(
|
||||
riskTemplateRes as Record<string, string>,
|
||||
)
|
||||
|
||||
optionsFetched.value = true // 标记已获取
|
||||
} catch (error) {
|
||||
console.error('获取表单选项失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* @description 页面加载后获取数据
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await getClientList()
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 搜索方法
|
||||
*/
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
await getClientList()
|
||||
} catch (err) {
|
||||
console.error('获取客户列表失败', err)
|
||||
}
|
||||
}
|
||||
const handleReset = async () => {
|
||||
// 重置搜索表单
|
||||
clientSearchForm.value = {
|
||||
username: '',
|
||||
status: '正常',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
}
|
||||
try {
|
||||
await getClientList()
|
||||
} catch (err) {
|
||||
console.error('获取客户列表失败', err)
|
||||
}
|
||||
}
|
||||
// 添加客户
|
||||
const handleAdd = () => {
|
||||
// 打开添加客户弹窗
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '添加客户'
|
||||
dialogType.value = 'add'
|
||||
clientForm.value = {
|
||||
//手续费模板
|
||||
feeTemplate: '',
|
||||
//风控模板
|
||||
|
|
@ -126,263 +322,121 @@ const clientForm = ref({
|
|||
//是否变更客户名
|
||||
userName: '',
|
||||
status: 1,
|
||||
})
|
||||
|
||||
// 定义客户表单配置
|
||||
const clientFormRef = ref()
|
||||
const clientFormRules = ref(rules())
|
||||
// 定义客户表单选项是否已获取
|
||||
const optionsFetched = ref(false)
|
||||
const useId = ref('')
|
||||
const clientFormOptions = computed(() => {
|
||||
return dialogType.value === 'add' ? clientAddFormItem : clientChangeFormItem;
|
||||
})
|
||||
const clientFormOptionsMap = ref<any>({
|
||||
feeTemplate: [],
|
||||
riskTemplate: [],
|
||||
agentUsername: [],
|
||||
isUpgrade: [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 2 }
|
||||
],
|
||||
status: [
|
||||
{ label: '正常', value: 1 },
|
||||
{ label: '禁用', value: 2 }
|
||||
],
|
||||
})
|
||||
// 定义客户表单选项切换
|
||||
const activeTab = ref('email')
|
||||
|
||||
/**
|
||||
* @description 统一数据处理方法
|
||||
*/
|
||||
// 映射对象为数组通用方法
|
||||
const mapObjectToOptions = (obj: Record<string, string>) => {
|
||||
return Object.entries(obj).map(([label, value]) => ({
|
||||
label, // 模板/代理名称
|
||||
value // 模板/代理ID
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 统一获取数据方法
|
||||
*/
|
||||
const getClientList = async () => {
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
page_size: pageSize.value,
|
||||
username: clientSearchForm.value.username,
|
||||
status: clientSearchForm.value.status || '',
|
||||
reg_start_time: clientSearchForm.value.startDateTime.length > 0 ? `${clientSearchForm.value.startDateTime} 0:00:00` : '',
|
||||
reg_end_time: clientSearchForm.value.endDateTime.length > 0 ? `${clientSearchForm.value.endDateTime} 23:59:59` : '',
|
||||
}
|
||||
const data = await getClientListApi(params)
|
||||
// 处理表格数据
|
||||
clientTree.value = data.data.map(item => ({
|
||||
...item,
|
||||
//注册时间
|
||||
createdTime: item.created_at,
|
||||
// 映射所属代理用户名
|
||||
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
|
||||
}));
|
||||
//分页数据
|
||||
total.value = Number(data.total)
|
||||
currentPage.value = Number(data.current_page)
|
||||
pageSize.value = Number(data.per_page)
|
||||
}
|
||||
|
||||
// 获取客户表单选项
|
||||
const getOptions = async () => {
|
||||
// 已获取过选项则直接返回,避免重复请求
|
||||
if (optionsFetched.value) return
|
||||
|
||||
try {
|
||||
const [agentRes, feeTemplateRes, riskTemplateRes] = await Promise.all([
|
||||
getAgentOptionsApi(),
|
||||
getFeeTemplateOptionsApi(),
|
||||
getRiskTemplateOptionsApi()
|
||||
])
|
||||
|
||||
// label=名称,value=ID
|
||||
clientFormOptionsMap.value.agentUsername = mapObjectToOptions(agentRes as Record<string, string>)
|
||||
clientFormOptionsMap.value.feeTemplate = mapObjectToOptions(feeTemplateRes as Record<string, string>)
|
||||
clientFormOptionsMap.value.riskTemplate = mapObjectToOptions(riskTemplateRes as Record<string, string>)
|
||||
|
||||
optionsFetched.value = true // 标记已获取
|
||||
} catch (error) {
|
||||
console.error('获取表单选项失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* @description 页面加载后获取数据
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await getClientList()
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 搜索方法
|
||||
*/
|
||||
const handleSearch = async () => {
|
||||
try {
|
||||
await getClientList()
|
||||
} catch (err) {
|
||||
console.error('获取客户列表失败', err)
|
||||
}
|
||||
}
|
||||
const handleReset = async () => {
|
||||
// 重置搜索表单
|
||||
clientSearchForm.value = {
|
||||
username: '',
|
||||
status: '正常',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
}
|
||||
try {
|
||||
await getClientList()
|
||||
} catch (err) {
|
||||
console.error('获取客户列表失败', err)
|
||||
}
|
||||
}
|
||||
// 添加客户
|
||||
const handleAdd = () => {
|
||||
// 打开添加客户弹窗
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '添加客户'
|
||||
dialogType.value = 'add'
|
||||
clientForm.value = {
|
||||
//手续费模板
|
||||
feeTemplate: '',
|
||||
//风控模板
|
||||
riskTemplate: '',
|
||||
//所属上级名
|
||||
agentUsername: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
countryCode: '+86',
|
||||
//是否升级
|
||||
isUpgrade: 1,
|
||||
//是否变更客户名
|
||||
userName: '',
|
||||
status: 1,
|
||||
}
|
||||
getOptions()
|
||||
}
|
||||
getOptions()
|
||||
}
|
||||
/**
|
||||
* @description 表格方法
|
||||
*/
|
||||
const handleChange = (row: any) => {
|
||||
// 打开修改客户弹窗
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '修改客户'
|
||||
dialogType.value = 'change'
|
||||
useId.value = row.id
|
||||
clientForm.value = {
|
||||
//手续费模板
|
||||
feeTemplate: row.wallet_capital.fee_setting_id,
|
||||
//风控模板
|
||||
riskTemplate: row.wallet_capital.risk_control_id,
|
||||
userName: row.username,
|
||||
status: row.status,
|
||||
isUpgrade: 2,
|
||||
} as any
|
||||
console.log('rowrowrowrowrowrowrowrowrow', clientForm.value)
|
||||
getOptions()
|
||||
// 打开修改客户弹窗
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '修改客户'
|
||||
dialogType.value = 'change'
|
||||
useId.value = row.id
|
||||
clientForm.value = {
|
||||
//手续费模板
|
||||
feeTemplate: row.wallet_capital.fee_setting_id,
|
||||
//风控模板
|
||||
riskTemplate: row.wallet_capital.risk_control_id,
|
||||
userName: row.username,
|
||||
status: row.status,
|
||||
isUpgrade: 2,
|
||||
} as any
|
||||
console.log('rowrowrowrowrowrowrowrowrow', clientForm.value)
|
||||
getOptions()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 分页方法
|
||||
*/
|
||||
const handlePaginationChange = (page: { currentPage: number, pageSize: number }) => {
|
||||
currentPage.value = page.currentPage
|
||||
pageSize.value = page.pageSize
|
||||
handleSearch()
|
||||
const handlePaginationChange = (page: { currentPage: number; pageSize: number }) => {
|
||||
currentPage.value = page.currentPage
|
||||
pageSize.value = page.pageSize
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 客户弹窗方法
|
||||
*/
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
await clientFormRef.value?.validate()
|
||||
if (dialogType.value === 'add') {
|
||||
const params = {
|
||||
reg_type: activeTab.value === 'email' ? 1 : 2,
|
||||
email: clientForm.value.email,
|
||||
mobile: clientForm.value.phone,
|
||||
parent_id: clientForm.value.agentUsername,
|
||||
risk_control_id: clientForm.value.riskTemplate,
|
||||
fee_setting_id: clientForm.value.feeTemplate,
|
||||
}
|
||||
await createClientApi(params)
|
||||
await getClientList()
|
||||
dialogVisible.value = false
|
||||
} else {
|
||||
const params = {
|
||||
user_id: useId.value,
|
||||
risk_control_id: clientForm.value.riskTemplate,
|
||||
fee_setting_id: clientForm.value.feeTemplate,
|
||||
username: clientForm.value.userName,
|
||||
is_levelup: clientForm.value.isUpgrade,
|
||||
status: clientForm.value.status,
|
||||
}
|
||||
await editClientApi(params)
|
||||
await getClientList()
|
||||
dialogVisible.value = false
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('客户表单验证失败', err)
|
||||
try {
|
||||
await clientFormRef.value?.validate()
|
||||
if (dialogType.value === 'add') {
|
||||
const params = {
|
||||
reg_type: activeTab.value === 'email' ? 1 : 2,
|
||||
email: clientForm.value.email,
|
||||
mobile: clientForm.value.phone,
|
||||
parent_id: clientForm.value.agentUsername,
|
||||
risk_control_id: clientForm.value.riskTemplate,
|
||||
fee_setting_id: clientForm.value.feeTemplate,
|
||||
}
|
||||
await createClientApi(params)
|
||||
await getClientList()
|
||||
dialogVisible.value = false
|
||||
} else {
|
||||
const params = {
|
||||
user_id: useId.value,
|
||||
risk_control_id: clientForm.value.riskTemplate,
|
||||
fee_setting_id: clientForm.value.feeTemplate,
|
||||
username: clientForm.value.userName,
|
||||
is_levelup: clientForm.value.isUpgrade,
|
||||
status: clientForm.value.status,
|
||||
}
|
||||
await editClientApi(params)
|
||||
await getClientList()
|
||||
dialogVisible.value = false
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('客户表单验证失败', err)
|
||||
}
|
||||
}
|
||||
const handleCancel = () => {
|
||||
// 关闭弹窗
|
||||
dialogVisible.value = false
|
||||
// 关闭弹窗
|
||||
dialogVisible.value = false
|
||||
}
|
||||
const handleClose = () => {
|
||||
// 关闭弹窗
|
||||
dialogVisible.value = false
|
||||
// 关闭弹窗
|
||||
dialogVisible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-form-item__content) {
|
||||
margin-left: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.phone-email {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.tab-btn {
|
||||
display: flex;
|
||||
margin-right: 10px;
|
||||
|
||||
.el-button {
|
||||
height: 32px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.group {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.tab-btn {
|
||||
display: flex;
|
||||
margin-right: 10px;
|
||||
|
||||
.el-button {
|
||||
height: 32px;
|
||||
margin-left: 0;
|
||||
}
|
||||
.el-form-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.group {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
.phone-item {
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.phone-item {
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
.el-select {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,41 +1,68 @@
|
|||
<template>
|
||||
<div class="system">
|
||||
<!-- 菜单列表头 -->
|
||||
<div class="header">
|
||||
<h4>菜单列表</h4>
|
||||
<el-button type="primary" @click="handleAddMenu">新增菜单</el-button>
|
||||
</div>
|
||||
<!-- 菜单列表表格 -->
|
||||
<MenuTable :table-data="menuTree" :columns="menuTableColumns" row-key="id" :tree-props="treeProps">
|
||||
<template #icon="{ row }">
|
||||
<el-icon v-if="row.icon && menuiconMap[row.icon]">
|
||||
<component :is="menuiconMap[row.icon]" />
|
||||
</el-icon>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #type="{ row }">
|
||||
{{ row.type === 1 ? '目录' : '按钮' }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
|
||||
inactive-text="禁用"/>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEditMenu(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDeleteMenu(row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</MenuTable>
|
||||
<div class="system">
|
||||
<!-- 菜单列表头 -->
|
||||
<div class="header">
|
||||
<h4>菜单列表</h4>
|
||||
<el-button type="primary" @click="handleAddMenu" v-auth="'menus_create'">新增菜单</el-button>
|
||||
</div>
|
||||
<!-- 菜单新增/编辑弹窗 -->
|
||||
<MenuDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
|
||||
@cancel="handleCancel" @close="handleClose">
|
||||
<MenuForm :form-data="menuForm" :form-rules="menuFormRules" :form-items="menuFormItemOptions"
|
||||
:options-map="menuFormOptionsMap" ref="menuFormRef" />
|
||||
</MenuDialog>
|
||||
<!-- 菜单列表表格 -->
|
||||
<MenuTable
|
||||
:table-data="menuTree"
|
||||
:columns="menuTableColumns"
|
||||
row-key="id"
|
||||
:tree-props="treeProps"
|
||||
>
|
||||
<template #icon="{ row }">
|
||||
<el-icon v-if="row.icon && menuiconMap[row.icon]">
|
||||
<component :is="menuiconMap[row.icon]" />
|
||||
</el-icon>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
<template #type="{ row }">
|
||||
{{ row.type === 1 ? '目录' : '按钮' }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
{{ row.status === 1 ? '启用' : '禁用' }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleEditMenu(row)"
|
||||
v-auth="'menus_edit'"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDeleteMenu(row)"
|
||||
v-auth="'menus_del'"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</MenuTable>
|
||||
</div>
|
||||
<!-- 菜单新增/编辑弹窗 -->
|
||||
<MenuDialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
:type="dialogType"
|
||||
@confirm="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
@close="handleClose"
|
||||
>
|
||||
<MenuForm
|
||||
:form-data="menuForm"
|
||||
:form-rules="menuFormRules"
|
||||
:form-items="menuFormItemOptions"
|
||||
:options-map="menuFormOptionsMap"
|
||||
ref="menuFormRef"
|
||||
/>
|
||||
</MenuDialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { FormInstance } from 'element-plus'
|
||||
|
|
@ -52,7 +79,7 @@ import { getMenuApi, createMenuApi, editMenuApi, deleteMenuApi } from '@/api/mod
|
|||
// 定义header配置
|
||||
const menuTitle = ref('菜单管理')
|
||||
const menuHeaderButtons = [
|
||||
{ label: '新增菜单', type: 'primary' as const, icon: Plus, key: 'addMenu' },
|
||||
{ label: '新增菜单', type: 'primary' as const, icon: Plus, key: 'addMenu' },
|
||||
]
|
||||
|
||||
// 定义表格配置
|
||||
|
|
@ -66,39 +93,39 @@ const dialogType = ref('add')
|
|||
|
||||
// 定义菜单表单数据
|
||||
const menuForm = ref({
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
})
|
||||
const menuFormRef = ref<FormInstance>()
|
||||
// 表单验证规则
|
||||
const menuFormRules = rules(menuForm.value, menuiconOptions)
|
||||
// icon和菜单表单选项映射
|
||||
const menuFormOptionsMap = ref({
|
||||
'parentName': [] as any[],
|
||||
'icon': menuiconOptions,
|
||||
'type': [
|
||||
{ label: '菜单', value: 1 },
|
||||
{ label: '按钮', value: 2 }
|
||||
],
|
||||
'status': [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 2 }
|
||||
]
|
||||
parentName: [] as any[],
|
||||
icon: menuiconOptions,
|
||||
type: [
|
||||
{ label: '菜单', value: 1 },
|
||||
{ label: '按钮', value: 2 },
|
||||
],
|
||||
status: [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 2 },
|
||||
],
|
||||
})
|
||||
|
||||
/**
|
||||
@description: 新增菜单
|
||||
**/
|
||||
const handleAddMenu = () => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '新增菜单'
|
||||
menuForm.value.status = 1 as any // 默认是启用状态
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '新增菜单'
|
||||
menuForm.value.status = 1 as any // 默认是启用状态
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,108 +134,105 @@ const handleAddMenu = () => {
|
|||
|
||||
// 获取菜单列表
|
||||
const fetchMenuList = async () => {
|
||||
try {
|
||||
const data = await getMenuApi()
|
||||
menuTree.value = data
|
||||
// 处理parentName选项,添加一级菜单选项
|
||||
const parentNameOptions = data.map(item => ({
|
||||
label: item.name,
|
||||
value: item.id ?? ''
|
||||
}))
|
||||
menuFormOptionsMap.value.parentName = [
|
||||
{ label: '一级菜单', value: "0" },
|
||||
...parentNameOptions
|
||||
]
|
||||
} catch (err) {
|
||||
console.error('获取菜单列表失败', err)
|
||||
}
|
||||
try {
|
||||
const data = await getMenuApi()
|
||||
menuTree.value = data
|
||||
// 处理parentName选项,添加一级菜单选项
|
||||
const parentNameOptions = data.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id ?? '',
|
||||
}))
|
||||
menuFormOptionsMap.value.parentName = [{ label: '一级菜单', value: '0' }, ...parentNameOptions]
|
||||
} catch (err) {
|
||||
console.error('获取菜单列表失败', err)
|
||||
}
|
||||
}
|
||||
// 页面加载时获取菜单列表
|
||||
onMounted(async () => {
|
||||
await fetchMenuList()
|
||||
await fetchMenuList()
|
||||
})
|
||||
|
||||
/**
|
||||
@description: 处理菜单编辑/删除/状态切换
|
||||
**/
|
||||
const handleEditMenu = (row: any) => {
|
||||
console.log('编辑菜单', row)
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '编辑菜单'
|
||||
dialogType.value = 'edit'
|
||||
menuForm.value = {
|
||||
...row,
|
||||
id: row.id, // 菜单id
|
||||
parentName: row.name,
|
||||
status: row.status ?? 1, // 默认是启用状态
|
||||
api: row.api, // 后端路由
|
||||
}
|
||||
console.log('编辑菜单', row)
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '编辑菜单'
|
||||
dialogType.value = 'edit'
|
||||
menuForm.value = {
|
||||
...row,
|
||||
id: row.id, // 菜单id
|
||||
parentName: row.name,
|
||||
status: row.status ?? 1, // 默认是启用状态
|
||||
api: row.api, // 后端路由
|
||||
}
|
||||
}
|
||||
const handleDeleteMenu = async (row: any) => {
|
||||
try {
|
||||
await deleteMenuApi({ id: row.id })
|
||||
await fetchMenuList()
|
||||
} catch (err) {
|
||||
console.error('删除菜单失败')
|
||||
}
|
||||
try {
|
||||
await deleteMenuApi({ id: row.id })
|
||||
await fetchMenuList()
|
||||
} catch (err) {
|
||||
console.error('删除菜单失败')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@description: 处理弹窗提交/取消/关闭事件
|
||||
**/
|
||||
const handleSubmit = async () => {
|
||||
console.log('提交菜单表单')
|
||||
try {
|
||||
await menuFormRef.value?.validate()
|
||||
if (dialogType.value === 'add') {
|
||||
const params = {
|
||||
name: menuForm.value.name, // 菜单名称
|
||||
parent_id: menuForm.value.parentName, // 上级菜单id
|
||||
path: menuForm.value.path, // 路由路径
|
||||
api: menuForm.value.api , // 后端路由
|
||||
icon: menuForm.value.icon, // 图标名称
|
||||
sort: menuForm.value.sort ?? 1, // 排序(默认1)
|
||||
type: menuForm.value.type ?? 1, // 默认是菜单类型
|
||||
}
|
||||
await createMenuApi(params)
|
||||
await fetchMenuList()
|
||||
} else {
|
||||
await editMenuApi(menuForm.value)
|
||||
console.log('编辑菜单成功', menuForm.value)
|
||||
await fetchMenuList()
|
||||
}
|
||||
dialogVisible.value = false
|
||||
} catch (err) {
|
||||
console.log('表单验证失败')
|
||||
return
|
||||
console.log('提交菜单表单')
|
||||
try {
|
||||
await menuFormRef.value?.validate()
|
||||
if (dialogType.value === 'add') {
|
||||
const params = {
|
||||
name: menuForm.value.name, // 菜单名称
|
||||
parent_id: menuForm.value.parentName, // 上级菜单id
|
||||
path: menuForm.value.path, // 路由路径
|
||||
api: menuForm.value.api, // 后端路由
|
||||
icon: menuForm.value.icon, // 图标名称
|
||||
sort: menuForm.value.sort ?? 1, // 排序(默认1)
|
||||
type: menuForm.value.type ?? 1, // 默认是菜单类型
|
||||
}
|
||||
await createMenuApi(params)
|
||||
await fetchMenuList()
|
||||
} else {
|
||||
await editMenuApi(menuForm.value)
|
||||
console.log('编辑菜单成功', menuForm.value)
|
||||
await fetchMenuList()
|
||||
}
|
||||
dialogVisible.value = false
|
||||
} catch (err) {
|
||||
console.log('表单验证失败')
|
||||
return
|
||||
}
|
||||
}
|
||||
const handleCancel = () => {
|
||||
dialogVisible.value = false
|
||||
dialogType.value = 'add'
|
||||
menuForm.value = {
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
}
|
||||
dialogVisible.value = false
|
||||
dialogType.value = 'add'
|
||||
menuForm.value = {
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
}
|
||||
}
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
dialogType.value = 'add'
|
||||
menuForm.value = {
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
}
|
||||
dialogVisible.value = false
|
||||
dialogType.value = 'add'
|
||||
menuForm.value = {
|
||||
name: '', // 菜单名称
|
||||
parentName: '', // 上级菜单名称
|
||||
path: '', // 路由路径
|
||||
api: '', // 后端路由
|
||||
icon: '', // 图标名称
|
||||
sort: null, // 排序(默认1)
|
||||
type: null, // 默认是菜单类型
|
||||
status: null, // 默认是启用状态
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,55 +1,97 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- 搜索 -->
|
||||
<NoticeSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
|
||||
@reset="handleReset">
|
||||
<template #button>
|
||||
<el-button type="primary" @click="handleCreate">新建</el-button>
|
||||
</template>
|
||||
</NoticeSearch>
|
||||
<div class="tab">
|
||||
<el-button :type="activeTab === 2 ? 'primary' : 'default'" @click="handleTabChange(2)">已发布</el-button>
|
||||
<el-button :type="activeTab === 1 ? 'primary' : 'default'" @click="handleTabChange(1)">草稿</el-button>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<NoticeTable :table-data="noticeTree" :columns="noticeTableColumnsOptions" row-key="id">
|
||||
<template #status="{ row }">
|
||||
<!-- 修正状态显示:1=草稿,2=已发布 -->
|
||||
{{ row.status === 1 ? '草稿' : '已发布' }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button type="primary" size="small" v-if="row.status === 2" @click="handleView(row)">查看</el-button>
|
||||
<!-- 草稿才显示编辑/删除,已发布仅查看 -->
|
||||
<template v-if="row.status === 1">
|
||||
<el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</NoticeTable>
|
||||
<!-- 分页 -->
|
||||
<NoticePagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
|
||||
@pagination-change="handlePaginationChange" />
|
||||
<!-- dialog -->
|
||||
<NoticeDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType"
|
||||
:show-footer="dialogType !== 'view'" @confirm="handleSubmit" @cancel="handleCancel" @close="handleClose">
|
||||
<NoticeForm :form-data="noticeForm" :form-rules="noticeRules" :form-items="noticeFormItem"
|
||||
:options-map="noticeFormOptionsMap" ref="noticeFormRef" v-if="dialogType !== 'view'">
|
||||
<template #noticeContent="{ formData }">
|
||||
<div style="border: 1px solid #e6e6e6; margin: 10px 0;">
|
||||
<Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" mode="default"
|
||||
style="border-bottom: 1px solid #ccc;" />
|
||||
<Editor v-model="valueHtml" :defaultConfig="editorConfig" mode="default"
|
||||
@onCreated="handleCreated" style="height: 300px; overflow-y: auto;" />
|
||||
</div>
|
||||
</template>
|
||||
</NoticeForm>
|
||||
<div v-else class="view-content">
|
||||
<h2>公告名称:{{ noticeForm.noticeName }}</h2>
|
||||
<div v-html="noticeForm.noticeContent"></div>
|
||||
</div>
|
||||
</NoticeDialog>
|
||||
<!-- dialog表格 -->
|
||||
</div>
|
||||
<div>
|
||||
<!-- 搜索 -->
|
||||
<NoticeSearch
|
||||
:search-form="searchForm"
|
||||
:search-options="searchOptions"
|
||||
@search="handleSearch"
|
||||
@reset="handleReset"
|
||||
>
|
||||
<template #button>
|
||||
<el-button type="primary" @click="handleCreate" v-auth="'notice_createNotice'"
|
||||
>新建</el-button
|
||||
>
|
||||
</template>
|
||||
</NoticeSearch>
|
||||
<!-- 表格 -->
|
||||
<NoticeTable :table-data="noticeTree" :columns="noticeTableColumnsOptions" row-key="id">
|
||||
<template #status="{ row }">
|
||||
<!-- 修正状态显示:1=草稿,2=已发布 -->
|
||||
{{ row.status === 1 ? '草稿' : '已发布' }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button type="primary" size="small" v-if="row.status === 2" @click="handleView(row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<!-- 草稿才显示编辑/删除,已发布仅查看 -->
|
||||
<template v-if="row.status === 1">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleEdit(row)"
|
||||
v-auth="'notice_editNotice'"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
v-auth="'notice_delNotice'"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</template>
|
||||
</NoticeTable>
|
||||
<!-- 分页 -->
|
||||
<NoticePagination
|
||||
v-model="currentPage"
|
||||
v-model:pageSizeValue="pageSize"
|
||||
:total="total"
|
||||
@pagination-change="handlePaginationChange"
|
||||
/>
|
||||
<!-- dialog -->
|
||||
<NoticeDialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
:type="dialogType"
|
||||
:show-footer="dialogType !== 'view'"
|
||||
@confirm="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
@close="handleClose"
|
||||
>
|
||||
<NoticeForm
|
||||
:form-data="noticeForm"
|
||||
:form-rules="noticeRules"
|
||||
:form-items="noticeFormItem"
|
||||
:options-map="noticeFormOptionsMap"
|
||||
ref="noticeFormRef"
|
||||
v-if="dialogType !== 'view'"
|
||||
>
|
||||
<template #noticeContent="{ formData }">
|
||||
<div style="border: 1px solid #e6e6e6; margin: 10px 0">
|
||||
<Toolbar
|
||||
:editor="editorRef"
|
||||
:defaultConfig="toolbarConfig"
|
||||
mode="default"
|
||||
style="border-bottom: 1px solid #ccc"
|
||||
/>
|
||||
<Editor
|
||||
v-model="valueHtml"
|
||||
:defaultConfig="editorConfig"
|
||||
mode="default"
|
||||
@onCreated="handleCreated"
|
||||
style="height: 300px; overflow-y: auto"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</NoticeForm>
|
||||
<div v-else class="view-content">
|
||||
<h2>公告名称:{{ noticeForm.noticeName }}</h2>
|
||||
<div v-html="noticeForm.noticeContent"></div>
|
||||
</div>
|
||||
</NoticeDialog>
|
||||
<!-- dialog表格 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
@ -64,11 +106,14 @@ import { search, tableColumns, formItem } from './options'
|
|||
import { rules } from './rules'
|
||||
|
||||
// 接口
|
||||
import { getNoticeListApi, createNoticeApi, editNoticeApi, deleteNoticeApi } from '@/api/modules/notice'
|
||||
import {
|
||||
getNoticeListApi,
|
||||
createNoticeApi,
|
||||
editNoticeApi,
|
||||
deleteNoticeApi,
|
||||
} from '@/api/modules/notice'
|
||||
import { uploadImageApi } from '@/api/modules/upload'
|
||||
|
||||
|
||||
|
||||
import { DomEditor } from '@wangeditor/editor'
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
|
|
@ -81,48 +126,48 @@ const toolbarRef = shallowRef()
|
|||
const valueHtml = ref('')
|
||||
// 工具栏配置
|
||||
const toolbarConfig = {
|
||||
excludeKeys: ["group-video", "fullScreen"]
|
||||
excludeKeys: ['group-video', 'fullScreen'],
|
||||
}
|
||||
// 富文本编辑器配置
|
||||
const editorConfig = {
|
||||
placeholder: '请输入内容...',
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
customUpload: async (file: any, insertFn: any) => {
|
||||
try {
|
||||
// 调用封装后的上传API
|
||||
const res = await uploadImageApi(file);
|
||||
// 插入图片到富文本
|
||||
insertFn(res.url);
|
||||
} catch (error: any) {
|
||||
// 复用你已有的错误提示逻辑(ElNotification)
|
||||
const errMsg = error?.message || error?.data?.msg || '图片上传失败';
|
||||
alert(`图片${file.name}上传失败:${errMsg}`);
|
||||
ElNotification({
|
||||
message: errMsg || '未知的错误!',
|
||||
type: 'error',
|
||||
duration: 2000,
|
||||
customClass: 'global-notification'
|
||||
})
|
||||
}
|
||||
},
|
||||
// 保留基础配置
|
||||
fieldName: 'image',
|
||||
timeout: 30 * 1000,
|
||||
maxFileSize: 5 * 1024 * 1024,
|
||||
allowedFileTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
|
||||
placeholder: '请输入内容...',
|
||||
MENU_CONF: {
|
||||
uploadImage: {
|
||||
customUpload: async (file: any, insertFn: any) => {
|
||||
try {
|
||||
// 调用封装后的上传API
|
||||
const res = await uploadImageApi(file)
|
||||
// 插入图片到富文本
|
||||
insertFn(res.url)
|
||||
} catch (error: any) {
|
||||
// 复用你已有的错误提示逻辑(ElNotification)
|
||||
const errMsg = error?.message || error?.data?.msg || '图片上传失败'
|
||||
alert(`图片${file.name}上传失败:${errMsg}`)
|
||||
ElNotification({
|
||||
message: errMsg || '未知的错误!',
|
||||
type: 'error',
|
||||
duration: 2000,
|
||||
customClass: 'global-notification',
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
// 保留基础配置
|
||||
fieldName: 'image',
|
||||
timeout: 30 * 1000,
|
||||
maxFileSize: 5 * 1024 * 1024,
|
||||
allowedFileTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 定义搜索数据
|
||||
*/
|
||||
const searchForm = ref({
|
||||
noticeName: '',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
status: 2,
|
||||
noticeName: '',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
status: 2,
|
||||
})
|
||||
const searchOptions = ref(search)
|
||||
|
||||
|
|
@ -154,19 +199,19 @@ const dialogType = ref('')
|
|||
* @description: 定义弹窗表格数据
|
||||
*/
|
||||
const noticeForm = ref({
|
||||
noticeName: '',
|
||||
noticeContent: '',
|
||||
status: 1,
|
||||
id: 0,
|
||||
noticeName: '',
|
||||
noticeContent: '',
|
||||
status: 1,
|
||||
id: 0,
|
||||
})
|
||||
const noticeFormRef = ref()
|
||||
const noticeRules = ref(rules())
|
||||
const noticeFormItem = ref(formItem)
|
||||
const noticeFormOptionsMap = ref({
|
||||
status: [
|
||||
{ label: '草稿', value: 1 },
|
||||
{ label: '发布', value: 2 },
|
||||
],
|
||||
status: [
|
||||
{ label: '草稿', value: 1 },
|
||||
{ label: '发布', value: 2 },
|
||||
],
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
@ -174,152 +219,150 @@ const noticeFormOptionsMap = ref({
|
|||
*/
|
||||
//获取公告列表
|
||||
const getNoticeList = async () => {
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
page_size: pageSize.value,
|
||||
name: searchForm.value.noticeName,
|
||||
status: searchForm.value.status,
|
||||
publish_start_time: searchForm.value.startDateTime,
|
||||
publish_end_time: searchForm.value.endDateTime,
|
||||
}
|
||||
const data: any = await getNoticeListApi(params)
|
||||
// 表格数据
|
||||
noticeTree.value = data.data.map((item: any) => ({
|
||||
id: item.id,
|
||||
noticeName: item.name,
|
||||
noticeContent: item.content,
|
||||
publishTime: item.publish_time,
|
||||
status: item.status,
|
||||
}))
|
||||
// 分页数据
|
||||
total.value = data.total
|
||||
currentPage.value = data.current_page
|
||||
pageSize.value = Number(data.per_page)
|
||||
const params = {
|
||||
page: currentPage.value,
|
||||
page_size: pageSize.value,
|
||||
name: searchForm.value.noticeName,
|
||||
status: searchForm.value.status,
|
||||
publish_start_time: searchForm.value.startDateTime,
|
||||
publish_end_time: searchForm.value.endDateTime,
|
||||
}
|
||||
const data: any = await getNoticeListApi(params)
|
||||
// 表格数据
|
||||
noticeTree.value = data.data.map((item: any) => ({
|
||||
id: item.id,
|
||||
noticeName: item.name,
|
||||
noticeContent: item.content,
|
||||
publishTime: item.publish_time,
|
||||
status: item.status,
|
||||
}))
|
||||
// 分页数据
|
||||
total.value = data.total
|
||||
currentPage.value = data.current_page
|
||||
pageSize.value = Number(data.per_page)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 页面加载完成需要请求的数据
|
||||
*/
|
||||
onMounted(() => {
|
||||
getNoticeList()
|
||||
getNoticeList()
|
||||
})
|
||||
|
||||
/**
|
||||
* @description: 定义搜索方法
|
||||
*/
|
||||
const handleSearch = () => {
|
||||
getNoticeList()
|
||||
getNoticeList()
|
||||
}
|
||||
const handleReset = () => {
|
||||
searchForm.value = {
|
||||
noticeName: '',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
status: 2,
|
||||
}
|
||||
activeTab.value = 2
|
||||
getNoticeList()
|
||||
searchForm.value = {
|
||||
noticeName: '',
|
||||
startDateTime: '',
|
||||
endDateTime: '',
|
||||
status: 2,
|
||||
}
|
||||
activeTab.value = 2
|
||||
getNoticeList()
|
||||
}
|
||||
const handleCreate = () => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '新建公告'
|
||||
dialogType.value = 'create'
|
||||
noticeForm.value = {
|
||||
noticeName: '',
|
||||
noticeContent: '',
|
||||
status: 1,
|
||||
id: 0,
|
||||
} as any
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '新建公告'
|
||||
dialogType.value = 'create'
|
||||
noticeForm.value = {
|
||||
noticeName: '',
|
||||
noticeContent: '',
|
||||
status: 1,
|
||||
id: 0,
|
||||
} as any
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 定义tab方法
|
||||
*/
|
||||
const handleTabChange = (tab: number) => {
|
||||
activeTab.value = tab
|
||||
searchForm.value.status = tab
|
||||
currentPage.value = 1
|
||||
getNoticeList()
|
||||
activeTab.value = tab
|
||||
searchForm.value.status = tab
|
||||
currentPage.value = 1
|
||||
getNoticeList()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 定义表格方法
|
||||
*/
|
||||
const handleView = (row: any) => {
|
||||
console.log(row)
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '查看公告'
|
||||
dialogType.value = 'view'
|
||||
noticeForm.value = {
|
||||
noticeName: row.noticeName,
|
||||
noticeContent: row.noticeContent,
|
||||
} as any
|
||||
console.log(row)
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '查看公告'
|
||||
dialogType.value = 'view'
|
||||
noticeForm.value = {
|
||||
noticeName: row.noticeName,
|
||||
noticeContent: row.noticeContent,
|
||||
} as any
|
||||
}
|
||||
|
||||
|
||||
const handleEdit = (row: any) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '编辑公告'
|
||||
dialogType.value = 'edit'
|
||||
noticeForm.value = {
|
||||
noticeName: row.noticeName,
|
||||
status: row.status,
|
||||
id: row.id,
|
||||
} as any
|
||||
valueHtml.value = row.noticeContent
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '编辑公告'
|
||||
dialogType.value = 'edit'
|
||||
noticeForm.value = {
|
||||
noticeName: row.noticeName,
|
||||
status: row.status,
|
||||
id: row.id,
|
||||
} as any
|
||||
valueHtml.value = row.noticeContent
|
||||
}
|
||||
// 删除公告
|
||||
const handleDelete = async (row: any) => {
|
||||
const params = {
|
||||
id: row.id,
|
||||
}
|
||||
await deleteNoticeApi(params)
|
||||
getNoticeList()
|
||||
const params = {
|
||||
id: row.id,
|
||||
}
|
||||
await deleteNoticeApi(params)
|
||||
getNoticeList()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 定义分页方法
|
||||
*/
|
||||
const handlePaginationChange = async (page: { currentPage: number, pageSize: number }) => {
|
||||
currentPage.value = page.currentPage
|
||||
pageSize.value = page.pageSize
|
||||
await getNoticeList()
|
||||
const handlePaginationChange = async (page: { currentPage: number; pageSize: number }) => {
|
||||
currentPage.value = page.currentPage
|
||||
pageSize.value = page.pageSize
|
||||
await getNoticeList()
|
||||
}
|
||||
/**
|
||||
* @description: 定义弹窗方法
|
||||
*/
|
||||
const handleSubmit = async () => {
|
||||
await noticeFormRef.value.validate()
|
||||
if (dialogType.value === 'create') {
|
||||
noticeForm.value.noticeContent = valueHtml.value
|
||||
const params = {
|
||||
name: noticeForm.value.noticeName,
|
||||
content: noticeForm.value.noticeContent,
|
||||
status: noticeForm.value.status,
|
||||
}
|
||||
await createNoticeApi(params)
|
||||
dialogVisible.value = false
|
||||
getNoticeList()
|
||||
} else {
|
||||
noticeForm.value.noticeContent = valueHtml.value
|
||||
const params = {
|
||||
id: noticeForm.value.id,
|
||||
name: noticeForm.value.noticeName,
|
||||
content: noticeForm.value.noticeContent,
|
||||
status: noticeForm.value.status,
|
||||
}
|
||||
await editNoticeApi(params)
|
||||
dialogVisible.value = false
|
||||
getNoticeList()
|
||||
await noticeFormRef.value.validate()
|
||||
if (dialogType.value === 'create') {
|
||||
noticeForm.value.noticeContent = valueHtml.value
|
||||
const params = {
|
||||
name: noticeForm.value.noticeName,
|
||||
content: noticeForm.value.noticeContent,
|
||||
status: noticeForm.value.status,
|
||||
}
|
||||
|
||||
await createNoticeApi(params)
|
||||
dialogVisible.value = false
|
||||
getNoticeList()
|
||||
} else {
|
||||
noticeForm.value.noticeContent = valueHtml.value
|
||||
const params = {
|
||||
id: noticeForm.value.id,
|
||||
name: noticeForm.value.noticeName,
|
||||
content: noticeForm.value.noticeContent,
|
||||
status: noticeForm.value.status,
|
||||
}
|
||||
await editNoticeApi(params)
|
||||
dialogVisible.value = false
|
||||
getNoticeList()
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
dialogVisible.value = false
|
||||
dialogVisible.value = false
|
||||
}
|
||||
const handleClose = () => {
|
||||
dialogVisible.value = false
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -327,42 +370,42 @@ const handleClose = () => {
|
|||
*/
|
||||
// 组件销毁时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
const editor = editorRef.value
|
||||
if (editor == null) return
|
||||
editor.destroy()
|
||||
const editor = editorRef.value
|
||||
if (editor == null) return
|
||||
editor.destroy()
|
||||
})
|
||||
|
||||
// 富文本编辑器创建完成后回调
|
||||
const handleCreated = (editor: any) => {
|
||||
editorRef.value = editor
|
||||
editorRef.value = editor
|
||||
|
||||
// 在这里获取工具栏实例(必须等编辑器和工具栏都挂载后)
|
||||
nextTick(() => {
|
||||
const toolbar = DomEditor.getToolbar(editor)
|
||||
if (toolbar) {
|
||||
const curToolbarConfig = toolbar.getConfig()
|
||||
console.log('curToolbarConfig.toolbarKeys', curToolbarConfig.toolbarKeys)
|
||||
toolbarRef.value = toolbar
|
||||
console.log('toolbarRef.value', valueHtml.value)
|
||||
}
|
||||
})
|
||||
// 在这里获取工具栏实例(必须等编辑器和工具栏都挂载后)
|
||||
nextTick(() => {
|
||||
const toolbar = DomEditor.getToolbar(editor)
|
||||
if (toolbar) {
|
||||
const curToolbarConfig = toolbar.getConfig()
|
||||
console.log('curToolbarConfig.toolbarKeys', curToolbarConfig.toolbarKeys)
|
||||
toolbarRef.value = toolbar
|
||||
console.log('toolbarRef.value', valueHtml.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tab {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.el-button {
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.view-content {
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,17 +2,39 @@
|
|||
* @description: 搜索配置
|
||||
*/
|
||||
export const search = [
|
||||
{ prop: 'noticeName', label: '公告名称', type: 'input' as const, placeholder: '请输入公告名称', width: '120px' },
|
||||
{
|
||||
prop: "startDateTime", label: '发布时间', type: 'date' as const, dateType: 'date' as const, // 时间范围选择器
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
width: '180px',
|
||||
},
|
||||
{
|
||||
prop: "endDateTime", label: '结束时间', type: 'date' as const, dateType: 'date' as const, // 时间范围选择器
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
width: '180px',
|
||||
},
|
||||
{
|
||||
prop: 'noticeName',
|
||||
label: '公告名称',
|
||||
type: 'input' as const,
|
||||
placeholder: '请输入公告名称',
|
||||
width: '120px',
|
||||
},
|
||||
{
|
||||
prop: 'startDateTime',
|
||||
label: '发布时间',
|
||||
type: 'date' as const,
|
||||
dateType: 'date' as const, // 时间范围选择器
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
width: '180px',
|
||||
},
|
||||
{
|
||||
prop: 'endDateTime',
|
||||
label: '结束时间',
|
||||
type: 'date' as const,
|
||||
dateType: 'date' as const, // 时间范围选择器
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
width: '180px',
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
type: 'select' as const,
|
||||
placeholder: '请选择状态',
|
||||
options: [
|
||||
{ label: '草稿', value: 1 },
|
||||
{ label: '已发布', value: 2 },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<!-- 角色列表头 -->
|
||||
<div class="header">
|
||||
<h4>角色列表</h4>
|
||||
<el-button type="primary" @click="handleAddRole">新增角色</el-button>
|
||||
<el-button type="primary" @click="handleAddRole" v-auth="'roles_create'">新增角色</el-button>
|
||||
</div>
|
||||
<!-- 角色列表表格 -->
|
||||
<RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id">
|
||||
|
|
@ -20,11 +20,33 @@
|
|||
{{ row.created_at }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button link type="primary" size="small" @click="handleEditRole(row)"> 编辑 </el-button>
|
||||
<el-button link type="primary" size="small" @click="handlePermission(row)">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleEditRole(row)"
|
||||
v-auth="'roles_edit'"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handlePermission(row)"
|
||||
v-auth="'roles_setPermission'"
|
||||
>
|
||||
设置权限
|
||||
</el-button>
|
||||
<el-button link type="danger" size="small" @click="handleDeleteRole(row)"> 删除 </el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDeleteRole(row)"
|
||||
v-auth="'roles_del'"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</RoleTable>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<template>
|
||||
<div class="trade-group">
|
||||
<el-form-item label="交易组时间设置">
|
||||
<el-button type="primary" @click="addTableItem">添加</el-button>
|
||||
<el-button type="primary" @click="addTableItem" v-auth="'contractVariety_createGroup'"
|
||||
>添加</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
<!-- 表格 -->
|
||||
<div class="table-box">
|
||||
|
|
@ -60,16 +62,32 @@
|
|||
</template>
|
||||
</td>
|
||||
<td rowspan="2" style="width: 140px">
|
||||
<el-button type="primary" v-if="!item.editStatus" @click="item.editStatus = true"
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="!item.editStatus"
|
||||
@click="item.editStatus = true"
|
||||
v-auth="'contractVariety_editGroup'"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button type="danger" v-if="!item.editStatus" @click="deleteGroup(item.id, index)"
|
||||
<el-button
|
||||
type="danger"
|
||||
v-if="!item.editStatus"
|
||||
@click="deleteGroup(item.id, index)"
|
||||
v-auth="'contractVariety_delGroup'"
|
||||
>删除</el-button
|
||||
>
|
||||
<el-button type="primary" v-if="item.editStatus" @click="submitItem(index)"
|
||||
<el-button
|
||||
type="primary"
|
||||
v-if="item.editStatus"
|
||||
@click="submitItem(index)"
|
||||
v-auth="'contractVariety_editGroup'"
|
||||
>确认</el-button
|
||||
>
|
||||
<el-button type="danger" v-if="item.editStatus" @click="item.editStatus = false"
|
||||
<el-button
|
||||
type="danger"
|
||||
v-if="item.editStatus"
|
||||
@click="item.editStatus = false"
|
||||
v-auth="'contractVariety_editGroup'"
|
||||
>取消</el-button
|
||||
>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,17 @@
|
|||
@reset="handleReset"
|
||||
>
|
||||
<template #button="{ form }">
|
||||
<el-button type="primary" :disabled="!selectedRow" @click="handleEdit()"> 编辑 </el-button>
|
||||
<el-button type="primary" @click="handleAdd()"> 添加 </el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!selectedRow"
|
||||
@click="handleEdit()"
|
||||
v-auth="'contracVarietediariety'"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleAdd()" v-auth="'contractVariety_createVariety'">
|
||||
添加
|
||||
</el-button>
|
||||
</template>
|
||||
</VarietySearch>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue