perf: use table action

pull/110/MERGE
xingyu4j 2025-05-19 17:58:06 +08:00
parent f3c5f4d22b
commit 52ae513e1c
37 changed files with 866 additions and 1259 deletions

View File

@ -1,8 +1,7 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemDeptApi } from '#/api/system/dept'; import type { SystemDeptApi } from '#/api/system/dept';
import { useAccess } from '@vben/access';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
@ -10,8 +9,6 @@ import { getDeptList } from '#/api/system/dept';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -113,7 +110,6 @@ export function useFormSchema(): VbenFormSchema[] {
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns( export function useGridColumns(
onActionClick?: OnActionClickFn<SystemDeptApi.Dept>,
getLeaderName?: (userId: number) => string | undefined, getLeaderName?: (userId: number) => string | undefined,
): VxeTableGridOptions<SystemDeptApi.Dept>['columns'] { ): VxeTableGridOptions<SystemDeptApi.Dept>['columns'] {
return [ return [
@ -154,39 +150,10 @@ export function useGridColumns(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 200, width: 220,
align: 'right',
fixed: 'right', fixed: 'right',
headerAlign: 'center', slots: { default: 'actions' },
showOverflow: false,
cellRender: {
attrs: {
nameField: 'name',
nameTitle: '部门',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'append',
text: '新增下级',
show: hasAccessByCodes(['system:dept:create']),
},
{
code: 'edit',
show: hasAccessByCodes(['system:dept:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:dept:delete']),
disabled: (row: SystemDeptApi.Dept) => {
return !!(row.children && row.children.length > 0);
},
},
],
},
}, },
]; ];
} }

View File

@ -1,21 +1,18 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemDeptApi } from '#/api/system/dept'; import type { SystemDeptApi } from '#/api/system/dept';
import type { SystemUserApi } from '#/api/system/user'; import type { SystemUserApi } from '#/api/system/user';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteDept, getDeptList } from '#/api/system/dept'; import { deleteDept, getDeptList } from '#/api/system/dept';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns } from './data'; import { useGridColumns } from './data';
@ -62,41 +59,21 @@ function onEdit(row: SystemDeptApi.Dept) {
/** 删除部门 */ /** 删除部门 */
async function onDelete(row: SystemDeptApi.Dept) { async function onDelete(row: SystemDeptApi.Dept) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteDept(row.id as number);
await deleteDept(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({ code, row }: OnActionClickParams<SystemDeptApi.Dept>) {
switch (code) {
case 'append': {
onAppend(row);
break;
}
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick, getLeaderName), columns: useGridColumns(getLeaderName),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
pagerConfig: { pagerConfig: {
@ -136,17 +113,54 @@ onMounted(async () => {
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:dept:create']" label: $t('ui.actionTitle.create', ['菜单']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['部门']) }} auth: ['system:dept:create'],
</Button> onClick: onCreate,
<Button class="ml-2" @click="toggleExpand"> },
{{ isExpanded ? '收缩' : '展开' }} {
</Button> label: isExpanded ? '收缩' : '展开',
type: 'primary',
onClick: toggleExpand,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '新增下级',
type: 'link',
icon: ACTION_ICON.ADD,
auth: ['system:menu:create'],
onClick: onAppend.bind(null, row),
},
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:menu:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:menu:delete'],
disabled: !!(row.children && row.children.length > 0),
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,13 +1,8 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemLoginLogApi } from '#/api/system/login-log';
import { useAccess } from '@vben/access';
import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils'; import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -42,9 +37,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemLoginLogApi.LoginLog>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -91,26 +84,10 @@ export function useGridColumns<T = SystemLoginLogApi.LoginLog>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 120, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'username',
nameTitle: '登录日志',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '详情',
show: hasAccessByCodes(['system:login-log:query']),
},
],
},
}, },
]; ];
} }

View File

@ -1,19 +1,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemLoginLogApi } from '#/api/system/login-log'; import type { SystemLoginLogApi } from '#/api/system/login-log';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { exportLoginLog, getLoginLogPage } from '#/api/system/login-log'; import { exportLoginLog, getLoginLogPage } from '#/api/system/login-log';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -40,25 +35,12 @@ function onDetail(row: SystemLoginLogApi.LoginLog) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemLoginLogApi.LoginLog>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -92,15 +74,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
class="ml-2" {
@click="onExport" label: $t('ui.actionTitle.export'),
v-access:code="['system:login-log:export']" type: 'primary',
> icon: ACTION_ICON.DOWNLOAD,
<Download class="size-5" /> auth: ['system:login-log:export'],
{{ $t('ui.actionTitle.export') }} onClick: onExport,
</Button> },
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.detail'),
type: 'link',
icon: ACTION_ICON.VIEW,
auth: ['system:login-log:query'],
onClick: onDetail.bind(null, row),
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemMailAccountApi } from '#/api/system/mail/account';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -125,9 +120,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemMailAccountApi.MailAccount>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -179,29 +172,10 @@ export function useGridColumns<T = SystemMailAccountApi.MailAccount>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 130, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'mail',
nameTitle: '邮箱账号',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:mail-account:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:mail-account:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,14 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemMailAccountApi } from '#/api/system/mail/account'; import type { SystemMailAccountApi } from '#/api/system/mail/account';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -16,6 +12,7 @@ import {
getMailAccountPage, getMailAccountPage,
} from '#/api/system/mail/account'; } from '#/api/system/mail/account';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -43,35 +40,16 @@ function onEdit(row: SystemMailAccountApi.MailAccount) {
/** 删除邮箱账号 */ /** 删除邮箱账号 */
async function onDelete(row: SystemMailAccountApi.MailAccount) { async function onDelete(row: SystemMailAccountApi.MailAccount) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.mail]), content: $t('ui.actionMessage.deleting', [row.mail]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteMailAccount(row.id as number);
await deleteMailAccount(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.mail])); content: $t('ui.actionMessage.deleteSuccess', [row.mail]),
onRefresh(); key: 'action_key_msg',
} finally { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemMailAccountApi.MailAccount>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -79,7 +57,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -112,14 +90,41 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:mail-account:create']" label: $t('ui.actionTitle.create', ['邮箱账号']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['邮箱账号']) }} auth: ['system:mail-account:create'],
</Button> onClick: onCreate,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:mail-account:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:mail-account:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemMailLogApi } from '#/api/system/mail/log';
import { useAccess } from '@vben/access';
import { getSimpleMailAccountList } from '#/api/system/mail/account'; import { getSimpleMailAccountList } from '#/api/system/mail/account';
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -75,9 +70,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemMailLogApi.MailLog>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -125,26 +118,10 @@ export function useGridColumns<T = SystemMailLogApi.MailLog>(
minWidth: 120, minWidth: 120,
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 80, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'toMail',
nameTitle: '邮件日志',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '查看',
show: hasAccessByCodes(['system:mail-log:query']),
},
],
},
}, },
]; ];
} }

View File

@ -1,8 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemMailLogApi } from '#/api/system/mail/log'; import type { SystemMailLogApi } from '#/api/system/mail/log';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
@ -10,6 +7,7 @@ import { Page, useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getMailLogPage } from '#/api/system/mail/log'; import { getMailLogPage } from '#/api/system/mail/log';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import Detail from './modules/detail.vue'; import Detail from './modules/detail.vue';
@ -29,25 +27,12 @@ function onDetail(row: SystemMailLogApi.MailLog) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemMailLogApi.MailLog>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -79,7 +64,19 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> </template> <template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.detail'),
type: 'link',
icon: ACTION_ICON.VIEW,
auth: ['system:mail-log:query'],
onClick: onDetail.bind(null, row),
},
]"
/>
</template>
</Grid> </Grid>
</Page> </Page>
</template> </template>

View File

@ -1,8 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemMailTemplateApi } from '#/api/system/mail/template';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { getSimpleMailAccountList } from '#/api/system/mail/account'; import { getSimpleMailAccountList } from '#/api/system/mail/account';
@ -13,8 +10,6 @@ import {
getRangePickerDefaultProps, getRangePickerDefaultProps,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -193,8 +188,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemMailTemplateApi.MailTemplate>( export function useGridColumns(
onActionClick: OnActionClickFn<T>,
getAccountMail?: (accountId: number) => string | undefined, getAccountMail?: (accountId: number) => string | undefined,
): VxeTableGridOptions['columns'] { ): VxeTableGridOptions['columns'] {
return [ return [
@ -245,34 +239,10 @@ export function useGridColumns<T = SystemMailTemplateApi.MailTemplate>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 150, width: 220,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: '邮件模板',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:mail-template:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:mail-template:delete']),
},
{
code: 'send',
text: '测试',
show: hasAccessByCodes(['system:mail-template:send-mail']),
},
],
},
}, },
]; ];
} }

View File

@ -1,17 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemMailAccountApi } from '#/api/system/mail/account'; import type { SystemMailAccountApi } from '#/api/system/mail/account';
import type { SystemMailTemplateApi } from '#/api/system/mail/template'; import type { SystemMailTemplateApi } from '#/api/system/mail/template';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSimpleMailAccountList } from '#/api/system/mail/account'; import { getSimpleMailAccountList } from '#/api/system/mail/account';
@ -20,6 +16,7 @@ import {
getMailTemplatePage, getMailTemplatePage,
} from '#/api/system/mail/template'; } from '#/api/system/mail/template';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -28,11 +25,6 @@ import SendForm from './modules/send-form.vue';
const accountList = ref<SystemMailAccountApi.MailAccount[]>([]); const accountList = ref<SystemMailAccountApi.MailAccount[]>([]);
/** 获取邮箱账号 */
const getAccountMail = (accountId: number) => {
return accountList.value.find((account) => account.id === accountId)?.mail;
};
const [FormModal, formModalApi] = useVbenModal({ const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form, connectedComponent: Form,
destroyOnClose: true, destroyOnClose: true,
@ -65,39 +57,22 @@ function onSend(row: SystemMailTemplateApi.MailTemplate) {
/** 删除邮件模板 */ /** 删除邮件模板 */
async function onDelete(row: SystemMailTemplateApi.MailTemplate) { async function onDelete(row: SystemMailTemplateApi.MailTemplate) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, duration: 0,
key: 'action_process_msg', key: 'action_process_msg',
}); });
try { await deleteMailTemplate(row.id as number);
await deleteMailTemplate(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} finally { });
hideLoading(); onRefresh();
}
} }
/** 表格操作按钮的回调函数 */ /** 获取邮箱账号 */
function onActionClick({ function getAccountMail(accountId: number) {
code, return accountList.value.find((account) => account.id === accountId)?.mail;
row,
}: OnActionClickParams<SystemMailTemplateApi.MailTemplate>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
case 'send': {
onSend(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -105,7 +80,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick, getAccountMail), columns: useGridColumns(getAccountMail),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -144,14 +119,48 @@ onMounted(async () => {
<SendModal /> <SendModal />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:mail-template:create']" label: $t('ui.actionTitle.create', ['邮件模板']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['邮件模板']) }} auth: ['system:mail-template:create'],
</Button> onClick: onCreate,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:mail-template:update'],
onClick: onEdit.bind(null, row),
},
{
label: '测试',
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:mail-template:send-mail'],
onClick: onSend.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:mail-template:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,12 +1,11 @@
import type { Recordable } from '@vben/types'; import type { Recordable } from '@vben/types';
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemMenuApi } from '#/api/system/menu'; import type { SystemMenuApi } from '#/api/system/menu';
import { h } from 'vue'; import { h } from 'vue';
import { useAccess } from '@vben/access';
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { handleTree, isHttpUrl } from '@vben/utils'; import { handleTree, isHttpUrl } from '@vben/utils';
@ -21,8 +20,6 @@ import {
SystemMenuTypeEnum, SystemMenuTypeEnum,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -269,9 +266,7 @@ export function useFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns( export function useGridColumns(): VxeTableGridOptions<SystemMenuApi.Menu>['columns'] {
onActionClick: OnActionClickFn<SystemMenuApi.Menu>,
): VxeTableGridOptions<SystemMenuApi.Menu>['columns'] {
return [ return [
{ {
field: 'name', field: 'name',
@ -321,34 +316,10 @@ export function useGridColumns(
}, },
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 200, width: 220,
fixed: 'right', fixed: 'right',
align: 'center', slots: { default: 'actions' },
showOverflow: false,
cellRender: {
attrs: {
nameField: 'name',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'append',
text: '新增下级',
show: hasAccessByCodes(['system:menu:create']),
},
{
code: 'edit',
show: hasAccessByCodes(['system:menu:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:menu:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,20 +1,18 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemMenuApi } from '#/api/system/menu'; import type { SystemMenuApi } from '#/api/system/menu';
import { ref } from 'vue'; import { ref } from 'vue';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { IconifyIcon, Plus } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteMenu, getMenuList } from '#/api/system/menu'; import { deleteMenu, getMenuList } from '#/api/system/menu';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { SystemMenuTypeEnum } from '#/utils'; import { SystemMenuTypeEnum } from '#/utils';
@ -48,36 +46,16 @@ function onEdit(row: SystemMenuApi.Menu) {
/** 删除菜单 */ /** 删除菜单 */
async function onDelete(row: SystemMenuApi.Menu) { async function onDelete(row: SystemMenuApi.Menu) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteMenu(row.id as number);
await deleteMenu(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({ code, row }: OnActionClickParams<SystemMenuApi.Menu>) {
switch (code) {
case 'append': {
onAppend(row);
break;
}
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
/** 切换树形展开/收缩状态 */ /** 切换树形展开/收缩状态 */
@ -89,7 +67,7 @@ function toggleExpand() {
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
pagerConfig: { pagerConfig: {
@ -131,17 +109,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid> <Grid>
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:menu:create']" label: $t('ui.actionTitle.create', ['菜单']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['菜单']) }} auth: ['system:menu:create'],
</Button> onClick: onCreate,
<Button class="ml-2" @click="toggleExpand"> },
{{ isExpanded ? '收缩' : '展开' }} {
</Button> label: isExpanded ? '收缩' : '展开',
type: 'primary',
onClick: toggleExpand,
},
]"
/>
</template> </template>
<template #name="{ row }"> <template #name="{ row }">
<div class="flex w-full items-center gap-1"> <div class="flex w-full items-center gap-1">
@ -161,6 +144,37 @@ const [Grid, gridApi] = useVbenVxeGrid({
<div class="items-center justify-end"></div> <div class="items-center justify-end"></div>
</div> </div>
</template> </template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '新增下级',
type: 'link',
icon: ACTION_ICON.ADD,
auth: ['system:menu:create'],
onClick: onAppend.bind(null, row),
},
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:menu:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:menu:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template>
</Grid> </Grid>
</Page> </Page>
</template> </template>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemNoticeApi } from '#/api/system/notice';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -91,9 +86,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemNoticeApi.Notice>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -130,34 +123,10 @@ export function useGridColumns<T = SystemNoticeApi.Notice>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 220,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'title',
nameTitle: '公告',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:notice:update']),
},
{
code: 'push',
text: '推送',
show: hasAccessByCodes(['system:notice:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:notice:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,17 +1,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemNoticeApi } from '#/api/system/notice'; import type { SystemNoticeApi } from '#/api/system/notice';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteNotice, getNoticePage, pushNotice } from '#/api/system/notice'; import { deleteNotice, getNoticePage, pushNotice } from '#/api/system/notice';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -39,18 +36,16 @@ function onEdit(row: SystemNoticeApi.Notice) {
/** 删除公告 */ /** 删除公告 */
async function onDelete(row: SystemNoticeApi.Notice) { async function onDelete(row: SystemNoticeApi.Notice) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.title]), content: $t('ui.actionMessage.deleting', [row.title]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteNotice(row.id as number);
await deleteNotice(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.title])); content: $t('ui.actionMessage.deleteSuccess', [row.title]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
} }
/** 推送公告 */ /** 推送公告 */
@ -68,33 +63,12 @@ async function onPush(row: SystemNoticeApi.Notice) {
} }
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemNoticeApi.Notice>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
case 'push': {
onPush(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -124,14 +98,48 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:notice:create']" label: $t('ui.actionTitle.create', ['公告']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['公告']) }} auth: ['system:notice:create'],
</Button> onClick: onCreate,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:notice:update'],
onClick: onEdit.bind(null, row),
},
{
label: '推送',
type: 'link',
icon: ACTION_ICON.ADD,
auth: ['system:notice:update'],
onClick: onPush.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:notice:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,13 +1,8 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
import { useAccess } from '@vben/access';
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -65,9 +60,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -146,26 +139,10 @@ export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'id',
nameTitle: '站内信',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '详情',
show: hasAccessByCodes(['system:notify-message:query']),
},
],
},
}, },
]; ];
} }

View File

@ -1,8 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemNotifyMessageApi } from '#/api/system/notify/message'; import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
@ -10,6 +7,7 @@ import { Page, useVbenModal } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getNotifyMessagePage } from '#/api/system/notify/message'; import { getNotifyMessagePage } from '#/api/system/notify/message';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import Detail from './modules/detail.vue'; import Detail from './modules/detail.vue';
@ -29,25 +27,12 @@ function onDetail(row: SystemNotifyMessageApi.NotifyMessage) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemNotifyMessageApi.NotifyMessage>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -79,6 +64,20 @@ const [Grid, gridApi] = useVbenVxeGrid({
</template> </template>
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title="" /> <Grid table-title="">
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.detail'),
type: 'link',
icon: ACTION_ICON.VIEW,
auth: ['system:notify-message:query'],
onClick: onDetail.bind(null, row),
},
]"
/>
</template>
</Grid>
</Page> </Page>
</template> </template>

View File

@ -1,6 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
import type { DescriptionItemSchema } from '#/components/description'; import type { DescriptionItemSchema } from '#/components/description';
import { h } from 'vue'; import { h } from 'vue';
@ -36,9 +35,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
title: '', title: '',
@ -86,31 +83,10 @@ export function useGridColumns<T = SystemNotifyMessageApi.NotifyMessage>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'id',
nameTitle: '站内信',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '查看',
show: (row: any) => row.readStatus,
},
{
code: 'read',
text: '已读',
show: (row: any) => !row.readStatus,
},
],
},
}, },
]; ];
} }

View File

@ -1,14 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemNotifyMessageApi } from '#/api/system/notify/message'; import type { SystemNotifyMessageApi } from '#/api/system/notify/message';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { MdiCheckboxMarkedCircleOutline } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -17,6 +13,7 @@ import {
updateNotifyMessageRead, updateNotifyMessageRead,
} from '#/api/system/notify/message'; } from '#/api/system/notify/message';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import Detail from './modules/detail.vue'; import Detail from './modules/detail.vue';
@ -46,7 +43,10 @@ async function onRead(row: SystemNotifyMessageApi.NotifyMessage) {
// //
await updateNotifyMessageRead([row.id]); await updateNotifyMessageRead([row.id]);
// //
message.success('标记已读成功'); message.success({
content: '标记已读成功',
key: 'action_process_msg',
});
onRefresh(); onRefresh();
// //
@ -70,7 +70,10 @@ async function onMarkRead() {
// //
await updateNotifyMessageRead(ids); await updateNotifyMessageRead(ids);
// //
message.success('标记已读成功'); message.success({
content: '标记已读成功',
key: 'action_process_msg',
});
await gridApi.grid.setAllCheckboxRow(false); await gridApi.grid.setAllCheckboxRow(false);
onRefresh(); onRefresh();
} }
@ -85,34 +88,20 @@ async function onMarkAllRead() {
// //
await updateAllNotifyMessageRead(); await updateAllNotifyMessageRead();
// //
message.success('全部标记已读成功'); message.success({
content: '全部标记已读成功',
key: 'action_process_msg',
});
await gridApi.grid.setAllCheckboxRow(false); await gridApi.grid.setAllCheckboxRow(false);
onRefresh(); onRefresh();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemNotifyMessageApi.NotifyMessage>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
case 'read': {
onRead(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -150,14 +139,42 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button type="primary" @click="onMarkRead"> <TableAction
<MdiCheckboxMarkedCircleOutline /> :actions="[
标记已读 {
</Button> label: '标记已读',
<Button type="primary" class="ml-2" @click="onMarkAllRead"> type: 'primary',
<MdiCheckboxMarkedCircleOutline /> icon: 'mdi:checkbox-marked-circle-outline',
全部已读 onClick: onMarkRead,
</Button> },
{
label: '全部已读',
type: 'primary',
icon: 'mdi:checkbox-marked-circle-outline',
onClick: onMarkAllRead,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '查看',
type: 'link',
ifShow: row.readStatus,
icon: ACTION_ICON.VIEW,
onClick: onDetail.bind(null, row),
},
{
label: '已读',
type: 'link',
ifShow: !row.readStatus,
icon: ACTION_ICON.DELETE,
onClick: onRead.bind(null, row),
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,8 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemNotifyTemplateApi } from '#/api/system/notify/template';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
@ -14,8 +11,6 @@ import {
UserTypeEnum, UserTypeEnum,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -229,9 +224,7 @@ export function useSendNotifyFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemNotifyTemplateApi.NotifyTemplate>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -288,34 +281,10 @@ export function useGridColumns<T = SystemNotifyTemplateApi.NotifyTemplate>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 220,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: '站内信模板',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:notify-template:update']),
},
{
code: 'send',
text: '测试',
show: hasAccessByCodes(['system:notify-template:send-notify']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:notify-template:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,15 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemNotifyTemplateApi } from '#/api/system/notify/template'; import type { SystemNotifyTemplateApi } from '#/api/system/notify/template';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download, Plus } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -18,6 +14,7 @@ import {
getNotifyTemplatePage, getNotifyTemplatePage,
} from '#/api/system/notify/template'; } from '#/api/system/notify/template';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -62,39 +59,16 @@ function onSend(row: SystemNotifyTemplateApi.NotifyTemplate) {
/** 删除站内信模板 */ /** 删除站内信模板 */
async function onDelete(row: SystemNotifyTemplateApi.NotifyTemplate) { async function onDelete(row: SystemNotifyTemplateApi.NotifyTemplate) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteNotifyTemplate(row.id as number);
await deleteNotifyTemplate(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} finally { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemNotifyTemplateApi.NotifyTemplate>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
case 'send': {
onSend(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -102,7 +76,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -137,23 +111,55 @@ const [Grid, gridApi] = useVbenVxeGrid({
<SendModal /> <SendModal />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:notify-template:create']" label: $t('ui.actionTitle.create', ['短信渠道']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['站内信模板']) }} auth: ['system:notify-template:create'],
</Button> onClick: onCreate,
<Button },
type="primary" {
class="ml-2" label: $t('ui.actionTitle.export'),
@click="onExport" type: 'primary',
v-access:code="['system:notify-template:export']" icon: ACTION_ICON.DOWNLOAD,
> auth: ['system:notify-template:export'],
<Download class="size-5" /> onClick: onExport,
{{ $t('ui.actionTitle.export') }} },
</Button> ]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:notify-template:update'],
onClick: onEdit.bind(null, row),
},
{
label: '测试',
type: 'link',
icon: ACTION_ICON.ADD,
auth: ['system:notify-template:send-notify'],
onClick: onSend.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:notify-template:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemOAuth2ClientApi } from '#/api/system/oauth2/client';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -191,9 +186,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemOAuth2ClientApi.OAuth2Client>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'clientId', field: 'clientId',
@ -251,29 +244,10 @@ export function useGridColumns<T = SystemOAuth2ClientApi.OAuth2Client>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 130, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: 'OAuth2 客户端',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:oauth2-client:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:oauth2-client:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,14 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemOAuth2ClientApi } from '#/api/system/oauth2/client'; import type { SystemOAuth2ClientApi } from '#/api/system/oauth2/client';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -16,6 +12,7 @@ import {
getOAuth2ClientPage, getOAuth2ClientPage,
} from '#/api/system/oauth2/client'; } from '#/api/system/oauth2/client';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -43,35 +40,16 @@ function onEdit(row: SystemOAuth2ClientApi.OAuth2Client) {
/** 删除 OAuth2 客户端 */ /** 删除 OAuth2 客户端 */
async function onDelete(row: SystemOAuth2ClientApi.OAuth2Client) { async function onDelete(row: SystemOAuth2ClientApi.OAuth2Client) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteOAuth2Client(row.id as number);
await deleteOAuth2Client(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemOAuth2ClientApi.OAuth2Client>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -79,7 +57,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -116,14 +94,41 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title="OAuth2 "> <Grid table-title="OAuth2 ">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:oauth2-client:create']" label: $t('ui.actionTitle.create', [' OAuth2.0 客户端']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', [' OAuth2.0 客户端']) }} auth: ['system:oauth2-client:create'],
</Button> onClick: onCreate,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:oauth2-client:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:oauth2-client:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,13 +1,8 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemOAuth2TokenApi } from '#/api/system/oauth2/token';
import { useAccess } from '@vben/access';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -40,9 +35,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemOAuth2TokenApi.OAuth2Token>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'accessToken', field: 'accessToken',
@ -86,26 +79,10 @@ export function useGridColumns<T = SystemOAuth2TokenApi.OAuth2Token>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 100, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'accessToken',
nameTitle: 'OAuth2 令牌',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'delete',
text: '强退',
show: hasAccessByCodes(['system:oauth2-token:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,8 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemOAuth2TokenApi } from '#/api/system/oauth2/token'; import type { SystemOAuth2TokenApi } from '#/api/system/oauth2/token';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
@ -15,6 +12,7 @@ import {
getOAuth2TokenPage, getOAuth2TokenPage,
} from '#/api/system/oauth2/token'; } from '#/api/system/oauth2/token';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -26,31 +24,16 @@ function onRefresh() {
/** 删除 OAuth2 令牌 */ /** 删除 OAuth2 令牌 */
async function onDelete(row: SystemOAuth2TokenApi.OAuth2Token) { async function onDelete(row: SystemOAuth2TokenApi.OAuth2Token) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', ['令牌']), content: $t('ui.actionMessage.deleting', ['令牌']),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteOAuth2Token(row.accessToken);
await deleteOAuth2Token(row.accessToken); message.success({
message.success($t('ui.actionMessage.operationSuccess')); content: $t('ui.actionMessage.deleteSuccess', ['令牌']),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemOAuth2TokenApi.OAuth2Token>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -58,7 +41,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -92,6 +75,24 @@ const [Grid, gridApi] = useVbenVxeGrid({
/> />
</template> </template>
<Grid table-title="" /> <Grid table-title="">
<template #actions="{ row }">
<TableAction
:actions="[
{
label: '强退',
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:oauth2-token:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template>
</Grid>
</Page> </Page>
</template> </template>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemOperateLogApi } from '#/api/system/operate-log';
import { useAccess } from '@vben/access';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { getRangePickerDefaultProps } from '#/utils'; import { getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -75,9 +70,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemOperateLogApi.OperateLog>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -121,26 +114,10 @@ export function useGridColumns<T = SystemOperateLogApi.OperateLog>(
minWidth: 120, minWidth: 120,
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 120, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'action',
nameTitle: '操作日志',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '详情',
show: hasAccessByCodes(['system:operate-log:query']),
},
],
},
}, },
]; ];
} }

View File

@ -1,19 +1,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemOperateLogApi } from '#/api/system/operate-log'; import type { SystemOperateLogApi } from '#/api/system/operate-log';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { exportOperateLog, getOperateLogPage } from '#/api/system/operate-log'; import { exportOperateLog, getOperateLogPage } from '#/api/system/operate-log';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -40,25 +35,12 @@ function onDetail(row: SystemOperateLogApi.OperateLog) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemOperateLogApi.OperateLog>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -92,15 +74,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
class="ml-2" {
@click="onExport" label: $t('ui.actionTitle.export'),
v-access:code="['system:operate-log:export']" type: 'primary',
> icon: ACTION_ICON.DOWNLOAD,
<Download class="size-5" /> auth: ['system:operate-log:export'],
{{ $t('ui.actionTitle.export') }} onClick: onExport,
</Button> },
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.detail'),
type: 'link',
icon: ACTION_ICON.VIEW,
auth: ['system:operate-log:query'],
onClick: onDetail.bind(null, row),
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemPostApi } from '#/api/system/post';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -86,9 +81,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemPostApi.Post>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -131,29 +124,10 @@ export function useGridColumns<T = SystemPostApi.Post>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 130, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: '岗位',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:post:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:post:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,18 +1,15 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemPostApi } from '#/api/system/post'; import type { SystemPostApi } from '#/api/system/post';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download, Plus } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deletePost, exportPost, getPostPage } from '#/api/system/post'; import { deletePost, exportPost, getPostPage } from '#/api/system/post';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -46,32 +43,17 @@ function onEdit(row: SystemPostApi.Post) {
/** 删除岗位 */ /** 删除岗位 */
async function onDelete(row: SystemPostApi.Post) { async function onDelete(row: SystemPostApi.Post) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, duration: 0,
key: 'action_process_msg', key: 'action_process_msg',
}); });
try { await deletePost(row.id as number);
await deletePost(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({ code, row }: OnActionClickParams<SystemPostApi.Post>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -79,7 +61,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -109,23 +91,48 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:post:create']" label: $t('ui.actionTitle.create', ['短信渠道']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['岗位']) }} auth: ['system:post:create'],
</Button> onClick: onCreate,
<Button },
type="primary" {
class="ml-2" label: $t('ui.actionTitle.export'),
@click="onExport" type: 'primary',
v-access:code="['system:post:export']" icon: ACTION_ICON.DOWNLOAD,
> auth: ['system:post:export'],
<Download class="size-5" /> onClick: onExport,
{{ $t('ui.actionTitle.export') }} },
</Button> ]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:post:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:post:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,8 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemSmsChannelApi } from '#/api/system/sms/channel';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { import {
@ -12,8 +9,6 @@ import {
getRangePickerDefaultProps, getRangePickerDefaultProps,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -135,9 +130,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemSmsChannelApi.SmsChannel>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -194,29 +187,10 @@ export function useGridColumns<T = SystemSmsChannelApi.SmsChannel>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'signature',
nameTitle: '短信渠道',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:sms-channel:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:sms-channel:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,15 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemSmsChannelApi } from '#/api/system/sms/channel'; import type { SystemSmsChannelApi } from '#/api/system/sms/channel';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download, Plus } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -18,6 +14,7 @@ import {
getSmsChannelPage, getSmsChannelPage,
} from '#/api/system/sms/channel'; } from '#/api/system/sms/channel';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -51,35 +48,17 @@ function onEdit(row: SystemSmsChannelApi.SmsChannel) {
/** 删除短信渠道 */ /** 删除短信渠道 */
async function onDelete(row: SystemSmsChannelApi.SmsChannel) { async function onDelete(row: SystemSmsChannelApi.SmsChannel) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.signature]), content: $t('ui.actionMessage.deleting', [row.signature]),
duration: 0, duration: 0,
key: 'action_process_msg', key: 'action_process_msg',
}); });
try { await deleteSmsChannel(row.id as number);
await deleteSmsChannel(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.signature])); content: $t('ui.actionMessage.deleteSuccess', [row.signature]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemSmsChannelApi.SmsChannel>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -87,7 +66,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -121,23 +100,48 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:sms-channel:create']" label: $t('ui.actionTitle.create', ['短信渠道']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['短信渠道']) }} auth: ['system:sms-channel:create'],
</Button> onClick: onCreate,
<Button },
type="primary" {
class="ml-2" label: $t('ui.actionTitle.export'),
@click="onExport" type: 'primary',
v-access:code="['system:sms-channel:export']" icon: ACTION_ICON.DOWNLOAD,
> auth: ['system:sms-channel:export'],
<Download class="size-5" /> onClick: onExport,
{{ $t('ui.actionTitle.export') }} },
</Button> ]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:sms-channel:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:sms-channel:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,14 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemSmsLogApi } from '#/api/system/sms/log';
import { useAccess } from '@vben/access';
import { getSimpleSmsChannelList } from '#/api/system/sms/channel'; import { getSimpleSmsChannelList } from '#/api/system/sms/channel';
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
return [ return [
@ -84,9 +79,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemSmsLogApi.SmsLog>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -163,26 +156,10 @@ export function useGridColumns<T = SystemSmsLogApi.SmsLog>(
}, },
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 120, width: 80,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'mobile',
nameTitle: '短信日志',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'detail',
text: '详情',
show: hasAccessByCodes(['system:sms-log:query']),
},
],
},
}, },
]; ];
} }

View File

@ -1,19 +1,14 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemSmsLogApi } from '#/api/system/sms/log'; import type { SystemSmsLogApi } from '#/api/system/sms/log';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { exportSmsLog, getSmsLogPage } from '#/api/system/sms/log'; import { exportSmsLog, getSmsLogPage } from '#/api/system/sms/log';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -40,25 +35,12 @@ function onDetail(row: SystemSmsLogApi.SmsLog) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemSmsLogApi.SmsLog>) {
switch (code) {
case 'detail': {
onDetail(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -92,15 +74,30 @@ const [Grid, gridApi] = useVbenVxeGrid({
<DetailModal @success="onRefresh" /> <DetailModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
class="ml-2" {
@click="onExport" label: $t('ui.actionTitle.export'),
v-access:code="['system:sms-log:export']" type: 'primary',
> icon: ACTION_ICON.DOWNLOAD,
<Download class="size-5" /> auth: ['system:sms-log:export'],
{{ $t('ui.actionTitle.export') }} onClick: onExport,
</Button> },
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.detail'),
type: 'link',
icon: ACTION_ICON.VIEW,
auth: ['system:sms-log:query'],
onClick: onDetail.bind(null, row),
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,8 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemSmsTemplateApi } from '#/api/system/sms/template';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { getSimpleSmsChannelList } from '#/api/system/sms/channel'; import { getSimpleSmsChannelList } from '#/api/system/sms/channel';
@ -13,8 +10,6 @@ import {
getRangePickerDefaultProps, getRangePickerDefaultProps,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -204,9 +199,7 @@ export function useSendSmsFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemSmsTemplateApi.SmsTemplate>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -272,34 +265,10 @@ export function useGridColumns<T = SystemSmsTemplateApi.SmsTemplate>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 180, width: 220,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: '短信模板',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:sms-template:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:sms-template:delete']),
},
{
code: 'sms-send',
text: '发送短信',
show: hasAccessByCodes(['system:sms-template:send-sms']),
},
],
},
}, },
]; ];
} }

View File

@ -1,15 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemSmsTemplateApi } from '#/api/system/sms/template'; import type { SystemSmsTemplateApi } from '#/api/system/sms/template';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Download, Plus } from '@vben/icons';
import { downloadFileFromBlobPart } from '@vben/utils'; import { downloadFileFromBlobPart } from '@vben/utils';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -18,6 +14,7 @@ import {
getSmsTemplatePage, getSmsTemplatePage,
} from '#/api/system/sms/template'; } from '#/api/system/sms/template';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -62,39 +59,17 @@ function onSend(row: SystemSmsTemplateApi.SmsTemplate) {
/** 删除短信模板 */ /** 删除短信模板 */
async function onDelete(row: SystemSmsTemplateApi.SmsTemplate) { async function onDelete(row: SystemSmsTemplateApi.SmsTemplate) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, duration: 0,
key: 'action_process_msg', key: 'action_process_msg',
}); });
try { await deleteSmsTemplate(row.id as number);
await deleteSmsTemplate(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} finally { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemSmsTemplateApi.SmsTemplate>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
case 'sms-send': {
onSend(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -102,7 +77,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -137,23 +112,55 @@ const [Grid, gridApi] = useVbenVxeGrid({
<SendModal /> <SendModal />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:sms-template:create']" label: $t('ui.actionTitle.create', ['短信模板']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['短信模板']) }} auth: ['system:sms-template:create'],
</Button> onClick: onCreate,
<Button },
type="primary" {
class="ml-2" label: $t('ui.actionTitle.export'),
@click="onExport" type: 'primary',
v-access:code="['system:sms-template:export']" icon: ACTION_ICON.DOWNLOAD,
> auth: ['system:sms-template:export'],
<Download class="size-5" /> onClick: onExport,
{{ $t('ui.actionTitle.export') }} },
</Button> ]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:sms-template:update'],
onClick: onEdit.bind(null, row),
},
{
label: '发送短信',
type: 'link',
icon: ACTION_ICON.ADD,
auth: ['system:sms-template:send-sms'],
onClick: onSend.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:sms-template:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -1,8 +1,5 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { SystemSocialClientApi } from '#/api/system/social/client';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { import {
@ -12,8 +9,6 @@ import {
SystemUserSocialTypeEnum, SystemUserSocialTypeEnum,
} from '#/utils'; } from '#/utils';
const { hasAccessByCodes } = useAccess();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -152,9 +147,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns<T = SystemSocialClientApi.SocialClient>( export function useGridColumns(): VxeTableGridOptions['columns'] {
onActionClick: OnActionClickFn<T>,
): VxeTableGridOptions['columns'] {
return [ return [
{ {
field: 'id', field: 'id',
@ -205,29 +198,10 @@ export function useGridColumns<T = SystemSocialClientApi.SocialClient>(
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
field: 'operation',
title: '操作', title: '操作',
minWidth: 130, width: 130,
align: 'center',
fixed: 'right', fixed: 'right',
cellRender: { slots: { default: 'actions' },
attrs: {
nameField: 'name',
nameTitle: '社交客户端',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['system:social-client:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['system:social-client:delete']),
},
],
},
}, },
]; ];
} }

View File

@ -1,14 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { SystemSocialClientApi } from '#/api/system/social/client'; import type { SystemSocialClientApi } from '#/api/system/social/client';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
@ -16,6 +12,7 @@ import {
getSocialClientPage, getSocialClientPage,
} from '#/api/system/social/client'; } from '#/api/system/social/client';
import { DocAlert } from '#/components/doc-alert'; import { DocAlert } from '#/components/doc-alert';
import { ACTION_ICON, TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
@ -43,35 +40,16 @@ function onEdit(row: SystemSocialClientApi.SocialClient) {
/** 删除社交客户端 */ /** 删除社交客户端 */
async function onDelete(row: SystemSocialClientApi.SocialClient) { async function onDelete(row: SystemSocialClientApi.SocialClient) {
const hideLoading = message.loading({ message.loading({
content: $t('ui.actionMessage.deleting', [row.name]), content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0, key: 'action_key_msg',
key: 'action_process_msg',
}); });
try { await deleteSocialClient(row.id as number);
await deleteSocialClient(row.id as number); message.success({
message.success($t('ui.actionMessage.deleteSuccess', [row.name])); content: $t('ui.actionMessage.deleteSuccess', [row.name]),
onRefresh(); key: 'action_key_msg',
} catch { });
hideLoading(); onRefresh();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<SystemSocialClientApi.SocialClient>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
} }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
@ -79,7 +57,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
keepSource: true, keepSource: true,
proxyConfig: { proxyConfig: {
@ -113,14 +91,41 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" /> <FormModal @success="onRefresh" />
<Grid table-title=""> <Grid table-title="">
<template #toolbar-tools> <template #toolbar-tools>
<Button <TableAction
type="primary" :actions="[
@click="onCreate" {
v-access:code="['system:social-client:create']" label: $t('ui.actionTitle.create', ['社交客户端']),
> type: 'primary',
<Plus class="size-5" /> icon: ACTION_ICON.ADD,
{{ $t('ui.actionTitle.create', ['社交客户端']) }} auth: ['system:social-client:create'],
</Button> onClick: onCreate,
},
]"
/>
</template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
icon: ACTION_ICON.EDIT,
auth: ['system:social-client:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
icon: ACTION_ICON.DELETE,
auth: ['system:social-client:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template> </template>
</Grid> </Grid>
</Page> </Page>

View File

@ -19,11 +19,6 @@ const [DetailModal, detailModalApi] = useVbenModal({
destroyOnClose: true, destroyOnClose: true,
}); });
/** 刷新表格 */
// function onRefresh() {
// gridApi.query();
// }
/** 查看详情 */ /** 查看详情 */
function onDetail(row: SystemSocialUserApi.SocialUser) { function onDetail(row: SystemSocialUserApi.SocialUser) {
detailModalApi.setData(row).open(); detailModalApi.setData(row).open();