pull/146/head^2
xingyu4j 2025-06-16 16:59:04 +08:00
parent d09b993bc8
commit 014785a1ad
71 changed files with 447 additions and 423 deletions

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Item } from './ui/typeing'; import type { Item } from './ui/typing';
import { onMounted, onUnmounted, ref } from 'vue'; import { onMounted, onUnmounted, ref } from 'vue';

View File

@ -0,0 +1,2 @@
export { default as Tinyflow } from './tinyflow.vue';
export * from './ui/typing';

View File

@ -1,21 +1,21 @@
export declare type Item = { export interface Item {
children?: Item[]; children?: Item[];
label: string; label: string;
value: number | string; value: number | string;
}; }
export type Position = { export interface Position {
x: number; x: number;
y: number; y: number;
}; }
export type Viewport = { export interface Viewport {
x: number; x: number;
y: number; y: number;
zoom: number; zoom: number;
}; }
export type Node = { export interface Node {
data?: Record<string, any>; data?: Record<string, any>;
draggable?: boolean; draggable?: boolean;
height?: number; height?: number;
@ -24,23 +24,23 @@ export type Node = {
selected?: boolean; selected?: boolean;
type?: string; type?: string;
width?: number; width?: number;
}; }
export type Edge = { export interface Edge {
animated?: boolean; animated?: boolean;
id: string; id: string;
label?: string; label?: string;
source: string; source: string;
target: string; target: string;
type?: string; type?: string;
}; }
export type TinyflowData = Partial<{ export type TinyflowData = Partial<{
edges: Edge[]; edges: Edge[];
nodes: Node[]; nodes: Node[];
viewport: Viewport; viewport: Viewport;
}>; }>;
export declare type TinyflowOptions = { export interface TinyflowOptions {
data?: TinyflowData; data?: TinyflowData;
element: Element | string; element: Element | string;
provider?: { provider?: {
@ -48,7 +48,7 @@ export declare type TinyflowOptions = {
knowledge?: () => Item[] | Promise<Item[]>; knowledge?: () => Item[] | Promise<Item[]>;
llm?: () => Item[] | Promise<Item[]>; llm?: () => Item[] | Promise<Item[]>;
}; };
}; }
export declare class Tinyflow { export declare class Tinyflow {
private _init; private _init;
@ -66,5 +66,3 @@ export declare class Tinyflow {
getOptions(): TinyflowOptions; getOptions(): TinyflowOptions;
setData(data: TinyflowData): void; setData(data: TinyflowData): void;
} }
export {};

View File

@ -0,0 +1,3 @@
export { default as MarkdownView } from './markdown-view.vue';
export * from './typing';

View File

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { MarkdownViewProps } from './typing';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { MarkdownIt } from '@vben/plugins/markmap'; import { MarkdownIt } from '@vben/plugins/markmap';
@ -10,15 +12,10 @@ import hljs from 'highlight.js';
import 'highlight.js/styles/vs2015.min.css'; import 'highlight.js/styles/vs2015.min.css';
// //
const props = defineProps({ const props = defineProps<MarkdownViewProps>();
content: {
type: String,
required: true,
},
});
const { copy } = useClipboard(); // copy const { copy } = useClipboard(); // copy
const contentRef = ref(); const contentRef = ref<HTMLElement | null>(null);
const md = new MarkdownIt({ const md = new MarkdownIt({
highlight(str, lang) { highlight(str, lang) {
@ -40,7 +37,7 @@ const renderedMarkdown = computed(() => {
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {
// copy // copy
contentRef.value.addEventListener('click', (e: any) => { contentRef.value?.addEventListener('click', (e: any) => {
if (e.target.id === 'copy') { if (e.target.id === 'copy') {
copy(e.target?.dataset?.copy); copy(e.target?.dataset?.copy);
message.success('复制成功!'); message.success('复制成功!');

View File

@ -0,0 +1,3 @@
export type MarkdownViewProps = {
content: string;
};

View File

@ -28,7 +28,6 @@ const props = defineProps({
default: null, default: null,
}, },
}); });
/** 新建对话 */
// //
const emits = defineEmits([ const emits = defineEmits([
@ -37,9 +36,11 @@ const emits = defineEmits([
'onConversationClear', 'onConversationClear',
'onConversationDelete', 'onConversationDelete',
]); ]);
const [Drawer, drawerApi] = useVbenDrawer({ const [Drawer, drawerApi] = useVbenDrawer({
connectedComponent: RoleRepository, connectedComponent: RoleRepository,
}); });
// //
const searchName = ref<string>(''); // const searchName = ref<string>(''); //
const activeConversationId = ref<null | number>(null); // null const activeConversationId = ref<null | number>(null); // null
@ -50,7 +51,7 @@ const loading = ref<boolean>(false); // 加载中
const loadingTime = ref<any>(); const loadingTime = ref<any>();
/** 搜索对话 */ /** 搜索对话 */
const searchConversation = async () => { async function searchConversation() {
// //
if (searchName.value.trim().length === 0) { if (searchName.value.trim().length === 0) {
conversationMap.value = await getConversationGroupByCreateTime( conversationMap.value = await getConversationGroupByCreateTime(
@ -64,25 +65,25 @@ const searchConversation = async () => {
conversationMap.value = conversationMap.value =
await getConversationGroupByCreateTime(filterValues); await getConversationGroupByCreateTime(filterValues);
} }
}; }
/** 点击对话 */ /** 点击对话 */
const handleConversationClick = async (id: number) => { async function handleConversationClick(id: number) {
// //
const filterConversation = conversationList.value.find((item) => { const filterConversation = conversationList.value.find((item) => {
return item.id === id; return item.id === id;
}); });
// onConversationClick // onConversationClick
// noinspection JSVoidFunctionReturnValueUsed // noinspection JSVoidFunctionReturnValueUsed
const success = emits('onConversationClick', filterConversation); const success = emits('onConversationClick', filterConversation) as any;
// //
if (success) { if (success) {
activeConversationId.value = id; activeConversationId.value = id;
} }
}; }
/** 获取对话列表 */ /** 获取对话列表 */
const getChatConversationList = async () => { async function getChatConversationList() {
try { try {
// //
loadingTime.value = setTimeout(() => { loadingTime.value = setTimeout(() => {
@ -114,12 +115,12 @@ const getChatConversationList = async () => {
// //
loading.value = false; loading.value = false;
} }
}; }
/** 按照 creteTime 创建时间,进行分组 */ /** 按照 creteTime 创建时间,进行分组 */
const getConversationGroupByCreateTime = async ( async function getConversationGroupByCreateTime(
list: AiChatConversationApi.ChatConversationVO[], list: AiChatConversationApi.ChatConversationVO[],
) => { ) {
// (30) // (30)
// noinspection NonAsciiCharacters // noinspection NonAsciiCharacters
const groupMap: any = { const groupMap: any = {
@ -159,8 +160,9 @@ const getConversationGroupByCreateTime = async (
} }
} }
return groupMap; return groupMap;
}; }
const createConversation = async () => {
async function createConversation() {
// 1. // 1.
const conversationId = await createChatConversationMy( const conversationId = await createChatConversationMy(
{} as unknown as AiChatConversationApi.ChatConversationVO, {} as unknown as AiChatConversationApi.ChatConversationVO,
@ -171,12 +173,12 @@ const createConversation = async () => {
await handleConversationClick(conversationId); await handleConversationClick(conversationId);
// 4. // 4.
emits('onConversationCreate'); emits('onConversationCreate');
}; }
/** 修改对话的标题 */ /** 修改对话的标题 */
const updateConversationTitle = async ( async function updateConversationTitle(
conversation: AiChatConversationApi.ChatConversationVO, conversation: AiChatConversationApi.ChatConversationVO,
) => { ) {
// 1. // 1.
prompt({ prompt({
async beforeClose(scope) { async beforeClose(scope) {
@ -225,12 +227,12 @@ const updateConversationTitle = async (
title: '修改标题', title: '修改标题',
modelPropName: 'value', modelPropName: 'value',
}); });
}; }
/** 删除聊天对话 */ /** 删除聊天对话 */
const deleteChatConversation = async ( async function deleteChatConversation(
conversation: AiChatConversationApi.ChatConversationVO, conversation: AiChatConversationApi.ChatConversationVO,
) => { ) {
try { try {
// //
await confirm(`是否确认删除对话 - ${conversation.title}?`); await confirm(`是否确认删除对话 - ${conversation.title}?`);
@ -242,8 +244,9 @@ const deleteChatConversation = async (
// //
emits('onConversationDelete', conversation); emits('onConversationDelete', conversation);
} catch {} } catch {}
}; }
const handleClearConversation = async () => {
async function handleClearConversation() {
try { try {
await confirm('确认后对话会全部清空,置顶的对话除外。'); await confirm('确认后对话会全部清空,置顶的对话除外。');
await deleteChatConversationMyByUnpinned(); await deleteChatConversationMyByUnpinned();
@ -255,18 +258,18 @@ const handleClearConversation = async () => {
// //
emits('onConversationClear'); emits('onConversationClear');
} catch {} } catch {}
}; }
/** 对话置顶 */ /** 对话置顶 */
const handleTop = async ( async function handleTop(
conversation: AiChatConversationApi.ChatConversationVO, conversation: AiChatConversationApi.ChatConversationVO,
) => { ) {
// //
conversation.pinned = !conversation.pinned; conversation.pinned = !conversation.pinned;
await updateChatConversationMy(conversation); await updateChatConversationMy(conversation);
// //
await getChatConversationList(); await getChatConversationList();
}; }
// ============ ============ // ============ ============

View File

@ -47,10 +47,10 @@ const documentList = computed(() => {
}); });
/** 点击 document 处理 */ /** 点击 document 处理 */
const handleClick = (doc: any) => { function handleClick(doc: any) {
document.value = doc; document.value = doc;
dialogVisible.value = true; dialogVisible.value = true;
}; }
</script> </script>
<template> <template>

View File

@ -14,7 +14,7 @@ import { useClipboard } from '@vueuse/core';
import { Avatar, Button, message } from 'ant-design-vue'; import { Avatar, Button, message } from 'ant-design-vue';
import { deleteChatMessage } from '#/api/ai/chat/message'; import { deleteChatMessage } from '#/api/ai/chat/message';
import MarkdownView from '#/components/MarkdownView/index.vue'; import { MarkdownView } from '#/components/markdown-view';
import MessageKnowledge from './MessageKnowledge.vue'; import MessageKnowledge from './MessageKnowledge.vue';
// props // props
@ -67,44 +67,44 @@ function handleScroll() {
} }
/** 回到底部 */ /** 回到底部 */
const handleGoBottom = async () => { async function handleGoBottom() {
const scrollContainer = messageContainer.value; const scrollContainer = messageContainer.value;
scrollContainer.scrollTop = scrollContainer.scrollHeight; scrollContainer.scrollTop = scrollContainer.scrollHeight;
}; }
/** 回到顶部 */ /** 回到顶部 */
const handlerGoTop = async () => { async function handlerGoTop() {
const scrollContainer = messageContainer.value; const scrollContainer = messageContainer.value;
scrollContainer.scrollTop = 0; scrollContainer.scrollTop = 0;
}; }
defineExpose({ scrollToBottom, handlerGoTop }); // parent defineExpose({ scrollToBottom, handlerGoTop }); // parent
// ============ ============== // ============ ==============
/** 复制 */ /** 复制 */
const copyContent = async (content: string) => { async function copyContent(content: string) {
await copy(content); await copy(content);
message.success('复制成功!'); message.success('复制成功!');
}; }
/** 删除 */ /** 删除 */
const onDelete = async (id: number) => { async function onDelete(id: number) {
// message // message
await deleteChatMessage(id); await deleteChatMessage(id);
message.success('删除成功!'); message.success('删除成功!');
// //
emits('onDeleteSuccess'); emits('onDeleteSuccess');
}; }
/** 刷新 */ /** 刷新 */
const onRefresh = async (message: AiChatMessageApi.ChatMessageVO) => { async function onRefresh(message: AiChatMessageApi.ChatMessageVO) {
emits('onRefresh', message); emits('onRefresh', message);
}; }
/** 编辑 */ /** 编辑 */
const onEdit = async (message: AiChatMessageApi.ChatMessageVO) => { async function onEdit(message: AiChatMessageApi.ChatMessageVO) {
emits('onEdit', message); emits('onEdit', message);
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {

View File

@ -11,9 +11,9 @@ const promptList = [
prompt: '写一首好听的诗歌?', prompt: '写一首好听的诗歌?',
}, },
]; /** 选中 prompt 点击 */ ]; /** 选中 prompt 点击 */
const handlerPromptClick = async (prompt: any) => { async function handlerPromptClick(prompt: any) {
emits('onPrompt', prompt.prompt); emits('onPrompt', prompt.prompt);
}; }
</script> </script>
<template> <template>
<div class="relative flex h-full w-full flex-row justify-center"> <div class="relative flex h-full w-full flex-row justify-center">

View File

@ -4,9 +4,9 @@ import { Button } from 'ant-design-vue';
const emits = defineEmits(['onNewConversation']); const emits = defineEmits(['onNewConversation']);
/** 新建 conversation 聊天对话 */ /** 新建 conversation 聊天对话 */
const handlerNewChat = () => { function handlerNewChat() {
emits('onNewConversation'); emits('onNewConversation');
}; }
</script> </script>
<template> <template>

View File

@ -19,9 +19,9 @@ defineProps({
const emits = defineEmits(['onCategoryClick']); const emits = defineEmits(['onCategoryClick']);
/** 处理分类点击事件 */ /** 处理分类点击事件 */
const handleCategoryClick = async (category: string) => { async function handleCategoryClick(category: string) {
emits('onCategoryClick', category); emits('onCategoryClick', category);
}; }
</script> </script>
<template> <template>

View File

@ -33,7 +33,7 @@ const emits = defineEmits(['onDelete', 'onEdit', 'onUse', 'onPage']);
const tabsRef = ref<any>(); const tabsRef = ref<any>();
/** 操作:编辑、删除 */ /** 操作:编辑、删除 */
const handleMoreClick = async (data: any) => { async function handleMoreClick(data: any) {
const type = data[0]; const type = data[0];
const role = data[1]; const role = data[1];
if (type === 'delete') { if (type === 'delete') {
@ -41,22 +41,22 @@ const handleMoreClick = async (data: any) => {
} else { } else {
emits('onEdit', role); emits('onEdit', role);
} }
}; }
/** 选中 */ /** 选中 */
const handleUseClick = (role: any) => { function handleUseClick(role: any) {
emits('onUse', role); emits('onUse', role);
}; }
/** 滚动 */ /** 滚动 */
const handleTabsScroll = async () => { async function handleTabsScroll() {
if (tabsRef.value) { if (tabsRef.value) {
const { scrollTop, scrollHeight, clientHeight } = tabsRef.value; const { scrollTop, scrollHeight, clientHeight } = tabsRef.value;
if (scrollTop + clientHeight >= scrollHeight - 20 && !props.loading) { if (scrollTop + clientHeight >= scrollHeight - 20 && !props.loading) {
await emits('onPage'); await emits('onPage');
} }
} }
}; }
</script> </script>
<template> <template>

View File

@ -46,15 +46,15 @@ const activeCategory = ref<string>('全部'); // 选择中的分类
const categoryList = ref<string[]>([]); // const categoryList = ref<string[]>([]); //
/** tabs 点击 */ /** tabs 点击 */
const handleTabsClick = async (tab: any) => { async function handleTabsClick(tab: any) {
// //
activeTab.value = tab; activeTab.value = tab;
// //
await getActiveTabsRole(); await getActiveTabsRole();
}; }
/** 获取 my role 我的角色 */ /** 获取 my role 我的角色 */
const getMyRole = async (append?: boolean) => { async function getMyRole(append?: boolean) {
const params: AiModelChatRoleApi.ChatRolePageReqVO = { const params: AiModelChatRoleApi.ChatRolePageReqVO = {
...myRoleParams, ...myRoleParams,
name: search.value, name: search.value,
@ -66,10 +66,10 @@ const getMyRole = async (append?: boolean) => {
} else { } else {
myRoleList.value = list; myRoleList.value = list;
} }
}; }
/** 获取 public role 公共角色 */ /** 获取 public role 公共角色 */
const getPublicRole = async (append?: boolean) => { async function getPublicRole(append?: boolean) {
const params: AiModelChatRoleApi.ChatRolePageReqVO = { const params: AiModelChatRoleApi.ChatRolePageReqVO = {
...publicRoleParams, ...publicRoleParams,
category: activeCategory.value === '全部' ? '' : activeCategory.value, category: activeCategory.value === '全部' ? '' : activeCategory.value,
@ -82,10 +82,10 @@ const getPublicRole = async (append?: boolean) => {
} else { } else {
publicRoleList.value = list; publicRoleList.value = list;
} }
}; }
/** 获取选中的 tabs 角色 */ /** 获取选中的 tabs 角色 */
const getActiveTabsRole = async () => { async function getActiveTabsRole() {
if (activeTab.value === 'my-role') { if (activeTab.value === 'my-role') {
myRoleParams.pageNo = 1; myRoleParams.pageNo = 1;
await getMyRole(); await getMyRole();
@ -93,43 +93,44 @@ const getActiveTabsRole = async () => {
publicRoleParams.pageNo = 1; publicRoleParams.pageNo = 1;
await getPublicRole(); await getPublicRole();
} }
}; }
/** 获取角色分类列表 */ /** 获取角色分类列表 */
const getRoleCategoryList = async () => { async function getRoleCategoryList() {
categoryList.value = ['全部', ...(await getCategoryList())]; categoryList.value = ['全部', ...(await getCategoryList())];
}; }
/** 处理分类点击 */ /** 处理分类点击 */
const handlerCategoryClick = async (category: string) => { async function handlerCategoryClick(category: string) {
// //
activeCategory.value = category; activeCategory.value = category;
// //
await getActiveTabsRole(); await getActiveTabsRole();
}; }
const handlerAddRole = async () => { async function handlerAddRole() {
formModalApi.setData({ formType: 'my-create' }).open(); formModalApi.setData({ formType: 'my-create' }).open();
}; }
/** 编辑角色 */ /** 编辑角色 */
const handlerCardEdit = async (role: any) => { async function handlerCardEdit(role: any) {
formModalApi.setData({ formType: 'my-update', id: role.id }).open(); formModalApi.setData({ formType: 'my-update', id: role.id }).open();
}; }
/** 添加角色成功 */ /** 添加角色成功 */
const handlerAddRoleSuccess = async () => { async function handlerAddRoleSuccess() {
// //
await getActiveTabsRole(); await getActiveTabsRole();
}; }
/** 删除角色 */ /** 删除角色 */
const handlerCardDelete = async (role: any) => { async function handlerCardDelete(role: any) {
await deleteMy(role.id); await deleteMy(role.id);
// //
await getActiveTabsRole(); await getActiveTabsRole();
}; }
/** 角色分页:获取下一页 */ /** 角色分页:获取下一页 */
const handlerCardPage = async (type: string) => { async function handlerCardPage(type: string) {
try { try {
loading.value = true; loading.value = true;
if (type === 'public') { if (type === 'public') {
@ -142,10 +143,10 @@ const handlerCardPage = async (type: string) => {
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; }
/** 选择 card 角色:新建聊天对话 */ /** 选择 card 角色:新建聊天对话 */
const handlerCardUse = async (role: any) => { async function handlerCardUse(role: any) {
// 1. // 1.
const data: AiChatConversationApi.ChatConversationVO = { const data: AiChatConversationApi.ChatConversationVO = {
roleId: role.id, roleId: role.id,
@ -159,7 +160,8 @@ const handlerCardUse = async (role: any) => {
conversationId, conversationId,
}, },
}); });
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {
// //

View File

@ -61,7 +61,7 @@ const receiveMessageDisplayedText = ref('');
// =========== =========== // =========== ===========
/** 获取对话信息 */ /** 获取对话信息 */
const getConversation = async (id: null | number) => { async function getConversation(id: null | number) {
if (!id) { if (!id) {
return; return;
} }
@ -72,7 +72,7 @@ const getConversation = async (id: null | number) => {
} }
activeConversation.value = conversation; activeConversation.value = conversation;
activeConversationId.value = conversation.id; activeConversationId.value = conversation.id;
}; }
/** /**
* 点击某个对话 * 点击某个对话
@ -80,9 +80,9 @@ const getConversation = async (id: null | number) => {
* @param conversation 选中的对话 * @param conversation 选中的对话
* @return 是否切换成功 * @return 是否切换成功
*/ */
const handleConversationClick = async ( async function handleConversationClick(
conversation: AiChatConversationApi.ChatConversationVO, conversation: AiChatConversationApi.ChatConversationVO,
) => { ) {
// //
if (conversationInProgress.value) { if (conversationInProgress.value) {
alert('对话中,不允许切换!'); alert('对话中,不允许切换!');
@ -99,20 +99,20 @@ const handleConversationClick = async (
// //
prompt.value = ''; prompt.value = '';
return true; return true;
}; }
/** 删除某个对话*/ /** 删除某个对话*/
const handlerConversationDelete = async ( async function handlerConversationDelete(
delConversation: AiChatConversationApi.ChatConversationVO, delConversation: AiChatConversationApi.ChatConversationVO,
) => { ) {
// //
if (activeConversationId.value === delConversation.id) { if (activeConversationId.value === delConversation.id) {
await handleConversationClear(); await handleConversationClear();
} }
}; }
/** 清空选中的对话 */ /** 清空选中的对话 */
const handleConversationClear = async () => { async function handleConversationClear() {
// //
if (conversationInProgress.value) { if (conversationInProgress.value) {
alert('对话中,不允许切换!'); alert('对话中,不允许切换!');
@ -121,31 +121,31 @@ const handleConversationClear = async () => {
activeConversationId.value = null; activeConversationId.value = null;
activeConversation.value = null; activeConversation.value = null;
activeMessageList.value = []; activeMessageList.value = [];
}; }
const openChatConversationUpdateForm = async () => { async function openChatConversationUpdateForm() {
formModalApi.setData({ id: activeConversationId.value }).open(); formModalApi.setData({ id: activeConversationId.value }).open();
}; }
const handleConversationUpdateSuccess = async () => { async function handleConversationUpdateSuccess() {
// //
await getConversation(activeConversationId.value); await getConversation(activeConversationId.value);
}; }
/** 处理聊天对话的创建成功 */ /** 处理聊天对话的创建成功 */
const handleConversationCreate = async () => { async function handleConversationCreate() {
// //
await conversationListRef.value.createConversation(); await conversationListRef.value.createConversation();
}; }
/** 处理聊天对话的创建成功 */ /** 处理聊天对话的创建成功 */
const handleConversationCreateSuccess = async () => { async function handleConversationCreateSuccess() {
// //
prompt.value = ''; prompt.value = '';
}; }
// =========== =========== // =========== ===========
/** 获取消息 message 列表 */ /** 获取消息 message 列表 */
const getMessageList = async () => { async function getMessageList() {
try { try {
if (activeConversationId.value === null) { if (activeConversationId.value === null) {
return; return;
@ -171,7 +171,7 @@ const getMessageList = async () => {
// //
activeMessageListLoading.value = false; activeMessageListLoading.value = false;
} }
}; }
/** /**
* 消息列表 * 消息列表
@ -196,17 +196,17 @@ const messageList = computed(() => {
}); });
/** 处理删除 message 消息 */ /** 处理删除 message 消息 */
const handleMessageDelete = () => { function handleMessageDelete() {
if (conversationInProgress.value) { if (conversationInProgress.value) {
alert('回答中,不能删除!'); alert('回答中,不能删除!');
return; return;
} }
// message // message
getMessageList(); getMessageList();
}; }
/** 处理 message 清空 */ /** 处理 message 清空 */
const handlerMessageClear = async () => { async function handlerMessageClear() {
if (!activeConversationId.value) { if (!activeConversationId.value) {
return; return;
} }
@ -218,16 +218,16 @@ const handlerMessageClear = async () => {
// message // message
activeMessageList.value = []; activeMessageList.value = [];
} catch {} } catch {}
}; }
/** 回到 message 列表的顶部 */ /** 回到 message 列表的顶部 */
const handleGoTopMessage = () => { function handleGoTopMessage() {
messageRef.value.handlerGoTop(); messageRef.value.handlerGoTop();
}; }
// =========== =========== // =========== ===========
/** 处理来自 keydown 的发送消息 */ /** 处理来自 keydown 的发送消息 */
const handleSendByKeydown = async (event: any) => { async function handleSendByKeydown(event: any) {
// //
if (isComposing.value) { if (isComposing.value) {
return; return;
@ -248,15 +248,15 @@ const handleSendByKeydown = async (event: any) => {
event.preventDefault(); // event.preventDefault(); //
} }
} }
}; }
/** 处理来自【发送】按钮的发送消息 */ /** 处理来自【发送】按钮的发送消息 */
const handleSendByButton = () => { function handleSendByButton() {
doSendMessage(prompt.value?.trim() as string); doSendMessage(prompt.value?.trim() as string);
}; }
/** 处理 prompt 输入变化 */ /** 处理 prompt 输入变化 */
const handlePromptInput = (event) => { function handlePromptInput(event: any) {
// true // true
if (!isComposing.value) { if (!isComposing.value) {
// event data null // event data null
@ -273,27 +273,27 @@ const handlePromptInput = (event) => {
inputTimeout.value = setTimeout(() => { inputTimeout.value = setTimeout(() => {
isComposing.value = false; isComposing.value = false;
}, 400); }, 400);
}; }
const onCompositionstart = () => { function onCompositionstart() {
isComposing.value = true; isComposing.value = true;
}; }
const onCompositionend = () => { function onCompositionend() {
// console.log('...') // console.log('...')
setTimeout(() => { setTimeout(() => {
isComposing.value = false; isComposing.value = false;
}, 200); }, 200);
}; }
/** 真正执行【发送】消息操作 */ /** 真正执行【发送】消息操作 */
const doSendMessage = async (content: string) => { async function doSendMessage(content: string) {
// //
if (content.length === 0) { if (content.length === 0) {
message.error('发送失败,原因:内容为空!'); message.error('发送失败,原因:内容为空!');
return; return;
} }
if (activeConversationId.value == null) { if (activeConversationId.value === null) {
message.error('还没创建对话,不能发送!'); message.error('还没创建对话,不能发送!');
return; return;
} }
@ -304,12 +304,12 @@ const doSendMessage = async (content: string) => {
conversationId: activeConversationId.value, conversationId: activeConversationId.value,
content, content,
} as AiChatMessageApi.ChatMessageVO); } as AiChatMessageApi.ChatMessageVO);
}; }
/** 真正执行【发送】消息操作 */ /** 真正执行【发送】消息操作 */
const doSendMessageStream = async ( async function doSendMessageStream(
userMessage: AiChatMessageApi.ChatMessageVO, userMessage: AiChatMessageApi.ChatMessageVO,
) => { ) {
// AbortController 便 // AbortController 便
conversationInAbortController.value = new AbortController(); conversationInAbortController.value = new AbortController();
// //
@ -385,40 +385,40 @@ const doSendMessageStream = async (
}, },
); );
} catch {} } catch {}
}; }
/** 停止 stream 流式调用 */ /** 停止 stream 流式调用 */
const stopStream = async () => { async function stopStream() {
// tip stream message controller // tip stream message controller
if (conversationInAbortController.value) { if (conversationInAbortController.value) {
conversationInAbortController.value.abort(); conversationInAbortController.value.abort();
} }
// false // false
conversationInProgress.value = false; conversationInProgress.value = false;
}; }
/** 编辑 message设置为 prompt可以再次编辑 */ /** 编辑 message设置为 prompt可以再次编辑 */
const handleMessageEdit = (message: AiChatMessageApi.ChatMessageVO) => { function handleMessageEdit(message: AiChatMessageApi.ChatMessageVO) {
prompt.value = message.content; prompt.value = message.content;
}; }
/** 刷新 message基于指定消息再次发起对话 */ /** 刷新 message基于指定消息再次发起对话 */
const handleMessageRefresh = (message: AiChatMessageApi.ChatMessageVO) => { function handleMessageRefresh(message: AiChatMessageApi.ChatMessageVO) {
doSendMessage(message.content); doSendMessage(message.content);
}; }
// ============== ============= // ============== =============
/** 滚动到 message 底部 */ /** 滚动到 message 底部 */
const scrollToBottom = async (isIgnore?: boolean) => { async function scrollToBottom(isIgnore?: boolean) {
await nextTick(); await nextTick();
if (messageRef.value) { if (messageRef.value) {
messageRef.value.scrollToBottom(isIgnore); messageRef.value.scrollToBottom(isIgnore);
} }
}; }
/** 自提滚动效果 */ /** 自提滚动效果 */
const textRoll = async () => { async function textRoll() {
let index = 0; let index = 0;
try { try {
// //
@ -475,7 +475,7 @@ const textRoll = async () => {
}; };
let timer = setTimeout(task, textSpeed.value); let timer = setTimeout(task, textSpeed.value);
} catch {} } catch {}
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {
@ -569,8 +569,8 @@ onMounted(async () => {
<MessageList <MessageList
v-if="!activeMessageListLoading && messageList.length > 0" v-if="!activeMessageListLoading && messageList.length > 0"
ref="messageRef" ref="messageRef"
:conversation="activeConversation" :conversation="activeConversation as any"
:list="messageList" :list="messageList as any"
@on-delete-success="handleMessageDelete" @on-delete-success="handleMessageDelete"
@on-edit="handleMessageEdit" @on-edit="handleMessageEdit"
@on-refresh="handleMessageRefresh" @on-refresh="handleMessageRefresh"

View File

@ -2,7 +2,7 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { DICT_TYPE } from '#/utils'; import { DICT_TYPE, getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchemaConversation(): VbenFormSchema[] { export function useGridFormSchemaConversation(): VbenFormSchema[] {
@ -22,8 +22,7 @@ export function useGridFormSchemaConversation(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },
@ -118,8 +117,7 @@ export function useGridFormSchemaMessage(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -9,7 +9,7 @@ import { confirm } from '@vben/common-ui';
import { Button, Card, Image, message } from 'ant-design-vue'; import { Button, Card, Image, message } from 'ant-design-vue';
import { AiImageStatusEnum } from '#/utils/constants'; import { AiImageStatusEnum } from '#/utils';
// //
@ -24,20 +24,18 @@ const emits = defineEmits(['onBtnClick', 'onMjBtnClick']);
const cardImageRef = ref<any>(); // image ref const cardImageRef = ref<any>(); // image ref
/** 处理点击事件 */ /** 处理点击事件 */
const handleButtonClick = async (type: string, detail: AiImageApi.ImageVO) => { async function handleButtonClick(type: string, detail: AiImageApi.ImageVO) {
emits('onBtnClick', type, detail); emits('onBtnClick', type, detail);
}; }
/** 处理 Midjourney 按钮点击事件 */ /** 处理 Midjourney 按钮点击事件 */
const handleMidjourneyBtnClick = async ( async function handleMidjourneyBtnClick(
button: AiImageApi.ImageMidjourneyButtonsVO, button: AiImageApi.ImageMidjourneyButtonsVO,
) => { ) {
// //
await confirm(`确认操作 "${button.label} ${button.emoji}" ?`); await confirm(`确认操作 "${button.label} ${button.emoji}" ?`);
emits('onMjBtnClick', button, props.detail); emits('onMjBtnClick', button, props.detail);
}; }
// emits
/** 监听详情 */ /** 监听详情 */
const { detail } = toRefs(props); const { detail } = toRefs(props);
@ -46,7 +44,7 @@ watch(detail, async (newVal) => {
}); });
const loading = ref(); const loading = ref();
/** 处理加载状态 */ /** 处理加载状态 */
const handleLoading = async (status: number) => { async function handleLoading(status: number) {
// loading // loading
if (status === AiImageStatusEnum.IN_PROGRESS) { if (status === AiImageStatusEnum.IN_PROGRESS) {
loading.value = message.loading({ loading.value = message.loading({
@ -57,7 +55,7 @@ const handleLoading = async (status: number) => {
} else { } else {
if (loading.value) setTimeout(loading.value, 100); if (loading.value) setTimeout(loading.value, 100);
} }
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {

View File

@ -3,6 +3,8 @@ import type { AiImageApi } from '#/api/ai/image';
import { ref, toRefs, watch } from 'vue'; import { ref, toRefs, watch } from 'vue';
import { formatDate } from '@vben/utils';
import { Image } from 'ant-design-vue'; import { Image } from 'ant-design-vue';
import { getImageMy } from '#/api/ai/image'; import { getImageMy } from '#/api/ai/image';
@ -12,8 +14,7 @@ import {
StableDiffusionClipGuidancePresets, StableDiffusionClipGuidancePresets,
StableDiffusionSamplers, StableDiffusionSamplers,
StableDiffusionStylePresets, StableDiffusionStylePresets,
} from '#/utils/constants'; } from '#/utils';
import { formatTime } from '#/utils/formatTime';
// //
const props = defineProps({ const props = defineProps({
@ -25,9 +26,9 @@ const props = defineProps({
const detail = ref<AiImageApi.ImageVO>({} as AiImageApi.ImageVO); const detail = ref<AiImageApi.ImageVO>({} as AiImageApi.ImageVO);
/** 获取图片详情 */ /** 获取图片详情 */
const getImageDetail = async (id: number) => { async function getImageDetail(id: number) {
detail.value = await getImageMy(id); detail.value = await getImageMy(id);
}; }
const { id } = toRefs(props); const { id } = toRefs(props);
watch( watch(
@ -53,10 +54,10 @@ watch(
<div class="tip text-lg font-bold">时间</div> <div class="tip text-lg font-bold">时间</div>
<div class="body mt-2 text-gray-600"> <div class="body mt-2 text-gray-600">
<div> <div>
提交时间{{ formatTime(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }} 提交时间{{ formatDate(detail.createTime, 'yyyy-MM-dd HH:mm:ss') }}
</div> </div>
<div> <div>
生成时间{{ formatTime(detail.finishTime, 'yyyy-MM-dd HH:mm:ss') }} 生成时间{{ formatDate(detail.finishTime, 'yyyy-MM-dd HH:mm:ss') }}
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,6 +5,7 @@ import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { confirm, useVbenDrawer } from '@vben/common-ui'; import { confirm, useVbenDrawer } from '@vben/common-ui';
import { downloadFileFromImageUrl } from '@vben/utils';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
import { Button, Card, message, Pagination } from 'ant-design-vue'; import { Button, Card, message, Pagination } from 'ant-design-vue';
@ -15,8 +16,7 @@ import {
getImagePageMy, getImagePageMy,
midjourneyAction, midjourneyAction,
} from '#/api/ai/image'; } from '#/api/ai/image';
import { AiImageStatusEnum } from '#/utils/constants'; import { AiImageStatusEnum } from '#/utils';
import { download } from '#/utils/download';
import ImageCard from './ImageCard.vue'; import ImageCard from './ImageCard.vue';
import ImageDetail from './ImageDetail.vue'; import ImageDetail from './ImageDetail.vue';
@ -43,18 +43,18 @@ const inProgressTimer = ref<any>(); // 生成中的 image 定时器,轮询生
const showImageDetailId = ref<number>(0); // const showImageDetailId = ref<number>(0); //
/** 处理查看绘图作品 */ /** 处理查看绘图作品 */
const handleViewPublic = () => { function handleViewPublic() {
router.push({ router.push({
name: 'AiImageSquare', name: 'AiImageSquare',
}); });
}; }
/** 查看图片的详情 */ /** 查看图片的详情 */
const handleDetailOpen = async () => { async function handleDetailOpen() {
drawerApi.open(); drawerApi.open();
}; }
/** 获得 image 图片列表 */ /** 获得 image 图片列表 */
const getImageList = async () => { async function getImageList() {
const loading = message.loading({ const loading = message.loading({
content: `加载中...`, content: `加载中...`,
}); });
@ -77,10 +77,10 @@ const getImageList = async () => {
// Loading // Loading
loading(); loading();
} }
}; }
const debounceGetImageList = useDebounceFn(getImageList, 80); const debounceGetImageList = useDebounceFn(getImageList, 80);
/** 轮询生成中的 image 列表 */ /** 轮询生成中的 image 列表 */
const refreshWatchImages = async () => { async function refreshWatchImages() {
const imageIds = Object.keys(inProgressImageMap.value).map(Number); const imageIds = Object.keys(inProgressImageMap.value).map(Number);
if (imageIds.length === 0) { if (imageIds.length === 0) {
return; return;
@ -101,13 +101,13 @@ const refreshWatchImages = async () => {
} }
}); });
inProgressImageMap.value = newWatchImages; inProgressImageMap.value = newWatchImages;
}; }
/** 图片的点击事件 */ /** 图片的点击事件 */
const handleImageButtonClick = async ( async function handleImageButtonClick(
type: string, type: string,
imageDetail: AiImageApi.ImageVO, imageDetail: AiImageApi.ImageVO,
) => { ) {
// //
if (type === 'more') { if (type === 'more') {
showImageDetailId.value = imageDetail.id; showImageDetailId.value = imageDetail.id;
@ -124,20 +124,23 @@ const handleImageButtonClick = async (
} }
// //
if (type === 'download') { if (type === 'download') {
await download.image({ url: imageDetail.picUrl }); await downloadFileFromImageUrl({
fileName: imageDetail.model,
source: imageDetail.picUrl,
});
return; return;
} }
// //
if (type === 'regeneration') { if (type === 'regeneration') {
await emits('onRegeneration', imageDetail); await emits('onRegeneration', imageDetail);
} }
}; }
/** 处理 Midjourney 按钮点击事件 */ /** 处理 Midjourney 按钮点击事件 */
const handleImageMidjourneyButtonClick = async ( async function handleImageMidjourneyButtonClick(
button: AiImageApi.ImageMidjourneyButtonsVO, button: AiImageApi.ImageMidjourneyButtonsVO,
imageDetail: AiImageApi.ImageVO, imageDetail: AiImageApi.ImageVO,
) => { ) {
// 1. params // 1. params
const data = { const data = {
id: imageDetail.id, id: imageDetail.id,
@ -147,7 +150,7 @@ const handleImageMidjourneyButtonClick = async (
await midjourneyAction(data); await midjourneyAction(data);
// 3. // 3.
await getImageList(); await getImageList();
}; }
defineExpose({ getImageList }); /** 组件挂在的时候 */ defineExpose({ getImageList }); /** 组件挂在的时候 */
onMounted(async () => { onMounted(async () => {

View File

@ -10,11 +10,7 @@ import { confirm } from '@vben/common-ui';
import { Button, InputNumber, Select, Space, Textarea } from 'ant-design-vue'; import { Button, InputNumber, Select, Space, Textarea } from 'ant-design-vue';
import { drawImage } from '#/api/ai/image'; import { drawImage } from '#/api/ai/image';
import { import { AiPlatformEnum, ImageHotWords, OtherPlatformEnum } from '#/utils';
AiPlatformEnum,
ImageHotWords,
OtherPlatformEnum,
} from '#/utils/constants';
// //
@ -39,7 +35,7 @@ const platformModels = ref<AiModelModelApi.ModelVO[]>([]); // 模型列表
const modelId = ref<number>(); // const modelId = ref<number>(); //
/** 选择热词 */ /** 选择热词 */
const handleHotWordClick = async (hotWord: string) => { async function handleHotWordClick(hotWord: string) {
// //
if (selectHotWord.value === hotWord) { if (selectHotWord.value === hotWord) {
selectHotWord.value = ''; selectHotWord.value = '';
@ -49,10 +45,10 @@ const handleHotWordClick = async (hotWord: string) => {
// //
selectHotWord.value = hotWord; // selectHotWord.value = hotWord; //
prompt.value = hotWord; // prompt.value = hotWord; //
}; }
/** 图片生成 */ /** 图片生成 */
const handleGenerateImage = async () => { async function handleGenerateImage() {
// //
await confirm(`确认生成内容?`); await confirm(`确认生成内容?`);
try { try {
@ -76,17 +72,17 @@ const handleGenerateImage = async () => {
// //
drawIn.value = false; drawIn.value = false;
} }
}; }
/** 填充值 */ /** 填充值 */
const settingValues = async (detail: AiImageApi.ImageVO) => { async function settingValues(detail: AiImageApi.ImageVO) {
prompt.value = detail.prompt; prompt.value = detail.prompt;
width.value = detail.width; width.value = detail.width;
height.value = detail.height; height.value = detail.height;
}; }
/** 平台切换 */ /** 平台切换 */
const handlerPlatformChange = async (platform: any) => { async function handlerPlatformChange(platform: any) {
// //
platformModels.value = props.models.filter( platformModels.value = props.models.filter(
(item: AiModelModelApi.ModelVO) => item.platform === platform, (item: AiModelModelApi.ModelVO) => item.platform === platform,
@ -96,7 +92,7 @@ const handlerPlatformChange = async (platform: any) => {
? platformModels.value[0].id ? platformModels.value[0].id
: undefined; : undefined;
// //
}; }
/** 监听 models 变化 */ /** 监听 models 变化 */
watch( watch(

View File

@ -2,7 +2,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { AiImageApi } from '#/api/ai/image'; import type { AiImageApi } from '#/api/ai/image';
import type { AiModelModelApi } from '#/api/ai/model/model'; import type { AiModelModelApi } from '#/api/ai/model/model';
import type { ImageModelVO, ImageSizeVO } from '#/utils/constants'; import type { ImageModelVO, ImageSizeVO } from '#/utils';
import { ref } from 'vue'; import { ref } from 'vue';
@ -17,7 +17,7 @@ import {
Dall3SizeList, Dall3SizeList,
Dall3StyleList, Dall3StyleList,
ImageHotWords, ImageHotWords,
} from '#/utils/constants'; } from '#/utils';
// //
const props = defineProps({ const props = defineProps({
@ -37,7 +37,7 @@ const selectSize = ref<string>('1024x1024'); // 选中 size
const style = ref<string>('vivid'); // style const style = ref<string>('vivid'); // style
/** 选择热词 */ /** 选择热词 */
const handleHotWordClick = async (hotWord: string) => { async function handleHotWordClick(hotWord: string) {
// //
if (selectHotWord.value === hotWord) { if (selectHotWord.value === hotWord) {
selectHotWord.value = ''; selectHotWord.value = '';
@ -47,10 +47,10 @@ const handleHotWordClick = async (hotWord: string) => {
// //
selectHotWord.value = hotWord; selectHotWord.value = hotWord;
prompt.value = hotWord; prompt.value = hotWord;
}; }
/** 选择 model 模型 */ /** 选择 model 模型 */
const handleModelClick = async (model: ImageModelVO) => { async function handleModelClick(model: ImageModelVO) {
selectModel.value = model.key; selectModel.value = model.key;
// //
// //
@ -73,20 +73,20 @@ const handleModelClick = async (model: ImageModelVO) => {
if (recommendedSize) { if (recommendedSize) {
selectSize.value = recommendedSize.key; selectSize.value = recommendedSize.key;
} }
}; }
/** 选择 style 样式 */ /** 选择 style 样式 */
const handleStyleClick = async (imageStyle: ImageModelVO) => { async function handleStyleClick(imageStyle: ImageModelVO) {
style.value = imageStyle.key; style.value = imageStyle.key;
}; }
/** 选择 size 大小 */ /** 选择 size 大小 */
const handleSizeClick = async (imageSize: ImageSizeVO) => { async function handleSizeClick(imageSize: ImageSizeVO) {
selectSize.value = imageSize.key; selectSize.value = imageSize.key;
}; }
/** 图片生产 */ /** 图片生产 */
const handleGenerateImage = async () => { async function handleGenerateImage() {
// models // models
const matchedModel = props.models.find( const matchedModel = props.models.find(
(item) => (item) =>
@ -127,10 +127,10 @@ const handleGenerateImage = async () => {
// //
drawIn.value = false; drawIn.value = false;
} }
}; }
/** 填充值 */ /** 填充值 */
const settingValues = async (detail: AiImageApi.ImageVO) => { async function settingValues(detail: AiImageApi.ImageVO) {
prompt.value = detail.prompt; prompt.value = detail.prompt;
selectModel.value = detail.model; selectModel.value = detail.model;
style.value = detail.options?.style; style.value = detail.options?.style;
@ -138,7 +138,7 @@ const settingValues = async (detail: AiImageApi.ImageVO) => {
(item) => item.key === `${detail.width}x${detail.height}`, (item) => item.key === `${detail.width}x${detail.height}`,
) as ImageSizeVO; ) as ImageSizeVO;
await handleSizeClick(imageSize); await handleSizeClick(imageSize);
}; }
/** 暴露组件方法 */ /** 暴露组件方法 */
defineExpose({ settingValues }); defineExpose({ settingValues });

View File

@ -2,7 +2,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { AiImageApi } from '#/api/ai/image'; import type { AiImageApi } from '#/api/ai/image';
import type { AiModelModelApi } from '#/api/ai/model/model'; import type { AiModelModelApi } from '#/api/ai/model/model';
import type { ImageModelVO, ImageSizeVO } from '#/utils/constants'; import type { ImageModelVO, ImageSizeVO } from '#/utils';
import { ref } from 'vue'; import { ref } from 'vue';
@ -26,7 +26,7 @@ import {
MidjourneySizeList, MidjourneySizeList,
MidjourneyVersions, MidjourneyVersions,
NijiVersionList, NijiVersionList,
} from '#/utils/constants'; } from '#/utils';
// //
@ -51,7 +51,7 @@ const selectVersion = ref<any>('6.0'); // 选中的 version
const versionList = ref<any>(MidjourneyVersions); // version const versionList = ref<any>(MidjourneyVersions); // version
/** 选择热词 */ /** 选择热词 */
const handleHotWordClick = async (hotWord: string) => { async function handleHotWordClick(hotWord: string) {
// //
if (selectHotWord.value === hotWord) { if (selectHotWord.value === hotWord) {
selectHotWord.value = ''; selectHotWord.value = '';
@ -61,23 +61,23 @@ const handleHotWordClick = async (hotWord: string) => {
// //
selectHotWord.value = hotWord; // selectHotWord.value = hotWord; //
prompt.value = hotWord; // prompt.value = hotWord; //
}; }
/** 点击 size 尺寸 */ /** 点击 size 尺寸 */
const handleSizeClick = async (imageSize: ImageSizeVO) => { async function handleSizeClick(imageSize: ImageSizeVO) {
selectSize.value = imageSize.key; selectSize.value = imageSize.key;
}; }
/** 点击 model 模型 */ /** 点击 model 模型 */
const handleModelClick = async (model: ImageModelVO) => { async function handleModelClick(model: ImageModelVO) {
selectModel.value = model.key; selectModel.value = model.key;
versionList.value = versionList.value =
model.key === 'niji' ? NijiVersionList : MidjourneyVersions; model.key === 'niji' ? NijiVersionList : MidjourneyVersions;
selectVersion.value = versionList.value[0].value; selectVersion.value = versionList.value[0].value;
}; }
/** 图片生成 */ /** 图片生成 */
const handleGenerateImage = async () => { async function handleGenerateImage() {
// models // models
const matchedModel = props.models.find( const matchedModel = props.models.find(
(item) => (item) =>
@ -115,10 +115,10 @@ const handleGenerateImage = async () => {
// //
drawIn.value = false; drawIn.value = false;
} }
}; }
/** 填充值 */ /** 填充值 */
const settingValues = async (detail: AiImageApi.ImageVO) => { async function settingValues(detail: AiImageApi.ImageVO) {
// //
prompt.value = detail.prompt; prompt.value = detail.prompt;
// image size // image size
@ -137,7 +137,7 @@ const settingValues = async (detail: AiImageApi.ImageVO) => {
).value; ).value;
// image // image
referImageUrl.value = detail.options.referImageUrl; referImageUrl.value = detail.options.referImageUrl;
}; }
/** 暴露组件方法 */ /** 暴露组件方法 */
defineExpose({ settingValues }); defineExpose({ settingValues });

View File

@ -23,10 +23,7 @@ import {
StableDiffusionClipGuidancePresets, StableDiffusionClipGuidancePresets,
StableDiffusionSamplers, StableDiffusionSamplers,
StableDiffusionStylePresets, StableDiffusionStylePresets,
} from '#/utils/constants'; } from '#/utils';
import { hasChinese } from '#/utils/utils';
//
// //
const props = defineProps({ const props = defineProps({
@ -35,8 +32,13 @@ const props = defineProps({
default: () => [] as AiModelModelApi.ModelVO[], default: () => [] as AiModelModelApi.ModelVO[],
}, },
}); });
const emits = defineEmits(['onDrawStart', 'onDrawComplete']); const emits = defineEmits(['onDrawStart', 'onDrawComplete']);
function hasChinese(str: string) {
return /[\u4E00-\u9FA5]/.test(str);
}
// //
const drawIn = ref<boolean>(false); // const drawIn = ref<boolean>(false); //
const selectHotWord = ref<string>(''); // const selectHotWord = ref<string>(''); //
@ -52,7 +54,7 @@ const clipGuidancePreset = ref<string>('NONE'); // 文本提示相匹配的图
const stylePreset = ref<string>('3d-model'); // const stylePreset = ref<string>('3d-model'); //
/** 选择热词 */ /** 选择热词 */
const handleHotWordClick = async (hotWord: string) => { async function handleHotWordClick(hotWord: string) {
// //
if (selectHotWord.value === hotWord) { if (selectHotWord.value === hotWord) {
selectHotWord.value = ''; selectHotWord.value = '';
@ -62,10 +64,10 @@ const handleHotWordClick = async (hotWord: string) => {
// //
selectHotWord.value = hotWord; // selectHotWord.value = hotWord; //
prompt.value = hotWord; // prompt.value = hotWord; //
}; }
/** 图片生成 */ /** 图片生成 */
const handleGenerateImage = async () => { async function handleGenerateImage() {
// models // models
const selectModel = 'stable-diffusion-v1-6'; const selectModel = 'stable-diffusion-v1-6';
const matchedModel = props.models.find( const matchedModel = props.models.find(
@ -112,10 +114,10 @@ const handleGenerateImage = async () => {
// //
drawIn.value = false; drawIn.value = false;
} }
}; }
/** 填充值 */ /** 填充值 */
const settingValues = async (detail: AiImageApi.ImageVO) => { async function settingValues(detail: AiImageApi.ImageVO) {
prompt.value = detail.prompt; prompt.value = detail.prompt;
width.value = detail.width; width.value = detail.width;
height.value = detail.height; height.value = detail.height;
@ -125,7 +127,7 @@ const settingValues = async (detail: AiImageApi.ImageVO) => {
sampler.value = detail.options?.sampler; sampler.value = detail.options?.sampler;
clipGuidancePreset.value = detail.options?.clipGuidancePreset; clipGuidancePreset.value = detail.options?.clipGuidancePreset;
stylePreset.value = detail.options?.stylePreset; stylePreset.value = detail.options?.stylePreset;
}; }
/** 暴露组件方法 */ /** 暴露组件方法 */
defineExpose({ settingValues }); defineExpose({ settingValues });

View File

@ -9,7 +9,7 @@ import { Page } from '@vben/common-ui';
import { Segmented } from 'ant-design-vue'; import { Segmented } from 'ant-design-vue';
import { getModelSimpleList } from '#/api/ai/model/model'; import { getModelSimpleList } from '#/api/ai/model/model';
import { AiModelTypeEnum, AiPlatformEnum } from '#/utils/constants'; import { AiModelTypeEnum, AiPlatformEnum } from '#/utils';
import Common from './components/common/index.vue'; import Common from './components/common/index.vue';
import Dall3 from './components/dall3/index.vue'; import Dall3 from './components/dall3/index.vue';

View File

@ -2,7 +2,7 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
@ -49,8 +49,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -13,7 +13,7 @@ import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteImage, getImagePage, updateImage } from '#/api/ai/image'; import { deleteImage, getImagePage, updateImage } from '#/api/ai/image';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { AiImageStatusEnum } from '#/utils/constants'; import { AiImageStatusEnum } from '#/utils';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';

View File

@ -9,7 +9,7 @@ import { useDebounceFn } from '@vueuse/core';
import { Input, Pagination } from 'ant-design-vue'; import { Input, Pagination } from 'ant-design-vue';
import { getImagePageMy } from '#/api/ai/image'; import { getImagePageMy } from '#/api/ai/image';
// TODO @fan loading
const loading = ref(true); // const loading = ref(true); //
const list = ref<AiImageApi.ImageVO[]>([]); // const list = ref<AiImageApi.ImageVO[]>([]); //
const total = ref(0); // const total = ref(0); //
@ -21,7 +21,7 @@ const queryParams = reactive({
}); });
/** 查询列表 */ /** 查询列表 */
const getList = async () => { async function getList() {
loading.value = true; loading.value = true;
try { try {
const data = await getImagePageMy(queryParams); const data = await getImagePageMy(queryParams);
@ -30,7 +30,7 @@ const getList = async () => {
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; }
const debounceGetList = useDebounceFn(getList, 80); const debounceGetList = useDebounceFn(getList, 80);
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {

View File

@ -19,9 +19,9 @@ const parent = inject('parent') as any;
const pollingTimer = ref<null | number>(null); // ID const pollingTimer = ref<null | number>(null); // ID
/** 判断文件处理是否完成 */ /** 判断文件处理是否完成 */
const isProcessComplete = (file: any) => { function isProcessComplete(file: any) {
return file.progress === 100; return file.progress === 100;
}; }
/** 判断所有文件是否都处理完成 */ /** 判断所有文件是否都处理完成 */
const allProcessComplete = computed(() => { const allProcessComplete = computed(() => {
@ -29,14 +29,14 @@ const allProcessComplete = computed(() => {
}); });
/** 完成按钮点击事件处理 */ /** 完成按钮点击事件处理 */
const handleComplete = () => { function handleComplete() {
if (parent?.exposed?.handleBack) { if (parent?.exposed?.handleBack) {
parent.exposed.handleBack(); parent.exposed.handleBack();
} }
}; }
/** 获取文件处理进度 */ /** 获取文件处理进度 */
const getProcessList = async () => { async function getProcessList() {
try { try {
// 1. API // 1. API
const documentIds = props.modelValue.list const documentIds = props.modelValue.list
@ -82,7 +82,7 @@ const getProcessList = async () => {
console.error('获取处理进度失败:', error); console.error('获取处理进度失败:', error);
pollingTimer.value = window.setTimeout(getProcessList, 5000); pollingTimer.value = window.setTimeout(getProcessList, 5000);
} }
}; }
/** 组件挂载时开始轮询 */ /** 组件挂载时开始轮询 */
onMounted(() => { onMounted(() => {

View File

@ -42,12 +42,13 @@ const currentFile = ref<any>(null); // 当前选中的文件
const submitLoading = ref(false); // const submitLoading = ref(false); //
/** 选择文件 */ /** 选择文件 */
const selectFile = async (index: number) => { async function selectFile(index: number) {
currentFile.value = modelData.value.list[index]; currentFile.value = modelData.value.list[index];
await splitContentFile(currentFile.value); await splitContentFile(currentFile.value);
}; }
/** 获取文件分段内容 */ /** 获取文件分段内容 */
const splitContentFile = async (file: any) => { async function splitContentFile(file: any) {
if (!file || !file.url) { if (!file || !file.url) {
message.warning('文件 URL 不存在'); message.warning('文件 URL 不存在');
return; return;
@ -65,9 +66,9 @@ const splitContentFile = async (file: any) => {
} finally { } finally {
splitLoading.value = false; splitLoading.value = false;
} }
}; }
/** 处理预览分段 */ /** 处理预览分段 */
const handleAutoSegment = async () => { async function handleAutoSegment() {
// //
if ( if (
!currentFile.value && !currentFile.value &&
@ -84,18 +85,18 @@ const handleAutoSegment = async () => {
// //
await splitContentFile(currentFile.value); await splitContentFile(currentFile.value);
}; }
/** 上一步按钮处理 */ /** 上一步按钮处理 */
const handlePrevStep = () => { function handlePrevStep() {
const parentEl = parent || getCurrentInstance()?.parent; const parentEl = parent || getCurrentInstance()?.parent;
if (parentEl && typeof parentEl.exposed?.goToPrevStep === 'function') { if (parentEl && typeof parentEl.exposed?.goToPrevStep === 'function') {
parentEl.exposed.goToPrevStep(); parentEl.exposed.goToPrevStep();
} }
}; }
/** 保存操作 */ /** 保存操作 */
const handleSave = async () => { async function handleSave() {
// //
if ( if (
!currentFile?.value?.segments || !currentFile?.value?.segments ||
@ -140,7 +141,7 @@ const handleSave = async () => {
// //
submitLoading.value = false; submitLoading.value = false;
} }
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {

View File

@ -10,11 +10,11 @@ import { computed, getCurrentInstance, inject, onMounted, ref } from 'vue';
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales'; import { $t } from '@vben/locales';
import { generateAcceptedFileTypes } from '@vben/utils';
import { Button, Form, message, UploadDragger } from 'ant-design-vue'; import { Button, Form, message, UploadDragger } from 'ant-design-vue';
import { useUpload } from '#/components/upload/use-upload'; import { useUpload } from '#/components/upload/use-upload';
import { generateAcceptedFileTypes } from '#/utils/upload';
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -70,14 +70,14 @@ const modelData = computed({
set: (val) => emit('update:modelValue', val), set: (val) => emit('update:modelValue', val),
}); });
/** 确保 list 属性存在 */ /** 确保 list 属性存在 */
const ensureListExists = () => { function ensureListExists() {
if (!props.modelValue.list) { if (!props.modelValue.list) {
emit('update:modelValue', { emit('update:modelValue', {
...props.modelValue, ...props.modelValue,
list: [], list: [],
}); });
} }
}; }
/** 是否所有文件都已上传完成 */ /** 是否所有文件都已上传完成 */
const isAllUploaded = computed(() => { const isAllUploaded = computed(() => {
return ( return (
@ -93,7 +93,7 @@ const isAllUploaded = computed(() => {
* @param file 待上传的文件 * @param file 待上传的文件
* @returns 是否允许上传 * @returns 是否允许上传
*/ */
const beforeUpload = (file: any) => { function beforeUpload(file: any) {
// 1.1 // 1.1
const fileName = file.name.toLowerCase(); const fileName = file.name.toLowerCase();
const fileExtension = fileName.slice( const fileExtension = fileName.slice(
@ -112,7 +112,7 @@ const beforeUpload = (file: any) => {
// 2. // 2.
uploadingCount.value++; uploadingCount.value++;
return true; return true;
}; }
async function customRequest(info: UploadRequestOption<any>) { async function customRequest(info: UploadRequestOption<any>) {
const file = info.file as File; const file = info.file as File;
const name = file?.name; const name = file?.name;
@ -148,7 +148,7 @@ async function customRequest(info: UploadRequestOption<any>) {
* *
* @param index 要移除的文件索引 * @param index 要移除的文件索引
*/ */
const removeFile = (index: number) => { function removeFile(index: number) {
// //
const newList = [...props.modelValue.list]; const newList = [...props.modelValue.list];
newList.splice(index, 1); newList.splice(index, 1);
@ -157,10 +157,10 @@ const removeFile = (index: number) => {
...props.modelValue, ...props.modelValue,
list: newList, list: newList,
}); });
}; }
/** 下一步按钮处理 */ /** 下一步按钮处理 */
const handleNextStep = () => { function handleNextStep() {
// 1.1 // 1.1
if (!modelData.value.list || modelData.value.list.length === 0) { if (!modelData.value.list || modelData.value.list.length === 0) {
message.warning('请上传至少一个文件'); message.warning('请上传至少一个文件');
@ -177,7 +177,7 @@ const handleNextStep = () => {
if (parentEl && typeof parentEl.exposed?.goToNextStep === 'function') { if (parentEl && typeof parentEl.exposed?.goToNextStep === 'function') {
parentEl.exposed.goToNextStep(); parentEl.exposed.goToNextStep();
} }
}; }
/** 初始化 */ /** 初始化 */
onMounted(() => { onMounted(() => {
@ -210,9 +210,9 @@ onMounted(() => {
/> />
<div class="ant-upload-text text-[16px] text-[#606266]"> <div class="ant-upload-text text-[16px] text-[#606266]">
拖拽文件至此或者 拖拽文件至此或者
<em class="cursor-pointer not-italic text-[#409eff]" <em class="cursor-pointer not-italic text-[#409eff]">
>选择文件</em 选择文件
> </em>
</div> </div>
<div class="ant-upload-tip mt-10px text-[12px] text-[#909399]"> <div class="ant-upload-tip mt-10px text-[12px] text-[#909399]">
已支持 {{ supportedFileTypes.join('、') }}每个文件不超过 已支持 {{ supportedFileTypes.join('、') }}每个文件不超过

View File

@ -56,7 +56,7 @@ provide('parent', getCurrentInstance()); // 提供 parent 给子组件使用
const tabs = useTabs(); const tabs = useTabs();
/** 返回列表页 */ /** 返回列表页 */
const handleBack = () => { function handleBack() {
// //
tabs.closeCurrentTab(); tabs.closeCurrentTab();
// 使 name 'name'+ menuId // 使 name 'name'+ menuId
@ -66,10 +66,10 @@ const handleBack = () => {
knowledgeId: route.query.knowledgeId, knowledgeId: route.query.knowledgeId,
}, },
}); });
}; }
/** 初始化数据 */ /** 初始化数据 */
const initData = async () => { async function initData() {
if (route.query.knowledgeId) { if (route.query.knowledgeId) {
formData.value.knowledgeId = route.query.knowledgeId as any; formData.value.knowledgeId = route.query.knowledgeId as any;
} }
@ -91,20 +91,20 @@ const initData = async () => {
// //
goToNextStep(); goToNextStep();
} }
}; }
/** 切换到下一步 */ /** 切换到下一步 */
const goToNextStep = () => { function goToNextStep() {
if (currentStep.value < steps.length - 1) { if (currentStep.value < steps.length - 1) {
currentStep.value++; currentStep.value++;
} }
}; }
/** 切换到上一步 */ /** 切换到上一步 */
const goToPrevStep = () => { function goToPrevStep() {
if (currentStep.value > 0) { if (currentStep.value > 0) {
currentStep.value--; currentStep.value--;
} }
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {

View File

@ -17,7 +17,7 @@ import {
updateKnowledgeDocumentStatus, updateKnowledgeDocumentStatus,
} from '#/api/ai/knowledge/document'; } from '#/api/ai/knowledge/document';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { CommonStatusEnum } from '#/utils/constants'; import { CommonStatusEnum } from '#/utils';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';

View File

@ -8,6 +8,7 @@ import {
CommonStatusEnum, CommonStatusEnum,
DICT_TYPE, DICT_TYPE,
getDictOptions, getDictOptions,
getRangePickerDefaultProps,
} from '#/utils'; } from '#/utils';
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
@ -112,8 +113,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -57,20 +57,20 @@ async function handleDelete(row: AiKnowledgeKnowledgeApi.KnowledgeVO) {
} }
/** 文档按钮操作 */ /** 文档按钮操作 */
const router = useRouter(); const router = useRouter();
const handleDocument = (id: number) => { function handleDocument(id: number) {
router.push({ router.push({
name: 'AiKnowledgeDocument', name: 'AiKnowledgeDocument',
query: { knowledgeId: id }, query: { knowledgeId: id },
}); });
}; }
/** 跳转到文档召回测试页面 */ /** 跳转到文档召回测试页面 */
const handleRetrieval = (id: number) => { function handleRetrieval(id: number) {
router.push({ router.push({
name: 'AiKnowledgeRetrieval', name: 'AiKnowledgeRetrieval',
query: { id }, query: { id },
}); });
}; }
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {

View File

@ -32,7 +32,7 @@ const queryParams = reactive({
}); });
/** 调用文档召回测试接口 */ /** 调用文档召回测试接口 */
const getRetrievalResult = async () => { async function getRetrievalResult() {
if (!queryParams.content) { if (!queryParams.content) {
message.warning('请输入查询文本'); message.warning('请输入查询文本');
return; return;
@ -54,15 +54,15 @@ const getRetrievalResult = async () => {
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; }
/** 展开/收起段落内容 */ /** 展开/收起段落内容 */
const toggleExpand = (segment: any) => { function toggleExpand(segment: any) {
segment.expanded = !segment.expanded; segment.expanded = !segment.expanded;
}; }
/** 获取知识库信息 */ /** 获取知识库信息 */
const getKnowledgeInfo = async (id: number) => { async function getKnowledgeInfo(id: number) {
try { try {
const knowledge = await getKnowledge(id); const knowledge = await getKnowledge(id);
if (knowledge) { if (knowledge) {
@ -71,7 +71,7 @@ const getKnowledgeInfo = async (id: number) => {
knowledge.similarityThreshold || queryParams.similarityThreshold; knowledge.similarityThreshold || queryParams.similarityThreshold;
} }
} catch {} } catch {}
}; }
/** 初始化 */ /** 初始化 */
onMounted(() => { onMounted(() => {

View File

@ -18,7 +18,7 @@ import {
updateKnowledgeSegmentStatus, updateKnowledgeSegmentStatus,
} from '#/api/ai/knowledge/segment'; } from '#/api/ai/knowledge/segment';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { CommonStatusEnum } from '#/utils/constants'; import { CommonStatusEnum } from '#/utils';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue'; import Form from './modules/form.vue';
@ -93,9 +93,9 @@ const [Grid, gridApi] = useVbenVxeGrid({
}); });
/** 修改是否发布 */ /** 修改是否发布 */
const handleStatusChange = async ( async function handleStatusChange(
row: AiKnowledgeSegmentApi.KnowledgeSegmentVO, row: AiKnowledgeSegmentApi.KnowledgeSegmentVO,
) => { ) {
try { try {
// //
const text = row.status ? '启用' : '禁用'; const text = row.status ? '启用' : '禁用';
@ -112,7 +112,8 @@ const handleStatusChange = async (
? CommonStatusEnum.DISABLE ? CommonStatusEnum.DISABLE
: CommonStatusEnum.ENABLE; : CommonStatusEnum.ENABLE;
} }
}; }
onMounted(() => { onMounted(() => {
gridApi.formApi.setFieldValue('documentId', route.query.documentId); gridApi.formApi.setFieldValue('documentId', route.query.documentId);
}); });

View File

@ -6,7 +6,7 @@ import { nextTick, onMounted, ref } from 'vue';
import { alert, Page } from '@vben/common-ui'; import { alert, Page } from '@vben/common-ui';
import { generateMindMap } from '#/api/ai/mindmap'; import { generateMindMap } from '#/api/ai/mindmap';
import { MindMapContentExample } from '#/utils/constants'; import { MindMapContentExample } from '#/utils';
import Left from './modules/Left.vue'; import Left from './modules/Left.vue';
import Right from './modules/Right.vue'; import Right from './modules/Right.vue';
@ -21,13 +21,13 @@ const leftRef = ref<InstanceType<typeof Left>>(); // 左边组件
const rightRef = ref(); // const rightRef = ref(); //
/** 使用已有内容直接生成 */ /** 使用已有内容直接生成 */
const directGenerate = (existPrompt: string) => { function directGenerate(existPrompt: string) {
isEnd.value = false; // false true watch isEnd.value = false; // false true watch
generatedContent.value = existPrompt; generatedContent.value = existPrompt;
isEnd.value = true; isEnd.value = true;
}; }
/** 提交生成 */ /** 提交生成 */
const submit = (data: AiMindmapApi.AiMindMapGenerateReqVO) => { function submit(data: AiMindmapApi.AiMindMapGenerateReqVO) {
isGenerating.value = true; isGenerating.value = true;
isStart.value = true; isStart.value = true;
isEnd.value = false; isEnd.value = false;
@ -59,13 +59,13 @@ const submit = (data: AiMindmapApi.AiMindMapGenerateReqVO) => {
}, },
ctrl: ctrl.value, ctrl: ctrl.value,
}); });
}; }
/** 停止 stream 生成 */ /** 停止 stream 生成 */
const stopStream = () => { function stopStream() {
isGenerating.value = false; isGenerating.value = false;
isStart.value = false; isStart.value = false;
ctrl.value?.abort(); ctrl.value?.abort();
}; }
/** 初始化 */ /** 初始化 */
onMounted(() => { onMounted(() => {

View File

@ -3,7 +3,7 @@ import { reactive, ref } from 'vue';
import { Button, Textarea } from 'ant-design-vue'; import { Button, Textarea } from 'ant-design-vue';
import { MindMapContentExample } from '#/utils/constants'; import { MindMapContentExample } from '#/utils';
defineProps<{ defineProps<{
isGenerating: boolean; isGenerating: boolean;

View File

@ -7,11 +7,10 @@ import {
Toolbar, Toolbar,
Transformer, Transformer,
} from '@vben/plugins/markmap'; } from '@vben/plugins/markmap';
import { downloadImageByCanvas } from '@vben/utils';
import { Button, Card, message } from 'ant-design-vue'; import { Button, Card, message } from 'ant-design-vue';
import { download } from '#/utils/download';
const props = defineProps<{ const props = defineProps<{
generatedContent: string; // generatedContent: string; //
isEnd: boolean; // isEnd: boolean; //
@ -85,7 +84,7 @@ const update = () => {
} }
}; };
/** 处理内容 */ /** 处理内容 */
const processContent = (text: string) => { function processContent(text: string) {
const arr: string[] = []; const arr: string[] = [];
const lines = text.split('\n'); const lines = text.split('\n');
for (let line of lines) { for (let line of lines) {
@ -97,21 +96,21 @@ const processContent = (text: string) => {
arr.push(line); arr.push(line);
} }
return arr.join('\n'); return arr.join('\n');
}; }
/** 下载图片download SVG to png file */ /** 下载图片download SVG to png file */
const downloadImage = () => { function downloadImage() {
const svgElement = mindMapRef.value; const svgElement = mindMapRef.value;
// SVG // SVG
const serializer = new XMLSerializer(); const serializer = new XMLSerializer();
const source = `<?xml version="1.0" standalone="no"?>\r\n${serializer.serializeToString(svgRef.value!)}`; const source = `<?xml version="1.0" standalone="no"?>\r\n${serializer.serializeToString(svgRef.value!)}`;
const base64Url = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(source)}`; const base64Url = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(source)}`;
download.image({ downloadImageByCanvas({
url: base64Url, url: base64Url,
canvasWidth: svgElement?.offsetWidth, canvasWidth: svgElement?.offsetWidth,
canvasHeight: svgElement?.offsetHeight, canvasHeight: svgElement?.offsetHeight,
drawWithImageSize: false, drawWithImageSize: false,
}); });
}; }
defineExpose({ defineExpose({
scrollBottom() { scrollBottom() {
mdContainerRef.value?.scrollTo(0, mdContainerRef.value?.scrollHeight); mdContainerRef.value?.scrollTo(0, mdContainerRef.value?.scrollHeight);

View File

@ -2,6 +2,7 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
@ -26,8 +27,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -75,13 +75,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
}, },
} as VxeTableGridOptions<AiMindmapApi.MindMapVO>, } as VxeTableGridOptions<AiMindmapApi.MindMapVO>,
}); });
const openPreview = async (row: AiMindmapApi.MindMapVO) => { async function openPreview(row: AiMindmapApi.MindMapVO) {
previewVisible.value = false; previewVisible.value = false;
drawerApi.open(); drawerApi.open();
await nextTick(); await nextTick();
previewVisible.value = true; previewVisible.value = true;
previewContent.value = row.generatedContent; previewContent.value = row.generatedContent;
}; }
onMounted(async () => { onMounted(async () => {
// //
userList.value = await getSimpleUserList(); userList.value = await getSimpleUserList();

View File

@ -109,9 +109,9 @@ onMounted(async () => {
/> />
</template> </template>
<template #keyId="{ row }"> <template #keyId="{ row }">
<span>{{ <span>
apiKeyList.find((item) => item.id === row.keyId)?.name {{ apiKeyList.find((item) => item.id === row.keyId)?.name }}
}}</span> </span>
</template> </template>
<template #actions="{ row }"> <template #actions="{ row }">
<TableAction <TableAction

View File

@ -1,7 +1,12 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import {
CommonStatusEnum,
DICT_TYPE,
getDictOptions,
getRangePickerDefaultProps,
} from '#/utils';
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
return [ return [
@ -64,8 +69,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -8,7 +8,7 @@ import { Page } from '@vben/common-ui';
import List from './list/index.vue'; import List from './list/index.vue';
import Mode from './mode/index.vue'; import Mode from './mode/index.vue';
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicIndex' });
const listRef = ref<Nullable<{ generateMusic: (...args: any) => void }>>(null); const listRef = ref<Nullable<{ generateMusic: (...args: any) => void }>>(null);

View File

@ -4,12 +4,11 @@ import type { Nullable } from '@vben/types';
import { inject, reactive, ref } from 'vue'; import { inject, reactive, ref } from 'vue';
import { IconifyIcon } from '@vben/icons'; import { IconifyIcon } from '@vben/icons';
import { formatPast } from '@vben/utils';
import { Image, Slider } from 'ant-design-vue'; import { Image, Slider } from 'ant-design-vue';
import { formatPast } from '#/utils/formatTime'; defineOptions({ name: 'AiMusicAudioBarIndex' });
defineOptions({ name: 'Index' });
const currentSong = inject('currentSong', {}); const currentSong = inject('currentSong', {});

View File

@ -9,7 +9,7 @@ import audioBar from './audioBar/index.vue';
import songCard from './songCard/index.vue'; import songCard from './songCard/index.vue';
import songInfo from './songInfo/index.vue'; import songInfo from './songInfo/index.vue';
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicListIndex' });
const currentType = ref('mine'); const currentType = ref('mine');
// loading // loading

View File

@ -5,7 +5,7 @@ import { IconifyIcon } from '@vben/icons';
import { Image } from 'ant-design-vue'; import { Image } from 'ant-design-vue';
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicSongCardIndex' });
defineProps({ defineProps({
songInfo: { songInfo: {

View File

@ -3,7 +3,7 @@ import { inject } from 'vue';
import { Button, Card, Image } from 'ant-design-vue'; import { Button, Card, Image } from 'ant-design-vue';
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicSongInfoIndex' });
const currentSong = inject('currentSong', {}); const currentSong = inject('currentSong', {});
</script> </script>

View File

@ -5,7 +5,7 @@ import { Select, Switch, Textarea } from 'ant-design-vue';
import Title from '../title/index.vue'; import Title from '../title/index.vue';
defineOptions({ name: 'Desc' }); defineOptions({ name: 'AiMusicModeDesc' });
const formData = reactive({ const formData = reactive({
desc: '', desc: '',

View File

@ -8,7 +8,7 @@ import { Button, Card, Radio } from 'ant-design-vue';
import desc from './desc.vue'; import desc from './desc.vue';
import lyric from './lyric.vue'; import lyric from './lyric.vue';
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicModeIndex' });
const emits = defineEmits(['generateMusic']); const emits = defineEmits(['generateMusic']);

View File

@ -5,7 +5,7 @@ import { Button, Input, Select, Space, Tag, Textarea } from 'ant-design-vue';
import Title from '../title/index.vue'; import Title from '../title/index.vue';
defineOptions({ name: 'Lyric' }); defineOptions({ name: 'AiMusicModeLyric' });
const tags = ['rock', 'punk', 'jazz', 'soul', 'country', 'kidsmusic', 'pop']; const tags = ['rock', 'punk', 'jazz', 'soul', 'country', 'kidsmusic', 'pop'];

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
defineOptions({ name: 'Index' }); defineOptions({ name: 'AiMusicTitleIndex' });
defineProps({ defineProps({
title: { title: {

View File

@ -2,7 +2,7 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
@ -45,8 +45,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -13,7 +13,7 @@ import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { deleteMusic, getMusicPage, updateMusic } from '#/api/ai/music'; import { deleteMusic, getMusicPage, updateMusic } from '#/api/ai/music';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { AiMusicStatusEnum } from '#/utils/constants'; import { AiMusicStatusEnum } from '#/utils';
import { useGridColumns, useGridFormSchema } from './data'; import { useGridColumns, useGridFormSchema } from './data';

View File

@ -1,7 +1,7 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
@ -30,8 +30,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -28,14 +28,14 @@ const basicInfoRef = ref<InstanceType<typeof BasicInfo>>();
const workflowDesignRef = ref<InstanceType<typeof WorkflowDesign>>(); const workflowDesignRef = ref<InstanceType<typeof WorkflowDesign>>();
/** 步骤校验函数 */ /** 步骤校验函数 */
const validateBasic = async () => { async function validateBasic() {
await basicInfoRef.value?.validate(); await basicInfoRef.value?.validate();
}; }
/** 工作流设计校验 */ /** 工作流设计校验 */
const validateWorkflow = async () => { async function validateWorkflow() {
await workflowDesignRef.value?.validate(); await workflowDesignRef.value?.validate();
}; }
const currentStep = ref(-1); // -1 const currentStep = ref(-1); // -1
@ -60,7 +60,8 @@ provide('workflowData', workflowData);
/** 初始化数据 */ /** 初始化数据 */
const actionType = route.params.type as string; const actionType = route.params.type as string;
const initData = async () => {
async function initData() {
if (actionType === 'update') { if (actionType === 'update') {
const workflowId = route.params.id as string; const workflowId = route.params.id as string;
formData.value = await getWorkflow(workflowId); formData.value = await getWorkflow(workflowId);
@ -79,10 +80,10 @@ const initData = async () => {
// //
currentStep.value = 0; currentStep.value = 0;
}; }
/** 校验所有步骤数据是否完整 */ /** 校验所有步骤数据是否完整 */
const validateAllSteps = async () => { async function validateAllSteps() {
// //
try { try {
await validateBasic(); await validateBasic();
@ -99,10 +100,10 @@ const validateAllSteps = async () => {
throw new Error('请完善工作流信息'); throw new Error('请完善工作流信息');
} }
return true; return true;
}; }
/** 保存操作 */ /** 保存操作 */
const handleSave = async () => { async function handleSave() {
try { try {
// //
await validateAllSteps(); await validateAllSteps();
@ -124,10 +125,10 @@ const handleSave = async () => {
console.error('保存失败:', error); console.error('保存失败:', error);
message.warning(error.message || '请完善所有步骤的必填信息'); message.warning(error.message || '请完善所有步骤的必填信息');
} }
}; }
/** 发布操作 */ /** 发布操作 */
const handleDeploy = async () => { async function handleDeploy() {
try { try {
// //
if (!formData.value.id) { if (!formData.value.id) {
@ -158,10 +159,10 @@ const handleDeploy = async () => {
console.error('发布失败:', error); console.error('发布失败:', error);
message.warning(error.message || '发布失败'); message.warning(error.message || '发布失败');
} }
}; }
/** 步骤切换处理 */ /** 步骤切换处理 */
const handleStepClick = async (index: number) => { async function handleStepClick(index: number) {
try { try {
if (index !== 0) { if (index !== 0) {
await validateBasic(); await validateBasic();
@ -176,17 +177,17 @@ const handleStepClick = async (index: number) => {
console.error('步骤切换失败:', error); console.error('步骤切换失败:', error);
message.warning('请先完善当前步骤必填信息'); message.warning('请先完善当前步骤必填信息');
} }
}; }
const tabs = useTabs(); const tabs = useTabs();
/** 返回列表页 */ /** 返回列表页 */
const handleBack = () => { function handleBack() {
// //
tabs.closeCurrentTab(); tabs.closeCurrentTab();
// 使 name 'name'+ menuId // 使 name 'name'+ menuId
router.push({ path: '/ai/workflow' }); router.push({ path: '/ai/workflow' });
}; }
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {

View File

@ -18,9 +18,9 @@ const rules: Record<string, Rule[]> = {
}; };
/** 表单校验 */ /** 表单校验 */
const validate = async () => { async function validate() {
await formRef.value?.validate(); await formRef.value?.validate();
}; }
defineExpose({ validate }); defineExpose({ validate });
</script> </script>

View File

@ -4,11 +4,12 @@ import type { Ref } from 'vue';
import { inject, ref } from 'vue'; import { inject, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui'; import { useVbenDrawer } from '@vben/common-ui';
import { isNumber } from '@vben/utils';
import { Button, Input, Select } from 'ant-design-vue'; import { Button, Input, Select } from 'ant-design-vue';
import { testWorkflow } from '#/api/ai/workflow'; import { testWorkflow } from '#/api/ai/workflow';
import Tinyflow from '#/components/tinyflow/tinyflow.vue'; import { Tinyflow } from '#/components/tinyflow';
defineProps<{ defineProps<{
provider: any; provider: any;
@ -28,26 +29,26 @@ const [Drawer, drawerApi] = useVbenDrawer({
modal: false, modal: false,
}); });
/** 展示工作流测试抽屉 */ /** 展示工作流测试抽屉 */
const testWorkflowModel = () => { function testWorkflowModel() {
drawerApi.open(); drawerApi.open();
const startNode = getStartNode(); const startNode = getStartNode();
// //
const parameters = startNode.data?.parameters || []; const parameters = startNode.data?.parameters || [];
const paramDefinitions = {}; const paramDefinitions: Record<string, any> = {};
// 便 // 便
parameters.forEach((param) => { parameters.forEach((param: any) => {
paramDefinitions[param.name] = param; paramDefinitions[param.name] = param;
}); });
function mergeIfRequiredButNotSet(target) { function mergeIfRequiredButNotSet(target: any) {
const needPushList = []; const needPushList = [];
for (const key in paramDefinitions) { for (const key in paramDefinitions) {
const param = paramDefinitions[key]; const param = paramDefinitions[key];
if (param.required) { if (param.required) {
const item = target.find((item) => item.key === key); const item = target.find((item: any) => item.key === key);
if (!item) { if (!item) {
needPushList.push({ needPushList.push({
@ -63,10 +64,10 @@ const testWorkflowModel = () => {
mergeIfRequiredButNotSet(params4Test.value); mergeIfRequiredButNotSet(params4Test.value);
paramsOfStartNode.value = paramDefinitions; paramsOfStartNode.value = paramDefinitions;
}; }
/** 运行流程 */ /** 运行流程 */
const goRun = async () => { async function goRun() {
try { try {
const val = tinyflowRef.value.getData(); const val = tinyflowRef.value.getData();
loading.value = true; loading.value = true;
@ -77,13 +78,13 @@ const goRun = async () => {
// //
const parameters = startNode.data?.parameters || []; const parameters = startNode.data?.parameters || [];
const paramDefinitions = {}; const paramDefinitions: Record<string, any> = {};
parameters.forEach((param) => { parameters.forEach((param: any) => {
paramDefinitions[param.name] = param.dataType; paramDefinitions[param.name] = param.dataType;
}); });
// //
const convertedParams = {}; const convertedParams: Record<string, any> = {};
for (const { key, value } of params4Test.value) { for (const { key, value } of params4Test.value) {
const paramKey = key.trim(); const paramKey = key.trim();
if (!paramKey) continue; if (!paramKey) continue;
@ -95,8 +96,8 @@ const goRun = async () => {
try { try {
convertedParams[paramKey] = convertParamValue(value, dataType); convertedParams[paramKey] = convertParamValue(value, dataType);
} catch (error_) { } catch (error: any) {
throw new Error(`参数 ${paramKey} 转换失败: ${error_.message}`); throw new Error(`参数 ${paramKey} 转换失败: ${error.message}`);
} }
} }
@ -107,42 +108,42 @@ const goRun = async () => {
const response = await testWorkflow(data); const response = await testWorkflow(data);
testResult.value = response; testResult.value = response;
} catch (error_) { } catch (error: any) {
error.value = error.value =
error_.response?.data?.message || '运行失败,请检查参数和网络连接'; error.response?.data?.message || '运行失败,请检查参数和网络连接';
} finally { } finally {
loading.value = false; loading.value = false;
} }
}; }
/** 获取开始节点 */ /** 获取开始节点 */
const getStartNode = () => { function getStartNode() {
const val = tinyflowRef.value.getData(); const val = tinyflowRef.value.getData();
const startNode = val.nodes.find((node) => node.type === 'startNode'); const startNode = val.nodes.find((node: any) => node.type === 'startNode');
if (!startNode) { if (!startNode) {
throw new Error('流程缺少开始节点'); throw new Error('流程缺少开始节点');
} }
return startNode; return startNode;
}; }
/** 添加参数项 */ /** 添加参数项 */
const addParam = () => { function addParam() {
params4Test.value.push({ key: '', value: '' }); params4Test.value.push({ key: '', value: '' });
}; }
/** 删除参数项 */ /** 删除参数项 */
const removeParam = (index) => { function removeParam(index: number) {
params4Test.value.splice(index, 1); params4Test.value.splice(index, 1);
}; }
/** 类型转换函数 */ /** 类型转换函数 */
const convertParamValue = (value, dataType) => { function convertParamValue(value: string, dataType: string) {
if (value === '') return null; // if (value === '') return null; //
switch (dataType) { switch (dataType) {
case 'Number': { case 'Number': {
const num = Number(value); const num = Number(value);
if (isNaN(num)) throw new Error('非数字格式'); if (!isNumber(num)) throw new Error('非数字格式');
return num; return num;
} }
case 'String': { case 'String': {
@ -157,24 +158,24 @@ const convertParamValue = (value, dataType) => {
case 'Object': { case 'Object': {
try { try {
return JSON.parse(value); return JSON.parse(value);
} catch (error_) { } catch (error: any) {
throw new Error(`JSON格式错误: ${error_.message}`); throw new Error(`JSON格式错误: ${error.message}`);
} }
} }
default: { default: {
throw new Error(`不支持的类型: ${dataType}`); throw new Error(`不支持的类型: ${dataType}`);
} }
} }
}; }
/** 表单校验 */ /** 表单校验 */
const validate = async () => { async function validate() {
// //
if (!workflowData.value) { if (!workflowData.value) {
throw new Error('请设计流程'); throw new Error('请设计流程');
} }
workflowData.value = tinyflowRef.value.getData(); workflowData.value = tinyflowRef.value.getData();
return true; return true;
}; }
defineExpose({ validate }); defineExpose({ validate });
</script> </script>

View File

@ -6,8 +6,12 @@ import { ref } from 'vue';
import { createReusableTemplate } from '@vueuse/core'; import { createReusableTemplate } from '@vueuse/core';
import { Button, message, Textarea } from 'ant-design-vue'; import { Button, message, Textarea } from 'ant-design-vue';
import { DICT_TYPE, getIntDictOptions } from '#/utils'; import {
import { AiWriteTypeEnum, WriteExample } from '#/utils/constants'; AiWriteTypeEnum,
DICT_TYPE,
getIntDictOptions,
WriteExample,
} from '#/utils';
import Tag from './Tag.vue'; import Tag from './Tag.vue';
@ -33,19 +37,19 @@ function omit(obj: Record<string, any>, keysToOmit: string[]) {
return result; return result;
} }
/** 点击示例的时候,将定义好的文章作为示例展示出来 */ /** 点击示例的时候,将定义好的文章作为示例展示出来 */
const example = (type: 'reply' | 'write') => { function example(type: 'reply' | 'write') {
formData.value = { formData.value = {
...initData, ...initData,
...omit(WriteExample[type], ['data']), ...omit(WriteExample[type], ['data']),
}; };
emit('example', type); emit('example', type);
}; }
/** 重置,将表单值作为初选值 */ /** 重置,将表单值作为初选值 */
const reset = () => { function reset() {
formData.value = { ...initData }; formData.value = { ...initData };
emit('reset'); emit('reset');
}; }
const selectedTab = ref<TabType>(AiWriteTypeEnum.WRITING); const selectedTab = ref<TabType>(AiWriteTypeEnum.WRITING);
const tabs: { const tabs: {
@ -83,7 +87,7 @@ const formData = ref<AiWriteApi.WriteVO>({ ...initData });
/** 用来记录切换之前所填写的数据,切换的时候给赋值回来 */ /** 用来记录切换之前所填写的数据,切换的时候给赋值回来 */
const recordFormData = {} as Record<AiWriteTypeEnum, AiWriteApi.WriteVO>; const recordFormData = {} as Record<AiWriteTypeEnum, AiWriteApi.WriteVO>;
/** 切换tab */ /** 切换tab */
const switchTab = (value: TabType) => { function switchTab(value: TabType) {
if (value !== selectedTab.value) { if (value !== selectedTab.value) {
// //
recordFormData[selectedTab.value] = formData.value; recordFormData[selectedTab.value] = formData.value;
@ -91,10 +95,10 @@ const switchTab = (value: TabType) => {
// //
formData.value = { ...initData, ...recordFormData[value] }; formData.value = { ...initData, ...recordFormData[value] };
} }
}; }
/** 提交写作 */ /** 提交写作 */
const submit = () => { function submit() {
if (selectedTab.value === 2 && !formData.value.originalContent) { if (selectedTab.value === 2 && !formData.value.originalContent) {
message.warning('请输入原文'); message.warning('请输入原文');
return; return;
@ -111,7 +115,7 @@ const submit = () => {
/** 使用选中 tab 值覆盖当前的 type 类型 */ /** 使用选中 tab 值覆盖当前的 type 类型 */
type: selectedTab.value, type: selectedTab.value,
}); });
}; }
</script> </script>
<template> <template>

View File

@ -40,9 +40,9 @@ defineExpose({
/** 点击复制的时候复制内容 */ /** 点击复制的时候复制内容 */
const showCopy = computed(() => props.content && !props.isWriting); // const showCopy = computed(() => props.content && !props.isWriting); //
const copyContent = () => { function copyContent() {
copy(props.content); copy(props.content);
}; }
/** 复制成功的时候 copied.value 为 true */ /** 复制成功的时候 copied.value 为 true */
watch(copied, (val) => { watch(copied, (val) => {

View File

@ -6,7 +6,7 @@ import { nextTick, ref } from 'vue';
import { alert, Page } from '@vben/common-ui'; import { alert, Page } from '@vben/common-ui';
import { writeStream } from '#/api/ai/write'; import { writeStream } from '#/api/ai/write';
import { WriteExample } from '#/utils/constants'; import { WriteExample } from '#/utils';
import Left from './components/Left.vue'; import Left from './components/Left.vue';
import Right from './components/Right.vue'; import Right from './components/Right.vue';
@ -16,15 +16,15 @@ const isWriting = ref(false); // 是否正在写作中
const abortController = ref<AbortController>(); // // abort ( stream ) const abortController = ref<AbortController>(); // // abort ( stream )
/** 停止 stream 生成 */ /** 停止 stream 生成 */
const stopStream = () => { function stopStream() {
abortController.value?.abort(); abortController.value?.abort();
isWriting.value = false; isWriting.value = false;
}; }
/** 执行写作 */ /** 执行写作 */
const rightRef = ref<InstanceType<typeof Right>>(); const rightRef = ref<InstanceType<typeof Right>>();
const submit = (data: Partial<AiWriteApi.WriteVO>) => { function submit(data: Partial<AiWriteApi.WriteVO>) {
abortController.value = new AbortController(); abortController.value = new AbortController();
writeResult.value = ''; writeResult.value = '';
isWriting.value = true; isWriting.value = true;
@ -51,17 +51,17 @@ const submit = (data: Partial<AiWriteApi.WriteVO>) => {
throw error; throw error;
}, },
}); });
}; }
/** 点击示例触发 */ /** 点击示例触发 */
const handleExampleClick = (type: keyof typeof WriteExample) => { function handleExampleClick(type: keyof typeof WriteExample) {
writeResult.value = WriteExample[type].data; writeResult.value = WriteExample[type].data;
}; }
/** 点击重置的时候清空写作的结果*/ /** 点击重置的时候清空写作的结果*/
const reset = () => { function reset() {
writeResult.value = ''; writeResult.value = '';
}; }
</script> </script>
<template> <template>

View File

@ -2,7 +2,7 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { DICT_TYPE, getDictOptions } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
/** 列表的搜索表单 */ /** 列表的搜索表单 */
export function useGridFormSchema(): VbenFormSchema[] { export function useGridFormSchema(): VbenFormSchema[] {
@ -40,8 +40,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -3,7 +3,12 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { getSimpleUserList } from '#/api/system/user'; import { getSimpleUserList } from '#/api/system/user';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import {
CommonStatusEnum,
DICT_TYPE,
getDictOptions,
getRangePickerDefaultProps,
} from '#/utils';
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
@ -87,7 +92,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -2,7 +2,12 @@ import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; import {
CommonStatusEnum,
DICT_TYPE,
getDictOptions,
getRangePickerDefaultProps,
} from '#/utils';
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
@ -74,8 +79,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
label: '创建时间', label: '创建时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
placeholder: ['开始时间', '结束时间'], ...getRangePickerDefaultProps(),
valueFormat: 'YYYY-MM-DD HH:mm:ss',
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -71,6 +71,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];

View File

@ -77,6 +77,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];

View File

@ -55,7 +55,6 @@ export function useGridFormSchema(
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
placeholder: ['开始日期', '结束日期'],
allowClear: true, allowClear: true,
}, },
}, },
@ -65,7 +64,6 @@ export function useGridFormSchema(
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
placeholder: ['开始日期', '结束日期'],
allowClear: true, allowClear: true,
}, },
}, },

View File

@ -21,6 +21,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];

View File

@ -50,13 +50,13 @@ export function useGridFormSchema(): VbenFormSchema[] {
allowClear: true, allowClear: true,
}, },
}, },
// 发起时间
{ {
fieldName: 'createTime', fieldName: 'createTime',
label: '发起时间', label: '发起时间',
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];

View File

@ -21,6 +21,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];

View File

@ -56,6 +56,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
component: 'RangePicker', component: 'RangePicker',
componentProps: { componentProps: {
...getRangePickerDefaultProps(), ...getRangePickerDefaultProps(),
allowClear: true,
}, },
}, },
]; ];