index.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. import { View, Text } from "@tarojs/components";
  2. import Taro from "@tarojs/taro";
  3. import { useState } from "react";
  4. import WidgetCard from "@/components/widgets/widget-card/index";
  5. import WidgetContent from "@/components/widgets/widget-content/index";
  6. import WidgetMap from "@/components/widgets/widget-map/index";
  7. import WidgetTypeRow from "@/components/widgets/widget-type-row/index";
  8. import WidgetTitleRow from "@/components/widgets/widget-title-row/index";
  9. import PopupLinkCopyer from "@/components/popup-link-copyer";
  10. import type {
  11. IEntityDocument,
  12. TEntityComponent,
  13. TSocialMediaItem,
  14. } from "@/types/index";
  15. import { SocialMediaType } from "@/consts/socialMedia";
  16. import { useComponentStore } from "@/store/componentStore";
  17. import NewCompButton from "./components/new-comp-button/index";
  18. import SocialMedia from "./components/social-media";
  19. import CardTitle from "./components/card-title/index";
  20. import CardContacts from "./components/card-contacts/index";
  21. import CardTel from "./components/card-tel/index";
  22. import CardChannels from "./components/card-channels/index";
  23. import CardMedia from "./components/card-media/index";
  24. import CardMiniProgram from "./components/card-mini-program/index";
  25. import CardLink from "./components/card-link/index";
  26. import IconMail from '@/components/icon/icon-email'
  27. import IconBag from '@/components/icon/icon-bag'
  28. import IconGroup from '@/components/icon/icon-group'
  29. import IconBuilding from '@/components/icon/icon-building'
  30. import { TComponentItem } from "@/types/agent";
  31. import { editAgentWebsite } from "@/service/agent";
  32. interface Props {
  33. components: TComponentItem[];
  34. editMode?: boolean;
  35. }
  36. export default ({ components, editMode = false }: Props) => {
  37. const {
  38. saveComponent,
  39. delComponent,
  40. setCurrentComponent,
  41. setInsertIndex,
  42. swapTwoComponent,
  43. } = useComponentStore();
  44. const [show, setShow] = useState(true);
  45. const [mapVisible, setMapVisible] = useState(false);
  46. const [currentMediaItem, setCurrentMediaItem] =
  47. useState<TSocialMediaItem | null>(null);
  48. const [currentLink, setCurrentLink] = useState("");
  49. const showMediaLink = (mediaItem: TSocialMediaItem, link: string, c: TEntityComponent) => {
  50. console.log(c.type, SocialMediaType.shiping.value)
  51. // 视频号不显示复制框,直接跳转
  52. if(c?.type === SocialMediaType.shiping.value && link){
  53. Taro.openChannelsUserProfile({
  54. finderUserName: link
  55. })
  56. return
  57. }
  58. setCurrentMediaItem(mediaItem);
  59. setCurrentLink(link);
  60. setShow(true);
  61. };
  62. const handleDelete = (c: TComponentItem) => {
  63. delComponent(c);
  64. };
  65. const handleNavigate = (c: TEntityComponent, url: string) => {
  66. setInsertIndex(-1);
  67. setCurrentComponent(c);
  68. let _url = url;
  69. if (_url.indexOf("?") > -1) {
  70. _url += `&id=${c.id}`;
  71. } else {
  72. _url += `?id=${c.id}`;
  73. }
  74. Taro.navigateTo({ url: _url });
  75. };
  76. const saveAddress = async (value, component:TEntityComponent) => {
  77. if(!value.address.length){
  78. return
  79. }
  80. const c = {
  81. data: {
  82. address: value.address,
  83. name: value.name,
  84. latitude: value.latitude,
  85. longitude: value.longitude,
  86. },
  87. enabled: component?.enabled ?? true,
  88. id: component?.id,
  89. name: component?.name ?? "地址",
  90. characterProfileId: component?.characterProfileId,
  91. type: "address",
  92. };
  93. await saveComponent(c)
  94. };
  95. const handleChooseAddress = async (value, c:TEntityComponent) => {
  96. // setInsertIndex(-1);
  97. // setCurrentComponent(c);
  98. // setMapVisible(true)
  99. // const option = {
  100. // address: value.address,
  101. // latitude: value.latitude,
  102. // longitude: value.longitude,
  103. // success(result:Taro.chooseLocation.SuccessCallbackResult) {
  104. // console.log(result)
  105. // value = {
  106. // address: result.address,
  107. // name: result.name,
  108. // latitude: result.latitude,
  109. // longitude: result.longitude
  110. // }
  111. // saveAddress(value, c)
  112. // }
  113. // }
  114. // Taro.chooseLocation(option)
  115. };
  116. const handleSort = async (c: TComponentItem, direction: number) => {
  117. console.log(c, direction)
  118. const res = await swapTwoComponent(c, direction);
  119. };
  120. const handleSwitchChanged = (c: TEntityComponent, checked: boolean) => {
  121. // saveComponent({
  122. // ...c,
  123. // enabled: checked,
  124. // });
  125. };
  126. const changeStyle = (c: TEntityComponent) => {
  127. // saveComponent({
  128. // ...c,
  129. // });
  130. };
  131. const handleCreateNew = (index: number) => {
  132. setInsertIndex(index);
  133. setCurrentComponent(null);
  134. Taro.navigateTo({
  135. url: "/pages/component-library/index",
  136. });
  137. };
  138. // 添加组件
  139. const renderNewCompButton = (index: number) => {
  140. return (
  141. <View onClick={() => handleCreateNew(index)}>
  142. <NewCompButton index={index}></NewCompButton>
  143. </View>
  144. );
  145. };
  146. // 渲染组件列表
  147. const renderComponents = () => {
  148. if (!components) {
  149. return <></>;
  150. }
  151. let componentsWithJSX = components
  152. .map((c: TComponentItem, index: number) => {
  153. if (!c.data) {
  154. return undefined;
  155. }
  156. // 视频号
  157. if(c.type === 'channels'){
  158. return {
  159. component: c,
  160. renderer: (
  161. <CardChannels
  162. index={index}
  163. onSwitchChanged={handleSwitchChanged}
  164. components={components}
  165. component={c}
  166. editMode={editMode}
  167. onDelete={handleDelete}
  168. onMove={handleSort}
  169. onClick={handleNavigate}
  170. ></CardChannels>
  171. ),
  172. };
  173. }
  174. // 小程序链接
  175. if(c.type === 'miniProgram'){
  176. return {
  177. component: c,
  178. renderer: (
  179. <CardMiniProgram
  180. index={index}
  181. onSwitchChanged={handleSwitchChanged}
  182. components={components}
  183. component={c}
  184. editMode={editMode}
  185. onDelete={handleDelete}
  186. onMove={handleSort}
  187. onClick={handleNavigate}
  188. />
  189. ),
  190. };
  191. }
  192. // 联系人
  193. if(c.type === "bluebook"){
  194. return {
  195. component: c,
  196. renderer: (
  197. <CardContacts
  198. index={index}
  199. key={c.id}
  200. component={c}
  201. components={components}
  202. onSwitchChanged={handleSwitchChanged}
  203. editMode={editMode}
  204. onDelete={handleDelete}
  205. onMove={handleSort}
  206. onStyleChanged={changeStyle}
  207. onClick={() =>
  208. editMode &&
  209. handleNavigate(
  210. c,
  211. `/pages/editor-pages/editor-link-contact/index`
  212. )
  213. }
  214. ></CardContacts>
  215. ),
  216. };
  217. }
  218. // 社交媒体组件
  219. if (c?.type && SocialMediaType[c?.type]) {
  220. console.log(SocialMediaType[c?.type]);
  221. const { value } = SocialMediaType[c.type];
  222. return {
  223. component: c,
  224. renderer: (
  225. <SocialMedia
  226. index={index}
  227. mediaItem={SocialMediaType[c.type]}
  228. onSwitchChanged={handleSwitchChanged}
  229. component={c}
  230. components={components}
  231. editMode={editMode}
  232. onDelete={handleDelete}
  233. onClick={() =>
  234. editMode &&
  235. handleNavigate(
  236. c,
  237. `/pages/editor-pages/editor-link-social/index?mediaType=${value}`
  238. )
  239. }
  240. onMove={handleSort}
  241. showMediaLink={(mediaItem, link)=> showMediaLink(mediaItem, link, c)}
  242. onStyleChanged={changeStyle}
  243. ></SocialMedia>
  244. ),
  245. };
  246. }
  247. if (c.data && c.type === "title") {
  248. return {
  249. component: c,
  250. renderer: (
  251. <CardTitle
  252. onSwitchChanged={handleSwitchChanged}
  253. index={index}
  254. component={c}
  255. components={components}
  256. editMode={editMode}
  257. onDelete={handleDelete}
  258. onMove={handleSort}
  259. onStyleChanged={changeStyle}
  260. >
  261. </CardTitle>
  262. ),
  263. };
  264. }
  265. if (c.type === "text") {
  266. return {
  267. component: c,
  268. renderer: (
  269. <>
  270. <WidgetCard
  271. index={index}
  272. enabled={c.enabled}
  273. onSwitchChanged={(checked) => handleSwitchChanged(c, checked)}
  274. components={components}
  275. editMode={editMode}
  276. onDelete={() => handleDelete(c)}
  277. onMove={(direction) => handleSort(c, direction)}
  278. onChanged={()=> {
  279. if(c.data?.layout === 'center'){
  280. changeStyle({...c, data: {...c.data, layout: 'left'}})
  281. }else{
  282. changeStyle({...c, data: {...c.data, layout: 'center'}})
  283. }
  284. }}
  285. >
  286. <WidgetContent
  287. editMode={editMode}
  288. onClick={() =>
  289. editMode &&
  290. handleNavigate(
  291. c,
  292. `/pages/editor-pages/editor-textarea/index`
  293. )
  294. }
  295. center={c.data.layout === "center"}
  296. data={c}
  297. >
  298. {c.data.text}
  299. </WidgetContent>
  300. </WidgetCard>
  301. </>
  302. ),
  303. };
  304. }
  305. if (c.type === 'link') {
  306. return {
  307. component: c,
  308. renderer: (
  309. <CardLink
  310. index={index}
  311. onSwitchChanged={handleSwitchChanged}
  312. components={components}
  313. component={c}
  314. editMode={editMode}
  315. onDelete={handleDelete}
  316. onMove={handleSort}
  317. onStyleChanged={changeStyle}
  318. onClick={(c, link, mediaItem) =>{
  319. if(editMode){
  320. handleNavigate(
  321. c,
  322. `/pages/editor-pages/editor-link/index`,
  323. )
  324. }else{
  325. showMediaLink(mediaItem, link, c)
  326. }
  327. }}
  328. ></CardLink>
  329. ),
  330. };
  331. }
  332. if (c.type === "email") {
  333. return {
  334. component: c,
  335. renderer: (
  336. <>
  337. <WidgetCard
  338. index={index}
  339. enabled={c.enabled}
  340. onSwitchChanged={(checked) => handleSwitchChanged(c, checked)}
  341. components={components}
  342. editMode={editMode}
  343. onDelete={() => handleDelete(c)}
  344. onMove={(direction) => handleSort(c, direction)}
  345. onChanged={()=> {
  346. if(c.data?.layout === 'center'){
  347. changeStyle({...c, data: {...c.data, layout: 'left'}})
  348. }else{
  349. changeStyle({...c, data: {...c.data, layout: 'center'}})
  350. }
  351. }}
  352. >
  353. <WidgetTypeRow
  354. editMode={editMode}
  355. onClick={() =>
  356. editMode &&
  357. handleNavigate(
  358. c,
  359. "/pages/editor-pages/editor-email/index"
  360. )
  361. }
  362. type={IconMail()}
  363. layout={c.data.layout}
  364. >
  365. {c.data.text}
  366. </WidgetTypeRow>
  367. </WidgetCard>
  368. </>
  369. ),
  370. };
  371. }
  372. if (c.type === "tel") {
  373. return {
  374. component: c,
  375. renderer: (
  376. <CardTel
  377. index={index}
  378. onSwitchChanged={handleSwitchChanged}
  379. component={c}
  380. components={components}
  381. editMode={editMode}
  382. onDelete={handleDelete}
  383. onClick={() =>
  384. editMode &&
  385. handleNavigate(
  386. c,
  387. `/pages/editor-pages/editor-tel/index`
  388. )
  389. }
  390. onMove={handleSort}
  391. onStyleChanged={changeStyle}
  392. ></CardTel>
  393. ),
  394. };
  395. }
  396. if (c.type === "media") {
  397. return {
  398. component: c,
  399. renderer: (
  400. <>
  401. <CardMedia
  402. index={index}
  403. component={c}
  404. onSwitchChanged={handleSwitchChanged}
  405. components={components}
  406. editMode={editMode}
  407. onDelete={() => handleDelete(c)}
  408. onClick={() =>
  409. editMode &&
  410. handleNavigate(c, "/pages/editor-pages/editor-media/index")
  411. }
  412. onMove={handleSort}
  413. onStyleChanged={changeStyle}
  414. >
  415. </CardMedia>
  416. </>
  417. ),
  418. };
  419. }
  420. if (c.type === "address") {
  421. return {
  422. component: c,
  423. renderer: (
  424. <>
  425. <WidgetCard
  426. index={index}
  427. enabled={c.enabled}
  428. disableChangeStyle
  429. onSwitchChanged={(checked) => handleSwitchChanged(c, checked)}
  430. components={components}
  431. editMode={editMode}
  432. onDelete={() => handleDelete(c)}
  433. onClick={() =>
  434. editMode && handleChooseAddress(c.data, c)
  435. }
  436. onMove={(direction) => handleSort(c, direction)}
  437. >
  438. <WidgetMap
  439. latitude={c.data.latitude}
  440. longitude={c.data.longitude}
  441. name={c.data.name}
  442. address={c.data.address}
  443. >
  444. {c.data.name}
  445. </WidgetMap>
  446. </WidgetCard>
  447. </>
  448. ),
  449. };
  450. }
  451. })
  452. .filter((item) => !!item);
  453. // 如果是编辑模式则显示 “添加组件” 按钮
  454. if (editMode) {
  455. const _components: JSX.Element[] = [renderNewCompButton(-1)];
  456. for (let i = 0; i < componentsWithJSX.length; i++) {
  457. _components.push(componentsWithJSX[i].renderer);
  458. const index = componentsWithJSX[i].component.data.index ?? 0;
  459. _components.push(renderNewCompButton(index));
  460. }
  461. return _components;
  462. }
  463. return componentsWithJSX.map((item) => item.renderer);
  464. };
  465. return (
  466. <>
  467. {currentMediaItem && (
  468. <PopupLinkCopyer
  469. mediaItem={currentMediaItem}
  470. show={show}
  471. setShow={setShow}
  472. link={currentLink}
  473. />
  474. )}
  475. {renderComponents()}
  476. </>
  477. );
  478. };