feat: 账号配置表格头部接入KtTable

This commit is contained in:
sunlei 2026-06-07 22:57:34 +08:00
parent 01743cfc18
commit 5af4b4d297
3 changed files with 143 additions and 169 deletions

View File

@ -32,6 +32,14 @@ const AKtTable = KtTable as any;
const ASpin = Spin as any; const ASpin = Spin as any;
const ATabs = Tabs as any; const ATabs = Tabs as any;
const configTabItems = [
{ key: 'command', label: '在线命令' },
{ key: 'event', label: '事件触发' },
{ key: 'rule', label: '自动回复规则' },
] as const;
type ConfigTabKey = (typeof configTabItems)[number]['key'];
export default defineComponent({ export default defineComponent({
name: 'QqBotAccountConfigPanel', name: 'QqBotAccountConfigPanel',
props: { props: {
@ -41,7 +49,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const activeTab = ref('command'); const activeTab = ref<ConfigTabKey>('command');
const boundCommands = ref<QqbotApi.Command[]>([]); const boundCommands = ref<QqbotApi.Command[]>([]);
const boundRules = ref<QqbotApi.Rule[]>([]); const boundRules = ref<QqbotApi.Rule[]>([]);
const commandTemplates = ref<QqbotApi.Command[]>([]); const commandTemplates = ref<QqbotApi.Command[]>([]);
@ -167,6 +175,28 @@ export default defineComponent({
rowVisible: (row) => boundRuleIds.value.has(row.id), rowVisible: (row) => boundRuleIds.value.has(row.id),
}, },
]; ];
const activeColumns = computed(() => {
if (activeTab.value === 'event') return eventColumns;
if (activeTab.value === 'rule') return ruleColumns;
return commandColumns;
});
const activeRows = computed(() => {
if (activeTab.value === 'event') return eventPlugins.value;
if (activeTab.value === 'rule') return mergedRuleTemplates.value;
return mergedCommandTemplates.value;
});
const activeRowActions = computed(() => {
if (activeTab.value === 'event') return eventRowActions;
if (activeTab.value === 'rule') return ruleRowActions;
return commandRowActions;
});
const activeRowKey = computed(() => {
if (activeTab.value === 'event') {
return (row: QqbotApi.EventPlugin) =>
`${currentSelfId.value}:${row.key}`;
}
return 'id';
});
watch( watch(
currentSelfId, currentSelfId,
@ -319,149 +349,106 @@ export default defineComponent({
); );
}; };
const renderCommandTable = () => { const renderTableTitle = () => {
return ( return (
<AKtTable <div class="qqbot-account-config-panel__table-title">
class="qqbot-account-config-panel__table" <span></span>
columns={commandColumns} <Tag color="processing">{`Self ID${currentSelfId.value || '-'}`}</Tag>
dataSource={mergedCommandTemplates.value} {props.account?.name ? <Tag>{props.account.name}</Tag> : null}
rowActions={commandRowActions} </div>
rowKey="id"
showDefaultButtons={false}
showFooter={false}
showHeader={false}
showIndex={false}
showPagination={false}
showTableSetting={false}
size="small"
v-slots={{
bodyCell: ({ column, record }: any) => {
const row = record as QqbotApi.Command;
const bound = boundCommandIds.value.has(row.id);
if (column.key === 'aliases') {
return row.aliases?.join(' / ') || '-';
}
if (column.key === 'targetType') {
return getOptionLabel(qqbotRuleTargetOptions, row.targetType);
}
if (column.key === 'enabled') {
return renderEnabledTag(row.enabled);
}
if (column.key === 'bound') {
return renderBoundTag(bound);
}
return undefined;
},
}}
/>
); );
}; };
const renderEventTable = () => { const renderHeaderControls = () => {
return ( return (
<AKtTable <div class="kt-table__header-control-group">
class="qqbot-account-config-panel__table" <ATabs
columns={eventColumns} class="kt-table__header-tabs"
dataSource={eventPlugins.value} items={[...configTabItems]}
rowActions={eventRowActions} v-model:activeKey={activeTab.value}
rowKey={(row: QqbotApi.EventPlugin) => />
`${currentSelfId.value}:${row.key}` </div>
}
showDefaultButtons={false}
showFooter={false}
showHeader={false}
showIndex={false}
showPagination={false}
showTableSetting={false}
size="small"
v-slots={{
bodyCell: ({ column, record }: any) => {
const row = record as QqbotApi.EventPlugin;
if (column.key === 'triggerType') {
return row.triggerType === 'message'
? '消息事件'
: row.triggerType;
}
if (column.key === 'bound') {
return renderBoundTag(row.bound);
}
return undefined;
},
}}
/>
); );
}; };
const renderRuleTable = () => { const renderBodyCell = ({ column, record }: any) => {
return ( if (activeTab.value === 'event') {
<AKtTable const row = record as QqbotApi.EventPlugin;
class="qqbot-account-config-panel__table" if (column.key === 'triggerType') {
columns={ruleColumns} return row.triggerType === 'message' ? '消息事件' : row.triggerType;
dataSource={mergedRuleTemplates.value} }
rowActions={ruleRowActions} if (column.key === 'bound') {
rowKey="id" return renderBoundTag(row.bound);
showDefaultButtons={false} }
showFooter={false} return undefined;
showHeader={false} }
showIndex={false}
showPagination={false} if (activeTab.value === 'rule') {
showTableSetting={false} const row = record as QqbotApi.Rule;
size="small" const bound = boundRuleIds.value.has(row.id);
v-slots={{ if (column.key === 'matchType') {
bodyCell: ({ column, record }: any) => { return getOptionLabel(qqbotRuleMatchOptions, row.matchType);
const row = record as QqbotApi.Rule; }
const bound = boundRuleIds.value.has(row.id); if (column.key === 'targetType') {
if (column.key === 'matchType') { return getOptionLabel(qqbotRuleTargetOptions, row.targetType);
return getOptionLabel(qqbotRuleMatchOptions, row.matchType); }
} if (column.key === 'replyContent') {
if (column.key === 'targetType') { return (
return getOptionLabel(qqbotRuleTargetOptions, row.targetType); <span class="qqbot-account-config-panel__ellipsis">
} {row.replyContent || '-'}
if (column.key === 'replyContent') { </span>
return ( );
<span class="qqbot-account-config-panel__ellipsis"> }
{row.replyContent || '-'} if (column.key === 'enabled') {
</span> return renderEnabledTag(row.enabled);
); }
} if (column.key === 'bound') {
if (column.key === 'enabled') { return renderBoundTag(bound);
return renderEnabledTag(row.enabled); }
} return undefined;
if (column.key === 'bound') { }
return renderBoundTag(bound);
} const row = record as QqbotApi.Command;
return undefined; const bound = boundCommandIds.value.has(row.id);
}, if (column.key === 'aliases') {
}} return row.aliases?.join(' / ') || '-';
/> }
); if (column.key === 'targetType') {
return getOptionLabel(qqbotRuleTargetOptions, row.targetType);
}
if (column.key === 'enabled') {
return renderEnabledTag(row.enabled);
}
if (column.key === 'bound') {
return renderBoundTag(bound);
}
return undefined;
}; };
return () => ( return () => (
<div class="qqbot-account-config-panel"> <div class="qqbot-account-config-panel">
<div class="qqbot-account-config-panel__account"> <div class="qqbot-account-config-panel__spin">
<Tag color="processing">Self ID{currentSelfId.value || '-'}</Tag> <ASpin spinning={loading.value}>
{props.account?.name ? <Tag>{props.account.name}</Tag> : null} <AKtTable
class="qqbot-account-config-panel__table"
columns={activeColumns.value}
dataSource={activeRows.value}
rowActions={activeRowActions.value}
rowKey={activeRowKey.value}
showDefaultButtons={false}
showFooter={false}
showIndex={false}
showPagination={false}
showTableSetting={false}
size="small"
v-slots={{
bodyCell: renderBodyCell,
headerControls: renderHeaderControls,
title: renderTableTitle,
}}
/>
</ASpin>
</div> </div>
<ATabs
class="qqbot-account-config-panel__tabs"
items={[
{ key: 'command', label: '在线命令' },
{ key: 'event', label: '事件触发' },
{ key: 'rule', label: '自动回复规则' },
]}
v-model:activeKey={activeTab.value}
/>
<ASpin
class="qqbot-account-config-panel__spin"
spinning={loading.value}
>
<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>
); );
}, },

View File

@ -33,24 +33,14 @@
font-weight: 600; font-weight: 600;
} }
&__card { &__content {
flex: 1; flex: 1;
min-height: 0; min-height: 0;
} }
&__card, &__content,
&__card > .ant-card-body { &__content > .ant-spin-nested-loading,
display: flex; &__content > .ant-spin-nested-loading > .ant-spin-container {
flex-direction: column;
min-height: 0;
}
&__card > .ant-card-body {
flex: 1;
}
&__card .ant-spin-nested-loading,
&__card .ant-spin-container {
display: flex; display: flex;
flex: 1 1 0; flex: 1 1 0;
flex-direction: column; flex-direction: column;
@ -65,19 +55,9 @@
flex-direction: column; flex-direction: column;
min-height: 0; min-height: 0;
&__account {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 10px;
}
&__tabs {
flex: none;
}
&__spin, &__spin,
&__spin > .ant-spin-container { &__spin > .ant-spin-nested-loading,
&__spin > .ant-spin-nested-loading > .ant-spin-container {
display: flex; display: flex;
flex: 1 1 0; flex: 1 1 0;
flex-direction: column; flex-direction: column;
@ -85,19 +65,19 @@
min-height: 0; min-height: 0;
} }
&__content {
display: flex;
flex: 1;
min-width: 0;
min-height: 0;
overflow: hidden;
}
&__table { &__table {
flex: 1 1 0; flex: 1 1 0;
width: 100%; width: 100%;
min-width: 0; min-width: 0;
min-height: 0; min-height: 0;
.kt-table__header {
margin-bottom: 8px;
}
.kt-table__main-content {
padding: 12px;
}
} }
&__ellipsis { &__ellipsis {
@ -108,4 +88,12 @@
vertical-align: bottom; vertical-align: bottom;
white-space: nowrap; white-space: nowrap;
} }
&__table-title {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
min-width: 0;
}
} }

View File

@ -6,7 +6,7 @@ import { useRoute, useRouter } from 'vue-router';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { ArrowLeft } from '@vben/icons'; import { ArrowLeft } from '@vben/icons';
import { Alert, Button, Card, Spin, Tag } from 'antdv-next'; import { Alert, Button, Spin, Tag } from 'antdv-next';
import { getQqbotAccountList } from '#/api/qqbot'; import { getQqbotAccountList } from '#/api/qqbot';
@ -15,7 +15,6 @@ import AccountConfigPanel from './components/AccountConfigPanel';
import './config.scss'; import './config.scss';
const AButton = Button as any; const AButton = Button as any;
const ACard = Card as any;
const ASpin = Spin as any; const ASpin = Spin as any;
export default defineComponent({ export default defineComponent({
@ -112,7 +111,7 @@ export default defineComponent({
</div> </div>
</div> </div>
<ACard class="qqbot-account-config__card" variant="borderless"> <div class="qqbot-account-config__content">
<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" />
@ -120,7 +119,7 @@ export default defineComponent({
<AccountConfigPanel account={account.value} /> <AccountConfigPanel account={account.value} />
)} )}
</ASpin> </ASpin>
</ACard> </div>
</div> </div>
</Page> </Page>
); );