From 05c8496469effdec432aeb0e99730e25917272d7 Mon Sep 17 00:00:00 2001 From: abearxiong Date: Sat, 14 Feb 2026 03:06:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=87=B3=200.0.49=EF=BC=8C=E6=96=B0=E5=A2=9E=20storeList=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98=E5=8C=96=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=8C=E6=B7=BB=E5=8A=A0=20store-auth=20?= =?UTF-8?q?=E5=92=8C=20store-mark=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bun.config.ts | 13 ++- package.json | 15 ++-- pnpm-lock.yaml | 68 ++++++++++++++++ query/query-login/login-cache.ts | 4 + query/query-login/query-login.ts | 45 ++++++----- src/get-query-list.ts | 20 ++++- store/store-auth/index.ts | 66 ++++++++++++++++ store/store-mark/index.ts | 132 +++++++++++++++++++++++++++++++ tsconfig.json | 23 ++++++ 9 files changed, 360 insertions(+), 26 deletions(-) create mode 100644 store/store-auth/index.ts create mode 100644 store/store-mark/index.ts create mode 100644 tsconfig.json diff --git a/bun.config.ts b/bun.config.ts index fd5b76e..e14caea 100644 --- a/bun.config.ts +++ b/bun.config.ts @@ -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, + }) } \ No newline at end of file diff --git a/package.json b/package.json index 3bda8a4..2320c13 100644 --- a/package.json +++ b/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/*" } } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ddfd01..abd6954 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/query/query-login/login-cache.ts b/query/query-login/login-cache.ts index 0ee1bf9..31d6012 100644 --- a/query/query-login/login-cache.ts +++ b/query/query-login/login-cache.ts @@ -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 { 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); } diff --git a/query/query-login/query-login.ts b/query/query-login/query-login.ts index 00c97fd..2e78ee6 100644 --- a/query/query-login/query-login.ts +++ b/query/query-login/query-login.ts @@ -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({ 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({ 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({ 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'; */ diff --git a/src/get-query-list.ts b/src/get-query-list.ts index 9aeec81..04b0bd4 100644 --- a/src/get-query-list.ts +++ b/src/get-query-list.ts @@ -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); \ No newline at end of file +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); \ No newline at end of file diff --git a/store/store-auth/index.ts b/store/store-auth/index.ts new file mode 100644 index 0000000..4cd91dc --- /dev/null +++ b/store/store-auth/index.ts @@ -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('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; + openUser: boolean; + setOpenUser: (openUser: boolean) => void; + switchOrg: (username?: string, type?: 'user' | 'org') => Promise; + isAdmin: boolean; + setIsAdmin: (isAdmin: boolean) => void; + checkHasOrg: () => boolean; +}; +export const useLayoutStore = create((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; + }, +})); diff --git a/store/store-mark/index.ts b/store/store-mark/index.ts new file mode 100644 index 0000000..f758ea8 --- /dev/null +++ b/store/store-mark/index.ts @@ -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('queryLogin'); + +type ManagerStore = { + /** 当前选中的Mark */ + currentMarkId: string; + setCurrentMarkId: (markId: string) => void; + markData?: Mark | undefined; + setMarkData: (mark?: Partial) => void; + /** 获取Mark列表 */ + getList: () => Promise; + getMarkFromList: (markId: string) => Mark | undefined; + updateMark: (mark: Mark) => Promise; + getMark: (markId: string) => Promise>; + deleteMark: (markId: string) => Promise; + /** 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; + queryMark?: QueryMark; + markType?: MarkType; + open: boolean; + setOpen: (open: boolean) => void; +}; +export const useMarkStore = create((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) => 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 } })), + }; +}); + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4d48c6e --- /dev/null +++ b/tsconfig.json @@ -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", + ] +} \ No newline at end of file