front/src/views/channel/weightRounding/index.vue
2026-02-24 18:33:14 +08:00

1215 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="weight-rounding-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.weightRounding.search.placeholder')"
:refresh-title="t('channel.weightRounding.search.refresh')"
:add-title="t('channel.weightRounding.search.addRounding')"
show-node-index
:show-method="false"
:show-map-count="false"
:show-node-code="false"
show-node-actions
:delete-label="t('channel.weightRounding.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.weightRounding.actions.delete') }}
</a-doption>
</template>
<template #node-second-row-extra="{ nodeData }">
<table class="product-second-row-table">
<tr>
<td class="product-row-left">
<span class="update-time">{{ t('channel.weightRounding.updateTime', { time: nodeData?.updateTime ?? '' }) }}</span>
</td>
<td class="product-row-right"></td>
</tr>
</table>
</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.weightRounding.pagination.total', { count: totalCount }) }}
</span>
<a-button
size="small"
:disabled="currentPage <= 1"
@click="handlePageChange(currentPage - 1)"
>
&lt;
</a-button>
<span class="current-page">{{ currentPage }}</span>
<a-button
size="small"
:disabled="currentPage >= Math.ceil(totalCount / pageSize)"
@click="handlePageChange(currentPage + 1)"
>
&gt;
</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.weightRounding.pagination.perPage') }}</span>
<span class="go-to-text">{{ $t('channel.weightRounding.pagination.goTo') }}</span>
<a-input
v-model="jumpPage"
size="small"
class="jump-input"
@keyup.enter="handleJumpPage"
/>
<span class="page-text">{{ $t('channel.weightRounding.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 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';
const userStore = useUserStore();
const { t } = useI18n();
defineOptions({
name: 'WeightRounding',
});
type IDialogConfig = {
show: boolean;
type: 'add' | 'edit';
title: string;
};
const formProRef = ref();
/** 左侧弹窗表单 */
const formTopProps = computed(() => {
return (isTop = false) => {
const titleList = [
{
label: t('channel.weightRounding.form.keyword'),
field: 'name',
comp: 'AInput',
compProps: {
onKeyup: (e: KeyboardEvent) => {
if (e.key === 'Enter') onFormSubmitClick();
},
maxlength: 50,
placeholder: t('channel.weightRounding.form.placeholder.keyword'),
},
span: 6,
},
];
const obj = !isTop
? { formLayout: 'vertical', defaultSpan: 24 }
: {
layout: 'inline',
buttonConfig: {
showBtn: true,
okText: t('channel.weightRounding.search.button.query'),
showReset: true,
showOk: true,
resetText: t('channel.weightRounding.search.button.reset'),
},
};
return {
...obj,
itemList: isTop
? titleList
: [
{
label: t('channel.weightRounding.form.roundingName'),
field: 'name',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.roundingName'),
clearable: true,
},
span: isTop ? 6 : 24,
rules: [
{
required: true,
message: t('channel.weightRounding.form.rules.roundingNameRequired'),
},
],
},
],
};
};
});
const formPros = reactive({
formLayout: 'vertical',
defaultSpan: 24,
itemList: [
{
label: t('channel.weightRounding.form.startValue'),
field: 'startValue',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.startValue'),
clearable: true,
},
rules: [
{
required: true,
message: t('channel.weightRounding.form.rules.startValueRequired'),
},
],
span: 24,
},
{
label: t('channel.weightRounding.form.endValue'),
field: 'endValue',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.endValue'),
clearable: true,
},
rules: [
{
required: true,
message: t('channel.weightRounding.form.rules.endValueRequired'),
},
],
span: 24,
},
{
label: t('channel.weightRounding.form.public'),
field: 'public',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.public'),
clearable: true,
},
span: 24,
},
{
label: t('channel.weightRounding.form.customerGroup1'),
field: 'customerGroup1',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.customerGroup1'),
clearable: true,
},
span: 24,
},
{
label: t('channel.weightRounding.form.customerGroup2'),
field: 'customerGroup2',
comp: 'a-input',
compProps: {
placeholder: t('channel.weightRounding.form.placeholder.customerGroup2'),
clearable: true,
},
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({
startValue: '',
endValue: '',
public: '',
customerGroup1: '',
customerGroup2: '',
});
// 左侧菜单数据
const leftMenuData = ref<any[]>([
{
id: 1,
name: '0.5进位制',
tags: ['dhl', 'usps'],
updateTime: '2023.6.6 12:45'
},
{
id: 2,
name: '0.1进位制',
tags: ['ups'],
updateTime: '2023.6.6 12:45'
}
]);
const leftExpandedKeys = ref<string[]>(['category-list']);
const leftTreeData = computed<CustomLeftMenuTreeNode[]>(() => [
{
key: 'category-list',
title: t('channel.weightRounding.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 roundingData = ref<any[]>([
{
id: 1,
startValue: '0.00',
endValue: '1.00',
public: '0.5',
customerGroup1: '0',
customerGroup2: '0'
},
{
id: 2,
startValue: '1.00',
endValue: '2.00',
public: '',
customerGroup1: '',
customerGroup2: ''
},
{
id: 3,
startValue: '2.00',
endValue: '3.00',
public: '',
customerGroup1: '',
customerGroup2: ''
}
]);
// 表格列配置
const tableColumns = computed(() => [
{ title: t('channel.weightRounding.table.serialNo'), dataIndex: 'index', width: 80, align: 'center', slotName: 'index' },
{ title: t('channel.weightRounding.table.startValue'), dataIndex: 'startValue', width: 120 },
{ title: t('channel.weightRounding.table.endValue'), dataIndex: 'endValue', width: 120 },
{ title: t('channel.weightRounding.table.public'), dataIndex: 'public', width: 120 },
{ title: t('channel.weightRounding.table.customerGroup1'), dataIndex: 'customerGroup1', width: 120 },
{ title: t('channel.weightRounding.table.customerGroup2'), dataIndex: 'customerGroup2', width: 120 },
{ title: t('channel.weightRounding.table.actions'), dataIndex: 'action', width: 100, align: 'center', slotName: 'action' },
]);
const tableRef = ref<any>(null);
const tableProps = reactive<any>({
useForm: false,
isColumnsDrag: false,
mouseConfig: { area: false },
showPager: false,
columns: [
{
field: 'index',
title: t('channel.weightRounding.table.serialNo'),
width: 80,
align: 'center',
formatter: ({ rowIndex }: any) => {
return (currentPage.value - 1) * pageSize.value + rowIndex + 1;
},
},
{
field: 'startValue',
title: t('channel.weightRounding.table.startValue'),
},
{
field: 'endValue',
title: t('channel.weightRounding.table.endValue'),
},
{
field: 'public',
title: t('channel.weightRounding.table.public'),
},
{
field: 'customerGroup1',
title: t('channel.weightRounding.table.customerGroup1'),
},
{
field: 'customerGroup2',
title: t('channel.weightRounding.table.customerGroup2'),
},
{
field: 'action',
title: t('channel.weightRounding.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.weightRounding.modal.addRounding'),
edit: t('channel.weightRounding.modal.editRounding'),
};
editFormParams.options = 1;
editFormParams.id = undefined;
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.weightRounding.modal.addRule'),
edit: t('channel.weightRounding.modal.editRule'),
};
editFormRightParams.options = 1;
editFormRightParams.areaId = currentId.value?.id;
editFormRightParams.options = 1;
if (type === 'edit') {
unref(modalFormRightRef)?.openModalFn({
id: row?.id,
title: titleObj[type],
});
editFormRightParams.options = 3;
editRightRowParams.value = cloneDeep({
...row,
});
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.weightRounding.modal.deleteConfirm'),
title: t('channel.weightRounding.modal.warningTitle'),
onOk: async () => {
// await deleteForewarningServiceKpiAreaDeleteKpiArea({ id });
onFormSubmitClick();
$baseMessage(t('channel.weightRounding.message.deleteSuccess'), 'success');
if (id === currentId.value?.id) currentId.value = undefined;
},
});
}
/** 删除右侧数据 */
function handleDelRightData(id: number) {
$baseConfirm({
content: t('channel.weightRounding.modal.deleteConfirmDetail'),
title: t('channel.weightRounding.modal.warningTitle'),
onOk: async () => {
// await deleteForewarningServiceKpiAreaDeleteKpiAreaInfo({ id });
roundingData.value = roundingData.value.filter(item => item.id !== id);
loadTableData();
$baseMessage(t('channel.weightRounding.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 = roundingData.value;
totalCount.value = roundingData.value.length;
tableRef.value?.reloadData?.(items);
} catch (error) {
$baseMessage(t('channel.weightRounding.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.weightRounding.message.loadFailed'), 'error');
}
}
/** 查询 */
function onFormSubmitClick(data?: any) {
Object.assign(searchModel, data || {});
loadLeftMenuData();
currentId.value = undefined;
tableRef.value?.reloadData?.([]);
totalCount.value = 0;
}
/** 左侧弹窗保存 */
function onSubmitLeft() {
onFormSubmitClick();
}
/** 右侧弹窗保存 */
function onSubmitRight() {
loadTableData();
}
watch(
() => currentId.value,
(val) => {
if (val) {
currentPage.value = 1;
loadTableData();
} else {
tableRef.value?.reloadData?.([]);
totalCount.value = 0;
}
}
);
onMounted(() => {
onFormSubmitClick();
});
</script>
<style scoped lang="less">
.weight-rounding-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;
}
/* 第二行表格:更新时间布局与样式对齐销售产品的创建时间 */
.left-sidebar .product-second-row-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.left-sidebar .product-row-left {
text-align: left;
padding: 0;
padding-left: 24px;
vertical-align: middle;
width: auto;
font-size: 12px;
color: rgba(255, 255, 255, 0.65);
.update-time {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.left-sidebar .product-row-right {
text-align: right;
padding: 0;
width: 30px;
vertical-align: middle;
}
.left-sidebar :deep(.node-second-row-extra-slot) {
display: block;
width: 100%;
}
.left-sidebar :deep(.node-second-row-extra-cell) {
text-align: left;
}
.left-sidebar :deep(.tree-node.selected .update-time) {
color: #666 !important;
}
.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;
&.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;
}
}
// 左侧菜单样式
.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;
flex-direction: column;
&: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-tags,
.menu-update {
color: #000 !important;
}
}
}
.menu-item-content {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 8px;
}
.menu-text {
color: #fff;
font-size: 14px;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
.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;
}
.menu-tags {
display: flex;
gap: 4px;
margin-bottom: 4px;
flex-wrap: wrap;
}
.tag {
padding: 2px 8px;
background: rgba(255, 255, 255, 0.15);
color: rgba(255, 255, 255, 0.8);
border-radius: 12px;
font-size: 12px;
border: none;
}
.menu-update {
font-size: 12px;
color: rgba(255, 255, 255, 0.65);
}
.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>