Skip to content

Commit

Permalink
Merge pull request #3 from besscroft/main
Browse files Browse the repository at this point in the history
fork sync
  • Loading branch information
minimua authored Nov 28, 2024
2 parents 2deae2e + d90c770 commit bc20e83
Show file tree
Hide file tree
Showing 20 changed files with 1,775 additions and 317 deletions.
7 changes: 6 additions & 1 deletion app/admin/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export default function About() {
url: 'https://github.com/hexgu',
avatar: 'https://avatars.githubusercontent.com/u/85490069?v=4'
},
{
name: 'xcsoft',
url: 'https://github.com/soxft',
avatar: 'https://avatars.githubusercontent.com/u/42080379?v=4'
},
]
return (
<div className="flex flex-col space-y-2 h-full flex-1 w-full mx-auto items-center p-2">
Expand All @@ -53,7 +58,7 @@ export default function About() {
/>
</svg>

<p className="whitespace-nowrap text-sm">v2.0.4</p>
<p className="whitespace-nowrap text-sm">v2.0.5</p>
</span>
<span>PicImpact 是一个摄影师专用的摄影作品展示网站,基于 Next.js + Hono.js 开发。</span>
<div className="flex flex-col w-full">
Expand Down
7 changes: 5 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ProgressBarProviders } from '~/app/providers/progress-bar-providers'
import { ButtonStoreProvider } from '~/app/providers/button-store-Providers'

import '~/style/globals.css'
import { fetchCustomInfo } from '~/server/db/query'
import { fetchConfigsByKeys } from '~/server/db/query'

type Props = {
params: { id: string }
Expand All @@ -19,7 +19,10 @@ export async function generateMetadata(
parent: ResolvingMetadata
): Promise<Metadata> {

const data = await fetchCustomInfo()
const data = await fetchConfigsByKeys([
'custom_title',
'custom_favicon_url'
])

return {
title: data?.find((item: any) => item.config_key === 'custom_title')?.config_value || 'PicImpact',
Expand Down
9 changes: 7 additions & 2 deletions app/rss.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import 'server-only'
import RSS from 'rss'
import { fetchCustomInfo, getRSSImages } from '~/server/db/query'
import { fetchConfigsByKeys, getRSSImages } from '~/server/db/query'

export async function GET(request: Request) {
const data = await fetchCustomInfo()
const data = await fetchConfigsByKeys([
'custom_title',
'custom_author',
'rss_feed_id',
'rss_user_id'
])

const url = new URL(request.url);

Expand Down
22 changes: 20 additions & 2 deletions components/MasonryItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function MasonryItem() {
data: MasonryViewData,
}

async function loadingHandle(handle: string) {
const loadingHandle = React.useCallback(async (handle: string) => {
const idx = MasonryViewDataList.findIndex((item: ImageType) => MasonryViewData.id === item.id)
if (handle === 'next' && idx === MasonryViewDataList.length - 1) {
setMasonryViewData(MasonryViewDataList[0] || MasonryViewData)
Expand All @@ -67,7 +67,8 @@ export default function MasonryItem() {
setMasonryViewData(next || MasonryViewData)
}
}
}
}, [MasonryViewData, MasonryViewDataList, setMasonryViewData]);


async function downloadImg() {
setDownload(true)
Expand All @@ -93,6 +94,23 @@ export default function MasonryItem() {
}
}

React.useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
if (MasonryView) {
if (e.key === "ArrowLeft") {
loadingHandle("prev");
} else if (e.key === "ArrowRight") {
loadingHandle("next");
}
}
};

document.addEventListener("keydown", handleKey);
return () => {
document.removeEventListener("keydown", handleKey);
};
}, [MasonryView, loadingHandle]);

return (
<Dialog
defaultOpen={false}
Expand Down
39 changes: 18 additions & 21 deletions components/admin/list/ImageBatchDeleteSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import {
DialogTitle,
DialogTrigger,
} from '~/components/ui/dialog'
import { Label } from '~/components/ui/label.tsx'

export default function ImageBatchDeleteSheet(props : Readonly<ImageServerHandleProps & { dataProps: DataProps } & { pageNum: number } & { album: string }>) {
const { dataProps, pageNum, album, ...restProps } = props
const { mutate } = useSWRInfiniteServerHook(restProps, pageNum, album)
const { imageBatchDelete, setImageBatchDelete } = useButtonStore(
(state) => state,
)
const [isOpen, setIsOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [data, setData] = useState([] as any[])

Expand All @@ -55,7 +55,6 @@ export default function ImageBatchDeleteSheet(props : Readonly<ImageServerHandle
toast.error('删除失败!')
} finally {
setLoading(false)
setIsOpen(false)
}
}

Expand All @@ -78,8 +77,11 @@ export default function ImageBatchDeleteSheet(props : Readonly<ImageServerHandle
<div className="space-y-2">
{
dataProps.data && dataProps.data.map((item: ImageType) => (
<div key={item.id} className="flex flex-row items-center justify-start space-x-3 space-y-0 rounded-md border p-4 shadow">
<div
key={item.id}
className="relative flex w-full items-start gap-2 rounded-lg border border-input p-4 shadow-sm shadow-black/5 has-[[data-state=checked]]:border-ring">
<Checkbox
className="order-1 after:absolute after:inset-0"
checked={data?.includes(item.id)}
onCheckedChange={(checked) => {
return checked
Expand All @@ -91,16 +93,18 @@ export default function ImageBatchDeleteSheet(props : Readonly<ImageServerHandle
)
}}
/>
<Avatar>
<AvatarImage src={item.preview_url || item.preview_url} alt="avatar"/>
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<div className="space-y-1 leading-none">
<div>
{item.id.substring(0, 16) + '...'}
</div>
<div>
{item.title ? item.title.length > 16 ? item.title.substring(0, 16) + '...' : item.title : 'N&A'}
<div className="flex grow items-center gap-3">
<Avatar>
<AvatarImage src={item.preview_url || item.preview_url} alt="avatar"/>
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<div className="grid gap-2">
<Label htmlFor="checkbox-15">
{item.id.substring(0, 16) + '...'}
</Label>
<p id="checkbox-15-description" className="text-xs text-muted-foreground">
{item.title ? item.title.length > 16 ? item.title.substring(0, 20) + '...' : item.title : 'N&A'}
</p>
</div>
</div>
</div>
Expand All @@ -109,14 +113,7 @@ export default function ImageBatchDeleteSheet(props : Readonly<ImageServerHandle
<Dialog>
<DialogTrigger asChild>
<Button
onClick={() => {
if (data.length === 0) {
toast.warning('请选择要删除的图片')
return
} else {
setIsOpen(true)
}
}}
disabled={data.length === 0}
aria-label="更新"
>
删除
Expand Down
56 changes: 37 additions & 19 deletions components/admin/list/ImageEditSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { useButtonStore } from '~/app/providers/button-store-Providers'
import { ImageServerHandleProps, ImageType } from '~/types'
import { useSWRInfiniteServerHook } from '~/hooks/useSWRInfiniteServerHook'
import { Select } from 'antd'
import React, { useState } from 'react'
import { toast } from 'sonner'
import { fetcher } from '~/lib/utils/fetcher'
Expand All @@ -12,7 +11,8 @@ import { Switch } from '~/components/ui/switch'
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '~/components/ui/sheet'
import { ReloadIcon } from '@radix-ui/react-icons'
import { Button } from '~/components/ui/button'

import MultipleSelector, { Option } from '~/components/ui/origin/multiselect.tsx'
import { Tag, TagInput } from 'emblor'

export default function ImageEditSheet(props : Readonly<ImageServerHandleProps & { pageNum: number } & { album: string }>) {
const { pageNum, album, ...restProps } = props
Expand All @@ -21,7 +21,8 @@ export default function ImageEditSheet(props : Readonly<ImageServerHandleProps &
(state) => state,
)
const [loading, setLoading] = useState(false)
const { data, isLoading } = useSWR('/api/v1/copyrights/get', fetcher)
const { data} = useSWR('/api/v1/copyrights/get', fetcher)
const [activeTagIndex, setActiveTagIndex] = useState<number | null>(null);

async function submit() {
if (!image.url) {
Expand Down Expand Up @@ -56,8 +57,6 @@ export default function ImageEditSheet(props : Readonly<ImageServerHandleProps &
}
}

const fieldNames = { label: 'name', value: 'id' }

return (
<Sheet
defaultOpen={false}
Expand Down Expand Up @@ -222,24 +221,43 @@ export default function ImageEditSheet(props : Readonly<ImageServerHandleProps &
className="mt-1 w-full border-none p-0 focus:border-transparent focus:outline-none focus:ring-0 sm:text-sm"
/>
</label>
<Select
className="!block"
mode="multiple"
placeholder="选择版权信息"
defaultValue={image.copyrights}
fieldNames={fieldNames}
<MultipleSelector
commandProps={{
label: "选择版权信息",
}}
options={data}
onChange={(value, option: any) => {
setImageEditData({...image, copyrights: value})
value={!image.copyrights ? [] : image.copyrights.map((item: any) => {
const found = data?.find((element: any) => element.value === item)
return {
label: found?.label || '',
value: item
}
})}
placeholder="选择版权信息"
emptyIndicator={<p className="text-center text-sm">暂未选择版权信息</p>}
onChange={(options: Option[]) => {
const values = options.map(option => option.value)
setImageEditData({...image, copyrights: values})
}}
/>
<Select
mode="tags"
value={image.labels}
style={{width: '100%'}}
<TagInput
tags={!image.labels ? [] : image.labels.map((label: string) => ({ id: Math.floor(Math.random() * 1000), text: label }))}
setTags={(newTags: any) => {
setImageEditData({...image, labels: newTags?.map((label: Tag) => label.text)})
}}
placeholder="请输入图片索引标签,如:猫猫,不要输入特殊字符。"
onChange={(value: any) => setImageEditData({...image, labels: value})}
options={[]}
styleClasses={{
inlineTagsContainer:
"border-input rounded-lg bg-background shadow-sm shadow-black/5 transition-shadow focus-within:border-ring focus-within:outline-none focus-within:ring-[3px] focus-within:ring-ring/20 p-1 gap-1",
input: "w-full min-w-[80px] focus-visible:outline-none shadow-none px-2 h-7",
tag: {
body: "h-7 relative bg-background border border-input hover:bg-background rounded-md font-medium text-xs ps-2 pe-7",
closeButton:
"absolute -inset-y-px -end-px p-0 rounded-e-lg flex size-7 transition-colors outline-0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring/70 text-muted-foreground/80 hover:text-foreground",
},
}}
activeTagIndex={activeTagIndex}
setActiveTagIndex={setActiveTagIndex}
/>
<div className="flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
<div className="flex flex-col gap-1">
Expand Down
26 changes: 16 additions & 10 deletions components/admin/list/ImageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,19 @@ import { Sheet, SheetContent, SheetHeader, SheetTitle } from '~/components/ui/sh
import { useButtonStore } from '~/app/providers/button-store-Providers'
import { DataProps, ImageType } from '~/types'
import React from 'react'
import { Select } from 'antd'
import { fetcher } from '~/lib/utils/fetcher'
import useSWR from 'swr'
import ExifView from '~/components/ExifView'
import { Switch } from '~/components/ui/switch'
import LivePhoto from '~/components/LivePhoto.tsx'
import MultipleSelector from '~/components/ui/origin/multiselect.tsx'

export default function ImageView() {
const { imageView, imageViewData, setImageView, setImageViewData } = useButtonStore(
(state) => state,
)
const { data } = useSWR('/api/v1/copyrights/get', fetcher)

const fieldNames = { label: 'name', value: 'id' }

const props: DataProps = {
data: imageViewData,
}
Expand Down Expand Up @@ -141,14 +139,22 @@ export default function ImageView() {
className="mt-1 w-full border-none p-0 focus:border-transparent focus:outline-none focus:ring-0 sm:text-sm"
/>
</label>
<Select
className="!block"
mode="multiple"
placeholder="暂未选择版权信息"
disabled
defaultValue={imageViewData?.copyrights}
fieldNames={fieldNames}
<MultipleSelector
commandProps={{
label: "选择版权信息",
}}
options={data}
disabled
hidePlaceholderWhenSelected
value={!imageViewData.copyrights ? [] : imageViewData.copyrights.map((item: any) => {
const found = data?.find((element: any) => element.value === item)
return {
label: found?.label || '',
value: item
}
})}
placeholder="选择版权信息"
emptyIndicator={<p className="text-center text-sm">暂未选择版权信息</p>}
/>
<div className="flex flex-row items-center justify-between rounded-lg border p-3 shadow-sm">
<div className="flex flex-col gap-1">
Expand Down
Loading

0 comments on commit bc20e83

Please sign in to comment.