cascader.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <template>
  2. <div class="oCascader controller" :class="[preview ? '' : 'o-unit']" v-if="widget.type == 'cascader'">
  3. <van-field
  4. :name="widget.model"
  5. v-model="values"
  6. :label="widget.name || '级联选择'"
  7. :required="fileCheck ? false : options.required || false"
  8. :disabled="options.disabled || false"
  9. clearable
  10. readonly
  11. :placeholder="options.placeholder || '请选择'"
  12. :rules="rule"
  13. @click="onClick"
  14. v-if="!preview"
  15. >
  16. <template #right-icon>
  17. <!-- <input type="hidden" v-model="dataModel"> -->
  18. <i class="van-icon van-icon-arrow van-cell__right-icon"></i>
  19. </template>
  20. </van-field>
  21. <van-cell v-else class="preview" :title="widget.name || '级联选择'" :value="previewValue"></van-cell>
  22. <van-popup v-model="showCascader" position="bottom">
  23. <!-- <van-picker
  24. show-toolbar
  25. :columns="columns"
  26. value-key="label"
  27. @confirm="onConfirm"
  28. visible-item-count="4"
  29. @cancel="showCascader = false"
  30. /> -->
  31. <van-cascader
  32. :title="options.placeholder || '请选择'"
  33. :options="columns"
  34. active-color="#01C1B5"
  35. @close="showCascader = false"
  36. @finish="onConfirm"
  37. />
  38. </van-popup>
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. name: 'oCascader',
  44. props: ['widget', 'preview', 'value', 'fileCheck'],
  45. data() {
  46. return {
  47. dataModel: this.widget.options?.defaultValue || [],
  48. values: null,
  49. showCascader: false,
  50. columns: this.widget.options?.options || [],
  51. previewValue: null,
  52. }
  53. },
  54. mounted() {
  55. // 初始化参数
  56. const options = this.widget.options?.options || []
  57. this.columns = this.filterOptions(options)
  58. if(this.value) {
  59. const widget = this.widget
  60. const model = widget.originModel || widget.model
  61. for(let v in this.value) {
  62. if(v == model) {
  63. this.previewValue = this.value[v]
  64. }
  65. }
  66. }
  67. },
  68. methods: {
  69. filterOptions(options) {
  70. let tempList = []
  71. options.forEach(item => {
  72. if(item.children && item.children.length > 0) {
  73. tempList.push({
  74. text: item.label,
  75. value: item.value,
  76. children: this.filterOptions(item.children)
  77. })
  78. } else {
  79. tempList.push({
  80. text: item.label,
  81. value: item.value
  82. })
  83. }
  84. })
  85. return tempList
  86. },
  87. onClick() {
  88. this.showCascader = true
  89. },
  90. onConfirm({ selectedOptions }) {
  91. this.dataModel = selectedOptions.map((option) => option.text).join('/')
  92. // console.log(selectedOptions)
  93. this.values = selectedOptions.map((option) => option.text).join('/')
  94. this.showCascader = false
  95. },
  96. },
  97. computed: {
  98. options() {
  99. return this.widget.options || {}
  100. },
  101. rule() {
  102. let rules = this.widget.rules || []
  103. if(rules && rules.length > 0) {
  104. rules.forEach(item => {
  105. if(item.pattern) {
  106. item.pattern = eval(item.pattern)
  107. }
  108. // 判断是否上传文件
  109. if(this.fileCheck) {
  110. item.required = false
  111. }
  112. });
  113. }
  114. return rules
  115. }
  116. },
  117. watch: {
  118. // dataModel: {
  119. // deep: true,
  120. // handler(newValue) {
  121. // if (newValue !== undefined && newValue !== null) {
  122. // }
  123. // }
  124. // },
  125. }
  126. }
  127. </script>
  128. <style lang='less' scoped>
  129. @import url('./controlCommon.less');
  130. </style>