edit-float-btn.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <div>
  3. <!-- 内容 -->
  4. <div class="content-wrap float-btn" v-show="diyStore.editTab == 'content'">
  5. <div class="edit-attr-item-wrap">
  6. <h3 class="mb-[10px]">按钮位置</h3>
  7. <el-form label-width="80px" class="px-[10px]">
  8. <el-form-item label="按钮位置">
  9. <span>{{ selectTemplate.name }}</span>
  10. <ul class="ml-[10px] flex items-center">
  11. <template v-for="(item, i) in templateList" :key="i">
  12. <li
  13. v-if="diyStore.editComponent.style === 'style-1' || (diyStore.editComponent.style === 'style-2' && i > 1)"
  14. :class="[
  15. 'w-[50px] h-[32px] flex items-center justify-center border-solid border-[1px] border-[#eee] cursor-pointer',
  16. { 'border-r-transparent': templateList.length != i + 1 },
  17. item.className == diyStore.editComponent.bottomPosition ? '!border-[var(--el-color-primary)]' : ''
  18. ]"
  19. @click="changeTemplateList(item)"
  20. >
  21. <span :class="['iconfont !text-[20px]', item.src]"></span>
  22. </li>
  23. </template>
  24. </ul>
  25. </el-form-item>
  26. <el-form-item label="上下偏移">
  27. <el-slider v-model="diyStore.editComponent.offset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="100" />
  28. </el-form-item>
  29. <el-form-item label="左右偏移">
  30. <el-slider v-model="diyStore.editComponent.lateralOffset" show-input size="small" class="ml-[10px] diy-nav-slider" :max="15" :min="-10" />
  31. </el-form-item>
  32. </el-form>
  33. </div>
  34. <div class="edit-attr-item-wrap">
  35. <h3 class="mb-[10px]">图片设置</h3>
  36. <el-form label-width="80px" class="px-[10px]">
  37. <el-form-item label="图片大小">
  38. <el-slider v-model="diyStore.editComponent.imageSize" show-input size="small" class="ml-[10px] diy-nav-slider" :min="30" :max="100" />
  39. </el-form-item>
  40. <el-form-item label="图片圆角">
  41. <el-slider v-model="diyStore.editComponent.aroundRadius" show-input size="small" class="ml-[10px] diy-nav-slider" :max="50" />
  42. </el-form-item>
  43. <div class="text-[12px] text-[#999] mb-[15px] mt-[5px]">建议上传正方形图片</div>
  44. <div ref="imageBoxRef">
  45. <div
  46. v-for="(item, index) in diyStore.editComponent.list"
  47. :key="item.id"
  48. class="item-wrap p-[10px] pb-0 relative border border-dashed border-gray-300 mb-[16px]"
  49. >
  50. <el-form-item label="图片上传">
  51. <upload-image v-model="item.imageUrl" :limit="1" />
  52. </el-form-item>
  53. <div
  54. class="del absolute cursor-pointer z-[2] top-[-8px] right-[-8px]"
  55. v-show="diyStore.editComponent.list.length > 1"
  56. @click="diyStore.editComponent.list.splice(index, 1)"
  57. >
  58. <icon name="element CircleCloseFilled" color="#bbb" size="20px" />
  59. </div>
  60. <el-form-item label="链接地址">
  61. <WebLinkInput :pageType="'2'" v-model="item.link" placeholder="请输入或选择链接" />
  62. </el-form-item>
  63. </div>
  64. </div>
  65. </el-form>
  66. <el-button v-show="diyStore.editComponent.list.length < 3" class="w-full" @click="addImageAd">添加图片</el-button>
  67. </div>
  68. </div>
  69. <!-- 样式 -->
  70. <div class="style-wrap" v-show="diyStore.editTab == 'style'">
  71. <!-- 组件样式 -->
  72. <slot name="style"></slot>
  73. </div>
  74. </div>
  75. </template>
  76. <script lang="ts" setup>
  77. import Sortable from 'sortablejs';
  78. import useDiyStore from '@/store/modules/diy';
  79. import { range } from 'lodash-es';
  80. const diyStore = useDiyStore();
  81. diyStore.editComponent.ignore = ['pageBgColor', 'marginTop', 'marginBottom', 'marginBoth', 'componentBgUrl']; // 忽略公共属性
  82. // 组件验证
  83. diyStore.editComponent.verify = (index: number) => {
  84. const res = { code: true, message: '' };
  85. diyStore.value[index].list.forEach((item: any) => {
  86. if (item.imageUrl === '') {
  87. res.code = false;
  88. res.message = '请上传图片';
  89. return res;
  90. }
  91. });
  92. return res;
  93. };
  94. const templateList = ref([
  95. {
  96. name: '左上',
  97. src: 'iconzuoshangpc',
  98. className: 'upperLeft'
  99. },
  100. {
  101. name: '右上',
  102. src: 'iconyoushangpc',
  103. className: 'upperRight'
  104. },
  105. {
  106. name: '左下',
  107. src: 'iconzuoxiapc',
  108. className: 'lowerLeft'
  109. },
  110. {
  111. name: '右下',
  112. src: 'iconyouxiapc',
  113. className: 'lowerRight'
  114. }
  115. ]);
  116. const selectTemplate = ref<any>({});
  117. templateList.value.forEach((item) => {
  118. if (item.className == diyStore.editComponent.bottomPosition) {
  119. selectTemplate.value = item;
  120. }
  121. });
  122. const changeTemplateList = (data: any) => {
  123. selectTemplate.value = data;
  124. diyStore.editComponent.bottomPosition = data.className;
  125. };
  126. const addImageAd = () => {
  127. diyStore.editComponent.list.push({
  128. id: diyStore.generateRandom(),
  129. imageUrl: '',
  130. link: { name: '' }
  131. });
  132. };
  133. const imageBoxRef = ref();
  134. diyStore.editComponent.list.forEach((item: any) => {
  135. if (!item.id) item.id = diyStore.generateRandom();
  136. });
  137. onMounted(() => {
  138. nextTick(() => {
  139. const imageSortable = Sortable.create(imageBoxRef.value, {
  140. group: 'item-wrap',
  141. animation: 200,
  142. onEnd: (event) => {
  143. const temp = diyStore.editComponent.list[event.oldIndex!];
  144. diyStore.editComponent.list.splice(event.oldIndex!, 1);
  145. diyStore.editComponent.list.splice(event.newIndex!, 0, temp);
  146. imageSortable.sort(
  147. range(diyStore.editComponent.list.length).map((value) => {
  148. return value.toString();
  149. })
  150. );
  151. }
  152. });
  153. });
  154. });
  155. defineExpose({});
  156. </script>
  157. <style lang="scss" scoped></style>