navConfig.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <view class="uni-app">
  3. <view class="status-bar" />
  4. <view class="main-container">
  5. <wk-nav-bar title="底部导航栏设置">
  6. <!-- #ifndef MP-WEIXIN -->
  7. <button class="button white-btn" @click="handleSave">
  8. 保存
  9. </button>
  10. <!-- #endif -->
  11. </wk-nav-bar>
  12. <view class="container">
  13. <view class="section">
  14. <view class="section-title">
  15. <text class="section-title__text">
  16. 个性化导航栏设置
  17. </text>
  18. <text class="section-title__desc">
  19. (长按拖动调整顺序)
  20. </text>
  21. </view>
  22. <view class="wk-drag-sort">
  23. <view
  24. v-for="(item, index) in sortList"
  25. :id="`wk-drag-sort-item-` + index"
  26. :key="item.type"
  27. :class="{disabled: item.typeNum === 12}"
  28. class="wk-drag-sort-item"
  29. @touchstart="handleTouchstart($event, index)"
  30. @touchmove.stop.prevent="handleTouchmove($event, index)"
  31. @touchend="handleTouchend($event, index)"
  32. @tap.stop="handleRemove(index)">
  33. <view class="quick-item">
  34. <text :class="item.active_icon" class="icon" />
  35. <text class="text">
  36. {{ item.name }}
  37. </text>
  38. <image
  39. v-if="!item.disabled"
  40. :src="$static('images/icon/status_invalid.png')"
  41. class="control-icon" />
  42. </view>
  43. </view>
  44. <template v-if="sortList.length < 5">
  45. <view
  46. v-for="i in (5 - sortList.length)"
  47. :key="i"
  48. class="empty-item" />
  49. </template>
  50. <view
  51. :style="{
  52. left: moveLeft + 'px',
  53. top: moveTop + 'px',
  54. width: itemWidth + 'px',
  55. height: itemHeight + 'px',
  56. visibility: showMoveItem ? 'unset' : 'hidden'
  57. }"
  58. class="move-item">
  59. <view
  60. v-if="moveItemData"
  61. class="quick-item">
  62. <text :class="moveItemData.active_icon" class="icon" />
  63. <text
  64. class="text">
  65. {{ moveItemData.name }}
  66. </text>
  67. </view>
  68. </view>
  69. </view>
  70. </view>
  71. <view class="section">
  72. <view class="section-title">
  73. <text class="section-title__text">
  74. 全部
  75. </text>
  76. </view>
  77. <view class="section-body">
  78. <view
  79. v-for="(item, index) in otherList"
  80. :key="item.type"
  81. class="quick-item"
  82. @click="handleAdd(index)">
  83. <text :class="item.active_icon" class="icon" />
  84. <text class="text">
  85. {{ item.name }}
  86. </text>
  87. <image
  88. :src="$static('images/icon/add_primary.png')"
  89. class="control-icon" />
  90. </view>
  91. </view>
  92. </view>
  93. </view>
  94. <!-- #ifdef MP-WEIXIN -->
  95. <view class="footer-btn-group">
  96. <button class="button" @click="handleSave">
  97. 保存
  98. </button>
  99. </view>
  100. <!-- #endif -->
  101. </view>
  102. </view>
  103. </template>
  104. <script>
  105. import { GetNavConfig, SetNavConfig } from '@/api/base.js'
  106. import { mapMutations } from 'vuex'
  107. import { navLibList, getNavList } from '@/utils/data.js'
  108. import { DEFAULT_NAV_CONFIG } from '@/config.js'
  109. import dragSortMixins from '@/components/wk-drag-sort/mixins.js'
  110. export default {
  111. name: 'NavConfig',
  112. mixins: [dragSortMixins],
  113. data() {
  114. return {
  115. routerQuery: {},
  116. navConfig: {},
  117. configList: DEFAULT_NAV_CONFIG.nav
  118. }
  119. },
  120. computed: {
  121. otherList() {
  122. return navLibList.filter(o => !this.configList.includes(o.typeNum) && o.typeNum !== 4)
  123. },
  124. sortList() {
  125. return getNavList(this.configList)
  126. }
  127. },
  128. onLoad(options) {
  129. this.routerQuery = options
  130. this.initCom()
  131. },
  132. methods: {
  133. ...mapMutations({
  134. setNavFooter: 'user/SET_NAV_FOOTER'
  135. }),
  136. initCom() {
  137. GetNavConfig().then(res => {
  138. this.navConfig = this.$isEmpty(res) ? {} : res[0]
  139. this.configList = this.navConfig.nav || DEFAULT_NAV_CONFIG.nav
  140. if (!this.configList.includes(12)) {
  141. this.configList.push(12)
  142. }
  143. if (this.configList.length > 5) {
  144. this.configList.splice(4, this.configList.length - 5)
  145. }
  146. if (!this.$isEmpty(this.navConfig)) {
  147. uni.setStorageSync('navConfig', this.navConfig)
  148. }
  149. }).catch(() => {
  150. })
  151. },
  152. handleRemove(index) {
  153. const item = this.sortList[index]
  154. if (item.typeNum === 12) return
  155. this.configList.splice(index, 1)
  156. },
  157. handleSort(list) {
  158. this.configList = list.map(o => o.typeNum)
  159. },
  160. handleAdd(index) {
  161. if (this.configList.length >= 5) {
  162. this.configList.splice(5)
  163. this.$toast('导航栏最多可以展示5个应用')
  164. return
  165. }
  166. const item = this.otherList[index]
  167. this.configList.push(item.typeNum)
  168. },
  169. handleSave() {
  170. if (this.configList.length < 3) {
  171. this.$toast('导航栏最少要展示3个应用')
  172. return
  173. }
  174. if (!this.configList.includes(12)) {
  175. this.$toast('导航栏必须包含"我的"')
  176. return
  177. }
  178. const params = {
  179. ...this.navConfig,
  180. nav: this.configList
  181. }
  182. SetNavConfig([params]).then(() => {
  183. this.setNavFooter(params)
  184. uni.setStorageSync('navConfig', params)
  185. this.$Router.reLaunch('/pages/home/index')
  186. }).catch(() => {})
  187. }
  188. }
  189. }
  190. </script>
  191. <style scoped lang="scss">
  192. .container {
  193. flex: 1;
  194. .quick-item {
  195. position: relative;
  196. width: calc(25% - 20rpx);
  197. height: 150rpx;
  198. flex-direction: column;
  199. box-shadow: 0px 6rpx 18rpx rgba(232, 232, 233, 0.77);
  200. border-radius: 16rpx;
  201. background-color: white;
  202. margin: 10rpx;
  203. @include center;
  204. .icon {
  205. font-size: 46rpx;
  206. color: $theme-color;
  207. }
  208. .text {
  209. font-size: $wk-font-mini;
  210. margin-top: 10rpx;
  211. }
  212. .control-icon {
  213. position: absolute;
  214. top: 5rpx;
  215. right: 5rpx;
  216. width: 36rpx;
  217. height: 36rpx;
  218. }
  219. }
  220. .empty-item {
  221. width: calc(25% - 20rpx);
  222. height: 150rpx;
  223. box-shadow: unset;
  224. border: 1rpx dashed #999999;
  225. border-radius: 16rpx;
  226. margin: 10rpx;
  227. }
  228. .section {
  229. background-color: white;
  230. padding: 32rpx;
  231. .section-title {
  232. margin-bottom: 20rpx;
  233. .section-title__text {
  234. font-size: $wk-font-large;
  235. font-weight: bold;
  236. color: $dark;
  237. }
  238. .section-title__desc {
  239. font-size: $wk-font-base;
  240. color: $gray;
  241. }
  242. }
  243. .section-body {
  244. width: 100%;
  245. flex-wrap: wrap;
  246. @include left;
  247. }
  248. .wk-drag-sort {
  249. width: 100%;
  250. flex-wrap: wrap;
  251. @include left;
  252. .wk-drag-sort-item {
  253. width: calc(25% - 20rpx);
  254. height: 150rpx;
  255. margin: 10rpx;
  256. }
  257. .quick-item {
  258. width: 100%;
  259. height: 100%;
  260. margin: 0;
  261. }
  262. .move-item {
  263. position: fixed;
  264. visibility: hidden;
  265. z-index: 10;
  266. will-change: top left;
  267. }
  268. .wk-drag-sort-item.disabled {
  269. .quick-item .icon {
  270. color: $theme-color;
  271. }
  272. }
  273. }
  274. }
  275. }
  276. </style>