index.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <template>
  2. <div :style="{width}">
  3. <template v-if="!securityConfig.trigger">
  4. <el-input :placeholder="config.placeholder" readonly v-bind="$attrs" :model-value="proxyOtherValue[0].value || modelValue" :style="{width: config.width || '100%'}" :disabled="disabled" @click="openDialog">
  5. <template #append>
  6. <el-button icon="el-icon-search" :disabled="disabled" @click="openDialog"></el-button>
  7. </template>
  8. </el-input>
  9. </template>
  10. <template v-if="securityConfig.trigger === 'button'">
  11. <cip-button type="primary" :disabled="disabled" @click="openDialog">选择({{multiple && (defaultValue?.length || 0)}})</cip-button>
  12. </template>
  13. <cip-dialog
  14. v-model="tableDialog"
  15. :title="`选择${config.label}`"
  16. custom-class="select-input__dialog"
  17. top="6vh"
  18. :on-confirm="onConfirm">
  19. <select-table
  20. :checked-item="checkItem"
  21. :option-props="optionProps"
  22. :hide-index="config.tableHideIndex"
  23. :entity="config.entity"
  24. :curd-fn="config.curdFn"
  25. :table-columns="config.tableColumns"
  26. :search-field-list="config.searchFieldList"
  27. :default-search-filter="config.defaultSearchFilter"
  28. :with-pagination="config.withPagination"
  29. :with-tags="config.withTags"
  30. :check-type="multiple?'checkbox':'radio'"
  31. :hide-search="config.hideSearch"
  32. class="select-input-table-dialog"
  33. @select-value="selectValue">
  34. </select-table>
  35. </cip-dialog>
  36. </div>
  37. </template>
  38. <script>
  39. import CipDialog from '@cip/components/cip-dialog'
  40. import CipButton from '@cip/components/cip-button'
  41. import SelectTable from './components/select-table'
  42. import CipMessage from '@cip/components/cip-message'
  43. import { ElInput, ElButton } from 'element-plus'
  44. import { computed, ref } from 'vue'
  45. import { formInputProps, fromInputEmits } from '../../form-input-props'
  46. import { useFormInput } from '@cip/components/hooks/form-input'
  47. import { isArray } from '@cip/utils/util'
  48. export default {
  49. components: { ElInput, ElButton, CipDialog, CipButton, SelectTable },
  50. props: formInputProps,
  51. emits: [...fromInputEmits],
  52. setup (props, context) {
  53. const { emitInput, emitOtherValue, proxyOtherValue, securityConfig, updateStream, ...formInput } = useFormInput(props, context, {
  54. fromModelValue: () => {},
  55. maxOtherKey: 2
  56. })
  57. const multiple = computed(() => {
  58. return securityConfig.value.multiple ?? false
  59. })
  60. const optionProps = computed(() => {
  61. return Object.assign({},
  62. { label: 'label', value: 'value' },
  63. securityConfig.value.defaultProp, // 兼容历史数据
  64. securityConfig.value.optionProps
  65. )
  66. })
  67. const tableDialog = ref(false)
  68. // 打开选择弹框
  69. const openDialog = () => {
  70. checkItem.value = multiple.value ? [...defaultValue.value] : { ...defaultValue.value }
  71. tableDialog.value = true
  72. }
  73. const getEmitValue = (type) => { // {'value'| 'label'}
  74. const rows = checkItem.value
  75. if (multiple.value) {
  76. let modelValue = rows.map(i => i[optionProps.value[type]])
  77. if (!securityConfig.value.array) {
  78. modelValue = modelValue.join(',')
  79. }
  80. return modelValue
  81. } else {
  82. return rows[optionProps.value[type]]
  83. }
  84. }
  85. // 确认保存
  86. const onConfirm = async (resolve, reject) => {
  87. if (securityConfig.value.validate) {
  88. const { valid, message = '校验失败' } = await securityConfig.value.validate?.(checkItem.value)
  89. if (!valid) {
  90. CipMessage.warning(message)
  91. reject()
  92. }
  93. }
  94. const value = getEmitValue('value') // multiple.value ? rows.map(i => i[optionProps.value.value]).join(',') : rows[optionProps.value.value]
  95. const label = getEmitValue('label') // multiple.value ? rows.map(i => i[optionProps.value.label]).join(',') : rows[optionProps.value.label]
  96. // emitInput(value)
  97. updateStream.appendValue(value)
  98. updateStream.appendOtherValue(label)
  99. // proxyOtherValue[0].value = label
  100. updateStream.appendOtherValue(checkItem.value, 2)
  101. // proxyOtherValue[1].value = checkItem.value
  102. updateStream.end()
  103. resolve()
  104. }
  105. const fromModel = (val) => {
  106. const result = []
  107. if (val) {
  108. if (isArray(val)) {
  109. return val
  110. } else {
  111. return val.split(',')
  112. }
  113. }
  114. return result
  115. }
  116. // 选择table组件
  117. const defaultValue = computed({
  118. get () {
  119. if (multiple.value) {
  120. if (proxyOtherValue[1].value) return proxyOtherValue[1].value
  121. let code = fromModel(props.modelValue)
  122. if (securityConfig.value.valueType === 'number') code = code.map(v => Number(v))
  123. const name = fromModel(proxyOtherValue[0].value) // 没有这个数据怎么办
  124. return code.map((i, idx) => ({
  125. [optionProps.value.value]: i,
  126. [optionProps.value.label]: name[idx]
  127. }))
  128. } else {
  129. return {
  130. [optionProps.value.value]: props.modelValue,
  131. [optionProps.value.label]: proxyOtherValue[0].value
  132. }
  133. }
  134. }
  135. })
  136. const checkItem = ref()
  137. const selectValue = async (val) => {
  138. checkItem.value = val
  139. }
  140. return {
  141. ...formInput,
  142. securityConfig,
  143. proxyOtherValue,
  144. multiple,
  145. optionProps,
  146. tableDialog,
  147. defaultValue,
  148. openDialog,
  149. onConfirm,
  150. checkItem,
  151. selectValue
  152. }
  153. }
  154. }
  155. </script>
  156. <style lang="less">
  157. .select-input-table-dialog{
  158. .dialog-tags{
  159. flex-basis: 220px;
  160. }
  161. }
  162. .select-input__dialog{
  163. .el-dialog__body{
  164. padding: 0;
  165. }
  166. }
  167. </style>