1234 lines
31 KiB
Vue
1234 lines
31 KiB
Vue
<template>
|
||
<div class="blacklist-layout">
|
||
<div ref="refHeight" class="layout-content">
|
||
<BasicLayoutLeftRight :left-width="280">
|
||
<template #left>
|
||
<div class="left-sidebar">
|
||
<CustomLeftMenu
|
||
:tree-data="leftTreeData"
|
||
:selected-keys="leftSelectedKeys"
|
||
v-model:expanded-keys="leftExpandedKeys"
|
||
:search-keyword="searchModel.keyword"
|
||
@update:search-keyword="(v) => (searchModel.keyword = v)"
|
||
:search-placeholder="t('channel.area.search.placeholder')"
|
||
:refresh-title="t('channel.area.search.refresh')"
|
||
:add-title="t('channel.area.search.addArea')"
|
||
show-node-index
|
||
:show-method="false"
|
||
:show-map-count="false"
|
||
:show-node-code="false"
|
||
show-node-actions
|
||
:delete-label="t('channel.area.actions.delete')"
|
||
@search="onFormSubmitClick"
|
||
@refresh="onFormSubmitClick"
|
||
@add="handleOpenModal('add')"
|
||
@select="handleSelectFromTree"
|
||
@delete-node="handleDeleteLeftNode"
|
||
>
|
||
<template #node-menu="{ nodeData }">
|
||
<a-doption value="edit" @click="handleOpenModal('edit', nodeData)">
|
||
<IconEdit />
|
||
{{ t('channel.area.actions.edit') }}
|
||
</a-doption>
|
||
<a-doption value="delete" @click="handleDelData(nodeData?.id)">
|
||
<IconDelete />
|
||
{{ t('channel.area.actions.delete') }}
|
||
</a-doption>
|
||
</template>
|
||
</CustomLeftMenu>
|
||
|
||
<ModalForm
|
||
ref="modalFormLeftRef"
|
||
:edit-api="postForewarningServiceKpiAreaModifyKpiArea"
|
||
:add-api="postForewarningServiceKpiAreaCreateKpiArea"
|
||
:info-api="returnEditRowParams"
|
||
:api-params="editFormParams"
|
||
:form-props="formTopProps()"
|
||
@on-submit="onSubmitLeft"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<template #right>
|
||
<div class="right-content-panel">
|
||
<ModalForm
|
||
ref="modalFormRightRef"
|
||
:edit-api="postForewarningServiceKpiAreaModifyKpiAreaInfo"
|
||
:add-api="postForewarningServiceKpiAreaAddAreaInfo"
|
||
:info-api="returnRightEditRowParams"
|
||
:api-params="editFormRightParams"
|
||
:form-props="formPros"
|
||
@on-submit="onSubmitRight"
|
||
/>
|
||
|
||
<!-- 表格操作按钮和分页控制 -->
|
||
<div class="table-toolbar">
|
||
<div class="toolbar-left">
|
||
<div class="custom-buttons">
|
||
<a-button
|
||
class="btn-add"
|
||
:disabled="!currentId?.id"
|
||
@click="handleOpenRightModal('add')"
|
||
>
|
||
新增
|
||
</a-button>
|
||
</div>
|
||
</div>
|
||
<div class="toolbar-right">
|
||
<div class="pagination-controls">
|
||
<span class="total-records">
|
||
{{ $t('channel.area.pagination.total', { count: totalCount }) }}
|
||
</span>
|
||
<a-button
|
||
size="small"
|
||
:disabled="currentPage <= 1"
|
||
@click="handlePageChange(currentPage - 1)"
|
||
>
|
||
<
|
||
</a-button>
|
||
<span class="current-page">{{ currentPage }}</span>
|
||
<a-button
|
||
size="small"
|
||
:disabled="currentPage >= Math.ceil(totalCount / pageSize)"
|
||
@click="handlePageChange(currentPage + 1)"
|
||
>
|
||
>
|
||
</a-button>
|
||
<a-select
|
||
v-model="pageSize"
|
||
size="small"
|
||
class="page-size-select"
|
||
@change="handlePageSizeChange"
|
||
>
|
||
<a-option :value="10">10</a-option>
|
||
<a-option :value="30">30</a-option>
|
||
<a-option :value="50">50</a-option>
|
||
<a-option :value="100">100</a-option>
|
||
</a-select>
|
||
<span class="page-size-text">{{ $t('channel.area.pagination.perPage') }}</span>
|
||
<span class="go-to-text">{{ $t('channel.area.pagination.goTo') }}</span>
|
||
<a-input
|
||
v-model="jumpPage"
|
||
size="small"
|
||
class="jump-input"
|
||
@keyup.enter="handleJumpPage"
|
||
/>
|
||
<span class="page-text">{{ $t('channel.area.pagination.page') }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 使用 TablePro 组件 -->
|
||
<div style="flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column;">
|
||
<TablePro ref="tableRef" v-bind="tableProps" style="flex: 1; height: 100%;">
|
||
<template #action="{ row }">
|
||
<div class="action-buttons">
|
||
<a-button
|
||
type="text"
|
||
size="small"
|
||
class="action-btn edit-btn"
|
||
style="color: #8c8c8c !important;"
|
||
@click="handleOpenRightModal('edit', row)"
|
||
:title="$t('trajectory.region.actions.edit')"
|
||
>
|
||
<IconEdit />
|
||
</a-button>
|
||
<a-button
|
||
type="text"
|
||
size="small"
|
||
class="action-btn delete-btn"
|
||
style="color: #ff4d4f !important;"
|
||
@click="handleDelRightData(row.id)"
|
||
:title="$t('trajectory.region.actions.delete')"
|
||
>
|
||
<IconDelete />
|
||
</a-button>
|
||
</div>
|
||
</template>
|
||
</TablePro>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</BasicLayoutLeftRight>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { cloneDeep } from 'lodash-es';
|
||
import { useI18n } from 'vue-i18n';
|
||
import { useUserStore } from '@/store';
|
||
import {
|
||
postForewarningServiceKpiAreaCreateKpiArea,
|
||
postForewarningServiceKpiAreaAddAreaInfo,
|
||
deleteForewarningServiceKpiAreaDeleteKpiArea,
|
||
deleteForewarningServiceKpiAreaDeleteKpiAreaInfo,
|
||
postForewarningServiceKpiAreaGetKpiAreaInfos,
|
||
postForewarningServiceKpiAreaModifyKpiAreaInfo,
|
||
postForewarningServiceKpiAreaModifyKpiArea,
|
||
postForewarningServiceKpiAreaGetKpiAreas,
|
||
} from '@/api/interface-Provider/kpiArea';
|
||
|
||
import { $baseMessage } from '@/utils';
|
||
import { IconEdit, IconDelete, IconPlus, IconSearch } from '@arco-design/web-vue/es/icon';
|
||
import CustomLeftMenu from '@/components/CustomLeftMenu/index.vue';
|
||
import type { CustomLeftMenuTreeNode } from '@/components/CustomLeftMenu/types';
|
||
|
||
import TemplateScroll from './components/TemplateScroll.vue';
|
||
|
||
const userStore = useUserStore();
|
||
const { t } = useI18n();
|
||
// import { CountryGetPageGET } from '@/api/dc-masterData/Country'
|
||
|
||
defineOptions({
|
||
name: 'Blacklist',
|
||
});
|
||
|
||
type IDialogConfig = {
|
||
show: boolean;
|
||
type: 'add' | 'edit';
|
||
title: string;
|
||
};
|
||
|
||
const formProRef = ref();
|
||
/** 左侧弹窗表单 */
|
||
|
||
const formTopProps = computed(() => {
|
||
return (isTop = false) => {
|
||
const titleList = [
|
||
{
|
||
label: t('channel.area.form.keyword'),
|
||
field: 'name',
|
||
comp: 'AInput',
|
||
compProps: {
|
||
onKeyup: (e: KeyboardEvent) => {
|
||
if (e.key === 'Enter') onFormSubmitClick();
|
||
},
|
||
maxlength: 50,
|
||
placeholder: t('channel.area.form.placeholder.keyword'),
|
||
},
|
||
span: 6,
|
||
},
|
||
];
|
||
const obj = !isTop
|
||
? { formLayout: 'vertical', defaultSpan: 24 }
|
||
: {
|
||
layout: 'inline',
|
||
buttonConfig: {
|
||
showBtn: true,
|
||
okText: t('channel.area.search.button.query'),
|
||
showReset: true,
|
||
showOk: true,
|
||
resetText: t('channel.area.search.button.reset'),
|
||
},
|
||
};
|
||
return {
|
||
...obj,
|
||
itemList: isTop
|
||
? titleList
|
||
: [
|
||
{
|
||
label: t('channel.area.form.areaName'),
|
||
field: 'name',
|
||
comp: 'a-input',
|
||
compProps: {
|
||
placeholder: t('channel.area.form.placeholder.areaName'),
|
||
clearable: true,
|
||
},
|
||
span: isTop ? 6 : 24,
|
||
|
||
rules: [
|
||
{
|
||
required: true,
|
||
message: t('channel.area.form.rules.areaNameRequired'),
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|
||
};
|
||
});
|
||
|
||
const formPros = reactive({
|
||
formLayout: 'vertical',
|
||
defaultSpan: 24,
|
||
itemList: [
|
||
{
|
||
label: t('channel.area.form.country'),
|
||
field: 'countryName',
|
||
comp: 'AInput',
|
||
compProps: () => {
|
||
return {
|
||
onChange: (e: any) => {
|
||
editFormRightParams.countryCode = e;
|
||
},
|
||
};
|
||
},
|
||
|
||
rules: [
|
||
{
|
||
required: true,
|
||
message: t('channel.area.form.rules.countryRequired'),
|
||
},
|
||
],
|
||
span: 24,
|
||
},
|
||
{
|
||
label: t('channel.area.form.province'),
|
||
field: 'province',
|
||
comp: 'a-input',
|
||
compProps: {
|
||
placeholder: t('channel.area.form.placeholder.input'),
|
||
clearable: true,
|
||
},
|
||
rules: [
|
||
{
|
||
max: 128,
|
||
message: t('channel.area.form.rules.maxLength128'),
|
||
trigger: 'change',
|
||
},
|
||
],
|
||
span: 24,
|
||
},
|
||
{
|
||
label: t('channel.area.form.city'),
|
||
field: 'city',
|
||
comp: 'a-input',
|
||
compProps: {
|
||
placeholder: t('channel.area.form.placeholder.input'),
|
||
clearable: true,
|
||
},
|
||
rules: [
|
||
{
|
||
max: 128,
|
||
message: t('channel.area.form.rules.maxLength128'),
|
||
trigger: 'change',
|
||
},
|
||
],
|
||
span: 24,
|
||
},
|
||
{
|
||
label: t('channel.area.form.leftPostCode'),
|
||
field: 'leftPostCode',
|
||
comp: 'a-input',
|
||
compProps: {
|
||
placeholder: t('channel.area.form.placeholder.input'),
|
||
clearable: true,
|
||
},
|
||
dynamicRules: ({ model }) => {
|
||
return [
|
||
{
|
||
required: model.rightPostCode,
|
||
pattern: /^((?![\u4E00-\u9FA5]).)*$/,
|
||
message: t('channel.area.form.rules.noChinese'),
|
||
trigger: 'change',
|
||
},
|
||
{
|
||
validator: (rule: any, value: any, callback: any) => {
|
||
if (value) {
|
||
if (!value.trim())
|
||
callback(new Error(t('channel.area.form.rules.noSpacesOnly')));
|
||
else callback();
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
trigger: 'change',
|
||
},
|
||
{
|
||
max: 30,
|
||
message: t('channel.area.form.rules.maxLength30'),
|
||
trigger: 'change',
|
||
},
|
||
];
|
||
},
|
||
span: 24,
|
||
},
|
||
{
|
||
label: t('channel.area.form.rightPostCode'),
|
||
field: 'rightPostCode',
|
||
comp: 'a-input',
|
||
compProps: {
|
||
placeholder: t('channel.area.form.placeholder.input'),
|
||
clearable: true,
|
||
},
|
||
dynamicRules: ({ model }) => {
|
||
return [
|
||
{
|
||
required: model.leftPostCode,
|
||
pattern: /^((?![\u4E00-\u9FA5]).)*$/,
|
||
message: t('channel.area.form.rules.noChinese'),
|
||
trigger: 'change',
|
||
},
|
||
{
|
||
validator: (rule: any, value: any, callback: any) => {
|
||
if (value) {
|
||
if (!value.trim())
|
||
callback(new Error(t('channel.area.form.rules.noSpacesOnlyEnd')));
|
||
else callback();
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
trigger: 'change',
|
||
},
|
||
{
|
||
max: 30,
|
||
message: t('channel.area.form.rules.maxLength30'),
|
||
trigger: 'change',
|
||
},
|
||
];
|
||
},
|
||
span: 24,
|
||
},
|
||
],
|
||
});
|
||
|
||
/** 右侧弹窗表单 */
|
||
const rightModalschemas = [];
|
||
|
||
/** 保存接口额外参数 */
|
||
const editFormParams = reactive<any>({
|
||
options: 1,
|
||
id: undefined,
|
||
appKey: userStore.appKey,
|
||
});
|
||
const editLeftRowParams = ref<any>({});
|
||
const editRightRowParams = ref<any>({});
|
||
/** 保存接口右侧弹窗额外参数 */
|
||
const editFormRightParams = reactive<any>({
|
||
options: 1,
|
||
id: undefined,
|
||
});
|
||
const currentId = ref<any | undefined>();
|
||
const templateScrollRef = ref();
|
||
const modalFormLeftRef = ref();
|
||
const modalFormRightRef = ref();
|
||
const refHeight = ref();
|
||
|
||
const { contentHeight } = useContentHeight(refHeight, true, 12);
|
||
|
||
/** 搜索条件 */
|
||
const searchModel = reactive<any>({
|
||
keyword: '',
|
||
appKey: userStore.appKey,
|
||
});
|
||
|
||
// 自定义表格相关
|
||
const tableData = ref<any[]>([]);
|
||
const totalCount = ref(0);
|
||
const currentPage = ref(1);
|
||
const pageSize = ref(30);
|
||
const jumpPage = ref('');
|
||
|
||
// 搜索参数
|
||
const searchParams = reactive({
|
||
leftPostcode: '',
|
||
rightPostcode: '',
|
||
leftPostCode: '',
|
||
rightPostCode: '',
|
||
remark: '',
|
||
});
|
||
|
||
// 表格列配置
|
||
const tableColumns = computed(() => [
|
||
{ title: t('channel.area.table.serialNo'), dataIndex: 'index', width: 80, align: 'center', slotName: 'index' },
|
||
{ title: t('channel.area.table.leftPostcode'), dataIndex: 'leftPostcode', width: 150 },
|
||
{ title: t('channel.area.table.rightPostcode'), dataIndex: 'rightPostcode', width: 150 },
|
||
{ title: t('channel.area.table.leftPostCode'), dataIndex: 'leftPostCode', width: 150 },
|
||
{ title: t('channel.area.table.rightPostCode'), dataIndex: 'rightPostCode', width: 150 },
|
||
{ title: t('channel.area.table.remark'), dataIndex: 'remark', width: 150 },
|
||
{ title: t('channel.area.table.actions'), dataIndex: 'action', width: 150, align: 'center', slotName: 'action' },
|
||
]);
|
||
|
||
// 左侧菜单数据
|
||
const leftMenuData = ref<any[]>([]);
|
||
const leftExpandedKeys = ref<string[]>(['category-list']);
|
||
|
||
const leftTreeData = computed<CustomLeftMenuTreeNode[]>(() => [
|
||
{
|
||
key: 'category-list',
|
||
title: t('channel.area.listTitle'),
|
||
children: leftMenuData.value.map((item) => ({
|
||
key: `item-${item.id}`,
|
||
title: item.name,
|
||
isLeaf: true,
|
||
id: item.id,
|
||
name: item.name,
|
||
...item,
|
||
})),
|
||
},
|
||
]);
|
||
|
||
const leftSelectedKeys = computed(() =>
|
||
currentId.value?.id ? [`item-${currentId.value.id}`] : []
|
||
);
|
||
|
||
function handleSelectFromTree(keys: string[], info: any) {
|
||
const key = info.node?.key;
|
||
if (!key || !key.startsWith('item-')) return;
|
||
const id = Number(key.replace('item-', ''));
|
||
const item = leftMenuData.value.find((i) => i.id === id);
|
||
if (item) cellClick(item);
|
||
}
|
||
|
||
function handleDeleteLeftNode(nodeData: any) {
|
||
if (nodeData?.id != null) handleDelData(nodeData.id);
|
||
}
|
||
|
||
const tableRef = ref<any>(null);
|
||
const tableProps = reactive<any>({
|
||
useForm: false,
|
||
isColumnsDrag: false,
|
||
mouseConfig: { area: false },
|
||
showPager: false,
|
||
|
||
columns: [
|
||
{
|
||
field: 'index',
|
||
title: t('channel.area.table.serialNo'),
|
||
width: 80,
|
||
align: 'center',
|
||
formatter: ({ rowIndex }: any) => {
|
||
return (currentPage.value - 1) * pageSize.value + rowIndex + 1;
|
||
},
|
||
},
|
||
{
|
||
field: 'countryName',
|
||
title: t('channel.area.form.country'),
|
||
},
|
||
{
|
||
field: 'province',
|
||
title: t('channel.area.form.province'),
|
||
},
|
||
{
|
||
field: 'city',
|
||
title: t('channel.area.form.city'),
|
||
},
|
||
{
|
||
field: 'leftPostcode',
|
||
title: t('channel.area.table.leftPostcode'),
|
||
},
|
||
{
|
||
field: 'rightPostcode',
|
||
title: t('channel.area.table.rightPostcode'),
|
||
},
|
||
{
|
||
field: 'action',
|
||
title: t('channel.area.table.actions'),
|
||
width: 110,
|
||
align: 'center',
|
||
slots: {
|
||
default: 'action',
|
||
},
|
||
},
|
||
],
|
||
});
|
||
|
||
/** 单击行获取行数据 par: any */
|
||
function cellClick(par: any) {
|
||
currentId.value = par;
|
||
currentPage.value = 1;
|
||
loadTableData();
|
||
}
|
||
|
||
/** 点击新增 编辑打开左侧弹窗 */
|
||
function handleOpenModal(type: IDialogConfig['type'], row?: any) {
|
||
const titleObj: { [x in IDialogConfig['type']]: string } = {
|
||
add: t('channel.area.modal.addArea'),
|
||
edit: t('channel.area.modal.editArea'),
|
||
};
|
||
editFormParams.options = 1;
|
||
editFormParams.id = undefined;
|
||
// setModalProps({
|
||
// title: titleObj[type],
|
||
// })
|
||
editFormParams.options = 1;
|
||
if (type === 'edit') {
|
||
modalFormLeftRef.value?.openModalFn({
|
||
id: row?.id,
|
||
title: titleObj[type],
|
||
});
|
||
editFormParams.options = 3;
|
||
editFormParams.id = row?.id;
|
||
editLeftRowParams.value = cloneDeep({
|
||
...row,
|
||
appKey: userStore.appKey,
|
||
});
|
||
return;
|
||
}
|
||
modalFormLeftRef.value?.openModalFn({
|
||
id: editFormParams.id,
|
||
title: titleObj[type],
|
||
});
|
||
}
|
||
|
||
async function returnEditRowParams() {
|
||
return {
|
||
code: '200',
|
||
data: editLeftRowParams.value,
|
||
msg: '成功',
|
||
};
|
||
}
|
||
|
||
/** 点击新增 编辑打开右侧弹窗 */
|
||
function handleOpenRightModal(type: IDialogConfig['type'], row?: any) {
|
||
const titleObj: { [x in IDialogConfig['type']]: string } = {
|
||
add: t('channel.area.modal.addDetail'),
|
||
edit: t('channel.area.modal.editDetail'),
|
||
};
|
||
editFormRightParams.options = 1;
|
||
editFormRightParams.areaId = currentId.value?.id;
|
||
// setModalPropsRight({
|
||
// title: titleObj[type],
|
||
// });
|
||
editFormRightParams.options = 1;
|
||
if (type === 'edit') {
|
||
unref(modalFormRightRef)?.openModalFn({
|
||
id: row?.id,
|
||
title: titleObj[type],
|
||
});
|
||
editFormRightParams.options = 3;
|
||
editRightRowParams.value = cloneDeep({
|
||
...row,
|
||
leftPostCode: row.leftPostcode,
|
||
rightPostCode: row.rightPostcode,
|
||
});
|
||
return;
|
||
}
|
||
unref(modalFormRightRef)?.openModalFn({
|
||
areaId: editFormRightParams.id,
|
||
title: titleObj[type],
|
||
|
||
formData: {
|
||
areaId: currentId.value?.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
async function returnRightEditRowParams() {
|
||
return {
|
||
code: '200',
|
||
data: editRightRowParams.value,
|
||
msg: '成功',
|
||
};
|
||
}
|
||
|
||
/** 删除数据 */
|
||
function handleDelData(id: number) {
|
||
$baseConfirm({
|
||
content: t('channel.area.modal.deleteConfirm'),
|
||
title: t('channel.area.modal.warningTitle'),
|
||
onOk: async () => {
|
||
await deleteForewarningServiceKpiAreaDeleteKpiArea({ id });
|
||
onFormSubmitClick();
|
||
$baseMessage(t('channel.area.message.deleteSuccess'), 'success');
|
||
if (id === currentId.value.id) currentId.value = undefined;
|
||
},
|
||
});
|
||
}
|
||
/** 删除右侧数据 */
|
||
function handleDelRightData(id: number) {
|
||
$baseConfirm({
|
||
content: t('channel.area.modal.deleteConfirmDetail'),
|
||
title: t('channel.area.modal.warningTitle'),
|
||
onOk: async () => {
|
||
await deleteForewarningServiceKpiAreaDeleteKpiAreaInfo({ id });
|
||
loadTableData();
|
||
$baseMessage(t('channel.area.message.deleteSuccess'), 'success');
|
||
},
|
||
});
|
||
}
|
||
|
||
// 加载表格数据
|
||
async function loadTableData() {
|
||
if (!currentId.value?.id) {
|
||
tableRef.value?.reloadData?.([]);
|
||
totalCount.value = 0;
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const params = {
|
||
...searchParams,
|
||
areaId: currentId.value.id,
|
||
pageIndex: currentPage.value,
|
||
pageSize: pageSize.value,
|
||
};
|
||
|
||
const response = await postForewarningServiceKpiAreaGetKpiAreaInfos(params);
|
||
const items = response.items || response || [];
|
||
totalCount.value = response.totalCount || response.length || 0;
|
||
tableRef.value?.reloadData?.(items);
|
||
} catch (error) {
|
||
$baseMessage(t('channel.area.message.loadFailed'), 'error');
|
||
}
|
||
}
|
||
|
||
// 表头搜索
|
||
function handleHeaderSearch() {
|
||
currentPage.value = 1;
|
||
loadTableData();
|
||
}
|
||
|
||
function handleHeaderBlur() {
|
||
handleHeaderSearch();
|
||
}
|
||
|
||
// 分页改变
|
||
function handlePageChange(page: number) {
|
||
currentPage.value = page;
|
||
loadTableData();
|
||
}
|
||
|
||
// 每页数量改变
|
||
function handlePageSizeChange(size: number) {
|
||
pageSize.value = size;
|
||
currentPage.value = 1;
|
||
loadTableData();
|
||
}
|
||
|
||
// 跳转页码
|
||
function handleJumpPage() {
|
||
const val = Number(jumpPage.value);
|
||
if (!val || val < 1) return;
|
||
const max = Math.max(1, Math.ceil(totalCount.value / pageSize.value));
|
||
handlePageChange(Math.min(val, max));
|
||
}
|
||
|
||
// 加载左侧菜单数据
|
||
async function loadLeftMenuData() {
|
||
try {
|
||
const params = {
|
||
pageIndex: 1,
|
||
pageSize: 30,
|
||
...searchModel,
|
||
appKey: userStore.appKey,
|
||
};
|
||
|
||
const response = await postForewarningServiceKpiAreaGetKpiAreas(params);
|
||
leftMenuData.value = response.items || response || [];
|
||
} catch (error) {
|
||
$baseMessage(t('channel.area.message.loadFailed'), 'error');
|
||
}
|
||
}
|
||
|
||
/** 查询 */
|
||
function onFormSubmitClick(data?: any) {
|
||
Object.assign(searchModel, data || {});
|
||
|
||
loadLeftMenuData();
|
||
currentId.value = undefined;
|
||
tableData.value = [];
|
||
totalCount.value = 0;
|
||
}
|
||
|
||
/** 左侧弹窗保存 */
|
||
function onSubmitLeft() {
|
||
onFormSubmitClick();
|
||
}
|
||
/** 右侧弹窗保存 */
|
||
function onSubmitRight() {
|
||
loadTableData();
|
||
}
|
||
|
||
watch(
|
||
() => currentId.value,
|
||
(val) => {
|
||
if (val) {
|
||
currentPage.value = 1;
|
||
loadTableData();
|
||
} else {
|
||
tableData.value = [];
|
||
totalCount.value = 0;
|
||
}
|
||
}
|
||
);
|
||
|
||
onMounted(() => {
|
||
onFormSubmitClick();
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.blacklist-layout {
|
||
display: flex;
|
||
width: 100%;
|
||
height: 100%;
|
||
padding: 16px;
|
||
gap: 16px;
|
||
background-color: var(--color-fill-2);
|
||
overflow: hidden;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.layout-content {
|
||
flex: 1;
|
||
display: flex;
|
||
overflow: hidden;
|
||
min-width: 0;
|
||
width: 100%;
|
||
|
||
:deep(.trb-transform) {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
}
|
||
|
||
:deep(.trb-transform > div) {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
:deep(.flex-1) {
|
||
min-width: 0;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
/* 左侧使用 CustomLeftMenu,仅保留布局(与销售产品一致) */
|
||
.left-sidebar {
|
||
width: 280px;
|
||
flex-shrink: 0;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.sidebar-header {
|
||
padding: 10px 12px !important;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||
min-height: 48px !important;
|
||
display: flex !important;
|
||
align-items: center !important;
|
||
color: #fff;
|
||
}
|
||
|
||
.search-box {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
width: 100%;
|
||
}
|
||
|
||
.search-actions {
|
||
display: flex;
|
||
gap: 4px;
|
||
}
|
||
|
||
.action-icon-btn {
|
||
width: 28px;
|
||
height: 28px;
|
||
padding: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #fff;
|
||
border: 1px solid transparent;
|
||
border-radius: 4px;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
|
||
&:hover {
|
||
background-color: rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
&.add-btn {
|
||
color: var(--app-primary-color) !important;
|
||
background-color: var(--app-primary-color-light) !important;
|
||
border: 1px solid var(--app-primary-color) !important;
|
||
border-radius: 50% !important;
|
||
width: 28px !important;
|
||
height: 28px !important;
|
||
min-width: 28px !important;
|
||
max-width: 28px !important;
|
||
min-height: 28px !important;
|
||
max-height: 28px !important;
|
||
padding: 0 !important;
|
||
line-height: 28px !important;
|
||
|
||
&:hover {
|
||
color: #ffffff !important;
|
||
background-color: var(--app-primary-color) !important;
|
||
border-color: var(--app-primary-color) !important;
|
||
}
|
||
}
|
||
|
||
&.refresh-btn {
|
||
color: #fff;
|
||
&:hover {
|
||
color: var(--app-primary-color);
|
||
}
|
||
}
|
||
}
|
||
|
||
.menu-list {
|
||
flex: 1;
|
||
padding: 8px 0 0;
|
||
overflow-y: auto;
|
||
color: #fff;
|
||
background: transparent;
|
||
border-radius: 16px;
|
||
padding-right: 4px;
|
||
}
|
||
|
||
.menu-list::-webkit-scrollbar {
|
||
width: 6px;
|
||
}
|
||
|
||
.menu-list::-webkit-scrollbar-track {
|
||
background: rgba(0, 0, 0, 0.08);
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.menu-list::-webkit-scrollbar-thumb {
|
||
background: rgba(86, 144, 236, 0.65);
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.menu-list::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(59, 97, 148, 0.85);
|
||
}
|
||
|
||
.right-content-panel {
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: #fff;
|
||
border-radius: 24px;
|
||
overflow: hidden;
|
||
padding: 16px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.table-toolbar {
|
||
margin-bottom: 8px;
|
||
padding: 0 16px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
|
||
.toolbar-left {
|
||
flex: 1;
|
||
|
||
.custom-buttons {
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
|
||
.arco-btn {
|
||
border-radius: 20px;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
border: 2px solid;
|
||
position: relative;
|
||
overflow: hidden;
|
||
padding: 8px 16px;
|
||
height: auto;
|
||
|
||
// 所有按钮 - 深青色
|
||
&.btn-add {
|
||
background: var(--app-primary-color);
|
||
border-color: var(--app-primary-color);
|
||
color: #ffffff;
|
||
|
||
&:hover:not(:disabled) {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active:not(:disabled) {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
}
|
||
|
||
// 禁用状态
|
||
&:disabled {
|
||
opacity: 1;
|
||
cursor: not-allowed;
|
||
background: rgba(169, 169, 169, 0.8) !important;
|
||
border-color: rgba(169, 169, 169, 0.8) !important;
|
||
color: #ffffff !important;
|
||
transform: none !important;
|
||
box-shadow: none !important;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.toolbar-right {
|
||
.pagination-controls {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
white-space: nowrap;
|
||
flex-wrap: nowrap;
|
||
|
||
.total-records,
|
||
.go-to-text,
|
||
.page-size-text,
|
||
.page-text {
|
||
font-size: 12px;
|
||
color: #4e5969;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.current-page {
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #1d2129;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.arco-btn-size-small {
|
||
padding: 0 8px;
|
||
height: 24px;
|
||
min-width: 24px;
|
||
border-radius: 4px;
|
||
color: #4e5969;
|
||
border: 1px solid #e5e6eb;
|
||
background-color: #fff;
|
||
|
||
&:hover {
|
||
background-color: #f2f3f5;
|
||
}
|
||
|
||
&:disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.6;
|
||
}
|
||
}
|
||
|
||
.arco-select-size-small {
|
||
.arco-select-view {
|
||
height: 24px;
|
||
line-height: 24px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
|
||
.arco-input-number-size-small {
|
||
.arco-input-wrapper {
|
||
height: 24px;
|
||
line-height: 24px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
|
||
.action-btn {
|
||
padding: 4px;
|
||
border-radius: 4px;
|
||
transition: all 0.2s ease;
|
||
|
||
&.edit-btn {
|
||
color: #8c8c8c !important;
|
||
|
||
&:hover {
|
||
background-color: #f5f5f5 !important;
|
||
color: #4e5969 !important;
|
||
}
|
||
}
|
||
|
||
&.delete-btn {
|
||
color: #ff4d4f;
|
||
|
||
&:hover {
|
||
background-color: #fff2f0;
|
||
color: #ff7875;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 确保 TablePro 正确填充空间
|
||
.right-content-panel {
|
||
:deep(.table-pro) {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
:deep(.table-pro .arco-table-container) {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
:deep(.table-pro .arco-table-body) {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
}
|
||
}
|
||
|
||
.empty-state {
|
||
padding: 40px 0;
|
||
text-align: center;
|
||
}
|
||
|
||
// 左侧菜单样式
|
||
.menu-item {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
padding: 10px 12px;
|
||
margin: 8px 0;
|
||
border-radius: 18px;
|
||
transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
|
||
cursor: pointer;
|
||
background: rgba(255, 255, 255, 0.02);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
&:hover {
|
||
background-color: rgba(13, 29, 61, 0.8);
|
||
border-color: rgba(255, 255, 255, 0.2);
|
||
transform: translateX(4px);
|
||
}
|
||
|
||
&.menu-item-selected {
|
||
background: #FFF394;
|
||
box-shadow: 0 10px 20px rgba(255, 243, 148, 0.4);
|
||
border-color: #FFF394 !important;
|
||
color: #000 !important;
|
||
|
||
.menu-text,
|
||
.menu-index {
|
||
color: #000 !important;
|
||
}
|
||
}
|
||
border: 1px solid transparent;
|
||
|
||
&:hover {
|
||
background: #f7f8fa;
|
||
border-color: #e5e6eb;
|
||
}
|
||
|
||
&.menu-item-selected {
|
||
background: linear-gradient(135deg, #e6f7f7 0%, #f0f9f9 100%);
|
||
border-color: var(--app-primary-color);
|
||
box-shadow: 0 2px 8px rgba(45, 140, 140, 0.15);
|
||
|
||
.menu-text {
|
||
color: var(--app-primary-color);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.menu-index {
|
||
background: var(--app-primary-color);
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
}
|
||
|
||
.menu-item-content {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
flex: 1;
|
||
}
|
||
|
||
.menu-index {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
color: rgba(255, 255, 255, 0.8);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.menu-text {
|
||
color: #fff;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.menu-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
|
||
.edit-btn, .delete-btn {
|
||
padding: 2px 6px;
|
||
height: 24px;
|
||
font-size: 12px;
|
||
border-radius: 4px;
|
||
color: rgba(255, 255, 255, 0.65);
|
||
|
||
&.edit-btn {
|
||
&:hover {
|
||
color: var(--app-primary-color);
|
||
background: rgba(73, 186, 179, 0.1);
|
||
}
|
||
}
|
||
|
||
&.delete-btn {
|
||
&:hover {
|
||
color: #f53f3f;
|
||
background: rgba(245, 63, 63, 0.1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.menu-item:hover .menu-actions {
|
||
opacity: 1;
|
||
}
|
||
|
||
.empty-menu {
|
||
padding: 40px 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
// 新增按钮样式
|
||
.add-btn {
|
||
width: 32px;
|
||
height: 32px;
|
||
padding: 0;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: var(--app-primary-color);
|
||
border-color: var(--app-primary-color);
|
||
|
||
&:hover {
|
||
background: #2A7F7F;
|
||
border-color: #2A7F7F;
|
||
}
|
||
|
||
&:active {
|
||
background: #257272;
|
||
border-color: #257272;
|
||
}
|
||
|
||
.arco-icon {
|
||
font-size: 16px;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
</style>
|