Commit 28692f2c by Ivan

feat: update edit

parent 63b84398
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
import * as Form from '@radix-ui/react-form' import * as Form from '@radix-ui/react-form'
import TagSearchInput from './TagSearchInput' import TagSearchInput from './TagSearchInput'
import ComImageStatusSelect from './images/ComImageStatusSelect'
export default function ImageUploadForm({ export default function ImageUploadForm({
data, data,
...@@ -11,6 +12,7 @@ export default function ImageUploadForm({ ...@@ -11,6 +12,7 @@ export default function ImageUploadForm({
submitButtonText = '上传图片', submitButtonText = '上传图片',
processingButtonText = '上传中...', processingButtonText = '上传中...',
showTagsField = true, showTagsField = true,
showStatusField = false,
isEdit = false, isEdit = false,
image = null, image = null,
tags = [], tags = [],
...@@ -151,7 +153,17 @@ export default function ImageUploadForm({ ...@@ -151,7 +153,17 @@ export default function ImageUploadForm({
/> />
</div> </div>
)} )}
{
showStatusField && (
<Form.Field name="status" className="space-y-2">
<ComImageStatusSelect
value={data.status}
onChange={(value) => setData('status', value)}
allowAll={false}
/>
</Form.Field>
)
}
{showTagsField && ( {showTagsField && (
<Form.Field name="tags" className="space-y-2"> <Form.Field name="tags" className="space-y-2">
<Form.Label className="block text-sm font-medium text-gray-700"> <Form.Label className="block text-sm font-medium text-gray-700">
...@@ -165,9 +177,7 @@ export default function ImageUploadForm({ ...@@ -165,9 +177,7 @@ export default function ImageUploadForm({
placeholder="点击搜索图标添加标签" placeholder="点击搜索图标添加标签"
/> />
</Form.Control> </Form.Control>
<p className="text-xs text-gray-500">
点击右侧搜索图标可按分类浏览标签
</p>
</Form.Field> </Form.Field>
)} )}
......
...@@ -2,14 +2,11 @@ import { useState, useEffect, useRef, useCallback } from 'react' ...@@ -2,14 +2,11 @@ import { useState, useEffect, useRef, useCallback } from 'react'
import { Head, Link, router } from '@inertiajs/react' import { Head, Link, router } from '@inertiajs/react'
import * as Form from '@radix-ui/react-form' import * as Form from '@radix-ui/react-form'
import * as Collapsible from '@radix-ui/react-collapsible' import * as Collapsible from '@radix-ui/react-collapsible'
import * as Select from '@radix-ui/react-select'
import { uniqBy } from 'lodash-es' import { uniqBy } from 'lodash-es'
import { ComImageCard } from './ComImageCard' import { ComImageCard } from './ComImageCard'
import TagSearchInput from '../TagSearchInput' import TagSearchInput from '../TagSearchInput'
import DateRangePicker from '../DateRangePicker' import DateRangePicker from '../DateRangePicker'
import { ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/24/solid' import ComImageStatusSelect from './ComImageStatusSelect'
export default function ComImageIndex({ title, description, path, images, pagination, filters, auth, backLink, actionButton, showUserName = false, allTags = {} }) { export default function ComImageIndex({ title, description, path, images, pagination, filters, auth, backLink, actionButton, showUserName = false, allTags = {} }) {
const [allImages, setAllImages] = useState(images || []) const [allImages, setAllImages] = useState(images || [])
...@@ -44,10 +41,6 @@ export default function ComImageIndex({ title, description, path, images, pagina ...@@ -44,10 +41,6 @@ export default function ComImageIndex({ title, description, path, images, pagina
setSearchParams({ ...searchParams, status_eq: statusValue }) setSearchParams({ ...searchParams, status_eq: statusValue })
} }
const clearStatus = () => {
setSearchParams({ ...searchParams, status_eq: '' })
}
const handleSearch = (e) => { const handleSearch = (e) => {
e.preventDefault() e.preventDefault()
setLoadedPageMap({}) setLoadedPageMap({})
...@@ -281,70 +274,10 @@ export default function ComImageIndex({ title, description, path, images, pagina ...@@ -281,70 +274,10 @@ export default function ComImageIndex({ title, description, path, images, pagina
状态 状态
</Form.Label> </Form.Label>
<Form.Control asChild> <Form.Control asChild>
<Select.Root <ComImageStatusSelect
value={searchParams.status_eq || "all"} value={searchParams.status_eq || "all"}
onValueChange={handleStatusChange} onChange={handleStatusChange}
> />
<div className="relative">
<Select.Trigger className="mt-1 inline-flex items-center justify-between w-full px-3 py-2 text-sm border border-gray-300 rounded-md shadow-sm bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<Select.Value placeholder="选择状态" />
<Select.Icon>
<ChevronDownIcon className="h-4 w-4 text-gray-500" />
</Select.Icon>
</Select.Trigger>
{searchParams.status_eq && (
<button
type="button"
onClick={clearStatus}
className="absolute right-8 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
aria-label="清空状态筛选"
>
<XMarkIcon className="h-4 w-4" />
</button>
)}
</div>
<Select.Portal>
<Select.Content className="overflow-hidden bg-white rounded-md shadow-lg border border-gray-200 z-50">
<Select.ScrollUpButton className="flex items-center justify-center h-6 bg-white text-gray-700 cursor-default">
<ChevronUpIcon className="h-4 w-4" />
</Select.ScrollUpButton>
<Select.Viewport className="p-1">
<Select.Group>
<Select.Item value="all" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>全部状态</Select.ItemText>
</Select.Item>
<Select.Item value="pending" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>待审核</Select.ItemText>
</Select.Item>
<Select.Item value="approved" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>已通过</Select.ItemText>
</Select.Item>
<Select.Item value="rejected" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>已拒绝</Select.ItemText>
</Select.Item>
</Select.Group>
</Select.Viewport>
<Select.ScrollDownButton className="flex items-center justify-center h-6 bg-white text-gray-700 cursor-default">
<ChevronDownIcon className="h-4 w-4" />
</Select.ScrollDownButton>
</Select.Content>
</Select.Portal>
</Select.Root>
{/* <select
name="status_eq"
value={searchParams.status_eq}
onChange={handleInputChange}
className="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md"
>
<option value="">全部状态</option>
<option value="pending">待审核</option>
<option value="approved">已通过</option>
<option value="rejected">已拒绝</option>
</select> */}
</Form.Control> </Form.Control>
</Form.Field> </Form.Field>
</div> </div>
......
...@@ -123,7 +123,8 @@ export default function ComImageShow({ path, image, can_edit, can_approve, isAdm ...@@ -123,7 +123,8 @@ export default function ComImageShow({ path, image, can_edit, can_approve, isAdm
<Dialog.Root open={isModalOpen} onOpenChange={setIsModalOpen}> <Dialog.Root open={isModalOpen} onOpenChange={setIsModalOpen}>
<Dialog.Portal> <Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 bg-black/50" /> <Dialog.Overlay className="fixed inset-0 bg-black/50" />
<Dialog.Content className="fixed inset-0 flex items-center justify-center"> <Dialog.Content className="fixed inset-0 flex items-center justify-center z-50">
<Dialog.Title className="hidden"/>
<div className="relative w-full h-full max-w-screen-xl max-h-screen p-4"> <div className="relative w-full h-full max-w-screen-xl max-h-screen p-4">
<img <img
src={image.file_url} src={image.file_url}
......
import * as Select from '@radix-ui/react-select'
import { ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/24/solid'
export default function ComImageStatusSelect({
value,
onChange,
disabled = false,
allowAll = true
}) {
return (
<Select.Root
value={value}
onValueChange={onChange}
disabled={disabled}
>
<div className="relative">
<Select.Trigger className="mt-1 inline-flex items-center justify-between w-full px-3 py-2 text-sm border border-gray-300 rounded-md shadow-sm bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<Select.Value placeholder="选择状态" />
<Select.Icon>
<ChevronDownIcon className="h-4 w-4 text-gray-500" />
</Select.Icon>
</Select.Trigger>
{value && (
<button
type="button"
onClick={() => onChange('')}
className="absolute right-8 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
aria-label="清空状态筛选"
>
<XMarkIcon className="h-4 w-4" />
</button>
)}
</div>
<Select.Portal>
<Select.Content className="overflow-hidden bg-white rounded-md shadow-lg border border-gray-200 z-50">
<Select.ScrollUpButton className="flex items-center justify-center h-6 bg-white text-gray-700 cursor-default">
<ChevronUpIcon className="h-4 w-4" />
</Select.ScrollUpButton>
<Select.Viewport className="p-1">
<Select.Group>
{
allowAll &&
<Select.Item value="all" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>全部状态</Select.ItemText>
</Select.Item>
}
<Select.Item value="pending" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>待审核</Select.ItemText>
</Select.Item>
<Select.Item value="approved" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>已通过</Select.ItemText>
</Select.Item>
<Select.Item value="rejected" className="relative flex items-center h-8 px-6 py-2 text-sm rounded hover:bg-indigo-100 hover:text-indigo-900 cursor-pointer outline-none data-[highlighted]:bg-indigo-100 data-[highlighted]:text-indigo-900">
<Select.ItemText>已拒绝</Select.ItemText>
</Select.Item>
</Select.Group>
</Select.Viewport>
<Select.ScrollDownButton className="flex items-center justify-center h-6 bg-white text-gray-700 cursor-default">
<ChevronDownIcon className="h-4 w-4" />
</Select.ScrollDownButton>
</Select.Content>
</Select.Portal>
</Select.Root>
)
}
\ No newline at end of file
...@@ -148,7 +148,7 @@ export default function ComTagsIndex({ ...@@ -148,7 +148,7 @@ export default function ComTagsIndex({
</Link> </Link>
</div> </div>
{isAdmin && <div className="!mt-2 flex space-x-2 justify-end mt-auto pt-2 border-t border-gray-200"> {isAdmin && <div className="!mt-2 flex space-x-2 justify-end mt-auto pt-2">
<button <button
onClick={() => openEditModal(tag)} onClick={() => openEditModal(tag)}
className="text-xs text-indigo-600 hover:text-indigo-900" className="text-xs text-indigo-600 hover:text-indigo-900"
......
...@@ -8,7 +8,7 @@ export default function Layout({ children, user, title }) { ...@@ -8,7 +8,7 @@ export default function Layout({ children, user, title }) {
return ( return (
<div className="min-h-screen bg-gray-50 flex flex-col"> <div className="min-h-screen bg-gray-50 flex flex-col">
<header className="bg-white shadow-sm"> <header className="bg-white shadow-sm sticky top-0 z-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16"> <div className="flex justify-between h-16">
<div className="flex"> <div className="flex">
......
import { Head } from '@inertiajs/react' import { Head, useForm } from '@inertiajs/react'
import Layout from '../../Layout' import Layout from '../../Layout'
import ComImageEdit from '../../../components/images/ComImageEdit' import ImageUploadForm from '../../../components/ImageUploadForm'
export default function AdminImagesEdit({ image, tags, auth }) { export default function AdminImagesEdit({ image, tags, auth }) {
// 初始化已有标签的ID数组
const initialTagIds = image.tags
? image.tags.map(tag => tag.id)
: []
const { data, setData, patch, processing, errors } = useForm({
title: image.title || '',
status: image.status,
tag_ids: initialTagIds,
})
const handleSubmit = (e) => {
e.preventDefault()
patch(`/admin/images/${image.id}`)
}
return ( return (
<Layout user={auth}> <Layout user={auth}>
<Head title={`管理 - 编辑 ${image.title}`} /> <Head title={`管理 - 编辑 ${image.title}`} />
<ComImageEdit
image={image} <div className="bg-white shadow overflow-hidden sm:rounded-lg">
tags={tags} <div className="px-4 py-5 sm:px-6">
path={`/admin/images/${image.id}`} <h1 className="text-2xl font-bold text-gray-900">编辑图片</h1>
isAdmin={true} <p className="mt-1 max-w-2xl text-sm text-gray-500">
/> 更新图片信息
</p>
</div>
<div className="border-t border-gray-200 px-4 py-5 sm:px-6">
<ImageUploadForm
data={data}
setData={setData}
processing={processing}
errors={errors}
onSubmit={handleSubmit}
submitButtonText="保存"
processingButtonText="保存中..."
showTagsField={true}
showStatusField={true}
isEdit={true}
image={image}
tags={tags}
cancelUrl={`/admin/images/${image.id}`}
/>
</div>
</div>
</Layout> </Layout>
) )
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment