import type { TableColumnType } from 'antdv-next'; import type { PropType } from 'vue'; import type { QqbotApi } from '#/api/qqbot'; import type { KtTableRowAction } from '#/components/ktTable'; import { computed, defineComponent, ref, watch } from 'vue'; import { message, Spin, Tabs, Tag } from 'antdv-next'; import { bindQqbotAccountCommand, bindQqbotAccountRule, bindQqbotEventPlugin, getQqbotCommandList, getQqbotEventPluginList, getQqbotRuleList, unbindQqbotAccountCommand, unbindQqbotAccountRule, unbindQqbotEventPlugin, } from '#/api/qqbot'; import { KtTable } from '#/components/ktTable'; import { getOptionLabel, qqbotRuleMatchOptions, qqbotRuleTargetOptions, } from '../../modules/options'; const AKtTable = KtTable as any; const ASpin = Spin 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({ name: 'QqBotAccountConfigPanel', props: { account: { default: undefined, type: Object as PropType, }, }, setup(props) { const activeTab = ref('command'); const boundCommands = ref([]); const boundRules = ref([]); const commandTemplates = ref([]); const eventPlugins = ref([]); const loading = ref(false); const ruleTemplates = ref([]); const currentSelfId = computed(() => props.account?.selfId || ''); const boundCommandIds = computed( () => new Set(boundCommands.value.map((item) => item.id)), ); const boundRuleIds = computed( () => new Set(boundRules.value.map((item) => item.id)), ); const mergedCommandTemplates = computed(() => mergeById(commandTemplates.value, boundCommands.value), ); const mergedRuleTemplates = computed(() => mergeById(ruleTemplates.value, boundRules.value), ); const commandColumns: Array> = [ { dataIndex: 'name', key: 'name', title: '命令模板', width: 160 }, { dataIndex: 'code', key: 'code', title: '命令编码', width: 140 }, { dataIndex: 'aliases', key: 'aliases', title: '别名', width: 200 }, { dataIndex: 'pluginKey', key: 'pluginKey', title: '插件', width: 140 }, { dataIndex: 'targetType', key: 'targetType', title: '目标范围', width: 100, }, { dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 }, { dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 }, ]; const commandRowActions: Array> = [ { key: 'bind', label: '绑定', onClick: async (row) => handleCommandBind(row), rowVisible: (row) => !boundCommandIds.value.has(row.id), }, { 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: Array> = [ { dataIndex: 'name', key: 'name', title: '插件模板', width: 160 }, { dataIndex: 'key', key: 'key', title: '插件 Key', width: 160 }, { dataIndex: 'triggerType', key: 'triggerType', title: '触发类型', width: 100, }, { dataIndex: 'description', key: 'description', title: '说明', width: 320, }, { dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 }, ]; const eventRowActions: Array> = [ { key: 'bind', label: '绑定', onClick: async (row) => handleEventBind(row), rowVisible: (row) => !row.bound, }, { confirm: (row) => `确认从当前账号解绑「${row.name}」吗?`, danger: true, key: 'unbind', label: '解绑', onClick: async (row) => handleEventUnbind(row), rowVisible: (row) => row.bound, }, ]; const ruleColumns: Array> = [ { dataIndex: 'name', key: 'name', title: '规则模板', width: 160 }, { dataIndex: 'keyword', key: 'keyword', title: '关键词', width: 180 }, { dataIndex: 'matchType', key: 'matchType', title: '匹配方式', width: 110, }, { dataIndex: 'targetType', key: 'targetType', title: '目标范围', width: 100, }, { dataIndex: 'replyContent', key: 'replyContent', title: '回复模板', width: 320, }, { dataIndex: 'enabled', key: 'enabled', title: '模板状态', width: 100 }, { dataIndex: 'bound', key: 'bound', title: '绑定状态', width: 100 }, ]; const ruleRowActions: Array> = [ { key: 'bind', label: '绑定', onClick: async (row) => handleRuleBind(row), rowVisible: (row) => !boundRuleIds.value.has(row.id), }, { confirm: (row) => `确认从当前账号解绑「${row.name || row.keyword}」吗?`, danger: true, key: 'unbind', label: '解绑', onClick: async (row) => handleRuleUnbind(row), 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( currentSelfId, (selfId) => { if (!selfId) { boundCommands.value = []; boundRules.value = []; commandTemplates.value = []; eventPlugins.value = []; ruleTemplates.value = []; return; } void refreshAll(); }, { immediate: true }, ); async function refreshAll() { loading.value = true; try { await Promise.all([ refreshCommandTemplates(), refreshEventPlugins(), refreshRuleTemplates(), ]); } finally { loading.value = false; } } async function refreshCommandTemplates() { const [templateResult, boundResult] = await Promise.all([ getQqbotCommandList({ pageNo: 1, pageSize: 500 }), getQqbotCommandList({ pageNo: 1, pageSize: 500, selfId: currentSelfId.value, }), ]); commandTemplates.value = templateResult.list || []; boundCommands.value = boundResult.list || []; } async function refreshCommandBindings() { const result = await getQqbotCommandList({ pageNo: 1, pageSize: 500, selfId: currentSelfId.value, }); boundCommands.value = result.list || []; } async function refreshEventPlugins() { eventPlugins.value = await getQqbotEventPluginList({ selfId: currentSelfId.value, }); } async function refreshRuleTemplates() { const [templateResult, boundResult] = await Promise.all([ getQqbotRuleList({ pageNo: 1, pageSize: 500 }), getQqbotRuleList({ pageNo: 1, pageSize: 500, selfId: currentSelfId.value, }), ]); ruleTemplates.value = templateResult.list || []; boundRules.value = boundResult.list || []; } async function refreshRuleBindings() { const result = await getQqbotRuleList({ pageNo: 1, pageSize: 500, selfId: currentSelfId.value, }); boundRules.value = result.list || []; } async function handleCommandBind(row: QqbotApi.Command) { if (!ensureSelfId()) return; await bindQqbotAccountCommand(currentSelfId.value, row.id); message.success('命令已绑定到当前账号'); await refreshCommandBindings(); } async function handleCommandUnbind(row: QqbotApi.Command) { if (!ensureSelfId()) return; await unbindQqbotAccountCommand(currentSelfId.value, row.id); message.success('命令已从当前账号解绑'); await refreshCommandBindings(); } async function handleEventBind(row: QqbotApi.EventPlugin) { if (!ensureSelfId()) return; await bindQqbotEventPlugin(currentSelfId.value, row.key); message.success('事件插件已绑定到当前账号'); await refreshEventPlugins(); } async function handleEventUnbind(row: QqbotApi.EventPlugin) { if (!ensureSelfId()) return; await unbindQqbotEventPlugin(currentSelfId.value, row.key); message.success('事件插件已从当前账号解绑'); await refreshEventPlugins(); } async function handleRuleBind(row: QqbotApi.Rule) { if (!ensureSelfId()) return; await bindQqbotAccountRule(currentSelfId.value, row.id); message.success('规则已绑定到当前账号'); await refreshRuleBindings(); } async function handleRuleUnbind(row: QqbotApi.Rule) { if (!ensureSelfId()) return; await unbindQqbotAccountRule(currentSelfId.value, row.id); message.success('规则已从当前账号解绑'); await refreshRuleBindings(); } function ensureSelfId() { if (currentSelfId.value) return true; message.warning('缺少账号 Self ID,请从账号连接列表进入配置页'); return false; } function mergeById(templates: T[], bound: T[]) { const map = new Map(); templates.forEach((item) => map.set(item.id, item)); bound.forEach((item) => { if (!map.has(item.id)) map.set(item.id, item); }); return [...map.values()]; } const renderBoundTag = (bound: boolean) => { return ( {bound ? '已绑定' : '未绑定'} ); }; const renderEnabledTag = (enabled: boolean) => { return ( {enabled ? '启用' : '停用'} ); }; const renderTableTitle = () => { return ( ); }; const renderHeaderControls = () => { return (
); }; const renderBodyCell = ({ column, record }: any) => { if (activeTab.value === 'event') { 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; } if (activeTab.value === 'rule') { const row = record as QqbotApi.Rule; const bound = boundRuleIds.value.has(row.id); if (column.key === 'matchType') { return getOptionLabel(qqbotRuleMatchOptions, row.matchType); } if (column.key === 'targetType') { return getOptionLabel(qqbotRuleTargetOptions, row.targetType); } if (column.key === 'replyContent') { return ( ); } if (column.key === 'enabled') { return renderEnabledTag(row.enabled); } if (column.key === 'bound') { return renderBoundTag(bound); } return undefined; } 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; }; return () => ( ); }, });