generated from kevisual/vite-react-template
feat: 优化mark接口文档和工作空间页面字段
This commit is contained in:
@@ -88,7 +88,7 @@ export const App = () => {
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
||||
}}
|
||||
>
|
||||
<h3 style={{ margin: '0 0 8px 0', fontSize: '16px' }}>{item.name || '未命名'}</h3>
|
||||
<h3 style={{ margin: '0 0 8px 0', fontSize: '16px' }}>{item.title || '未命名'}</h3>
|
||||
<p style={{ margin: '0 0 8px 0', color: '#666', fontSize: '14px' }}>ID: {item.id}</p>
|
||||
<p style={{ margin: '0 0 8px 0', color: '#999', fontSize: '12px' }}>
|
||||
创建时间: {item.created_at ? new Date(item.created_at).toLocaleString() : '-'}
|
||||
@@ -156,22 +156,30 @@ export const App = () => {
|
||||
function CreateDialog({ open, onClose, onSubmit }: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSubmit: (data: { name: string, data?: any }) => Promise<void>;
|
||||
onSubmit: (data: { title: string, tags?: string[], link?: string, summary?: string, description?: string, data?: any }) => Promise<void>;
|
||||
}) {
|
||||
const [name, setName] = useState('');
|
||||
const [title, setTitle] = useState('');
|
||||
const [tags, setTags] = useState('');
|
||||
const [link, setLink] = useState('');
|
||||
const [summary, setSummary] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [data, setData] = useState('');
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setName('');
|
||||
setTitle('');
|
||||
setTags('');
|
||||
setLink('');
|
||||
setSummary('');
|
||||
setDescription('');
|
||||
setData('');
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!name.trim()) {
|
||||
alert('请输入名称');
|
||||
if (!title.trim()) {
|
||||
alert('请输入标题');
|
||||
return;
|
||||
}
|
||||
setSubmitting(true);
|
||||
@@ -186,7 +194,14 @@ function CreateDialog({ open, onClose, onSubmit }: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
await onSubmit({ name: name.trim(), data: parsedData });
|
||||
await onSubmit({
|
||||
title: title.trim(),
|
||||
tags: tags.split(',').map(t => t.trim()).filter(Boolean),
|
||||
link: link.trim(),
|
||||
summary: summary.trim(),
|
||||
description: description.trim(),
|
||||
data: parsedData
|
||||
});
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
@@ -211,17 +226,19 @@ function CreateDialog({ open, onClose, onSubmit }: {
|
||||
background: '#fff',
|
||||
borderRadius: '8px',
|
||||
padding: '24px',
|
||||
width: '480px',
|
||||
maxWidth: '90%'
|
||||
width: '520px',
|
||||
maxWidth: '90%',
|
||||
maxHeight: '90vh',
|
||||
overflow: 'auto'
|
||||
}} onClick={e => e.stopPropagation()}>
|
||||
<h2 style={{ margin: '0 0 20px 0' }}>创建Workspace</h2>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>名称</label>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>标题</label>
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
placeholder="请输入名称"
|
||||
value={title}
|
||||
onChange={e => setTitle(e.target.value)}
|
||||
placeholder="请输入标题"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
@@ -231,6 +248,71 @@ function CreateDialog({ open, onClose, onSubmit }: {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>标签 (逗号分隔)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={tags}
|
||||
onChange={e => setTags(e.target.value)}
|
||||
placeholder="标签1, 标签2, 标签3"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>链接</label>
|
||||
<input
|
||||
type="text"
|
||||
value={link}
|
||||
onChange={e => setLink(e.target.value)}
|
||||
placeholder="https://..."
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>摘要</label>
|
||||
<input
|
||||
type="text"
|
||||
value={summary}
|
||||
onChange={e => setSummary(e.target.value)}
|
||||
placeholder="简要描述"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>描述</label>
|
||||
<textarea
|
||||
value={description}
|
||||
onChange={e => setDescription(e.target.value)}
|
||||
placeholder="详细描述..."
|
||||
rows={3}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box',
|
||||
resize: 'vertical'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>数据 (JSON)</label>
|
||||
<textarea
|
||||
@@ -289,22 +371,30 @@ function EditDialog({ open, item, onClose, onSubmit }: {
|
||||
open: boolean;
|
||||
item: any;
|
||||
onClose: () => void;
|
||||
onSubmit: (id: string, data: { name?: string, data?: any }) => Promise<void>;
|
||||
onSubmit: (id: string, data: { title?: string, tags?: string[], link?: string, summary?: string, description?: string, data?: any }) => Promise<void>;
|
||||
}) {
|
||||
const [name, setName] = useState('');
|
||||
const [title, setTitle] = useState('');
|
||||
const [tags, setTags] = useState('');
|
||||
const [link, setLink] = useState('');
|
||||
const [summary, setSummary] = useState('');
|
||||
const [description, setDescription] = useState('');
|
||||
const [data, setData] = useState('');
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (open && item) {
|
||||
setName(item.name || '');
|
||||
setTitle(item.title || '');
|
||||
setTags(item.tags ? item.tags.join(', ') : '');
|
||||
setLink(item.link || '');
|
||||
setSummary(item.summary || '');
|
||||
setDescription(item.description || '');
|
||||
setData(item.data ? JSON.stringify(item.data, null, 2) : '');
|
||||
}
|
||||
}, [open, item]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!name.trim()) {
|
||||
alert('请输入名称');
|
||||
if (!title.trim()) {
|
||||
alert('请输入标题');
|
||||
return;
|
||||
}
|
||||
if (!item?.id) return;
|
||||
@@ -320,7 +410,14 @@ function EditDialog({ open, item, onClose, onSubmit }: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
await onSubmit(item.id, { name: name.trim(), data: parsedData });
|
||||
await onSubmit(item.id, {
|
||||
title: title.trim(),
|
||||
tags: tags.split(',').map(t => t.trim()).filter(Boolean),
|
||||
link: link.trim(),
|
||||
summary: summary.trim(),
|
||||
description: description.trim(),
|
||||
data: parsedData
|
||||
});
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
@@ -345,17 +442,19 @@ function EditDialog({ open, item, onClose, onSubmit }: {
|
||||
background: '#fff',
|
||||
borderRadius: '8px',
|
||||
padding: '24px',
|
||||
width: '480px',
|
||||
maxWidth: '90%'
|
||||
width: '520px',
|
||||
maxWidth: '90%',
|
||||
maxHeight: '90vh',
|
||||
overflow: 'auto'
|
||||
}} onClick={e => e.stopPropagation()}>
|
||||
<h2 style={{ margin: '0 0 20px 0' }}>编辑Workspace</h2>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>名称</label>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>标题</label>
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
placeholder="请输入名称"
|
||||
value={title}
|
||||
onChange={e => setTitle(e.target.value)}
|
||||
placeholder="请输入标题"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
@@ -365,6 +464,71 @@ function EditDialog({ open, item, onClose, onSubmit }: {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>标签 (逗号分隔)</label>
|
||||
<input
|
||||
type="text"
|
||||
value={tags}
|
||||
onChange={e => setTags(e.target.value)}
|
||||
placeholder="标签1, 标签2, 标签3"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>链接</label>
|
||||
<input
|
||||
type="text"
|
||||
value={link}
|
||||
onChange={e => setLink(e.target.value)}
|
||||
placeholder="https://..."
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>摘要</label>
|
||||
<input
|
||||
type="text"
|
||||
value={summary}
|
||||
onChange={e => setSummary(e.target.value)}
|
||||
placeholder="简要描述"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '16px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>描述</label>
|
||||
<textarea
|
||||
value={description}
|
||||
onChange={e => setDescription(e.target.value)}
|
||||
placeholder="详细描述..."
|
||||
rows={3}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
boxSizing: 'border-box',
|
||||
resize: 'vertical'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>数据 (JSON)</label>
|
||||
<textarea
|
||||
|
||||
@@ -7,7 +7,11 @@ import { toast } from 'sonner';
|
||||
|
||||
type WorkspaceItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
title: string;
|
||||
tags?: string[];
|
||||
link?: string;
|
||||
summary?: string;
|
||||
description?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
data?: any;
|
||||
@@ -28,8 +32,8 @@ type WorkspaceState = {
|
||||
setEditingItem: (item: WorkspaceItem | null) => void;
|
||||
// 数据操作
|
||||
getList: (params?: { search?: string, page?: number, pageSize?: number }) => Promise<void>;
|
||||
createItem: (data: { name: string, data?: any }) => Promise<void>;
|
||||
updateItem: (id: string, data: { name?: string, data?: any }) => Promise<void>;
|
||||
createItem: (data: { title: string, tags?: string[], link?: string, summary?: string, description?: string, data?: any }) => Promise<void>;
|
||||
updateItem: (id: string, data: { title?: string, tags?: string[], link?: string, summary?: string, description?: string, data?: any }) => Promise<void>;
|
||||
deleteItem: (id: string) => Promise<void>;
|
||||
getItem: (id: string) => Promise<WorkspaceItem | null>;
|
||||
}
|
||||
@@ -76,8 +80,12 @@ export const useWorkspaceStore = create<WorkspaceState>((set, get) => ({
|
||||
createItem: async (data) => {
|
||||
try {
|
||||
const res = await queryApi.mark.create({
|
||||
name: data.name,
|
||||
title: data.title,
|
||||
markType: 'cnb',
|
||||
tags: data.tags || [],
|
||||
link: data.link || '',
|
||||
summary: data.summary || '',
|
||||
description: data.description || '',
|
||||
data: data.data || {}
|
||||
});
|
||||
if (res.code === 200) {
|
||||
@@ -97,7 +105,13 @@ export const useWorkspaceStore = create<WorkspaceState>((set, get) => ({
|
||||
try {
|
||||
const res = await queryApi.mark.update({
|
||||
id,
|
||||
...data
|
||||
data: {
|
||||
title: data.title || '',
|
||||
tags: data.tags || [],
|
||||
link: data.link || '',
|
||||
summary: data.summary || '',
|
||||
description: data.description || ''
|
||||
}
|
||||
});
|
||||
if (res.code === 200) {
|
||||
toast.success('更新成功');
|
||||
|
||||
Reference in New Issue
Block a user