Browse Source

fix: 角色详情暂存

pull/9/head^2
WIN-UGQIHHLSKBB\EDY 2 months ago
parent
commit
b1436f649a
  1. 16
      dist/assets/index-BsAG4qOC.js
  2. 1
      dist/assets/index-BsAG4qOC.js.map
  3. 4
      dist/assets/index-BtKOhFDr.js
  4. 2
      dist/assets/index-BtKOhFDr.js.map
  5. 3
      dist/assets/index-CMelOH19.js
  6. 1
      dist/assets/index-CMelOH19.js.map
  7. 4
      dist/assets/index-CRljK-5g.js
  8. 2
      dist/assets/index-CRljK-5g.js.map
  9. 4
      dist/assets/index-CWlhV1_Y.js
  10. 2
      dist/assets/index-CWlhV1_Y.js.map
  11. 4
      dist/assets/index-CabOpxrn.js
  12. 2
      dist/assets/index-CabOpxrn.js.map
  13. 2
      dist/assets/index-CbzZwvE5.css
  14. 4
      dist/assets/index-Cj5Yr2cE.js
  15. 2
      dist/assets/index-Cj5Yr2cE.js.map
  16. 3
      dist/assets/index-CxNpK-Jv.js
  17. 1
      dist/assets/index-CxNpK-Jv.js.map
  18. 4
      dist/assets/index-D-2eIkAO.js
  19. 2
      dist/assets/index-D-2eIkAO.js.map
  20. 2
      dist/assets/index-D3L8Pvto.css
  21. 4
      dist/assets/index-D7dQqKr0.js
  22. 2
      dist/assets/index-D7dQqKr0.js.map
  23. 4
      dist/assets/index-Doy3itgP.js
  24. 2
      dist/assets/index-Doy3itgP.js.map
  25. 4
      dist/assets/index-aifF7E64.js
  26. 2
      dist/assets/index-aifF7E64.js.map
  27. 4
      dist/assets/index-cq_7SkNd.js
  28. 2
      dist/assets/index-cq_7SkNd.js.map
  29. 16
      dist/assets/index-o9oOhmS5.js
  30. 1
      dist/assets/index-o9oOhmS5.js.map
  31. 4
      dist/assets/index-so1PvyyN.js
  32. 2
      dist/assets/index-so1PvyyN.js.map
  33. 4
      dist/index.html
  34. 1007
      src/dialog/character-detail/index.scss
  35. 513
      src/dialog/character-detail/index.tsx

16
dist/assets/index-BsAG4qOC.js

File diff suppressed because one or more lines are too long

1
dist/assets/index-BsAG4qOC.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-C9OY5P5s.js → dist/assets/index-BtKOhFDr.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-C9OY5P5s.js.map → dist/assets/index-BtKOhFDr.js.map

File diff suppressed because one or more lines are too long

3
dist/assets/index-CMelOH19.js

File diff suppressed because one or more lines are too long

1
dist/assets/index-CMelOH19.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-BjOIsaJY.js → dist/assets/index-CRljK-5g.js

@ -1,2 +1,2 @@
import{j as t}from"./markdown-vendor-BZI_VWzW.js";import{b9 as d}from"./index-BsAG4qOC.js";import{r as a}from"./data-vendor-BOGugMqL.js";import{f as m,g}from"./react-vendor-wlKWdfEb.js";import"./arco-vendor-CAnKnMnO.js";function _(){const[i,s]=a.useState(void 0),[o,r]=a.useState(void 0),{id:n}=m(),[c]=g(),e=n??c.get("id")??void 0;return a.useEffect(()=>{e&&(s(void 0),d({id:e}).then(l=>{s(l.data?.content),r(l.data?.title)}))},[e]),t.jsx("div",{className:"legal-page",children:t.jsxs("section",{className:"legal-page__section",id:e,"aria-labelledby":"legal-doc-title",children:[t.jsx("h1",{className:"legal-page__title",id:"legal-doc-title",children:o}),t.jsx("div",{className:"legal-page__content",children:t.jsx("div",{dangerouslySetInnerHTML:{__html:i??""}})})]})})}export{_ as default};
//# sourceMappingURL=index-BjOIsaJY.js.map
import{j as t}from"./markdown-vendor-BZI_VWzW.js";import{b9 as d}from"./index-o9oOhmS5.js";import{r as a}from"./data-vendor-BOGugMqL.js";import{f as m,g}from"./react-vendor-wlKWdfEb.js";import"./arco-vendor-CAnKnMnO.js";function _(){const[i,s]=a.useState(void 0),[o,r]=a.useState(void 0),{id:n}=m(),[c]=g(),e=n??c.get("id")??void 0;return a.useEffect(()=>{e&&(s(void 0),d({id:e}).then(l=>{s(l.data?.content),r(l.data?.title)}))},[e]),t.jsx("div",{className:"legal-page",children:t.jsxs("section",{className:"legal-page__section",id:e,"aria-labelledby":"legal-doc-title",children:[t.jsx("h1",{className:"legal-page__title",id:"legal-doc-title",children:o}),t.jsx("div",{className:"legal-page__content",children:t.jsx("div",{dangerouslySetInnerHTML:{__html:i??""}})})]})})}export{_ as default};
//# sourceMappingURL=index-CRljK-5g.js.map

2
dist/assets/index-BjOIsaJY.js.map → dist/assets/index-CRljK-5g.js.map

@ -1 +1 @@
{"version":3,"file":"index-BjOIsaJY.js","sources":["../../src/pages/content/page/index.tsx"],"sourcesContent":["import { getContent } from \"@/api/api\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { useParams, useSearchParams } from \"react-router-dom\";\r\nimport \"./index.scss\";\r\n\r\nexport default function Content() {\r\n\r\n const [html, setHtml] = useState<string | undefined>(undefined);\r\n const [title, setTitle] = useState<string | undefined>(undefined);\r\n const { id: idFromPath } = useParams();\r\n const [searchParams] = useSearchParams();\r\n const id = idFromPath ?? searchParams.get(\"id\") ?? undefined;\r\n\r\n useEffect(() => {\r\n if (!id) return;\r\n setHtml(undefined);\r\n getContent({ id }).then((res) => {\r\n setHtml(res.data?.content);\r\n setTitle(res.data?.title);\r\n });\r\n }, [id]);\r\n\r\n return (\r\n <div className=\"legal-page\">\r\n <section\r\n className=\"legal-page__section\"\r\n id={id}\r\n aria-labelledby=\"legal-doc-title\"\r\n >\r\n <h1 className=\"legal-page__title\" id=\"legal-doc-title\">\r\n {title}\r\n </h1>\r\n <div className=\"legal-page__content\">\r\n <div dangerouslySetInnerHTML={{ __html: html ?? \"\" }} />\r\n </div>\r\n </section>\r\n </div>\r\n );\r\n}\r\n"],"names":["Content","html","setHtml","useState","title","setTitle","idFromPath","useParams","searchParams","useSearchParams","id","useEffect","getContent","res","jsx","jsxs"],"mappings":"4NAKA,SAAwBA,GAAU,CAE9B,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAA6B,MAAS,EACxD,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAA6B,MAAS,EAC1D,CAAE,GAAIG,CAAA,EAAeC,EAAA,EACrB,CAACC,CAAY,EAAIC,EAAA,EACjBC,EAAKJ,GAAcE,EAAa,IAAI,IAAI,GAAK,OAEnDG,OAAAA,EAAAA,UAAU,IAAM,CACPD,IACLR,EAAQ,MAAS,EACjBU,EAAW,CAAE,GAAAF,CAAA,CAAI,EAAE,KAAMG,GAAQ,CAC7BX,EAAQW,EAAI,MAAM,OAAO,EACzBR,EAASQ,EAAI,MAAM,KAAK,CAC5B,CAAC,EACL,EAAG,CAACH,CAAE,CAAC,EAGHI,EAAAA,IAAC,MAAA,CAAI,UAAU,aACX,SAAAC,EAAAA,KAAC,UAAA,CACG,UAAU,sBACV,GAAAL,EACA,kBAAgB,kBAEhB,SAAA,CAAAI,MAAC,KAAA,CAAG,UAAU,oBAAoB,GAAG,kBAChC,SAAAV,EACL,EACAU,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACX,SAAAA,EAAAA,IAAC,MAAA,CAAI,wBAAyB,CAAE,OAAQb,GAAQ,EAAA,CAAG,CAAG,CAAA,CAC1D,CAAA,CAAA,CAAA,EAER,CAER"}
{"version":3,"file":"index-CRljK-5g.js","sources":["../../src/pages/content/page/index.tsx"],"sourcesContent":["import { getContent } from \"@/api/api\";\r\nimport { useEffect, useState } from \"react\";\r\nimport { useParams, useSearchParams } from \"react-router-dom\";\r\nimport \"./index.scss\";\r\n\r\nexport default function Content() {\r\n\r\n const [html, setHtml] = useState<string | undefined>(undefined);\r\n const [title, setTitle] = useState<string | undefined>(undefined);\r\n const { id: idFromPath } = useParams();\r\n const [searchParams] = useSearchParams();\r\n const id = idFromPath ?? searchParams.get(\"id\") ?? undefined;\r\n\r\n useEffect(() => {\r\n if (!id) return;\r\n setHtml(undefined);\r\n getContent({ id }).then((res) => {\r\n setHtml(res.data?.content);\r\n setTitle(res.data?.title);\r\n });\r\n }, [id]);\r\n\r\n return (\r\n <div className=\"legal-page\">\r\n <section\r\n className=\"legal-page__section\"\r\n id={id}\r\n aria-labelledby=\"legal-doc-title\"\r\n >\r\n <h1 className=\"legal-page__title\" id=\"legal-doc-title\">\r\n {title}\r\n </h1>\r\n <div className=\"legal-page__content\">\r\n <div dangerouslySetInnerHTML={{ __html: html ?? \"\" }} />\r\n </div>\r\n </section>\r\n </div>\r\n );\r\n}\r\n"],"names":["Content","html","setHtml","useState","title","setTitle","idFromPath","useParams","searchParams","useSearchParams","id","useEffect","getContent","res","jsx","jsxs"],"mappings":"4NAKA,SAAwBA,GAAU,CAE9B,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAA6B,MAAS,EACxD,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAA6B,MAAS,EAC1D,CAAE,GAAIG,CAAA,EAAeC,EAAA,EACrB,CAACC,CAAY,EAAIC,EAAA,EACjBC,EAAKJ,GAAcE,EAAa,IAAI,IAAI,GAAK,OAEnDG,OAAAA,EAAAA,UAAU,IAAM,CACPD,IACLR,EAAQ,MAAS,EACjBU,EAAW,CAAE,GAAAF,CAAA,CAAI,EAAE,KAAMG,GAAQ,CAC7BX,EAAQW,EAAI,MAAM,OAAO,EACzBR,EAASQ,EAAI,MAAM,KAAK,CAC5B,CAAC,EACL,EAAG,CAACH,CAAE,CAAC,EAGHI,EAAAA,IAAC,MAAA,CAAI,UAAU,aACX,SAAAC,EAAAA,KAAC,UAAA,CACG,UAAU,sBACV,GAAAL,EACA,kBAAgB,kBAEhB,SAAA,CAAAI,MAAC,KAAA,CAAG,UAAU,oBAAoB,GAAG,kBAChC,SAAAV,EACL,EACAU,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACX,SAAAA,EAAAA,IAAC,MAAA,CAAI,wBAAyB,CAAE,OAAQb,GAAQ,EAAA,CAAG,CAAG,CAAA,CAC1D,CAAA,CAAA,CAAA,EAER,CAER"}

4
dist/assets/index-Cb2xuryx.js → dist/assets/index-CWlhV1_Y.js

@ -1,2 +1,2 @@
import{j as e}from"./markdown-vendor-BZI_VWzW.js";import{b7 as m,b8 as d}from"./index-BsAG4qOC.js";import{u as g,r as o}from"./data-vendor-BOGugMqL.js";import{b as _}from"./react-vendor-wlKWdfEb.js";import"./arco-vendor-CAnKnMnO.js";const h="#user-agreement",c="#privacy-policy";function j(){const{t:l}=g(),{hash:i}=_(),t=i===c,r=l(t?"app.privacy_policy":"app.user_terms"),n=t?c.replace("#",""):h.replace("#",""),[p,a]=o.useState(void 0);return o.useEffect(()=>{a(void 0),t?m().then(s=>a(s.data?.content)):d().then(s=>a(s.data?.content))},[t]),e.jsx("div",{className:"legal-page",children:e.jsxs("section",{className:"legal-page__section",id:n,"aria-labelledby":"legal-doc-title",children:[e.jsx("h1",{className:"legal-page__title",id:"legal-doc-title",children:r}),e.jsx("div",{className:"legal-page__content",children:e.jsx("div",{dangerouslySetInnerHTML:{__html:p??""}})})]})})}export{j as default};
//# sourceMappingURL=index-Cb2xuryx.js.map
import{j as e}from"./markdown-vendor-BZI_VWzW.js";import{b7 as m,b8 as d}from"./index-o9oOhmS5.js";import{u as g,r as o}from"./data-vendor-BOGugMqL.js";import{b as _}from"./react-vendor-wlKWdfEb.js";import"./arco-vendor-CAnKnMnO.js";const h="#user-agreement",c="#privacy-policy";function j(){const{t:l}=g(),{hash:i}=_(),t=i===c,r=l(t?"app.privacy_policy":"app.user_terms"),n=t?c.replace("#",""):h.replace("#",""),[p,a]=o.useState(void 0);return o.useEffect(()=>{a(void 0),t?m().then(s=>a(s.data?.content)):d().then(s=>a(s.data?.content))},[t]),e.jsx("div",{className:"legal-page",children:e.jsxs("section",{className:"legal-page__section",id:n,"aria-labelledby":"legal-doc-title",children:[e.jsx("h1",{className:"legal-page__title",id:"legal-doc-title",children:r}),e.jsx("div",{className:"legal-page__content",children:e.jsx("div",{dangerouslySetInnerHTML:{__html:p??""}})})]})})}export{j as default};
//# sourceMappingURL=index-CWlhV1_Y.js.map

2
dist/assets/index-Cb2xuryx.js.map → dist/assets/index-CWlhV1_Y.js.map

@ -1 +1 @@
{"version":3,"file":"index-Cb2xuryx.js","sources":["../../src/pages/legal/index.tsx"],"sourcesContent":["import { getPrivacyPolicy, getUserTerms } from \"@/api/api\";\nimport { useEffect, useState } from \"react\";\nimport { useLocation } from \"react-router-dom\";\nimport { useTranslation } from \"react-i18next\";\nimport \"./index.scss\";\n\nconst USER_AGREEMENT_HASH = \"#user-agreement\";\nconst PRIVACY_POLICY_HASH = \"#privacy-policy\";\n\nexport default function Legal() {\n const { t } = useTranslation();\n const { hash } = useLocation();\n const showPrivacy = hash === PRIVACY_POLICY_HASH;\n const title = showPrivacy ? t(\"app.privacy_policy\") : t(\"app.user_terms\");\n const sectionId = showPrivacy\n ? PRIVACY_POLICY_HASH.replace(\"#\", \"\")\n : USER_AGREEMENT_HASH.replace(\"#\", \"\");\n\n const [html, setHtml] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n setHtml(undefined);\n if (showPrivacy) {\n getPrivacyPolicy().then((res) => setHtml(res.data?.content));\n } else {\n getUserTerms().then((res) => setHtml(res.data?.content));\n }\n }, [showPrivacy]);\n\n return (\n <div className=\"legal-page\">\n <section\n className=\"legal-page__section\"\n id={sectionId}\n aria-labelledby=\"legal-doc-title\"\n >\n <h1 className=\"legal-page__title\" id=\"legal-doc-title\">\n {title}\n </h1>\n <div className=\"legal-page__content\">\n <div dangerouslySetInnerHTML={{ __html: html ?? \"\" }} />\n </div>\n </section>\n </div>\n );\n}\n"],"names":["USER_AGREEMENT_HASH","PRIVACY_POLICY_HASH","Legal","t","useTranslation","hash","useLocation","showPrivacy","title","sectionId","html","setHtml","useState","useEffect","getPrivacyPolicy","res","getUserTerms","jsx","jsxs"],"mappings":"yOAMA,MAAMA,EAAsB,kBACtBC,EAAsB,kBAE5B,SAAwBC,GAAQ,CAC9B,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACR,CAAE,KAAAC,CAAA,EAASC,EAAA,EACXC,EAAcF,IAASJ,EACvBO,EAAsBL,EAAdI,EAAgB,qBAA0B,gBAAN,EAC5CE,EAAYF,EACdN,EAAoB,QAAQ,IAAK,EAAE,EACnCD,EAAoB,QAAQ,IAAK,EAAE,EAEjC,CAACU,EAAMC,CAAO,EAAIC,EAAAA,SAA6B,MAAS,EAE9DC,OAAAA,EAAAA,UAAU,IAAM,CACdF,EAAQ,MAAS,EACbJ,EACFO,EAAA,EAAmB,KAAMC,GAAQJ,EAAQI,EAAI,MAAM,OAAO,CAAC,EAE3DC,EAAA,EAAe,KAAMD,GAAQJ,EAAQI,EAAI,MAAM,OAAO,CAAC,CAE3D,EAAG,CAACR,CAAW,CAAC,EAGdU,EAAAA,IAAC,MAAA,CAAI,UAAU,aACb,SAAAC,EAAAA,KAAC,UAAA,CACC,UAAU,sBACV,GAAIT,EACJ,kBAAgB,kBAEhB,SAAA,CAAAQ,MAAC,KAAA,CAAG,UAAU,oBAAoB,GAAG,kBAClC,SAAAT,EACH,EACAS,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,wBAAyB,CAAE,OAAQP,GAAQ,EAAA,CAAG,CAAG,CAAA,CACxD,CAAA,CAAA,CAAA,EAEJ,CAEJ"}
{"version":3,"file":"index-CWlhV1_Y.js","sources":["../../src/pages/legal/index.tsx"],"sourcesContent":["import { getPrivacyPolicy, getUserTerms } from \"@/api/api\";\nimport { useEffect, useState } from \"react\";\nimport { useLocation } from \"react-router-dom\";\nimport { useTranslation } from \"react-i18next\";\nimport \"./index.scss\";\n\nconst USER_AGREEMENT_HASH = \"#user-agreement\";\nconst PRIVACY_POLICY_HASH = \"#privacy-policy\";\n\nexport default function Legal() {\n const { t } = useTranslation();\n const { hash } = useLocation();\n const showPrivacy = hash === PRIVACY_POLICY_HASH;\n const title = showPrivacy ? t(\"app.privacy_policy\") : t(\"app.user_terms\");\n const sectionId = showPrivacy\n ? PRIVACY_POLICY_HASH.replace(\"#\", \"\")\n : USER_AGREEMENT_HASH.replace(\"#\", \"\");\n\n const [html, setHtml] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n setHtml(undefined);\n if (showPrivacy) {\n getPrivacyPolicy().then((res) => setHtml(res.data?.content));\n } else {\n getUserTerms().then((res) => setHtml(res.data?.content));\n }\n }, [showPrivacy]);\n\n return (\n <div className=\"legal-page\">\n <section\n className=\"legal-page__section\"\n id={sectionId}\n aria-labelledby=\"legal-doc-title\"\n >\n <h1 className=\"legal-page__title\" id=\"legal-doc-title\">\n {title}\n </h1>\n <div className=\"legal-page__content\">\n <div dangerouslySetInnerHTML={{ __html: html ?? \"\" }} />\n </div>\n </section>\n </div>\n );\n}\n"],"names":["USER_AGREEMENT_HASH","PRIVACY_POLICY_HASH","Legal","t","useTranslation","hash","useLocation","showPrivacy","title","sectionId","html","setHtml","useState","useEffect","getPrivacyPolicy","res","getUserTerms","jsx","jsxs"],"mappings":"yOAMA,MAAMA,EAAsB,kBACtBC,EAAsB,kBAE5B,SAAwBC,GAAQ,CAC9B,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACR,CAAE,KAAAC,CAAA,EAASC,EAAA,EACXC,EAAcF,IAASJ,EACvBO,EAAsBL,EAAdI,EAAgB,qBAA0B,gBAAN,EAC5CE,EAAYF,EACdN,EAAoB,QAAQ,IAAK,EAAE,EACnCD,EAAoB,QAAQ,IAAK,EAAE,EAEjC,CAACU,EAAMC,CAAO,EAAIC,EAAAA,SAA6B,MAAS,EAE9DC,OAAAA,EAAAA,UAAU,IAAM,CACdF,EAAQ,MAAS,EACbJ,EACFO,EAAA,EAAmB,KAAMC,GAAQJ,EAAQI,EAAI,MAAM,OAAO,CAAC,EAE3DC,EAAA,EAAe,KAAMD,GAAQJ,EAAQI,EAAI,MAAM,OAAO,CAAC,CAE3D,EAAG,CAACR,CAAW,CAAC,EAGdU,EAAAA,IAAC,MAAA,CAAI,UAAU,aACb,SAAAC,EAAAA,KAAC,UAAA,CACC,UAAU,sBACV,GAAIT,EACJ,kBAAgB,kBAEhB,SAAA,CAAAQ,MAAC,KAAA,CAAG,UAAU,oBAAoB,GAAG,kBAClC,SAAAT,EACH,EACAS,EAAAA,IAAC,MAAA,CAAI,UAAU,sBACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,wBAAyB,CAAE,OAAQP,GAAQ,EAAA,CAAG,CAAG,CAAA,CACxD,CAAA,CAAA,CAAA,EAEJ,CAEJ"}

4
dist/assets/index-BtHCI_tu.js → dist/assets/index-CabOpxrn.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-BtHCI_tu.js.map → dist/assets/index-CabOpxrn.js.map

File diff suppressed because one or more lines are too long

2
dist/assets/index-dkWdjmXf.css → dist/assets/index-CbzZwvE5.css

File diff suppressed because one or more lines are too long

4
dist/assets/index-BYyxXmKq.js → dist/assets/index-Cj5Yr2cE.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-BYyxXmKq.js.map → dist/assets/index-Cj5Yr2cE.js.map

File diff suppressed because one or more lines are too long

3
dist/assets/index-CxNpK-Jv.js

File diff suppressed because one or more lines are too long

1
dist/assets/index-CxNpK-Jv.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-DEddGiNX.js → dist/assets/index-D-2eIkAO.js

@ -1,2 +1,2 @@
import{j as t}from"./markdown-vendor-BZI_VWzW.js";import{L as o}from"./react-vendor-wlKWdfEb.js";import{R as s}from"./index-BsAG4qOC.js";import{u as r}from"./data-vendor-BOGugMqL.js";import"./arco-vendor-CAnKnMnO.js";function c(){const{t:e}=r();return t.jsxs("div",{className:"flex min-h-[60vh] flex-col items-center justify-center text-gray-600",children:[t.jsx("p",{className:"text-6xl font-bold text-gray-300",children:"404"}),t.jsx("p",{className:"mt-2",children:e("notFound.title")}),t.jsx(o,{to:s.EXPLORE,className:"mt-4 text-blue-600 hover:underline",children:e("notFound.backHome")})]})}export{c as default};
//# sourceMappingURL=index-DEddGiNX.js.map
import{j as t}from"./markdown-vendor-BZI_VWzW.js";import{L as o}from"./react-vendor-wlKWdfEb.js";import{R as s}from"./index-o9oOhmS5.js";import{u as r}from"./data-vendor-BOGugMqL.js";import"./arco-vendor-CAnKnMnO.js";function c(){const{t:e}=r();return t.jsxs("div",{className:"flex min-h-[60vh] flex-col items-center justify-center text-gray-600",children:[t.jsx("p",{className:"text-6xl font-bold text-gray-300",children:"404"}),t.jsx("p",{className:"mt-2",children:e("notFound.title")}),t.jsx(o,{to:s.EXPLORE,className:"mt-4 text-blue-600 hover:underline",children:e("notFound.backHome")})]})}export{c as default};
//# sourceMappingURL=index-D-2eIkAO.js.map

2
dist/assets/index-DEddGiNX.js.map → dist/assets/index-D-2eIkAO.js.map

@ -1 +1 @@
{"version":3,"file":"index-DEddGiNX.js","sources":["../../src/pages/NotFound/index.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { useTranslation } from \"react-i18next\";\nimport { ROUTES } from \"@/constants\";\n\nexport default function NotFound() {\n const { t } = useTranslation();\n return (\n <div className=\"flex min-h-[60vh] flex-col items-center justify-center text-gray-600\">\n <p className=\"text-6xl font-bold text-gray-300\">404</p>\n <p className=\"mt-2\">{t(\"notFound.title\")}</p>\n <Link to={ROUTES.EXPLORE} className=\"mt-4 text-blue-600 hover:underline\">\n {t(\"notFound.backHome\")}\n </Link>\n </div>\n );\n}\n"],"names":["NotFound","t","useTranslation","jsxs","jsx","Link","ROUTES"],"mappings":"yNAIA,SAAwBA,GAAW,CACjC,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACd,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,uEACb,SAAA,CAAAC,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,MAAG,QAClD,IAAA,CAAE,UAAU,OAAQ,SAAAH,EAAE,gBAAgB,EAAE,EACzCG,EAAAA,IAACC,GAAK,GAAIC,EAAO,QAAS,UAAU,qCACjC,SAAAL,EAAE,mBAAmB,CAAA,CACxB,CAAA,EACF,CAEJ"}
{"version":3,"file":"index-D-2eIkAO.js","sources":["../../src/pages/NotFound/index.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { useTranslation } from \"react-i18next\";\nimport { ROUTES } from \"@/constants\";\n\nexport default function NotFound() {\n const { t } = useTranslation();\n return (\n <div className=\"flex min-h-[60vh] flex-col items-center justify-center text-gray-600\">\n <p className=\"text-6xl font-bold text-gray-300\">404</p>\n <p className=\"mt-2\">{t(\"notFound.title\")}</p>\n <Link to={ROUTES.EXPLORE} className=\"mt-4 text-blue-600 hover:underline\">\n {t(\"notFound.backHome\")}\n </Link>\n </div>\n );\n}\n"],"names":["NotFound","t","useTranslation","jsxs","jsx","Link","ROUTES"],"mappings":"yNAIA,SAAwBA,GAAW,CACjC,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EACd,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,uEACb,SAAA,CAAAC,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,MAAG,QAClD,IAAA,CAAE,UAAU,OAAQ,SAAAH,EAAE,gBAAgB,EAAE,EACzCG,EAAAA,IAACC,GAAK,GAAIC,EAAO,QAAS,UAAU,qCACjC,SAAAL,EAAE,mBAAmB,CAAA,CACxB,CAAA,EACF,CAEJ"}

2
dist/assets/index-DjgdMGkk.css → dist/assets/index-D3L8Pvto.css

File diff suppressed because one or more lines are too long

4
dist/assets/index-nPw91zMs.js → dist/assets/index-D7dQqKr0.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-nPw91zMs.js.map → dist/assets/index-D7dQqKr0.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-Dpbc9haf.js → dist/assets/index-Doy3itgP.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-Dpbc9haf.js.map → dist/assets/index-Doy3itgP.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-B2pCqNwa.js → dist/assets/index-aifF7E64.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-B2pCqNwa.js.map → dist/assets/index-aifF7E64.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-D39sZ_W_.js → dist/assets/index-cq_7SkNd.js

@ -1,2 +1,2 @@
import{j as s}from"./markdown-vendor-BZI_VWzW.js";import{u as G,r as t}from"./data-vendor-BOGugMqL.js";import{g as U}from"./react-vendor-wlKWdfEb.js";import{bl as V,bm as H,o as Y,f as Z}from"./index-BsAG4qOC.js";import"./arco-vendor-CAnKnMnO.js";const _=20,T=[{title:"image",assetType:"1"},{title:"video",assetType:"2"},{title:"template",assetType:"4"},{title:"character",assetType:"5"}];function A(o){const r=o;return r?.data?.list??r?.list??[]}function B(o){const r=o?.id??o?.assetId;return r==null||r===""?null:String(r)}function ee({tabIdPrefix:o}){const{t:r}=G(),[x,S]=U(),[l,b]=t.useState("1"),[c,f]=t.useState([]),[N,j]=t.useState(1),[g,u]=t.useState(!0),[d,F]=t.useState(!1),[v,C]=t.useState(!1),[h,I]=t.useState(null),L=t.useRef(null),P=t.useRef(!1),i=t.useRef(0),k=t.useRef(async()=>{});t.useEffect(()=>{const e=x.get("type");e!=null&&T.some(a=>a.assetType===e)&&b(e)},[x]);const w=t.useCallback(e=>({assetType:l,page:e,pageSize:_}),[l]),p=t.useCallback(e=>l==="5"?V({page:e,pageSize:_}):H(w(e)),[w,l]);t.useEffect(()=>{let e=!1;i.current+=1;const a=i.current;return j(1),u(!0),f([]),F(!0),I(null),p(1).then(n=>{if(e||i.current!==a)return;const m=A(n);f(m),u(m.length>=_)}).catch(n=>{e||i.current!==a||(I(n instanceof Error?n:new Error(String(n))),f([]),u(!1))}).finally(()=>{!e&&i.current===a&&F(!1)}),()=>{e=!0}},[p,l]);const D=t.useCallback(async()=>{if(!g||P.current||d||v)return;P.current=!0,C(!0);const e=i.current,a=N+1;try{const n=await p(a);if(i.current!==e)return;const m=A(n);m.length===0?u(!1):(f(q=>[...q,...m]),j(a),u(m.length>=_))}catch{i.current===e&&u(!1)}finally{P.current=!1,C(!1)}},[p,g,d,v,N]);k.current=D,t.useEffect(()=>{const e=L.current;if(!e||!g||d)return;const a=new IntersectionObserver(n=>{n[0]?.isIntersecting&&k.current()},{root:null,rootMargin:"200px",threshold:0});return a.observe(e),()=>a.disconnect()},[g,d,c.length]);const z=t.useCallback(e=>{b(e),S(a=>{const n=new URLSearchParams(a);return n.set("type",String(e)),n},{replace:!0})},[S]),y=t.useCallback(async e=>{const a=e.assetId;a!=null&&await Y({assetId:a})},[]),E=t.useCallback(async e=>{Z({id:e.id})},[]),R=t.useCallback(e=>{e.currentTarget.querySelector("video")?.play()},[]),M=t.useCallback(e=>{e.currentTarget.querySelector("video")?.pause()},[]),O=t.useMemo(()=>T.map(({title:e,assetType:a})=>({assetType:a,label:r(`pages.create.filters.${e}`)})),[r]),$=t.useMemo(()=>c.map(e=>{const a=B(e)??`row-${l}`;return l=="2"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void y(e),onMouseEnter:R,onMouseLeave:M,children:s.jsx("video",{className:"myFavoritePanel__media",src:e.asset.video,muted:!0,playsInline:!0,loop:!0,preload:"metadata",poster:e.asset.cover,"aria-hidden":!0})},a):l=="1"||l=="4"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void y(e),children:s.jsx("img",{className:"myFavoritePanel__media",src:e?.asset?.images?.[0],alt:"",loading:"lazy"})},a):l=="5"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void E(e),children:s.jsx("img",{className:"myFavoritePanel__media",src:e.avatar,alt:"",loading:"lazy"})},a):s.jsx("li",{className:"myFavoritePanel__item myFavoritePanel__item_empty",children:s.jsx("span",{className:"myFavoritePanel__emptyLabel",children:r("pages.create.panels.favorite.noPreview")})},a)}),[y,E,c,R,M,l,r]);return s.jsxs("div",{className:"myFavoritePanel",children:[s.jsx("div",{className:"createPage__subRow myFavoritePanel__subRow",children:s.jsx("div",{className:"createPage__filters",role:"group","aria-label":r("pages.create.filtersAria"),"data-active-tab":l,children:O.map(({assetType:e,label:a})=>s.jsx("button",{type:"button","data-type":e,"data-selected":l===e,"aria-pressed":l===e,className:classNames("createPage__filterPill",l===e&&"createPage__filterPill_active"),onClick:()=>z(e),children:a},e))})}),s.jsxs("section",{className:"createPage__panel createPage__panel_below_filters",id:`${o}-panel-favorite`,role:"tabpanel","aria-labelledby":`${o}-tab-favorite`,children:[d&&c.length===0?s.jsx("p",{className:"createPage__panelStatus",children:r("common.loading")}):null,h?s.jsx("p",{className:"createPage__panelStatus createPage__panelStatus_error",children:h.message}):null,!d&&!h&&c.length===0?s.jsx("p",{className:"createPage__panelPlaceholder",children:r("pages.create.panels.favorite.placeholder")}):null,c.length>0?s.jsxs(s.Fragment,{children:[s.jsx("ul",{className:"myFavoritePanel__list",role:"list",children:$}),g?s.jsx("div",{ref:L,className:"myFavoritePanel__sentinel","aria-hidden":!0}):null,v?s.jsx("p",{className:"createPage__panelStatus myFavoritePanel__loadMore",children:r("common.loading")}):null]}):null]})]})}export{ee as default};
//# sourceMappingURL=index-D39sZ_W_.js.map
import{j as s}from"./markdown-vendor-BZI_VWzW.js";import{u as G,r as t}from"./data-vendor-BOGugMqL.js";import{g as U}from"./react-vendor-wlKWdfEb.js";import{bl as V,bm as H,o as Y,f as Z}from"./index-o9oOhmS5.js";import"./arco-vendor-CAnKnMnO.js";const _=20,T=[{title:"image",assetType:"1"},{title:"video",assetType:"2"},{title:"template",assetType:"4"},{title:"character",assetType:"5"}];function A(o){const r=o;return r?.data?.list??r?.list??[]}function B(o){const r=o?.id??o?.assetId;return r==null||r===""?null:String(r)}function ee({tabIdPrefix:o}){const{t:r}=G(),[x,S]=U(),[l,b]=t.useState("1"),[c,f]=t.useState([]),[N,j]=t.useState(1),[g,u]=t.useState(!0),[d,F]=t.useState(!1),[v,C]=t.useState(!1),[h,I]=t.useState(null),L=t.useRef(null),P=t.useRef(!1),i=t.useRef(0),k=t.useRef(async()=>{});t.useEffect(()=>{const e=x.get("type");e!=null&&T.some(a=>a.assetType===e)&&b(e)},[x]);const w=t.useCallback(e=>({assetType:l,page:e,pageSize:_}),[l]),p=t.useCallback(e=>l==="5"?V({page:e,pageSize:_}):H(w(e)),[w,l]);t.useEffect(()=>{let e=!1;i.current+=1;const a=i.current;return j(1),u(!0),f([]),F(!0),I(null),p(1).then(n=>{if(e||i.current!==a)return;const m=A(n);f(m),u(m.length>=_)}).catch(n=>{e||i.current!==a||(I(n instanceof Error?n:new Error(String(n))),f([]),u(!1))}).finally(()=>{!e&&i.current===a&&F(!1)}),()=>{e=!0}},[p,l]);const D=t.useCallback(async()=>{if(!g||P.current||d||v)return;P.current=!0,C(!0);const e=i.current,a=N+1;try{const n=await p(a);if(i.current!==e)return;const m=A(n);m.length===0?u(!1):(f(q=>[...q,...m]),j(a),u(m.length>=_))}catch{i.current===e&&u(!1)}finally{P.current=!1,C(!1)}},[p,g,d,v,N]);k.current=D,t.useEffect(()=>{const e=L.current;if(!e||!g||d)return;const a=new IntersectionObserver(n=>{n[0]?.isIntersecting&&k.current()},{root:null,rootMargin:"200px",threshold:0});return a.observe(e),()=>a.disconnect()},[g,d,c.length]);const z=t.useCallback(e=>{b(e),S(a=>{const n=new URLSearchParams(a);return n.set("type",String(e)),n},{replace:!0})},[S]),y=t.useCallback(async e=>{const a=e.assetId;a!=null&&await Y({assetId:a})},[]),E=t.useCallback(async e=>{Z({id:e.id})},[]),R=t.useCallback(e=>{e.currentTarget.querySelector("video")?.play()},[]),M=t.useCallback(e=>{e.currentTarget.querySelector("video")?.pause()},[]),O=t.useMemo(()=>T.map(({title:e,assetType:a})=>({assetType:a,label:r(`pages.create.filters.${e}`)})),[r]),$=t.useMemo(()=>c.map(e=>{const a=B(e)??`row-${l}`;return l=="2"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void y(e),onMouseEnter:R,onMouseLeave:M,children:s.jsx("video",{className:"myFavoritePanel__media",src:e.asset.video,muted:!0,playsInline:!0,loop:!0,preload:"metadata",poster:e.asset.cover,"aria-hidden":!0})},a):l=="1"||l=="4"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void y(e),children:s.jsx("img",{className:"myFavoritePanel__media",src:e?.asset?.images?.[0],alt:"",loading:"lazy"})},a):l=="5"?s.jsx("li",{className:"myFavoritePanel__item",onClick:()=>void E(e),children:s.jsx("img",{className:"myFavoritePanel__media",src:e.avatar,alt:"",loading:"lazy"})},a):s.jsx("li",{className:"myFavoritePanel__item myFavoritePanel__item_empty",children:s.jsx("span",{className:"myFavoritePanel__emptyLabel",children:r("pages.create.panels.favorite.noPreview")})},a)}),[y,E,c,R,M,l,r]);return s.jsxs("div",{className:"myFavoritePanel",children:[s.jsx("div",{className:"createPage__subRow myFavoritePanel__subRow",children:s.jsx("div",{className:"createPage__filters",role:"group","aria-label":r("pages.create.filtersAria"),"data-active-tab":l,children:O.map(({assetType:e,label:a})=>s.jsx("button",{type:"button","data-type":e,"data-selected":l===e,"aria-pressed":l===e,className:classNames("createPage__filterPill",l===e&&"createPage__filterPill_active"),onClick:()=>z(e),children:a},e))})}),s.jsxs("section",{className:"createPage__panel createPage__panel_below_filters",id:`${o}-panel-favorite`,role:"tabpanel","aria-labelledby":`${o}-tab-favorite`,children:[d&&c.length===0?s.jsx("p",{className:"createPage__panelStatus",children:r("common.loading")}):null,h?s.jsx("p",{className:"createPage__panelStatus createPage__panelStatus_error",children:h.message}):null,!d&&!h&&c.length===0?s.jsx("p",{className:"createPage__panelPlaceholder",children:r("pages.create.panels.favorite.placeholder")}):null,c.length>0?s.jsxs(s.Fragment,{children:[s.jsx("ul",{className:"myFavoritePanel__list",role:"list",children:$}),g?s.jsx("div",{ref:L,className:"myFavoritePanel__sentinel","aria-hidden":!0}):null,v?s.jsx("p",{className:"createPage__panelStatus myFavoritePanel__loadMore",children:r("common.loading")}):null]}):null]})]})}export{ee as default};
//# sourceMappingURL=index-cq_7SkNd.js.map

2
dist/assets/index-D39sZ_W_.js.map → dist/assets/index-cq_7SkNd.js.map

File diff suppressed because one or more lines are too long

16
dist/assets/index-o9oOhmS5.js

File diff suppressed because one or more lines are too long

1
dist/assets/index-o9oOhmS5.js.map

File diff suppressed because one or more lines are too long

4
dist/assets/index-C-_04j_5.js → dist/assets/index-so1PvyyN.js

File diff suppressed because one or more lines are too long

2
dist/assets/index-C-_04j_5.js.map → dist/assets/index-so1PvyyN.js.map

File diff suppressed because one or more lines are too long

4
dist/index.html

@ -18,12 +18,12 @@
<!-- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet"> -->
<!-- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> -->
<!-- <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet"> -->
<script type="module" crossorigin src="/assets/index-BsAG4qOC.js"></script>
<script type="module" crossorigin src="/assets/index-o9oOhmS5.js"></script>
<link rel="modulepreload" crossorigin href="/assets/data-vendor-BOGugMqL.js">
<link rel="modulepreload" crossorigin href="/assets/markdown-vendor-BZI_VWzW.js">
<link rel="modulepreload" crossorigin href="/assets/react-vendor-wlKWdfEb.js">
<link rel="modulepreload" crossorigin href="/assets/arco-vendor-CAnKnMnO.js">
<link rel="stylesheet" crossorigin href="/assets/index-DjgdMGkk.css">
<link rel="stylesheet" crossorigin href="/assets/index-D3L8Pvto.css">
</head>
<body>
<div id="root"></div>

1007
src/dialog/character-detail/index.scss

File diff suppressed because it is too large

513
src/dialog/character-detail/index.tsx

@ -1,7 +1,7 @@
import { useCopyText } from "@/hooks/useCopyText";
import "./index.scss";
import { addCharacterLike, addUserFollow, delCharacterLike, deleteCharacter, deleteUserFollow, getCharacterDetail, updateCharacter } from "@/api/api";
import { useEffect, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { Dropdown, Input, Message, Modal } from "@arco-design/web-react";
import AvatarCropModal from "@/components/AvatarCropModal";
@ -51,12 +51,28 @@ export default function CharacterDetailDialog({
const [railMenuOpen, setRailMenuOpen] = useState(false);
const [isEditingCharacterName, setIsEditingCharacterName] = useState(false);
const [isEditingDescription, setIsEditingDescription] = useState(false);
const [isSavingCharacterName, setIsSavingCharacterName] = useState(false);
const [isSavingDescription, setIsSavingDescription] = useState(false);
const [characterName, setCharacterName] = useState("");
const [description, setDescription] = useState("");
const [isPublic, setIsPublic] = useState(false);
const [cropModalImage, setCropModalImage] = useState("");
const [characterDetail, setCharacterDetail] = useState<any>({});
const skipNextNameBlurRef = useRef(false);
const skipNextIntroBlurRef = useRef(false);
const requestAppendImageUrl = useGlobalPromptImageStore((s) => s.requestAppendImageUrl);
const placeCaretAtEnd = useCallback((eventTarget: EventTarget | null) => {
if (!(eventTarget instanceof HTMLInputElement) && !(eventTarget instanceof HTMLTextAreaElement)) return;
const target = eventTarget;
const valueLength = target.value.length;
requestAnimationFrame(() => {
try {
target.setSelectionRange(valueLength, valueLength);
} catch {
// Some input modes may not support selection APIs.
}
});
}, []);
// 是否是自己的角色
const isOwnCharacter = useMemo(() => {
@ -69,6 +85,11 @@ export default function CharacterDetailDialog({
const isUserUploadCharacter = useMemo(() => {
return characterDetail?.characterType === 2;
}, [characterDetail?.characterType]);
const characterNameInputWidth = useMemo(() => {
const textLength = Array.from(characterName || "").length;
const computedWidth = textLength * 14 + 28;
return Math.min(200, Math.max(69, computedWidth));
}, [characterName]);
useEffect(() => {
if (characterId == null || characterId === "") return;
@ -184,12 +205,12 @@ export default function CharacterDetailDialog({
const submitCharacterUpdate = async (overrides?: Partial<{ characterName: string; description: string; isPublic: boolean; avatar: string }>) => {
const id = characterDetail?.id ?? characterId;
if (id == null || id === "") return;
if (id == null || id === "") return false;
const payload = {
id,
characterName: overrides?.characterName ?? characterName ?? "",
description: overrides?.description ?? description ?? "",
isPublic: overrides?.isPublic ?? isPublic,
characterName: overrides?.characterName ?? characterDetail?.title ?? "",
description: overrides?.description ?? characterDetail?.description ?? "",
isPublic: overrides?.isPublic ?? Boolean(characterDetail?.isPublic),
avatar: overrides?.avatar ?? characterDetail?.avatar ?? characterDetail?.headImage ?? "",
};
try {
@ -208,8 +229,13 @@ export default function CharacterDetailDialog({
isPublic: payload.isPublic,
avatar: payload.avatar,
});
setCharacterName(payload.characterName);
setDescription(payload.description);
setIsPublic(payload.isPublic);
return true;
} catch {
Message.error(t("pages.charactersCreate.updateFailed"));
return false;
}
};
@ -223,14 +249,20 @@ export default function CharacterDetailDialog({
setIsEditingCharacterName(false);
};
const handleFinishEditName = () => {
if (!isEditingCharacterName) return;
const handleFinishEditName = async () => {
if (!isEditingCharacterName || isSavingCharacterName) return;
const trimmedName = characterName.trim();
const fallbackName = characterDetail?.title ?? "";
const nextName = trimmedName || fallbackName;
setCharacterName(nextName);
setIsEditingCharacterName(false);
void submitCharacterUpdate({ characterName: nextName });
if (nextName === fallbackName) {
setCharacterName(nextName);
setIsEditingCharacterName(false);
return;
}
setIsSavingCharacterName(true);
const ok = await submitCharacterUpdate({ characterName: nextName });
setIsSavingCharacterName(false);
if (ok) setIsEditingCharacterName(false);
};
const handleStartEditIntro = () => {
@ -243,14 +275,20 @@ export default function CharacterDetailDialog({
setIsEditingDescription(false);
};
const handleFinishEditIntro = () => {
if (!isEditingDescription) return;
const handleFinishEditIntro = async () => {
if (!isEditingDescription || isSavingDescription) return;
const trimmedIntro = description.trim();
const fallbackIntro = characterDetail?.description ?? "";
const nextIntro = trimmedIntro || fallbackIntro;
setDescription(nextIntro);
setIsEditingDescription(false);
void submitCharacterUpdate({ description: nextIntro });
if (nextIntro === fallbackIntro) {
setDescription(nextIntro);
setIsEditingDescription(false);
return;
}
setIsSavingDescription(true);
const ok = await submitCharacterUpdate({ description: nextIntro });
setIsSavingDescription(false);
if (ok) setIsEditingDescription(false);
};
const handleTogglePublic = () => {
@ -268,6 +306,9 @@ export default function CharacterDetailDialog({
setCropModalImage(sourceImage);
};
const promptQuickActions = ["5s 虚实结合 Vlog", "拿起角色手办", "剧情九宫格", "趣味表情包", "喝咖啡", "逛公园", "和爱丽丝聚餐~", "一张臭美照~"];
const mediaActions = ["生成视频", "超清", "细节修复"];
return (
<>
<div
@ -293,244 +334,246 @@ export default function CharacterDetailDialog({
alt=""
onClick={() => onClose?.()}
/>
<Dropdown
trigger="click"
position="bl"
popupVisible={railMenuOpen}
onVisibleChange={setRailMenuOpen}
droplist={
<div id="character-details-rail-menu" className="character_detail_dialog__floatMenu" role="menu" aria-label={t("character_detail.download")}>
<button type="button" className="character_detail_dialog__floatRow" role="menuitem" onClick={handleDownload}>
<img className="character_detail_dialog__floatRowIcon" src={new URL("/src/assets/images/ic_download.png", import.meta.url).href} alt="" />
{t("character_detail.download")}
</button>
{isUserUploadCharacter && isOwnCharacter ? (
<button type="button" className="character_detail_dialog__floatRow" role="menuitem" onClick={handleDeleteCharacter}>
<img className="character_detail_dialog__floatRowIcon" src={new URL("/src/assets/images/ic_delete.png", import.meta.url).href} alt="" />
{t("pages.assetDetails.delete")}
</button>
) : null}
</div>
}
>
<button
type="button"
className="character_detail_dialog__railThumbBtn"
aria-label={t("character_detail.download")}
aria-haspopup="menu"
aria-expanded={railMenuOpen}
aria-controls="character-details-rail-menu"
>
<img src={new URL("/src/assets/images/ic_more.png", import.meta.url).href} alt="" />
</button>
</Dropdown>
</div>
</div>
<aside className="character_detail_dialog__right">
<div className="character_detail_dialog__sidebarMain">
<div className="character_detail_dialog__rightColumn">
{characterDetail.userInfo && isUserUploadCharacter && (
<div className="character_detail_dialog__authorRow">
<div className="character_detail_dialog__authorInfo">
<img className="character_detail_dialog__authorAvatar" src={characterDetail.userInfo.avatar} alt="" />
<div className="character_detail_dialog__authorMeta">
<p className="character_detail_dialog__authorName">{characterDetail.userInfo.name}</p>
<p className="character_detail_dialog__authorFollowers">{characterDetail.userInfo.fansNum || 0} {t("pages.profile.stats.fans")}</p>
</div>
</div>
{!characterDetail.userInfo.userFollowed ? (
<button type="button" className="character_detail_dialog__authorFollowBtn" onClick={() => addFollow(characterDetail.userInfo.id)}>
{t("pages.profile.stats.following")}
</button>
) : (
<button
type="button"
className="character_detail_dialog__authorFollowBtn character_detail_dialog__authorFollowBtn_active"
onClick={() => delFollow(characterDetail.userInfo.userId)}
>
{t("pages.charactersCreate.followed")}
</button>
)}
</div>
)}
<div className="character_detail_dialog__avatarSection">
<div className="character_detail_dialog__avatarPreview">
<img className="character_detail_dialog__avatarPreviewImage" src={characterDetail.avatar || characterDetail.headImage || characterDetail.threeViewImage} alt="" />
</div>
</div>
{isOwnCharacter && isUserUploadCharacter && (
<div className="character_detail_dialog__avatarUpdate">
<button type="button" className="character_detail_dialog__avatarUpdateBtn" onClick={handleOpenAvatarCrop}>
<div className="character_detail_dialog__rightColumn">
<div className="character_detail_dialog__mainContent">
<div className="character_detail_dialog__authorRow">
{characterDetail.userInfo && isUserUploadCharacter ? (
<div className="character_detail_dialog__authorInfo">
<img className="character_detail_dialog__authorAvatar" src={characterDetail.userInfo.avatar} alt="" />
<p className="character_detail_dialog__authorName">{characterDetail.userInfo.name}</p>
{!characterDetail.userInfo.userFollowed ? (
<button type="button" className="character_detail_dialog__authorFollowBtn" onClick={() => addFollow(characterDetail.userInfo.id)}>
+{t("pages.profile.stats.following")}
</button>
</div>
)}
<div className="character_detail_dialog__nameRow">
<div className="character_detail_dialog__nameLabel">{t("character_detail.name_label")}</div>
<div className="character_detail_dialog__nameValue">
{!isEditingCharacterName ? (
<>
{isOwnCharacter && <img
className="character_detail_dialog__edit"
src={new URL("/src/assets/images/ic_character_edit.png", import.meta.url).href}
alt=""
onClick={handleStartEditName}
/>}
<div className="character_detail_dialog__nameValueText">@{characterDetail.title}</div>
</>
) : (
<div className="character_detail_dialog__nameEditField">
<Input
autoFocus
className="character_detail_dialog__nameInput"
value={characterName}
onChange={setCharacterName}
onBlur={handleFinishEditName}
onPressEnter={handleFinishEditName}
onKeyDown={(event) => {
if (event.key === "Escape") handleCancelEditName();
}}
/>
</div>
)}
</div>
</div>
<div className="character_detail_dialog__divider" role="presentation" />
<div className="character_detail_dialog__intro">
<p className="character_detail_dialog__introTitle">{t("character_detail.role_intro_title")}</p>
<div className="character_detail_dialog__introBody">
{!isEditingDescription ? (
<>
<p className="character_detail_dialog__introText">{characterDetail.description}</p>
{isOwnCharacter && <img
className="character_detail_dialog__edit"
src={new URL("/src/assets/images/ic_character_edit.png", import.meta.url).href}
alt=""
onClick={handleStartEditIntro}
/>}
</>
) : (
<Input.TextArea
autoFocus
className="character_detail_dialog__introInput"
value={description}
onChange={setDescription}
onBlur={handleFinishEditIntro}
autoSize={{ minRows: 3, maxRows: 8 }}
onKeyDown={(event) => {
if (event.key === "Escape") handleCancelEditIntro();
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") handleFinishEditIntro();
}}
/>
)}
</div>
</div>
{isOwnCharacter && (
<div className="character_detail_dialog__toggleRow">
<span className="character_detail_dialog__toggleLabel">{t("pages.charactersCreate.createRoleModal.publicDisplay")}</span>
) : (
<button
type="button"
className={`character_detail_dialog__toggle${isPublic ? " character_detail_dialog__toggle_on" : ""}`}
onClick={handleTogglePublic}
aria-label={t("pages.charactersCreate.createRoleModal.publicDisplaySwitchAria")}
aria-pressed={isPublic}
className="character_detail_dialog__authorFollowBtn character_detail_dialog__authorFollowBtn_active"
onClick={() => delFollow(characterDetail.userInfo.userId)}
>
<span className="character_detail_dialog__toggleKnob" />
<span className="character_detail_dialog__toggleText">{isPublic ? "ON" : "OFF"}</span>
{t("pages.charactersCreate.followed")}
</button>
</div>
)}
<div className="character_detail_dialog__divider" role="presentation" />
{characterDetail.taskInfo != null && (
<div className="character_detail_dialog__taskInfoGroup">
{/* <div className="character_detail_dialog__materialsBlock">
<span className="character_detail_dialog__taskFieldLabel">{t("pages.assetDetails.useMaterial")}</span>
<div className="character_detail_dialog__materialsList">
{characterDetail.taskInfo?.characterList?.map((c: any, index: number) => (
<div key={`${c.id}-${index}`} className="character_detail_dialog__materialItem">
<img alt="" className="character_detail_dialog__materialImage" src={c.threeViewImage} />
</div>
))}
{characterDetail.taskInfo?.images?.map((image: string, index: number) => (
<div key={`${image}-${index}`} className="character_detail_dialog__materialItem">
<img alt="" className="character_detail_dialog__materialImage" src={image} />
</div>
))}
</div>
</div> */}
<div className="character_detail_dialog__taskMetaRow">
<span className="character_detail_dialog__taskMetaLabel">{t("pages.assetDetails.model")}</span>
<span className="character_detail_dialog__taskMetaValue">{characterDetail.taskInfo?.aiModelName ?? ""}</span>
</div>
<div className="character_detail_dialog__taskMetaRow">
<span className="character_detail_dialog__taskMetaLabel">{t("pages.assetDetails.ratio")}</span>
<span className="character_detail_dialog__taskMetaValue">{characterDetail.taskInfo?.aspectRatio ?? ""}</span>
</div>
<div className="character_detail_dialog__taskMetaRow">
<span className="character_detail_dialog__taskMetaLabel">{t("pages.assetDetails.size")}</span>
<span className="character_detail_dialog__taskMetaValue">
{characterDetail.taskInfo?.width && characterDetail.taskInfo?.height
? `${characterDetail.taskInfo.width}x${characterDetail.taskInfo.height}`
: ""}
</span>
</div>
<div className="character_detail_dialog__taskMetaRow">
<span className="character_detail_dialog__taskMetaLabel">{t("pages.charactersCreate.createRoleModal.createDate")}</span>
<span className="character_detail_dialog__taskMetaValue">{formatTaskCreateDate(characterDetail.taskInfo)}</span>
)}
</div>
) : (
<div />
)}
<div className="character_detail_dialog__authorActions">
<button type="button" className="character_detail_dialog__likeRow" onClick={() => { toggleLike() }}>
<img src={new URL(`/src/assets/images/${characterDetail.userLiked ? "ic_like_active" : "ic_like"}.png`, import.meta.url).href} alt="" />
{characterDetail.likeNum || 0}
</button>
<Dropdown
trigger="click"
position="bl"
popupVisible={railMenuOpen}
onVisibleChange={setRailMenuOpen}
droplist={
<div id="character-details-rail-menu" className="character_detail_dialog__floatMenu" role="menu" aria-label={t("character_detail.download")}>
<button type="button" className="character_detail_dialog__floatRow" role="menuitem" onClick={handleDownload}>
<img className="character_detail_dialog__floatRowIcon" src={new URL("/src/assets/images/ic_download.png", import.meta.url).href} alt="" />
{t("character_detail.download")}
</button>
{isUserUploadCharacter && isOwnCharacter ? (
<button type="button" className="character_detail_dialog__floatRow" role="menuitem" onClick={handleDeleteCharacter}>
<img className="character_detail_dialog__floatRowIcon" src={new URL("/src/assets/images/ic_delete.png", import.meta.url).href} alt="" />
{t("pages.assetDetails.delete")}
</button>
) : null}
</div>
}
>
<button
type="button"
className="character_detail_dialog__moreBtn"
aria-label={t("character_detail.download")}
aria-haspopup="menu"
aria-expanded={railMenuOpen}
aria-controls="character-details-rail-menu"
>
<img src={new URL("/src/assets/images/ic_more.png", import.meta.url).href} alt="" />
</button>
</Dropdown>
</div>
</div>
<div className="character_detail_dialog__metaHintRow">
<span className="character_detail_dialog__metaHintText">{formatLocalDate(characterDetail.createTime ?? characterDetail.taskInfo?.createTime)}</span>
<span className="character_detail_dialog__metaHintDivider" />
<span className="character_detail_dialog__metaHintText">AI生成</span>
</div>
<div className="character_detail_dialog__divider" role="presentation" />
<div className="character_detail_dialog__avatarSection">
<div className="character_detail_dialog__avatarPreview">
<img className="character_detail_dialog__avatarPreviewImage" src={characterDetail.avatar || characterDetail.headImage || characterDetail.threeViewImage} alt="" />
</div>
</div>
{false && isOwnCharacter && isUserUploadCharacter && (
<div className="character_detail_dialog__avatarUpdate">
<button type="button" className="character_detail_dialog__avatarUpdateBtn" onClick={handleOpenAvatarCrop}>
</button>
</div>
)}
<div className="character_detail_dialog__nameRow">
<div className="character_detail_dialog__nameValue">
{!isEditingCharacterName ? (
<>
<div className="character_detail_dialog__nameValueText">{characterDetail.title}</div>
{isOwnCharacter && <img
className="character_detail_dialog__edit"
src={new URL("/src/assets/images/ic_character_edit.png", import.meta.url).href}
alt=""
onClick={handleStartEditName}
/>}
</>
) : (
<div className="character_detail_dialog__nameEditField">
<Input
autoFocus
className="character_detail_dialog__nameInput"
style={{ width: `${characterNameInputWidth}px` }}
value={characterName}
onChange={setCharacterName}
onFocus={(event) => placeCaretAtEnd(event.target)}
onBlur={() => {
if (skipNextNameBlurRef.current) {
skipNextNameBlurRef.current = false;
return;
}
void handleFinishEditName();
}}
onPressEnter={() => { void handleFinishEditName(); }}
onKeyDown={(event) => {
if (event.key === "Escape") {
skipNextNameBlurRef.current = true;
handleCancelEditName();
}
}}
/>
</div>
)}
</div>
</div>
<div className="character_detail_dialog__sidebarFoot">
<div className="character_detail_dialog__likeRow" onClick={() => { toggleLike() }}>
<img src={new URL(`/src/assets/images/${characterDetail.userLiked ? "ic_like_active" : "ic_like"}.png`, import.meta.url).href} alt="" />
{characterDetail.likeNum || 0}
</div>
{/* 跳去参考 */}
{/* <div
className="character_detail_dialog__cta"
onClick={() => {
const refImage = String(characterDetail?.threeViewImage ?? "").trim();
const refTitle = String(characterDetail?.title ?? "").trim();
const refId = characterDetail?.id;
if (!refImage || refId == null) return;
requestApplyCharacterToReference({
id: refId,
title: refTitle,
threeViewImage: refImage,
});
onClose?.();
<div className="character_detail_dialog__intro">
<p className="character_detail_dialog__introTitle">{t("character_detail.role_intro_title")}</p>
<div className="character_detail_dialog__introBody">
{!isEditingDescription ? (
<>
<p className="character_detail_dialog__introText">{characterDetail.description}</p>
{isOwnCharacter && <img
className="character_detail_dialog__edit"
src={new URL("/src/assets/images/ic_character_edit.png", import.meta.url).href}
alt=""
onClick={handleStartEditIntro}
/>}
</>
) : (
<Input.TextArea
autoFocus
className="character_detail_dialog__introInput"
value={description}
onChange={setDescription}
onFocus={(event) => placeCaretAtEnd(event.target)}
onBlur={() => {
if (skipNextIntroBlurRef.current) {
skipNextIntroBlurRef.current = false;
return;
}
void handleFinishEditIntro();
}}
>
{t("character_detail.use_character")}
</div> */}
<div
className="character_detail_dialog__cta"
onClick={() => {
const refImage = String(characterDetail?.threeViewImage ?? "").trim();
const refTitle = String(characterDetail?.title ?? "").trim();
if (!refImage) return;
requestAppendImageUrl(refImage, refTitle, 103);
onClose?.();
autoSize={{ minRows: 3, maxRows: 8 }}
onKeyDown={(event) => {
if (event.key === "Escape") {
skipNextIntroBlurRef.current = true;
handleCancelEditIntro();
}
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") void handleFinishEditIntro();
}}
>
{t("character_detail.use_character")}
</div>
/>
)}
</div>
</div>
{isOwnCharacter && (
<div className="character_detail_dialog__toggleRow">
<span className="character_detail_dialog__toggleLabel">{t("pages.charactersCreate.createRoleModal.publicDisplay")}</span>
<button
type="button"
className="character_detail_dialog__toggleStatus"
onClick={handleTogglePublic}
aria-label={t("pages.charactersCreate.createRoleModal.publicDisplaySwitchAria")}
aria-pressed={isPublic}
>
<span className={`character_detail_dialog__toggleStatusPart${isPublic ? " character_detail_dialog__toggleStatusPart_active" : ""}`}></span>
<span className="character_detail_dialog__toggleStatusSlash"> / </span>
<span className={`character_detail_dialog__toggleStatusPart${!isPublic ? " character_detail_dialog__toggleStatusPart_active" : ""}`}></span>
</button>
</div>
)}
{characterDetail.taskInfo != null && (
<div className="character_detail_dialog__taskInlineMeta">
<span className="character_detail_dialog__taskInlineMetaItem">{characterDetail.taskInfo?.aiModelName ?? ""}</span>
<span className="character_detail_dialog__taskInlineMetaDivider" />
<span className="character_detail_dialog__taskInlineMetaItem">
{characterDetail.taskInfo?.width && characterDetail.taskInfo?.height
? `${characterDetail.taskInfo.width}P`
: ""}
</span>
<span className="character_detail_dialog__taskInlineMetaDivider" />
<span className="character_detail_dialog__taskInlineMetaItem">{characterDetail.taskInfo?.aspectRatio ?? ""}</span>
<span className="character_detail_dialog__taskInlineMetaDivider" />
<span className="character_detail_dialog__taskInlineMetaItem"></span>
</div>
)}
</div>
<div className="character_detail_dialog__sidebarFoot">
<div className="character_detail_dialog__actionPanel character_detail_dialog__actionPanel_prompt">
{promptQuickActions.map((label) => (
<button key={label} type="button" className="character_detail_dialog__panelActionBtn">
<span className="character_detail_dialog__panelActionIcon" />
<span className="character_detail_dialog__panelActionText">{label}</span>
</button>
))}
</div>
<div className="character_detail_dialog__actionPanel character_detail_dialog__actionPanel_media">
{mediaActions.map((label) => (
<button key={label} type="button" className="character_detail_dialog__panelActionBtn">
<span className="character_detail_dialog__panelActionIcon" />
<span className="character_detail_dialog__panelActionText">{label}</span>
</button>
))}
</div>
<div className="character_detail_dialog__actionPanel character_detail_dialog__actionPanel_primary">
<div
className="character_detail_dialog__panelActionBtn character_detail_dialog__panelActionBtn_active"
onClick={() => {
const refImage = String(characterDetail?.threeViewImage ?? "").trim();
const refTitle = String(characterDetail?.title ?? "").trim();
if (!refImage) return;
requestAppendImageUrl(refImage, refTitle, 103);
onClose?.();
}}
>
<span className="character_detail_dialog__panelActionIcon" />
<span className="character_detail_dialog__panelActionText">{t("character_detail.use_character")}</span>
</div>
{/*
<button type="button" className="character_detail_dialog__primaryBtn" onClick={onUseCharacter}>
{t("character_detail.use_character")}
</button> */}
<button type="button" className="character_detail_dialog__panelActionBtn" onClick={onUseCharacter}>
<span className="character_detail_dialog__panelActionIcon" />
<span className="character_detail_dialog__panelActionText"></span>
</button>
</div>
</div>
</div>
</aside>
</div>
<AvatarCropModal

Loading…
Cancel
Save