1.优化分红方式
This commit is contained in:
@@ -2,6 +2,9 @@ export default {
|
||||
username: 'Username',
|
||||
nickname: 'Nickname',
|
||||
group: 'Group',
|
||||
channel: 'Channel',
|
||||
parent_admin: 'Parent agent',
|
||||
commission_share_rate: 'Commission share (%)',
|
||||
avatar: 'Avatar',
|
||||
email: 'Email',
|
||||
mobile: 'Mobile Number',
|
||||
@@ -12,4 +15,12 @@ export default {
|
||||
'Please leave blank if not modified': 'Please leave blank if you do not modify.',
|
||||
'Personal signature': 'Personal Signature',
|
||||
'Administrator login': 'Administrator Login Name',
|
||||
'Manage subordinate agents here':
|
||||
'Manage your subordinate agents here. You can only see yourself and your downline, not sub-agents under other agents.',
|
||||
'Parent admin placeholder': 'Leave empty for top-level channel agent',
|
||||
'Share remainder hint':
|
||||
'Siblings already use {used}%; remaining allocatable {remaining}%. After saving this value, parent keeps about {after}%.',
|
||||
'Share remainder none for parent': 'Sibling shares total 100%; the parent will keep no commission at this level.',
|
||||
'Share remainder none after current': 'This rate exceeds the remaining allocatable share. Please lower it before saving.',
|
||||
'Commission share rate range': 'Commission share must be between 0 and 100',
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ export default {
|
||||
username: '用户名',
|
||||
nickname: '昵称',
|
||||
group: '角色组',
|
||||
channel: '渠道',
|
||||
parent_admin: '上级代理',
|
||||
commission_share_rate: '分红比例(%)',
|
||||
avatar: '头像',
|
||||
email: '电子邮箱',
|
||||
mobile: '手机号',
|
||||
@@ -12,4 +15,10 @@ export default {
|
||||
'Please leave blank if not modified': '不修改请留空',
|
||||
'Personal signature': '个性签名',
|
||||
'Administrator login': '管理员登录名',
|
||||
'Manage subordinate agents here': '在此管理您下级代理管理员;仅显示您本人及所有下级,无法查看其他代理线下的子代理。',
|
||||
'Parent admin placeholder': '留空表示渠道顶级代理',
|
||||
'Share remainder hint': '同上级下已分配 {used}%,当前剩余可设 {remaining}%;若本项设为当前值,保存后上级约剩 {after}%。',
|
||||
'Share remainder none for parent': '同上级下子代理比例已合计 100%,上级在本层将无分红留存。',
|
||||
'Share remainder none after current': '当前比例将超过剩余可分配额度,请调低后再保存。',
|
||||
'Commission share rate range': '分红比例须在 0~100 之间',
|
||||
}
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert
|
||||
class="ba-table-alert admin-tree-alert"
|
||||
v-if="!adminInfo.super"
|
||||
:title="t('auth.admin.Manage subordinate agents here')"
|
||||
type="info"
|
||||
show-icon
|
||||
/>
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'unfold', 'comSearch', 'quickSearch', 'columnDisplay']"
|
||||
:quick-search-placeholder="t('Quick search placeholder', { fields: t('auth.admin.username') + '/' + t('auth.admin.nickname') })"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table />
|
||||
<Table ref="tableRef" :pagination="false" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<PopupForm />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { provide } from 'vue'
|
||||
import { onMounted, provide, useTemplateRef } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import PopupForm from './popupForm.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
@@ -34,6 +37,7 @@ defineOptions({
|
||||
|
||||
const { t } = useI18n()
|
||||
const adminInfo = useAdminInfo()
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
|
||||
const optButtons = defaultOptButtons(['edit', 'delete'])
|
||||
optButtons[1].display = (row) => {
|
||||
@@ -43,23 +47,69 @@ optButtons[1].display = (row) => {
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi('/admin/auth.Admin/'),
|
||||
{
|
||||
expandAll: true,
|
||||
dblClickNotEditColumn: [undefined, 'status'],
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{ label: t('auth.admin.username'), prop: 'username', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('Id'), prop: 'id', align: 'center', show: false, operator: '=', operatorPlaceholder: t('Id'), width: 70 },
|
||||
{
|
||||
label: t('auth.admin.username'),
|
||||
prop: 'username',
|
||||
align: 'left',
|
||||
minWidth: 160,
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{ label: t('auth.admin.nickname'), prop: 'nickname', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{
|
||||
label: t('auth.admin.channel'),
|
||||
prop: 'channel_id',
|
||||
show: false,
|
||||
operator: 'eq',
|
||||
comSearchRender: 'remoteSelect',
|
||||
comSearchInputAttr: {
|
||||
remoteUrl: '/admin/channel/index',
|
||||
field: 'name',
|
||||
pk: 'id',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('auth.admin.channel'),
|
||||
prop: 'channel_name',
|
||||
align: 'center',
|
||||
minWidth: 120,
|
||||
operator: false,
|
||||
},
|
||||
{
|
||||
label: t('auth.admin.parent_admin'),
|
||||
prop: 'parent_admin_username',
|
||||
align: 'center',
|
||||
minWidth: 120,
|
||||
operator: false,
|
||||
},
|
||||
{
|
||||
label: t('auth.admin.commission_share_rate'),
|
||||
prop: 'commission_share_rate',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
operator: false,
|
||||
formatter: (_row, _col, val) => {
|
||||
if (val === null || val === undefined || val === '') return '-'
|
||||
return `${val}%`
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('auth.admin.group'),
|
||||
prop: 'group_name_arr',
|
||||
align: 'center',
|
||||
minWidth: 150,
|
||||
minWidth: 140,
|
||||
operator: false,
|
||||
render: 'tags',
|
||||
},
|
||||
{ label: t('auth.admin.invite_code'), prop: 'invite_code', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('auth.admin.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false },
|
||||
{ label: t('auth.admin.email'), prop: 'email', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('auth.admin.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query') },
|
||||
{ label: t('auth.admin.avatar'), prop: 'avatar', align: 'center', render: 'image', operator: false, show: false },
|
||||
{ label: t('auth.admin.email'), prop: 'email', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query'), show: false },
|
||||
{ label: t('auth.admin.mobile'), prop: 'mobile', align: 'center', operator: 'LIKE', operatorPlaceholder: t('Fuzzy query'), show: false },
|
||||
{
|
||||
label: t('auth.admin.Last login'),
|
||||
prop: 'last_login_time',
|
||||
@@ -68,6 +118,7 @@ const baTable = new baTableClass(
|
||||
sortable: 'custom',
|
||||
operator: 'RANGE',
|
||||
width: 160,
|
||||
show: false,
|
||||
},
|
||||
{ label: t('Create time'), prop: 'create_time', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
@@ -88,7 +139,7 @@ const baTable = new baTableClass(
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
minWidth: '80',
|
||||
width: 100,
|
||||
render: 'buttons',
|
||||
buttons: optButtons,
|
||||
operator: false,
|
||||
@@ -100,22 +151,32 @@ const baTable = new baTableClass(
|
||||
{
|
||||
defaultItems: {
|
||||
status: 'enable',
|
||||
parent_admin_id: null,
|
||||
commission_share_rate: null,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// 编辑自身时不提交角色组,避免与后端「不可修改自己所在管理组」校验冲突
|
||||
baTable.before.onSubmit = ({ operate, items }) => {
|
||||
if (operate === 'edit' && items.id == adminInfo.id) {
|
||||
delete items.group_arr
|
||||
delete items.group_name_arr
|
||||
delete items.parent_admin_id
|
||||
delete items.commission_share_rate
|
||||
}
|
||||
}
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
.admin-tree-alert {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
@@ -41,6 +40,19 @@
|
||||
prop="nickname"
|
||||
:placeholder="t('Please input field', { field: t('auth.admin.nickname') })"
|
||||
/>
|
||||
<FormItem
|
||||
v-if="showChannelField"
|
||||
:label="t('auth.admin.channel')"
|
||||
v-model="baTable.form.items!.channel_id"
|
||||
type="remoteSelect"
|
||||
prop="channel_id"
|
||||
:input-attr="{
|
||||
remoteUrl: '/admin/channel/index',
|
||||
field: 'name',
|
||||
pk: 'id',
|
||||
placeholder: t('Click select'),
|
||||
}"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('auth.admin.group')"
|
||||
v-model="singleGroupValue"
|
||||
@@ -56,6 +68,37 @@
|
||||
placeholder: t('Click select'),
|
||||
}"
|
||||
/>
|
||||
<FormItem
|
||||
v-if="showParentField"
|
||||
:label="t('auth.admin.parent_admin')"
|
||||
v-model="baTable.form.items!.parent_admin_id"
|
||||
type="remoteSelect"
|
||||
prop="parent_admin_id"
|
||||
:input-attr="{
|
||||
remoteUrl: '/admin/auth.Admin/index',
|
||||
field: 'username',
|
||||
pk: 'id',
|
||||
params: parentSelectParams,
|
||||
placeholder: t('auth.admin.Parent admin placeholder'),
|
||||
}"
|
||||
/>
|
||||
<FormItem
|
||||
v-if="showShareRateField"
|
||||
:label="t('auth.admin.commission_share_rate')"
|
||||
v-model="baTable.form.items!.commission_share_rate"
|
||||
type="number"
|
||||
prop="commission_share_rate"
|
||||
:input-attr="{
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 0.01,
|
||||
precision: 2,
|
||||
class: 'w100',
|
||||
}"
|
||||
/>
|
||||
<el-form-item v-if="showShareRateField && shareHint" label=" ">
|
||||
<el-alert :title="shareHint" :type="shareHintType" :closable="false" show-icon />
|
||||
</el-form-item>
|
||||
<FormItem
|
||||
v-if="baTable.form.operate == 'Edit'"
|
||||
:label="t('auth.admin.invite_code')"
|
||||
@@ -123,7 +166,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, inject, watch, useTemplateRef } from 'vue'
|
||||
import { computed, inject, reactive, ref, useTemplateRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import { regularPassword, buildValidatorData } from '/@/utils/validate'
|
||||
@@ -131,6 +174,7 @@ import type { FormItemRule } from 'element-plus'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import createAxios from '/@/utils/axios'
|
||||
|
||||
const config = useConfig()
|
||||
const adminInfo = useAdminInfo()
|
||||
@@ -139,6 +183,45 @@ const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const shareHint = ref('')
|
||||
const shareHintType = ref<'info' | 'warning'>('info')
|
||||
|
||||
const isSelfEdit = computed(() => baTable.form.operate === 'Edit' && adminInfo.id == baTable.form.items?.id)
|
||||
|
||||
const showChannelField = computed(() => adminInfo.super && !isSelfEdit.value)
|
||||
|
||||
const showParentField = computed(() => adminInfo.super && !isSelfEdit.value)
|
||||
|
||||
const showShareRateField = computed(() => {
|
||||
if (isSelfEdit.value) return false
|
||||
if (adminInfo.super) {
|
||||
const pid = baTable.form.items?.parent_admin_id
|
||||
return pid !== null && pid !== undefined && pid !== '' && Number(pid) > 0
|
||||
}
|
||||
if (baTable.form.operate === 'Add') {
|
||||
return true
|
||||
}
|
||||
const pid = baTable.form.items?.parent_admin_id
|
||||
return pid !== null && pid !== undefined && pid !== '' && Number(pid) > 0
|
||||
})
|
||||
|
||||
const parentSelectParams = computed(() => {
|
||||
const params: anyObj = { select: true, limit: 200 }
|
||||
const cid = baTable.form.items?.channel_id
|
||||
if (cid !== null && cid !== undefined && cid !== '') {
|
||||
params['search[0][field]'] = 'channel_id'
|
||||
params['search[0][operator]'] = 'eq'
|
||||
params['search[0][val]'] = cid
|
||||
}
|
||||
const excludeId = baTable.form.items?.id
|
||||
if (excludeId) {
|
||||
params['search[1][field]'] = 'id'
|
||||
params['search[1][operator]'] = 'neq'
|
||||
params['search[1][val]'] = excludeId
|
||||
}
|
||||
return params
|
||||
})
|
||||
|
||||
const singleGroupValue = computed({
|
||||
get: () => {
|
||||
const group = baTable.form.items?.group_arr
|
||||
@@ -155,6 +238,73 @@ const singleGroupValue = computed({
|
||||
},
|
||||
})
|
||||
|
||||
const loadShareRemainder = async () => {
|
||||
if (!showShareRateField.value) {
|
||||
shareHint.value = ''
|
||||
return
|
||||
}
|
||||
let parentId = baTable.form.items?.parent_admin_id
|
||||
if (!adminInfo.super) {
|
||||
parentId = adminInfo.id
|
||||
}
|
||||
if (!parentId || Number(parentId) <= 0) {
|
||||
shareHint.value = ''
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await createAxios({
|
||||
url: '/admin/auth.Admin/commissionShareRemainder',
|
||||
method: 'get',
|
||||
params: {
|
||||
parent_admin_id: parentId,
|
||||
exclude_id: baTable.form.items?.id || 0,
|
||||
},
|
||||
})
|
||||
const remaining = res.data.remaining_rate ?? '100.00'
|
||||
const used = res.data.used_rate ?? '0.00'
|
||||
const current = baTable.form.items?.commission_share_rate
|
||||
let afterCurrent = remaining
|
||||
if (current !== null && current !== undefined && current !== '') {
|
||||
afterCurrent = (Number(remaining) - Number(current)).toFixed(2)
|
||||
}
|
||||
shareHint.value = t('auth.admin.Share remainder hint', {
|
||||
used,
|
||||
remaining,
|
||||
after: afterCurrent,
|
||||
})
|
||||
shareHintType.value = Number(remaining) <= 0 || Number(afterCurrent) < 0 ? 'warning' : 'info'
|
||||
if (Number(remaining) <= 0) {
|
||||
shareHint.value = t('auth.admin.Share remainder none for parent')
|
||||
} else if (Number(afterCurrent) <= 0 && current) {
|
||||
shareHint.value = t('auth.admin.Share remainder none after current')
|
||||
}
|
||||
} catch {
|
||||
shareHint.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [baTable.form.items?.parent_admin_id, baTable.form.items?.commission_share_rate, baTable.form.operate],
|
||||
() => {
|
||||
void loadShareRemainder()
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => baTable.form.items?.share_remainder,
|
||||
(val) => {
|
||||
if (val && baTable.form.operate === 'Edit') {
|
||||
shareHint.value = t('auth.admin.Share remainder hint', {
|
||||
used: val.used_rate ?? '0.00',
|
||||
remaining: val.remaining_rate ?? '100.00',
|
||||
after: val.remaining_rate ?? '100.00',
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
username: [buildValidatorData({ name: 'required', title: t('auth.admin.username') }), buildValidatorData({ name: 'account' })],
|
||||
nickname: [buildValidatorData({ name: 'required', title: t('auth.admin.nickname') })],
|
||||
@@ -179,6 +329,24 @@ const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
commission_share_rate: [
|
||||
{
|
||||
validator: (_rule: any, val: unknown, callback: Function) => {
|
||||
if (!showShareRateField.value) {
|
||||
return callback()
|
||||
}
|
||||
if (val === null || val === undefined || val === '') {
|
||||
return callback(new Error(t('Please input field', { field: t('auth.admin.commission_share_rate') })))
|
||||
}
|
||||
const num = Number(val)
|
||||
if (!Number.isFinite(num) || num < 0 || num > 100) {
|
||||
return callback(new Error(t('auth.admin.Commission share rate range')))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
email: [buildValidatorData({ name: 'email', message: t('Please enter the correct field', { field: t('auth.admin.email') }) })],
|
||||
mobile: [buildValidatorData({ name: 'mobile', message: t('Please enter the correct field', { field: t('auth.admin.mobile') }) })],
|
||||
password: [
|
||||
|
||||
@@ -106,51 +106,6 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog class="ba-operate-dialog" :close-on-click-modal="false" :model-value="shareDialog.visible" @close="closeShareDialog">
|
||||
<template #header>
|
||||
<div class="title">{{ t('channel.share_config_title') }}</div>
|
||||
</template>
|
||||
<div v-loading="shareDialog.loading" class="manual-settle-dialog-body">
|
||||
<el-alert type="info" :closable="false" show-icon class="mb-12">
|
||||
{{ t('channel.share_config_tip') }}
|
||||
</el-alert>
|
||||
<el-table :data="shareDialog.list" border size="small">
|
||||
<el-table-column :label="t('channel.admin_group_names')" min-width="260">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.role_group_name" class="share-group-single">{{ scope.row.role_group_name }}</span>
|
||||
<span v-else class="share-group-empty">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="username" :label="t('channel.admin__username')" min-width="120" />
|
||||
<el-table-column :label="t('channel.status')" width="120">
|
||||
<template #default="scope">
|
||||
<el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="t('channel.share_rate_percent')" min-width="180">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
v-model="scope.row.share_rate"
|
||||
:disabled="scope.row.status !== 1"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="0.01"
|
||||
:precision="2"
|
||||
class="w100"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="share-total-row">
|
||||
<span>{{ t('channel.share_total_enabled') }}: </span>
|
||||
<el-tag :type="shareEnabledTotal === '100.00' ? 'success' : 'danger'">{{ shareEnabledTotal }}%</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="closeShareDialog">{{ t('Cancel') }}</el-button>
|
||||
<el-button type="primary" :loading="shareDialog.saving" @click="saveShareDialog">{{ t('Save') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -176,20 +131,6 @@ const { t } = useI18n()
|
||||
const adminInfo = useAdminInfo()
|
||||
const tableRef = useTemplateRef('tableRef')
|
||||
let optButtons: OptButton[] = [
|
||||
{
|
||||
render: 'tipButton',
|
||||
name: 'shareConfig',
|
||||
title: 'channel.share_config',
|
||||
text: '',
|
||||
type: 'primary',
|
||||
icon: 'el-icon-Setting',
|
||||
class: 'table-row-share-config',
|
||||
disabledTip: false,
|
||||
display: () => auth('edit'),
|
||||
click: (row: TableRow) => {
|
||||
void openShareDialog(row)
|
||||
},
|
||||
},
|
||||
{
|
||||
render: 'tipButton',
|
||||
name: 'manualSettle',
|
||||
@@ -242,13 +183,6 @@ const manualSettle = reactive({
|
||||
},
|
||||
})
|
||||
|
||||
const shareDialog = reactive({
|
||||
visible: false,
|
||||
loading: false,
|
||||
saving: false,
|
||||
channelId: 0,
|
||||
list: [] as Array<{ admin_id: number; username: string; role_group_name: string; role_level: number; status: number; share_rate: number | null }>,
|
||||
})
|
||||
const settleFilterMode = ref<'all' | 'with_balance' | 'no_balance' | 'enabled' | 'disabled'>('all')
|
||||
const settleStats = reactive({
|
||||
channel_total: 0,
|
||||
@@ -259,90 +193,6 @@ const settleStats = reactive({
|
||||
carryover_positive_total: '0.00',
|
||||
})
|
||||
|
||||
const shareEnabledTotal = computed(() => {
|
||||
let sum = 0
|
||||
for (const row of shareDialog.list) {
|
||||
if (row.status === 1) {
|
||||
const n = Number(row.share_rate ?? 0)
|
||||
if (Number.isFinite(n)) {
|
||||
sum += n
|
||||
}
|
||||
}
|
||||
}
|
||||
return sum.toFixed(2)
|
||||
})
|
||||
|
||||
const closeShareDialog = () => {
|
||||
shareDialog.visible = false
|
||||
shareDialog.channelId = 0
|
||||
shareDialog.list = []
|
||||
}
|
||||
|
||||
const openShareDialog = async (row: TableRow) => {
|
||||
shareDialog.channelId = Number(row.id || 0)
|
||||
shareDialog.visible = true
|
||||
shareDialog.loading = true
|
||||
try {
|
||||
const res = await createAxios(
|
||||
{
|
||||
url: '/admin/channel/channelAdminShareList',
|
||||
method: 'get',
|
||||
params: { id: row.id },
|
||||
},
|
||||
{ showErrorMessage: true }
|
||||
)
|
||||
if (res.code !== 1 || !res.data) {
|
||||
closeShareDialog()
|
||||
return
|
||||
}
|
||||
const list = Array.isArray(res.data.list) ? res.data.list : []
|
||||
shareDialog.list = list.map((item: anyObj) => {
|
||||
const rate = item.share_rate
|
||||
return {
|
||||
admin_id: Number(item.admin_id || 0),
|
||||
username: String(item.username || ''),
|
||||
role_group_name: String(item.role_group_name || ''),
|
||||
role_level: Number(item.role_level ?? 9999),
|
||||
status: Number(item.status ?? 1) === 1 ? 1 : 0,
|
||||
share_rate: rate === null || rate === undefined || rate === '' ? null : Number(rate),
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
shareDialog.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
const saveShareDialog = async () => {
|
||||
if (!shareDialog.channelId) {
|
||||
return
|
||||
}
|
||||
if (shareEnabledTotal.value !== '100.00') {
|
||||
ElMessage.error(t('channel.share_total_must_100'))
|
||||
return
|
||||
}
|
||||
shareDialog.saving = true
|
||||
try {
|
||||
await createAxios(
|
||||
{
|
||||
url: '/admin/channel/saveChannelAdminShare',
|
||||
method: 'post',
|
||||
data: {
|
||||
id: shareDialog.channelId,
|
||||
list: shareDialog.list.map((row) => ({
|
||||
admin_id: row.admin_id,
|
||||
status: row.status,
|
||||
share_rate: Number(row.share_rate || 0).toFixed(2),
|
||||
})),
|
||||
},
|
||||
},
|
||||
{ showSuccessMessage: true }
|
||||
)
|
||||
closeShareDialog()
|
||||
} finally {
|
||||
shareDialog.saving = false
|
||||
}
|
||||
}
|
||||
|
||||
const resetManualSettleForm = () => {
|
||||
manualSettle.form.settlement_no = ''
|
||||
manualSettle.form.period_start_at = ''
|
||||
|
||||
Reference in New Issue
Block a user