change to next

This commit is contained in:
xiongxiao
2026-01-15 12:32:07 +08:00
parent 62b5c5841a
commit b2f315a459
122 changed files with 9396 additions and 9354 deletions

View File

@@ -0,0 +1,209 @@
import { useState, useEffect, useRef } from "react"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"
import { Input } from "@/components/ui/input"
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { DataItemForm } from "@/app/view/components/DataItemForm"
import { ViewFormItem } from "@/app/view/components/ViewFormItem"
import { nanoid } from "nanoid"
interface ViewEditorProps {
open: boolean
onOpenChange: (open: boolean) => void
data?: {
id?: string
title?: string
data?: { items: any[] }
views?: any[]
}
onSave: (data: any) => void
}
export const ViewEditor = ({ open, onOpenChange, data, onSave }: ViewEditorProps) => {
const [title, setTitle] = useState('')
const [dataItems, setDataItems] = useState<any[]>([])
const [views, setViews] = useState<any[]>([])
const dataItemsScrollRef = useRef<HTMLDivElement>(null)
const viewsScrollRef = useRef<HTMLDivElement>(null)
const isUpdate = !!data?.id
useEffect(() => {
if (open) {
setTitle(data?.title || '')
setDataItems(data?.data?.items || [])
setViews(data?.views || [])
}
}, [open, data])
const handleAddDataItem = () => {
setDataItems([...dataItems, { type: 'api', api: { url: '' } }])
// 异步滚动到底部,使用 smooth 平滑滚动
setTimeout(() => {
if (dataItemsScrollRef.current) {
dataItemsScrollRef.current.scrollTo({
top: dataItemsScrollRef.current.scrollHeight,
behavior: 'smooth'
})
}
}, 0)
}
const handleUpdateDataItem = (index: number, item: any) => {
const newItems = [...dataItems]
newItems[index] = item
setDataItems(newItems)
}
const handleRemoveDataItem = (index: number) => {
setDataItems(dataItems.filter((_, i) => i !== index))
}
const handleAddView = () => {
setViews([...views, { id: nanoid(16), title: '', query: '' }])
// 异步滚动到底部,使用 smooth 平滑滚动
setTimeout(() => {
if (viewsScrollRef.current) {
viewsScrollRef.current.scrollTo({
top: viewsScrollRef.current.scrollHeight,
behavior: 'smooth'
})
}
}, 0)
}
const handleUpdateView = (index: number, view: any) => {
const newViews = [...views]
newViews[index] = view
setViews(newViews)
}
const handleRemoveView = (index: number) => {
setViews(views.filter((_, i) => i !== index))
}
const handleSave = () => {
const pickData = dataItems.map(item => {
if (item.type === 'api') {
delete item.api.query
}
if (item.type === 'worker') {
delete item.worker.worker
}
if (item.type === 'context') {
delete item.context.router
}
if (item.type === 'page') {
}
return item
})
const viewData = {
id: data?.id,
title,
data: {
items: pickData
},
views
}
onSave(viewData)
onOpenChange(false)
}
const handleClose = () => {
onOpenChange(false)
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl">
<DialogHeader>
<DialogTitle>{isUpdate ? '编辑视图' : '新增视图'}</DialogTitle>
</DialogHeader>
<div className="space-y-4">
{/* 固定的视图标题 */}
<div className="space-y-2">
<Label htmlFor="title"></Label>
<Input
id="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="输入视图标题"
/>
</div>
{/* Tabs 容器 */}
<Tabs defaultValue="data" className="w-full flex flex-col">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="data"></TabsTrigger>
<TabsTrigger value="views"></TabsTrigger>
</TabsList>
{/* 数据项配置 Tab */}
<TabsContent value="data" className="flex flex-col mt-4">
<div className="flex justify-between items-center mb-4">
<h3 className="font-medium"> (data.items)</h3>
<Button type="button" variant="outline" size="sm" onClick={handleAddDataItem} className="cursor-pointer">
</Button>
</div>
<div ref={dataItemsScrollRef} className="space-y-4 max-h-[50vh] overflow-y-auto pr-4">
{dataItems.length === 0 ? (
<div className="text-center text-sm text-gray-500 py-8">
"添加数据项"
</div>
) : (
dataItems.map((item, index) => (
<DataItemForm
key={index}
item={item}
onChange={(newItem) => handleUpdateDataItem(index, newItem)}
onRemove={() => handleRemoveDataItem(index)}
/>
))
)}
</div>
</TabsContent>
{/* 视图配置 Tab */}
<TabsContent value="views" className="flex flex-col mt-4">
<div className="flex justify-between items-center mb-4">
<h3 className="font-medium"> (views)</h3>
<Button type="button" variant="outline" size="sm" onClick={handleAddView} className="cursor-pointer">
</Button>
</div>
<div ref={viewsScrollRef} className="space-y-4 max-h-[50vh] overflow-y-auto pr-4">
{views.length === 0 ? (
<div className="text-center text-sm text-gray-500 py-8">
"添加视图"
</div>
) : (
views.map((view, index) => (
<ViewFormItem
key={view.id || index}
view={view}
onChange={(newView) => handleUpdateView(index, newView)}
onRemove={() => handleRemoveView(index)}
/>
))
)}
</div>
</TabsContent>
</Tabs>
</div>
<DialogFooter>
<Button type="button" variant="outline" onClick={handleClose} className="cursor-pointer">
</Button>
<Button type="button" onClick={handleSave} className="cursor-pointer">
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}