index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <!-- 级联选择器 -->
  2. <template>
  3. <div class="d-flex" style="width: 100%;">
  4. <div class="mr-2" :class="`${prop.size}Title`">
  5. <span style="color: #777;">{{ item?.label }}</span>
  6. <span v-if="prop.required" style="color: var(--v-error-base);"> *</span>
  7. <!-- <span style="color: #777;"> :</span> -->
  8. </div>
  9. <div style="flex: 1;">
  10. <el-cascader
  11. v-model="value"
  12. :show-all-levels="prop.checkStrictly"
  13. :size="prop.size"
  14. :clearable="item.clearable"
  15. :placeholder="item.placeholder || getPlaceholder()"
  16. :class="{'required': requiredTxt}"
  17. style="width: 100%;"
  18. :props="prop"
  19. :options="item.items"
  20. :collapse-tags="item.collapseTags || false"
  21. :collapse-tags-tooltip="true"
  22. @blur="handleBlur"
  23. @change="handleChange"
  24. ></el-cascader>
  25. <div v-if="!prop.hideDetails" :style="{'display': requiredTxt? 'block' : 'inline-block'}" class="requiredTxt">{{ requiredTxt }}</div>
  26. </div>
  27. </div>
  28. </template>
  29. <script setup>
  30. // import 'element-plus/es/components/cascader-panel/style/css'
  31. // import { ElCascaderPanel } from 'element-plus'
  32. import 'element-plus/es/components/cascader/style/css'
  33. import { ElCascader } from 'element-plus'
  34. import { ref, watch } from 'vue'
  35. defineOptions({ name:'FormUI-el-cascade'})
  36. const props = defineProps({item: Object, modelValue: [String, Number, Object]})
  37. const emit = defineEmits(['update:modelValue', 'change'])
  38. const item = props.item
  39. const prop = {
  40. ...item,
  41. label: item.itemText || 'label',
  42. value: item.itemValue || 'value',
  43. required: item.required || false,
  44. size: item.size || 'large', // 'large' | 'default' | 'small'
  45. multiple: item.multiple || false,
  46. emitPath: item.emitPath || false, // 在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
  47. // checkStrictly: item.checkStrictly || false, // 是否严格的遵守父子节点不互相关联
  48. }
  49. const value = ref()
  50. watch(
  51. () => props.modelValue,
  52. (newVal) => {
  53. value.value = newVal
  54. },
  55. { immediate: true },
  56. { deep: true }
  57. )
  58. const handleChange = (val) => {
  59. value.value = val
  60. handleBlur()
  61. emit('update:modelValue', value.value)
  62. emit('change', value.value)
  63. }
  64. const requiredTxt = ref('')
  65. const handleBlur = () => {
  66. if (prop.required && (value.value === '' || value.value === null || value.value === undefined)) requiredTxt.value = '请选择' + item?.label
  67. else requiredTxt.value = ''
  68. return requiredTxt.value
  69. }
  70. const getPlaceholder = () => {
  71. return prop.required ? item?.label + ' *' : item?.label
  72. }
  73. defineExpose({
  74. handleBlur
  75. })
  76. </script>
  77. <style lang="scss" scoped>
  78. .requiredTxt {
  79. font-size: 12px;
  80. padding: 6px 16px 0;
  81. color: var(--v-error-base)
  82. }
  83. .largeTitle {
  84. line-height: 40px;
  85. }
  86. .defaultTitle {
  87. line-height: 32px;
  88. }
  89. :deep(.icon-circle-close) {
  90. color: #666;
  91. font-size: 22px;
  92. &:hover {
  93. color: #333 !important;
  94. }
  95. }
  96. :deep(.el-input--large) {
  97. font-size: 16px;
  98. color: #000;
  99. }
  100. :deep(.el-cascader-node__label) {
  101. font-weight: normal !important;
  102. }
  103. :deep(.el-input.is-focus) {
  104. box-shadow: 0 0 0 2px var(--v-primary-base, var(--el-color-primary)) inset;
  105. border-radius: 5px;
  106. }
  107. :deep(.el-input__wrapper.is-focus) {
  108. box-shadow: 0 0 0 2px var(--v-primary-base, var(--el-color-primary)) inset;
  109. border-radius: 5px;
  110. &:hover {
  111. box-shadow: 0 0 0 2px var(--v-primary-base, var(--el-color-primary)) inset;
  112. }
  113. }
  114. :deep(.required) {
  115. --el-border-color: var(--v-error-base) !important;
  116. --el-border-color-hover: var(--v-error-base) !important;
  117. .el-input.is-focus {
  118. box-shadow: 0 0 0 2px var(--v-error-base, var(--v-error-base)) inset !important;
  119. border-radius: 5px;
  120. }
  121. .el-input__wrapper.is-focus {
  122. box-shadow: 0 0 0 2px var(--v-error-base, var(--v-error-base)) inset !important;
  123. border-radius: 5px;
  124. &:hover {
  125. box-shadow: 0 0 0 2px var(--v-error-base, var(--v-error-base)) inset !important;
  126. }
  127. }
  128. }
  129. </style>