generated from kevisual/vite-react-template
feat: add cnb API module with various endpoints for workspace management, repository operations, and issue tracking
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/cnb-center",
|
"name": "@kevisual/cnb-center",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.7",
|
"version": "0.0.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"basename": "/root/cnb-center",
|
"basename": "/root/cnb-center",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"ui": "pnpm dlx shadcn@latest add ",
|
"ui": "pnpm dlx shadcn@latest add ",
|
||||||
"pub": "envision deploy ./dist -k cnb-center -v 0.0.7 -y y -u"
|
"pub": "envision deploy ./dist -k cnb-center -v 0.0.8 -y y -u"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
|
|||||||
@@ -1,28 +1,9 @@
|
|||||||
import { QueryRouterServer } from '@kevisual/router/browser'
|
import { QueryRouterServer } from '@kevisual/router/browser'
|
||||||
|
|
||||||
import { useContextKey } from '@kevisual/context'
|
import { useContextKey } from '@kevisual/context'
|
||||||
import { useConfigStore } from '@/pages/config/store'
|
|
||||||
import { useGiteaConfigStore } from '@/pages/config/gitea/store'
|
import { useGiteaConfigStore } from '@/pages/config/gitea/store'
|
||||||
import { CNB } from '@kevisual/cnb'
|
|
||||||
import { Gitea } from '@kevisual/gitea';
|
import { Gitea } from '@kevisual/gitea';
|
||||||
export const app = useContextKey('app', new QueryRouterServer())
|
export const app = useContextKey('app', new QueryRouterServer())
|
||||||
|
|
||||||
export const cnb: CNB = useContextKey('cnb', () => {
|
|
||||||
const state = useConfigStore.getState()
|
|
||||||
const config = state.config || {}
|
|
||||||
const cors: any = {}
|
|
||||||
if (config.ENABLE_CORS) {
|
|
||||||
cors.baseUrl = config.CNB_CORS_URL || 'https://cors.kevisual.cn'
|
|
||||||
}
|
|
||||||
console.log('state', state)
|
|
||||||
// if(state.config.)
|
|
||||||
return new CNB({
|
|
||||||
token: config.CNB_API_KEY,
|
|
||||||
cookie: config.CNB_COOKIE,
|
|
||||||
cors
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// import '@kevisual/cnb-ai'
|
// import '@kevisual/cnb-ai'
|
||||||
|
|
||||||
const url = 'https://kevisual.cn/root/cnb-ai/dist/app.js'
|
const url = 'https://kevisual.cn/root/cnb-ai/dist/app.js'
|
||||||
|
|||||||
1227
src/modules/cnb-api.ts
Normal file
1227
src/modules/cnb-api.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,28 +3,14 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
|
|||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import { Info } from 'lucide-react';
|
import { Info } from 'lucide-react';
|
||||||
import { configSchema } from './store/schema';
|
|
||||||
import { toast } from 'sonner';
|
|
||||||
import { useLayoutStore } from '../auth/store';
|
|
||||||
import { useShallow } from 'zustand/shallow';
|
|
||||||
|
|
||||||
export const ConfigPage = () => {
|
export const ConfigPage = () => {
|
||||||
const { config, setConfig, resetConfig, saveToRemote, loadFromRemote } = useConfigStore();
|
const { config, setConfig, saveToRemote, loadFromRemote } = useConfigStore();
|
||||||
const layoutStore = useLayoutStore(useShallow(state => ({ me: state.me })))
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const result = configSchema.safeParse(config);
|
saveToRemote();
|
||||||
if (result.success) {
|
|
||||||
toast.success('配置已保存')
|
|
||||||
setTimeout(() => {
|
|
||||||
location.reload()
|
|
||||||
}, 400)
|
|
||||||
} else {
|
|
||||||
console.error('验证错误:', result.error.format());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (field: keyof typeof config, value: string | boolean) => {
|
const handleChange = (field: keyof typeof config, value: string | boolean) => {
|
||||||
@@ -105,87 +91,13 @@ export const ConfigPage = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="cors-url">跨域地址</Label>
|
|
||||||
<Input
|
|
||||||
id="cors-url"
|
|
||||||
type="url"
|
|
||||||
value={config.CNB_CORS_URL}
|
|
||||||
onChange={(e) => handleChange('CNB_CORS_URL', e.target.value)}
|
|
||||||
placeholder="https://cors.example.com"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<Checkbox
|
|
||||||
id="enable-cors"
|
|
||||||
checked={config.ENABLE_CORS}
|
|
||||||
onCheckedChange={(checked) => handleChange('ENABLE_CORS', checked === true)}
|
|
||||||
/>
|
|
||||||
<Label htmlFor="enable-cors" className="cursor-pointer">
|
|
||||||
启用跨域
|
|
||||||
</Label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="ai-base-url">AI 基础地址</Label>
|
|
||||||
<Input
|
|
||||||
id="ai-base-url"
|
|
||||||
type="url"
|
|
||||||
value={config.AI_BASE_URL}
|
|
||||||
onChange={(e) => handleChange('AI_BASE_URL', e.target.value)}
|
|
||||||
placeholder="请输入 AI 基础地址"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="ai-model">AI 模型</Label>
|
|
||||||
<Input
|
|
||||||
id="ai-model"
|
|
||||||
type="text"
|
|
||||||
value={config.AI_MODEL}
|
|
||||||
onChange={(e) => handleChange('AI_MODEL', e.target.value)}
|
|
||||||
placeholder="请输入 AI 模型名称"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Label htmlFor="ai-api-key">AI 密钥</Label>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<Info className="h-4 w-4 text-muted-foreground cursor-help" />
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p>
|
|
||||||
如果使用 CNB 的 AI,密钥和 API 密钥一样即可
|
|
||||||
</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<Input
|
|
||||||
id="ai-api-key"
|
|
||||||
type="password"
|
|
||||||
value={config.AI_API_KEY}
|
|
||||||
onChange={(e) => handleChange('AI_API_KEY', e.target.value)}
|
|
||||||
placeholder="请输入您的 AI API 密钥"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<Button type="submit">保存配置</Button>
|
|
||||||
<Button type="button" variant="outline" onClick={resetConfig}>
|
|
||||||
重置为默认值
|
|
||||||
</Button>
|
|
||||||
{layoutStore.me && <>
|
|
||||||
<Button type="button" variant="outline" onClick={loadFromRemote}>
|
<Button type="button" variant="outline" onClick={loadFromRemote}>
|
||||||
获取远端配置
|
获取远端配置
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="button" variant="outline" onClick={saveToRemote}>
|
<Button type="button" variant="outline" onClick={saveToRemote}>
|
||||||
保存到远端
|
保存到远端
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
import type { Config, defaultConfig } from './schema';
|
import type { Config, } from './schema';
|
||||||
import { queryLogin } from '@/modules/query';
|
import { queryLogin } from '@/modules/query';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
@@ -18,11 +18,6 @@ const STORAGE_KEY = 'cnb-config';
|
|||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
CNB_API_KEY: '',
|
CNB_API_KEY: '',
|
||||||
CNB_COOKIE: '',
|
CNB_COOKIE: '',
|
||||||
CNB_CORS_URL: 'https://cors.kevisual.cn',
|
|
||||||
ENABLE_CORS: true,
|
|
||||||
AI_BASE_URL: 'https://api.cnb.cool/kevisual/cnb-ai/-/ai/',
|
|
||||||
AI_MODEL: 'CNB-Models',
|
|
||||||
AI_API_KEY: ''
|
|
||||||
}
|
}
|
||||||
const loadInitialConfig = (): Config => {
|
const loadInitialConfig = (): Config => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3,11 +3,6 @@ import { z } from 'zod';
|
|||||||
export const configSchema = z.object({
|
export const configSchema = z.object({
|
||||||
CNB_API_KEY: z.string().min(1, 'API Key is required'),
|
CNB_API_KEY: z.string().min(1, 'API Key is required'),
|
||||||
CNB_COOKIE: z.string().min(1, 'Cookie is required'),
|
CNB_COOKIE: z.string().min(1, 'Cookie is required'),
|
||||||
CNB_CORS_URL: z.url('Must be a valid URL'),
|
|
||||||
ENABLE_CORS: z.boolean(),
|
|
||||||
AI_BASE_URL: z.url('Must be a valid URL'),
|
|
||||||
AI_MODEL: z.string().min(1, 'AI Model is required'),
|
|
||||||
AI_API_KEY: z.string().min(1, 'AI API Key is required'),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type Config = z.infer<typeof configSchema>;
|
export type Config = z.infer<typeof configSchema>;
|
||||||
@@ -15,9 +10,4 @@ export type Config = z.infer<typeof configSchema>;
|
|||||||
export const defaultConfig: Config = {
|
export const defaultConfig: Config = {
|
||||||
CNB_API_KEY: '',
|
CNB_API_KEY: '',
|
||||||
CNB_COOKIE: '',
|
CNB_COOKIE: '',
|
||||||
CNB_CORS_URL: 'https://cors.kevisual.cn',
|
|
||||||
ENABLE_CORS: true,
|
|
||||||
AI_BASE_URL: '',
|
|
||||||
AI_MODEL: '',
|
|
||||||
AI_API_KEY: ''
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { useRepoStore } from '../store'
|
|||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { useShallow } from 'zustand/shallow'
|
import { useShallow } from 'zustand/shallow'
|
||||||
import { myOrgs } from '../store/build'
|
import { myOrgs } from '../store/build'
|
||||||
import { app, cnb } from '@/agents/app'
|
import { app } from '@/agents/app'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { useNavigate } from '@tanstack/react-router'
|
import { useNavigate } from '@tanstack/react-router'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export function EditRepoDialog({ open, onOpenChange, repo }: EditRepoDialogProps
|
|||||||
path: repo.path,
|
path: repo.path,
|
||||||
description: data.description?.trim() || '',
|
description: data.description?.trim() || '',
|
||||||
site: data.site?.trim() || '',
|
site: data.site?.trim() || '',
|
||||||
topics: tags.join(','),
|
topics: tags as any,
|
||||||
license: data.license?.trim() || '',
|
license: data.license?.trim() || '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { query } from '@/modules/query';
|
import { query } from '@/modules/query';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { cnb } from '@/agents/app'
|
import { queryApi as cnbApi } from '@/modules/cnb-api'
|
||||||
import { WorkspaceInfo } from '@kevisual/cnb'
|
import { WorkspaceInfo } from '@kevisual/cnb'
|
||||||
import { createBuildConfig, createCommitBlankConfig, createDevConfig } from './build';
|
import { createBuildConfig, createCommitBlankConfig, createDevConfig } from './build';
|
||||||
import { useLayoutStore } from '@/pages/auth/store';
|
import { useLayoutStore } from '@/pages/auth/store';
|
||||||
import { useConfigStore } from '@/pages/config/store';
|
|
||||||
interface DisplayModule {
|
interface DisplayModule {
|
||||||
activity: boolean;
|
activity: boolean;
|
||||||
contributors: boolean;
|
contributors: boolean;
|
||||||
@@ -77,7 +76,7 @@ type State = {
|
|||||||
showCreateDialog: boolean;
|
showCreateDialog: boolean;
|
||||||
setShowCreateDialog: (show: boolean) => void;
|
setShowCreateDialog: (show: boolean) => void;
|
||||||
getList: (params?: { search?: string }, silent?: boolean) => Promise<any>;
|
getList: (params?: { search?: string }, silent?: boolean) => Promise<any>;
|
||||||
updateRepoInfo: (data: Partial<Data>) => Promise<any>;
|
updateRepoInfo: (data: Partial<Data & { topics: string[] }>) => Promise<any>;
|
||||||
createRepo: (data: { visibility: any, path: string, description: string, license: string }) => Promise<any>;
|
createRepo: (data: { visibility: any, path: string, description: string, license: string }) => Promise<any>;
|
||||||
deleteItem: (repo: string) => Promise<any>;
|
deleteItem: (repo: string) => Promise<any>;
|
||||||
workspaceList: WorkspaceInfo[];
|
workspaceList: WorkspaceInfo[];
|
||||||
@@ -236,9 +235,10 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
toast.error('请先保存构建配置');
|
toast.error('请先保存构建配置');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const res = await cnb.build.startBuild(config.repo, {
|
const res = await cnbApi.cnb['cloud-build']({
|
||||||
|
repo: config.repo,
|
||||||
branch: config.branch,
|
branch: config.branch,
|
||||||
env: {},
|
env: {} as any,
|
||||||
event: config.event,
|
event: config.event,
|
||||||
config: config.config,
|
config: config.config,
|
||||||
})
|
})
|
||||||
@@ -252,7 +252,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
const { setLoading } = get();
|
const { setLoading } = get();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await cnb.repo.getRepo(repo)
|
const res = await cnbApi.cnb['get-repo']({ name: repo })
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const data = res.data!;
|
const data = res.data!;
|
||||||
set({ editRepo: data })
|
set({ editRepo: data })
|
||||||
@@ -275,9 +275,9 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
search: params.search
|
search: params.search
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const res = await cnb.repo.getRepoList(opts)
|
const res = await cnbApi.cnb['list-repos'](opts)
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const list = res.data! || []
|
const list = res.data?.list || []
|
||||||
set({ list });
|
set({ list });
|
||||||
} else {
|
} else {
|
||||||
toast.error(res.message || '请求失败');
|
toast.error(res.message || '请求失败');
|
||||||
@@ -291,7 +291,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
},
|
},
|
||||||
updateRepoInfo: async (data) => {
|
updateRepoInfo: async (data) => {
|
||||||
const repo = data.path!;
|
const repo = data.path!;
|
||||||
let topics = data.topics?.split?.(',');
|
let topics = data.topics as string[];
|
||||||
if (Array.isArray(topics)) {
|
if (Array.isArray(topics)) {
|
||||||
topics = topics.map(t => t.trim()).filter(Boolean);
|
topics = topics.map(t => t.trim()).filter(Boolean);
|
||||||
}
|
}
|
||||||
@@ -299,12 +299,12 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
topics.push('cnb-center')
|
topics.push('cnb-center')
|
||||||
}
|
}
|
||||||
const updateData = {
|
const updateData = {
|
||||||
description: data.description,
|
description: data.description!,
|
||||||
license: data?.license as any,
|
license: data?.license as any,
|
||||||
site: data.site,
|
site: data.site,
|
||||||
topics: topics
|
topics: topics
|
||||||
}
|
}
|
||||||
const res = await cnb.repo.updateRepoInfo(repo, updateData)
|
const res = await cnbApi.cnb['update-repo-info']({ name: repo, ...updateData })
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
toast.success('更新成功');
|
toast.success('更新成功');
|
||||||
} else {
|
} else {
|
||||||
@@ -329,7 +329,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
description: data.description || '',
|
description: data.description || '',
|
||||||
license: data?.license as any,
|
license: data?.license as any,
|
||||||
};
|
};
|
||||||
const res = await cnb.repo.createRepo(createData);
|
const res = await cnbApi.cnb['create-repo'](createData);
|
||||||
console.log('res', res)
|
console.log('res', res)
|
||||||
// if (res.code === 200) {
|
// if (res.code === 200) {
|
||||||
// toast.success('仓库创建成功');
|
// toast.success('仓库创建成功');
|
||||||
@@ -345,7 +345,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
},
|
},
|
||||||
deleteItem: async (repo: string) => {
|
deleteItem: async (repo: string) => {
|
||||||
try {
|
try {
|
||||||
const res = await cnb.repo.deleteRepoCookie(repo)
|
const res = await cnbApi.cnb['delete-repo']({ name: repo });
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
toast.success('删除成功');
|
toast.success('删除成功');
|
||||||
// 刷新列表
|
// 刷新列表
|
||||||
@@ -367,7 +367,8 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
},
|
},
|
||||||
workspaceList: [],
|
workspaceList: [],
|
||||||
getWorkspaceList: async () => {
|
getWorkspaceList: async () => {
|
||||||
const res = await cnb.workspace.list({
|
// const res = await cnb.workspace.list({
|
||||||
|
const res = await cnbApi.cnb['list-workspace']({
|
||||||
status: 'running',
|
status: 'running',
|
||||||
pageSize: 100
|
pageSize: 100
|
||||||
})
|
})
|
||||||
@@ -381,9 +382,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
startWorkspace: async (data, params = { open: true, branch: 'main' }) => {
|
startWorkspace: async (data, params = { open: true, branch: 'main' }) => {
|
||||||
const repo = data.path;
|
const repo = data.path;
|
||||||
const checkOpen = async () => {
|
const checkOpen = async () => {
|
||||||
const res = await cnb.workspace.startWorkspace(repo!, {
|
const res = await cnbApi.cnb['start-workspace']({ repo: repo!, branch: params.branch || 'main' });
|
||||||
branch: params.branch || 'main'
|
|
||||||
})
|
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
if (!res?.data?.sn) {
|
if (!res?.data?.sn) {
|
||||||
const url = res.data?.url! || '';
|
const url = res.data?.url! || '';
|
||||||
@@ -456,7 +455,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
toast.error('未选择工作区');
|
toast.error('未选择工作区');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const res = await cnb.workspace.stopWorkspace({ sn });
|
const res = await cnbApi.cnb['stop-workspace']({ sn })
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (res?.code === 200) {
|
if (res?.code === 200) {
|
||||||
toast.success('工作区已停止');
|
toast.success('工作区已停止');
|
||||||
@@ -469,7 +468,7 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
},
|
},
|
||||||
selectWorkspace: undefined,
|
selectWorkspace: undefined,
|
||||||
getWorkspaceDetail: async (workspaceInfo) => {
|
getWorkspaceDetail: async (workspaceInfo) => {
|
||||||
const res = await cnb.workspace.getDetail(workspaceInfo.slug, workspaceInfo.sn) as any;
|
const res = await cnbApi.cnb['get-workspace']({ repo: workspaceInfo.slug, sn: workspaceInfo.sn }) as any;
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
set({
|
set({
|
||||||
workspaceLink: res.data,
|
workspaceLink: res.data,
|
||||||
@@ -488,9 +487,10 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let event = toRepo ? 'api_trigger_sync_to_gitea' : 'api_trigger_sync_from_gitea';
|
let event = toRepo ? 'api_trigger_sync_to_gitea' : 'api_trigger_sync_from_gitea';
|
||||||
const res = await cnb.build.startBuild(repo, {
|
const res = await cnbApi.cnb['cloud-build']({
|
||||||
|
repo: toRepo! || fromRepo!,
|
||||||
branch: 'main',
|
branch: 'main',
|
||||||
env: {},
|
env: {} as any,
|
||||||
event: event,
|
event: event,
|
||||||
config: createBuildConfig({ repo: toRepo! || fromRepo! }),
|
config: createBuildConfig({ repo: toRepo! || fromRepo! }),
|
||||||
})
|
})
|
||||||
@@ -501,9 +501,10 @@ export const useRepoStore = create<State>((set, get) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
buildUpdate: async (data) => {
|
buildUpdate: async (data) => {
|
||||||
const res = await cnb.build.startBuild(data.path!, {
|
const res = await cnbApi.cnb['cloud-build']({
|
||||||
|
repo: data.path!,
|
||||||
branch: 'main',
|
branch: 'main',
|
||||||
env: {},
|
env: {} as any,
|
||||||
event: 'api_trigger_event',
|
event: 'api_trigger_event',
|
||||||
config: createCommitBlankConfig({ repo: data.path!, event: 'api_trigger_event' }),
|
config: createCommitBlankConfig({ repo: data.path!, event: 'api_trigger_event' }),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
import { create } from 'zustand';
|
|
||||||
import { query } from '@/modules/query';
|
|
||||||
import { toast } from 'sonner';
|
|
||||||
import { cnb } from '@/agents/app'
|
|
||||||
|
|
||||||
interface DisplayModule {
|
|
||||||
activity: boolean;
|
|
||||||
contributors: boolean;
|
|
||||||
release: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Languages {
|
|
||||||
language: string;
|
|
||||||
color: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Data {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
freeze: boolean;
|
|
||||||
status: number;
|
|
||||||
visibility_level: string;
|
|
||||||
flags: string;
|
|
||||||
created_at: string;
|
|
||||||
updated_at: string;
|
|
||||||
description: string;
|
|
||||||
site: string;
|
|
||||||
topics: string;
|
|
||||||
license: string;
|
|
||||||
display_module: DisplayModule;
|
|
||||||
star_count: number;
|
|
||||||
fork_count: number;
|
|
||||||
mark_count: number;
|
|
||||||
last_updated_at?: string | null;
|
|
||||||
web_url: string;
|
|
||||||
path: string;
|
|
||||||
tags: any;
|
|
||||||
open_issue_count: number;
|
|
||||||
open_pull_request_count: number;
|
|
||||||
languages: Languages;
|
|
||||||
second_languages: Languages;
|
|
||||||
last_update_username: string;
|
|
||||||
last_update_nickname: string;
|
|
||||||
access: string;
|
|
||||||
stared: boolean;
|
|
||||||
star_time: string;
|
|
||||||
pinned: boolean;
|
|
||||||
pinned_time: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
formData: Record<string, any>;
|
|
||||||
setFormData: (data: Record<string, any>) => void;
|
|
||||||
showEdit: boolean;
|
|
||||||
setShowEdit: (showEdit: boolean) => void;
|
|
||||||
loading: boolean;
|
|
||||||
setLoading: (loading: boolean) => void;
|
|
||||||
list: Data[];
|
|
||||||
editRepo: Data | null;
|
|
||||||
setEditRepo: (repo: Data | null) => void;
|
|
||||||
showEditDialog: boolean;
|
|
||||||
setShowEditDialog: (show: boolean) => void;
|
|
||||||
getList: () => Promise<any>;
|
|
||||||
updateRepoInfo: (data: Partial<Data>) => Promise<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useRepoStore = create<State>((set, get) => {
|
|
||||||
return {
|
|
||||||
formData: {},
|
|
||||||
setFormData: (data) => set({ formData: data }),
|
|
||||||
showEdit: false,
|
|
||||||
setShowEdit: (showEdit) => set({ showEdit }),
|
|
||||||
loading: false,
|
|
||||||
setLoading: (loading) => set({ loading }),
|
|
||||||
list: [],
|
|
||||||
editRepo: null,
|
|
||||||
setEditRepo: (repo) => set({ editRepo: repo }),
|
|
||||||
showEditDialog: false,
|
|
||||||
setShowEditDialog: (show) => set({ showEditDialog: show }),
|
|
||||||
getItem: async (id) => {
|
|
||||||
const { setLoading } = get();
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
const res = await query.post({
|
|
||||||
path: 'demo',
|
|
||||||
key: 'item',
|
|
||||||
data: { id }
|
|
||||||
})
|
|
||||||
if (res.code === 200) {
|
|
||||||
return res;
|
|
||||||
} else {
|
|
||||||
toast.error(res.message || '请求失败');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getList: async () => {
|
|
||||||
const { setLoading } = get();
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
const res = await cnb.repo.getRepoList({})
|
|
||||||
if (res.code === 200) {
|
|
||||||
const list = res.data! || []
|
|
||||||
set({ list });
|
|
||||||
} else {
|
|
||||||
toast.error(res.message || '请求失败');
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateRepoInfo: async (data) => {
|
|
||||||
const repo = data.path!;
|
|
||||||
const updateData = {
|
|
||||||
description: data.description,
|
|
||||||
license: data?.license as any,
|
|
||||||
site: data.site,
|
|
||||||
topics: data.topics?.split?.(','),
|
|
||||||
}
|
|
||||||
const res = await cnb.repo.updateRepoInfo(repo, updateData)
|
|
||||||
if (res.code === 200) {
|
|
||||||
toast.success('更新成功');
|
|
||||||
} else {
|
|
||||||
toast.error(res.message || '更新失败');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user