pcEdit.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. <template>
  2. <div class="pcEdit">
  3. <div class="pcEdit-pages">
  4. <el-header class="flex items-center h-[50px] bg-primary px-[20px]">
  5. <div class="text-white cursor-pointer flex items-center" @click="goBack">
  6. <el-icon size="14">
  7. <ArrowLeft />
  8. </el-icon>
  9. <span class="pl-[5px] text-[14px]">返回</span>
  10. </div>
  11. <div class="text-white ml-[10px] mr-[20px] flex items-center">
  12. <span class="mr-[5px] text-[rgba(255,255,255,.5)]">|</span>
  13. <span class="mr-[5px] text-[14px]">正在装修:{{ query.title || '页面名字' }}</span>
  14. </div>
  15. <div class="flex-1"></div>
  16. <el-button @click="preview()">保存并预览</el-button>
  17. <el-button @click="save()">保存</el-button>
  18. </el-header>
  19. <div class="full-container flex flex-row flex-1 bg-page">
  20. <div class="component-list w-[192px]">
  21. <!-- 组件列表区域 -->
  22. <el-collapse v-model="activeNames" @change="handleChange">
  23. <el-collapse-item v-for="(item, key) in collapse" :key="key" :title="item.name" :name="key">
  24. <ul class="flex flex-row flex-wrap">
  25. <li
  26. v-for="(compItem, compKey) in item.list"
  27. :key="compKey"
  28. class="w-2/4 text-center cursor-pointer h-[65px]"
  29. :title="compItem.name"
  30. @click="diyStore.addComponent(compItem, compKey)"
  31. >
  32. <icon v-if="compItem.icon" :name="compItem.icon" size="20px" class="inline-block mt-[3px]" />
  33. <icon v-else name="iconfont iconkaifazujian" size="20px" class="inline-block mt-[3px]" />
  34. <span class="block text-[12px] truncate">{{ compItem.name }}</span>
  35. </li>
  36. </ul>
  37. </el-collapse-item>
  38. </el-collapse>
  39. </div>
  40. <div class="preview-wrap">
  41. <!-- 组件编辑区域 -->
  42. <div class="preview-pages shadow-lg">
  43. <!-- @end="onDragEnd" -->
  44. <draggable v-model="diyStore.componentList" item-key="itemKey" class="drag-area">
  45. <template #item="{ element, index }">
  46. <div @click="diyStore.onComponent(element, index)" class="component-bos">
  47. <div class="component-box" :style="{ borderWidth: diyStore.currentIndex == index ? '2px' : '0px' }"></div>
  48. <component :is="element.components" :key="element.itemKey" :index="index"></component>
  49. </div>
  50. </template>
  51. </draggable>
  52. </div>
  53. </div>
  54. <!-- 编辑组件属性区域 -->
  55. <div class="edit-attribute-wrap w-[400px]">
  56. <!-- 编辑组件属性区域 -->
  57. <el-scrollbar>
  58. <el-card class="box-card" shadow="never">
  59. <template #header>
  60. <div class="card-header flex justify-between items-center">
  61. <span class="title flex-1">{{ diyStore.currentIndex == -99 ? '页面设置' : diyStore.editComponent.name }}</span>
  62. <div class="tab-wrap flex rounded-[50px] bg-gray-100 text-[14px]">
  63. <span
  64. class="cursor-pointer rounded-[50px] py-[5px] px-[15px]"
  65. :class="{ 'bg-primary text-white': diyStore.editTab == 'content' }"
  66. @click="diyStore.editTab = 'content'"
  67. >内容</span
  68. >
  69. <span
  70. class="cursor-pointer rounded-[50px] py-[5px] px-[15px]"
  71. :class="{ 'bg-primary text-white': diyStore.editTab == 'style' }"
  72. @click="diyStore.editTab = 'style'"
  73. >样式</span
  74. >
  75. </div>
  76. </div>
  77. </template>
  78. <div class="edit-component-wrap">
  79. <component
  80. v-if="diyStore.currentKey"
  81. :is="diyStore.editComponent.edit"
  82. :key="diyStore.currentIndex"
  83. :value="diyStore.componentList[diyStore.currentIndex]"
  84. >
  85. <template #style>
  86. <div class="edit-attr-item-wrap">
  87. <h3 class="mb-[10px]">组件样式</h3>
  88. <el-form label-width="90px" class="px-[10px]">
  89. <template v-if="diyStore.editComponent.ignore.indexOf('pageBgColor') == -1">
  90. <el-form-item label="底部背景">
  91. <el-color-picker v-model="diyStore.editComponent.pageStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
  92. <icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
  93. <el-color-picker v-model="diyStore.editComponent.pageEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
  94. </el-form-item>
  95. <div class="text-sm text-gray-400 ml-[90px] mb-[10px]">底部背景包含边距和圆角</div>
  96. </template>
  97. <el-form-item label="渐变角度" v-if="diyStore.editComponent.ignore.indexOf('pageBgColor') == -1">
  98. <el-radio-group v-model="diyStore.editComponent.pageGradientAngle">
  99. <el-radio value="to bottom">从上到下</el-radio>
  100. <el-radio value="to right">从左到右</el-radio>
  101. </el-radio-group>
  102. </el-form-item>
  103. <el-form-item label="组件背景色" v-if="diyStore.editComponent.ignore.indexOf('componentBgColor') == -1">
  104. <el-color-picker v-model="diyStore.editComponent.componentStartBgColor" show-alpha :predefine="diyStore.predefineColors" />
  105. <icon name="iconfont iconmap-connect" size="20px" class="block !text-gray-400 mx-[5px]" />
  106. <el-color-picker v-model="diyStore.editComponent.componentEndBgColor" show-alpha :predefine="diyStore.predefineColors" />
  107. </el-form-item>
  108. <el-form-item label="渐变角度" v-if="diyStore.editComponent.ignore.indexOf('componentBgColor') == -1">
  109. <el-radio-group v-model="diyStore.editComponent.componentGradientAngle">
  110. <el-radio value="to bottom">从上到下</el-radio>
  111. <el-radio value="to right">从左到右</el-radio>
  112. </el-radio-group>
  113. </el-form-item>
  114. <el-form-item label="上边距" v-if="diyStore.editComponent.ignore.indexOf('marginTop') == -1">
  115. <el-slider
  116. v-model="diyStore.editComponent.padding.top"
  117. show-input
  118. size="small"
  119. :min="-100"
  120. class="ml-[10px] diy-nav-slider"
  121. />
  122. </el-form-item>
  123. <el-form-item label="下边距" v-if="diyStore.editComponent.ignore.indexOf('marginBottom') == -1">
  124. <el-slider
  125. v-model="diyStore.editComponent.padding.bottom"
  126. show-input
  127. size="small"
  128. class="ml-[10px] diy-nav-slider"
  129. :min="-100"
  130. />
  131. </el-form-item>
  132. <el-form-item label="左右边距" v-if="diyStore.editComponent.ignore.indexOf('marginBoth') == -1">
  133. <el-slider v-model="diyStore.editComponent.padding.both" show-input size="small" class="ml-[10px] diy-nav-slider" />
  134. </el-form-item>
  135. <el-form-item label="上圆角" v-if="diyStore.editComponent.ignore.indexOf('topRounded') == -1">
  136. <el-slider
  137. v-model="diyStore.editComponent.topRounded"
  138. show-input
  139. size="small"
  140. class="ml-[10px] diy-nav-slider"
  141. :max="100"
  142. />
  143. </el-form-item>
  144. <el-form-item label="下圆角" v-if="diyStore.editComponent.ignore.indexOf('bottomRounded') == -1">
  145. <el-slider
  146. v-model="diyStore.editComponent.bottomRounded"
  147. show-input
  148. size="small"
  149. class="ml-[10px] diy-nav-slider"
  150. :max="100"
  151. />
  152. </el-form-item>
  153. </el-form>
  154. </div>
  155. </template>
  156. </component>
  157. </div>
  158. </el-card>
  159. </el-scrollbar>
  160. <!-- <div v-for="(item, index) in diyStore.componentList" :key="index">
  161. <component v-if="item.itemKey == diyStore.currentKey" :is="item.edit" :value="item"> </component>
  162. </div> -->
  163. </div>
  164. </div>
  165. </div>
  166. </div>
  167. </template>
  168. <script setup name="Index" lang="ts">
  169. import { pcAddDiy } from '@/api/diy/index';
  170. import icon from '@/components/icon/index.vue';
  171. import draggable from 'vuedraggable';
  172. import usePcdiyStore from '@/store/modules/pcdiy';
  173. const diyStore = usePcdiyStore();
  174. const route = useRoute();
  175. const query = route.query;
  176. // 头部组件
  177. import head from '@/views/diy/pcPages/head.vue';
  178. const headRef = shallowRef(head);
  179. import headEdit from '@/views/diy/pcEdit/head-edit.vue';
  180. const headEditRef = shallowRef(headEdit);
  181. //文本标题
  182. import textTitle from '@/views/diy/pcPages/textTitle.vue';
  183. const ctextTitleRef = shallowRef(textTitle);
  184. import textTitleEdit from '@/views/diy/pcEdit/textTitle-edit.vue';
  185. const textTitleEditRef = shallowRef(textTitleEdit);
  186. //图文导航
  187. import navigation from '@/views/diy/pcPages/navigation.vue';
  188. const navigationRef = shallowRef(navigation);
  189. import navigationEdit from '@/views/diy/pcEdit/navigation-edit.vue';
  190. const navigationEditRef = shallowRef(navigationEdit);
  191. //图片魔方
  192. import imageCube from '@/views/diy/pcPages/imageCube.vue';
  193. const imageCubeRef = shallowRef(imageCube);
  194. import imageCubeEdit from '@/views/diy/pcEdit/imageCube-edit.vue';
  195. const imageCubeEditRef = shallowRef(imageCubeEdit);
  196. //轮播图
  197. import carousel from '@/views/diy/pcPages/carousel.vue';
  198. const carouselRef = shallowRef(carousel);
  199. import carouselEdit from '@/views/diy/pcEdit/carousel-edit.vue';
  200. const carouselEditRef = shallowRef(carouselEdit);
  201. //文章咨询
  202. import article from '@/views/diy/pcPages/article.vue';
  203. const articleRef = shallowRef(article);
  204. import articleEdit from '@/views/diy/pcEdit/article-edit.vue';
  205. const articleEditRef = shallowRef(articleEdit);
  206. //品牌组件
  207. import brand from '@/views/diy/pcPages/brand.vue';
  208. const brandeRef = shallowRef(brand);
  209. import brandEdit from '@/views/diy/pcEdit/brand-edit.vue';
  210. const brandEditRef = shallowRef(brandEdit);
  211. //图文广告
  212. import advert from '@/views/diy/pcPages/advert.vue';
  213. const advertRef = shallowRef(advert);
  214. import advertEdit from '@/views/diy/pcEdit/advert-edit.vue';
  215. const advertEditRef = shallowRef(advertEdit);
  216. //楼层组件
  217. import floor from '@/views/diy/pcPages/floor.vue';
  218. const floorRef = shallowRef(floor);
  219. import floorEdit from '@/views/diy/pcEdit/floor-edit.vue';
  220. const floorEditRef = shallowRef(floorEdit);
  221. //商品组件
  222. import goods from '@/views/diy/pcPages/goods.vue';
  223. const goodsRef = shallowRef(goods);
  224. import goodsEdit from '@/views/diy/pcEdit/goods-edit.vue';
  225. const goodsEditRef = shallowRef(goodsEdit);
  226. //多商品组
  227. import goodsList from '@/views/diy/pcPages/goodsList.vue';
  228. const goodsListRef = shallowRef(goodsList);
  229. import goodsListEdit from '@/views/diy/pcEdit/goodsList-edit.vue';
  230. const goodsListEditRef = shallowRef(goodsListEdit);
  231. //发现组件
  232. import discover from '@/views/diy/pcPages/discover.vue';
  233. const discoverRef = shallowRef(discover);
  234. import discoverEdit from '@/views/diy/pcEdit/discover-edit.vue';
  235. const discoverEditRef = shallowRef(discoverEdit);
  236. const itemKey = ref<any>(0);
  237. //左边得组件
  238. const uniqueIdCounter = ref<any>(0);
  239. const activeNames = ref<any>([0]);
  240. const collapse = ref<any>([
  241. {
  242. name: '基础组件',
  243. list: [
  244. {
  245. name: '头部组件',
  246. icon: 'iconfont iconfuwenbenpc',
  247. id: 1,
  248. components: markRaw(headRef.value),
  249. edit: markRaw(headEditRef.value)
  250. },
  251. {
  252. name: '文本标题',
  253. icon: 'iconfont iconbiaotipc',
  254. id: 2,
  255. components: markRaw(ctextTitleRef.value),
  256. edit: markRaw(textTitleEditRef.value)
  257. },
  258. {
  259. name: '图文导航',
  260. icon: 'iconfont icontuwendaohangpc',
  261. id: 3,
  262. components: markRaw(navigationRef.value),
  263. edit: markRaw(navigationEditRef.value)
  264. },
  265. {
  266. name: '图片魔方',
  267. icon: 'iconfont iconmofangpc',
  268. id: 4,
  269. components: markRaw(imageCubeRef.value),
  270. edit: markRaw(imageCubeEditRef.value)
  271. },
  272. {
  273. name: '活动魔方',
  274. icon: 'iconfont iconmofangpc',
  275. id: 5
  276. },
  277. {
  278. name: '轮播图',
  279. icon: 'iconfont icona-tupianzhanbopc302',
  280. id: 6,
  281. components: markRaw(carouselRef.value),
  282. edit: markRaw(carouselEditRef.value)
  283. },
  284. {
  285. name: '文章咨询',
  286. icon: 'iconfont icongonggaopc',
  287. id: 7,
  288. components: markRaw(articleRef.value),
  289. edit: markRaw(articleEditRef.value)
  290. },
  291. {
  292. name: '品牌组件',
  293. icon: 'iconfont iconmiaoshashangpin',
  294. id: 8,
  295. components: markRaw(brandeRef.value),
  296. edit: markRaw(brandEditRef.value)
  297. },
  298. {
  299. name: '图文广告',
  300. icon: 'iconfont icontupiandaohangpc',
  301. id: 9,
  302. components: markRaw(advertRef.value),
  303. edit: markRaw(advertEditRef.value)
  304. },
  305. {
  306. name: '楼层组件',
  307. icon: 'iconfont iconshangpinliebiaopc',
  308. id: 10,
  309. components: markRaw(floorRef.value),
  310. edit: markRaw(floorEditRef.value)
  311. },
  312. {
  313. name: '商品组件',
  314. icon: 'iconfont icona-shangpintuijianpc30',
  315. id: 11,
  316. components: markRaw(goodsRef.value),
  317. edit: markRaw(goodsEditRef.value)
  318. },
  319. {
  320. name: '多商品组',
  321. icon: 'iconfont iconduoshangpinzupc',
  322. id: 12,
  323. components: markRaw(goodsListRef.value),
  324. edit: markRaw(goodsListEditRef.value)
  325. },
  326. {
  327. name: '发现组件',
  328. icon: 'iconfont iconrequpc',
  329. id: 13,
  330. components: markRaw(discoverRef.value),
  331. edit: markRaw(discoverEditRef.value)
  332. }
  333. ]
  334. }
  335. ]);
  336. const componentList = ref<any>([
  337. // {
  338. // components: ctextTitleRef
  339. // }
  340. ]);
  341. const handleChange = (val: string[]) => {};
  342. // 返回上一页
  343. const goBack = () => {};
  344. // 预览
  345. const preview = () => {};
  346. // 保存
  347. const save = () => {
  348. const datas = {
  349. name: query.title,
  350. siteId: '',
  351. clientId: '',
  352. type: query.type,
  353. remark: '',
  354. previewPicUrls: '',
  355. property: JSON.stringify(diyStore.componentList),
  356. isHome: 1
  357. };
  358. const api = pcAddDiy;
  359. api(datas)
  360. .then((res: any) => {
  361. if (res.code == 200) {
  362. }
  363. })
  364. .catch(() => {});
  365. };
  366. </script>
  367. <style lang="scss" scoped>
  368. .pcEdit {
  369. width: 100%;
  370. overflow: auto;
  371. }
  372. .pcEdit-pages {
  373. min-height: calc(100vh - 84px);
  374. // min-width: 1900px;
  375. .full-container {
  376. height: calc(100vh - 134px);
  377. background-color: #f2f2f2;
  378. .component-list {
  379. height: 100%;
  380. background-color: #ffffff;
  381. padding: 0 10px;
  382. }
  383. .component-list ul li {
  384. &:not(.disabled):hover {
  385. color: var(--el-color-primary);
  386. background: var(--el-color-primary-light-9);
  387. }
  388. }
  389. .preview-wrap {
  390. flex: 1;
  391. display: flex;
  392. justify-content: center;
  393. .preview-pages {
  394. margin: 30px auto;
  395. width: 1300px;
  396. background: var(--el-bg-color-page);
  397. overflow: auto;
  398. height: calc(130vh - 194px);
  399. zoom: 0.7;
  400. // height: calc(100vh - 194px);
  401. /* 为了兼容某些情况,可能还需要配合 display */
  402. display: inline-block;
  403. }
  404. .component-bos {
  405. position: relative;
  406. .component-box {
  407. position: absolute;
  408. width: 100%;
  409. height: 100%;
  410. top: 0;
  411. left: 0;
  412. border: 2px solid var(--el-color-primary);
  413. z-index: 2;
  414. cursor: move;
  415. }
  416. }
  417. }
  418. //编辑组件属性区域
  419. .edit-attribute-wrap {
  420. background: var(--el-bg-color);
  421. }
  422. .edit-attribute-wrap .box-card {
  423. border: none;
  424. }
  425. .edit-attr-item-wrap {
  426. border-top: 2px solid var(--el-color-info-light-8);
  427. padding-top: 20px;
  428. &:first-of-type {
  429. border-top: none;
  430. padding-top: 0;
  431. }
  432. }
  433. }
  434. :deep(.el-header) {
  435. height: 50px;
  436. }
  437. }
  438. </style>