refactor(@vben/web-antd): 优化word模块类型推断

-修复了一些类型定义和数据结构的问题
This commit is contained in:
Kven 2025-06-23 21:25:52 +08:00
parent f32b395e27
commit 25c027f3d8
9 changed files with 176 additions and 64 deletions

View File

@ -52,5 +52,8 @@
"pinia": "catalog:", "pinia": "catalog:",
"vue": "catalog:", "vue": "catalog:",
"vue-router": "catalog:" "vue-router": "catalog:"
},
"devDependencies": {
"@types/markdown-it": "^14.1.2"
} }
} }

View File

@ -24,15 +24,21 @@ export namespace ChatflowApi {
} }
export interface ChatListResult { export interface ChatListResult {
id: string; data: [
name: string; {
inputs: { createAt: string;
[key: string]: any; id: string;
}; inputs: {
status: string; [key: string]: any;
introduction: string; };
createAt: string; introduction: string;
updatedAt: string; name: string;
status: string;
updatedAt: string;
},
];
limit: number;
hasMore: boolean;
} }
export interface deleteParams { export interface deleteParams {
@ -47,6 +53,24 @@ export namespace ChatflowApi {
firstId: string; firstId: string;
limit: string; limit: string;
} }
export interface ChatMessageResult {
data: [
{
answer: string;
conversationId: string;
createdAt: string;
id: string;
inputs: {
[key: string]: any;
};
messageFiles: [];
query: string;
},
];
limit: number;
hasMore: boolean;
}
} }
// 聊天流 // 聊天流
@ -69,7 +93,7 @@ export async function getChatList(
const url = params.appid const url = params.appid
? `/v1/chat/conversations/${params.appid}` ? `/v1/chat/conversations/${params.appid}`
: '/v1/chat/conversations/'; : '/v1/chat/conversations/';
return requestClient.request<ChatflowApi.ChatListResult[]>(url, { return requestClient.request<ChatflowApi.ChatListResult>(url, {
data, data,
method: 'POST', method: 'POST',
}); });
@ -95,5 +119,8 @@ export function getChatflowMessage(
appId: string, appId: string,
data: ChatflowApi.ChatMessageParams, data: ChatflowApi.ChatMessageParams,
) { ) {
return requestClient.post(`/v1/chat/messages/${appId}`, data); return requestClient.post<ChatflowApi.ChatMessageResult>(
`/v1/chat/messages/${appId}`,
data,
);
} }

View File

@ -1,12 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ConversationsProps } from 'ant-design-x-vue'; import type { ConversationsProps } from 'ant-design-x-vue';
import type { PropsHistory } from '../typing'; import type { AppListResult, ModeListResult, PropsHistory } from '../typing';
import { computed, h, ref, watch } from 'vue'; import { computed, h, ref, watch } from 'vue';
import { DeleteOutlined } from '@ant-design/icons-vue'; import { DeleteOutlined } from '@ant-design/icons-vue';
// import { Card, CardContent, CardHeader, CardTitle } from '@vben-core/shadcn-ui';
import { Menu } from 'ant-design-vue'; import { Menu } from 'ant-design-vue';
import { Conversations } from 'ant-design-x-vue'; import { Conversations } from 'ant-design-x-vue';
@ -31,17 +30,23 @@ const conversationsItems = ref(defaultConversationsItems);
const activeKey = ref(defaultConversationsItems.value[0]?.key); const activeKey = ref(defaultConversationsItems.value[0]?.key);
// props.items key=id, label=name, title=name // props.items key=id, label=name, title=name
const transformItems = computed(() => { const transformItems = computed(() => {
return props.temp.map((item) => ({ return props.temp.map((item: AppListResult) => ({
key: item.id, key: item.id,
label: item.name, label: item.name,
title: item.name, title: item.name,
})); }));
}); });
const itemsData = ref(); const itemsData = ref<ModeListResult[]>([
{
title: '',
label: '',
key: '',
},
]);
const handleMenuClick = (item: { key: string }) => { const handleMenuClick = (info: any) => {
const selectedItem = itemsData.value.find((i) => i.key === item.key); const selectedItem = itemsData.value.find((i) => i.key === info.key);
if (selectedItem) { if (selectedItem) {
// title -> name, key -> id // title -> name, key -> id
const transformedItem = { const transformedItem = {
@ -75,7 +80,7 @@ const menuConfig: ConversationsProps['menu'] = (conversation) => ({
}, },
}); });
const selectedKeys = ref([]); const selectedKeys = ref<string[]>([]);
const openKeys = ref([]); const openKeys = ref([]);
// transformItems itemsData // transformItems itemsData
@ -90,7 +95,7 @@ watch(
watch( watch(
() => itemsData.value, () => itemsData.value,
(newVal) => { (newVal) => {
if (newVal && newVal.length > 0) { if (newVal.length > 0 && newVal[0]) {
selectedKeys.value = [newVal[0].key]; selectedKeys.value = [newVal[0].key];
handleMenuClick(newVal[0]); handleMenuClick(newVal[0]);
} }

View File

@ -7,20 +7,14 @@ import type {
import type { DrawerPlacement } from '@vben/common-ui'; import type { DrawerPlacement } from '@vben/common-ui';
import type { Props, ResultItem } from '../typing'; import type { Props, ResultItem, WordTempItem } from '../typing';
import { computed, h, ref, watch } from 'vue'; import { computed, h, ref, watch } from 'vue';
import { useVbenDrawer } from '@vben/common-ui'; import { useVbenDrawer } from '@vben/common-ui';
import { useUserStore } from '@vben/stores'; import { useUserStore } from '@vben/stores';
import { import { EditOutlined, UserOutlined } from '@ant-design/icons-vue';
EditOutlined,
// CloudUploadOutlined,
// PaperClipOutlined,
UserOutlined,
} from '@ant-design/icons-vue';
// import type { VNode } from 'vue';
import { import {
Badge, Badge,
Button, Button,
@ -41,38 +35,41 @@ import {
Sender, Sender,
Welcome, Welcome,
} from 'ant-design-x-vue'; } from 'ant-design-x-vue';
import markdownit from 'markdown-it'; import markdownIt from 'markdown-it';
import WordPreview from './word-preview.vue'; import WordPreview from './word-preview.vue';
defineOptions({ name: 'WordWorkView' }); defineOptions({ name: 'WordWorkView' });
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
item: () => null, item: {
id: '',
name: '',
} as WordTempItem,
itemMessage: Array, itemMessage: Array,
paramsData: () => null, paramsData: Array,
runChatflow: () => async () => ({ runChatFlow: () => async () => ({
data: { data: {
outputs: { outputs: {
result: '', result: '',
}, },
}, },
}), }),
projectInfo: () => ({ projectInfo: {
projectName: '', projectName: '',
projectContext: '', projectContext: '',
projectKeyAvoidTechOrKeyword: '', projectKeyAvoidTechOrKeyword: '',
userInitialInnovationPoint: '', userInitialInnovationPoint: '',
}), },
}); });
const emit = defineEmits(['history']); const emit = defineEmits(['history']);
// markdown // markdown
const md = markdownit({ html: true, breaks: true }); const md = markdownIt({ html: true, breaks: true });
const renderMarkdown: BubbleListProps['roles'][string]['messageRender'] = ( const renderMarkdown: BubbleListProps['roles'][string]['messageRender'] = (
content, content: string,
) => { ) => {
return h(Typography, [ return h(Typography, [
h('div', { h('div', {

View File

@ -1,7 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ResultItem, WordTempItem } from './typing'; import type {
AppListResult,
import type { PPTTempItem } from '#/views/ppt/typing'; ChatListResult,
ResultItem,
WordTempItem,
} from './typing';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
@ -20,11 +23,11 @@ import {
import { WordListView, WordWorkView } from './components'; import { WordListView, WordWorkView } from './components';
const temp = ref([]); const temp = ref<AppListResult[]>([]);
const hitsory = ref([]); const history = ref<ChatListResult[]>([]);
const loading = ref(true); const loading = ref(true);
const params = ref({}); const params = ref([]);
const projectInfo = ref({}); const projectInfo = ref({});
const userStore = useUserStore(); const userStore = useUserStore();
@ -41,7 +44,7 @@ const getLogs = async (appid: string) => {
limit: '9', limit: '9',
}, },
); );
hitsory.value = res.data; history.value = res.data;
loading.value = false; loading.value = false;
}; };
@ -54,7 +57,10 @@ const getTemp = async () => {
} }
}; };
const currentTemp = ref<null | PPTTempItem>(null); const currentTemp = ref<AppListResult>({
id: '',
name: '',
});
const activeKey = ref(''); const activeKey = ref('');
function handleClickMode(item: WordTempItem) { function handleClickMode(item: WordTempItem) {
@ -74,13 +80,13 @@ async function changeLogs(id: string) {
appid: id, appid: id,
}, },
{ {
userId: '1562', userId: userStore.userInfo?.userId || '',
lastId: '', lastId: '',
sortBy: '', sortBy: '',
limit: '9', limit: '9',
}, },
); );
hitsory.value = res.data; history.value = res.data;
activeKey.value = res.data[0].id; activeKey.value = res.data[0].id;
} }
@ -101,9 +107,9 @@ const itemMessage = ref<ResultItem[]>([]);
async function deleteLog(item: any) { async function deleteLog(item: any) {
const res = await deleteChatflow({ const res = await deleteChatflow({
appId: currentTemp.value.id, appId: currentTemp.value.id || '',
conversationId: item, conversationId: item,
userId: '1562', userId: userStore.userInfo?.userId || '',
}); });
if (res.message === '删除成功') { if (res.message === '删除成功') {
message.success('删除成功'); message.success('删除成功');
@ -121,7 +127,7 @@ async function getParameters(id: string) {
async function handleClick(item: string) { async function handleClick(item: string) {
const res = await getChatflowMessage(currentTemp.value.id, { const res = await getChatflowMessage(currentTemp.value.id, {
userId: '1562', userId: userStore.userInfo?.userId || '',
firstId: '', firstId: '',
conversationId: item, conversationId: item,
limit: '', limit: '',
@ -135,7 +141,7 @@ async function handleClick(item: string) {
key: itemMessage.value.length + 1, key: itemMessage.value.length + 1,
role: 'user', // 'user' or 'ai' role: 'user', // 'user' or 'ai'
content: msg.inputs.projectName, content: msg.inputs.projectName,
footer: msg.footer, // footer: msg.footer,
}); });
} }
if (msg.answer) { if (msg.answer) {
@ -161,7 +167,7 @@ onMounted(() => {
<WordListView <WordListView
title="选择模板" title="选择模板"
:temp="temp" :temp="temp"
:items="hitsory" :items="history"
:loading="loading" :loading="loading"
:key="activeKey" :key="activeKey"
@click-mode="handleClickMode" @click-mode="handleClickMode"
@ -173,7 +179,7 @@ onMounted(() => {
<WordWorkView <WordWorkView
:item="currentTemp" :item="currentTemp"
:params-data="params" :params-data="params"
:run-chatflow="sendWord" :run-chat-flow="sendWord"
:item-message="itemMessage" :item-message="itemMessage"
:project-info="projectInfo" :project-info="projectInfo"
@history="changeLogs" @history="changeLogs"

View File

@ -18,7 +18,7 @@ interface WordHistoryItem {
interface ResultItem { interface ResultItem {
key: number; key: number;
role: 'ai' | 'user'; role: 'ai' | 'user';
content: string; content: any;
footer?: any; footer?: any;
} }
@ -48,21 +48,58 @@ interface WorkflowResult {
} }
interface Props { interface Props {
itemMessage?: ResultItem[]; itemMessage?: ResultItem[];
item?: WordTempItem; item?: null | WordTempItem;
paramsData?: object; paramsData?: string[];
runChatflow?: ( runChatFlow?: (
appId: any, appId: any,
context: WorkflowContext, context: WorkflowContext,
) => Promise<WorkflowResult>; ) => Promise<WorkflowResult>;
projectInfo: object; projectInfo: {
projectContext: string;
projectKeyAvoidTechOrKeyword: string;
projectName: string;
userInitialInnovationPoint: string;
};
}
interface AppListResult {
id: string;
name: string;
} }
interface PropsHistory { interface PropsHistory {
temp: any; temp: any;
items?: WordHistoryItem[]; items?: AppListResult[];
key?: string; key?: string;
title: string; title: string;
loading: boolean; loading: boolean;
} }
export type { Props, PropsHistory, ResultItem, WordHistoryItem, WordTempItem }; interface ChatListResult {
id: string;
name: string;
inputs: {
[key: string]: any;
};
status: string;
introduction: string;
createAt: string;
updatedAt: string;
}
interface ModeListResult {
title: string;
label: string;
key: string;
}
export type {
AppListResult,
ChatListResult,
ModeListResult,
Props,
PropsHistory,
ResultItem,
WordHistoryItem,
WordTempItem,
};

View File

@ -3,6 +3,8 @@ import type { DataNode } from 'ant-design-vue/es/tree';
import type { Recordable } from '@vben/types'; import type { Recordable } from '@vben/types';
import type { Dept, DeptList } from '#/views/workflow/typing';
import { ref } from 'vue'; import { ref } from 'vue';
import { useVbenModal, VbenTree } from '@vben/common-ui'; import { useVbenModal, VbenTree } from '@vben/common-ui';
@ -18,7 +20,7 @@ const emits = defineEmits(['success']);
const workflowId = ref(); const workflowId = ref();
const deptData = ref<DataNode[]>([]); const deptData = ref<DataNode[]>([]);
function convertToTreeNode(item: any): DataNode { function convertToTreeNode(item: Dept): DataNode {
return { return {
key: item.id, key: item.id,
title: item.name, title: item.name,
@ -29,7 +31,7 @@ function convertToTreeNode(item: any): DataNode {
async function getDeptList() { async function getDeptList() {
const res = await getAllDeptTree(0); const res = await getAllDeptTree(0);
deptData.value = res.map((item) => convertToTreeNode(item)); deptData.value = res.map((item: Dept) => convertToTreeNode(item));
} }
const [Form, formApi] = useVbenForm({ const [Form, formApi] = useVbenForm({
@ -39,8 +41,6 @@ const [Form, formApi] = useVbenForm({
const [Modal, modalApi] = useVbenModal({ const [Modal, modalApi] = useVbenModal({
async onConfirm() { async onConfirm() {
// const values = await formApi;
if (!formApi.form.values.deptIds) return;
const deptIds = formApi.form.values.deptIds; const deptIds = formApi.form.values.deptIds;
modalApi.lock(); modalApi.lock();
try { try {
@ -52,7 +52,7 @@ const [Modal, modalApi] = useVbenModal({
message: '操作成功', message: '操作成功',
}); });
emits('success'); emits('success');
modalApi.close(); await modalApi.close();
} finally { } finally {
modalApi.lock(false); modalApi.lock(false);
} }
@ -61,7 +61,7 @@ const [Modal, modalApi] = useVbenModal({
if (isOpen) { if (isOpen) {
workflowId.value = modalApi.getData().id; workflowId.value = modalApi.getData().id;
const res = await linkDetail(workflowId.value); const res = await linkDetail(workflowId.value);
const deptIds = res.map((item) => item.deptId); const deptIds = res.map((item: DeptList) => item.deptId);
await getDeptList(); await getDeptList();
// deptIds // deptIds
formApi.form.setValues({ formApi.form.setValues({

View File

@ -0,0 +1,15 @@
interface Dept {
id: number;
pid?: number;
createTime: string;
name: string;
enabled: string;
children: Dept[];
}
interface DeptList {
workflowId: string;
deptId: number;
}
export type { Dept, DeptList };

View File

@ -673,6 +673,10 @@ importers:
vue-router: vue-router:
specifier: 'catalog:' specifier: 'catalog:'
version: 4.5.1(vue@3.5.13(typescript@5.8.3)) version: 4.5.1(vue@3.5.13(typescript@5.8.3))
devDependencies:
'@types/markdown-it':
specifier: ^14.1.2
version: 14.1.2
internal/lint-configs/commitlint-config: internal/lint-configs/commitlint-config:
dependencies: dependencies:
@ -3889,6 +3893,9 @@ packages:
'@types/json-schema@7.0.15': '@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
'@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
'@types/lodash.clonedeep@4.5.9': '@types/lodash.clonedeep@4.5.9':
resolution: {integrity: sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==} resolution: {integrity: sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==}
@ -3904,6 +3911,12 @@ packages:
'@types/lodash@4.17.16': '@types/lodash@4.17.16':
resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
'@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
'@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
'@types/minimatch@3.0.5': '@types/minimatch@3.0.5':
resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
@ -12784,6 +12797,8 @@ snapshots:
'@types/json-schema@7.0.15': {} '@types/json-schema@7.0.15': {}
'@types/linkify-it@5.0.0': {}
'@types/lodash.clonedeep@4.5.9': '@types/lodash.clonedeep@4.5.9':
dependencies: dependencies:
'@types/lodash': 4.17.16 '@types/lodash': 4.17.16
@ -12802,6 +12817,13 @@ snapshots:
'@types/lodash@4.17.16': {} '@types/lodash@4.17.16': {}
'@types/markdown-it@14.1.2':
dependencies:
'@types/linkify-it': 5.0.0
'@types/mdurl': 2.0.0
'@types/mdurl@2.0.0': {}
'@types/minimatch@3.0.5': {} '@types/minimatch@3.0.5': {}
'@types/node@12.20.55': {} '@types/node@12.20.55': {}