feat: 更新版本至 0.0.49,新增 storeList 支持,优化登录缓存,添加 store-auth 和 store-mark 功能
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { buildWithBun } from '@kevisual/code-builder'
|
||||
import { queryList } from './src/get-query-list.ts'
|
||||
import { queryList, storeList } from './src/get-query-list.ts'
|
||||
|
||||
// await buildWithBun({ naming: "app", entry: "query/index.ts", meta: import.meta, dts: true })
|
||||
|
||||
@@ -11,4 +11,15 @@ for (const query of queryList) {
|
||||
target: 'browser',
|
||||
dts: true,
|
||||
})
|
||||
}
|
||||
|
||||
for (const store of storeList) {
|
||||
await buildWithBun({
|
||||
naming: store.name,
|
||||
entry: `store/${store.name}/index.ts`,
|
||||
meta: import.meta,
|
||||
external: ['sonner', 'zustand', '@kevisual/context'],
|
||||
target: 'browser',
|
||||
dts: true,
|
||||
})
|
||||
}
|
||||
15
package.json
15
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kevisual/api",
|
||||
"version": "0.0.48",
|
||||
"version": "0.0.49",
|
||||
"description": "",
|
||||
"main": "mod.ts",
|
||||
"scripts": {
|
||||
@@ -12,6 +12,7 @@
|
||||
"files": [
|
||||
"dist",
|
||||
"query",
|
||||
"store",
|
||||
"mod.ts"
|
||||
],
|
||||
"keywords": [],
|
||||
@@ -28,15 +29,14 @@
|
||||
"@kevisual/types": "^0.0.12",
|
||||
"@kevisual/use-config": "^1.0.30",
|
||||
"@types/bun": "^1.3.9",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/node": "^25.2.3",
|
||||
"@types/spark-md5": "^3.0.5",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^17.3.1",
|
||||
"fast-glob": "^3.3.3",
|
||||
"ws": "npm:@kevisual/ws"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kevisual/context": "^0.0.4",
|
||||
"@kevisual/js-filter": "^0.0.5",
|
||||
"@kevisual/load": "^0.0.6",
|
||||
"es-toolkit": "^1.44.0",
|
||||
@@ -44,7 +44,9 @@
|
||||
"fuse.js": "^7.1.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"path-browserify-esm": "^1.0.6",
|
||||
"spark-md5": "^3.0.2"
|
||||
"sonner": "^2.0.7",
|
||||
"spark-md5": "^3.0.2",
|
||||
"zustand": "^5.0.11"
|
||||
},
|
||||
"exports": {
|
||||
".": "./mod.ts",
|
||||
@@ -54,9 +56,9 @@
|
||||
"./proxy": "./query/query-proxy/index.ts",
|
||||
"./secret": "./query/query-secret/index.ts",
|
||||
"./resources": "./query/query-resources/index.ts",
|
||||
"./utils": "./dist/utils.js",
|
||||
"./query-secret": "./dist/query-secret.js",
|
||||
"./query-mark": "./dist/query-mark.js",
|
||||
"./utils": "./dist/utils.js",
|
||||
"./query-upload": "./dist/query-upload.js",
|
||||
"./query-app": "./dist/query-app.js",
|
||||
"./query-proxy": "./dist/query-proxy.js",
|
||||
@@ -65,7 +67,10 @@
|
||||
"./query-login": "./dist/query-login.js",
|
||||
"./query-ai": "./dist/query-ai.js",
|
||||
"./query-resources": "./dist/query-resources.js",
|
||||
"./store-mark": "./dist/store-mark.js",
|
||||
"./store-auth": "./dist/store-auth.js",
|
||||
"./src/*": "./src/*",
|
||||
"./store/*": "./src/*",
|
||||
"./query/*": "./query/*"
|
||||
}
|
||||
}
|
||||
68
pnpm-lock.yaml
generated
68
pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@kevisual/context':
|
||||
specifier: ^0.0.4
|
||||
version: 0.0.4
|
||||
'@kevisual/js-filter':
|
||||
specifier: ^0.0.5
|
||||
version: 0.0.5
|
||||
@@ -29,9 +32,15 @@ importers:
|
||||
path-browserify-esm:
|
||||
specifier: ^1.0.6
|
||||
version: 1.0.6
|
||||
sonner:
|
||||
specifier: ^2.0.7
|
||||
version: 2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
spark-md5:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
zustand:
|
||||
specifier: ^5.0.11
|
||||
version: 5.0.11(react@19.2.4)
|
||||
devDependencies:
|
||||
'@kevisual/cache':
|
||||
specifier: ^0.0.5
|
||||
@@ -108,6 +117,9 @@ packages:
|
||||
resolution: {integrity: sha512-0aqATB31/yw4k4s5/xKnfr4DKbUnx8e3Z3BmKbiXTrc+CqWiWTdlGe9bKI9dZ2Df+xNp6g11W4xM2NICNyyCCw==}
|
||||
hasBin: true
|
||||
|
||||
'@kevisual/context@0.0.4':
|
||||
resolution: {integrity: sha512-HJeLeZQLU+7tCluSfOyvkgKLs0HjCZrdJlZgEgKRSa8XTwZfMAUt6J7qZTbrZAHBlPtX68EPu/PI8JMCeu3WAQ==}
|
||||
|
||||
'@kevisual/js-filter@0.0.5':
|
||||
resolution: {integrity: sha512-+S+Sf3K/aP6XtZI2s7TgKOr35UuvUvtpJ9YDW30a+mY0/N8gRuzyKhieBzQN7Ykayzz70uoMavBXut2rUlLgzw==}
|
||||
|
||||
@@ -398,6 +410,15 @@ packages:
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
react-dom@19.2.4:
|
||||
resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
|
||||
peerDependencies:
|
||||
react: ^19.2.4
|
||||
|
||||
react@19.2.4:
|
||||
resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
reusify@1.1.0:
|
||||
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
@@ -405,10 +426,19 @@ packages:
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
scheduler@0.27.0:
|
||||
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
|
||||
|
||||
selfsigned@2.4.1:
|
||||
resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
sonner@2.0.7:
|
||||
resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
||||
react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc
|
||||
|
||||
spark-md5@3.0.2:
|
||||
resolution: {integrity: sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw==}
|
||||
|
||||
@@ -441,6 +471,24 @@ packages:
|
||||
whatwg-url@5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
|
||||
zustand@5.0.11:
|
||||
resolution: {integrity: sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
peerDependencies:
|
||||
'@types/react': '>=18.0.0'
|
||||
immer: '>=9.0.6'
|
||||
react: '>=18.0.0'
|
||||
use-sync-external-store: '>=1.2.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
immer:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
use-sync-external-store:
|
||||
optional: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@kevisual/cache@0.0.5':
|
||||
@@ -451,6 +499,8 @@ snapshots:
|
||||
|
||||
'@kevisual/code-builder@0.0.6': {}
|
||||
|
||||
'@kevisual/context@0.0.4': {}
|
||||
|
||||
'@kevisual/js-filter@0.0.5': {}
|
||||
|
||||
'@kevisual/load@0.0.6':
|
||||
@@ -723,17 +773,31 @@ snapshots:
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
react-dom@19.2.4(react@19.2.4):
|
||||
dependencies:
|
||||
react: 19.2.4
|
||||
scheduler: 0.27.0
|
||||
|
||||
react@19.2.4: {}
|
||||
|
||||
reusify@1.1.0: {}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
scheduler@0.27.0: {}
|
||||
|
||||
selfsigned@2.4.1:
|
||||
dependencies:
|
||||
'@types/node-forge': 1.3.11
|
||||
node-forge: 1.3.1
|
||||
|
||||
sonner@2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
|
||||
dependencies:
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
|
||||
spark-md5@3.0.2: {}
|
||||
|
||||
to-regex-range@5.0.1:
|
||||
@@ -758,3 +822,7 @@ snapshots:
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
|
||||
zustand@5.0.11(react@19.2.4):
|
||||
optionalDependencies:
|
||||
react: 19.2.4
|
||||
|
||||
@@ -31,6 +31,8 @@ export type CacheLoginUser = {
|
||||
id?: string;
|
||||
accessToken?: string;
|
||||
refreshToken?: string;
|
||||
accessTokenExpiresIn?: number;
|
||||
createdAt?: number;
|
||||
};
|
||||
type CacheLogin = {
|
||||
loginUsers: CacheLoginUser[];
|
||||
@@ -162,6 +164,8 @@ export class LoginCacheStore implements CacheStore<any> {
|
||||
this.cacheData.id = user.id;
|
||||
this.cacheData.accessToken = user.accessToken;
|
||||
this.cacheData.refreshToken = user.refreshToken;
|
||||
this.cacheData.accessTokenExpiresIn = user.accessTokenExpiresIn;
|
||||
this.cacheData.createdAt = user.createdAt;
|
||||
await this.setValue(this.cacheData);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export class QueryLogin extends BaseQuery {
|
||||
this.isBrowser = opts?.isBrowser ?? true;
|
||||
this.init();
|
||||
this.onLoad = opts?.onLoad;
|
||||
this.storage = opts?.storage || localStorage;
|
||||
this.storage = opts?.storage || globalThis?.localStorage;
|
||||
}
|
||||
setQuery(query: Query) {
|
||||
this.query = query;
|
||||
@@ -67,9 +67,9 @@ export class QueryLogin extends BaseQuery {
|
||||
async login(data: QueryLoginData) {
|
||||
const res = await this.post<QueryLoginResult>({ key: 'login', ...data });
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -81,9 +81,9 @@ export class QueryLogin extends BaseQuery {
|
||||
async loginByCode(data: { phone: string; code: string }) {
|
||||
const res = await this.post<QueryLoginResult>({ path: 'sms', key: 'login', data });
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -91,17 +91,17 @@ export class QueryLogin extends BaseQuery {
|
||||
* 设置token
|
||||
* @param token
|
||||
*/
|
||||
async setLoginToken(token: { accessToken: string; refreshToken: string }) {
|
||||
const { accessToken, refreshToken } = token;
|
||||
async setLoginToken(token: { accessToken: string; refreshToken: string; accessTokenExpiresIn?: number }) {
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = token;
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
}
|
||||
async loginByWechat(data: { code: string }) {
|
||||
const res = await this.post<QueryLoginResult>({ path: 'wx', key: 'open-login', code: data.code });
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ export class QueryLogin extends BaseQuery {
|
||||
* 登陆成功,需要获取用户信息进行缓存
|
||||
* @param param0
|
||||
*/
|
||||
async beforeSetLoginUser({ accessToken, refreshToken, check401 }: { accessToken?: string; refreshToken?: string; check401?: boolean }) {
|
||||
async beforeSetLoginUser({ accessToken, refreshToken, check401, accessTokenExpiresIn }: { accessTokenExpiresIn?: number, accessToken?: string; refreshToken?: string; check401?: boolean }) {
|
||||
if (accessToken && refreshToken) {
|
||||
const resUser = await this.getMe(accessToken, check401);
|
||||
if (resUser.code === 200) {
|
||||
@@ -137,6 +137,8 @@ export class QueryLogin extends BaseQuery {
|
||||
id: user.id,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
accessTokenExpiresIn,
|
||||
createdAt: Date.now(),
|
||||
});
|
||||
} else {
|
||||
console.error('登录失败');
|
||||
@@ -185,9 +187,9 @@ export class QueryLogin extends BaseQuery {
|
||||
if (hasRefreshToken) {
|
||||
const res = await that.queryRefreshToken(hasRefreshToken);
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
||||
that.storage.setItem('token', accessToken || '');
|
||||
await that.beforeSetLoginUser({ accessToken, refreshToken, check401: false });
|
||||
await that.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn, check401: false });
|
||||
if (refetch && ctx && ctx.req && ctx.req.url && ctx.fetch) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
const url = ctx.req?.url;
|
||||
@@ -336,12 +338,17 @@ export class QueryLogin extends BaseQuery {
|
||||
const user = localUserList.find((userItem) => userItem.user!.username === username);
|
||||
if (user) {
|
||||
this.storage.setItem('token', user.accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken: user.accessToken, refreshToken: user.refreshToken });
|
||||
await this.beforeSetLoginUser({
|
||||
accessToken: user.accessToken,
|
||||
refreshToken: user.refreshToken,
|
||||
accessTokenExpiresIn: user.accessTokenExpiresIn
|
||||
});
|
||||
return {
|
||||
code: 200,
|
||||
data: {
|
||||
accessToken: user.accessToken,
|
||||
refreshToken: user.refreshToken,
|
||||
accessTokenExpiresIn: user.accessTokenExpiresIn,
|
||||
},
|
||||
success: true,
|
||||
message: '切换用户成功',
|
||||
@@ -350,9 +357,9 @@ export class QueryLogin extends BaseQuery {
|
||||
const res = await this.postSwitchUser(username);
|
||||
|
||||
if (res.code === 200) {
|
||||
const { accessToken, refreshToken } = res?.data || {};
|
||||
const { accessToken, refreshToken, accessTokenExpiresIn } = res?.data || {};
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -409,9 +416,9 @@ export class QueryLogin extends BaseQuery {
|
||||
loginToken: token,
|
||||
});
|
||||
if (res.code === 200) {
|
||||
const accessToken = res.data?.accessToken;
|
||||
const { accessTokenExpiresIn, accessToken, refreshToken } = res.data;
|
||||
this.storage.setItem('token', accessToken || '');
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken: res.data?.refreshToken });
|
||||
await this.beforeSetLoginUser({ accessToken, refreshToken, accessTokenExpiresIn });
|
||||
return res;
|
||||
}
|
||||
return false;
|
||||
@@ -421,7 +428,7 @@ export class QueryLogin extends BaseQuery {
|
||||
*
|
||||
*
|
||||
|
||||
import MD5 from 'crypto-js/md5.js';
|
||||
// import MD5 from 'crypto-js/md5.js';
|
||||
import jsonwebtoken from 'jsonwebtoken';
|
||||
|
||||
*/
|
||||
|
||||
@@ -16,4 +16,22 @@ export const queryList = lists.map((filePath) => {
|
||||
// console.log('Query List:', queryList);
|
||||
|
||||
const pkgs = queryList.map(q => q.pkgs).join('\n');
|
||||
console.log('Package Entries:\n\r', pkgs);
|
||||
console.log('Package Entries:\n\r', pkgs);
|
||||
|
||||
const storeLists = glob.sync('store/*/index.ts', {
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
export const storeList = storeLists.map((filePath) => {
|
||||
const segments = filePath.split('/');
|
||||
const storeName = segments[segments.length - 2];
|
||||
return {
|
||||
name: storeName,
|
||||
pkgs: `"./${storeName}": "./dist/${storeName}.js",`
|
||||
};
|
||||
});
|
||||
|
||||
// console.log('Store List:', storeList);
|
||||
|
||||
const storePkgs = storeList.map(s => s.pkgs).join('\n');
|
||||
console.log('Store Entries:\n\r', storePkgs);
|
||||
66
store/store-auth/index.ts
Normal file
66
store/store-auth/index.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
import { create } from 'zustand';
|
||||
import { toast } from 'sonner';
|
||||
import { useContextKey } from '@kevisual/context';
|
||||
import { type QueryLoginBrowser } from '@/query/query-login/index.ts'
|
||||
const queryLogin = useContextKey<QueryLoginBrowser>('queryLogin');
|
||||
|
||||
type Me = {
|
||||
id?: string;
|
||||
username?: string;
|
||||
nickname?: string | null;
|
||||
needChangePassword?: boolean;
|
||||
role?: string;
|
||||
description?: string | null;
|
||||
type?: 'user' | 'org';
|
||||
orgs?: string[];
|
||||
avatar?: string;
|
||||
};
|
||||
export type LayoutStore = {
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
me: Me;
|
||||
setMe: (me: Me) => void;
|
||||
getMe: () => Promise<void>;
|
||||
openUser: boolean;
|
||||
setOpenUser: (openUser: boolean) => void;
|
||||
switchOrg: (username?: string, type?: 'user' | 'org') => Promise<void>;
|
||||
isAdmin: boolean;
|
||||
setIsAdmin: (isAdmin: boolean) => void;
|
||||
checkHasOrg: () => boolean;
|
||||
};
|
||||
export const useLayoutStore = create<LayoutStore>((set, get) => ({
|
||||
open: false,
|
||||
setOpen: (open) => set({ open }),
|
||||
me: {},
|
||||
setMe: (me) => set({ me }),
|
||||
getMe: async () => {
|
||||
const res = await queryLogin.getMe();
|
||||
if (res.code === 200) {
|
||||
set({ me: res.data });
|
||||
set({ isAdmin: res.data.orgs?.includes('admin') });
|
||||
}
|
||||
},
|
||||
openUser: false,
|
||||
setOpenUser: (openUser) => set({ openUser }),
|
||||
switchOrg: async (username?: string, type?: string) => {
|
||||
const res = await queryLogin.switchUser(username || '');
|
||||
if (res.code === 200) {
|
||||
toast.success('Switch success');
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
} else {
|
||||
toast.error(res.message || 'Request failed');
|
||||
}
|
||||
},
|
||||
isAdmin: false,
|
||||
setIsAdmin: (isAdmin) => set({ isAdmin }),
|
||||
checkHasOrg: () => {
|
||||
const user = get().me || {};
|
||||
if (!user.orgs) {
|
||||
return false;
|
||||
}
|
||||
return user?.orgs?.length > 0;
|
||||
},
|
||||
}));
|
||||
132
store/store-mark/index.ts
Normal file
132
store/store-mark/index.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { create } from 'zustand';
|
||||
import { type Result } from '@kevisual/query/query';
|
||||
import { MarkType, Mark, QueryMark } from '@kevisual/api/query-mark';
|
||||
import { uniqBy } from 'es-toolkit';
|
||||
import { useContextKey } from '@kevisual/context';
|
||||
import { type QueryLoginBrowser } from '@/query/query-login/index.ts'
|
||||
const queryClient = useContextKey<QueryLoginBrowser>('queryLogin');
|
||||
|
||||
type ManagerStore = {
|
||||
/** 当前选中的Mark */
|
||||
currentMarkId: string;
|
||||
setCurrentMarkId: (markId: string) => void;
|
||||
markData?: Mark | undefined;
|
||||
setMarkData: (mark?: Partial<Mark>) => void;
|
||||
/** 获取Mark列表 */
|
||||
getList: () => Promise<any>;
|
||||
getMarkFromList: (markId: string) => Mark | undefined;
|
||||
updateMark: (mark: Mark) => Promise<any>;
|
||||
getMark: (markId: string) => Promise<Result<Mark>>;
|
||||
deleteMark: (markId: string) => Promise<any>;
|
||||
/** Mark列表 */
|
||||
list: Mark[];
|
||||
setList: (list: Mark[]) => void;
|
||||
pagination: {
|
||||
current: number;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
};
|
||||
setPagination: (pagination: { current: number; pageSize: number; total: number }) => void;
|
||||
/** 搜索 */
|
||||
search: string;
|
||||
setSearch: (search: string) => void;
|
||||
/** 初始化 */
|
||||
init: (markType: MarkType) => Promise<void>;
|
||||
queryMark?: QueryMark;
|
||||
markType?: MarkType;
|
||||
open: boolean;
|
||||
setOpen: (open: boolean) => void;
|
||||
};
|
||||
export const useMarkStore = create<ManagerStore>((set, get) => {
|
||||
return {
|
||||
currentMarkId: '',
|
||||
setCurrentMarkId: (markId: string) => set(() => ({ currentMarkId: markId })),
|
||||
open: false,
|
||||
setOpen: (open: boolean) => set(() => ({ open })),
|
||||
getList: async () => {
|
||||
const queryMark = get().queryMark!;
|
||||
const { search, pagination } = get();
|
||||
const res = await queryMark.getMarkList({ page: pagination.current, pageSize: pagination.pageSize, search });
|
||||
const oldList = get().list;
|
||||
if (res.code === 200) {
|
||||
const { pagination, list } = res.data || {};
|
||||
const newList = [...oldList, ...list!];
|
||||
const uniqueList = uniqBy(newList, (item) => item.id);
|
||||
set(() => ({ list: uniqueList }));
|
||||
set(() => ({ pagination: { current: pagination!.current, pageSize: pagination!.pageSize, total: pagination!.total } }));
|
||||
}
|
||||
},
|
||||
getMarkFromList: (markId: string) => {
|
||||
return get().list.find((item) => item.id === markId);
|
||||
},
|
||||
updateMark: async (mark: Mark) => {
|
||||
const queryMark = get().queryMark!;
|
||||
const res = await queryMark.updateMark(mark);
|
||||
if (res.code === 200) {
|
||||
set((state) => {
|
||||
const oldList = state.list;
|
||||
const resMark = res.data!;
|
||||
const newList = oldList.map((item) => (item.id === mark.id ? mark : item));
|
||||
if (!mark.id) {
|
||||
newList.unshift(resMark);
|
||||
}
|
||||
return {
|
||||
list: newList,
|
||||
};
|
||||
});
|
||||
}
|
||||
return res;
|
||||
},
|
||||
getMark: async (markId: string) => {
|
||||
const queryMark = get().queryMark!;
|
||||
const res = await queryMark.getMark(markId);
|
||||
return res;
|
||||
},
|
||||
list: [],
|
||||
setList: (list: any[]) => set(() => ({ list })),
|
||||
init: async (markType: MarkType = 'wallnote') => {
|
||||
// await get().getList();
|
||||
console.log('init', set, get);
|
||||
const queryMark = new QueryMark({
|
||||
query: queryClient as any,
|
||||
markType,
|
||||
});
|
||||
const url = new URL(window.location.href);
|
||||
const pageSize = url.searchParams.get('pageSize') || '10';
|
||||
set({ queryMark, markType, list: [], pagination: { current: 1, pageSize: parseInt(pageSize), total: 0 }, currentMarkId: '', markData: undefined });
|
||||
setTimeout(async () => {
|
||||
console.log('get', get);
|
||||
get().getList();
|
||||
}, 1000);
|
||||
},
|
||||
deleteMark: async (markId: string) => {
|
||||
const queryMark = get().queryMark!;
|
||||
const res = await queryMark.deleteMark(markId);
|
||||
const currentMarkId = get().currentMarkId;
|
||||
if (res.code === 200) {
|
||||
// get().getList();
|
||||
set((state) => ({
|
||||
list: state.list.filter((item) => item.id !== markId),
|
||||
}));
|
||||
if (currentMarkId === markId) {
|
||||
set(() => ({ currentMarkId: '', markData: undefined }));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
},
|
||||
queryMark: undefined,
|
||||
markType: 'simple',
|
||||
markData: undefined,
|
||||
setMarkData: (mark?: Partial<Mark>) => set(() => ({ markData: mark as Mark })),
|
||||
pagination: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
},
|
||||
setPagination: (pagination: { current: number; pageSize: number; total: number }) => set(() => ({ pagination })),
|
||||
/** 搜索 */
|
||||
search: '',
|
||||
setSearch: (search: string) => set(() => ({ search, list: [], pagination: { current: 1, pageSize: 10, total: 0 } })),
|
||||
};
|
||||
});
|
||||
|
||||
23
tsconfig.json
Normal file
23
tsconfig.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"extends": "@kevisual/types/json/frontend.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"@/query*": [
|
||||
"query/*"
|
||||
],
|
||||
"@/store*": [
|
||||
"store/*"
|
||||
],
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
},
|
||||
"include": [
|
||||
"src",
|
||||
"query",
|
||||
"store",
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user