|
@@ -1,276 +0,0 @@
|
|
|
-import ChatAI from "@/components/chat-ai/index";
|
|
|
-import ComponentList from "@/components/component-list";
|
|
|
-import NavBarNormal from "@/components/nav-bar-normal/index";
|
|
|
-import PageCustom from "@/components/page-custom/index";
|
|
|
-import IconEditOutline from "@/images/icon-edit-outline.png";
|
|
|
-import { useAppStore } from "@/store/appStore";
|
|
|
-import { useCharacterStore, useCurrentCharacter, useCharacterStyle } from "@/store/characterStore";
|
|
|
-import { useComponentStore } from "@/store/componentStore";
|
|
|
-import { uploadImage } from "@/utils/http";
|
|
|
-
|
|
|
-import CustomShareComponent from "@/components/custom-share/CustomShareComponent";
|
|
|
-import { Button, Image, Input, View, Video } from "@tarojs/components";
|
|
|
-import Taro, { useDidShow, useRouter, useUnload } from "@tarojs/taro";
|
|
|
-import { useRef, useState } from "react";
|
|
|
-import style from "./index.module.less";
|
|
|
-import BgStyleConfig from "./components/bg-style-config/index";
|
|
|
-import AvatarMagicStyle from "./components/avatar-magic-style/index";
|
|
|
-
|
|
|
-import BottomNavBar from "./components/bottom-nav-bar";
|
|
|
-import TabButtons from "./components/tab-buttons";
|
|
|
-import { EUploadFileScene } from "@/consts/enum";
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// !!! 临时存储当前头像上传组件上传的 url 用于判断是否要显示默认头像
|
|
|
-let uploadedAvatarUrl = "";
|
|
|
-export default function Index() {
|
|
|
- const router = useRouter();
|
|
|
- const { profileId, createTimeCloseEnough } = router.params;
|
|
|
- const statusBarHeight = useAppStore((state) => state.statusBarHeight);
|
|
|
- const headerHeight = useAppStore((state) => state.headerHeight);
|
|
|
- const maxAvatarVideoSize = useAppStore((state) => state.appConfig?.maxAvatarVideoSize); // unit MB
|
|
|
- const { saveCharacter, fetchCharacterList, getCharacterById } =
|
|
|
- useCharacterStore();
|
|
|
- const character = useCurrentCharacter();
|
|
|
- console.log("page: profileId: ", profileId);
|
|
|
- const { fetchComponentList } = useComponentStore();
|
|
|
- const components = useComponentStore((state) => state.components);
|
|
|
- const inputRef = useRef(null);
|
|
|
- const {customStyled, customBgImg } = useCharacterStyle();
|
|
|
- const [avatarUrl, setAvatarUrl] = useState(character?.avatar);
|
|
|
- const [showBgStyle, setShowBgStyle] = useState(false);
|
|
|
- const [showMagicStyle, setShowMagicStyle] = useState(false);
|
|
|
-
|
|
|
- const bgImageStyle = customBgImg
|
|
|
- ? {
|
|
|
- background: `url(${customBgImg})`,
|
|
|
- // 背景图片需要顶部距离+53 tabButton 高度
|
|
|
- backgroundPosition: `0 ${statusBarHeight+53}px`
|
|
|
- }
|
|
|
- : undefined;
|
|
|
- const processChooseResult = async (response: {
|
|
|
- code: number;
|
|
|
- data: string;
|
|
|
- msg: string;
|
|
|
-} | null)=> {
|
|
|
- if (response?.code === 0 && response.data && profileId) {
|
|
|
- await saveCharacter({
|
|
|
- avatar: response.data,
|
|
|
- profileId: profileId,
|
|
|
- });
|
|
|
- fetchCharacterList();
|
|
|
- }
|
|
|
- Taro.hideLoading()
|
|
|
- }
|
|
|
- const onChooseAvatar = async () => {
|
|
|
- Taro.chooseMedia({
|
|
|
- count: 1,
|
|
|
- mediaType: ["image", "video"],
|
|
|
- sourceType: ["album", "camera"],
|
|
|
- async success(r) {
|
|
|
- const tempFile = r.tempFiles[0]
|
|
|
- const tmpPath = tempFile.tempFilePath;
|
|
|
- if (maxAvatarVideoSize && tempFile.size > maxAvatarVideoSize * 1024 * 1024) {
|
|
|
- Taro.showToast({
|
|
|
- title: `文件不能超过${maxAvatarVideoSize}MB`,
|
|
|
- icon: 'none'
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- uploadedAvatarUrl = tmpPath;
|
|
|
- setAvatarUrl(tmpPath);
|
|
|
- if(r.type === 'image'){
|
|
|
- Taro.cropImage({
|
|
|
- src: tmpPath,
|
|
|
- cropScale: "1:1",
|
|
|
- success: async (res) => {
|
|
|
- const path = res.tempFilePath;
|
|
|
- Taro.showLoading()
|
|
|
- const response = await uploadImage(path);
|
|
|
- processChooseResult(response)
|
|
|
- },
|
|
|
- });
|
|
|
- }else if(r.type === 'video'){
|
|
|
- Taro.showLoading()
|
|
|
- const response = await uploadImage(tmpPath, EUploadFileScene.AVATAR);
|
|
|
- processChooseResult(response)
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const handleInputFocus = () => {
|
|
|
- if (inputRef.current) {
|
|
|
- //@ts-ignore
|
|
|
- inputRef.current?.focus();
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const handleNicknameChange = async (e: any) => {
|
|
|
- const nickname = e.detail.value.trim();
|
|
|
- if (nickname && profileId) {
|
|
|
- await saveCharacter({
|
|
|
- name: nickname,
|
|
|
- profileId: profileId,
|
|
|
- });
|
|
|
- fetchCharacterList();
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const handleNav2SetChat = () => {
|
|
|
- if (profileId) {
|
|
|
- Taro.navigateTo({
|
|
|
- url: `/pages/editor-pages/editor-chat/index?profileId=${profileId}`,
|
|
|
- });
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const handleNavBack = async () => {
|
|
|
- await fetchCharacterList();
|
|
|
- return true;
|
|
|
- };
|
|
|
-
|
|
|
- const toggleMagicStylePanel = ()=> {
|
|
|
- console.log('hello')
|
|
|
- setShowMagicStyle(!showMagicStyle)
|
|
|
- }
|
|
|
-
|
|
|
- useDidShow(() => {
|
|
|
- if (profileId) {
|
|
|
- // 重新获取当前角色信息
|
|
|
- getCharacterById(profileId);
|
|
|
- fetchComponentList(profileId);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- useUnload(() => {
|
|
|
- const pages = Taro.getCurrentPages();
|
|
|
- // 退出页面时清空
|
|
|
- if (pages.length <= 2) {
|
|
|
- uploadedAvatarUrl = "";
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- const renderAvatar = () => {
|
|
|
- // !!! avatarUrl 有可能是默认的头像,但第一次创建时业务上要求不显示默认头像
|
|
|
- // todo: 使用 AvatarMedia 代替
|
|
|
- const isUseUploadedUrl = !createTimeCloseEnough || uploadedAvatarUrl.length;
|
|
|
- if (avatarUrl && isUseUploadedUrl) {
|
|
|
- if(avatarUrl.lastIndexOf('.mp4') > -1){
|
|
|
- return (
|
|
|
- <>
|
|
|
- <View className={style.iconCamera}></View>
|
|
|
- <Video
|
|
|
- controls={false}
|
|
|
- showCenterPlayBtn={false}
|
|
|
- loop={true}
|
|
|
- muted={true}
|
|
|
- objectFit="cover"
|
|
|
- className={`${style.avatar}`}
|
|
|
- src={avatarUrl}
|
|
|
- />
|
|
|
- </>
|
|
|
- );
|
|
|
- }
|
|
|
- return (
|
|
|
- <>
|
|
|
- <View className={style.iconCamera}></View>
|
|
|
- <Image
|
|
|
- mode='aspectFill'
|
|
|
- className={style.avatar}
|
|
|
- src={avatarUrl}
|
|
|
- ></Image>
|
|
|
- </>
|
|
|
- );
|
|
|
- }
|
|
|
- return <View className={style.iconCamera}></View>;
|
|
|
- };
|
|
|
- const avatarEditor = () => {
|
|
|
- return (
|
|
|
- <Button
|
|
|
- className={style.openDataAvatarChooseButton}
|
|
|
- onClick={onChooseAvatar}
|
|
|
- >
|
|
|
- {renderAvatar()}
|
|
|
- </Button>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- const nicknameEditor = () => {
|
|
|
- return (
|
|
|
- <>
|
|
|
- <View className={style.nickname}>
|
|
|
- <Input
|
|
|
- ref={inputRef}
|
|
|
- type='nickname'
|
|
|
- defaultValue={character?.name}
|
|
|
- placeholder='您的主页名称'
|
|
|
- className={style.nickname}
|
|
|
- onConfirm={(e) => {
|
|
|
- handleNicknameChange(e);
|
|
|
- }}
|
|
|
- onBlur={(e) => {
|
|
|
- handleNicknameChange(e);
|
|
|
- }}
|
|
|
- ></Input>
|
|
|
- <Image
|
|
|
- onClick={() => handleInputFocus()}
|
|
|
- src={IconEditOutline}
|
|
|
- className='w-24 h-24 absolute -right-20 top-0'
|
|
|
- style={{}}
|
|
|
- ></Image>
|
|
|
- </View>
|
|
|
- </>
|
|
|
- );
|
|
|
- };
|
|
|
-
|
|
|
- const renderAI = () => {
|
|
|
- if (character) {
|
|
|
- return (
|
|
|
- <ChatAI
|
|
|
- avatarRenderer={avatarEditor}
|
|
|
- nicknameRenderer={nicknameEditor}
|
|
|
- character={character}
|
|
|
- playGreeting={false}
|
|
|
- getSession={true}
|
|
|
- ></ChatAI>
|
|
|
- );
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- return (
|
|
|
- <PageCustom style={bgImageStyle} paddingTop={statusBarHeight}>
|
|
|
- <NavBarNormal scrollFadeIn={false} showBgColor onNavBack={handleNavBack}>编辑</NavBarNormal>
|
|
|
- <View style={customStyled} className="w-full">
|
|
|
-
|
|
|
- <TabButtons onNav2SetChat={handleNav2SetChat} customBgImg={customBgImg} statusBarHeight={headerHeight} />
|
|
|
-
|
|
|
-
|
|
|
- <View
|
|
|
- className={`flex flex-col items-center w-full mt-48 ${customBgImg ? '':'global-gray-bg'} ${style.contentWrap}`}
|
|
|
- >
|
|
|
- <CustomShareComponent character={character} />
|
|
|
- <View className="relative">
|
|
|
- {renderAI()}
|
|
|
- <View className="absolute right-40 top-120 z-10 w-40 h-40" onClick={toggleMagicStylePanel}>
|
|
|
-
|
|
|
- {/* {showMagicStyle ? 'yoyo':'go'} */}
|
|
|
- </View>
|
|
|
- </View>
|
|
|
-
|
|
|
- <View className='w-full pt-48 px-16 overflow-x-hidden'>
|
|
|
- <View className='flex flex-col gap-10'>
|
|
|
- <ComponentList editMode components={components}></ComponentList>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- </View>
|
|
|
- <BottomNavBar onShowBgStyle={() => setShowBgStyle(true)} profileId={profileId} />
|
|
|
- </View>
|
|
|
- <BgStyleConfig setShow={setShowBgStyle} show={showBgStyle} ></BgStyleConfig>
|
|
|
- <AvatarMagicStyle setShow={setShowMagicStyle} show={showMagicStyle} ></AvatarMagicStyle>
|
|
|
- </PageCustom>
|
|
|
- );
|
|
|
-}
|