feat: update new feature temp for panel

This commit is contained in:
2025-03-04 01:20:55 +08:00
parent 6e96247b50
commit fd3288cb5b
45 changed files with 2559 additions and 954 deletions

View File

@@ -0,0 +1,5 @@
import { useEffect } from 'react';
export const AiApp = () => {
return <div>AiApp</div>;
};

28
template/ai-app/main.tsx Normal file
View File

@@ -0,0 +1,28 @@
import { createRoot, Root } from 'react-dom/client';
import { AiApp } from './AiApp';
import { app, initAIAppRootOrCreate, useContextKey } from '../app';
import { Editor } from '@/pages/editor/index';
import { ExampleApp } from '@/modules/panels/Example';
initAIAppRootOrCreate();
app
.route({
path: 'ai',
key: 'render',
description: '渲染AI应用',
run: async (ctx) => {
const root = initAIAppRootOrCreate();
console.log('ai render');
console.log('ai render', root);
if (!root) {
return;
}
const aiRoot = createRoot(root!);
// aiRoot.render(<Editor />);
// aiRoot.render(<AiApp />);
aiRoot.render(<ExampleApp />);
useContextKey('aiRoot', () => aiRoot, true);
ctx.body = 'aiRoot';
},
})
.addTo(app);

View File

@@ -1,3 +1,39 @@
import { QueryAI } from '@kevisual/query/query-ai';
import { MyCache } from '@kevisual/cache';
import { useContextKey } from '@kevisual/system-lib/dist/web-config';
import { QueryRouterServer } from '@kevisual/system-lib/dist/router-browser';
import { QueryClient } from '@kevisual/system-lib/dist/query-browser';
import { Page } from '@kevisual/system-lib/dist/web-page';
import { BaseLoad } from '@kevisual/system-lib/dist/load';
import { Message } from '@kevisual/system-ui/dist/message';
export { useContextKey };
export const message = useContextKey<Message>('message', () => {
return new Message();
});
export const load = useContextKey<BaseLoad>('load', () => {
return new BaseLoad();
});
export const app = useContextKey<QueryRouterServer>('app');
export const page = useContextKey<Page>('page');
export const query = useContextKey<QueryClient>('query', () => {
return new QueryClient({
io: true,
});
});
export const workCache = useContextKey<MyCache>('workCache', () => {
return new MyCache('work');
});
export const queryAI = useContextKey<QueryAI>('queryAI', () => {
return new QueryAI();
});
export const initAIAppRootOrCreate = () => {
const root = document.getElementById('ai-root');
if (!root) {
const root = document.createElement('div');
root.id = 'ai-root';
document.body.appendChild(root);
}
return root;
};

39
template/index.ts Normal file
View File

@@ -0,0 +1,39 @@
import { app, page, load } from './app';
import './ai-app/main';
import './tailwind.css';
import './workspace/entry';
page.addPage('/', 'workspace');
const runLoad = () => {
load.load(
() => {
// @TODO 这里需要优化,不能每次都去调用
page.subscribe(
'workspace',
async () => {
await app.call({
path: 'workspace',
key: 'enter',
});
setTimeout(() => {
app.call({
path: 'ai',
key: 'render',
});
}, 1000);
},
{ runImmediately: true },
);
},
{
key: 'workspaceRoute',
isReRun: true,
checkSuccess: () => {
return page.pageModule.has('workspace');
},
},
);
};
// runLoad()

32
template/tailwind.css Normal file
View File

@@ -0,0 +1,32 @@
@import 'tailwindcss';
#ai-root {
width: 100%;
height: 100%;
background-color: #f0f0f0;
position: fixed;
top: 0;
left: 0;
z-index: 900;
}
/* # 背景设置为透明 */
#ai-root {
/* @apply bg-transparent */
@apply border-none box-border border-2 border-gray-300 rounded-md;
@apply pointer-events-none;
}
#ai-root {
.node-editor {
@apply pointer-events-auto;
@apply absolute bottom-0 left-0 w-full h-[20vh] border border-gray-300 shadow-md;
.tiptap {
@apply mx-0 h-full overflow-y-auto;
}
}
#app {
@apply w-full h-full overflow-hidden;
}
}

6
template/user/route.ts Normal file
View File

@@ -0,0 +1,6 @@
import { app } from '../app';
app.route({
path: 'user',
key: 'login',
});

View File

@@ -0,0 +1,50 @@
import { message } from '../../app';
import { query } from '../../app';
import { createStore } from 'zustand/vanilla';
type User = {
id: string;
username?: string;
nickname?: string;
avatar: string;
};
interface UserWallStore {
user?: User;
setUser: (user: User) => void;
/**
* 查询用户信息,用户没有登陆,则打开登陆页面
* @param openOnNoLogin
* @returns
*/
queryMe: (openOnNoLogin?: boolean) => Promise<void>;
logout: () => void;
isLogin: () => boolean;
}
export const useUserWallStore = createStore<UserWallStore>((set, get) => ({
user: undefined,
setUser: (user: User) => set({ user }),
queryMe: async (openOnNoLogin = true) => {
const res = await query.post(
{
path: 'user',
key: 'me',
},
{
afterResponse: !openOnNoLogin ? async (res) => res : undefined,
},
);
console.log('queryMe', res);
if (res.code === 200) {
set({ user: res.data });
}
},
logout: () => {
set({ user: undefined });
localStorage.removeItem('token');
},
isLogin: () => {
return !!get().user;
},
}));

View File

@@ -0,0 +1,25 @@
import { app } from '../app';
app
.route({
path: 'wallnote',
key: 'list',
validator: {
pagiantion: {
type: 'object',
properties: {
page: {
type: 'number',
},
},
},
},
run: async (ctx) => {
const { pagiantion } = ctx.validator.pagiantion;
const { page } = pagiantion;
const { data } = await ctx.query.get('/wallnote/list', {
page,
});
},
})
.addTo(app);

View File

@@ -0,0 +1,29 @@
import { app, page } from '../app';
import { message } from '@kevisual/system-ui/dist/message';
let isRender = false;
app
.route({
path: 'workspace',
key: 'enter',
run: async (ctx) => {
// 第一次进入页面获取用户信息如果没有登陆则去登陆TODO
// 只根据id来判断工作区。
const url = new URL(location.href);
const isWorksapce = url.pathname.startsWith('/workspace');
if (!isWorksapce) {
message.error('请先进入工作区');
return;
}
console.log('workspace enter');
if (!isRender) {
app.call({
path: 'wallnote',
key: 'render',
});
isRender = true;
}
ctx.body = '';
},
})
.addTo(app);