selectGroup.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <template>
  2. <a-select
  3. :title="title"
  4. v-model="selectedVal"
  5. :collapse-tags="collapseTags"
  6. :placeholder="placeholder"
  7. :allow-create="allowCreate"
  8. :allowClear="allowClear"
  9. :mode="multiple ? 'multiple' : 'default'"
  10. :disabled="disabled"
  11. :filterOption="filterOptionAll"
  12. :remote="remote"
  13. :remote-method="remoteMethod"
  14. :maxTagCount="maxTagCount"
  15. >
  16. <a-select-option v-for="(item, index) in filterOption" :value="item.value" :key="'select' + item.value + index">
  17. {{ item.label }}
  18. </a-select-option>
  19. </a-select>
  20. </template>
  21. <script>
  22. // import { dictionary } from '@/components/service/core/dictionary'
  23. // import { queryParaCascByIdAndParamType } from '@/components/service/core/sysConfig'
  24. import { isArray } from '@/utils/Tools'
  25. import { httpAction, getAction } from '@/api/manage'
  26. export default {
  27. name: 'selectPara',
  28. props: {
  29. code: {
  30. // 字典代码
  31. type: String,
  32. default: '',
  33. },
  34. require: {
  35. type: Boolean,
  36. default() {
  37. return false
  38. },
  39. },
  40. value: {
  41. // v-model绑定值
  42. type: [String, Array, Number, Boolean],
  43. default() {
  44. if (this.multiple) return []
  45. else return ''
  46. },
  47. },
  48. label: {
  49. // label值
  50. type: [String, Array, Number],
  51. default() {
  52. if (this.multiple) {
  53. return []
  54. }
  55. if (!this.multiple) {
  56. return ''
  57. }
  58. },
  59. },
  60. collapseTags: {
  61. // 多选时是否将选中值按文字的形式展示
  62. type: Boolean,
  63. default: false,
  64. },
  65. placeholder: {
  66. type: String,
  67. default: '请选择',
  68. },
  69. options: {
  70. // 外部传入的options 可代替自带的请求项
  71. type: Array,
  72. default() {
  73. return []
  74. },
  75. },
  76. allowCreate: {
  77. // 是否允许创建新条目
  78. type: Boolean,
  79. default: false,
  80. },
  81. defaultFirstOption: {
  82. // 按回车键 选择第一项
  83. type: Boolean,
  84. default: false,
  85. },
  86. allowClear: {
  87. // 选项是否可清除
  88. type: Boolean,
  89. default: true,
  90. },
  91. disabled: {
  92. // 是否禁用
  93. type: Boolean,
  94. default: false,
  95. },
  96. multiple: {
  97. // 是否多选
  98. type: Boolean,
  99. default: false,
  100. },
  101. filterable: {
  102. // 模糊搜索
  103. type: Boolean,
  104. default: false,
  105. },
  106. remote: {
  107. // 远程搜索
  108. type: Boolean,
  109. default: false,
  110. },
  111. remoteMethod: {
  112. // 远程搜索方法
  113. type: Function,
  114. default: () => {
  115. console.error('没有配置远程搜索方法!')
  116. },
  117. },
  118. disabledChange: {
  119. // 禁用change事件
  120. type: Boolean,
  121. default: false,
  122. },
  123. enable: {
  124. // 允许选择的项 为空数组全显示,不为空数组只显示规定的选项
  125. type: Array,
  126. default() {
  127. return []
  128. },
  129. },
  130. casCode: {
  131. // 下级级联参数的code
  132. type: String,
  133. default: '',
  134. },
  135. casVal: {
  136. // 下级参数绑定值
  137. type: [String, Number],
  138. default: '',
  139. },
  140. casLabel: {
  141. // 下级参数绑定label
  142. type: String,
  143. default: '',
  144. },
  145. casOpt: {
  146. // 级联参数options
  147. type: Array,
  148. default() {
  149. return []
  150. },
  151. },
  152. maxTagCount: {
  153. type: Number,
  154. default() {
  155. return 2
  156. },
  157. },
  158. },
  159. data() {
  160. return {
  161. selectOption: [],
  162. visible: false,
  163. label_tmp: null,
  164. }
  165. },
  166. watch: {
  167. options(val) {
  168. if (isArray(val)) {
  169. this.selectOption.splice(0, this.selectOption.length)
  170. this.selectOption.push(...val)
  171. }
  172. },
  173. value(val, oldVal) {
  174. if (!this.valueEquals(val, oldVal)) {
  175. this.selectChange(val)
  176. }
  177. },
  178. },
  179. computed: {
  180. selectedVal: {
  181. get: function () {
  182. return this.value
  183. },
  184. set: function (val) {
  185. this.$emit('input', val)
  186. },
  187. },
  188. filterOption() {
  189. // 过滤后的下拉项
  190. if (this.enable.length == 0) {
  191. return this.selectOption
  192. } else {
  193. return this.selectOption.filter((v) => this.enable.findIndex((item) => item == v.value) > -1)
  194. }
  195. },
  196. title() {
  197. // title提示文字
  198. // if (!this.multiple) {
  199. // return this.filterOption.filter((v) => v.value == this.value).length == 1
  200. // ? this.filterOption.filter((v) => v.value == this.value)[0].label
  201. // : ''
  202. // } else if (this.multiple) {
  203. // return this.filterOption
  204. // .filter((item) => {
  205. // return this.value.findIndex((v) => v == item.value) > -1
  206. // })
  207. // .map((item2) => item2.label)
  208. // }
  209. // if (this.enable.length > 0) {
  210. // return this.filterOption.map((v) => v.label)
  211. // }
  212. },
  213. },
  214. mounted() {
  215. this.$nextTick(() => {
  216. if (this.code && this.options.length == 0) {
  217. // 如果code值不为空且options.lengt==0, 则去请求字典项
  218. this.getOptions()
  219. } else {
  220. // 否则将外部传入的options显示到下拉框中
  221. this.selectOption.splice(0, this.selectOption.length)
  222. this.selectOption.push(...this.options)
  223. this.setDefaultVal(this.selectOption)
  224. }
  225. })
  226. },
  227. methods: {
  228. filterOptionAll(input, option) {
  229. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  230. },
  231. getOptions() {
  232. // 获取字典项
  233. getAction('/sys/dictItem/list', { dictId: this.code, pageSize: 1000, pageNo: 1 }).then((res) => {
  234. if (res.success && isArray(res.result.records)) {
  235. let data = res.result.records
  236. data = data.map((v) => {
  237. return {
  238. ...v,
  239. label: v.itemText,
  240. value: v.itemValue+"",
  241. }
  242. })
  243. if (!this.multiple && !this.require) {
  244. data.unshift({ label: '不限', value: 'unlimited' })
  245. if (this.value == ''|| this.value == null || this.value.length == 0 ) {
  246. this.selectedVal = ['unlimited']
  247. }
  248. } else {
  249. if (this.value == ''|| this.value == null || this.value.length == 0 ) {
  250. this.selectedVal = []
  251. this.$emit('clearValidate', this.selectedVal)
  252. }
  253. }
  254. this.selectOption.splice(0, this.selectOption.length)
  255. this.selectOption.push(...data)
  256. this.setDefaultVal(this.selectOption)
  257. }
  258. })
  259. },
  260. selectChange(val) {
  261. // 选择change事件
  262. if (this.multiple) {
  263. // 多选
  264. if (isArray(val) && val.length == 0) {
  265. this.$emit('update:label', [])
  266. this.emitChange([], [])
  267. return
  268. }
  269. if (isArray(val) && val.length > 0) {
  270. this.label_tmp = val.map((v) => {
  271. let item = this.selectOption.find((n) => {
  272. return n.value == v
  273. })
  274. if (item) {
  275. return item.label
  276. }
  277. })
  278. this.$emit('update:label', this.label_tmp)
  279. this.emitChange(val, this.label_tmp)
  280. }
  281. }
  282. if (!this.multiple) {
  283. // 单选
  284. if (!this.valueEquals(val, this.selectedVal)) return
  285. if (!val) {
  286. this.emitChange('', '', '')
  287. this.$emit('update:label', '')
  288. this.clearCascadeOpt()
  289. return
  290. }
  291. let total = 0
  292. let interval = window.setInterval(() => {
  293. // 定时 解决下级级联参数没有触发change事件的问题
  294. total++
  295. let obj = this.selectOption.find((v) => v.value == val)
  296. if (obj) {
  297. this.$emit('update:label', obj.label)
  298. this.emitChange(this.selectedVal, obj.id, obj.cId)
  299. this.getCascadeOption(obj.id)
  300. window.clearInterval(interval)
  301. }
  302. if (total >= 200) {
  303. // 超过2秒 结束计数
  304. window.clearInterval(interval)
  305. }
  306. }, 10)
  307. }
  308. },
  309. valueEquals(a, b) {
  310. // 比较两个值是否相同
  311. if (a === b) return true
  312. if (!(a instanceof Array)) return false
  313. if (!(b instanceof Array)) return false
  314. if (a.length !== b.length) return false
  315. for (let i = 0; i !== a.length; ++i) {
  316. if (a[i] !== b[i]) return false
  317. }
  318. return true
  319. },
  320. emitChange(...args) {
  321. // 触发外部change方法
  322. if (!this.disabledChange) {
  323. setTimeout(() => {
  324. this.$emit('change', ...args)
  325. }, 1)
  326. }
  327. },
  328. // 获取下级级联参数的options 开始==================
  329. getCascadeOption(id) {
  330. // 获取下级级联参数
  331. if (!this.casCode) return
  332. queryParaCascByIdAndParamType(id, this.casCode).then((res) => {
  333. if (res.data.code == 1000) {
  334. let data = res.data.data
  335. if (isArray(data)) {
  336. data = data.map((item) => {
  337. return {
  338. value: item.valStr,
  339. label: item.name,
  340. ...item,
  341. }
  342. })
  343. this.$emit('update:casOpt', data)
  344. this.clearCascadeVal()
  345. }
  346. }
  347. })
  348. },
  349. clearCascadeOpt() {
  350. // 清空下级级联参数
  351. if (!this.casCode) return
  352. this.$emit('update:casOpt', [])
  353. this.clearCascadeVal()
  354. },
  355. clearCascadeVal() {
  356. // 清空下级参数绑定值
  357. this.$emit('update:casVal', '')
  358. this.$emit('update:casLabel', '')
  359. },
  360. // 获取下级级联参数的options 结束==================
  361. setDefaultVal(options = []) {
  362. // 设置默认值(只有值为空的情况下可以设置默认值)
  363. let def = options.find((v) => v.haveDefault == '1')
  364. if (def) {
  365. if (!this.value && this.value !== 0) {
  366. this.$emit('input', def.value)
  367. this.$emit('update:label', def.name)
  368. }
  369. }
  370. },
  371. },
  372. }
  373. </script>