SystemEdit.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. <template>
  2. <div>
  3. <el-dialog
  4. v-loading="loading"
  5. :visible.sync="visible"
  6. :close-on-press-escape="false"
  7. :close-on-click-modal="false"
  8. :show-close="false"
  9. append-to-body
  10. custom-class="home-edit-dialog"
  11. title="Setting"
  12. >
  13. <div class="drag-container">
  14. <div v-loading="allLoading" class="drag-left">
  15. <div class="item-filter">
  16. list
  17. <el-input v-model="systemName" size="mini" clearable class="filter-item-input">
  18. <el-button slot="append" icon="el-icon-search" />
  19. </el-input>
  20. </div>
  21. <draggable
  22. v-model="allBizData"
  23. :group="{name: 'system', pull: 'clone', put: false}"
  24. :clone="clone"
  25. :sort="false"
  26. :move="checkMove"
  27. :set-data="setData"
  28. filter=".filtered"
  29. class="drag-item-box"
  30. >
  31. <div
  32. v-for="(element, index) in allBizData"
  33. :key="element.id"
  34. class="drag-item"
  35. :class="{'filtered': element.isFavorite}"
  36. >
  37. <i class="el-icon-plus handle-icon" @click="clickAddItem(index)" />
  38. <el-avatar :size="56" :src="element.url" />
  39. <div class="item-name">{{ element.businessName }}</div>
  40. </div>
  41. </draggable>
  42. <div v-if="allBizTotal > 0" class="page">
  43. <el-pagination
  44. small
  45. layout="prev, pager, next"
  46. :current-page="current"
  47. :total="allBizTotal"
  48. :page-size="size"
  49. @current-change="handleCurrentChange"
  50. />
  51. </div>
  52. </div>
  53. <div v-loading="myLoading" class="drag-right">
  54. <div class="drag-title">My
  55. <div class="item-tip">tip</div>
  56. </div>
  57. <el-scrollbar class="my-scroll-box">
  58. <draggable
  59. :list="myBizData"
  60. group="system"
  61. class="drag-item-box"
  62. :set-data="setData"
  63. @add="addItem"
  64. >
  65. <div v-for="(element, index) in myBizData" :key="element.id" class="drag-item">
  66. <i class="el-icon-minus handle-icon" @click="clickRemoveItem(index)" />
  67. <el-avatar :size="56" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
  68. <div class="item-content">
  69. <div class="item-name">{{ element.businessName }}</div>
  70. <div class="item-system">{{ element.appName }}</div>
  71. </div>
  72. </div>
  73. </draggable>
  74. </el-scrollbar>
  75. </div>
  76. </div>
  77. <div slot="footer">
  78. <el-button size="small" @click="close">Cancel</el-button>
  79. <el-button type="primary" size="small" @click="saveFavorite">Confirm</el-button>
  80. </div>
  81. </el-dialog>
  82. </div>
  83. </template>
  84. <script>
  85. import draggable from 'vuedraggable'
  86. import { hasValidRecords } from '@/utils/convert'
  87. import { fetchAllBizList, fetchMyBizList, pushSaveFavorite } from '@/api/biz'
  88. export default {
  89. components: {
  90. draggable
  91. },
  92. props: {},
  93. data() {
  94. return {
  95. // dialog
  96. visible: false,
  97. // table
  98. current: 1,
  99. size: 15,
  100. allBizTotal: 0,
  101. allBizData: [],
  102. myBizData: [
  103. { businessName: 'bizleft4', id: 4 },
  104. { businessName: 'bizleft5', id: 5 },
  105. { businessName: 'bizleft6', id: 6 },
  106. { businessName: 'bizleft7', id: 7 }
  107. ],
  108. // filter
  109. formData: {
  110. systemNumber: '',
  111. systemName: '',
  112. businessName: '',
  113. businessNumber: ''
  114. },
  115. // select data
  116. systemData: [],
  117. businessData: [],
  118. // others
  119. loading: false,
  120. allLoading: false,
  121. myLoading: false
  122. }
  123. },
  124. computed: {
  125. myBizIds() {
  126. return this.myBizData.map(item => item.id)
  127. }
  128. },
  129. created() {
  130. },
  131. methods: {
  132. // 改变每页显示条数
  133. handleSizeChange(val) {
  134. this.current = 1
  135. this.size = val
  136. this.getAllBizList()
  137. },
  138. // 切换第几页
  139. handleCurrentChange(val) {
  140. this.current = val
  141. this.getAllBizList()
  142. },
  143. // 重置搜索项
  144. resetTable(formName) {
  145. this.$refs[formName].resetFields()
  146. this.getAllBizList()
  147. },
  148. // 点击搜索按钮
  149. searchTable() {
  150. this.current = 1
  151. this.getAllBizList()
  152. },
  153. // 获取table数据
  154. getAllBizList() {
  155. this.allLoading = true
  156. const params = {
  157. page: this.current,
  158. size: this.size,
  159. params: {
  160. delFlag: 0,
  161. appName: this.formData.systemName,
  162. businessName: this.formData.businessName
  163. }
  164. }
  165. fetchAllBizList(params).then(response => {
  166. this.allLoading = false
  167. if (hasValidRecords(response)) {
  168. response.data.records.forEach(item => {
  169. if (this.myBizIds.includes(item.id)) {
  170. item.isFavorite = true
  171. } else {
  172. item.isFavorite = false
  173. }
  174. })
  175. this.allBizData = response.data.records
  176. this.allBizTotal = response.data.total
  177. } else {
  178. this.allBizData = []
  179. this.allBizTotal = 0
  180. }
  181. }).catch(error => {
  182. console.log(error)
  183. this.allLoading = false
  184. this.$message.error({
  185. type: 'error',
  186. duration: 0,
  187. showClose: true,
  188. message: error.message
  189. })
  190. })
  191. },
  192. getMyBizList() {
  193. this.myLoading = true
  194. this.allLoading = true
  195. const params = {
  196. page: 1,
  197. size: 50,
  198. params: {
  199. delFlag: 0
  200. }
  201. }
  202. fetchMyBizList(params).then(response => {
  203. this.myLoading = false
  204. if (hasValidRecords(response)) {
  205. this.myBizData = response.data.records
  206. } else {
  207. this.myBizData = []
  208. }
  209. this.searchTable()
  210. }).catch(error => {
  211. console.log(error)
  212. this.myLoading = false
  213. this.$message.error({
  214. type: 'error',
  215. duration: 0,
  216. showClose: true,
  217. message: error.message
  218. })
  219. })
  220. },
  221. saveFavorite() {
  222. this.loading = true
  223. pushSaveFavorite(this.myBizData).then(res => {
  224. this.loading = false
  225. this.visible = false
  226. this.$message({
  227. type: 'success',
  228. message: 'Save Successfully!'
  229. })
  230. }).catch(error => {
  231. console.log(error)
  232. this.loading = false
  233. this.$message.error({
  234. type: 'error',
  235. duration: 0,
  236. showClose: true,
  237. message: error.message
  238. })
  239. })
  240. },
  241. /**
  242. * 加载dialog
  243. */
  244. open() {
  245. this.allBizData = []
  246. this.myBizData = []
  247. this.visible = true
  248. this.getMyBizList()
  249. },
  250. close() {
  251. this.visible = false
  252. },
  253. clone(item) {
  254. return { ...item }
  255. },
  256. checkMove(evt) {
  257. return !this.myBizIds.includes(evt.draggedContext.element.id)
  258. },
  259. addItem(evt) {
  260. this.allBizData[evt.oldIndex].isFavorite = true
  261. },
  262. clickAddItem(index) {
  263. this.myBizData.push({ ...this.allBizData[index] })
  264. this.allBizData[index].isFavorite = true
  265. },
  266. clickRemoveItem(index) {
  267. const removed = this.myBizData.splice(index, 1)[0]
  268. this.allBizData.forEach(item => {
  269. if (item.id === removed.id) {
  270. item.isFavorite = false
  271. }
  272. })
  273. },
  274. setData(dataTransfer) {
  275. // to avoid Firefox bug
  276. // Detail see : https://github.com/RubaXa/Sortable/issues/1012
  277. dataTransfer.setData('Text', '')
  278. }
  279. }
  280. }
  281. </script>
  282. <style lang="scss" scoped>
  283. .drag-container {
  284. display: flex;
  285. justify-content: center;
  286. .drag-left, .drag-right {
  287. width: 50%;
  288. padding: 0 0 20px 20px;
  289. max-height: 540px;
  290. }
  291. .drag-left {
  292. background-color: #F8F9F9;
  293. position: relative;
  294. .page {
  295. position: absolute;
  296. bottom: 0;
  297. left: 0;
  298. width: 100%;
  299. text-align: center;
  300. ::v-deep {
  301. .btn-prev, .btn-next, .el-pager li{
  302. background-color: transparent;
  303. }
  304. }
  305. }
  306. }
  307. .drag-right {
  308. .my-scroll-box {
  309. // 48 = drag-title + item-tip - drag-right.margin-bottom
  310. height: calc(100% - 48px);
  311. margin-top: -2px;
  312. }
  313. ::v-deep {
  314. .el-scrollbar__wrap{
  315. overflow-x: hidden;
  316. padding-top: 2px;
  317. }
  318. .el-scrollbar__bar.is-horizontal {
  319. display: none;
  320. }
  321. }
  322. }
  323. .drag-title {
  324. font-size: 14px;
  325. line-height: 2;
  326. height: 28px;
  327. color: rgba(0,0,0,0.85);
  328. }
  329. .item-filter, .item-tip {
  330. height: 40px;
  331. }
  332. .item-tip {
  333. font-size: 12px;
  334. line-height: 40px;
  335. color: rgba(0,0,0,0.65);
  336. }
  337. .filter-item-input {
  338. float: right;
  339. width: 150px;
  340. }
  341. .drag-item-box {
  342. display: flex;
  343. flex-wrap: wrap;
  344. }
  345. .drag-item {
  346. width: 150px;
  347. height: 100px;
  348. border: 1px solid rgba(0,0,0,0.09);
  349. margin-bottom: 10px;
  350. margin-right: 20px;
  351. display: flex;
  352. flex-direction: column;
  353. justify-content: center;
  354. align-items: center;
  355. border-radius: 10px;
  356. position: relative;
  357. cursor: move;
  358. cursor: -webkit-grabbing;
  359. .handle-icon {
  360. display: inline-block;
  361. position: absolute;
  362. top: -3px;
  363. right: -7px;
  364. border-radius: 50%;
  365. background-color: #FF0000;
  366. color: #FFFFFF;
  367. cursor: pointer;
  368. z-index: 100;
  369. }
  370. &.filtered {
  371. cursor: pointer;
  372. .el-icon-plus {
  373. display: none;
  374. }
  375. }
  376. .item-system {
  377. width: 130px;
  378. text-overflow: ellipsis;
  379. overflow: hidden;
  380. white-space: nowrap;
  381. }
  382. .item-system {
  383. font-size: 14px;
  384. color: rgba(0,0,0,0.45);
  385. }
  386. }
  387. }
  388. </style>