canvasEditPage.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <template>
  2. <div class="layout hom-layout" v-loading="loading">
  3. <draggable
  4. class="dragArea list-group"
  5. :list="componentsData"
  6. group="pageEdit"
  7. @change="pageChange"
  8. >
  9. <div class="list-group-item" v-for="(item,index) in componentsData" :key="index" :class="[{'on':activeComponent == index},'item-'+item.type]" @click="selectComponent(item,index)">
  10. <component v-show="!item.isEmpty" :isNoData.sync='item.isEmpty' :is="componentMap[terminal-1].get(item.type)" :componentContent="item.componentContent" :terminal="terminal" :typeId="typeId" :shopId="shopId" @cleckLoading="cleckLoading"></component>
  11. <div class="no-data" v-show="item.isEmpty">
  12. <i class="iconfont icon-kong"></i>
  13. <p>暂无数据<br>请在右边窗口编辑内容</p>
  14. </div>
  15. <div class="btns">
  16. <span @click="delComponent(item,index)"><i class="iconfont icon-shanchu"></i></span>
  17. </div>
  18. </div>
  19. </draggable>
  20. </div>
  21. </template>
  22. <script>
  23. import draggable from 'vuedraggable'
  24. import componentMap from './canvasShow/componentMap'
  25. import { mapGetters, mapMutations } from 'vuex'
  26. export default {
  27. // import testData from '@@/config/testData3'
  28. name: 'canvasEditPage',
  29. components: {
  30. draggable
  31. },
  32. props: {
  33. terminal: {
  34. type: Number,
  35. default: 4
  36. },
  37. typeId: {
  38. type: Number,
  39. default: 1
  40. },
  41. shopId: {
  42. type: Number,
  43. default: 0
  44. }
  45. },
  46. data () {
  47. return {
  48. activeComponent: -1,
  49. componentMap: componentMap,
  50. loading: false
  51. }
  52. },
  53. mounted () {
  54. // this.setComponentsData(testData)
  55. },
  56. computed: {
  57. ...mapGetters([
  58. 'componentsData'
  59. ])
  60. },
  61. methods: {
  62. ...mapMutations({
  63. setActiveComponent: 'SET_ACTIVECOMPONENT',
  64. setComponentsData: 'SET_COMPONENTSDATA'
  65. }),
  66. // 画布添加或者移动了组件
  67. pageChange (e) {
  68. if (e.added) {
  69. this.activeComponent = e.added.newIndex
  70. e.added.element.index = e.added.newIndex
  71. this.setActiveComponent(e.added.element)
  72. }
  73. if (e.moved) {
  74. this.activeComponent = e.moved.newIndex
  75. e.moved.element.index = e.moved.newIndex
  76. this.setActiveComponent(e.moved.element)
  77. }
  78. this.$emit('showRightBox', true)
  79. },
  80. // 选中组件
  81. selectComponent (item, index) {
  82. this.activeComponent = index
  83. item.index = index
  84. this.setActiveComponent(item)
  85. this.$emit('showRightBox', true)
  86. },
  87. // 删除组件
  88. delComponent (item, index) {
  89. this.$confirm('确定删除吗?', '提示', {
  90. confirmButtonText: '确定',
  91. cancelButtonText: '取消',
  92. type: 'warning'
  93. }).then(() => {
  94. this.activeComponent = -1
  95. this.componentsData.splice(index, 1)
  96. this.$emit('showRightBox', false)
  97. }).catch(() => {
  98. })
  99. },
  100. cleckLoading(){
  101. if(typeof(uni) !== 'undefined'){
  102. uni.getStorage({
  103. key: 'sendNum',
  104. success: function (res) {
  105. let sendNum = res.data;
  106. this.loading = parseInt(sendNum) !== 0
  107. }
  108. })
  109. } else {
  110. let sendNum = localStorage.getItem('sendNum')
  111. this.loading = parseInt(sendNum) !== 0
  112. }
  113. },
  114. // 检查组件是否为空
  115. checkIsNoData(dataList) {
  116. for(let i=0;i<dataList.length;i++){
  117. const newVal = dataList[i].componentContent
  118. let isEmpty = true
  119. let _data = ''
  120. switch (dataList[i].type){
  121. case 'banner':
  122. _data=newVal.bannerData
  123. _data.forEach(function(value ){
  124. if(value.bannerUrl){
  125. isEmpty = false
  126. }
  127. })
  128. break
  129. case 'notice':
  130. case 'text':
  131. case 'imageTextNav':
  132. case 'imageText':
  133. case 'imageTextList':
  134. case 'brandList':
  135. case 'categoryList':
  136. case 'assistDiv':
  137. isEmpty = false
  138. break
  139. case 'productList':
  140. _data = newVal.productData
  141. if((_data.sourceType=='1' && _data.productIdList.length > 0) || (_data.sourceType=='2' && _data.categoryId != 0)){
  142. isEmpty = false
  143. }
  144. break
  145. case 'custom':
  146. _data=newVal.imgData
  147. _data.forEach(function(value ){
  148. if(value.src){
  149. isEmpty = false
  150. }
  151. })
  152. break
  153. case 'groupList':
  154. if(this.typeId === 1){
  155. isEmpty = false
  156. }
  157. else {
  158. if(newVal.shopGroupWorkId){
  159. isEmpty = false
  160. }
  161. }
  162. break
  163. case 'spikeList':
  164. if(newVal.shopSeckillId){
  165. isEmpty = false
  166. }
  167. break
  168. case 'discountList':
  169. if(newVal.discountId){
  170. isEmpty = false
  171. }
  172. break
  173. case 'priceList':
  174. if(newVal.priceId){
  175. isEmpty = false
  176. }
  177. break
  178. case 'vip':
  179. isEmpty = false
  180. break
  181. case 'coupon':
  182. if(newVal.selectedCoupon.length > 0){
  183. isEmpty = false
  184. }
  185. break
  186. case 'newProduct':
  187. _data = newVal.productData
  188. if((_data.sourceType=='1' && _data.productIdList.length > 0) || (_data.sourceType=='2' && _data.categoryId != 0)){
  189. isEmpty = false
  190. }
  191. break
  192. case 'shop':
  193. _data=newVal.imgTextData
  194. _data.forEach(function(value ){
  195. if(value.img){
  196. isEmpty = false
  197. }
  198. })
  199. break
  200. }
  201. dataList[i].isEmpty = isEmpty
  202. this.$forceUpdate()
  203. }
  204. console.log(dataList)
  205. },
  206. },
  207. // 监控组件是否为空
  208. watch: {
  209. 'componentsData': {
  210. handler(newVal, oldVal) {
  211. this.checkIsNoData(newVal)
  212. },
  213. deep: true
  214. }
  215. }
  216. }
  217. </script>
  218. <style lang="scss" scoped>
  219. .hom-layout {
  220. background-color: #fff;
  221. ::v-deep .sortable-chosen {
  222. .contentBox {
  223. display: none;
  224. }
  225. .cloneText {
  226. display: block;
  227. width: 100%;
  228. height: 50px;
  229. line-height: 50px;
  230. font-size: 18px;
  231. text-align: center;
  232. background-color: $mainColor;
  233. color: #fff;
  234. }
  235. }
  236. .list-group {
  237. min-height: calc(100vh - 50px);
  238. }
  239. .list-group-item {
  240. position: relative;
  241. cursor: move;
  242. background-color: #fff;
  243. min-height: 100px;
  244. &.item-assistDiv,&.item-notice,&.item-text{
  245. min-height: 0px;
  246. }
  247. .btns {
  248. display: none;
  249. }
  250. &:hover {
  251. &:after {
  252. content: '';
  253. position: absolute;
  254. width: 100%;
  255. height: 100%;
  256. left: 0;
  257. top: 0;
  258. border: 1px $mainColor dashed;
  259. z-index: 2;
  260. }
  261. }
  262. &.on {
  263. &:after {
  264. content: '';
  265. position: absolute;
  266. width: 100%;
  267. height: 100%;
  268. left: 0;
  269. top: 0;
  270. border: 1px $mainColor solid;
  271. z-index: 2;
  272. }
  273. .btns {
  274. display: block;
  275. position: absolute;
  276. right: -13px;
  277. top: 50%;
  278. margin-top: -13px;
  279. z-index: 3;
  280. span {
  281. display: block;
  282. width: 26px;
  283. height: 26px;
  284. line-height: 26px;
  285. text-align: center;
  286. color: #666;
  287. background-color: #fff;
  288. box-shadow: 0 0 2px rgba(51, 51, 51, 0.2);
  289. cursor: pointer;
  290. }
  291. }
  292. }
  293. }
  294. }
  295. .no-data {
  296. width: 100%;
  297. display: flex;
  298. height: 300px;
  299. -webkit-box-align: center;
  300. align-items: center;
  301. -webkit-box-pack: center;
  302. justify-content: center;
  303. color: #999;
  304. text-align: center;
  305. font-size: 16px;
  306. line-height: 1.8;
  307. .iconfont {
  308. font-size: 100px;
  309. color: $mainColor;
  310. margin-right: 50px;
  311. }
  312. }
  313. </style>
  314. <style lang="scss">
  315. .warp {
  316. width: 690px;
  317. margin: 0 auto;
  318. max-width: 100%;
  319. &.terminal4 {
  320. width: 1200px;
  321. max-width: 100%;
  322. }
  323. }
  324. .flex-box {
  325. display: flex;
  326. }
  327. </style>