index.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <template>
  2. <div :style="{width}">
  3. <!--输入框-->
  4. <template v-if="!securityConfig.trigger">
  5. <el-input :placeholder="config.placeholder" readonly v-bind="$attrs" :model-value="proxyOtherValue[0].value || modelValue" :style="{width: config.width || '100%'}" :disabled="disabled" @click="openDialog">
  6. <template #append>
  7. <cip-button :square="true" :icon="Search" :disabled="disabled" @click="openDialog"/>
  8. </template>
  9. </el-input>
  10. </template>
  11. <!--按钮模式-->
  12. <template v-if="securityConfig.trigger === 'button'">
  13. <cip-button type="primary" :disabled="disabled" @click="openDialog">选择({{multiple && (defaultValue?.length || 0)}})</cip-button>
  14. </template>
  15. <!--选择弹窗-->
  16. <cip-dialog
  17. v-model="tableDialog"
  18. :title="`选择${config.label}`"
  19. class="select-input__dialog"
  20. top="6vh"
  21. :on-confirm="onConfirm">
  22. <cip-select-table
  23. style="width: 100%"
  24. v-bind="selectTableProps"
  25. :multiple="multiple"
  26. v-model="cacheSelectItem"
  27. />
  28. </cip-dialog>
  29. </div>
  30. </template>
  31. <script>
  32. import { computed, ref } from 'vue'
  33. import { ElInput } from 'element-plus'
  34. import { Search } from '@element-plus/icons-vue'
  35. import CipDialog from '@cip/components/cip-dialog'
  36. import CipButton from '@cip/components/cip-button'
  37. import CipSelectTable from '@cip/components/cip-select-table'
  38. import CipMessage from '@cip/components/cip-message'
  39. import { formInputProps, fromInputEmits, useFormInput, useInputProps } from '@cip/components/helper/form-input'
  40. import { isArray, isNotEmpty } from '@cip/utils/util'
  41. export default {
  42. components: { ElInput, CipDialog, CipButton, CipSelectTable },
  43. props: formInputProps,
  44. emits: fromInputEmits,
  45. setup (props, context) {
  46. // 转换较为复杂,放弃使用formInput提供的fromModelValue及toModelValue进行modelValue的转换
  47. const {
  48. emitInput,
  49. emitOtherValue,
  50. proxyOtherValue,
  51. securityConfig,
  52. updateStream,
  53. ...formInput
  54. } = useFormInput(props, context, {
  55. fromModelValue: () => {},
  56. maxOtherKey: 2
  57. })
  58. const multiple = computed(() => {
  59. return securityConfig.value.multiple ?? false
  60. })
  61. const optionProps = computed(() => {
  62. return Object.assign({},
  63. { label: 'label', value: 'value' },
  64. securityConfig.value.defaultProp, // 兼容历史数据
  65. securityConfig.value.optionProps
  66. )
  67. })
  68. // cip-select-table的配置
  69. const selectTableProps = useInputProps(props, [
  70. 'direction',
  71. 'multiple',
  72. 'entity',
  73. 'curdFn',
  74. 'tableColumns',
  75. 'searchFieldList',
  76. 'optionProps',
  77. 'hideSearch',
  78. 'defaultSearchModel',
  79. 'withPagination',
  80. 'selectable',
  81. ['tableHideIndex', 'hideIndex'],
  82. ['defaultSearchFilter', 'defaultSearchModel'],
  83. 'tableExpandRender',
  84. 'withTags'
  85. ])
  86. const tableDialog = ref(false)
  87. const cacheSelectItem = ref()
  88. // 打开选择弹框
  89. const openDialog = () => {
  90. if (defaultValue.value) {
  91. // 进行一次浅拷贝,防止修改数据导致值直接变化
  92. cacheSelectItem.value = multiple.value ? [...defaultValue.value] : { ...defaultValue.value }
  93. } else {
  94. // 清理上一次的选中结果
  95. cacheSelectItem.value = multiple.value ? [] : undefined
  96. }
  97. tableDialog.value = true
  98. }
  99. // 获取emit需要的值
  100. const getEmitValue = (type) => { // {'value'| 'label'}
  101. const rows = cacheSelectItem.value
  102. if (multiple.value) {
  103. let modelValue = rows.map(i => i[optionProps.value[type]])
  104. if (!securityConfig.value.array) {
  105. modelValue = modelValue.join(',')
  106. }
  107. return modelValue
  108. } else {
  109. return rows[optionProps.value[type]]
  110. }
  111. }
  112. // 确认保存
  113. const onConfirm = async (resolve, reject) => {
  114. if (securityConfig.value.validate) {
  115. const { valid, message = '校验失败' } = await securityConfig.value.validate?.(cacheSelectItem.value)
  116. if (!valid) {
  117. CipMessage.warning(message)
  118. reject()
  119. }
  120. }
  121. const value = getEmitValue('value')
  122. const label = getEmitValue('label')
  123. updateStream.appendValue(value)
  124. updateStream.appendOtherValue(label)
  125. updateStream.appendOtherValue(cacheSelectItem.value, 2)
  126. updateStream.end()
  127. resolve()
  128. }
  129. const fromModel = (val) => {
  130. const result = []
  131. if (val) {
  132. if (isArray(val)) {
  133. return val
  134. } else {
  135. return val.split(',')
  136. }
  137. }
  138. return result
  139. }
  140. // 选择table组件
  141. const defaultValue = computed(() => {
  142. if (isNotEmpty(props.modelValue)) {
  143. if (multiple.value) {
  144. if (proxyOtherValue[1].value) return proxyOtherValue[1].value
  145. let code = fromModel(props.modelValue)
  146. if (securityConfig.value.valueType === 'number') code = code.map(v => Number(v))
  147. const name = fromModel(proxyOtherValue[0].value) // 没有这个数据怎么办
  148. return code.map((i, idx) => ({
  149. [optionProps.value.value]: i,
  150. [optionProps.value.label]: name[idx]
  151. }))
  152. } else {
  153. return {
  154. [optionProps.value.value]: props.modelValue,
  155. [optionProps.value.label]: proxyOtherValue[0].value
  156. }
  157. }
  158. } else {
  159. return undefined
  160. }
  161. })
  162. return {
  163. ...formInput,
  164. selectTableProps,
  165. securityConfig,
  166. proxyOtherValue,
  167. multiple,
  168. optionProps,
  169. tableDialog,
  170. defaultValue,
  171. openDialog,
  172. onConfirm,
  173. cacheSelectItem,
  174. Search
  175. }
  176. }
  177. }
  178. </script>
  179. <style lang="less">
  180. .select-input-table-dialog{
  181. .dialog-tags{
  182. flex-basis: 220px;
  183. }
  184. }
  185. .select-input__dialog{
  186. .@{elNamespace}-dialog__body{
  187. padding: 0;
  188. }
  189. }
  190. </style>