style: 优化按钮样式

This commit is contained in:
xlsea 2025-05-10 10:45:30 +08:00
parent cc34f546c6
commit 5b0ae4443c
12 changed files with 80 additions and 40 deletions

View File

@ -58,7 +58,7 @@ function handleExport() {
<slot name="default"> <slot name="default">
<NButton v-if="showAdd" :disabled="disableAdd" size="small" ghost type="primary" @click="add"> <NButton v-if="showAdd" :disabled="disableAdd" size="small" ghost type="primary" @click="add">
<template #icon> <template #icon>
<icon-ic-round-plus class="text-icon" /> <icon-material-symbols:add class="text-icon" />
</template> </template>
{{ $t('common.add') }} {{ $t('common.add') }}
</NButton> </NButton>
@ -66,7 +66,7 @@ function handleExport() {
<template #trigger> <template #trigger>
<NButton size="small" ghost type="error" :disabled="disabledDelete"> <NButton size="small" ghost type="error" :disabled="disabledDelete">
<template #icon> <template #icon>
<icon-ic-round-delete class="text-icon" /> <icon-material-symbols:delete-outline class="text-icon" />
</template> </template>
{{ $t('common.batchDelete') }} {{ $t('common.batchDelete') }}
</NButton> </NButton>
@ -75,7 +75,7 @@ function handleExport() {
</NPopconfirm> </NPopconfirm>
<NButton v-if="showExport" size="small" ghost @click="handleExport"> <NButton v-if="showExport" size="small" ghost @click="handleExport">
<template #icon> <template #icon>
<icon-material-symbols:download-2-rounded class="text-icon" /> <icon-material-symbols:download-rounded class="text-icon" />
</template> </template>
导出 导出
</NButton> </NButton>
@ -83,7 +83,7 @@ function handleExport() {
<slot name="after"></slot> <slot name="after"></slot>
<NButton size="small" @click="refresh"> <NButton size="small" @click="refresh">
<template #icon> <template #icon>
<icon-mdi-refresh class="text-icon" :class="{ 'animate-spin': loading }" /> <icon-material-symbols:refresh-rounded class="text-icon" :class="{ 'animate-spin': loading }" />
</template> </template>
{{ $t('common.refresh') }} {{ $t('common.refresh') }}
</NButton> </NButton>

View File

@ -106,6 +106,7 @@ defineExpose({
v-model:expanded-keys="expandedKeys" v-model:expanded-keys="expandedKeys"
multiple multiple
checkable checkable
:selectable="false"
key-field="id" key-field="id"
label-field="label" label-field="label"
:data="options" :data="options"

View File

@ -23,7 +23,7 @@ export function useTreeTable<A extends NaiveUI.TreeTableApiFn>(
idField, idField,
parentIdField = 'parentId', parentIdField = 'parentId',
childrenField = 'children', childrenField = 'children',
defaultExpandAll = true defaultExpandAll = false
} = config; } = config;
const SELECTION_KEY = '__selection__'; const SELECTION_KEY = '__selection__';
@ -56,10 +56,8 @@ export function useTreeTable<A extends NaiveUI.TreeTableApiFn>(
childrenField childrenField
}); });
// 如果设置了默认展开所有则收集所有节点的key // if defaultExpandAll is true, expand all nodes
if (defaultExpandAll) { expandedRowKeys.value = defaultExpandAll ? records.map(item => item[idField]) : [records[0][idField]];
expandedRowKeys.value = records.map(item => item[idField]);
}
return { data: treeData }; return { data: treeData };
}, },
@ -129,14 +127,18 @@ export function useTreeTable<A extends NaiveUI.TreeTableApiFn>(
return keys; return keys;
} }
/** 展开所有节点 */ const { bool: isCollapse, toggle: toggleCollapse } = useBoolean(defaultExpandAll);
/** expand all nodes */
function expandAll() { function expandAll() {
toggleCollapse();
expandedRowKeys.value = collectAllNodeKeys(data.value); expandedRowKeys.value = collectAllNodeKeys(data.value);
} }
/** 收起所有节点 */ /** collapse all nodes */
function collapseAll() { function collapseAll() {
expandedRowKeys.value = []; toggleCollapse();
expandedRowKeys.value = data.value.length ? [data.value[0][idField]] : [];
} }
scope.run(() => { scope.run(() => {
@ -164,6 +166,7 @@ export function useTreeTable<A extends NaiveUI.TreeTableApiFn>(
updateSearchParams, updateSearchParams,
resetSearchParams, resetSearchParams,
expandedRowKeys, expandedRowKeys,
isCollapse,
expandAll, expandAll,
collapseAll collapseAll
}; };

View File

@ -32,15 +32,15 @@ declare namespace CommonType {
/** The res error code */ /** The res error code */
type ErrorCode = '401' | '403' | '404' | 'default'; type ErrorCode = '401' | '403' | '404' | 'default';
/** 构造树型结构数据的配置选项 */ /** The configuration options for constructing tree structure data */
type TreeConfig = { type TreeConfig = {
/** id字段名 */ /** id field name */
idField: string; idField: string;
/** 父节点字段名 */ /** parent id field name */
parentIdField?: string; parentIdField?: string;
/** 子节点字段名 */ /** children field name */
childrenField?: string; childrenField?: string;
/** 过滤函数 */ /** filter function */
filterFn?: (node: any) => boolean; filterFn?: (node: any) => boolean;
}; };
} }

View File

@ -40,15 +40,27 @@ declare module 'vue' {
IconIcRoundSearch: typeof import('~icons/ic/round-search')['default'] IconIcRoundSearch: typeof import('~icons/ic/round-search')['default']
IconIcRoundUpload: typeof import('~icons/ic/round-upload')['default'] IconIcRoundUpload: typeof import('~icons/ic/round-upload')['default']
IconLocalBanner: typeof import('~icons/local/banner')['default'] IconLocalBanner: typeof import('~icons/local/banner')['default']
'IconMaterialSymbols:add': typeof import('~icons/material-symbols/add')['default']
'IconMaterialSymbols:collapseAllRounded': typeof import('~icons/material-symbols/collapse-all-rounded')['default']
'IconMaterialSymbols:deleteOutline': typeof import('~icons/material-symbols/delete-outline')['default']
'IconMaterialSymbols:download2Rounded': typeof import('~icons/material-symbols/download2-rounded')['default'] 'IconMaterialSymbols:download2Rounded': typeof import('~icons/material-symbols/download2-rounded')['default']
'IconMaterialSymbols:downloadRounded': typeof import('~icons/material-symbols/download-rounded')['default']
'IconMaterialSymbols:expandAllRounded': typeof import('~icons/material-symbols/expand-all-rounded')['default']
'IconMaterialSymbols:imageOutline': typeof import('~icons/material-symbols/image-outline')['default']
'IconMaterialSymbols:refreshRounded': typeof import('~icons/material-symbols/refresh-rounded')['default']
'IconMaterialSymbols:settingsOutlineRounded': typeof import('~icons/material-symbols/settings-outline-rounded')['default']
'IconMaterialSymbols:syncOutline': typeof import('~icons/material-symbols/sync-outline')['default'] 'IconMaterialSymbols:syncOutline': typeof import('~icons/material-symbols/sync-outline')['default']
'IconMaterialSymbols:upload2Rounded': typeof import('~icons/material-symbols/upload2-rounded')['default'] 'IconMaterialSymbols:upload2Rounded': typeof import('~icons/material-symbols/upload2-rounded')['default']
'IconMaterialSymbols:uploadRounded': typeof import('~icons/material-symbols/upload-rounded')['default']
'IconMaterialSymbols:warningOutlineRounded': typeof import('~icons/material-symbols/warning-outline-rounded')['default']
IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default'] IconMdiArrowDownThin: typeof import('~icons/mdi/arrow-down-thin')['default']
IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default'] IconMdiArrowUpThin: typeof import('~icons/mdi/arrow-up-thin')['default']
IconMdiDrag: typeof import('~icons/mdi/drag')['default'] IconMdiDrag: typeof import('~icons/mdi/drag')['default']
IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default'] IconMdiKeyboardEsc: typeof import('~icons/mdi/keyboard-esc')['default']
IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default'] IconMdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
IconMdiRefresh: typeof import('~icons/mdi/refresh')['default'] IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
'IconQuill:collapse': typeof import('~icons/quill/collapse')['default']
'IconQuill:expand': typeof import('~icons/quill/expand')['default']
IconUilSearch: typeof import('~icons/uil/search')['default'] IconUilSearch: typeof import('~icons/uil/search')['default']
JsonPreview: typeof import('./../components/custom/json-preview.vue')['default'] JsonPreview: typeof import('./../components/custom/json-preview.vue')['default']
LangSwitch: typeof import('./../components/common/lang-switch.vue')['default'] LangSwitch: typeof import('./../components/common/lang-switch.vue')['default']

View File

@ -156,11 +156,19 @@ async function handleExport() {
} }
async function handleCleanOperLog() { async function handleCleanOperLog() {
window.$dialog?.error({
title: '提示',
content: '是否确认清空所有操作日志数据项?',
positiveText: '确认清空',
negativeText: '取消',
onPositiveClick: async () => {
const { error } = await fetchCleanOperLog(); const { error } = await fetchCleanOperLog();
if (error) return; if (error) return;
window.$message?.success('清理成功'); window.$message?.success('清成功');
await getData(); await getData();
} }
});
}
</script> </script>
<template> <template>
@ -182,11 +190,14 @@ async function handleCleanOperLog() {
<template #prefix> <template #prefix>
<NButton <NButton
v-if="hasAuth('monitor:operlog:remove')" v-if="hasAuth('monitor:operlog:remove')"
type="warning" type="error"
ghost ghost
size="small" size="small"
@click="handleCleanOperLog" @click="handleCleanOperLog"
> >
<template #icon>
<icon-material-symbols:warning-outline-rounded />
</template>
清空 清空
</NButton> </NButton>
</template> </template>

View File

@ -215,6 +215,9 @@ async function handleRefreshCache() {
size="small" size="small"
@click="handleRefreshCache" @click="handleRefreshCache"
> >
<template #icon>
<icon-material-symbols:sync-outline />
</template>
刷新缓存 刷新缓存
</NButton> </NButton>
</template> </template>

View File

@ -1,7 +1,7 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { NButton, NDivider } from 'naive-ui'; import { NButton, NDivider } from 'naive-ui';
import { jsonClone } from '@sa/utils'; import { jsonClone } from '@sa/utils';
import type { TableDataWithIndex } from '@sa/hooks'; import { type TableDataWithIndex } from '@sa/hooks';
import { fetchBatchDeleteDept, fetchGetDeptList } from '@/service/api/system/dept'; import { fetchBatchDeleteDept, fetchGetDeptList } from '@/service/api/system/dept';
import { useAppStore } from '@/store/modules/app'; import { useAppStore } from '@/store/modules/app';
import { useAuth } from '@/hooks/business/auth'; import { useAuth } from '@/hooks/business/auth';
@ -31,6 +31,7 @@ const {
searchParams, searchParams,
resetSearchParams, resetSearchParams,
expandedRowKeys, expandedRowKeys,
isCollapse,
expandAll, expandAll,
collapseAll collapseAll
} = useTreeTable({ } = useTreeTable({
@ -173,8 +174,18 @@ async function addInRow(row: TableDataWithIndex<Api.System.Dept>) {
@refresh="getData" @refresh="getData"
> >
<template #prefix> <template #prefix>
<NButton size="small" @click="expandAll">展开</NButton> <NButton v-if="!isCollapse" :disabled="!expandedRowKeys.length" size="small" @click="expandAll">
<NButton size="small" @click="collapseAll">收起</NButton> <template #icon>
<icon-quill:expand />
</template>
全部展开
</NButton>
<NButton v-if="isCollapse" :disabled="!expandedRowKeys.length" size="small" @click="collapseAll">
<template #icon>
<icon-quill:collapse />
</template>
全部收起
</NButton>
</template> </template>
</TableHeaderOperation> </TableHeaderOperation>
</template> </template>

View File

@ -305,13 +305,13 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
v-model:checked-keys="checkedKeys" v-model:checked-keys="checkedKeys"
v-model:expanded-keys="expandedKeys" v-model:expanded-keys="expandedKeys"
:cancelable="false" :cancelable="false"
block-node
show-line show-line
:data="treeData as []" :data="treeData as []"
:default-expanded-keys="[0]" :default-expanded-keys="[0]"
:show-irrelevant-nodes="false" :show-irrelevant-nodes="false"
:pattern="name" :pattern="name"
block-line class="menu-tree h-full min-h-200px py-3"
class="h-full min-h-200px py-3"
key-field="menuId" key-field="menuId"
label-field="menuName" label-field="menuName"
virtual-scroll virtual-scroll
@ -482,11 +482,11 @@ const btnColumns: DataTableColumns<Api.System.Menu> = [
.menu-tree { .menu-tree {
:deep(.n-tree-node) { :deep(.n-tree-node) {
height: 33px; height: 25px;
} }
:deep(.n-tree-node-switcher) { :deep(.n-tree-node-switcher) {
height: 33px; height: 25px;
} }
:deep(.n-tree-node-switcher__icon) { :deep(.n-tree-node-switcher__icon) {

View File

@ -161,7 +161,7 @@ const {
<ButtonIcon <ButtonIcon
text text
type="primary" type="primary"
icon="material-symbols:download" icon="material-symbols:download-rounded"
class="text-20px" class="text-20px"
tooltipContent={$t('common.download')} tooltipContent={$t('common.download')}
onClick={() => download(row.ossId!)} onClick={() => download(row.ossId!)}
@ -298,15 +298,15 @@ function handleToOssConfig() {
</template> </template>
</NSwitch> </NSwitch>
<NButton type="primary" size="small" ghost @click="handleUpload('file')"> <NButton size="small" ghost @click="handleUpload('file')">
<template #icon> <template #icon>
<icon-ic-round-file-upload /> <icon-material-symbols:upload-rounded />
</template> </template>
上传文件 上传文件
</NButton> </NButton>
<NButton type="primary" size="small" ghost @click="handleUpload('image')"> <NButton size="small" ghost @click="handleUpload('image')">
<template #icon> <template #icon>
<icon-ic-round-image /> <icon-material-symbols:image-outline />
</template> </template>
上传图片 上传图片
</NButton> </NButton>

View File

@ -257,7 +257,6 @@ async function handleStatusChange(
:default-expanded-keys="deptData?.length ? [deptData[0].id!] : []" :default-expanded-keys="deptData?.length ? [deptData[0].id!] : []"
:show-irrelevant-nodes="false" :show-irrelevant-nodes="false"
:pattern="deptPattern" :pattern="deptPattern"
block-line
class="infinite-scroll h-full min-h-200px py-3" class="infinite-scroll h-full min-h-200px py-3"
key-field="id" key-field="id"
label-field="label" label-field="label"
@ -289,7 +288,7 @@ async function handleStatusChange(
<template #after> <template #after>
<NButton v-if="hasAuth('system:user:import')" size="small" ghost @click="handleImport"> <NButton v-if="hasAuth('system:user:import')" size="small" ghost @click="handleImport">
<template #icon> <template #icon>
<icon-material-symbols:upload-2-rounded class="text-icon" /> <icon-material-symbols:upload-rounded class="text-icon" />
</template> </template>
导入 导入
</NButton> </NButton>
@ -351,11 +350,11 @@ async function handleStatusChange(
} }
:deep(.n-tree-node) { :deep(.n-tree-node) {
height: 33px; height: 25px;
} }
:deep(.n-tree-node-switcher) { :deep(.n-tree-node-switcher) {
height: 33px; height: 25px;
} }
:deep(.n-tree-node-switcher__icon) { :deep(.n-tree-node-switcher__icon) {

View File

@ -287,13 +287,13 @@ getDataNames();
@click="() => handleGenCode()" @click="() => handleGenCode()"
> >
<template #icon> <template #icon>
<icon-ic-round-download class="text-icon" /> <icon-material-symbols:download-rounded class="text-icon" />
</template> </template>
生成代码 生成代码
</NButton> </NButton>
<NButton size="small" ghost type="primary" @click="handleImport"> <NButton size="small" ghost type="primary" @click="handleImport">
<template #icon> <template #icon>
<icon-ic-round-upload class="text-icon" /> <icon-material-symbols:upload-rounded class="text-icon" />
</template> </template>
导入 导入
</NButton> </NButton>