dialog.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <el-dialog
  3. v-if="dialogVisible"
  4. ref="dialog"
  5. :show-close="showClose"
  6. :close-on-click-modal="closeOnClickModal"
  7. :close-on-press-escape="closeOnPressEscape"
  8. :visible.sync="dialogVisible"
  9. :width="width"
  10. :top="marginTop"
  11. lock-scroll
  12. append-to-body
  13. custom-class="ibps-selector-dialog"
  14. class="ibps-selector-dialog__wrapper"
  15. @close="handleClose"
  16. >
  17. <slot slot="title" name="title" />
  18. <div :style="{height:multiple?'35px':'35px'}" class="ibps-selector-header">
  19. <el-tag
  20. v-for="(item,index) in selectedItems"
  21. :key="index"
  22. closable
  23. @close="handleRemove(index,true)"
  24. >{{ item }}</el-tag>
  25. </div>
  26. <div>
  27. <slot
  28. :multiple="multiple"
  29. :height="height"
  30. :value="value"
  31. />
  32. </div>
  33. <div
  34. v-if="buttonGroup && buttonGroup.length >0"
  35. slot="footer"
  36. class="el-dialog--center"
  37. >
  38. <el-button
  39. v-for="(button,index) in buttonGroup"
  40. :key="index"
  41. :type="button.type"
  42. :icon="button.icon"
  43. :disabled="button.key==='confirm'?isDisabled:false"
  44. @click="button.action"
  45. >
  46. {{ button.label }}
  47. </el-button>
  48. </div>
  49. </el-dialog>
  50. </template>
  51. <script>
  52. import ActionUtils from '@/utils/action'
  53. export default {
  54. props: {
  55. visible: Boolean, // 是否可见
  56. title: { // 标题
  57. type: String,
  58. default: '选择器'
  59. },
  60. marginTop: { // Dialog CSS 中的 margin-top 值
  61. type: String,
  62. default: '5vh'
  63. },
  64. width: { // 宽
  65. type: String,
  66. default: '60%'
  67. },
  68. height: { // 高
  69. type: String,
  70. default: '400px'
  71. },
  72. closeOnClickModal: { // 是否可以通过点击 modal 关闭 Dialog
  73. type: Boolean,
  74. default: false
  75. },
  76. closeOnPressEscape: { // 是否可以通过按下 ESC 关闭 Dialog
  77. type: Boolean,
  78. default: false
  79. },
  80. showClose: { // 是否显示关闭按钮
  81. type: Boolean,
  82. default: true
  83. },
  84. beforeClose: { // 关闭前的回调,会暂停 Dialog 的关闭
  85. type: Function
  86. },
  87. fullscreen: { // 是否为全屏 Dialog
  88. type: Boolean,
  89. default: false
  90. },
  91. labelKey: { // 展示的值
  92. type: [String, Function],
  93. default: 'name'
  94. },
  95. value: { // 值
  96. type: [Object, Array],
  97. default () { return this.multiple ? [] : {} }
  98. },
  99. cleanClose: { // 按钮清空并关闭
  100. type: Boolean,
  101. default: false
  102. },
  103. defaultButton: {
  104. type: Boolean,
  105. default: true
  106. },
  107. buttons: { // 按钮组
  108. type: Array,
  109. default () {
  110. return []
  111. }
  112. },
  113. confirmButtonText: {
  114. type: String
  115. },
  116. cleanButtonText: {
  117. type: String
  118. },
  119. cancelButtonText: {
  120. type: String
  121. },
  122. multiple: { // 是否多选
  123. type: Boolean,
  124. default: false
  125. },
  126. isDisabled: { // 是否多选
  127. type: Boolean,
  128. default: false
  129. }
  130. },
  131. data () {
  132. return {
  133. dialogVisible: this.visible
  134. }
  135. },
  136. computed: {
  137. selectedItems () {
  138. if (this.$utils.isEmpty(this.value)) { return [] }
  139. if (this.multiple) {
  140. const items = []
  141. this.value.forEach(item => {
  142. items.push(this.handleLabel(item))
  143. })
  144. return items
  145. } else {
  146. return [this.handleLabel(this.value)]
  147. }
  148. },
  149. bodyStyle () {
  150. return {
  151. height: this.height,
  152. overflow: 'hidden'
  153. }
  154. },
  155. buttonGroup () {
  156. let buttons = []
  157. if (this.$utils.isEmpty(this.buttons) && this.defaultButton) {
  158. buttons = buttons.concat([
  159. { key: 'confirm', label: this.confirmButtonText || '确定', icon: 'ibps-icon-ok', type: 'primary', action: () => this.handleOk() },
  160. { key: 'clean', label: this.cleanButtonText || '清空', icon: 'ibps-icon-clean', type: 'info', action: () => this.handleClean() },
  161. { key: 'cleanAndClose', label: '清空并关闭', icon: 'ibps-icon-clean', type: 'warning', action: () => this.handleCleanAndClose() },
  162. { key: 'cancel', label: this.cancelButtonText || '取消', icon: 'ibps-icon-cancel', action: () => this.handleCancel() }
  163. ])
  164. } else {
  165. buttons = this.buttons
  166. }
  167. if (this.$utils.isEmpty(buttons)) {
  168. return []
  169. }
  170. return buttons.map(button => {
  171. if (button.action) {
  172. const action = button.action
  173. button.action = (e) => action(() => {}, this, e)
  174. }
  175. return button
  176. })
  177. }
  178. },
  179. watch: {
  180. visible: {
  181. handler: function (val, oldVal) {
  182. this.dialogVisible = this.visible
  183. },
  184. immediate: true
  185. }
  186. },
  187. methods: {
  188. handleLabel (data) {
  189. const config = this.labelKey
  190. if (typeof config === 'function') {
  191. return config(data)
  192. } else if (typeof config === 'string') {
  193. return data[config]
  194. } else if (typeof config === 'undefined') {
  195. const dataProp = data['name']
  196. return dataProp === undefined ? '' : dataProp
  197. }
  198. },
  199. // 确定
  200. handleOk () {
  201. const data = this.multiple ? this.value.slice(0) : this.value
  202. if (this.$utils.isEmpty(data)) {
  203. ActionUtils.warning('请选择记录!')
  204. return
  205. }
  206. this.$emit('input', data)
  207. this.$emit('action-event', 'confirm', data)
  208. },
  209. // 清空
  210. handleClean () {
  211. const data = this.multiple ? [] : {}
  212. if (!this.cleanClose) {
  213. this.$emit('input', data)
  214. }
  215. this.$emit('action-event', 'clean', data)
  216. },
  217. // 清空并关闭
  218. handleCleanAndClose () {
  219. const data = this.multiple ? [] : {}
  220. this.$emit('input', data)
  221. this.$emit('action-event', 'confirm', data)
  222. this.handleClose()
  223. },
  224. // 取消
  225. handleCancel () {
  226. this.handleClose()
  227. this.$emit('action-event', 'cancel')
  228. },
  229. // 关闭窗口
  230. handleClose () {
  231. this.$emit('close', false)
  232. },
  233. /**
  234. * 删除
  235. */
  236. handleRemove (index, bool) {
  237. let res
  238. let removeValue
  239. if (this.multiple) {
  240. const selected = JSON.parse(JSON.stringify(this.value))
  241. selected.splice(index, 1)
  242. res = selected
  243. removeValue = this.value[index]
  244. } else {
  245. res = {}
  246. removeValue = res
  247. }
  248. this.$emit('input', res)
  249. this.$emit('remove-select', removeValue)
  250. }
  251. }
  252. }
  253. </script>