@funhub/platform 0.1.108 → 0.1.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/biz/business/card-grid/variants/card-grid-2x3-infinite/runtime/client.mjs +1 -1
- package/dist/components/biz/business/card-grid/variants/card-grid-3x3-infinite/runtime/client.mjs +1 -1
- package/dist/components/biz/business/detail/video-detail-actions/client.mjs +1 -1
- package/dist/components/biz/business/detail/video-detail-info/material.mjs +1 -1
- package/dist/components/biz/business/detail/video-detail-info-title-tags-episodes/material.mjs +1 -1
- package/dist/components/biz/business/detail/video-detail-recommend/client.mjs +1 -1
- package/dist/components/biz/business/home-recommend/shared/home-recommend-base.mjs +1 -1
- package/dist/components/biz/business/post-card/variants/basic-post-card/runtime/client.mjs +1 -1
- package/dist/components/biz/business/profile/profile-main/shell.mjs +1 -1
- package/dist/components/pages/home/client.mjs +1 -1
- package/dist/components/ui/button.d.mts +1 -1
- package/dist/components/ui/infinite-scroll.d.mts +0 -5
- package/dist/components/ui/infinite-scroll.mjs +1 -1
- package/dist/hooks/use-sticky.mjs +1 -1
- package/dist/utils/helper.mjs +1 -1
- package/package.json +2 -6
- package/bin/index.mjs +0 -323
- package/templates/base/_meta.json +0 -4
- package/templates/base/template/README.md.template +0 -32
- package/templates/base/template/__dot__gitignore +0 -6
- package/templates/base/template/app/[locale]/layout.tsx.template +0 -36
- package/templates/base/template/app/[locale]/page.tsx.template +0 -24
- package/templates/base/template/app/globals.css +0 -26
- package/templates/base/template/app/layout.tsx.template +0 -38
- package/templates/base/template/eslint.config.mjs.template +0 -68
- package/templates/base/template/i18n/request.ts.template +0 -3
- package/templates/base/template/next-env.d.ts.template +0 -4
- package/templates/base/template/next.config.ts.template +0 -21
- package/templates/base/template/package.json.template +0 -37
- package/templates/base/template/postcss.config.js.template +0 -18
- package/templates/base/template/proxy.ts.template +0 -18
- package/templates/base/template/tailwind.config.cjs.template +0 -13
- package/templates/base/template/tsconfig.json.template +0 -43
package/dist/components/biz/business/card-grid/variants/card-grid-2x3-infinite/runtime/client.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{CardSpec as e}from"../../../../../utils/constants/card-spec.mjs";import{mergeStyles as t}from"../../../../../utils/styles/helpers.mjs";import{transformContentListToCardItems as n}from"../../../../../utils/transformers/card-grid.mjs";import{gContentGetAppChannelBlockData as r}from"../../../../../../../service/generated/client.mjs";import{Box as i}from"../../../../../../ui/box.mjs";import{InfiniteScroll as a}from"../../../../../../ui/infinite-scroll.mjs";import{Text as o}from"../../../../../../ui/text.mjs";import{usePaginated as s}from"../../../../../../../hooks/query/use-query.mjs";import c from"../../../../../basics/card-layout/runtime/client.mjs";import{useLayoutEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{jsx as p,jsxs as m}from"react/jsx-runtime";const h={},g={list:[],title:``,cursor:``,block_id:``};function _({props:_=h,styles:v,data:y=g}){let b=e.V2_LARGE,{gap:x=8}=_||{},{title:S,cursor:C,block_id:w,list:T}=y,E=v?t(v,{}):void 0,D=T&&T.length>0,O=u(()=>{if(!D)return;let e=C&&C.trim()?C:void 0;return{pages:[{data:{block:{data:{videos:T,cursor:C||``}}}}],pageParams:[e]}},[D,T,C]),{data:k,fetchNextPage:A,hasNextPage:j}=s({key:[`card-grid-2x3-infinite`,w],queryFn:e=>r({block_id:w,cursor:e||void 0,page_size:20}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!w,initialData:O,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:D&&C&&C.trim()?C:void 0}),M=d(T),[N,P]=f(!1);l(()=>{P(!0)},[]);let F=u(()=>{let e=[...M.current];if(!N)return e;let t=[...e],n=k?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.videos||[];t.push(...r)}return t},[N,k?.pages]),I=u(()=>n(F,`view-duration`),[F]);return m(i,{children:[S&&p(o,{as:`h2`,className:`text-[18px] font-bold text-text1 mb-[10px] px-[12px]`,children:S}),p(a,{loadMore:()=>A().then(()=>void 0),hasMore:j===!0||j===void 0&&!!C&&T.length>0,initialLoad:!0,
|
|
2
|
+
"use client";import{CardSpec as e}from"../../../../../utils/constants/card-spec.mjs";import{mergeStyles as t}from"../../../../../utils/styles/helpers.mjs";import{transformContentListToCardItems as n}from"../../../../../utils/transformers/card-grid.mjs";import{gContentGetAppChannelBlockData as r}from"../../../../../../../service/generated/client.mjs";import{Box as i}from"../../../../../../ui/box.mjs";import{InfiniteScroll as a}from"../../../../../../ui/infinite-scroll.mjs";import{Text as o}from"../../../../../../ui/text.mjs";import{usePaginated as s}from"../../../../../../../hooks/query/use-query.mjs";import c from"../../../../../basics/card-layout/runtime/client.mjs";import{useLayoutEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{jsx as p,jsxs as m}from"react/jsx-runtime";const h={},g={list:[],title:``,cursor:``,block_id:``};function _({props:_=h,styles:v,data:y=g}){let b=e.V2_LARGE,{gap:x=8}=_||{},{title:S,cursor:C,block_id:w,list:T}=y,E=v?t(v,{}):void 0,D=T&&T.length>0,O=u(()=>{if(!D)return;let e=C&&C.trim()?C:void 0;return{pages:[{data:{block:{data:{videos:T,cursor:C||``}}}}],pageParams:[e]}},[D,T,C]),{data:k,fetchNextPage:A,hasNextPage:j}=s({key:[`card-grid-2x3-infinite`,w],queryFn:e=>r({block_id:w,cursor:e||void 0,page_size:20}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!w,initialData:O,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:D&&C&&C.trim()?C:void 0}),M=d(T),[N,P]=f(!1);l(()=>{P(!0)},[]);let F=u(()=>{let e=[...M.current];if(!N)return e;let t=[...e],n=k?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.videos||[];t.push(...r)}return t},[N,k?.pages]),I=u(()=>n(F,`view-duration`),[F]);return m(i,{children:[S&&p(o,{as:`h2`,className:`text-[18px] font-bold text-text1 mb-[10px] px-[12px]`,children:S}),p(a,{loadMore:()=>A().then(()=>void 0),hasMore:j===!0||j===void 0&&!!C&&T.length>0,initialLoad:!0,threshold:1e3,className:``,children:p(c,{props:{cardSpec:b,gap:x},data:I,styles:E})})]})}export{_ as default};
|
package/dist/components/biz/business/card-grid/variants/card-grid-3x3-infinite/runtime/client.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{CardSpec as e}from"../../../../../utils/constants/card-spec.mjs";import{mergeStyles as t}from"../../../../../utils/styles/helpers.mjs";import{transformContentListToCardItems as n}from"../../../../../utils/transformers/card-grid.mjs";import{gContentGetAppChannelBlockData as r}from"../../../../../../../service/generated/client.mjs";import{Box as i}from"../../../../../../ui/box.mjs";import{InfiniteScroll as a}from"../../../../../../ui/infinite-scroll.mjs";import{Text as o}from"../../../../../../ui/text.mjs";import{usePaginated as s}from"../../../../../../../hooks/query/use-query.mjs";import c from"../../../../../basics/card-layout/runtime/client.mjs";import{useLayoutEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{jsx as p,jsxs as m}from"react/jsx-runtime";const h={},g={list:[],title:``,cursor:``,block_id:``};function _({props:_=h,styles:v,data:y=g}){let b=e.V3_SMALL,{gap:x=8}=_||{},{title:S,cursor:C,block_id:w,list:T}=y,E=v?t(v,{}):void 0,D=T&&T.length>0,O=u(()=>{if(!D)return;let e=C&&C.trim()?C:void 0;return{pages:[{data:{block:{data:{videos:T,cursor:C||``}}}}],pageParams:[e]}},[D,T,C]),{data:k,fetchNextPage:A,hasNextPage:j}=s({key:[`card-grid-3x3-infinite`,w],queryFn:e=>r({block_id:w,cursor:e||void 0,page_size:21}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!w,initialData:O,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:D&&C&&C.trim()?C:void 0}),M=d(T),[N,P]=f(!1);l(()=>{P(!0)},[]);let F=u(()=>{let e=[...M.current];if(!N)return e;let t=[...e],n=k?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.videos||[];t.push(...r)}return t},[N,k?.pages]),I=u(()=>n(F,`view-duration`),[F]);return m(i,{children:[S&&p(o,{as:`h2`,className:`text-[18px] font-bold text-text1 mb-[10px] px-[12px]`,children:S}),p(a,{loadMore:()=>A().then(()=>void 0),hasMore:j===!0||j===void 0&&!!C&&T.length>0,className:``,initialLoad:!0,
|
|
2
|
+
"use client";import{CardSpec as e}from"../../../../../utils/constants/card-spec.mjs";import{mergeStyles as t}from"../../../../../utils/styles/helpers.mjs";import{transformContentListToCardItems as n}from"../../../../../utils/transformers/card-grid.mjs";import{gContentGetAppChannelBlockData as r}from"../../../../../../../service/generated/client.mjs";import{Box as i}from"../../../../../../ui/box.mjs";import{InfiniteScroll as a}from"../../../../../../ui/infinite-scroll.mjs";import{Text as o}from"../../../../../../ui/text.mjs";import{usePaginated as s}from"../../../../../../../hooks/query/use-query.mjs";import c from"../../../../../basics/card-layout/runtime/client.mjs";import{useLayoutEffect as l,useMemo as u,useRef as d,useState as f}from"react";import{jsx as p,jsxs as m}from"react/jsx-runtime";const h={},g={list:[],title:``,cursor:``,block_id:``};function _({props:_=h,styles:v,data:y=g}){let b=e.V3_SMALL,{gap:x=8}=_||{},{title:S,cursor:C,block_id:w,list:T}=y,E=v?t(v,{}):void 0,D=T&&T.length>0,O=u(()=>{if(!D)return;let e=C&&C.trim()?C:void 0;return{pages:[{data:{block:{data:{videos:T,cursor:C||``}}}}],pageParams:[e]}},[D,T,C]),{data:k,fetchNextPage:A,hasNextPage:j}=s({key:[`card-grid-3x3-infinite`,w],queryFn:e=>r({block_id:w,cursor:e||void 0,page_size:21}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!w,initialData:O,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:D&&C&&C.trim()?C:void 0}),M=d(T),[N,P]=f(!1);l(()=>{P(!0)},[]);let F=u(()=>{let e=[...M.current];if(!N)return e;let t=[...e],n=k?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.videos||[];t.push(...r)}return t},[N,k?.pages]),I=u(()=>n(F,`view-duration`),[F]);return m(i,{children:[S&&p(o,{as:`h2`,className:`text-[18px] font-bold text-text1 mb-[10px] px-[12px]`,children:S}),p(a,{loadMore:()=>A().then(()=>void 0),hasMore:j===!0||j===void 0&&!!C&&T.length>0,className:``,initialLoad:!0,threshold:1e3,children:p(c,{props:{cardSpec:b,gap:x},data:I,styles:E})})]})}export{_ as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{useRequest as e}from"../../../../../hooks/query/use-query.mjs";import{batchQueryContentInteractions as t}from"../../../../../hooks/use-content-operate.mjs";import{DetailOperate as n}from"../shared/detail-operate.mjs";import{editorPreviewInformation as r}from"../shared/editor-preview.mjs";import{useVideoDetailMaterialRuntimeContext as i}from"../shared/runtime-context-provider.mjs";import{useCallback as a,useEffect as o,useRef as s,useState as c}from"react";import{jsx as l}from"react/jsx-runtime";function u({mode:u=`renderer`}){let d=i(),f=d?.information,p=d?.onUpdateInformation,m=!!d?.isWebView,h=u===`editor`,g=u===`renderer`,_=h,v=_?r:f,[y,b]=c(v),x=s(v),S=s(``);o(()=>{b(v)},[v]);let C=p?v:y;o(()=>{x.current=C},[C]);let w=g&&!m&&!!v?.id,{data:T}=e([`video-detail-actions-interaction`,v?.id],async()=>v?.id?await t([v.id],1):null,{enabled:w,staleTime:0,refetchOnMount:`always`,refetchOnWindowFocus:!1}),E=a(e=>{if(!_){if(p){p(e);return}b(t=>{if(!t)return t;let n=e.static?{...t.static||{},...e.static||{}}:t.static;return{...t,...e,static:n}})}},[p,_]);return o(()=>{let e=T?.interaction_list?.[0],t=x.current;if(!e||!t)return;let n=`${e.is_liked?1:0}-${e.is_disliked?1:0}-${e.is_collected?1:0}`;if(S.current===n)return;S.current=n;let r=e.is_liked||!1,i=e.is_disliked||!1,a=e.is_collected||!1,o=!!t.like,s=!!t.dislike,c=!!t.collect,l=t.static?.like_cnt,u
|
|
2
|
+
"use client";import{useRequest as e}from"../../../../../hooks/query/use-query.mjs";import{batchQueryContentInteractions as t}from"../../../../../hooks/use-content-operate.mjs";import{DetailOperate as n}from"../shared/detail-operate.mjs";import{editorPreviewInformation as r}from"../shared/editor-preview.mjs";import{useVideoDetailMaterialRuntimeContext as i}from"../shared/runtime-context-provider.mjs";import{useCallback as a,useEffect as o,useRef as s,useState as c}from"react";import{jsx as l}from"react/jsx-runtime";function u({mode:u=`renderer`}){let d=i(),f=d?.information,p=d?.onUpdateInformation,m=!!d?.isWebView,h=u===`editor`,g=u===`renderer`,_=h,v=_?r:f,[y,b]=c(v),x=s(v),S=s(``);o(()=>{b(v)},[v]);let C=p?v:y;o(()=>{x.current=C},[C]);let w=g&&!m&&!!v?.id,{data:T}=e([`video-detail-actions-interaction`,v?.id],async()=>v?.id?await t([v.id],1):null,{enabled:w,staleTime:0,refetchOnMount:`always`,refetchOnWindowFocus:!1}),E=a(e=>{if(!_){if(p){p(e);return}b(t=>{if(!t)return t;let n=e.static?{...t.static||{},...e.static||{}}:t.static;return{...t,...e,static:n}})}},[p,_]);return o(()=>{let e=T?.interaction_list?.[0],t=x.current;if(!e||!t)return;let n=`${e.is_liked?1:0}-${e.is_disliked?1:0}-${e.is_collected?1:0}`;if(S.current===n)return;S.current=n;let r=e.is_liked||!1,i=e.is_disliked||!1,a=e.is_collected||!1,o=!!t.like,s=!!t.dislike,c=!!t.collect,l=t.static?.like_cnt,u=typeof l==`number`?l:Number(l||0),d=u;o===r?r&&u===0&&(d=1):d=Math.max(0,u+(r?1:-1));let f=d!==u;o===r&&s===i&&c===a&&!f||E({like:r,dislike:i,collect:a,...f?{static:{...t.static||{},like_cnt:d}}:{}})},[E,T]),C?l(`div`,{className:_?`pointer-events-none`:void 0,children:l(n,{mode:u,information:C,onUpdate:E})}):null}export{u as VideoDetailActionsClient};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
import{defineMaterial as e}from"../../../../../utils/schema/material.mjs";import{VideoDetailInfoClient as t}from"./client.mjs";import{videoDetailInfoInspectorPropsSchema as n}from"./schema.mjs";import{VideoDetailInfo as r}from"./server.mjs";const i=e({type:`video-detail-info`,name:`专辑信息样式
|
|
2
|
+
import{defineMaterial as e}from"../../../../../utils/schema/material.mjs";import{VideoDetailInfoClient as t}from"./client.mjs";import{videoDetailInfoInspectorPropsSchema as n}from"./schema.mjs";import{VideoDetailInfo as r}from"./server.mjs";const i=e({type:`video-detail-info`,name:`专辑信息样式1`,icon:`/static/components-thumb/media_info_description_episode.png`,category:`内容组件`,serverComponent:r,clientComponent:t,propsSchema:n});export{i as videoDetailInfoMaterial};
|
package/dist/components/biz/business/detail/video-detail-info-title-tags-episodes/material.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
import{defineMaterial as e}from"../../../../../utils/schema/material.mjs";import{VideoDetailInfoTitleTagsEpisodesClient as t}from"./client.mjs";import{videoDetailInfoTitleTagsEpisodesInspectorPropsSchema as n}from"./schema.mjs";import{VideoDetailInfoTitleTagsEpisodes as r}from"./server.mjs";const i=e({type:`video-detail-info-title-tags-episodes`,name:`专辑信息样式
|
|
2
|
+
import{defineMaterial as e}from"../../../../../utils/schema/material.mjs";import{VideoDetailInfoTitleTagsEpisodesClient as t}from"./client.mjs";import{videoDetailInfoTitleTagsEpisodesInspectorPropsSchema as n}from"./schema.mjs";import{VideoDetailInfoTitleTagsEpisodes as r}from"./server.mjs";const i=e({type:`video-detail-info-title-tags-episodes`,name:`专辑信息样式2`,icon:`/static/components-thumb/media_info_episode_list.png`,category:`内容组件`,serverComponent:r,clientComponent:t,propsSchema:n});export{i as videoDetailInfoTitleTagsEpisodesMaterial};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{gContentGetGuessYouLikeVideos as e,pContentBatchGetVideoDetail as t}from"../../../../../service/generated/client.mjs";import{Box as n}from"../../../../ui/box.mjs";import{Text as r}from"../../../../ui/text.mjs";import{useRequest as i}from"../../../../../hooks/query/use-query.mjs";import{useKeepAliveState as a}from"../../../../common/keep-scroll-position/index.mjs";import o from"../../../../../assets/icons/detail/video_flag.mjs";import{MiniThreeCard as s}from"../../../../common/cards/mini-three-card.mjs";import{useCardDecoration as c}from"../../../../../hooks/use-card-decoration.mjs";import{buildEditorPreviewRecommendList as l}from"../shared/editor-preview.mjs";import{useVideoDetailMaterialRuntimeContext as u}from"../shared/runtime-context-provider.mjs";import{applyPlayCountDelta as ee,clampColumns as d,mergeManualAndPool as f,normalizeRecommendRuntimeProps as p,resolveRows as m}from"./utils.mjs";import{useCallback as te,useEffect as h,useMemo as g,useRef as ne,useState as re}from"react";import{jsx as _,jsxs as ie}from"react/jsx-runtime";function v({rows:v,columns:ae,smartTagEnabled:y,smartTagIds:b,title:pe,showPlayCount:me,playCountDelta:he,showEpisode:ge,enableInfinite:S,items:C,mode:_e=`renderer`}){let w=u()?.detailId||``,ve=_e===`editor`,T=ve,{getVerticalHoCoverImageUrl:E,getTitleText:D}=c(),O=ne(null),k=g(()=>p({smartTagEnabled:y,smartTagIds:b,enableInfinite:S,items:C}),[S,C,y,b]),A=k.smartTagEnabled,j=k.smartTagIds,M=g(()=>k.items??[],[k.items]),N=k.enableInfinite&&!ve,P=!A,F=N&&A&&!T,ye=m(v,N),I=d(ae),L=ye*I,R=Math.max(1,L),z=g(()=>[`video-detail-recommend`,w||`unknown`,R,j.join(`,`)].join(`:`),[w,R,j]),[be,B]=a(`${z}:pool`,[]),[V,H]=a(`${z}:has-more`,!1),[U,W]=re(!1),G=g(()=>l(L),[L]),{data:K}=i([`video-detail-recommend`,w,F?`paged`:`all`,R,j.join(`,`)],async()=>T?null:await e({page_size:R,tags:j}),{enabled:!T&&A}),q=g(()=>T?G:oe(K?.data?.videos),[K?.data?.videos,G,T]);h(()=>{if(!F){W(!1);return}B(e=>{if(!q.length)return e;if(!e.length)return q;let t=[...q],n=new Set(q.map(e=>e.id).filter(Boolean));return e.forEach(e=>{(!e.id||!n.has(e.id))&&(t.push(e),e.id&&n.add(e.id))}),t});let e=ce(K?.data?.videos,R);H(t=>t||e),W(!1)},[K?.data?.videos,q,R,H,B,F]);let J=F?be:q,Y=g(()=>P?Array.from(new Set(M.filter(e=>e.coverMode===`content`).map(e=>x(e.contentId)).filter(Boolean))):[],[M,P]),{data:xe}=i([`video-detail-recommend-manual-details`,Y.join(`,`)],async()=>{if(!Y.length)return[];let e=await t({ids:Y});return(Array.isArray(e.data?.videos)?e.data.videos:[]).map(e=>se(e))},{enabled:Y.length>0}),Se=g(()=>P?new Set(M.map(e=>x(e.contentId)).filter(Boolean)):new Set,[M,P]),Ce=g(()=>T?J:J.filter(e=>!Se.has(e.id)),[J,T,Se]),X=g(()=>{if(!P||!M.length)return[];let e=new Map;return J.forEach(t=>{let n=x(t.id);n&&e.set(n,t)}),(xe||[]).forEach(t=>{let n=x(t.id);n&&e.set(n,t)}),M.map((t,n)=>{let r=T?G[n%Math.max(1,G.length)]:fe(t,n),i=x(t.contentId),a=typeof t.coverUrl==`string`?t.coverUrl.trim():``,o=e.get(i)??{...r,id:i||r.id||`preview-manual-${n+1}`,name:r.name||`猜你喜欢 ${n+1}`,img_y:a||r.img_y,img_x:a||r.img_x},s=t.titleMode===`custom`?t.title:D(o),c=t.coverMode===`content`?E(o)||a:a||E(o);return{info:{...o,name:s||o.name,img_y:c||o.img_y,img_x:c||o.img_x},config:{showPlayCount:t.showPlayCount,playCountDelta:t.playCountDelta,showEpisode:t.showEpisode}}}).filter(Boolean)},[G,J,D,E,xe,M,P]),Z=g(()=>Ce.map(e=>({info:e})),[Ce]),we=P&&M.length>0,Te=g(()=>we?X:f(X,Z,L),[we,X,L,Z]),Q=g(()=>{if(F){if(!X.length)return Z;let e=new Set(X.map(e=>e.info.id).filter(Boolean));return X.concat(Z.filter(t=>!e.has(t.info.id)))}if(N){if(!X.length)return Z;let e=new Set(X.map(e=>e.info.id).filter(Boolean));return X.concat(Z.filter(t=>!e.has(t.info.id)))}return Te},[Te,X,Z,N,F]),Ee=V&&Q.length>0?Math.max(0,Q.length-4):-1,De=String(pe||``).trim(),$=te(async()=>{if(!(!F||!V||U)){W(!0);try{let t=await e({page_size:R,tags:j}),n=Array.isArray(t.data?.videos)?t.data.videos:[],r=oe(n),i=0;B(e=>{let t=new Set(e.map(e=>e.id).filter(Boolean)),n=[...e];return r.forEach(e=>{(!e.id||!t.has(e.id))&&(n.push(e),e.id&&t.add(e.id))}),i=n.length-e.length,n}),H(ce(n,R)&&i>0)}catch(e){console.error(`猜你喜欢分页加载失败`,e),H(!1)}finally{W(!1)}}},[V,U,R,j,H,B,F]);return h(()=>{if(!F)return;let e=O.current;if(!e||!V)return;let t=new IntersectionObserver(e=>{e[0]?.isIntersecting&&!U&&$()});return t.observe(e),()=>{t.disconnect()}},[$,V,U,F,Ee]),Q.length?ie(n,{className:`w-full mt-[16px] ${T?`pointer-events-none`:``}`,children:[De?_(r,{className:`block pl-[12px] mb-[8px] text-text1 text-[18px] leading-[26px] font-bold`,children:De}):null,_(n,{className:`w-full flex flex-wrap px-[12px]`,children:Q.map((e,t)=>{let n=D(e.info),i=me!==!1&&(e.config?.showPlayCount??!0),a=Number(e.config?.playCountDelta??he??0),c=e.config?.showEpisode??ge,l=ue(ee(e.info.play_count||0,a)),u=le(e.info),d=Number.isFinite(I)&&I>0?I:3,f=`${100/d}%`,p=t%d,m=d>1?{paddingLeft:8*p/d,paddingRight:8*(d-p-1)/d}:null;return _(`div`,{ref:t===Ee?O:void 0,style:{width:f,...m||{}},children:_(s,{url:E(e.info),text:n,textChild:_(r,{as:`h3`,className:`text-text1 text-[16px] h-[24px] leading-[24px] mt-[4px] line-clamp-1`,children:n}),style:{width:`100%`},bottomLeftChild:i?ie(`div`,{className:`h-[20px] leading-[20px] text-[#fff] text-[12px] px-[4px] rounded-[4px] bg-[#333] ml-[4px] flex items-center`,children:[_(o,{className:`w-[16px] h-[auto] text-[#fff] mr-[4px]`}),l]}):null,bottomRightChild:c&&u?_(`div`,{className:`text-[#fff] text-[12px] leading-[20px] pr-2`,children:u}):null,linkPath:T?``:de(e.info)})},`guess-like-${t}`)})})]}):null}function ae(e){return{id:e.video_id||``,mid:``,name:e.name||``,cat_id:``,cat_name:``,status:`1`,status_text:``,create_time:``,content_type:0,episode_cnt:e.episode_count||0,show_at:e.show_at??``,position:``,img_type:e.img_type??``,img_x:e.img_x??``,img_y:e.img_y??``,img_width:``,img_height:``,play_count:e.play_count,preview_images:[],duration:String(e.duration??``),score:String(e.score??``),is_more_link:e.is_more_link?`y`:`n`,update_status:String(e.update_status??``),description:e.description??``,language:``,director:``,actor:``,area:``,issue_date:``,publisher:``,series:``,number:``,tags:[],source_tags:e.source_tags??``,source_actor:[],links:Array.isArray(e.episodes)?e.episodes.map(e=>({id:e.id??``,name:e.name??``,preview_m3u8_url:e.preview_m3u8_url??``,m3u8_url:e.m3u8_url??``})):[],money:``,up_user:``,source_username:``,task_id:``,file_status:``}}function oe(e){return Array.isArray(e)?e.map(e=>ae(e)):[]}function se(e){let t=String(e?.id||e?.mid||e?.video_id||``),n=Number(e?.content_type||0)===2||e?.is_more_link===`y`||e?.is_more_link===`1`||e?.is_more_link===!0,r=Array.isArray(e?.links)?e.links.map(e=>({id:String(e?.id||``),name:String(e?.name||``),preview_m3u8_url:String(e?.preview_m3u8_url||``),m3u8_url:String(e?.m3u8_url||``)})):[],i=Array.isArray(e?.video_episodes)?e.video_episodes.length:0,a=Number(e?.episode_cnt||i||r.length||0);return{id:t,mid:String(e?.mid||t),name:String(e?.name||``),cat_id:String(e?.cat_id||``),cat_name:String(e?.cat_name||``),status:String(e?.status||`1`),status_text:String(e?.status_text||``),create_time:String(e?.create_time||``),content_type:0,type:n?2:1,episode_cnt:Number.isFinite(a)?a:0,show_at:String(e?.show_at||``),position:String(e?.position||``),img_type:String(e?.img_type||``),img_x:String(e?.img_x||``),img_y:String(e?.img_y||``),img_width:String(e?.img_width||``),img_height:String(e?.img_height||``),play_count:Number(e?.play_count??e?.browse_count??0),preview_images:Array.isArray(e?.preview_images)?e.preview_images:[],duration:String(e?.duration||``),score:String(e?.score||``),is_more_link:n?`y`:`n`,update_status:String(e?.update_status||``),description:String(e?.description||``),language:String(e?.language||``),director:String(e?.director||``),actor:String(e?.actor||``),area:String(e?.area||``),issue_date:String(e?.issue_date||``),publisher:String(e?.publisher||``),series:String(e?.series||``),number:String(e?.number||``),tags:Array.isArray(e?.tags)?e.tags:[],source_tags:String(e?.source_tags||``),source_actor:Array.isArray(e?.source_actor)?e.source_actor:[],links:r,money:String(e?.money||``),up_user:String(e?.up_user||``),source_username:String(e?.source_username||``),task_id:String(e?.task_id||``),file_status:String(e?.file_status||``)}}function ce(e,t){if(!Array.isArray(e)||e.length===0)return!1;let n=e[0];if(typeof n?.has_more==`boolean`)return n.has_more;let r=Number(n?.total??0);return Number.isFinite(r)&&r>0?r>t:e.length>=t}function le(e){if(y(e)){let t=Number(e.episode_cnt||e.links?.length||0);return t>0?`全${t}集`:``}return b(Number(e.duration||0))}function y(e){if(Number(e.type??e.content_type??0)===2)return!0;let t=e.is_more_link;if(t===!0||t===`y`||t===`1`)return!0;let n=Number(e.episode_cnt||e.links?.length||0);return Number.isFinite(n)&&n>1}function b(e){if(!Number.isFinite(e)||e<=0)return``;let t=Math.floor(e),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=e=>String(e).padStart(2,`0`);return n>0?`${a(n)}:${a(r)}:${a(i)}`:`${a(r)}:${a(i)}`}function ue(e){let t=Number(e||`0`);return Number.isNaN(t)||t<=0?`0`:t>=1e4?`${(t/1e4).toFixed(1)}w`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function de(e){if(e.content_type===0){let t=encodeURIComponent(e.name||``);return`/video/${e.id}/${t}/episode/1`}return`/post/${e.id}`}function x(e){return typeof e==`string`?e.trim():``}function fe(e,t){let n=x(e.contentId)||`manual-${t+1}`,r=typeof e.coverUrl==`string`?e.coverUrl.trim():``,i=typeof e.title==`string`?e.title.trim():``,a=typeof e.description==`string`?e.description.trim():``;return{id:n,mid:n,name:i||`猜你喜欢 ${t+1}`,cat_id:``,cat_name:``,status:`1`,status_text:``,create_time:``,content_type:0,type:1,episode_cnt:0,show_at:``,position:``,img_type:``,img_x:r,img_y:r,img_width:``,img_height:``,play_count:0,preview_images:[],duration:``,score:``,is_more_link:`n`,update_status:``,description:a,language:``,director:``,actor:``,area:``,issue_date:``,publisher:``,series:``,number:``,tags:[],source_tags:``,source_actor:[],links:[],money:``,up_user:``,source_username:``,task_id:``,file_status:``}}export{v as VideoDetailRecommendClient};
|
|
2
|
+
"use client";import{gContentGetGuessYouLikeVideos as e,pContentBatchGetVideoDetail as t}from"../../../../../service/generated/client.mjs";import{Box as n}from"../../../../ui/box.mjs";import{Text as r}from"../../../../ui/text.mjs";import{useRequest as i}from"../../../../../hooks/query/use-query.mjs";import{useKeepAliveState as a}from"../../../../common/keep-scroll-position/index.mjs";import o from"../../../../../assets/icons/detail/video_flag.mjs";import{MiniThreeCard as s}from"../../../../common/cards/mini-three-card.mjs";import{useCardDecoration as c}from"../../../../../hooks/use-card-decoration.mjs";import{buildEditorPreviewRecommendList as l}from"../shared/editor-preview.mjs";import{useVideoDetailMaterialRuntimeContext as u}from"../shared/runtime-context-provider.mjs";import{applyPlayCountDelta as ee,clampColumns as d,mergeManualAndPool as f,normalizeRecommendRuntimeProps as p,resolveRows as m}from"./utils.mjs";import{useCallback as te,useEffect as h,useMemo as g,useRef as ne,useState as re}from"react";import{jsx as _,jsxs as ie}from"react/jsx-runtime";function v({rows:v,columns:ae,smartTagEnabled:y,smartTagIds:b,title:pe,showPlayCount:me,playCountDelta:he,showEpisode:ge,enableInfinite:S,items:C,mode:_e=`renderer`}){let w=u()?.detailId||``,ve=_e===`editor`,T=ve,{getVerticalHoCoverImageUrl:E,getTitleText:D}=c(),O=ne(null),k=g(()=>p({smartTagEnabled:y,smartTagIds:b,enableInfinite:S,items:C}),[S,C,y,b]),A=k.smartTagEnabled,j=k.smartTagIds,M=g(()=>k.items??[],[k.items]),N=k.enableInfinite&&!ve,P=!A,F=N&&A&&!T,ye=m(v,N),I=d(ae),L=ye*I,R=Math.max(1,L),z=g(()=>[`video-detail-recommend`,w||`unknown`,R,j.join(`,`)].join(`:`),[w,R,j]),[be,B]=a(`${z}:pool`,[]),[V,H]=a(`${z}:has-more`,!1),[U,W]=re(!1),G=g(()=>l(L),[L]),{data:K}=i([`video-detail-recommend`,w,F?`paged`:`all`,R,j.join(`,`)],async()=>T?null:await e({page_size:R,tags:j}),{enabled:!T&&A}),q=g(()=>T?G:oe(K?.data?.videos),[K?.data?.videos,G,T]);h(()=>{if(!F){W(!1);return}B(e=>{if(!q.length)return e;if(!e.length)return q;let t=[...q],n=new Set(q.map(e=>e.id).filter(Boolean));return e.forEach(e=>{(!e.id||!n.has(e.id))&&(t.push(e),e.id&&n.add(e.id))}),t});let e=ce(K?.data?.videos,R);H(t=>t||e),W(!1)},[K?.data?.videos,q,R,H,B,F]);let J=F?be:q,Y=g(()=>P?Array.from(new Set(M.filter(e=>e.coverMode===`content`).map(e=>x(e.contentId)).filter(Boolean))):[],[M,P]),{data:xe}=i([`video-detail-recommend-manual-details`,Y.join(`,`)],async()=>{if(!Y.length)return[];let e=await t({ids:Y});return(Array.isArray(e.data?.videos)?e.data.videos:[]).map(e=>se(e))},{enabled:Y.length>0}),Se=g(()=>P?new Set(M.map(e=>x(e.contentId)).filter(Boolean)):new Set,[M,P]),Ce=g(()=>T?J:J.filter(e=>!Se.has(e.id)),[J,T,Se]),X=g(()=>{if(!P||!M.length)return[];let e=new Map;return J.forEach(t=>{let n=x(t.id);n&&e.set(n,t)}),(xe||[]).forEach(t=>{let n=x(t.id);n&&e.set(n,t)}),M.map((t,n)=>{let r=T?G[n%Math.max(1,G.length)]:fe(t,n),i=x(t.contentId),a=typeof t.coverUrl==`string`?t.coverUrl.trim():``,o=e.get(i)??{...r,id:i||r.id||`preview-manual-${n+1}`,name:r.name||`猜你喜欢 ${n+1}`,img_y:a||r.img_y,img_x:a||r.img_x},s=t.titleMode===`custom`?t.title:D(o),c=t.coverMode===`content`?E(o)||a:a||E(o);return{info:{...o,name:s||o.name,img_y:c||o.img_y,img_x:c||o.img_x},config:{showPlayCount:t.showPlayCount,playCountDelta:t.playCountDelta,showEpisode:t.showEpisode}}}).filter(Boolean)},[G,J,D,E,T,xe,M,P]),Z=g(()=>Ce.map(e=>({info:e})),[Ce]),we=P&&M.length>0,Te=g(()=>we?X:f(X,Z,L),[we,X,L,Z]),Q=g(()=>{if(F){if(!X.length)return Z;let e=new Set(X.map(e=>e.info.id).filter(Boolean));return X.concat(Z.filter(t=>!e.has(t.info.id)))}if(N){if(!X.length)return Z;let e=new Set(X.map(e=>e.info.id).filter(Boolean));return X.concat(Z.filter(t=>!e.has(t.info.id)))}return Te},[Te,X,Z,N,F]),Ee=V&&Q.length>0?Math.max(0,Q.length-4):-1,De=String(pe||``).trim(),$=te(async()=>{if(!(!F||!V||U)){W(!0);try{let t=await e({page_size:R,tags:j}),n=Array.isArray(t.data?.videos)?t.data.videos:[],r=oe(n),i=0;B(e=>{let t=new Set(e.map(e=>e.id).filter(Boolean)),n=[...e];return r.forEach(e=>{(!e.id||!t.has(e.id))&&(n.push(e),e.id&&t.add(e.id))}),i=n.length-e.length,n}),H(ce(n,R)&&i>0)}catch(e){console.error(`猜你喜欢分页加载失败`,e),H(!1)}finally{W(!1)}}},[V,U,R,j,H,B,F]);return h(()=>{if(!F)return;let e=O.current;if(!e||!V)return;let t=new IntersectionObserver(e=>{e[0]?.isIntersecting&&!U&&$()});return t.observe(e),()=>{t.disconnect()}},[$,V,U,F,Ee]),Q.length?ie(n,{className:`w-full mt-[16px] ${T?`pointer-events-none`:``}`,children:[De?_(r,{className:`block pl-[12px] mb-[8px] text-text1 text-[18px] leading-[26px] font-bold`,children:De}):null,_(n,{className:`w-full flex flex-wrap px-[12px]`,children:Q.map((e,t)=>{let n=D(e.info),i=me!==!1&&(e.config?.showPlayCount??!0),a=Number(e.config?.playCountDelta??he??0),c=e.config?.showEpisode??ge,l=ue(ee(e.info.play_count||0,a)),u=le(e.info),d=Number.isFinite(I)&&I>0?I:3,f=`${100/d}%`,p=t%d,m=d>1?{paddingLeft:8*p/d,paddingRight:8*(d-p-1)/d}:null;return _(`div`,{ref:t===Ee?O:void 0,style:{width:f,...m||{}},children:_(s,{url:E(e.info),text:n,textChild:_(r,{as:`h3`,className:`text-text1 text-[16px] h-[24px] leading-[24px] mt-[4px] line-clamp-1`,children:n}),style:{width:`100%`},bottomLeftChild:i?ie(`div`,{className:`h-[20px] leading-[20px] text-[#fff] text-[12px] px-[4px] rounded-[4px] bg-[#333] ml-[4px] flex items-center`,children:[_(o,{className:`w-[16px] h-[auto] text-[#fff] mr-[4px]`}),l]}):null,bottomRightChild:c&&u?_(`div`,{className:`text-[#fff] text-[12px] leading-[20px] pr-2`,children:u}):null,linkPath:T?``:de(e.info)})},`guess-like-${t}`)})})]}):null}function ae(e){let t=e.is_more_link?`y`:`n`;return{id:e.video_id||``,mid:``,name:e.name||``,cat_id:``,cat_name:``,status:`1`,status_text:``,create_time:``,content_type:e.content_type,episode_cnt:e.episode_count||0,show_at:e.show_at??``,position:``,img_type:e.img_type??``,img_x:e.img_x??``,img_y:e.img_y??``,img_width:``,img_height:``,play_count:e.play_count,preview_images:[],duration:String(e.duration??``),score:String(e.score??``),is_more_link:t,update_status:String(e.update_status??``),description:e.description??``,language:``,director:``,actor:``,area:``,issue_date:``,publisher:``,series:``,number:``,tags:[],source_tags:e.source_tags??``,source_actor:[],links:Array.isArray(e.episodes)?e.episodes.map(e=>({id:e.id??``,name:e.name??``,preview_m3u8_url:e.preview_m3u8_url??``,m3u8_url:e.m3u8_url??``})):[],money:``,up_user:``,source_username:``,task_id:``,file_status:``}}function oe(e){return Array.isArray(e)?e.map(e=>ae(e)):[]}function se(e){let t=String(e?.id||e?.mid||e?.video_id||``),n=e?.is_more_link===`y`?`y`:`n`,r=Array.isArray(e?.links)?e.links.map(e=>({id:String(e?.id||``),name:String(e?.name||``),preview_m3u8_url:String(e?.preview_m3u8_url||``),m3u8_url:String(e?.m3u8_url||``)})):[],i=Array.isArray(e?.video_episodes)?e.video_episodes.length:0,a=Number(e?.episode_cnt||i||r.length||0);return{id:t,mid:String(e?.mid||t),name:String(e?.name||``),cat_id:String(e?.cat_id||``),cat_name:String(e?.cat_name||``),status:String(e?.status||`1`),status_text:String(e?.status_text||``),create_time:String(e?.create_time||``),content_type:e?.content_type,episode_cnt:Number.isFinite(a)?a:0,show_at:String(e?.show_at||``),position:String(e?.position||``),img_type:String(e?.img_type||``),img_x:String(e?.img_x||``),img_y:String(e?.img_y||``),img_width:String(e?.img_width||``),img_height:String(e?.img_height||``),play_count:Number(e?.play_count??e?.browse_count??0),preview_images:Array.isArray(e?.preview_images)?e.preview_images:[],duration:String(e?.duration||``),score:String(e?.score||``),is_more_link:n,update_status:String(e?.update_status||``),description:String(e?.description||``),language:String(e?.language||``),director:String(e?.director||``),actor:String(e?.actor||``),area:String(e?.area||``),issue_date:String(e?.issue_date||``),publisher:String(e?.publisher||``),series:String(e?.series||``),number:String(e?.number||``),tags:Array.isArray(e?.tags)?e.tags:[],source_tags:String(e?.source_tags||``),source_actor:Array.isArray(e?.source_actor)?e.source_actor:[],links:r,money:String(e?.money||``),up_user:String(e?.up_user||``),source_username:String(e?.source_username||``),task_id:String(e?.task_id||``),file_status:String(e?.file_status||``)}}function ce(e,t){if(!Array.isArray(e)||e.length===0)return!1;let n=e[0];if(typeof n?.has_more==`boolean`)return n.has_more;let r=Number(n?.total??0);return Number.isFinite(r)&&r>0?r>t:e.length>=t}function le(e){if(y(e)){let t=Number(e.episode_cnt||e.links?.length||0);return t>0?`全${t}集`:``}return b(Number(e.duration||0))}function y(e){return e.is_more_link===`y`}function b(e){if(!Number.isFinite(e)||e<=0)return``;let t=Math.floor(e),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=e=>String(e).padStart(2,`0`);return n>0?`${a(n)}:${a(r)}:${a(i)}`:`${a(r)}:${a(i)}`}function ue(e){let t=Number(e||`0`);return Number.isNaN(t)||t<=0?`0`:t>=1e4?`${(t/1e4).toFixed(1)}w`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function de(e){let t=encodeURIComponent(e.name||``);return`/video/${e.id}/${t}/episode/1`}function x(e){return typeof e==`string`?e.trim():``}function fe(e,t){let n=x(e.contentId)||`manual-${t+1}`,r=typeof e.coverUrl==`string`?e.coverUrl.trim():``,i=typeof e.title==`string`?e.title.trim():``,a=typeof e.description==`string`?e.description.trim():``;return{id:n,mid:n,name:i||`猜你喜欢 ${t+1}`,cat_id:``,cat_name:``,status:`1`,status_text:``,create_time:``,content_type:1,episode_cnt:0,show_at:``,position:``,img_type:``,img_x:r,img_y:r,img_width:``,img_height:``,play_count:0,preview_images:[],duration:``,score:``,is_more_link:`n`,update_status:``,description:a,language:``,director:``,actor:``,area:``,issue_date:``,publisher:``,series:``,number:``,tags:[],source_tags:``,source_actor:[],links:[],money:``,up_user:``,source_username:``,task_id:``,file_status:``}}export{v as VideoDetailRecommendClient};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{pContentGetPopularVideoList as e}from"../../../../../service/generated/client.mjs";import{Image as t}from"../../../../ui/image.mjs";import{Box as n}from"../../../../ui/box.mjs";import{Text as r}from"../../../../ui/text.mjs";import i from"../../../../../assets/icons/detail/video_flag.mjs";import{MiniThreeCard as a}from"../../../../common/cards/mini-three-card.mjs";import{HOME_RECOMMEND_DEFAULT_GRID_COLUMNS as o,HOME_RECOMMEND_DEFAULT_GRID_ROWS as s,HOME_RECOMMEND_DEFAULT_PLAY_COUNT_DELTA as c,HOME_RECOMMEND_DEFAULT_SHOW_EPISODE as l,HOME_RECOMMEND_DEFAULT_SHOW_PLAY_COUNT as u,HOME_RECOMMEND_MAX_GRID_COLUMNS as ee,HOME_RECOMMEND_MAX_GRID_ROWS as te}from"./home-recommend-default-config.mjs";import{HOME_RECOMMEND_CARD_CONFIG_FIELD as d}from"./home-recommend-preview.mjs";import{useCallback as f,useEffect as p,useLayoutEffect as m,useMemo as h,useRef as g,useState as _}from"react";import{jsx as v,jsxs as y}from"react/jsx-runtime";import{useRouter as ne}from"next/navigation";const re={},ie={list:[]};function b({variant:t,props:i=re,data:a=ie,mode:d=`renderer`}){let b=d===`editor`,S=ne(),{list:C,title:se,cursor:T}=a,E=h(()=>Array.isArray(C)?C:[],[C]),D=h(()=>Array.isArray(a.icons)?a.icons:[],[a.icons]),{rows:O,columns:ce,moreLink:k,title:A,smartTagEnabled:j,smartTagIds:M,catId:ue,showPlayCount:de,playCountDelta:fe,showEpisode:pe,enableInfinite:me}=i,F=me===!0&&j===!0,I=!b&&F&&E.length>=16,L=h(()=>Array.isArray(M)?M.map(e=>String(e||``).trim()).filter(Boolean):[],[M]),R=typeof ue==`string`?ue.trim():``,[z,he]=_(0),[ge,_e]=_(E),[ve,ye]=_(D),[B,V]=_(()=>N(T)),[be,xe]=_(!1),Se=g(null),H=g(null),U=g(!1);p(()=>{_e(E),ye(D),V(N(T))},[T,D,E]);let Ce=oe(O,s,te),W=oe(ce,o,ee),G=F?16:t===`grid`?Ce*W:16,we=Ce*W,Te=b&&t===`grid`,K=Te?ge.slice(0,we):ge,q=Te?ve.slice(0,we):ve,Ee=t===`waterfall`?6:4,J=K.length>0?Math.max(0,K.length-Ee):-1,De=!!B,Oe=A&&A.trim()||se||``,Y=de??u,X=Number(fe??c),Z=pe??l,ke=!F,Q=ke?ae(k):``,Ae=ke&&!!Q,je=f(async()=>{let t=B;if(!(!I||!t||U.current)){U.current=!0,xe(!0);try{let n=await e({cursor:t,page_size:G,tags:L.length>0?L:void 0,cat_id:R||void 0}),r=Array.isArray(n.data?.videos)?n.data.videos:[],i=N(n.data?.cursor);r.length>0&&_e(e=>e.concat(r)),V(e=>{if(!(!r.length||!i))return i===e?void 0:i})}catch(e){console.error(`推荐位加载下一页失败(client)`,e),V(void 0)}finally{U.current=!1,xe(!1)}}},[B,R,G,L,I]),Me=f(()=>{Q&&(Q.startsWith(`http`)?window.location.href=Q:S.push(Q))},[Q,S]);p(()=>{let e=H.current;if(!e||!I||!De)return;let t=
|
|
2
|
+
"use client";import{pContentGetPopularVideoList as e}from"../../../../../service/generated/client.mjs";import{Image as t}from"../../../../ui/image.mjs";import{Box as n}from"../../../../ui/box.mjs";import{Text as r}from"../../../../ui/text.mjs";import i from"../../../../../assets/icons/detail/video_flag.mjs";import{MiniThreeCard as a}from"../../../../common/cards/mini-three-card.mjs";import{HOME_RECOMMEND_DEFAULT_GRID_COLUMNS as o,HOME_RECOMMEND_DEFAULT_GRID_ROWS as s,HOME_RECOMMEND_DEFAULT_PLAY_COUNT_DELTA as c,HOME_RECOMMEND_DEFAULT_SHOW_EPISODE as l,HOME_RECOMMEND_DEFAULT_SHOW_PLAY_COUNT as u,HOME_RECOMMEND_MAX_GRID_COLUMNS as ee,HOME_RECOMMEND_MAX_GRID_ROWS as te}from"./home-recommend-default-config.mjs";import{HOME_RECOMMEND_CARD_CONFIG_FIELD as d}from"./home-recommend-preview.mjs";import{useCallback as f,useEffect as p,useLayoutEffect as m,useMemo as h,useRef as g,useState as _}from"react";import{jsx as v,jsxs as y}from"react/jsx-runtime";import{useRouter as ne}from"next/navigation";const re={},ie={list:[]};function b({variant:t,props:i=re,data:a=ie,mode:d=`renderer`}){let b=d===`editor`,S=ne(),{list:C,title:se,cursor:T}=a,E=h(()=>Array.isArray(C)?C:[],[C]),D=h(()=>Array.isArray(a.icons)?a.icons:[],[a.icons]),{rows:O,columns:ce,moreLink:k,title:A,smartTagEnabled:j,smartTagIds:M,catId:ue,showPlayCount:de,playCountDelta:fe,showEpisode:pe,enableInfinite:me}=i,F=me===!0&&j===!0,I=!b&&F&&E.length>=16,L=h(()=>Array.isArray(M)?M.map(e=>String(e||``).trim()).filter(Boolean):[],[M]),R=typeof ue==`string`?ue.trim():``,[z,he]=_(0),[ge,_e]=_(E),[ve,ye]=_(D),[B,V]=_(()=>N(T)),[be,xe]=_(!1),Se=g(null),H=g(null),U=g(!1);p(()=>{_e(E),ye(D),V(N(T))},[T,D,E]);let Ce=oe(O,s,te),W=oe(ce,o,ee),G=F?16:t===`grid`?Ce*W:16,we=Ce*W,Te=b&&t===`grid`,K=Te?ge.slice(0,we):ge,q=Te?ve.slice(0,we):ve,Ee=t===`waterfall`?6:4,J=K.length>0?Math.max(0,K.length-Ee):-1,De=!!B,Oe=A&&A.trim()||se||``,Y=de??u,X=Number(fe??c),Z=pe??l,ke=!F,Q=ke?ae(k):``,Ae=ke&&!!Q,je=f(async()=>{let t=B;if(!(!I||!t||U.current)){U.current=!0,xe(!0);try{let n=await e({cursor:t,page_size:G,tags:L.length>0?L:void 0,cat_id:R||void 0}),r=Array.isArray(n.data?.videos)?n.data.videos:[],i=N(n.data?.cursor);r.length>0&&_e(e=>e.concat(r)),V(e=>{if(!(!r.length||!i))return i===e?void 0:i})}catch(e){console.error(`推荐位加载下一页失败(client)`,e),V(void 0)}finally{U.current=!1,xe(!1)}}},[B,R,G,L,I]),Me=f(()=>{Q&&(Q.startsWith(`http`)?window.location.href=Q:S.push(Q))},[Q,S]);p(()=>{let e=H.current;if(!e||!I||!De)return;let t=new IntersectionObserver(e=>{!e[0]?.isIntersecting||be||je()},{root:null,threshold:0});return t.observe(e),()=>{t.disconnect()}},[je,De,be,K.length,G,I,J]),m(()=>{let e=Se.current;if(!e||t!==`waterfall`)return;let n=()=>{let t=e.clientWidth||0;he(t>0?(t-12)/2:0)};n();let r=new ResizeObserver(n);return r.observe(e),()=>{r.disconnect()}},[t]);let $=h(()=>t===`waterfall`?le(K,q,z):{left:[],right:[]},[z,q,K,t]);return K.length?y(n,{className:`w-full mt-[16px]`,children:[y(n,{className:`flex items-center justify-between px-[12px] mb-[8px]`,children:[v(r,{className:`flex-1 min-w-0 text-text1 text-[18px] leading-[26px] font-bold line-clamp-1`,children:Oe}),Ae&&v(r,{className:`text-text3 text-[12px] leading-[18px] cursor-pointer`,onClick:Me,children:`更多`})]}),t===`grid`&&v(n,{className:`w-full flex flex-wrap px-[12px]`,children:K.map((e,n)=>{let r=q[n],i=w(e),a=Y&&(i?.showPlayCount??!0),o=i?.playCountDelta??X,s=i?.showEpisode??Z,c=n%W,l=W>1?{paddingLeft:12*c/W,paddingRight:12*(W-c-1)/W}:void 0;return v(`div`,{ref:n===J?H:void 0,className:`min-w-0`,style:{width:`${100/W}%`,...l||{}},children:v(x,{variant:t,item:e,icon:r,index:n,showPlayCount:a,playCountDelta:o,showEpisode:s,widthStyle:{width:`100%`}})},P(e,n))})}),t===`waterfall`&&y(n,{ref:Se,className:`w-full px-[12px] flex gap-[12px]`,children:[v(n,{className:`flex-1 min-w-0 flex flex-col`,children:$.left.map(e=>{let n=w(e.item),r=Y&&(n?.showPlayCount??!0),i=n?.playCountDelta??X,a=n?.showEpisode??Z;return v(`div`,{ref:e.index===J?H:void 0,children:v(x,{variant:t,item:e.item,icon:e.icon,index:e.index,showPlayCount:r,playCountDelta:i,showEpisode:a,widthStyle:{width:`100%`}})},P(e.item,e.index))})}),v(n,{className:`flex-1 min-w-0 flex flex-col`,children:$.right.map(e=>{let n=w(e.item),r=Y&&(n?.showPlayCount??!0),i=n?.playCountDelta??X,a=n?.showEpisode??Z;return v(`div`,{ref:e.index===J?H:void 0,children:v(x,{variant:t,item:e.item,icon:e.icon,index:e.index,showPlayCount:r,playCountDelta:i,showEpisode:a,widthStyle:{width:`100%`}})},P(e.item,e.index))})})]})]}):null}function x({variant:e,item:t,icon:o,index:s,showPlayCount:c,playCountDelta:l,showEpisode:u,widthStyle:ee}){let te=se(t),d=t.name||t?.title||``,f=O(ce(t.static?.browse_cnt??0,l)),p=E(t,u),m=j(t,o,s);return v(a,{url:te,text:d,className:`w-full`,style:ee,topRightChild:m?v(S,{url:m}):void 0,bottomLeftChild:c?y(n,{className:`h-[20px] leading-[20px] text-[#fff] text-[12px] px-[4px] rounded-[4px] bg-[#333] ml-[4px] flex items-center`,children:[v(i,{className:`w-[16px] h-[auto] text-[#fff] mr-[4px]`}),f]}):null,bottomRightChild:u?p&&v(r,{className:`text-[#fff] text-[12px] leading-[18px] pr-2`,children:p}):null,textChild:v(n,{className:`py-[4px]`,children:v(r,{as:`h3`,className:`text-text1 text-[16px] leading-[24px] ${e===`waterfall`?`break-words line-clamp-3`:`line-clamp-1`}`,children:d})}),linkPath:C(t)})}function S({url:e}){return v(n,{className:`relative w-[40px] h-[20px]`,children:v(t,{src:e,alt:`corner`,width:40,height:20,className:`w-full h-auto`})})}function C(e){let t=encodeURIComponent(e.name||``);return`/video/${e.id||``}/${t}/episode/1`}function ae(e){return e?e.trim():``}function oe(e,t,n){let r=Number(e);return!Number.isFinite(r)||r<=0?t:Math.min(n,Math.floor(r))}function w(e){return e[d]}function se(e){return e.img_y||e.img_x||e?.coverUrl}function T(e){return typeof e==`string`?e:``}function E(e,t){if(!t)return``;if(D(e)){let t=Number(e.episode_cnt||e.links?.length||0);return t>0?`全${t}集`:``}return A(Number(e.duration||0))}function D(e){if(Number(e.type??0)===2)return!0;let t=Number(e.episode_cnt||e.links?.length||0);return Number.isFinite(t)&&t>1}function O(e){return!Number.isFinite(e)||e<=0?`0`:e>=1e6?`${k(e/1e6)}M`:e>=1e3?`${k(e/1e3)}k`:Math.floor(e).toString()}function ce(e,t){let n=Number(e||0),r=Number(t||0);return!Number.isFinite(n)||!Number.isFinite(r)?0:Math.max(0,n+r)}function k(e){let t=e.toFixed(1);return t.endsWith(`.0`)?t.slice(0,-2):t}function A(e){if(!Number.isFinite(e)||e<=0)return``;let t=Math.floor(e),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=e=>String(e).padStart(2,`0`);return n>0?`${a(n)}:${a(r)}:${a(i)}`:`${a(r)}:${a(i)}`}function j(e,t,n){return T(e.badge_url)||T(t?.material_url)||``}function le(e,t,n){let r=[],i=[],a=n<=0,o=0,s=0;return e.forEach((e,c)=>{let l=t[c];if(a){c%2==0?r.push({item:e,icon:l,index:c}):i.push({item:e,icon:l,index:c});return}let u=M(n,e);o<=s?(r.push({item:e,icon:l,index:c}),o+=u):(i.push({item:e,icon:l,index:c}),s+=u)}),{left:r,right:i}}function M(e,t){if(!e)return 0;let n=e*1.3461538461538463,r=E(t,!0)?18:0;return n+20+r+6+16}function N(e){if(typeof e==`string`)return e.trim()||void 0}function P(e,t){return e.id?`home-recommend-${e.id}`:`home-recommend-${t}`}export{b as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{gContentGetAppChannelBlockData as e}from"../../../../../../../service/generated/client.mjs";import{Box as t}from"../../../../../../ui/box.mjs";import{InfiniteScroll as n}from"../../../../../../ui/infinite-scroll.mjs";import{usePaginated as r}from"../../../../../../../hooks/query/use-query.mjs";import{UserActivityListItem as i}from"../../../../../../common/list/user-activity-list/user-activity-list-item.mjs";import{useLayoutEffect as a,useMemo as o,useRef as s,useState as c}from"react";import{jsx as l}from"react/jsx-runtime";const u={},d={list:[],cursor:``,block_id:``};function f({props:f=u,styles:p,data:m=d}){let{list:h,cursor:g,block_id:_}=m,v=h&&h.length>0,y=o(()=>{if(!v)return;let e=g&&g.trim()?g:void 0;return{pages:[{data:{block:{data:{contents:h,cursor:g||``}}}}],pageParams:[e]}},[v,h,g]),{data:b,fetchNextPage:x,hasNextPage:S}=r({key:[`basic-post-card`,_],queryFn:t=>e({block_id:_,cursor:t||void 0,page_size:12}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!_,initialData:y,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:v&&g&&g.trim()?g:void 0}),C=s(h),[w,T]=c(!1);a(()=>{T(!0)},[]);let[E,D]=c({}),O=o(()=>{let e=[...C.current];if(!w)return e.map(e=>{let t=e.content_id;if(!t)return e;let n=E[t];return n===void 0?e:{...e,is_collected:n}});let t=[...e],n=b?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.contents||[];t.push(...r)}return t.map(e=>{let t=e.content_id;if(!t)return e;let n=E[t];return n===void 0?e:{...e,isCollected:n,is_collected:n}})},[b?.pages,w,E]);return l(t,{children:l(n,{loadMore:()=>x().then(()=>{}),hasMore:S===!0||S===void 0&&!!g&&h.length>0,initialLoad:!0,
|
|
2
|
+
"use client";import{gContentGetAppChannelBlockData as e}from"../../../../../../../service/generated/client.mjs";import{Box as t}from"../../../../../../ui/box.mjs";import{InfiniteScroll as n}from"../../../../../../ui/infinite-scroll.mjs";import{usePaginated as r}from"../../../../../../../hooks/query/use-query.mjs";import{UserActivityListItem as i}from"../../../../../../common/list/user-activity-list/user-activity-list-item.mjs";import{useLayoutEffect as a,useMemo as o,useRef as s,useState as c}from"react";import{jsx as l}from"react/jsx-runtime";const u={},d={list:[],cursor:``,block_id:``};function f({props:f=u,styles:p,data:m=d}){let{list:h,cursor:g,block_id:_}=m,v=h&&h.length>0,y=o(()=>{if(!v)return;let e=g&&g.trim()?g:void 0;return{pages:[{data:{block:{data:{contents:h,cursor:g||``}}}}],pageParams:[e]}},[v,h,g]),{data:b,fetchNextPage:x,hasNextPage:S}=r({key:[`basic-post-card`,_],queryFn:t=>e({block_id:_,cursor:t||void 0,page_size:12}),getNextPageParam:e=>{let t=e.data?.block?.data?.cursor;return t&&t.trim()?t:void 0},options:{enabled:!!_,initialData:y,refetchOnMount:!1,refetchOnWindowFocus:!1,refetchOnReconnect:!1},initialPageParam:v&&g&&g.trim()?g:void 0}),C=s(h),[w,T]=c(!1);a(()=>{T(!0)},[]);let[E,D]=c({}),O=o(()=>{let e=[...C.current];if(!w)return e.map(e=>{let t=e.content_id;if(!t)return e;let n=E[t];return n===void 0?e:{...e,is_collected:n}});let t=[...e],n=b?.pages;if(n&&n.length>1)for(let e=1;e<n.length;e++){let r=n[e].data?.block?.data?.contents||[];t.push(...r)}return t.map(e=>{let t=e.content_id;if(!t)return e;let n=E[t];return n===void 0?e:{...e,isCollected:n,is_collected:n}})},[b?.pages,w,E]);return l(t,{children:l(n,{loadMore:()=>x().then(()=>{}),hasMore:S===!0||S===void 0&&!!g&&h.length>0,initialLoad:!0,threshold:1e3,children:O.map(e=>l(i,{is_collected:e.is_collected,onCollectChange:(e,t)=>{e&&D(n=>({...n,[e]:t}))},...e},e.content_id||`item-${e.author?.user_id}-${e.create_time}`))})})}export{f as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{cn as e}from"../../../../../utils/cn.mjs";import{Button as t}from"../../../../ui/button.mjs";import{useUserStore as n}from"../../../../../store/modules/user-store.mjs";import{Box as r}from"../../../../ui/box.mjs";import{EmptyState as i}from"../../../../ui/empty.mjs";import{Tabs as a,TabsList as o,TabsTrigger as s}from"../../../../ui/tabs.mjs";import{Text as c}from"../../../../ui/text.mjs";import{useLoginModalStore as l}from"../../../../../store/modules/login-modal-store.mjs";import{profileMainMineTabOptions as u,profileMainProfileTabOptions as d}from"./variants.mjs";import{useEffect as f,useMemo as p,useRef as m}from"react";import{jsx as h,jsxs as g}from"react/jsx-runtime";import{useTranslations as _}from"next-intl";import{parseAsString as v,useQueryState as y}from"nuqs";function b(e){return e?[...u]:[...d]}function x(e,t){let n=b(t);return n.includes(e)?e:n[0]}function S(e){let t=window.getComputedStyle(e);return/auto|scroll|overlay/.test(t.overflowY)}function C(e){if(typeof window>`u`)return null;let t=e?.parentElement??null;for(;t;){if(S(t))return t;t=t.parentElement}
|
|
2
|
+
"use client";import{cn as e}from"../../../../../utils/cn.mjs";import{Button as t}from"../../../../ui/button.mjs";import{useUserStore as n}from"../../../../../store/modules/user-store.mjs";import{Box as r}from"../../../../ui/box.mjs";import{EmptyState as i}from"../../../../ui/empty.mjs";import{Tabs as a,TabsList as o,TabsTrigger as s}from"../../../../ui/tabs.mjs";import{Text as c}from"../../../../ui/text.mjs";import{useLoginModalStore as l}from"../../../../../store/modules/login-modal-store.mjs";import{profileMainMineTabOptions as u,profileMainProfileTabOptions as d}from"./variants.mjs";import{useEffect as f,useMemo as p,useRef as m}from"react";import{jsx as h,jsxs as g}from"react/jsx-runtime";import{useTranslations as _}from"next-intl";import{parseAsString as v,useQueryState as y}from"nuqs";function b(e){return e?[...u]:[...d]}function x(e,t){let n=b(t);return n.includes(e)?e:n[0]}function S(e){let t=window.getComputedStyle(e);return/auto|scroll|overlay/.test(t.overflowY)}function C(e){if(typeof window>`u`)return null;let t=e?.parentElement??null;for(;t;){if(S(t))return t;t=t.parentElement}return null}function w(e){return typeof window>`u`?0:e?e.scrollTop:window.scrollY||window.pageYOffset||0}function T(e,t){if(!(typeof window>`u`)){if(e){e.scrollTo({top:t});return}window.scrollTo({top:t,left:0})}}function E({profileId:u,currentUserId:d,isMine:S,renderMode:E,className:D,children:O}){let k=_(`components.pages.profile`),A=m(null),j=l(e=>e.open),M=n(e=>e.userId),N=b(S),[P,F]=y(`tab`,v.withDefault(`collect`)),I=p(()=>x(P,S),[S,P]),L=S?d||M||``:u,R=p(()=>`profile-scroll:${L||(S?`mine`:`guest`)}:${I}`,[S,I,L]);f(()=>{P!==I&&F(I,{shallow:!1})},[I,F,P]),f(()=>{if(typeof window>`u`)return;let e=C(A.current),t=window.sessionStorage.getItem(R),n=t?Number(t):0;Number.isFinite(n)&&n>0&&requestAnimationFrame(()=>{T(e,n)});let r=!1,i=()=>{r||(r=!0,requestAnimationFrame(()=>{window.sessionStorage.setItem(R,String(w(e))),r=!1}))};return e?(e.addEventListener(`scroll`,i,{passive:!0}),()=>{e.removeEventListener(`scroll`,i)}):(window.addEventListener(`scroll`,i,{passive:!0}),()=>{window.removeEventListener(`scroll`,i)})},[R]);let z={collect:k(`client.collect`),like:k(`client.like`),history:k(`client.history`)},B=O;return E===`login-required`?B=g(r,{className:`flex gap-4 flex-col items-center justify-center py-10 text-center`,children:[h(c,{className:`text-base text-text1`,children:k(`client.loginToView`)}),h(t,{size:`lg`,variant:`secondary`,onClick:j,children:k(`client.loginNow`)})]}):E===`privacy-collect`?B=h(i,{type:`no-content`,text:k(`client.collectionNotPublic`)}):E===`privacy-like`&&(B=h(i,{type:`no-content`,text:k(`client.likeNotPublic`)})),g(r,{ref:A,className:e(D),children:[h(r,{className:`border-b bg-bg1 sticky z-10 top-0 border-text1/5 h-10`,children:h(a,{value:I,onValueChange:e=>{F(e,{shallow:!1})},className:`w-fit`,children:h(o,{variant:`default`,className:`inline-flex h-9`,children:N.map(e=>h(s,{value:e,className:`p-2.5 !text-base !w-fit data-active:!text-lg data-active:font-bold`,children:z[e]},e))})})}),h(r,{className:`p-2`,children:B})]})}export{E as UserProfileMainShell};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{gContentGetAppChannelBlock as e,gContentGetAppChannelBlockData as t,gContentListVisibleFloatingBall as n}from"../../../service/generated/client.mjs";import{Image as r}from"../../ui/image.mjs";import{Box as i}from"../../ui/box.mjs";import{useRequest as a}from"../../../hooks/query/use-query.mjs";import{useRequireLogin as o}from"../../../hooks/use-auth.mjs";import{queryKey as s}from"../../../constants/query-key.mjs";import{useKeepAliveState as c}from"../../common/keep-scroll-position/index.mjs";import{extractDataByComponentType as l}from"../../biz/utils/transformers/data.mjs";import{useEffect as u,useLayoutEffect as d,useMemo as f,useRef as p}from"react";import{Fragment as m,jsx as h,jsxs as g}from"react/jsx-runtime";import{useRouter as _}from"next/navigation";
|
|
2
|
+
"use client";import{gContentGetAppChannelBlock as e,gContentGetAppChannelBlockData as t,gContentListVisibleFloatingBall as n}from"../../../service/generated/client.mjs";import{Image as r}from"../../ui/image.mjs";import{Box as i}from"../../ui/box.mjs";import{useRequest as a}from"../../../hooks/query/use-query.mjs";import{useRequireLogin as o}from"../../../hooks/use-auth.mjs";import{queryKey as s}from"../../../constants/query-key.mjs";import{useKeepAliveState as c}from"../../common/keep-scroll-position/index.mjs";import{extractDataByComponentType as l}from"../../biz/utils/transformers/data.mjs";import{useEffect as u,useLayoutEffect as d,useMemo as f,useRef as p}from"react";import{Fragment as m,jsx as h,jsxs as g}from"react/jsx-runtime";import{useRouter as _}from"next/navigation";function v(){if(typeof document>`u`)return 0;let e=document.querySelector(`[data-top-nav-root="true"]`);return e&&e.getBoundingClientRect().height||0}function y({currentChannelId:y,isPGC:b}){let x=_(),S=o(),{data:C}=a(s.GET_CONTENT_LIST(y),()=>e({channel_id:y})),{data:w}=a([s.FLOATING_BALL],()=>n()),T=f(()=>C?.data?.blocks||[],[C?.data?.blocks]),E=f(()=>{let e=T.findIndex(e=>e.type===4),t=e>=0?T[e]:null;return{index:e,block:t,blockId:t?.id||``}},[T]),{data:D}=a([s.GUESS_YOU_LIKE_USER_DATA,E.blockId],()=>t({block_id:E.blockId}),{enabled:!!E.blockId}),O=f(()=>{if(E.index<0)return T;let e=D?.data.block?.data?.users||[];return T.map((t,n)=>n===E.index?{...t,data:{...t.data||{},users:e}}:t)},[T,D,E.index]),[k,A]=c(`home-scroll-top-${y}`,0),j=p({restored:!1,lastScrollTop:k,key:y,rafId:null}),M=p(A),N=p(k);u(()=>{M.current=A},[A]),u(()=>{N.current=k},[k]),u(()=>{j.current.key!==y&&(j.current.restored=!1,j.current.lastScrollTop=k,N.current=k,j.current.key=y)},[y,k]);let P=O.length>0;d(()=>{if(!P||j.current.restored||k<=0)return;let e=v(),t=Math.max(0,k+e);window.requestAnimationFrame(()=>{window.scrollTo({top:t}),j.current.restored=!0,j.current.lastScrollTop=t})},[P,y,k]),u(()=>{let e=j.current;function t(){e.restored=!0,e.rafId!==null&&window.cancelAnimationFrame(e.rafId),e.rafId=window.requestAnimationFrame(()=>{e.rafId=null;let t=window.scrollY??document.documentElement.scrollTop??0,n=v(),r=Math.max(0,t-n);Math.abs(t-e.lastScrollTop)>1&&(e.lastScrollTop=t,M.current(r))})}return window.addEventListener(`scroll`,t,{passive:!0}),()=>{e.rafId!==null&&(window.cancelAnimationFrame(e.rafId),e.rafId=null),window.removeEventListener(`scroll`,t)}},[y]);let F=f(()=>l(O,b),[O,b]),I=f(()=>w?.data?.ball_infos?.find(e=>e.channel_id===y),[w?.data?.ball_infos,y]);return g(m,{children:[I&&h(i,{className:`fixed right-[20px] bottom-[80px] w-[52px] h-[52px] z-30 rounded-[16px] cursor-move select-none bg-[#FD4C5E33] overflow-hidden`,onClick:()=>{S(()=>{I?.jump_url&&x.push(I.jump_url)})},children:h(r,{src:I.material_url||``,alt:I.name||``,fill:!0,priority:!0,fetchPriority:`high`,sizes:`52px`,unoptimized:!0})}),F.map(e=>{let t=e.component,n=e.data.block_id||`block-${e.data.title||``}`;return h(t,{data:e.data},n)})]})}export{y as default};
|
|
@@ -8,7 +8,7 @@ import * as class_variance_authority_types0 from "class-variance-authority/types
|
|
|
8
8
|
/** buttonVariants 工具定义。 */
|
|
9
9
|
declare const buttonVariants: (props?: ({
|
|
10
10
|
variant?: "link" | "default" | "destructive" | "secondary" | "outline" | "ghost" | null | undefined;
|
|
11
|
-
size?: "default" | "
|
|
11
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
13
13
|
/** Button 组件属性。 */
|
|
14
14
|
type ButtonProps = Button.Props & VariantProps<typeof buttonVariants> & {
|
|
@@ -25,10 +25,6 @@ interface InfiniteScrollProps {
|
|
|
25
25
|
className?: string;
|
|
26
26
|
/** 是否禁用自动加载逻辑。 */
|
|
27
27
|
disabled?: boolean;
|
|
28
|
-
/**
|
|
29
|
-
* 滚动容器引用(用于容器内滚动)
|
|
30
|
-
*/
|
|
31
|
-
rootId?: string;
|
|
32
28
|
/** 组件挂载时是否立即触发一次加载。 */
|
|
33
29
|
initialLoad?: boolean;
|
|
34
30
|
}
|
|
@@ -46,7 +42,6 @@ declare function InfiniteScroll({
|
|
|
46
42
|
children,
|
|
47
43
|
className,
|
|
48
44
|
disabled,
|
|
49
|
-
rootId,
|
|
50
45
|
initialLoad
|
|
51
46
|
}: InfiniteScrollProps): react_jsx_runtime0.JSX.Element;
|
|
52
47
|
//#endregion
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{useTranslations as o}from"next-intl";const s=()=>a(`span`,{className:`inline-flex gap-1 ml-1`,children:[i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse`}),i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse animation-delay-200`}),i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse animation-delay-400`})]});function c({loadMore:c,hasMore:l,threshold:u=0,loadingText:d,emptyText:f,noMoreText:p,failedText:m,children:h,className:g=``,disabled:_=!1,
|
|
2
|
+
"use client";import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{useTranslations as o}from"next-intl";const s=()=>a(`span`,{className:`inline-flex gap-1 ml-1`,children:[i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse`}),i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse animation-delay-200`}),i(`span`,{className:`w-1 h-1 bg-current rounded-full animate-pulse animation-delay-400`})]});function c({loadMore:c,hasMore:l,threshold:u=0,loadingText:d,emptyText:f,noMoreText:p,failedText:m,children:h,className:g=``,disabled:_=!1,initialLoad:v=!1}){let y=o(`components.ui`),[b,x]=r(!1),[S,C]=r(!1),w=n(null),T=n(!1),E=n(!1),D=n(0),O=e(()=>window.scrollY??document.documentElement.scrollTop??0,[]),k=d??y(`infiniteScroll.loading`),A=m??y(`infiniteScroll.failed`),j=f??p??y(`infiniteScroll.noMore`),M=l!==!1,N=e(async(e,t)=>{if(!(_||T.current||!t&&!M)){T.current=!0,C(!0),e&&x(!1);try{await c(e)}catch{x(!0)}finally{T.current=!1}}},[M,_,c]),P=e(async(e=!1)=>{await N(e,!1)},[N]);t(()=>{!v||E.current||(E.current=!0,N(!1,!0))},[N,v]),t(()=>{let e=w.current;if(!e||_)return;let t=new IntersectionObserver(e=>{let t=e[0];if(t&&t.isIntersecting&&!T.current&&M){let e=O();if(e<=D.current)return;D.current=e,x(!1),P(!1)}},{root:null,rootMargin:`0px 0px ${u}px 0px`,threshold:0});return t.observe(e),()=>{t.disconnect()}},[_,P,M,O,u]);let F=()=>{x(!1),P(!0)};return _?i(`div`,{className:g,children:h}):a(`div`,{className:g,children:[h,a(`div`,{children:[i(`div`,{ref:w,className:`h-[10px]`,"aria-hidden":`true`}),M&&!b&&a(`div`,{className:`flex items-center justify-center text-[12px] h-8.5`,children:[i(`span`,{className:`text-text2 mr-2`,children:k}),i(s,{})]}),b&&i(`div`,{className:`text-center text-theme5 cursor-pointer`,onClick:F,children:A}),l===!1&&!b&&i(`div`,{className:`text-center text-text3 pt-1.5 pb-3 border-text1/5 border-b`,children:j})]})]})}export{c as InfiniteScroll};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
"use client";import{useEffect as e,useRef as t,useState as n}from"react";function r(r
|
|
2
|
+
"use client";import{useEffect as e,useRef as t,useState as n}from"react";function r(r){let[i,a]=n(!1),o=t(null),s=t(null);return e(()=>{let e=o.current;if(!e)return;let t=r?document.getElementById(r):null,n=!t,i=()=>t?t.scrollTop:window.scrollY??document.documentElement.scrollTop??0;if(s.current===null){let n=e.getBoundingClientRect();if(t){let e=t.getBoundingClientRect();s.current=n.top-e.top+t.scrollTop}else s.current=n.top+i()}let c=()=>{let e=i()>=s.current;a(t=>t===e?t:e)};return n?window.addEventListener(`scroll`,c,{passive:!0}):t.addEventListener(`scroll`,c,{passive:!0}),c(),()=>{n?window.removeEventListener(`scroll`,c):t.removeEventListener(`scroll`,c)}},[r]),{isSticky:i,ref:o}}export{r as useSticky};
|
package/dist/utils/helper.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
function e(e){return`${(e/430*100).toFixed(3)}vw`}function t(e){if(e)return e.trim()||void 0}function n(){
|
|
2
|
+
function e(e){return`${(e/430*100).toFixed(3)}vw`}function t(e){if(e)return e.trim()||void 0}function n(){typeof document<`u`&&(document.body.style.overflow=`hidden`)}function r(){typeof document<`u`&&(document.body.style.overflow=``)}export{n as disablePageScroll,r as enablePageScroll,t as normalizeClassName,e as pxToVw};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funhub/platform",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.110",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": [
|
|
7
7
|
"**/*.css"
|
|
@@ -62,12 +62,9 @@
|
|
|
62
62
|
},
|
|
63
63
|
"./theme.css": "./theme.css"
|
|
64
64
|
},
|
|
65
|
-
"bin": "./bin/index.mjs",
|
|
66
65
|
"files": [
|
|
67
|
-
"bin",
|
|
68
66
|
"config",
|
|
69
67
|
"dist",
|
|
70
|
-
"templates",
|
|
71
68
|
"theme.css"
|
|
72
69
|
],
|
|
73
70
|
"scripts": {
|
|
@@ -92,8 +89,7 @@
|
|
|
92
89
|
"i18n:build": "node scripts/i18n-flat-sync.mjs build",
|
|
93
90
|
"i18n:watch": "node scripts/i18n-flat-sync.mjs watch",
|
|
94
91
|
"i18n:check": "node scripts/i18n-flat-sync.mjs check",
|
|
95
|
-
"pretest": "pnpm i18n:build"
|
|
96
|
-
"init:local": "node ./bin/index.mjs"
|
|
92
|
+
"pretest": "pnpm i18n:build"
|
|
97
93
|
},
|
|
98
94
|
"peerDependencies": {
|
|
99
95
|
"@tanstack/query-core": ">=5",
|
package/bin/index.mjs
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/* eslint-disable no-console */
|
|
4
|
-
import { spawn } from 'node:child_process';
|
|
5
|
-
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import process from 'node:process';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import { cac } from 'cac';
|
|
10
|
-
|
|
11
|
-
const currentFilePath = fileURLToPath(import.meta.url);
|
|
12
|
-
const packageRoot = path.resolve(path.dirname(currentFilePath), '..');
|
|
13
|
-
const templatesRoot = path.join(packageRoot, 'templates');
|
|
14
|
-
const platformPackageJson = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 获取可用模板列表。
|
|
18
|
-
* @returns {Array<{ name: string, title: string, description: string, directory: string }>}
|
|
19
|
-
*/
|
|
20
|
-
function getAvailableTemplates() {
|
|
21
|
-
if (!existsSync(templatesRoot)) {
|
|
22
|
-
return [];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return readdirSync(templatesRoot)
|
|
26
|
-
.map((entryName) => {
|
|
27
|
-
const templateDir = path.join(templatesRoot, entryName);
|
|
28
|
-
if (!statSync(templateDir).isDirectory()) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const metaFilePath = path.join(templateDir, '_meta.json');
|
|
33
|
-
if (!existsSync(metaFilePath)) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const meta = JSON.parse(readFileSync(metaFilePath, 'utf8'));
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
name: entryName,
|
|
41
|
-
title: meta.title || entryName,
|
|
42
|
-
description: meta.description || '',
|
|
43
|
-
directory: templateDir,
|
|
44
|
-
};
|
|
45
|
-
})
|
|
46
|
-
.filter(Boolean);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 解析默认包管理器。
|
|
51
|
-
* @returns {'pnpm' | 'npm' | 'yarn' | 'bun'}
|
|
52
|
-
*/
|
|
53
|
-
function detectPackageManager() {
|
|
54
|
-
const userAgent = process.env.npm_config_user_agent || '';
|
|
55
|
-
|
|
56
|
-
if (userAgent.startsWith('yarn/')) {
|
|
57
|
-
return 'yarn';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (userAgent.startsWith('bun/')) {
|
|
61
|
-
return 'bun';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (userAgent.startsWith('npm/')) {
|
|
65
|
-
return 'npm';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return 'pnpm';
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* 根据当前平台返回命令名。
|
|
73
|
-
* @param {'pnpm' | 'npm' | 'yarn' | 'bun' | 'git'} command
|
|
74
|
-
* @returns {string}
|
|
75
|
-
*/
|
|
76
|
-
function resolveCommand(command) {
|
|
77
|
-
return process.platform === 'win32' ? `${command}.cmd` : command;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* 将目录名转换为 npm 包名。
|
|
82
|
-
* @param {string} projectName
|
|
83
|
-
* @returns {string}
|
|
84
|
-
*/
|
|
85
|
-
function toPackageName(projectName) {
|
|
86
|
-
return projectName
|
|
87
|
-
.trim()
|
|
88
|
-
.toLowerCase()
|
|
89
|
-
.replace(/\s+/g, '-')
|
|
90
|
-
.replace(/[^a-z0-9-_.~/@]/g, '-')
|
|
91
|
-
.replace(/-+/g, '-');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* 校验项目名是否合法。
|
|
96
|
-
* @param {string} projectName
|
|
97
|
-
*/
|
|
98
|
-
function validateProjectName(projectName) {
|
|
99
|
-
if (!projectName) {
|
|
100
|
-
throw new Error('项目名不能为空。');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (projectName === '.' || projectName === '..') {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (!/^[\w.-]+$/.test(projectName)) {
|
|
108
|
-
throw new Error('项目目录名仅支持字母、数字、点、中划线和下划线。');
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* 递归遍历目录文件。
|
|
114
|
-
* @param {string} targetDir
|
|
115
|
-
* @returns {string[]}
|
|
116
|
-
*/
|
|
117
|
-
function collectFiles(targetDir) {
|
|
118
|
-
const entries = readdirSync(targetDir, { withFileTypes: true });
|
|
119
|
-
const filePaths = [];
|
|
120
|
-
|
|
121
|
-
for (const entry of entries) {
|
|
122
|
-
const entryPath = path.join(targetDir, entry.name);
|
|
123
|
-
if (entry.isDirectory()) {
|
|
124
|
-
filePaths.push(...collectFiles(entryPath));
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
filePaths.push(entryPath);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return filePaths;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 判断文件是否可按文本方式渲染。
|
|
135
|
-
* @param {string} filePath
|
|
136
|
-
* @returns {boolean}
|
|
137
|
-
*/
|
|
138
|
-
function isRenderableTextFile(filePath) {
|
|
139
|
-
return /\.(?:json|md|tsx?|jsx?|mjs|cjs|css|txt|ya?ml|gitignore)$/i.test(filePath);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 渲染模板目录中的占位符文件。
|
|
144
|
-
* @param {string} targetDir
|
|
145
|
-
* @param {Record<string, string>} variables
|
|
146
|
-
*/
|
|
147
|
-
function renderTemplateFiles(targetDir, variables) {
|
|
148
|
-
const filePaths = collectFiles(targetDir);
|
|
149
|
-
|
|
150
|
-
for (const filePath of filePaths) {
|
|
151
|
-
const dirName = path.dirname(filePath);
|
|
152
|
-
const baseName = path.basename(filePath);
|
|
153
|
-
|
|
154
|
-
if (baseName === '__dot__gitignore') {
|
|
155
|
-
renameSync(filePath, path.join(dirName, '.gitignore'));
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (baseName.endsWith('.template')) {
|
|
160
|
-
const nextFilePath = path.join(dirName, baseName.replace(/\.template$/, ''));
|
|
161
|
-
renameSync(filePath, nextFilePath);
|
|
162
|
-
renderSingleFile(nextFilePath, variables);
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
renderSingleFile(filePath, variables);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* 渲染单个文本文件。
|
|
172
|
-
* @param {string} filePath
|
|
173
|
-
* @param {Record<string, string>} variables
|
|
174
|
-
*/
|
|
175
|
-
function renderSingleFile(filePath, variables) {
|
|
176
|
-
if (!isRenderableTextFile(filePath)) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
let content = readFileSync(filePath, 'utf8');
|
|
181
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
182
|
-
content = content.replaceAll(`{{${key}}}`, value);
|
|
183
|
-
}
|
|
184
|
-
writeFileSync(filePath, content);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* 执行子进程命令。
|
|
189
|
-
* @param {string} command
|
|
190
|
-
* @param {string[]} args
|
|
191
|
-
* @param {string} cwd
|
|
192
|
-
* @returns {Promise<void>}
|
|
193
|
-
*/
|
|
194
|
-
function runCommand(command, args, cwd) {
|
|
195
|
-
return new Promise((resolve, reject) => {
|
|
196
|
-
const child = spawn(resolveCommand(command), args, {
|
|
197
|
-
cwd,
|
|
198
|
-
stdio: 'inherit',
|
|
199
|
-
shell: false,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
child.on('close', (code) => {
|
|
203
|
-
if (code === 0) {
|
|
204
|
-
resolve();
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
reject(new Error(`${command} ${args.join(' ')} 执行失败,退出码 ${code}`));
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* 获取安装命令。
|
|
215
|
-
* @param {'pnpm' | 'npm' | 'yarn' | 'bun'} packageManager
|
|
216
|
-
* @returns {{ command: string, args: string[] }}
|
|
217
|
-
*/
|
|
218
|
-
function getInstallCommand(packageManager) {
|
|
219
|
-
switch (packageManager) {
|
|
220
|
-
case 'npm':
|
|
221
|
-
return { command: 'npm', args: ['install'] };
|
|
222
|
-
case 'yarn':
|
|
223
|
-
return { command: 'yarn', args: [] };
|
|
224
|
-
case 'bun':
|
|
225
|
-
return { command: 'bun', args: ['install'] };
|
|
226
|
-
default:
|
|
227
|
-
return { command: 'pnpm', args: ['install'] };
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* 初始化项目。
|
|
233
|
-
* @param {string | undefined} inputName
|
|
234
|
-
* @param {{ template?: string, pm?: 'pnpm' | 'npm' | 'yarn' | 'bun', install?: boolean, git?: boolean, force?: boolean }} options
|
|
235
|
-
*/
|
|
236
|
-
async function initProject(inputName, options) {
|
|
237
|
-
const templateName = options.template || 'base';
|
|
238
|
-
const packageManager = options.pm || detectPackageManager();
|
|
239
|
-
const availableTemplates = getAvailableTemplates();
|
|
240
|
-
const matchedTemplate = availableTemplates.find(item => item.name === templateName);
|
|
241
|
-
|
|
242
|
-
if (!matchedTemplate) {
|
|
243
|
-
throw new Error(`未找到模板 ${templateName},可用模板:${availableTemplates.map(item => item.name).join(', ')}`);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const workingDir = process.cwd();
|
|
247
|
-
const projectName = inputName || 'funhub-app';
|
|
248
|
-
validateProjectName(projectName);
|
|
249
|
-
|
|
250
|
-
const targetDir = path.resolve(workingDir, projectName);
|
|
251
|
-
const targetExists = existsSync(targetDir);
|
|
252
|
-
const targetBaseName = projectName === '.' ? path.basename(workingDir) : path.basename(targetDir);
|
|
253
|
-
const packageName = toPackageName(targetBaseName);
|
|
254
|
-
|
|
255
|
-
if (targetExists) {
|
|
256
|
-
const targetEntries = readdirSync(targetDir);
|
|
257
|
-
if (targetEntries.length > 0) {
|
|
258
|
-
if (!options.force) {
|
|
259
|
-
throw new Error(`目标目录 ${targetDir} 非空,请改用空目录或显式传入 --force。`);
|
|
260
|
-
}
|
|
261
|
-
rmSync(targetDir, { recursive: true, force: true });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
mkdirSync(targetDir, { recursive: true });
|
|
266
|
-
|
|
267
|
-
const sourceTemplateDir = path.join(matchedTemplate.directory, 'template');
|
|
268
|
-
cpSync(sourceTemplateDir, targetDir, { recursive: true });
|
|
269
|
-
|
|
270
|
-
renderTemplateFiles(targetDir, {
|
|
271
|
-
PROJECT_NAME: targetBaseName,
|
|
272
|
-
PACKAGE_NAME: packageName,
|
|
273
|
-
PLATFORM_VERSION: platformPackageJson.version,
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
console.log(`\n已创建 Funhub 项目:${targetBaseName}`);
|
|
277
|
-
console.log(`模板:${matchedTemplate.title}`);
|
|
278
|
-
console.log(`目录:${targetDir}`);
|
|
279
|
-
|
|
280
|
-
if (options.install !== false) {
|
|
281
|
-
const installCommand = getInstallCommand(packageManager);
|
|
282
|
-
console.log(`\n正在安装依赖(${packageManager})...`);
|
|
283
|
-
await runCommand(installCommand.command, installCommand.args, targetDir);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (options.git !== false) {
|
|
287
|
-
console.log('\n正在初始化 Git 仓库...');
|
|
288
|
-
await runCommand('git', ['init'], targetDir);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const relativeTargetDir = path.relative(workingDir, targetDir) || '.';
|
|
292
|
-
console.log('\n下一步:');
|
|
293
|
-
if (relativeTargetDir !== '.') {
|
|
294
|
-
console.log(` cd ${relativeTargetDir}`);
|
|
295
|
-
}
|
|
296
|
-
if (options.install === false) {
|
|
297
|
-
const installCommand = getInstallCommand(packageManager);
|
|
298
|
-
console.log(` ${installCommand.command} ${installCommand.args.join(' ')}`.trimEnd());
|
|
299
|
-
}
|
|
300
|
-
console.log(` ${packageManager} dev`);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const cli = cac('@funhub/platform');
|
|
304
|
-
|
|
305
|
-
cli
|
|
306
|
-
.command('init [project-name]', '初始化一个 Funhub 应用')
|
|
307
|
-
.option('--template <template>', '模板名称,默认 base')
|
|
308
|
-
.option('--pm <packageManager>', '包管理器,可选 pnpm/npm/yarn/bun')
|
|
309
|
-
.option('--no-install', '跳过依赖安装')
|
|
310
|
-
.option('--no-git', '跳过 git init')
|
|
311
|
-
.option('--force', '强制覆盖非空目录')
|
|
312
|
-
.action(async (projectName, options) => {
|
|
313
|
-
try {
|
|
314
|
-
await initProject(projectName, options);
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
console.error(`\n❌ ${(error && error.message) || '初始化失败'}`);
|
|
318
|
-
process.exit(1);
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
cli.help();
|
|
323
|
-
cli.parse();
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# {{PROJECT_NAME}}
|
|
2
|
-
|
|
3
|
-
基于 `@funhub/platform` 初始化的 Next.js Starter。
|
|
4
|
-
|
|
5
|
-
## 开始使用
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm install
|
|
9
|
-
pnpm dev
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## 可用命令
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pnpm dev
|
|
16
|
-
pnpm build
|
|
17
|
-
pnpm start
|
|
18
|
-
pnpm lint
|
|
19
|
-
pnpm typecheck
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## 目录说明
|
|
23
|
-
|
|
24
|
-
- `app/`: Next App Router 路由
|
|
25
|
-
- `i18n/`: next-intl 请求配置
|
|
26
|
-
- `proxy.ts`: 国际化路由中间件
|
|
27
|
-
|
|
28
|
-
## 依赖说明
|
|
29
|
-
|
|
30
|
-
- `@funhub/platform`: SDK 主包
|
|
31
|
-
- `@funhub/platform/config/tailwind`: Tailwind 预设与内容扫描配置
|
|
32
|
-
- `@funhub/platform/theme.css`: 平台主题变量
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import { FunhubProvider, LocaleSync } from '@funhub/platform/components/common';
|
|
3
|
-
import { defaultLocale, getMessages, isValidLocale, locales } from '@funhub/platform/i18n';
|
|
4
|
-
import { setRequestLocale } from 'next-intl/server';
|
|
5
|
-
|
|
6
|
-
interface LocaleLayoutProps {
|
|
7
|
-
children: ReactNode
|
|
8
|
-
params: Promise<{ locale: string }>
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 预生成支持的语言参数。
|
|
13
|
-
*/
|
|
14
|
-
export function generateStaticParams() {
|
|
15
|
-
return locales.map(item => ({ locale: item.code }));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 语言布局负责注入平台 Provider 与国际化上下文。
|
|
20
|
-
*/
|
|
21
|
-
export default async function LocaleLayout({ children, params }: LocaleLayoutProps) {
|
|
22
|
-
const { locale } = await params;
|
|
23
|
-
const validLocale = isValidLocale(locale) ? locale : defaultLocale;
|
|
24
|
-
|
|
25
|
-
setRequestLocale(validLocale);
|
|
26
|
-
const messages = getMessages(validLocale);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<>
|
|
30
|
-
<LocaleSync locale={validLocale} />
|
|
31
|
-
<FunhubProvider intl={{ locale: validLocale, messages }}>
|
|
32
|
-
{children}
|
|
33
|
-
</FunhubProvider>
|
|
34
|
-
</>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Button } from '@funhub/platform/components/biz';
|
|
2
|
-
import { DebugLocaleSwitcher } from '@funhub/platform/components/common';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Starter 首页,展示平台组件已接入成功。
|
|
6
|
-
*/
|
|
7
|
-
export default function HomePage() {
|
|
8
|
-
return (
|
|
9
|
-
<main className='min-h-screen bg-bg1 px-6 py-10 text-text1'>
|
|
10
|
-
<section className='mx-auto flex max-w-xl flex-col gap-4 rounded-3xl bg-bg2 p-6 shadow-sm'>
|
|
11
|
-
<span className='text-sm text-text3'>@funhub/platform starter</span>
|
|
12
|
-
<h1 className='text-2xl font-semibold'>{'{{PROJECT_NAME}}'}</h1>
|
|
13
|
-
<p className='text-sm leading-6 text-text2'>
|
|
14
|
-
这个项目已经接入平台主题、Tailwind 预设、next-intl 和 FunhubProvider,
|
|
15
|
-
你可以直接开始组合页面组件、业务组件或物料渲染能力。
|
|
16
|
-
</p>
|
|
17
|
-
<div className='flex flex-wrap gap-3 pt-2'>
|
|
18
|
-
<Button text='平台按钮已就绪' variant='red' disabled={false} />
|
|
19
|
-
<DebugLocaleSwitcher />
|
|
20
|
-
</div>
|
|
21
|
-
</section>
|
|
22
|
-
</main>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
html {
|
|
6
|
-
font-size: 16px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
body {
|
|
10
|
-
font-family: var(--font-sans), Arial, Helvetica, sans-serif;
|
|
11
|
-
-webkit-text-size-adjust: 100%;
|
|
12
|
-
-moz-text-size-adjust: 100%;
|
|
13
|
-
-ms-text-size-adjust: 100%;
|
|
14
|
-
text-size-adjust: 100%;
|
|
15
|
-
background: var(--color-bg1);
|
|
16
|
-
color: var(--color-text1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
* {
|
|
20
|
-
box-sizing: border-box;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
a {
|
|
24
|
-
color: inherit;
|
|
25
|
-
text-decoration: none;
|
|
26
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { Metadata, Viewport } from 'next';
|
|
2
|
-
import { ThemeSync } from '@funhub/platform/components/common';
|
|
3
|
-
import { defaultLocale } from '@funhub/platform/i18n';
|
|
4
|
-
import '@funhub/platform/theme.css';
|
|
5
|
-
import './globals.css';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Starter 应用默认 viewport 配置。
|
|
9
|
-
*/
|
|
10
|
-
export const viewport: Viewport = {
|
|
11
|
-
width: 'device-width',
|
|
12
|
-
initialScale: 1,
|
|
13
|
-
viewportFit: 'cover',
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Starter 应用的站点元信息。
|
|
18
|
-
*/
|
|
19
|
-
export const metadata: Metadata = {
|
|
20
|
-
title: '{{PROJECT_NAME}}',
|
|
21
|
-
description: 'A starter app powered by @funhub/platform',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 根布局负责挂载主题和全局样式。
|
|
26
|
-
*/
|
|
27
|
-
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
|
28
|
-
const theme = 'dark';
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<html lang={defaultLocale} className={theme} data-prefers-color-scheme={theme}>
|
|
32
|
-
<body suppressHydrationWarning>
|
|
33
|
-
<ThemeSync defaultTheme={theme} />
|
|
34
|
-
{children}
|
|
35
|
-
</body>
|
|
36
|
-
</html>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { antfu } from '@antfu/eslint-config';
|
|
2
|
-
|
|
3
|
-
export function react(options = {}) {
|
|
4
|
-
return antfu({
|
|
5
|
-
react: true,
|
|
6
|
-
ignores: [
|
|
7
|
-
'**/*.md',
|
|
8
|
-
'.next/**',
|
|
9
|
-
'out/**',
|
|
10
|
-
'build/**',
|
|
11
|
-
'public',
|
|
12
|
-
'next-env.d.ts',
|
|
13
|
-
...(options.ignores || []),
|
|
14
|
-
],
|
|
15
|
-
rules: {
|
|
16
|
-
'react-hooks/exhaustive-deps': 'error',
|
|
17
|
-
'eslint-comments/no-unlimited-disable': 'off',
|
|
18
|
-
'no-redeclare': 'off',
|
|
19
|
-
'jsdoc/require-returns-description': 'off',
|
|
20
|
-
'@typescript-eslint/no-redeclare': 'off',
|
|
21
|
-
'style/quotes': ['warn', 'single'],
|
|
22
|
-
'style/jsx-quotes': ['warn', 'prefer-single'],
|
|
23
|
-
'node/prefer-global/process': 'off',
|
|
24
|
-
'style/semi': ['warn', 'always'],
|
|
25
|
-
'package-json/valid-package-def': 'off',
|
|
26
|
-
'@eslint-react/no-missing-key': 'warn',
|
|
27
|
-
'no-restricted-syntax': 'off',
|
|
28
|
-
'react-hooks-extra/no-direct-set-state-in-use-effect': 'off',
|
|
29
|
-
'import/no-anonymous-default-export': 'off',
|
|
30
|
-
'eqeqeq': 'warn',
|
|
31
|
-
'ts/no-use-before-define': ['warn', { functions: false, variables: false }],
|
|
32
|
-
'no-use-before-define': ['warn', { functions: false, variables: false }],
|
|
33
|
-
'no-console': 'warn',
|
|
34
|
-
'unicorn/prefer-math-trunc': 'off',
|
|
35
|
-
'unicorn/prefer-dom-node-remove': 'off',
|
|
36
|
-
'@typescript-eslint/no-unsafe-function-type': 'off',
|
|
37
|
-
'no-empty': 'off',
|
|
38
|
-
'@typescript-eslint/no-empty-object-type': 'warn',
|
|
39
|
-
'unicorn/prefer-query-selector': 0,
|
|
40
|
-
'regexp/no-super-linear-backtracking': 0,
|
|
41
|
-
'regexp/no-useless-assertions': 0,
|
|
42
|
-
'unicorn/no-new-array': 0,
|
|
43
|
-
'@typescript-eslint/method-signature-style': 0,
|
|
44
|
-
'unicorn/prefer-code-point': 'warn',
|
|
45
|
-
'unicorn/no-object-as-default-parameter': 'warn',
|
|
46
|
-
'unused-imports/no-unused-vars': 'warn',
|
|
47
|
-
'@eslint-react/no-unstable-default-props': 'warn',
|
|
48
|
-
'unicorn/prefer-regexp-test': 'warn',
|
|
49
|
-
'no-unsafe-optional-chaining': 'warn',
|
|
50
|
-
'unicorn/prefer-logical-operator-over-ternary': 'warn',
|
|
51
|
-
'arrow-body-style': 0,
|
|
52
|
-
'unicorn/no-array-callback-reference': 0,
|
|
53
|
-
'prefer-regex-literals': 0,
|
|
54
|
-
'regexp/optimal-quantifier-concatenation': 'warn',
|
|
55
|
-
'unicorn/prefer-string-slice': 0,
|
|
56
|
-
'array-callback-return': 0,
|
|
57
|
-
'regexp/no-unused-capturing-group': 1,
|
|
58
|
-
'unicorn/no-anonymous-default-export': 0,
|
|
59
|
-
'unicorn/no-magic-array-flat-depth': 1,
|
|
60
|
-
'react-refresh/only-export-components': 0,
|
|
61
|
-
'react/no-array-index-key': 0,
|
|
62
|
-
'package-json/valid-name': 0,
|
|
63
|
-
...(options.rules || {}),
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export default react();
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { NextConfig } from 'next';
|
|
2
|
-
import createNextIntlPlugin from 'next-intl/plugin';
|
|
3
|
-
|
|
4
|
-
const withNextIntl = createNextIntlPlugin('./i18n/request.ts');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Starter 应用的 Next 配置。
|
|
8
|
-
*/
|
|
9
|
-
const nextConfig: NextConfig = {
|
|
10
|
-
transpilePackages: ['@funhub/platform'],
|
|
11
|
-
images: {
|
|
12
|
-
remotePatterns: [
|
|
13
|
-
{
|
|
14
|
-
protocol: 'https',
|
|
15
|
-
hostname: '*',
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export default withNextIntl(nextConfig);
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "{{PACKAGE_NAME}}",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "next dev",
|
|
7
|
-
"build": "next build",
|
|
8
|
-
"start": "next start",
|
|
9
|
-
"lint": "eslint .",
|
|
10
|
-
"fix": "eslint . --fix",
|
|
11
|
-
"typecheck": "tsc --noEmit"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@funhub/platform": "{{PLATFORM_VERSION}}",
|
|
15
|
-
"@tanstack/react-query": "^5.90.16",
|
|
16
|
-
"next": "16.1.6",
|
|
17
|
-
"next-intl": "^4.8.2",
|
|
18
|
-
"react": "19.2.0",
|
|
19
|
-
"react-dom": "19.2.0"
|
|
20
|
-
},
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"@antfu/eslint-config": "^7.4.3",
|
|
23
|
-
"@eslint-react/eslint-plugin": "^2.12.4",
|
|
24
|
-
"@types/node": "^20.19.17",
|
|
25
|
-
"@types/react": "^19.2.2",
|
|
26
|
-
"@types/react-dom": "^19.2.2",
|
|
27
|
-
"autoprefixer": "^10.4.23",
|
|
28
|
-
"eslint": "^10.0.0",
|
|
29
|
-
"eslint-plugin-react-hooks": "^7.0.1",
|
|
30
|
-
"eslint-plugin-react-refresh": "^0.5.0",
|
|
31
|
-
"postcss": "^8.5.6",
|
|
32
|
-
"postcss-nesting": "^13.0.2",
|
|
33
|
-
"postcss-px-to-viewport-8-plugin": "^1.2.5",
|
|
34
|
-
"tailwindcss": "^3.4.19",
|
|
35
|
-
"typescript": "^5.9.2"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
plugins: {
|
|
3
|
-
'postcss-nesting': {},
|
|
4
|
-
'tailwindcss': {},
|
|
5
|
-
'autoprefixer': {},
|
|
6
|
-
'postcss-px-to-viewport-8-plugin': {
|
|
7
|
-
unitToConvert: 'px',
|
|
8
|
-
viewportUnit: 'vw',
|
|
9
|
-
unitPrecision: 6,
|
|
10
|
-
fontViewportUnit: 'vw',
|
|
11
|
-
selectorBlackList: [],
|
|
12
|
-
minPixelValue: 1,
|
|
13
|
-
mediaQuery: false,
|
|
14
|
-
replace: true,
|
|
15
|
-
viewportWidth: 430,
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { NextRequest } from 'next/server';
|
|
2
|
-
import { routing } from '@funhub/platform/i18n';
|
|
3
|
-
import createMiddleware from 'next-intl/middleware';
|
|
4
|
-
|
|
5
|
-
const handleI18nRouting = createMiddleware(routing);
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 处理 Starter 应用的国际化路由。
|
|
9
|
-
* @param {NextRequest} request
|
|
10
|
-
*/
|
|
11
|
-
export default async function middleware(request: NextRequest) {
|
|
12
|
-
const response = handleI18nRouting(request);
|
|
13
|
-
return response;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const config = {
|
|
17
|
-
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)',
|
|
18
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/** @type {import('tailwindcss').Config} */
|
|
2
|
-
const {
|
|
3
|
-
platformTailwindPreset,
|
|
4
|
-
withPlatformTailwindContent,
|
|
5
|
-
} = require('@funhub/platform/config/tailwind');
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
content: withPlatformTailwindContent([
|
|
9
|
-
'./app/**/*.{js,ts,jsx,tsx}',
|
|
10
|
-
'./components/**/*.{js,ts,jsx,tsx}',
|
|
11
|
-
]),
|
|
12
|
-
presets: [platformTailwindPreset],
|
|
13
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"incremental": true,
|
|
4
|
-
"target": "ES2017",
|
|
5
|
-
"jsx": "react-jsx",
|
|
6
|
-
"lib": [
|
|
7
|
-
"dom",
|
|
8
|
-
"dom.iterable",
|
|
9
|
-
"esnext"
|
|
10
|
-
],
|
|
11
|
-
"module": "esnext",
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"paths": {
|
|
14
|
-
"@/*": [
|
|
15
|
-
"./*"
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
"resolveJsonModule": true,
|
|
19
|
-
"allowJs": true,
|
|
20
|
-
"strict": true,
|
|
21
|
-
"noEmit": true,
|
|
22
|
-
"esModuleInterop": true,
|
|
23
|
-
"forceConsistentCasingInFileNames": true,
|
|
24
|
-
"isolatedModules": true,
|
|
25
|
-
"skipLibCheck": true,
|
|
26
|
-
"plugins": [
|
|
27
|
-
{
|
|
28
|
-
"name": "next"
|
|
29
|
-
}
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
"include": [
|
|
33
|
-
"next-env.d.ts",
|
|
34
|
-
"**/*.ts",
|
|
35
|
-
"**/*.tsx",
|
|
36
|
-
".next/types/**/*.ts",
|
|
37
|
-
".next/dev/types/**/*.ts",
|
|
38
|
-
"**/*.mts"
|
|
39
|
-
],
|
|
40
|
-
"exclude": [
|
|
41
|
-
"node_modules"
|
|
42
|
-
]
|
|
43
|
-
}
|