feat: add cnb API module with various endpoints for workspace management, repository operations, and issue tracking

This commit is contained in:
2026-03-10 01:23:18 +08:00
parent 253ef2ac7d
commit 4ed81a1c68
10 changed files with 1264 additions and 288 deletions

View File

@@ -3,28 +3,14 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
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 = () => {
const { config, setConfig, resetConfig, saveToRemote, loadFromRemote } = useConfigStore();
const layoutStore = useLayoutStore(useShallow(state => ({ me: state.me })))
const { config, setConfig, saveToRemote, loadFromRemote } = useConfigStore();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
const result = configSchema.safeParse(config);
if (result.success) {
toast.success('配置已保存')
setTimeout(() => {
location.reload()
}, 400)
} else {
console.error('验证错误:', result.error.format());
}
saveToRemote();
};
const handleChange = (field: keyof typeof config, value: string | boolean) => {
@@ -105,87 +91,13 @@ export const ConfigPage = () => {
/>
</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">
<Button type="submit"></Button>
<Button type="button" variant="outline" onClick={resetConfig}>
<Button type="button" variant="outline" onClick={loadFromRemote}>
</Button>
<Button type="button" variant="outline" onClick={saveToRemote}>
</Button>
{layoutStore.me && <>
<Button type="button" variant="outline" onClick={loadFromRemote}>
</Button>
<Button type="button" variant="outline" onClick={saveToRemote}>
</Button>
</>
}
</div>
</form>
</CardContent>