Skip to content

Commit 335daae

Browse files
committed
feat: 解耦布局组件
1 parent 4f92de0 commit 335daae

9 files changed

Lines changed: 348 additions & 344 deletions

File tree

src/layout/Default.vue

Lines changed: 7 additions & 344 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ $props.page.detail.content.onSuccess(data => {
128128
129129
const config = useConfig()
130130
131-
const [DefineAvatar, Avatar] = createReusableTemplate<{ author: uni.item.Author }>()
132-
133131
const getActionInfo = (key: string) => Global.userActions.get([union.value.$$plugin, key])!
134132
135133
const getIsSubscribe = (author: uni.item.Author) =>
@@ -159,114 +157,9 @@ const removeSubscribe = (author: uni.item.Author) =>
159157
.where('key', '=', SubscribeDB.key.toString([author.$$plugin, author.label]))
160158
.execute()
161159
)
162-
163-
const [DefineSubscribeRow, SubscribeRow] = createReusableTemplate<{
164-
author: uni.item.Author
165-
class?: any
166-
}>()
167-
168-
const [DefineSubscribeSmallRow, SubscribeSmallRow] = createReusableTemplate<{
169-
author: uni.item.Author
170-
class?: any
171-
}>()
172160
</script>
173161

174162
<template>
175-
<DefineAvatar v-slot="{ author }">
176-
<VanPopover
177-
:actions="
178-
(author.actions ?? []).map(k => ({
179-
text: getActionInfo(k).name,
180-
icons: getActionInfo(k).icon,
181-
key: k
182-
}))
183-
"
184-
@select="q => getActionInfo(q.key).call(author)"
185-
placement="bottom-start"
186-
>
187-
<template #reference>
188-
<div class="van-ellipsis flex w-fit items-center pl-2 text-[16px] text-(--p-color)">
189-
<DcAuthorIcon :size-spacing="8.5" :author class="mx-2" />
190-
<div class="flex w-full flex-col text-nowrap">
191-
<div class="flex items-center text-(--nui-primary-color)">
192-
{{ author.label }}
193-
</div>
194-
<div class="-mt-0.5 flex max-w-2/3 items-center text-[11px] text-(--van-text-color-2)">
195-
{{ author.description }}
196-
</div>
197-
</div>
198-
</div>
199-
</template>
200-
<template #action="{ action: { text, icons } }: { action: PopoverAction; index: number }">
201-
<div class="relative flex w-full items-center justify-center gap-1 text-nowrap">
202-
<NIcon color="var(--van-text-color)" class="flex! items-center!" size="18px">
203-
<component :is="icons" />
204-
</NIcon>
205-
<div>{{ text }}</div>
206-
</div>
207-
</template>
208-
</VanPopover>
209-
</DefineAvatar>
210-
211-
<DefineSubscribeRow v-slot="{ author, class: className }">
212-
<div class="relative w-full" :class="className">
213-
<Avatar :author />
214-
<DcAwait :promise="() => getIsSubscribe(author)" v-slot="{ result: isSubscribe }">
215-
<slot name="subscribeRow" :="{ page, author, isSubscribe, type: 'common' }" />
216-
<Inject
217-
key="layout::layout::default.subscribe-row"
218-
:args="{ page, author, isSubscribe, type: 'common' }"
219-
/>
220-
221-
<NButton
222-
round
223-
type="primary"
224-
:color="isSubscribe ? '#6a7282' : undefined"
225-
class="absolute! top-1/2 right-3 -translate-y-1/2"
226-
size="small"
227-
@click.stop="isSubscribe ? removeSubscribe(author) : addSubscribe(author)"
228-
>
229-
<template #icon>
230-
<NIcon :class="isSubscribe ? 'rotate-45' : 'rotate-0'" class="transition-transform">
231-
<PlusRound />
232-
</NIcon>
233-
</template>
234-
<template #default>
235-
{{ isSubscribe ? '取关' : '关注' }}
236-
</template>
237-
</NButton>
238-
</DcAwait>
239-
</div>
240-
</DefineSubscribeRow>
241-
242-
<DefineSubscribeSmallRow v-slot="{ author, class: className }">
243-
<div class="relative w-full" :class="className">
244-
<Avatar :author />
245-
<DcAwait :promise="() => getIsSubscribe(author)" v-slot="{ result: isSubscribe }">
246-
<slot name="subscribeRow" :="{ page, author, isSubscribe, type: 'small' }" />
247-
<Inject
248-
key="layout::layout::default.subscribe-row"
249-
:args="{ page, author, isSubscribe, type: 'small' }"
250-
/>
251-
252-
<NButton
253-
round
254-
type="primary"
255-
:color="isSubscribe ? '#6a7282' : undefined"
256-
class="aspect-square px-0!"
257-
size="small"
258-
@click.stop="isSubscribe ? removeSubscribe(author) : addSubscribe(author)"
259-
>
260-
<template #icon>
261-
<NIcon :class="isSubscribe ? 'rotate-45' : 'rotate-0'" class="transition-transform">
262-
<PlusRound />
263-
</NIcon>
264-
</template>
265-
</NButton>
266-
</DcAwait>
267-
</div>
268-
</DefineSubscribeSmallRow>
269-
270163
<TitleDefine>
271164
<div
272165
class="mt-1 flex gap-1 text-xs font-normal text-(--van-text-color-2) *:flex *:items-center"
@@ -292,69 +185,7 @@ const [DefineSubscribeSmallRow, SubscribeSmallRow] = createReusableTemplate<{
292185
: 'var(--nui-body-color)'
293186
}"
294187
>
295-
<div class="relative flex h-[30vh] justify-center bg-black text-white">
296-
<div
297-
class="pt-safe pointer-events-none absolute top-0 z-3 flex h-14 w-full items-center *:pointer-events-auto"
298-
>
299-
<VanSticky>
300-
<div
301-
class="pt-safe flex h-[calc(56px+var(--safe-area-inset-top))] w-screen items-center transition-colors"
302-
:class="[isScrolled ? 'bg-(--p-color)' : 'bg-transparent']"
303-
>
304-
<NIcon color="white" size="1.5rem" class="ml-5" @click="$router.back()">
305-
<ArrowBackRound />
306-
</NIcon>
307-
<NIcon color="white" size="1.5rem" class="ml-5" @click="$router.force.push('/')">
308-
<svg
309-
xmlns="http://www.w3.org/2000/svg"
310-
xmlns:xlink="http://www.w3.org/1999/xlink"
311-
viewBox="0 0 24 24"
312-
>
313-
<g
314-
fill="none"
315-
stroke="currentColor"
316-
stroke-width="2"
317-
stroke-linecap="round"
318-
stroke-linejoin="round"
319-
>
320-
<path
321-
d="M19 8.71l-5.333-4.148a2.666 2.666 0 0 0-3.274 0L5.059 8.71a2.665 2.665 0 0 0-1.029 2.105v7.2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.2c0-.823-.38-1.6-1.03-2.105"
322-
></path>
323-
<path d="M16 15c-2.21 1.333-5.792 1.333-8 0"></path>
324-
</g>
325-
</svg>
326-
</NIcon>
327-
<div
328-
@click="scrollbar?.scrollTo({ behavior: 'smooth', top: 0, left: 0 })"
329-
class="flex size-full items-center justify-center text-[16px] transition-opacity"
330-
:class="[isScrolled || 'opacity-0']"
331-
>
332-
<NIcon size="2.5rem">
333-
<PlayArrowRound />
334-
</NIcon>
335-
返回顶部
336-
</div>
337-
</div>
338-
</VanSticky>
339-
</div>
340-
<Teleport to="#cover" :disabled="!fullscreen.isFullscreen.value">
341-
<slot name="view" />
342-
</Teleport>
343-
<VanRow class="pointer-events-none absolute bottom-0 z-2 w-full">
344-
<VanCol span="1" offset="21">
345-
<NButton
346-
class="pointer-events-auto text-3xl!"
347-
@click="setFullscreen(true)"
348-
text
349-
color="#fff"
350-
>
351-
<NIcon>
352-
<FullscreenRound />
353-
</NIcon>
354-
</NButton>
355-
</VanCol>
356-
</VanRow>
357-
</div>
188+
<ViewBox />
358189
<VanTabs
359190
shrink
360191
swipeable
@@ -375,42 +206,7 @@ const [DefineSubscribeSmallRow, SubscribeSmallRow] = createReusableTemplate<{
375206
@reset-retry="$props.page.reloadAll"
376207
class="min-h-[60vh]"
377208
>
378-
<div
379-
class="relative mt-3 flex items-center pb-2 text-nowrap"
380-
v-if="(union?.author.length ?? 0) > 1"
381-
@click="showDetailUsers = true"
382-
>
383-
<span class="ml-3 font-bold">创作团队</span>
384-
<span class="absolute right-3 text-(--van-text-color-2)"
385-
>共{{ union?.author.length }}位</span
386-
>
387-
<DcPopup v-model:show="showDetailUsers" position="bottom" round class="h-[50vh]">
388-
<SubscribeRow
389-
:author
390-
v-for="author of union.author"
391-
class="van-hairline--bottom py-2"
392-
/>
393-
</DcPopup>
394-
</div>
395-
<div
396-
class="flex items-center overflow-x-auto text-nowrap"
397-
@pointerdown.stop
398-
@click.stop
399-
@pointermove.stop
400-
>
401-
<SubscribeRow
402-
:author="union.author[0]"
403-
v-if="union?.author.length === 1"
404-
class="mt-3"
405-
/>
406-
<div v-else class="scroll flex overflow-x-scroll overflow-y-hidden" @click.stop>
407-
<SubscribeSmallRow
408-
class="flex items-center gap-3 text-nowrap"
409-
:author
410-
v-for="author of union?.author"
411-
/>
412-
</div>
413-
</div>
209+
<SubscribeList />
414210
<div class="mx-auto mt-2 w-[95%]">
415211
<div class="relative flex h-fit">
416212
<div class="relative w-[89%] text-[17px] font-medium">
@@ -441,61 +237,10 @@ const [DefineSubscribeSmallRow, SubscribeSmallRow] = createReusableTemplate<{
441237
{{ page.pid.content.data.value }}
442238
</div>
443239
</div>
444-
<DcText
445-
:text="union.description"
446-
v-if="isString(union?.description)"
447-
class="mt-1 justify-start text-xs font-normal text-(--van-text-color-2)"
448-
>
449-
</DcText>
450-
<DcText
451-
:text="union.description.content"
452-
v-else-if="union?.description?.type == 'text'"
453-
class="mt-1 justify-start text-xs font-normal text-(--van-text-color-2)"
454-
>
455-
</DcText>
456-
<div
457-
v-html="DOMPurify.sanitize(union?.description?.content ?? '')"
458-
v-else
459-
class="mt-1 max-w-full justify-start text-xs font-normal text-(--van-text-color-2)"
460-
></div>
461240

462-
<slot name="description" :="{ page, item: union }" />
463-
<Inject key="layout::layout::default.description" :args="{ page, item: union }" />
241+
<Description />
464242

465-
<div
466-
class="flex w-full flex-col"
467-
v-for="[name, categories] of Object.entries(
468-
Object.groupBy(union?.categories ?? [], v => v.group)
469-
)"
470-
>
471-
<NDivider
472-
class="my-1! text-xs! text-(--van-gray-7)! **:font-light!"
473-
title-placement="left"
474-
>
475-
{{ name }}
476-
</NDivider>
477-
<div class="flex flex-wrap gap-2.5 *:px-3! **:text-xs!">
478-
<NButton
479-
tertiary
480-
round
481-
type="tertiary"
482-
size="small"
483-
v-for="category of categories
484-
?.toSorted((a, b) => b.name.length - a.name.length)
485-
.filter(Boolean)"
486-
@click="
487-
SharedFunction.call(
488-
'routeToSearch',
489-
category.search.keyword,
490-
[page.plugin, category.search.source],
491-
category.search.sort
492-
)
493-
"
494-
>
495-
{{ category.name }}
496-
</NButton>
497-
</div>
498-
</div>
243+
<Tags />
499244
</NCollapseTransition>
500245
</div>
501246
<NIcon
@@ -508,92 +253,10 @@ const [DefineSubscribeSmallRow, SubscribeSmallRow] = createReusableTemplate<{
508253
<KeyboardArrowDownRound />
509254
</NIcon>
510255
</div>
511-
<!-- action bar -->
512-
<div class="mt-8 mb-4 flex justify-around" v-if="union">
513-
<DcToggleIcon
514-
padding
515-
size="27px"
516-
v-model="isLiked"
517-
@click="handleLike"
518-
:icon="LikeFilled"
519-
>
520-
{{ (union.likeNumber ?? 0) + (isLiked ? 1 : 0) || '喜欢' }}
521-
</DcToggleIcon>
522-
<DcToggleIcon padding size="27px" :icon="FolderOutlined" dis-changed>
523-
缓存
524-
</DcToggleIcon>
525-
<DcToggleIcon padding size="27px" dis-changed :icon="ReportGmailerrorredRound">
526-
举报
527-
</DcToggleIcon>
528-
<FavouriteSelect :item="union" />
529-
<ShareButton :page />
530-
531-
<slot name="action" :="{ page, item: union }" />
532-
<Inject key="layout::layout::default.action" :args="{ page, item: union }" />
533-
</div>
534-
<!-- ep select -->
535-
<div
536-
class="van-haptics-feedback relative mb-4 flex w-full items-center rounded py-2 pl-3"
537-
:class="[
538-
isR18g
539-
? config.isDark
540-
? ''
541-
: 'bg-(--van-gray-1)/70'
542-
: config.isDark
543-
? 'bg-(--van-gray-8)'
544-
: 'bg-(--van-gray-2)'
545-
]"
546-
v-if="eps && eps.length > 1"
547-
@click="openEpSelectPopup"
548-
>
549-
<span>选集</span>
550-
<span class="mx-0.5">·</span>
551-
<span class="van-ellipsis max-w-1/2">{{
552-
nowEp?.name || `第${nowEpIndex + 1}话`
553-
}}</span>
554-
<span class="absolute right-2 flex items-center text-xs text-(--van-text-color-2)">
555-
<span>{{ nowEpIndex + 1 }}/{{ eps.length }}</span>
556-
<NIcon size="12px" class="ml-1">
557-
<ArrowForwardIosOutlined />
558-
</NIcon>
559-
</span>
560-
</div>
561-
<DcPopup
562-
round
563-
position="bottom"
564-
class="flex h-[70vh] flex-col"
565-
v-model:show="isShowEpSelectPopup"
566-
>
567-
<div class="flex h-10 w-full items-center pt-2 pl-8 text-lg font-bold">选集</div>
568-
<DcList
569-
class="h-full w-full"
570-
:source="{ data: PromiseContent.resolve(eps), isEnd: true }"
571-
:itemHeight="40"
572-
v-slot="{ data: { item: ep, index }, height }"
573-
ref="epSelList"
574-
>
575-
<VanCell
576-
clickable
577-
@click="routeToContent({ ...union.toJSON(), thisEp: ep.toJSON() })"
578-
:title="ep.name || `第${index + 1}话`"
579-
:title-class="[nowEpId === ep.index && 'font-bold text-(--p-color)!']"
580-
class="flex w-full items-center"
581-
:style="{ height: `${height}px !important` }"
582-
>
583-
</VanCell>
584-
</DcList>
585-
</DcPopup>
586-
</div>
587-
<!-- recommend -->
588-
<div class="van-hairline--top w-full *:bg-transparent">
589-
<slot name="recommend" :="{ page, item: union }" />
590-
<Inject key="layout::layout::default.recommend" :args="{ page, item: union }" />
591-
<component
592-
:is="getItemCard(item.contentType)"
593-
:item
594-
v-for="item of page.recommends.content.data.value"
595-
/>
256+
<Actions />
257+
<EpController />
596258
</div>
259+
<Recommends />
597260
</DcContent>
598261
</VanTab>
599262

0 commit comments

Comments
 (0)