-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: ZTL-UwU <zhangtianli2006@163.com>
- Loading branch information
Showing
61 changed files
with
1,453 additions
and
378 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<template> | ||
<div> | ||
<Card | ||
v-if="isCard" | ||
:class="`flex flex-col justify-center items-start shadow p-0 pt-1 pb-2 ${stateColor.from[status]} from-[-10%] ${stateColor.via[status]} via-30% to-white to-80%`" style="background: linear-gradient(310deg, var(--tw-gradient-stops))" | ||
> | ||
<CardHeader :class="`pt-1 pb-0 text-3xl font-bold ${stateColor.text[status]}`"> | ||
{{ stateText[status] }} | ||
</CardHeader> | ||
<CardContent class="pt-0 pb-0"> | ||
<span class="text-md">目前投稿状态</span> | ||
</CardContent> | ||
</Card> | ||
<div v-else> | ||
<CardContent class="flex flex-row p-2 items-center"> | ||
<div | ||
class="h-3.5 w-3.5 rounded-full border-2" :class="[stateColor.bg[state], stateColor.border[state]]" | ||
/> | ||
<span class="ml-2 text-sm">目前投稿状态</span> | ||
<span class="font-bold ml-2 text-sm" :class="stateColor.text[state]">{{ stateText[state] }}</span> | ||
</CardContent> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
type TState = 'unknown' | 'can' | 'cannot'; | ||
const { | ||
isCard = false, | ||
status = 'unknown', | ||
} = defineProps<{ | ||
showButton?: boolean; | ||
isCard?: boolean; | ||
status?: TState; | ||
}>(); | ||
const { $trpc } = useNuxtApp(); | ||
const { data, suspense } = useQuery({ | ||
queryFn: () => $trpc.time.currently.query(), | ||
queryKey: ['time.currently'], | ||
}); | ||
await suspense(); | ||
const state = computed<TState>(() => data.value ? 'can' : 'cannot'); | ||
const stateText = { | ||
unknown: '未知', | ||
can: '开放', | ||
cannot: '关闭', | ||
}; | ||
const stateColor = { | ||
bg: { | ||
unknown: 'bg-slate-300', | ||
can: 'bg-green-300', | ||
cannot: 'bg-red-300', | ||
}, | ||
border: { | ||
unknown: 'border-slate-500', | ||
can: 'border-green-500', | ||
cannot: 'border-red-500', | ||
}, | ||
text: { | ||
unknown: 'text-slate-500', | ||
can: 'text-green-500', | ||
cannot: 'text-red-500', | ||
}, | ||
from: { | ||
unknown: 'from-slate-300', | ||
can: 'from-green-300', | ||
cannot: 'from-red-300', | ||
}, | ||
via: { | ||
unknown: 'via-slate-100', | ||
can: 'via-green-100', | ||
cannot: 'via-red-100', | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<template> | ||
<div class="flex flex-row gap-2"> | ||
<Button type="button" variant="outline" size="icon" @click="handleChange(value.setDate(value.getDate() - 1))"> | ||
<Icon name="lucide:minus" /> | ||
</Button> | ||
<div class="text-2xl font-bold self-center"> | ||
{{ `${dayString[value.getDay()]}` }} | ||
</div> | ||
<Button type="button" variant="outline" size="icon" @click="handleChange(value.setDate(value.getDate() + 1))"> | ||
<Icon name="lucide:plus" /> | ||
</Button> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
defineProps<{ | ||
value: Date; | ||
handleChange: any; | ||
}>(); | ||
const dayString = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<template> | ||
<div | ||
variant="outline" | ||
class="h-auto p-4 w-full border rounded-lg shadow-sm hover:bg-muted transition-colors cursor-pointer" | ||
:class="{ 'bg-muted/60': selected }" | ||
> | ||
<div class="text-secondary-foreground flex flex-row justify-between"> | ||
<Badge variant="secondary"> | ||
{{ time.name }} | ||
</Badge> | ||
<Switch :checked="time.isActive" @update:checked="mutate({ id: time.id, isActive: !time.isActive })" /> | ||
</div> | ||
<div class="flex flex-row mb-6 mt-4"> | ||
<span class="px-5 lg:px-10 pt-2"> | ||
<div v-if="time.repeats" class="text-2xl font-bold text-center"> | ||
{{ `${dayString[time.startAt.getDay()]}` }} | ||
</div> | ||
<div v-else class="text-2xl font-bold text-center"> | ||
{{ `${time.startAt.getMonth() + 1}-${time.startAt.getDate()}` }} | ||
</div> | ||
<div class="text-lg text-center"> | ||
{{ `${time.startAt.getHours().toString().padStart(2, '0')}:${time.startAt.getMinutes().toString().padStart(2, '0')}` }} | ||
</div> | ||
</span> | ||
<span class="flex-grow flex"> | ||
<div class="w-[50px] h-[2px] bg-slate-200 mx-auto self-center rounded-full" /> | ||
</span> | ||
<span class="px-5 lg:px-10 pt-2"> | ||
<div v-if="time.repeats" class="text-2xl font-bold text-center"> | ||
{{ `${dayString[time.endAt.getDay()]}` }} | ||
</div> | ||
<div v-else class="text-2xl font-bold text-center"> | ||
{{ `${time.endAt.getMonth() + 1}-${time.endAt.getDate()}` }} | ||
</div> | ||
<div class="text-lg text-center"> | ||
{{ `${time.endAt.getHours().toString().padStart(2, '0')}:${time.endAt.getMinutes().toString().padStart(2, '0')}` }} | ||
</div> | ||
</span> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import type { RouterOutput } from '~~/types'; | ||
const { selected = false } = defineProps<{ | ||
selected?: boolean; | ||
time: RouterOutput['time']['list'][0]; | ||
}>(); | ||
const { $trpc } = useNuxtApp(); | ||
const dayString = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; | ||
const queryClient = useQueryClient(); | ||
const { mutate } = useMutation({ | ||
mutationFn: $trpc.time.modifyActive.mutate, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: ['time.list'] }); | ||
queryClient.invalidateQueries({ queryKey: ['time.currently'] }); | ||
}, | ||
onError: err => useErrorHandler(err), | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
<template> | ||
<CardHeader> | ||
<CardTitle> | ||
创建开放时间 | ||
</CardTitle> | ||
</CardHeader> | ||
<CardContent> | ||
<form class="flex flex-col gap-4" @submit="onSubmit"> | ||
<FormField v-slot="{ componentField }" name="name"> | ||
<FormItem> | ||
<FormLabel>名称</FormLabel> | ||
<FormControl> | ||
<Input type="text" v-bind="componentField" /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
|
||
<FormField v-slot="{ value, handleChange }" name="repeats"> | ||
<FormItem> | ||
<FormLabel class="block"> | ||
每周重复 | ||
</FormLabel> | ||
<FormControl> | ||
<Switch :checked="value" @update:checked="handleChange" /> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
|
||
<div v-show="!values.repeats" class="grid grid-cols-2 gap-10"> | ||
<FormField v-slot="{ handleChange, value }" name="startAt"> | ||
<FormItem> | ||
<FormLabel class="block"> | ||
开始时间 | ||
</FormLabel> | ||
<DatePicker | ||
borderless | ||
:model-value="value" mode="dateTime" color="gray" locale="zh" trim-weeks | ||
is-required is24hr class="border rounded-lg shadow-sm" | ||
expanded | ||
@update:model-value="handleChange" | ||
/> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
<FormField v-slot="{ handleChange, value }" name="endAt"> | ||
<FormItem> | ||
<FormLabel class="block"> | ||
结束时间 | ||
</FormLabel> | ||
<DatePicker | ||
borderless | ||
:model-value="value" mode="dateTime" color="gray" locale="zh" trim-weeks | ||
is-required is24hr class="border rounded-lg shadow-sm" | ||
expanded | ||
@update:model-value="handleChange" | ||
/> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
</div> | ||
<div v-show="values.repeats" class="grid grid-cols-2 gap-10"> | ||
<FormField v-slot="{ handleChange, value }" name="startAt"> | ||
<FormItem> | ||
<FormLabel class="block"> | ||
开始时间 | ||
</FormLabel> | ||
<FormControl> | ||
<AdminTimeDayPicker :handle-change="handleChange" :value="value" /> | ||
<DatePicker | ||
:model-value="value" mode="time" color="gray" locale="zh" hide-time-header | ||
is-required is24hr style="border: none !important" @update:model-value="handleChange" | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
|
||
<FormField v-slot="{ handleChange, value }" name="endAt"> | ||
<FormItem> | ||
<FormLabel class="block"> | ||
结束时间 | ||
</FormLabel> | ||
<FormControl> | ||
<AdminTimeDayPicker :handle-change="handleChange" :value="value" /> | ||
<DatePicker | ||
:model-value="value" mode="time" color="gray" locale="zh" hide-time-header | ||
is-required is24hr style="border: none !important" @update:model-value="handleChange" | ||
/> | ||
</FormControl> | ||
<FormMessage /> | ||
</FormItem> | ||
</FormField> | ||
</div> | ||
|
||
<div class="mt-4"> | ||
<Button type="submit" :disabled="isPending"> | ||
<Icon v-if="isPending" name="lucide:loader-circle" class="mr-2 animate-spin" /> | ||
创建 | ||
</Button> | ||
</div> | ||
</form> | ||
</CardContent> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import * as z from 'zod'; | ||
import { DatePicker } from 'v-calendar'; | ||
const { $trpc } = useNuxtApp(); | ||
const formSchema = toTypedSchema(z.object({ | ||
name: z.string({ required_error: '名称长度至少为1' }).max(50, '名称长度最大为50'), | ||
repeats: z.boolean(), | ||
startAt: z.date(), | ||
endAt: z.date(), | ||
})); | ||
const { handleSubmit, resetForm, values } = useForm({ | ||
validationSchema: formSchema, | ||
initialValues: { | ||
repeats: false, | ||
startAt: new Date(), | ||
endAt: new Date(), | ||
}, | ||
}); | ||
const queryClient = useQueryClient(); | ||
const { mutate, isPending } = useMutation({ | ||
mutationFn: $trpc.time.create.mutate, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: ['time.list'] }); | ||
queryClient.invalidateQueries({ queryKey: ['time.currently'] }); | ||
toast.success('创建成功'); | ||
resetForm(); | ||
}, | ||
onError: err => useErrorHandler(err), | ||
}); | ||
const onSubmit = handleSubmit(async (values) => { | ||
mutate(values); | ||
}); | ||
</script> |
Oops, something went wrong.