front/src/views/channel/weightRounding/index.vue
2026-01-31 15:32:12 +08:00

1214 lines
30 KiB
Vue

<template>
<div class="weight-rounding-layout">
<div ref="refHeight" class="layout-content">
<BasicLayoutLeftRight :left-width="280">
<template #left>
<div class="left-sidebar">
<div class="sidebar-header">
<div class="search-box">
<a-input
v-model="searchModel.keyword"
:placeholder="t('channel.weightRounding.search.placeholder')"
allow-clear
size="small"
@change="onFormSubmitClick"
@clear="onFormSubmitClick"
@keyup.enter="onFormSubmitClick"
>
<template #prefix>
<icon-search />
</template>
</a-input>
<div class="search-actions">
<a-button
type="text"
size="small"
class="action-icon-btn refresh-btn"
@click="onFormSubmitClick"
:title="t('channel.weightRounding.search.refresh')"
>
↻
</a-button>
<a-button
type="text"
size="small"
class="action-icon-btn add-btn"
@click="handleOpenModal('add')"
:title="t('channel.weightRounding.search.addRounding')"
>
+
</a-button>
</div>
</div>
</div>
<div class="menu-list">
<div
v-for="(item, index) in leftMenuData"
:key="item.id"
class="menu-item"
:class="{ 'menu-item-selected': currentId?.id === item.id }"
@click="cellClick(item)"
>
<div class="menu-item-content">
<span class="menu-text">{{ item.name }}</span>
<div class="menu-actions">
<a-button
type="text"
size="small"
class="edit-btn"
@click.stop="handleOpenModal('edit', item)"
>
<template #icon>
<IconEdit />
</template>
</a-button>
<a-button
type="text"
size="small"
class="delete-btn"
@click.stop="handleDelData(item.id)"
>
<template #icon>
<IconDelete />
</template>
</a-button>
</div>
</div>
<div class="menu-tags">
<span
v-for="tag in item.tags"
:key="tag"
class="tag"
>
{{ tag }}
</span>
</div>
<div class="menu-update">
{{ t('channel.weightRounding.updateTime', { time: item.updateTime }) }}
</div>
</div>
<!-- 空状态 -->
<div v-if="!leftMenuData.length" class="empty-menu">
<a-empty :description="t('channel.weightRounding.empty')" />
</div>
</div>
<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';
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 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%;
}
}
.left-sidebar {
width: 280px;
background: var(--app-sidebar-bg);
backdrop-filter: blur(20px) saturate(180%);
-webkit-backdrop-filter: blur(20px) saturate(180%);
border: 1px solid rgba(255, 255, 255, 0.18);
border-top: 1px solid rgba(255, 255, 255, 0.25);
border-radius: 24px;
display: flex;
flex-direction: column;
flex-shrink: 0;
height: 100%;
padding: 12px;
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
0 2px 8px rgba(0, 0, 0, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.1),
inset 0 -1px 0 rgba(0, 0, 0, 0.2);
overflow: hidden;
color: #fff;
position: relative;
}
.left-sidebar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg,
transparent 0%,
rgba(255, 255, 255, 0.3) 50%,
transparent 100%);
pointer-events: none;
z-index: 1;
}
.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>