You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

222 lines
6.3 KiB

  1. <template>
  2. <view
  3. @click="modalClick"
  4. :class="[value ? 'show' : '', type === 'bottom' ? 'bottom-modal' : '', className]"
  5. :style="style"
  6. class="cu-modal"
  7. >
  8. <!-- 图片弹出窗口 -->
  9. <view v-if="type === 'img'" class="cu-dialog">
  10. <view
  11. :style="{ backgroundImage: 'url(' + img + ')', height: '200px' }"
  12. class="bg-img"
  13. style="position: relative;"
  14. >
  15. <view @tap="close" class="action text-white" style="position: absolute;top: 10px;right: 10px;">
  16. <l-icon type="close" />
  17. </view>
  18. </view>
  19. <view class="cu-bar bg-white"><view @tap="close" class="action margin-0 flex-sub solid-left">关闭</view></view>
  20. </view>
  21. <!-- 单选弹出窗口 -->
  22. <view v-else-if="type === 'radio'" @tap.stop class="cu-dialog">
  23. <radio-group @change="radioChange" class="block">
  24. <view class="cu-list menu text-left">
  25. <view v-for="(item, index) of range" :key="index" class="cu-item">
  26. <label class="flex justify-between align-center flex-sub">
  27. <view class="flex-sub">{{ objectMode ? item[textField] : item }}</view>
  28. <radio
  29. :checked="radioIndex === index ? true : false"
  30. :value="objectMode ? item[valueField] : item"
  31. :class="radioIndex === index ? 'checked' : ''"
  32. class="round"
  33. ></radio>
  34. </label>
  35. </view>
  36. </view>
  37. </radio-group>
  38. </view>
  39. <!-- 多选弹出窗口 -->
  40. <view v-else-if="type === 'checkbox'" @tap.stop class="cu-dialog">
  41. <view class="cu-bar bg-white">
  42. <view @tap="close(0)" class="action text-blue">取消</view>
  43. <view v-if="!readonly" @tap="close(1)" class="action text-green">确定</view>
  44. </view>
  45. <view class="grid col-3 padding-sm">
  46. <view v-for="(item, index) in range" :key="index" class="padding-xs">
  47. <button
  48. @tap="chooseCheckbox(index)"
  49. :class="checkboxIndex.includes(index) ? 'bg-orange' : 'line-orange'"
  50. class="cu-btn orange lg block"
  51. >
  52. {{ objectMode ? item[textField] : item }}
  53. </button>
  54. </view>
  55. </view>
  56. </view>
  57. <!-- 普通/对话/底部弹出窗口 -->
  58. <view v-else class="cu-dialog">
  59. <view :class="[type === 'bottom' ? '' : 'justify-end pading-left']" class="cu-bar bg-white">
  60. <!-- 普通/对话弹出窗口 -->
  61. <template v-if="type === 'default' || type === 'confirm'">
  62. <view class="content">
  63. <slot name="title">{{ title }}</slot>
  64. </view>
  65. <view @tap="close" class="action"><l-icon type="close" color="red" /></view>
  66. </template>
  67. <!-- 底部弹出窗口 -->
  68. <template v-if="type === 'bottom'">
  69. <slot name="action">
  70. <l-button @click="close" class="action padding-lr" line="red">取消</l-button>
  71. <view class="action padding-lr">{{ title }}</view>
  72. </slot>
  73. </template>
  74. </view>
  75. <view class="padding">
  76. <slot>{{ content }}</slot>
  77. </view>
  78. <!-- 对话弹出窗口的操作区 -->
  79. <template v-if="type === 'confirm'">
  80. <view class="cu-bar bg-white justify-end padding-right">
  81. <view class="action">
  82. <button @tap="close(0)" class="cu-btn line-green text-green">取消</button>
  83. <button @tap="close(1)" class="cu-btn bg-green margin-left">确定</button>
  84. </view>
  85. </view>
  86. </template>
  87. </view>
  88. </view>
  89. </template>
  90. <script>
  91. export default {
  92. name: 'l-modal',
  93. props: {
  94. title: {},
  95. content: {},
  96. value: {},
  97. type: { default: 'default' },
  98. img: {},
  99. range: { default: () => [] },
  100. radio: {},
  101. checkbox: {},
  102. readonly: {},
  103. textField: { default: 'text' },
  104. valueField: { default: 'value' }
  105. },
  106. data() {
  107. return {
  108. radioIndex: undefined,
  109. checkboxIndex: []
  110. }
  111. },
  112. created() {
  113. this.init()
  114. },
  115. methods: {
  116. init() {
  117. if (this.type === 'radio') {
  118. this.radioIndex = this.objectMode
  119. ? this.range.findIndex(t => t[this.valueField] === this.radio)
  120. : this.range.indexOf(this.radio)
  121. } else if (this.type === 'checkbox' && Array.isArray(this.checkbox)) {
  122. this.checkboxIndex = this.checkbox.reduce(
  123. (a, b) =>
  124. a.concat(this.objectMode ? this.range.findIndex(t => t[this.valueField] === b) : this.range.indexOf(b)),
  125. []
  126. )
  127. }
  128. },
  129. close(arg) {
  130. this.$emit('input', false)
  131. this.$emit('close', false)
  132. if (typeof arg === 'number') {
  133. this.$emit(['cancel', 'ok'][arg])
  134. }
  135. if (this.type === 'checkbox') {
  136. if (arg === 0) {
  137. this.checkboxIndex = this.checkbox
  138. } else {
  139. const checkboxValue = this.checkboxIndex.reduce(
  140. (a, b) => a.concat(this.objectMode ? this.range[b][this.valueField] : this.range[b]),
  141. []
  142. )
  143. this.$emit('checkboxChange', checkboxValue)
  144. this.$emit('checkboxIndex', this.checkboxIndex)
  145. }
  146. }
  147. if (typeof arg === 'number') {
  148. this.$emit(['cancel', 'ok'][arg])
  149. }
  150. },
  151. modalClick() {
  152. if (this.type === 'radio' || this.type === 'checkbox') {
  153. this.close()
  154. }
  155. },
  156. radioChange(e) {
  157. if (this.readonly) {
  158. return
  159. }
  160. this.radioIndex = this.objectMode
  161. ? this.range.findIndex(t => t[this.valueField] === e.detail.value)
  162. : this.range.indexOf(e.detail.value)
  163. this.$emit(
  164. 'radioChange',
  165. this.objectMode ? this.range[this.radioIndex][this.valueField] : this.range[this.radioIndex]
  166. )
  167. this.$emit('radioIndex', this.radioIndex)
  168. },
  169. chooseCheckbox(index) {
  170. if (this.readonly) {
  171. return
  172. }
  173. if (this.checkboxIndex.includes(index)) {
  174. this.checkboxIndex = this.checkboxIndex.filter(t => t !== index)
  175. } else {
  176. this.checkboxIndex.push(index)
  177. }
  178. const checkboxValue = this.checkboxIndex.reduce(
  179. (a, b) => a.concat(this.objectMode ? this.range[b][this.valueField] : this.range[b]),
  180. []
  181. )
  182. }
  183. },
  184. watch: {
  185. value(newVal) {
  186. if (newVal) {
  187. this.init()
  188. }
  189. }
  190. },
  191. computed: {
  192. objectMode() {
  193. return typeof this.range[0] === 'object'
  194. }
  195. }
  196. }
  197. </script>