feat: 账号功能配置接入KtTable
This commit is contained in:
parent
7d8f6c0f9d
commit
01743cfc18
@ -175,6 +175,7 @@ export default defineComponent({
|
|||||||
const permissions = useKtTablePermission(context);
|
const permissions = useKtTablePermission(context);
|
||||||
const {
|
const {
|
||||||
formButtons,
|
formButtons,
|
||||||
|
getVisibleRowActions,
|
||||||
headerButtons,
|
headerButtons,
|
||||||
renderButton,
|
renderButton,
|
||||||
renderRowAction,
|
renderRowAction,
|
||||||
@ -720,7 +721,7 @@ export default defineComponent({
|
|||||||
*/
|
*/
|
||||||
const renderActionCell = (record: KtTableRecord) => {
|
const renderActionCell = (record: KtTableRecord) => {
|
||||||
const { inlineActions, overflowActions } = splitRowActions(
|
const { inlineActions, overflowActions } = splitRowActions(
|
||||||
rowActions.value,
|
getVisibleRowActions(record),
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -167,6 +167,20 @@ export function useKtTableActions(options: UseKtTableActionsOptions) {
|
|||||||
await runHook('onAfterAction', action, result, context);
|
await runHook('onAfterAction', action, result, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按当前行过滤行操作,支持同一列按行状态展示不同按钮。
|
||||||
|
*
|
||||||
|
* @param row 当前行数据。
|
||||||
|
*/
|
||||||
|
function getVisibleRowActions(row: KtTableRecord) {
|
||||||
|
return rowActions.value.filter((action) => {
|
||||||
|
const { rowVisible } = action;
|
||||||
|
if (typeof rowVisible === 'function') return rowVisible(row, context);
|
||||||
|
if (typeof rowVisible === 'boolean') return rowVisible;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按配置决定是否弹出确认框后再执行行操作。
|
* 按配置决定是否弹出确认框后再执行行操作。
|
||||||
*
|
*
|
||||||
@ -239,6 +253,7 @@ export function useKtTableActions(options: UseKtTableActionsOptions) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
formButtons,
|
formButtons,
|
||||||
|
getVisibleRowActions,
|
||||||
headerButtons,
|
headerButtons,
|
||||||
renderButton,
|
renderButton,
|
||||||
renderRowAction: renderRowAction as (
|
renderRowAction: renderRowAction as (
|
||||||
|
|||||||
@ -104,6 +104,9 @@ export interface KtTableRowAction<
|
|||||||
row: Row,
|
row: Row,
|
||||||
context: KtTableContext<Row, SearchValues>,
|
context: KtTableContext<Row, SearchValues>,
|
||||||
) => Promise<void> | void;
|
) => Promise<void> | void;
|
||||||
|
rowVisible?:
|
||||||
|
| ((row: Row, context: KtTableContext<Row, SearchValues>) => boolean)
|
||||||
|
| boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KtTableStatistic<
|
export interface KtTableStatistic<
|
||||||
|
|||||||
@ -1,18 +1,13 @@
|
|||||||
|
import type { TableColumnType } from 'antdv-next';
|
||||||
|
|
||||||
import type { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
|
||||||
import type { QqbotApi } from '#/api/qqbot';
|
import type { QqbotApi } from '#/api/qqbot';
|
||||||
|
import type { KtTableRowAction } from '#/components/ktTable';
|
||||||
|
|
||||||
import { computed, defineComponent, ref, watch } from 'vue';
|
import { computed, defineComponent, ref, watch } from 'vue';
|
||||||
|
|
||||||
import {
|
import { message, Spin, Tabs, Tag } from 'antdv-next';
|
||||||
Button,
|
|
||||||
message,
|
|
||||||
Popconfirm,
|
|
||||||
Space,
|
|
||||||
Table,
|
|
||||||
Tabs,
|
|
||||||
Tag,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
bindQqbotAccountCommand,
|
bindQqbotAccountCommand,
|
||||||
@ -25,6 +20,7 @@ import {
|
|||||||
unbindQqbotAccountRule,
|
unbindQqbotAccountRule,
|
||||||
unbindQqbotEventPlugin,
|
unbindQqbotEventPlugin,
|
||||||
} from '#/api/qqbot';
|
} from '#/api/qqbot';
|
||||||
|
import { KtTable } from '#/components/ktTable';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getOptionLabel,
|
getOptionLabel,
|
||||||
@ -32,10 +28,8 @@ import {
|
|||||||
qqbotRuleTargetOptions,
|
qqbotRuleTargetOptions,
|
||||||
} from '../../modules/options';
|
} from '../../modules/options';
|
||||||
|
|
||||||
const AButton = Button as any;
|
const AKtTable = KtTable as any;
|
||||||
const APopconfirm = Popconfirm as any;
|
const ASpin = Spin as any;
|
||||||
const ASpace = Space as any;
|
|
||||||
const ATable = Table as any;
|
|
||||||
const ATabs = Tabs as any;
|
const ATabs = Tabs as any;
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@ -69,7 +63,7 @@ export default defineComponent({
|
|||||||
mergeById(ruleTemplates.value, boundRules.value),
|
mergeById(ruleTemplates.value, boundRules.value),
|
||||||
);
|
);
|
||||||
|
|
||||||
const commandColumns = [
|
const commandColumns: Array<TableColumnType<QqbotApi.Command>> = [
|
||||||
{ dataIndex: 'name', key: 'name', title: '命令模板', width: 160 },
|
{ dataIndex: 'name', key: 'name', title: '命令模板', width: 160 },
|
||||||
{ dataIndex: 'code', key: 'code', title: '命令编码', width: 140 },
|
{ dataIndex: 'code', key: 'code', title: '命令编码', width: 140 },
|
||||||
{ dataIndex: 'aliases', key: 'aliases', title: '别名', width: 200 },
|
{ dataIndex: 'aliases', key: 'aliases', title: '别名', width: 200 },
|
||||||
@ -82,15 +76,24 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
{ dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 },
|
{ dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 },
|
||||||
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
||||||
|
];
|
||||||
|
const commandRowActions: Array<KtTableRowAction<QqbotApi.Command>> = [
|
||||||
{
|
{
|
||||||
dataIndex: 'action',
|
key: 'bind',
|
||||||
fixed: 'right',
|
label: '绑定',
|
||||||
key: 'action',
|
onClick: async (row) => handleCommandBind(row),
|
||||||
title: '操作',
|
rowVisible: (row) => !boundCommandIds.value.has(row.id),
|
||||||
width: 100,
|
},
|
||||||
|
{
|
||||||
|
confirm: (row) => `确认从当前账号解绑「${row.name || row.code}」吗?`,
|
||||||
|
danger: true,
|
||||||
|
key: 'unbind',
|
||||||
|
label: '解绑',
|
||||||
|
onClick: async (row) => handleCommandUnbind(row),
|
||||||
|
rowVisible: (row) => boundCommandIds.value.has(row.id),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const eventColumns = [
|
const eventColumns: Array<TableColumnType<QqbotApi.EventPlugin>> = [
|
||||||
{ dataIndex: 'name', key: 'name', title: '插件模板', width: 160 },
|
{ dataIndex: 'name', key: 'name', title: '插件模板', width: 160 },
|
||||||
{ dataIndex: 'key', key: 'key', title: '插件 Key', width: 160 },
|
{ dataIndex: 'key', key: 'key', title: '插件 Key', width: 160 },
|
||||||
{
|
{
|
||||||
@ -106,15 +109,24 @@ export default defineComponent({
|
|||||||
width: 320,
|
width: 320,
|
||||||
},
|
},
|
||||||
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
||||||
|
];
|
||||||
|
const eventRowActions: Array<KtTableRowAction<QqbotApi.EventPlugin>> = [
|
||||||
{
|
{
|
||||||
dataIndex: 'action',
|
key: 'bind',
|
||||||
fixed: 'right',
|
label: '绑定',
|
||||||
key: 'action',
|
onClick: async (row) => handleEventBind(row),
|
||||||
title: '操作',
|
rowVisible: (row) => !row.bound,
|
||||||
width: 100,
|
},
|
||||||
|
{
|
||||||
|
confirm: (row) => `确认从当前账号解绑「${row.name}」吗?`,
|
||||||
|
danger: true,
|
||||||
|
key: 'unbind',
|
||||||
|
label: '解绑',
|
||||||
|
onClick: async (row) => handleEventUnbind(row),
|
||||||
|
rowVisible: (row) => row.bound,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const ruleColumns = [
|
const ruleColumns: Array<TableColumnType<QqbotApi.Rule>> = [
|
||||||
{ dataIndex: 'name', key: 'name', title: '规则模板', width: 160 },
|
{ dataIndex: 'name', key: 'name', title: '规则模板', width: 160 },
|
||||||
{ dataIndex: 'keyword', key: 'keyword', title: '关键词', width: 180 },
|
{ dataIndex: 'keyword', key: 'keyword', title: '关键词', width: 180 },
|
||||||
{
|
{
|
||||||
@ -137,12 +149,22 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
{ dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 },
|
{ dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 },
|
||||||
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
{ dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 },
|
||||||
|
];
|
||||||
|
const ruleRowActions: Array<KtTableRowAction<QqbotApi.Rule>> = [
|
||||||
{
|
{
|
||||||
dataIndex: 'action',
|
key: 'bind',
|
||||||
fixed: 'right',
|
label: '绑定',
|
||||||
key: 'action',
|
onClick: async (row) => handleRuleBind(row),
|
||||||
title: '操作',
|
rowVisible: (row) => !boundRuleIds.value.has(row.id),
|
||||||
width: 100,
|
},
|
||||||
|
{
|
||||||
|
confirm: (row) =>
|
||||||
|
`确认从当前账号解绑「${row.name || row.keyword}」吗?`,
|
||||||
|
danger: true,
|
||||||
|
key: 'unbind',
|
||||||
|
label: '解绑',
|
||||||
|
onClick: async (row) => handleRuleUnbind(row),
|
||||||
|
rowVisible: (row) => boundRuleIds.value.has(row.id),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -161,7 +183,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
async function refreshAll() {
|
async function refreshAll() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
@ -282,32 +303,6 @@ export default defineComponent({
|
|||||||
return [...map.values()];
|
return [...map.values()];
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderBindAction = (options: {
|
|
||||||
bound: boolean;
|
|
||||||
name: string;
|
|
||||||
onBind: () => Promise<void>;
|
|
||||||
onUnbind: () => Promise<void>;
|
|
||||||
}) => {
|
|
||||||
if (!options.bound) {
|
|
||||||
return (
|
|
||||||
<AButton onClick={options.onBind} type="link">
|
|
||||||
绑定
|
|
||||||
</AButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<APopconfirm
|
|
||||||
onConfirm={options.onUnbind}
|
|
||||||
title={`确认从当前账号解绑「${options.name}」吗?`}
|
|
||||||
>
|
|
||||||
<AButton danger type="link">
|
|
||||||
解绑
|
|
||||||
</AButton>
|
|
||||||
</APopconfirm>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderBoundTag = (bound: boolean) => {
|
const renderBoundTag = (bound: boolean) => {
|
||||||
return (
|
return (
|
||||||
<Tag color={bound ? 'success' : 'default'}>
|
<Tag color={bound ? 'success' : 'default'}>
|
||||||
@ -326,13 +321,18 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderCommandTable = () => {
|
const renderCommandTable = () => {
|
||||||
return (
|
return (
|
||||||
<ATable
|
<AKtTable
|
||||||
|
class="qqbot-account-config-panel__table"
|
||||||
columns={commandColumns}
|
columns={commandColumns}
|
||||||
dataSource={mergedCommandTemplates.value}
|
dataSource={mergedCommandTemplates.value}
|
||||||
loading={loading.value}
|
rowActions={commandRowActions}
|
||||||
pagination={false}
|
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
scroll={{ x: 1200, y: 420 }}
|
showDefaultButtons={false}
|
||||||
|
showFooter={false}
|
||||||
|
showHeader={false}
|
||||||
|
showIndex={false}
|
||||||
|
showPagination={false}
|
||||||
|
showTableSetting={false}
|
||||||
size="small"
|
size="small"
|
||||||
v-slots={{
|
v-slots={{
|
||||||
bodyCell: ({ column, record }: any) => {
|
bodyCell: ({ column, record }: any) => {
|
||||||
@ -350,21 +350,6 @@ export default defineComponent({
|
|||||||
if (column.key === 'bound') {
|
if (column.key === 'bound') {
|
||||||
return renderBoundTag(bound);
|
return renderBoundTag(bound);
|
||||||
}
|
}
|
||||||
if (column.key === 'action') {
|
|
||||||
return (
|
|
||||||
<ASpace>
|
|
||||||
{{
|
|
||||||
default: () =>
|
|
||||||
renderBindAction({
|
|
||||||
bound,
|
|
||||||
name: row.name || row.code,
|
|
||||||
onBind: () => handleCommandBind(row),
|
|
||||||
onUnbind: () => handleCommandUnbind(row),
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
</ASpace>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@ -374,15 +359,20 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderEventTable = () => {
|
const renderEventTable = () => {
|
||||||
return (
|
return (
|
||||||
<ATable
|
<AKtTable
|
||||||
|
class="qqbot-account-config-panel__table"
|
||||||
columns={eventColumns}
|
columns={eventColumns}
|
||||||
dataSource={eventPlugins.value}
|
dataSource={eventPlugins.value}
|
||||||
loading={loading.value}
|
rowActions={eventRowActions}
|
||||||
pagination={false}
|
|
||||||
rowKey={(row: QqbotApi.EventPlugin) =>
|
rowKey={(row: QqbotApi.EventPlugin) =>
|
||||||
`${currentSelfId.value}:${row.key}`
|
`${currentSelfId.value}:${row.key}`
|
||||||
}
|
}
|
||||||
scroll={{ x: 960, y: 420 }}
|
showDefaultButtons={false}
|
||||||
|
showFooter={false}
|
||||||
|
showHeader={false}
|
||||||
|
showIndex={false}
|
||||||
|
showPagination={false}
|
||||||
|
showTableSetting={false}
|
||||||
size="small"
|
size="small"
|
||||||
v-slots={{
|
v-slots={{
|
||||||
bodyCell: ({ column, record }: any) => {
|
bodyCell: ({ column, record }: any) => {
|
||||||
@ -395,21 +385,6 @@ export default defineComponent({
|
|||||||
if (column.key === 'bound') {
|
if (column.key === 'bound') {
|
||||||
return renderBoundTag(row.bound);
|
return renderBoundTag(row.bound);
|
||||||
}
|
}
|
||||||
if (column.key === 'action') {
|
|
||||||
return (
|
|
||||||
<ASpace>
|
|
||||||
{{
|
|
||||||
default: () =>
|
|
||||||
renderBindAction({
|
|
||||||
bound: row.bound,
|
|
||||||
name: row.name,
|
|
||||||
onBind: () => handleEventBind(row),
|
|
||||||
onUnbind: () => handleEventUnbind(row),
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
</ASpace>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@ -419,13 +394,18 @@ export default defineComponent({
|
|||||||
|
|
||||||
const renderRuleTable = () => {
|
const renderRuleTable = () => {
|
||||||
return (
|
return (
|
||||||
<ATable
|
<AKtTable
|
||||||
|
class="qqbot-account-config-panel__table"
|
||||||
columns={ruleColumns}
|
columns={ruleColumns}
|
||||||
dataSource={mergedRuleTemplates.value}
|
dataSource={mergedRuleTemplates.value}
|
||||||
loading={loading.value}
|
rowActions={ruleRowActions}
|
||||||
pagination={false}
|
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
scroll={{ x: 1200, y: 420 }}
|
showDefaultButtons={false}
|
||||||
|
showFooter={false}
|
||||||
|
showHeader={false}
|
||||||
|
showIndex={false}
|
||||||
|
showPagination={false}
|
||||||
|
showTableSetting={false}
|
||||||
size="small"
|
size="small"
|
||||||
v-slots={{
|
v-slots={{
|
||||||
bodyCell: ({ column, record }: any) => {
|
bodyCell: ({ column, record }: any) => {
|
||||||
@ -450,21 +430,6 @@ export default defineComponent({
|
|||||||
if (column.key === 'bound') {
|
if (column.key === 'bound') {
|
||||||
return renderBoundTag(bound);
|
return renderBoundTag(bound);
|
||||||
}
|
}
|
||||||
if (column.key === 'action') {
|
|
||||||
return (
|
|
||||||
<ASpace>
|
|
||||||
{{
|
|
||||||
default: () =>
|
|
||||||
renderBindAction({
|
|
||||||
bound,
|
|
||||||
name: row.name || row.keyword,
|
|
||||||
onBind: () => handleRuleBind(row),
|
|
||||||
onUnbind: () => handleRuleUnbind(row),
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
</ASpace>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@ -487,11 +452,16 @@ export default defineComponent({
|
|||||||
]}
|
]}
|
||||||
v-model:activeKey={activeTab.value}
|
v-model:activeKey={activeTab.value}
|
||||||
/>
|
/>
|
||||||
<div class="qqbot-account-config-panel__content">
|
<ASpin
|
||||||
{activeTab.value === 'command' ? renderCommandTable() : null}
|
class="qqbot-account-config-panel__spin"
|
||||||
{activeTab.value === 'event' ? renderEventTable() : null}
|
spinning={loading.value}
|
||||||
{activeTab.value === 'rule' ? renderRuleTable() : null}
|
>
|
||||||
</div>
|
<div class="qqbot-account-config-panel__content">
|
||||||
|
{activeTab.value === 'command' ? renderCommandTable() : null}
|
||||||
|
{activeTab.value === 'event' ? renderEventTable() : null}
|
||||||
|
{activeTab.value === 'rule' ? renderRuleTable() : null}
|
||||||
|
</div>
|
||||||
|
</ASpin>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -48,6 +48,15 @@
|
|||||||
&__card > .ant-card-body {
|
&__card > .ant-card-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__card .ant-spin-nested-loading,
|
||||||
|
&__card .ant-spin-container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.qqbot-account-config-panel {
|
.qqbot-account-config-panel {
|
||||||
@ -67,8 +76,27 @@
|
|||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__spin,
|
||||||
|
&__spin > .ant-spin-container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 0;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__table {
|
||||||
|
flex: 1 1 0;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +105,7 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,7 +112,7 @@ export default defineComponent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ACard bordered={false} class="qqbot-account-config__card">
|
<ACard class="qqbot-account-config__card" variant="borderless">
|
||||||
<ASpin spinning={loading.value}>
|
<ASpin spinning={loading.value}>
|
||||||
{errorMessage.value ? (
|
{errorMessage.value ? (
|
||||||
<Alert message={errorMessage.value} showIcon type="warning" />
|
<Alert message={errorMessage.value} showIcon type="warning" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user