generated from template/vite-react-template
feat: update new feature temp for panel
This commit is contained in:
5
template/ai-app/AiApp.tsx
Normal file
5
template/ai-app/AiApp.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const AiApp = () => {
|
||||
return <div>AiApp</div>;
|
||||
};
|
||||
28
template/ai-app/main.tsx
Normal file
28
template/ai-app/main.tsx
Normal 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);
|
||||
@@ -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
39
template/index.ts
Normal 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
32
template/tailwind.css
Normal 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
6
template/user/route.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { app } from '../app';
|
||||
|
||||
app.route({
|
||||
path: 'user',
|
||||
key: 'login',
|
||||
});
|
||||
50
template/user/store/index.ts
Normal file
50
template/user/store/index.ts
Normal 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;
|
||||
},
|
||||
}));
|
||||
25
template/wallnote/entry.ts
Normal file
25
template/wallnote/entry.ts
Normal 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);
|
||||
29
template/workspace/entry.ts
Normal file
29
template/workspace/entry.ts
Normal 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);
|
||||
|
||||
Reference in New Issue
Block a user