@weitutech/by-components 1.2.31 → 1.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -78969,8 +78969,8 @@ var pair_number_input_component = normalizeComponent(
78969
78969
  )
78970
78970
 
78971
78971
  /* harmony default export */ var pair_number_input = (pair_number_input_component.exports);
78972
- ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/form/comps/custom-date-picker.vue?vue&type=template&id=78d80522
78973
- var custom_date_pickervue_type_template_id_78d80522_render = function render() {
78972
+ ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/form/comps/custom-date-picker.vue?vue&type=template&id=9d8d406a
78973
+ var custom_date_pickervue_type_template_id_9d8d406a_render = function render() {
78974
78974
  var _vm = this,
78975
78975
  _c = _vm._self._c;
78976
78976
  return _c('div', {
@@ -79040,7 +79040,7 @@ var custom_date_pickervue_type_template_id_78d80522_render = function render() {
79040
79040
  }, [_vm._v(" " + _vm._s(char) + " ")]);
79041
79041
  }) : [_vm._v(_vm._s(_vm.activeShortcutLabel))]], 2) : _vm._e()], 1)], 2);
79042
79042
  };
79043
- var custom_date_pickervue_type_template_id_78d80522_staticRenderFns = [];
79043
+ var custom_date_pickervue_type_template_id_9d8d406a_staticRenderFns = [];
79044
79044
 
79045
79045
  // EXTERNAL MODULE: ./node_modules/moment/moment.js
79046
79046
  var moment = __webpack_require__(9412);
@@ -79051,6 +79051,17 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79051
79051
 
79052
79052
 
79053
79053
 
79054
+ const DEFAULT_FORMAT_BY_TYPE = {
79055
+ daterange: 'YYYY-MM-DD',
79056
+ datetimerange: 'YYYY-MM-DD HH:mm:ss',
79057
+ monthrange: 'YYYY-MM',
79058
+ date: 'YYYY-MM-DD',
79059
+ datetime: 'YYYY-MM-DD HH:mm:ss',
79060
+ month: 'YYYY-MM',
79061
+ year: 'YYYY',
79062
+ week: 'YYYY-MM-DD'
79063
+ };
79064
+ const FORM_FIELD_TYPE = 'customDatePicker';
79054
79065
  /* harmony default export */ var custom_date_pickervue_type_script_lang_js = ({
79055
79066
  name: 'ByCustomDatePicker',
79056
79067
  props: {
@@ -79078,6 +79089,23 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79078
79089
  type: String,
79079
79090
  default: ''
79080
79091
  },
79092
+ /**
79093
+ * 日期选择器类型(透传 el-date-picker 的 type)
79094
+ * 默认 daterange;常见:daterange / datetimerange / monthrange
79095
+ * 注意:Form 配置里字段 type 固定为 customDatePicker,请用本属性或 otherOption.type 指定面板类型
79096
+ */
79097
+ pickerType: {
79098
+ type: String,
79099
+ default: ''
79100
+ },
79101
+ /**
79102
+ * 绑定值格式(moment 格式,也兼容 Element 的 yyyy/dd 写法)
79103
+ * 不传时按 pickerType 自动推断,如 daterange → YYYY-MM-DD
79104
+ */
79105
+ valueFormat: {
79106
+ type: String,
79107
+ default: ''
79108
+ },
79081
79109
  /**
79082
79110
  * 快捷按钮展示方式
79083
79111
  * external: 快捷按钮在输入框右侧(默认,保持原有样式)
@@ -79098,43 +79126,81 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79098
79126
  };
79099
79127
  },
79100
79128
  computed: {
79129
+ /** 实际生效的面板类型 */
79130
+ resolvedPickerType() {
79131
+ const fromProp = this.normalizePickerType(this.pickerType);
79132
+ if (fromProp) return fromProp;
79133
+ const fromOther = this.normalizePickerType(this.otherOption && this.otherOption.type);
79134
+ if (fromOther) return fromOther;
79135
+ return 'daterange';
79136
+ },
79137
+ /** 实际生效的输出格式(moment) */
79138
+ resolvedValueFormat() {
79139
+ const raw = this.valueFormat || this.otherOption && this.otherOption.valueFormat || DEFAULT_FORMAT_BY_TYPE[this.resolvedPickerType] || 'YYYY-MM-DD';
79140
+ return this.toMomentDateFormat(raw);
79141
+ },
79142
+ /** 是否包含时分秒(用于快捷项起止时刻) */
79143
+ includesTime() {
79144
+ return /H{1,2}|m{1,2}|s{1,2}/.test(this.resolvedValueFormat);
79145
+ },
79101
79146
  shortcuts() {
79147
+ const fmt = this.resolvedValueFormat;
79148
+ const rangeOfDay = dayMoment => ({
79149
+ start_time: dayMoment.clone().startOf('day').format(fmt),
79150
+ end_time: this.includesTime ? dayMoment.clone().endOf('day').format(fmt) : dayMoment.clone().startOf('day').format(fmt)
79151
+ });
79152
+ const yesterday = rangeOfDay(moment_default()().subtract(1, 'days'));
79153
+ const today = rangeOfDay(moment_default()());
79102
79154
  return [{
79103
79155
  label: '上月',
79104
- start_time: moment_default()().subtract(1, 'months').startOf('month').format('YYYY-MM-DD'),
79105
- end_time: moment_default()().subtract(1, 'months').endOf('month').format('YYYY-MM-DD'),
79156
+ start_time: moment_default()().subtract(1, 'months').startOf('month').format(fmt),
79157
+ end_time: moment_default()().subtract(1, 'months').endOf('month').format(fmt),
79106
79158
  key: 'last_month'
79107
79159
  }, {
79108
79160
  label: '昨天',
79109
- start_time: moment_default()().subtract(1, 'days').format('YYYY-MM-DD'),
79110
- end_time: moment_default()().subtract(1, 'days').format('YYYY-MM-DD'),
79161
+ start_time: yesterday.start_time,
79162
+ end_time: yesterday.end_time,
79111
79163
  key: 'yesterday'
79112
79164
  }, {
79113
79165
  label: '今天',
79114
- start_time: moment_default()().startOf('day').format('YYYY-MM-DD'),
79115
- end_time: moment_default()().startOf('day').format('YYYY-MM-DD'),
79166
+ start_time: today.start_time,
79167
+ end_time: today.end_time,
79116
79168
  key: 'today'
79117
79169
  }, {
79118
79170
  label: '本周',
79119
- start_time: moment_default()().startOf('isoWeek').format('YYYY-MM-DD'),
79120
- end_time: moment_default()().endOf('isoWeek').format('YYYY-MM-DD'),
79171
+ start_time: moment_default()().startOf('isoWeek').format(fmt),
79172
+ end_time: moment_default()().endOf('isoWeek').format(fmt),
79121
79173
  key: 'week'
79122
79174
  }, {
79123
79175
  label: '本月',
79124
- start_time: moment_default()().startOf('month').format('YYYY-MM-DD'),
79125
- end_time: moment_default()().endOf('month').format('YYYY-MM-DD'),
79176
+ start_time: moment_default()().startOf('month').format(fmt),
79177
+ end_time: moment_default()().endOf('month').format(fmt),
79126
79178
  key: 'month'
79127
79179
  }];
79128
79180
  },
79129
79181
  dateOptions() {
79182
+ const {
79183
+ type: _type,
79184
+ valueFormat: _valueFormat,
79185
+ format: userFormat,
79186
+ ...restOther
79187
+ } = this.otherOption || {};
79188
+ const pickerType = this.resolvedPickerType;
79189
+ const elementFormat = this.toElementDateFormat(this.resolvedValueFormat);
79190
+ const needDefaultTime = pickerType === 'datetimerange' || pickerType === 'datetime';
79130
79191
  return {
79131
79192
  startPlaceholder: '开始时间',
79132
79193
  endPlaceholder: '结束时间',
79133
- type: 'daterange',
79134
79194
  rangeSeparator: '至',
79135
79195
  size: 'mini',
79136
79196
  active: '',
79137
- ...this.otherOption
79197
+ format: userFormat || elementFormat,
79198
+ ...(needDefaultTime ? {
79199
+ defaultTime: ['00:00:00', '23:59:59']
79200
+ } : {}),
79201
+ ...restOther,
79202
+ // 最终以解析后的 pickerType 为准,避免 Form 的 type=customDatePicker 或旧配置干扰
79203
+ type: pickerType
79138
79204
  };
79139
79205
  },
79140
79206
  panelDateOptions() {
@@ -79199,10 +79265,25 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79199
79265
  this.destroyShortcutTagObserver();
79200
79266
  },
79201
79267
  methods: {
79268
+ normalizePickerType(type) {
79269
+ if (!type || type === FORM_FIELD_TYPE) return '';
79270
+ return type;
79271
+ },
79272
+ /** Element 格式(yyyy/dd) → moment 格式(YYYY/DD) */
79273
+ toMomentDateFormat(fmt) {
79274
+ return String(fmt).replace(/yyyy/g, 'YYYY').replace(/dd/g, 'DD');
79275
+ },
79276
+ /** moment 格式 → Element 展示格式 */
79277
+ toElementDateFormat(fmt) {
79278
+ return String(fmt).replace(/YYYY/g, 'yyyy').replace(/DD/g, 'dd');
79279
+ },
79280
+ formatMomentValue(val) {
79281
+ return moment_default()(val).format(this.resolvedValueFormat);
79282
+ },
79202
79283
  syncActiveFromValue(newValue) {
79203
79284
  if (Array.isArray(newValue) && newValue.length) {
79204
- const start = moment_default()(newValue[0]).format('YYYY-MM-DD');
79205
- const end = moment_default()(newValue[1]).format('YYYY-MM-DD');
79285
+ const start = this.formatMomentValue(newValue[0]);
79286
+ const end = this.formatMomentValue(newValue[1]);
79206
79287
  let matchedKey = '';
79207
79288
  this.shortcuts.forEach(item => {
79208
79289
  if (item.start_time === start && item.end_time === end) {
@@ -79229,12 +79310,13 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79229
79310
  });
79230
79311
  }
79231
79312
  } else {
79232
- const formattedDates = e.map(item => moment_default()(item).format('YYYY-MM-DD'));
79313
+ const list = Array.isArray(e) ? e : [e];
79314
+ const formattedDates = list.map(item => this.formatMomentValue(item));
79233
79315
  this.$emit('input', formattedDates);
79234
79316
  if (this.startTimeField && this.endTimeField) {
79235
79317
  this.$emit('range-change', {
79236
- startTime: formattedDates[0],
79237
- endTime: formattedDates[1]
79318
+ startTime: formattedDates[0] || '',
79319
+ endTime: formattedDates[1] || ''
79238
79320
  });
79239
79321
  }
79240
79322
 
@@ -79344,8 +79426,8 @@ var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
79344
79426
  ;
79345
79427
  var custom_date_picker_component = normalizeComponent(
79346
79428
  comps_custom_date_pickervue_type_script_lang_js,
79347
- custom_date_pickervue_type_template_id_78d80522_render,
79348
- custom_date_pickervue_type_template_id_78d80522_staticRenderFns,
79429
+ custom_date_pickervue_type_template_id_9d8d406a_render,
79430
+ custom_date_pickervue_type_template_id_9d8d406a_staticRenderFns,
79349
79431
  false,
79350
79432
  null,
79351
79433
  null,
@@ -94686,8 +94768,8 @@ ByDialogService.install = function (Vue) {
94686
94768
  Vue.prototype.$byDialog = ByDialogService;
94687
94769
  };
94688
94770
  /* harmony default export */ var by_dialog_ByDialogService = (ByDialogService);
94689
- ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel/ByCascaderPanel.vue?vue&type=template&id=727f392c
94690
- var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94771
+ ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel/ByCascaderPanel.vue?vue&type=template&id=3691e51e
94772
+ var ByCascaderPanelvue_type_template_id_3691e51e_render = function render() {
94691
94773
  var _vm = this,
94692
94774
  _c = _vm._self._c;
94693
94775
  return _c('div', {
@@ -94706,7 +94788,10 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94706
94788
  }, [_vm._v("可选(" + _vm._s(_vm.selectedCount) + "/" + _vm._s(_vm.totalCount) + ")")]) : _vm._e(), _c('div', {
94707
94789
  staticClass: "search-section"
94708
94790
  }, [_c('div', {
94709
- staticClass: "search-container"
94791
+ staticClass: "search-container",
94792
+ class: {
94793
+ 'has-dropdown-filter': _vm.showDropdownFilter
94794
+ }
94710
94795
  }, [_c('div', {
94711
94796
  staticClass: "search-input-wrap",
94712
94797
  class: {
@@ -94805,7 +94890,37 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94805
94890
  slot: "reference"
94806
94891
  }, [_c('i', {
94807
94892
  staticClass: "el-icon-edit-outline"
94808
- })])], 1)], 1) : _vm._e()], 1), _vm.showRefreshBtn ? _c('el-tooltip', {
94893
+ })])], 1)], 1) : _vm._e()], 1), _vm.showDropdownFilter ? _c('div', {
94894
+ staticClass: "dropdown-filter-group"
94895
+ }, [_vm.dropdownFilterTitle ? _c('span', {
94896
+ staticClass: "dropdown-filter-title"
94897
+ }, [_vm._v(_vm._s(_vm.dropdownFilterTitle) + ":")]) : _vm._e(), _c('el-select', {
94898
+ staticClass: "dropdown-filter-select",
94899
+ attrs: {
94900
+ "placeholder": _vm.dropdownFilterPlaceholder,
94901
+ "clearable": "",
94902
+ "size": "mini",
94903
+ "disabled": _vm.panelViewMode
94904
+ },
94905
+ on: {
94906
+ "change": _vm.handleDropdownFilterChange
94907
+ },
94908
+ model: {
94909
+ value: _vm.dropdownFilterValue,
94910
+ callback: function ($$v) {
94911
+ _vm.dropdownFilterValue = $$v;
94912
+ },
94913
+ expression: "dropdownFilterValue"
94914
+ }
94915
+ }, _vm._l(_vm.normalizedDropdownFilterOptions, function (opt) {
94916
+ return _c('el-option', {
94917
+ key: 'df-' + opt.value,
94918
+ attrs: {
94919
+ "label": opt.label,
94920
+ "value": opt.value
94921
+ }
94922
+ });
94923
+ }), 1)], 1) : _vm._e(), _vm.showRefreshBtn ? _c('el-tooltip', {
94809
94924
  attrs: {
94810
94925
  "content": _vm.refreshTooltip,
94811
94926
  "placement": "top",
@@ -94847,8 +94962,8 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94847
94962
  directives: [{
94848
94963
  name: "show",
94849
94964
  rawName: "v-show",
94850
- value: _vm.searchInput === '' || !_vm.isShowSearch,
94851
- expression: "searchInput === '' || !isShowSearch"
94965
+ value: !_vm.isFilterView,
94966
+ expression: "!isFilterView"
94852
94967
  }],
94853
94968
  ref: "cascaderPanel",
94854
94969
  staticClass: "cascader-panel-inner",
@@ -94864,6 +94979,17 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94864
94979
  "expand-change": _vm.handleExpandChange,
94865
94980
  "change": _vm.handleValueChange
94866
94981
  },
94982
+ scopedSlots: _vm._u([{
94983
+ key: "default",
94984
+ fn: function ({
94985
+ node,
94986
+ data
94987
+ }) {
94988
+ return [_vm._v(" " + _vm._s(node.label)), _vm.showDropdownFilter && _vm.getNodeFilterFieldText(data) ? _c('span', {
94989
+ staticClass: "node-filter-field"
94990
+ }, [_vm._v(_vm._s(_vm.getNodeFilterFieldText(data)))]) : _vm._e()];
94991
+ }
94992
+ }], null, false, 181072543),
94867
94993
  model: {
94868
94994
  value: _vm.mainPanelValue,
94869
94995
  callback: function ($$v) {
@@ -94871,12 +94997,12 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94871
94997
  },
94872
94998
  expression: "mainPanelValue"
94873
94999
  }
94874
- }) : _vm._e(), _vm.searchOptions.length > 0 ? _c('el-cascader-panel', {
95000
+ }) : _vm._e(), _vm.viewOptions.length > 0 ? _c('el-cascader-panel', {
94875
95001
  directives: [{
94876
95002
  name: "show",
94877
95003
  rawName: "v-show",
94878
- value: _vm.searchInput !== '' && _vm.isShowSearch,
94879
- expression: "searchInput !== '' && isShowSearch"
95004
+ value: _vm.isFilterView,
95005
+ expression: "isFilterView"
94880
95006
  }],
94881
95007
  ref: "searchCascaderPanel",
94882
95008
  staticClass: "cascader-panel-inner",
@@ -94885,13 +95011,24 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94885
95011
  },
94886
95012
  attrs: {
94887
95013
  "append-to-body": false,
94888
- "options": _vm.searchOptions,
95014
+ "options": _vm.viewOptions,
94889
95015
  "props": _vm.cascaderProps
94890
95016
  },
94891
95017
  on: {
94892
95018
  "expand-change": _vm.handleExpandChange,
94893
95019
  "change": _vm.handleSearchValueChange
94894
95020
  },
95021
+ scopedSlots: _vm._u([{
95022
+ key: "default",
95023
+ fn: function ({
95024
+ node,
95025
+ data
95026
+ }) {
95027
+ return [_vm._v(" " + _vm._s(node.label)), _vm.showDropdownFilter && _vm.getNodeFilterFieldText(data) ? _c('span', {
95028
+ staticClass: "node-filter-field"
95029
+ }, [_vm._v(_vm._s(_vm.getNodeFilterFieldText(data)))]) : _vm._e()];
95030
+ }
95031
+ }], null, false, 181072543),
94895
95032
  model: {
94896
95033
  value: _vm.searchPanelValue,
94897
95034
  callback: function ($$v) {
@@ -94899,13 +95036,7 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94899
95036
  },
94900
95037
  expression: "searchPanelValue"
94901
95038
  }
94902
- }) : _vm._e(), _vm.isShowSearch && _vm.searchOptions.length === 0 ? _c('div', {
94903
- directives: [{
94904
- name: "show",
94905
- rawName: "v-show",
94906
- value: _vm.searchInput !== '',
94907
- expression: "searchInput !== ''"
94908
- }],
95039
+ }) : _vm._e(), _vm.isFilterView && _vm.viewOptions.length === 0 ? _c('div', {
94909
95040
  staticClass: "empty-search"
94910
95041
  }, [_c('el-empty', {
94911
95042
  attrs: {
@@ -94987,7 +95118,7 @@ var ByCascaderPanelvue_type_template_id_727f392c_render = function render() {
94987
95118
  staticClass: "empty-state"
94988
95119
  }, [_vm._v("暂无选中项")]) : _vm._e()], 2)])])])]);
94989
95120
  };
94990
- var ByCascaderPanelvue_type_template_id_727f392c_staticRenderFns = [];
95121
+ var ByCascaderPanelvue_type_template_id_3691e51e_staticRenderFns = [];
94991
95122
 
94992
95123
  ;// ./src/utils/cascaderUtils.js
94993
95124
 
@@ -95159,6 +95290,58 @@ class CascaderUtils {
95159
95290
  return result;
95160
95291
  }
95161
95292
 
95293
+ /**
95294
+ * 判断节点指定字段是否匹配下拉筛选值
95295
+ * @param {Object} node
95296
+ * @param {String} field
95297
+ * @param {*} filterValue
95298
+ * @returns {Boolean}
95299
+ */
95300
+ static isFilterFieldMatched(node, field, filterValue) {
95301
+ if (!node || !field || filterValue === null || filterValue === undefined || filterValue === '') {
95302
+ return false;
95303
+ }
95304
+ const raw = node[field];
95305
+ if (raw === null || raw === undefined || raw === '') {
95306
+ return false;
95307
+ }
95308
+ return String(raw).trim() === String(filterValue).trim();
95309
+ }
95310
+
95311
+ /**
95312
+ * 按数据字段过滤树:保留字段匹配的节点及其祖先路径
95313
+ * @param {Array} tree - 树形数据
95314
+ * @param {String} field - 数据中用于筛选的字段名
95315
+ * @param {*} filterValue - 下拉选中值
95316
+ * @param {Object} cascaderProps - 级联配置
95317
+ * @returns {Array} 过滤后的树
95318
+ */
95319
+ static filterTreeByField(tree, field, filterValue, cascaderProps) {
95320
+ if (!Array.isArray(tree) || !field || filterValue === null || filterValue === undefined || filterValue === '') {
95321
+ return tree || [];
95322
+ }
95323
+ const childrenKey = cascaderProps && cascaderProps.children || 'children';
95324
+ const result = [];
95325
+ tree.forEach(node => {
95326
+ const children = node[childrenKey];
95327
+ const hasChildren = Array.isArray(children) && children.length > 0;
95328
+ if (hasChildren) {
95329
+ const matchedChildren = this.filterTreeByField(children, field, filterValue, cascaderProps);
95330
+ if (matchedChildren.length > 0) {
95331
+ result.push({
95332
+ ...node,
95333
+ [childrenKey]: matchedChildren
95334
+ });
95335
+ }
95336
+ } else if (this.isFilterFieldMatched(node, field, filterValue)) {
95337
+ result.push({
95338
+ ...node
95339
+ });
95340
+ }
95341
+ });
95342
+ return result;
95343
+ }
95344
+
95162
95345
  /**
95163
95346
  * 获取叶子节点的值
95164
95347
  * @param {Array} tree - 树形数据
@@ -95610,6 +95793,13 @@ class CascaderUtils {
95610
95793
 
95611
95794
 
95612
95795
 
95796
+
95797
+
95798
+
95799
+
95800
+
95801
+
95802
+
95613
95803
  /* harmony default export */ var ByCascaderPanelvue_type_script_lang_js = ({
95614
95804
  name: 'ByCascaderPanel',
95615
95805
  props: {
@@ -95724,6 +95914,15 @@ class CascaderUtils {
95724
95914
  refreshing: {
95725
95915
  type: Boolean,
95726
95916
  default: false
95917
+ },
95918
+ /**
95919
+ * 下拉筛选配置。外部传入且 enabled 不为 false、并指定 field 时才展示下拉框。
95920
+ * { enabled, title, placeholder, options: [{ label, value }], field }
95921
+ * field 为数据中用于过滤和展示的字段名。
95922
+ */
95923
+ dropdownFilter: {
95924
+ type: Object,
95925
+ default: null
95727
95926
  }
95728
95927
  },
95729
95928
  data() {
@@ -95743,7 +95942,9 @@ class CascaderUtils {
95743
95942
  // 防止循环更新的标志
95744
95943
  batchSearchVisible: false,
95745
95944
  // 批量搜索弹窗显示状态
95746
- batchSearchContent: '' // 批量搜索输入内容
95945
+ batchSearchContent: '',
95946
+ // 批量搜索输入内容
95947
+ dropdownFilterValue: '' // 下拉筛选当前值,未开启时不使用
95747
95948
  };
95748
95949
  },
95749
95950
  computed: {
@@ -95816,6 +96017,61 @@ class CascaderUtils {
95816
96017
  this.searchSelectedValues = value ? [value] : [];
95817
96018
  }
95818
96019
  }
96020
+ },
96021
+ // 是否展示下拉筛选(外部有配置且指定了数据字段才展示)
96022
+ showDropdownFilter() {
96023
+ const cfg = this.dropdownFilter;
96024
+ return !!(cfg && typeof cfg === 'object' && cfg.enabled !== false && cfg.field);
96025
+ },
96026
+ dropdownFilterPlaceholder() {
96027
+ return this.dropdownFilter && this.dropdownFilter.placeholder || '请选择';
96028
+ },
96029
+ dropdownFilterTitle() {
96030
+ const title = this.dropdownFilter && this.dropdownFilter.title;
96031
+ return title != null && String(title).trim() !== '' ? String(title).trim() : '';
96032
+ },
96033
+ dropdownFilterField() {
96034
+ return this.dropdownFilter && this.dropdownFilter.field || '';
96035
+ },
96036
+ normalizedDropdownFilterOptions() {
96037
+ const opts = this.dropdownFilter && this.dropdownFilter.options || [];
96038
+ return opts.map(opt => {
96039
+ if (opt != null && typeof opt === 'object') {
96040
+ return {
96041
+ label: opt.label != null ? opt.label : opt.value,
96042
+ value: opt.value != null ? opt.value : opt.label
96043
+ };
96044
+ }
96045
+ return {
96046
+ label: String(opt),
96047
+ value: opt
96048
+ };
96049
+ });
96050
+ },
96051
+ hasActiveDropdownFilter() {
96052
+ return this.showDropdownFilter && this.dropdownFilterValue !== '' && this.dropdownFilterValue !== null && this.dropdownFilterValue !== undefined;
96053
+ },
96054
+ // 下拉筛选后的展示树;未筛选时等于完整 processed 树,保证原有逻辑不变
96055
+ displayOptions() {
96056
+ if (!this.hasActiveDropdownFilter) {
96057
+ return this.filteredOptions;
96058
+ }
96059
+ return CascaderUtils.filterTreeByField(this.filteredOptions, this.dropdownFilterField, this.dropdownFilterValue, this.cascaderProps);
96060
+ },
96061
+ isFilterView() {
96062
+ if (this.searchInput !== '' && this.isShowSearch) {
96063
+ return true;
96064
+ }
96065
+ return this.hasActiveDropdownFilter;
96066
+ },
96067
+ viewOptions() {
96068
+ if (this.searchInput !== '' && this.isShowSearch) {
96069
+ return this.searchOptions;
96070
+ }
96071
+ if (this.hasActiveDropdownFilter) {
96072
+ return this.displayOptions;
96073
+ }
96074
+ return [];
95819
96075
  }
95820
96076
  },
95821
96077
  watch: {
@@ -95855,6 +96111,9 @@ class CascaderUtils {
95855
96111
  // 普通模式下的全选判断
95856
96112
  this.isAllSelected = this.selectedCount === this.totalCount;
95857
96113
  }
96114
+ if (this.hasActiveDropdownFilter) {
96115
+ this.updateFilterAllSelectedState();
96116
+ }
95858
96117
  } else {
95859
96118
  // 单选模式:最多只能有一个选中项
95860
96119
  if (newVal.length > 1) {
@@ -95871,6 +96130,11 @@ class CascaderUtils {
95871
96130
  if (val) {
95872
96131
  this.batchSearchVisible = false;
95873
96132
  }
96133
+ },
96134
+ showDropdownFilter(val) {
96135
+ if (!val) {
96136
+ this.dropdownFilterValue = '';
96137
+ }
95874
96138
  }
95875
96139
  },
95876
96140
  mounted() {
@@ -95942,6 +96206,11 @@ class CascaderUtils {
95942
96206
  this.filteredOptions = this.processOptions(this.options);
95943
96207
  this.countTotalItems();
95944
96208
  this.updateSelectedItems();
96209
+ if (this.searchInput) {
96210
+ this.handleSearch();
96211
+ } else if (this.hasActiveDropdownFilter) {
96212
+ this.syncFilterViewSelection();
96213
+ }
95945
96214
  },
95946
96215
  // 处理选项数据,添加禁用状态
95947
96216
  processOptions(options) {
@@ -96030,10 +96299,14 @@ class CascaderUtils {
96030
96299
  this.searchInput = this.searchInput.trim();
96031
96300
  if (this.searchInput === '') {
96032
96301
  this.isShowSearch = false;
96302
+ this.searchOptions = [];
96303
+ if (this.hasActiveDropdownFilter) {
96304
+ this.syncFilterViewSelection();
96305
+ }
96033
96306
  return;
96034
96307
  }
96035
96308
  this.isShowSearch = false;
96036
- this.searchOptions = CascaderUtils.searchInTree(this.filteredOptions, this.searchInput, this.cascaderProps);
96309
+ this.searchOptions = CascaderUtils.searchInTree(this.displayOptions, this.searchInput, this.cascaderProps);
96037
96310
 
96038
96311
  // 只设置搜索范围内的选中值
96039
96312
  this.searchSelectedValues = CascaderUtils.getSearchSelectedValues(this.selectedValues, this.searchOptions, this.cascaderProps);
@@ -96070,7 +96343,7 @@ class CascaderUtils {
96070
96343
  handleExpandChange(values = []) {
96071
96344
  if (values.length === 1) {
96072
96345
  this.$nextTick(() => {
96073
- const panel = this.$refs.cascaderPanel || this.$refs.searchCascaderPanel;
96346
+ const panel = this.isFilterView ? this.$refs.searchCascaderPanel || this.$refs.cascaderPanel : this.$refs.cascaderPanel || this.$refs.searchCascaderPanel;
96074
96347
  if (panel) {
96075
96348
  const menus = panel.menus;
96076
96349
  const targetNode = menus[0].find(node => node.value == values[0]);
@@ -96110,15 +96383,15 @@ class CascaderUtils {
96110
96383
  this.$emit('input', emitValue);
96111
96384
  });
96112
96385
  },
96113
- // 搜索模式值变化处理
96386
+ // 搜索 / 下拉筛选视图值变化处理
96114
96387
  handleSearchValueChange(value) {
96115
- // 获取搜索面板中所有可能的叶子节点值
96116
- const searchLeafValues = CascaderUtils.getLeafValues(this.searchOptions, this.cascaderProps);
96388
+ // 获取当前筛选/搜索视图中所有可能的叶子节点值
96389
+ const viewLeafValues = CascaderUtils.getLeafValues(this.viewOptions, this.cascaderProps);
96117
96390
  if (this.isMultiple) {
96118
- // 多选模式:从主选择列表中移除搜索范围内的项,然后添加搜索面板中选中的项
96391
+ // 多选模式:从主选择列表中移除视图范围内的项,然后添加视图中选中的项
96119
96392
  this.selectedValues = this.selectedValues.filter(path => {
96120
96393
  const leafValue = path[path.length - 1];
96121
- return !searchLeafValues.includes(leafValue);
96394
+ return !viewLeafValues.includes(leafValue);
96122
96395
  });
96123
96396
  this.selectedValues = [...this.selectedValues, ...this.searchSelectedValues];
96124
96397
  } else {
@@ -96188,15 +96461,26 @@ class CascaderUtils {
96188
96461
  // 单选模式下不支持全选
96189
96462
  return;
96190
96463
  }
96191
- if (this.isAllSelected) {
96464
+ const config = {
96465
+ disabledField: this.disabledField,
96466
+ disabledValue: this.disabledValue,
96467
+ disabledCheck: this.disabledCheck
96468
+ };
96469
+ if (this.hasActiveDropdownFilter) {
96470
+ const viewPaths = CascaderUtils.getAllLeafPaths(this.displayOptions, config, this.cascaderProps);
96471
+ const viewLeafSet = new Set(viewPaths.map(path => path[path.length - 1]));
96472
+ if (this.isAllSelected) {
96473
+ this.selectedValues = this.selectedValues.filter(path => !viewLeafSet.has(path[path.length - 1]));
96474
+ } else {
96475
+ const preserved = this.selectedValues.filter(path => !viewLeafSet.has(path[path.length - 1]));
96476
+ this.selectedValues = [...preserved, ...viewPaths];
96477
+ }
96478
+ this.searchSelectedValues = CascaderUtils.getSearchSelectedValues(this.selectedValues, this.viewOptions, this.cascaderProps);
96479
+ this.updateSelectedItems();
96480
+ } else if (this.isAllSelected) {
96192
96481
  this.selectedValues = [];
96193
96482
  this.selectedItems = [];
96194
96483
  } else {
96195
- const config = {
96196
- disabledField: this.disabledField,
96197
- disabledValue: this.disabledValue,
96198
- disabledCheck: this.disabledCheck
96199
- };
96200
96484
  // 无论是普通模式还是聚合模式,全选时都选择所有可选的叶子节点
96201
96485
  this.selectedValues = CascaderUtils.getAllLeafPaths(this.filteredOptions, config, this.cascaderProps);
96202
96486
  this.updateSelectedItems();
@@ -96349,6 +96633,54 @@ class CascaderUtils {
96349
96633
  }
96350
96634
  this.$emit('refresh');
96351
96635
  },
96636
+ getNodeFilterFieldText(data) {
96637
+ if (!this.showDropdownFilter || !this.dropdownFilterField || !data) {
96638
+ return '';
96639
+ }
96640
+ const val = data[this.dropdownFilterField];
96641
+ if (val === null || val === undefined || val === '') {
96642
+ return '';
96643
+ }
96644
+ return `(${val})`;
96645
+ },
96646
+ updateFilterAllSelectedState() {
96647
+ if (!this.hasActiveDropdownFilter) {
96648
+ return;
96649
+ }
96650
+ const config = {
96651
+ disabledField: this.disabledField,
96652
+ disabledValue: this.disabledValue,
96653
+ disabledCheck: this.disabledCheck
96654
+ };
96655
+ const viewPaths = CascaderUtils.getAllLeafPaths(this.displayOptions, config, this.cascaderProps);
96656
+ if (viewPaths.length === 0) {
96657
+ this.isAllSelected = false;
96658
+ return;
96659
+ }
96660
+ const selectedLeafSet = new Set(this.selectedValues.map(path => path[path.length - 1]));
96661
+ this.isAllSelected = viewPaths.every(path => selectedLeafSet.has(path[path.length - 1]));
96662
+ },
96663
+ syncFilterViewSelection() {
96664
+ this.searchSelectedValues = CascaderUtils.getSearchSelectedValues(this.selectedValues, this.viewOptions, this.cascaderProps);
96665
+ this.$nextTick(() => {
96666
+ if (this.viewOptions.length > 0) {
96667
+ this.handleSearchExpand();
96668
+ }
96669
+ });
96670
+ },
96671
+ handleDropdownFilterChange() {
96672
+ if (this.searchInput) {
96673
+ this.handleSearch();
96674
+ return;
96675
+ }
96676
+ this.isShowSearch = false;
96677
+ this.searchOptions = [];
96678
+ if (this.hasActiveDropdownFilter) {
96679
+ this.syncFilterViewSelection();
96680
+ } else {
96681
+ this.searchSelectedValues = [];
96682
+ }
96683
+ },
96352
96684
  // 处理批量搜索
96353
96685
  handleBatchSearch() {
96354
96686
  if (!this.batchSearchContent.trim()) {
@@ -96471,8 +96803,8 @@ class CascaderUtils {
96471
96803
  ;
96472
96804
  var ByCascaderPanel_component = normalizeComponent(
96473
96805
  cascader_panel_ByCascaderPanelvue_type_script_lang_js,
96474
- ByCascaderPanelvue_type_template_id_727f392c_render,
96475
- ByCascaderPanelvue_type_template_id_727f392c_staticRenderFns,
96806
+ ByCascaderPanelvue_type_template_id_3691e51e_render,
96807
+ ByCascaderPanelvue_type_template_id_3691e51e_staticRenderFns,
96476
96808
  false,
96477
96809
  null,
96478
96810
  null,
@@ -96481,8 +96813,8 @@ var ByCascaderPanel_component = normalizeComponent(
96481
96813
  )
96482
96814
 
96483
96815
  /* harmony default export */ var ByCascaderPanel = (ByCascaderPanel_component.exports);
96484
- ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel-pro/ByCascaderPanelPro.vue?vue&type=template&id=961f637e
96485
- var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96816
+ ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel-pro/ByCascaderPanelPro.vue?vue&type=template&id=21ca97ff
96817
+ var ByCascaderPanelProvue_type_template_id_21ca97ff_render = function render() {
96486
96818
  var _vm = this,
96487
96819
  _c = _vm._self._c;
96488
96820
  return _c('div', {
@@ -96501,7 +96833,10 @@ var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96501
96833
  }, [_vm._v("可选(" + _vm._s(_vm.selectedCount) + "/" + _vm._s(_vm.totalCount) + ")")]) : _vm._e(), _c('div', {
96502
96834
  staticClass: "search-section"
96503
96835
  }, [_c('div', {
96504
- staticClass: "search-container"
96836
+ staticClass: "search-container",
96837
+ class: {
96838
+ 'has-dropdown-filter': _vm.showDropdownFilter
96839
+ }
96505
96840
  }, [_c('div', {
96506
96841
  staticClass: "search-input-wrap",
96507
96842
  class: {
@@ -96597,7 +96932,37 @@ var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96597
96932
  slot: "reference"
96598
96933
  }, [_c('i', {
96599
96934
  staticClass: "el-icon-edit-outline"
96600
- })])], 1)], 1) : _vm._e()], 1), _vm.showRefreshBtn ? _c('el-tooltip', {
96935
+ })])], 1)], 1) : _vm._e()], 1), _vm.showDropdownFilter ? _c('div', {
96936
+ staticClass: "dropdown-filter-group"
96937
+ }, [_vm.dropdownFilterTitle ? _c('span', {
96938
+ staticClass: "dropdown-filter-title"
96939
+ }, [_vm._v(_vm._s(_vm.dropdownFilterTitle) + ":")]) : _vm._e(), _c('el-select', {
96940
+ staticClass: "dropdown-filter-select",
96941
+ attrs: {
96942
+ "placeholder": _vm.dropdownFilterPlaceholder,
96943
+ "clearable": "",
96944
+ "size": "mini",
96945
+ "disabled": _vm.panelViewMode
96946
+ },
96947
+ on: {
96948
+ "change": _vm.handleDropdownFilterChange
96949
+ },
96950
+ model: {
96951
+ value: _vm.dropdownFilterValue,
96952
+ callback: function ($$v) {
96953
+ _vm.dropdownFilterValue = $$v;
96954
+ },
96955
+ expression: "dropdownFilterValue"
96956
+ }
96957
+ }, _vm._l(_vm.normalizedDropdownFilterOptions, function (opt) {
96958
+ return _c('el-option', {
96959
+ key: 'df-' + opt.value,
96960
+ attrs: {
96961
+ "label": opt.label,
96962
+ "value": opt.value
96963
+ }
96964
+ });
96965
+ }), 1)], 1) : _vm._e(), _vm.showRefreshBtn ? _c('el-tooltip', {
96601
96966
  attrs: {
96602
96967
  "content": _vm.refreshTooltip,
96603
96968
  "placement": "top",
@@ -96638,8 +97003,8 @@ var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96638
97003
  directives: [{
96639
97004
  name: "show",
96640
97005
  rawName: "v-show",
96641
- value: _vm.searchInput === '' || !_vm.isShowSearch,
96642
- expression: "searchInput === '' || !isShowSearch"
97006
+ value: !_vm.isFilterView,
97007
+ expression: "!isFilterView"
96643
97008
  }],
96644
97009
  ref: "cascaderPanel",
96645
97010
  staticClass: "cascader-panel-inner",
@@ -96655,44 +97020,41 @@ var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96655
97020
  "column-min-width": _vm.columnMinWidth,
96656
97021
  "column-max-width": _vm.columnMaxWidth,
96657
97022
  "disabled-config": _vm.disabledConfig,
96658
- "is-view-mode": _vm.panelViewMode
97023
+ "is-view-mode": _vm.panelViewMode,
97024
+ "filter-field": _vm.showDropdownFilter ? _vm.dropdownFilterField : ''
96659
97025
  },
96660
97026
  on: {
96661
97027
  "input": _vm.onMainPanelInput,
96662
97028
  "change": _vm.handleValueChange,
96663
97029
  "store-ready": _vm.schedulePanelSyncFromExternalValue
96664
97030
  }
96665
- }) : _vm._e(), _vm.searchOptions.length > 0 ? _c('VirtualCascaderPanel', {
97031
+ }) : _vm._e(), _vm.viewOptions.length > 0 ? _c('VirtualCascaderPanel', {
96666
97032
  directives: [{
96667
97033
  name: "show",
96668
97034
  rawName: "v-show",
96669
- value: _vm.searchInput !== '' && _vm.isShowSearch,
96670
- expression: "searchInput !== '' && isShowSearch"
97035
+ value: _vm.isFilterView,
97036
+ expression: "isFilterView"
96671
97037
  }],
96672
97038
  ref: "searchCascaderPanel",
96673
97039
  staticClass: "cascader-panel-inner",
96674
97040
  attrs: {
96675
97041
  "value": _vm.compactSearchPanelValue,
96676
97042
  "sync-value-from-parent": false,
96677
- "options": _vm.searchOptions,
97043
+ "options": _vm.viewOptions,
96678
97044
  "props": _vm.cascaderProps,
96679
97045
  "height": _vm.computedPanelHeight - 20,
96680
97046
  "column-min-width": _vm.columnMinWidth,
96681
97047
  "column-max-width": _vm.columnMaxWidth,
96682
97048
  "disabled-config": _vm.disabledConfig,
96683
- "is-view-mode": _vm.panelViewMode
97049
+ "is-view-mode": _vm.panelViewMode,
97050
+ "filter-field": _vm.showDropdownFilter ? _vm.dropdownFilterField : ''
96684
97051
  },
96685
97052
  on: {
96686
97053
  "input": _vm.onSearchPanelInput,
96687
- "change": _vm.handleSearchValueChange
97054
+ "change": _vm.handleSearchValueChange,
97055
+ "store-ready": _vm.syncSearchPanelSelection
96688
97056
  }
96689
- }) : _vm._e(), _vm.isShowSearch && _vm.searchOptions.length === 0 ? _c('div', {
96690
- directives: [{
96691
- name: "show",
96692
- rawName: "v-show",
96693
- value: _vm.searchInput !== '',
96694
- expression: "searchInput !== ''"
96695
- }],
97057
+ }) : _vm._e(), _vm.isFilterView && _vm.viewOptions.length === 0 ? _c('div', {
96696
97058
  staticClass: "empty-search"
96697
97059
  }, [_c('el-empty', {
96698
97060
  attrs: {
@@ -96763,7 +97125,7 @@ var ByCascaderPanelProvue_type_template_id_961f637e_render = function render() {
96763
97125
  staticClass: "empty-state"
96764
97126
  }, [_vm._v("暂无选中项")])], 1)])])])]);
96765
97127
  };
96766
- var ByCascaderPanelProvue_type_template_id_961f637e_staticRenderFns = [];
97128
+ var ByCascaderPanelProvue_type_template_id_21ca97ff_staticRenderFns = [];
96767
97129
 
96768
97130
  ;// ./src/components/cascader-panel-pro/cascaderStorePro.js
96769
97131
 
@@ -97055,14 +97417,22 @@ class CascaderUtilsPro {
97055
97417
  minWidth = 180,
97056
97418
  maxWidth = 420,
97057
97419
  extraPadding = 56,
97058
- hasCheckbox = true
97420
+ hasCheckbox = true,
97421
+ filterField = ''
97059
97422
  } = options;
97060
97423
  if (!nodes || nodes.length === 0) {
97061
97424
  return minWidth;
97062
97425
  }
97063
97426
  let maxLabelWidth = 0;
97064
97427
  nodes.forEach(node => {
97065
- maxLabelWidth = Math.max(maxLabelWidth, this.measureCascaderLabelWidth(node.label));
97428
+ let text = node.label || '';
97429
+ if (filterField) {
97430
+ const extra = node.raw && node.raw[filterField];
97431
+ if (extra !== null && extra !== undefined && extra !== '') {
97432
+ text += ` (${extra})`;
97433
+ }
97434
+ }
97435
+ maxLabelWidth = Math.max(maxLabelWidth, this.measureCascaderLabelWidth(text));
97066
97436
  });
97067
97437
  const checkboxWidth = hasCheckbox ? 28 : 0;
97068
97438
  const arrowWidth = 24;
@@ -97221,6 +97591,58 @@ class CascaderUtilsPro {
97221
97591
  return result;
97222
97592
  }
97223
97593
 
97594
+ /**
97595
+ * 判断节点指定字段是否匹配下拉筛选值
97596
+ * @param {Object} node
97597
+ * @param {String} field
97598
+ * @param {*} filterValue
97599
+ * @returns {Boolean}
97600
+ */
97601
+ static isFilterFieldMatched(node, field, filterValue) {
97602
+ if (!node || !field || filterValue === null || filterValue === undefined || filterValue === '') {
97603
+ return false;
97604
+ }
97605
+ const raw = node[field];
97606
+ if (raw === null || raw === undefined || raw === '') {
97607
+ return false;
97608
+ }
97609
+ return String(raw).trim() === String(filterValue).trim();
97610
+ }
97611
+
97612
+ /**
97613
+ * 按数据字段过滤树:保留字段匹配的节点及其祖先路径
97614
+ * @param {Array} tree - 树形数据
97615
+ * @param {String} field - 数据中用于筛选的字段名
97616
+ * @param {*} filterValue - 下拉选中值
97617
+ * @param {Object} cascaderProps - 级联配置
97618
+ * @returns {Array} 过滤后的树
97619
+ */
97620
+ static filterTreeByField(tree, field, filterValue, cascaderProps) {
97621
+ if (!Array.isArray(tree) || !field || filterValue === null || filterValue === undefined || filterValue === '') {
97622
+ return tree || [];
97623
+ }
97624
+ const childrenKey = cascaderProps && cascaderProps.children || 'children';
97625
+ const result = [];
97626
+ tree.forEach(node => {
97627
+ const children = node[childrenKey];
97628
+ const hasChildren = Array.isArray(children) && children.length > 0;
97629
+ if (hasChildren) {
97630
+ const matchedChildren = this.filterTreeByField(children, field, filterValue, cascaderProps);
97631
+ if (matchedChildren.length > 0) {
97632
+ result.push({
97633
+ ...node,
97634
+ [childrenKey]: matchedChildren
97635
+ });
97636
+ }
97637
+ } else if (this.isFilterFieldMatched(node, field, filterValue)) {
97638
+ result.push({
97639
+ ...node
97640
+ });
97641
+ }
97642
+ });
97643
+ return result;
97644
+ }
97645
+
97224
97646
  /**
97225
97647
  * 基于扁平 store 快速搜索(父节点命中时直接复用 raw 子树,跳过子级遍历)
97226
97648
  */
@@ -97764,8 +98186,8 @@ class CascaderUtilsPro {
97764
98186
  return paths;
97765
98187
  }
97766
98188
  }
97767
- ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel-pro/VirtualCascaderPanel.vue?vue&type=template&id=05f77638
97768
- var VirtualCascaderPanelvue_type_template_id_05f77638_render = function render() {
98189
+ ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel-pro/VirtualCascaderPanel.vue?vue&type=template&id=7d8ff846
98190
+ var VirtualCascaderPanelvue_type_template_id_7d8ff846_render = function render() {
97769
98191
  var _vm = this,
97770
98192
  _c = _vm._self._c;
97771
98193
  return _c('div', {
@@ -97846,7 +98268,9 @@ var VirtualCascaderPanelvue_type_template_id_05f77638_render = function render()
97846
98268
  }
97847
98269
  }, [_c('span')])], 1) : _vm._e(), _c('span', {
97848
98270
  staticClass: "el-cascader-node__label"
97849
- }, [_vm._v(_vm._s(item.label))]), !item.isLeaf ? _c('span', {
98271
+ }, [_vm.filterField ? [_vm._v(" " + _vm._s(item.label)), _vm.getFilterFieldText(item) ? _c('span', {
98272
+ staticClass: "node-filter-field"
98273
+ }, [_vm._v(_vm._s(_vm.getFilterFieldText(item)))]) : _vm._e()] : [_vm._v(_vm._s(item.label))]], 2), !item.isLeaf ? _c('span', {
97850
98274
  staticClass: "el-cascader-node__postfix"
97851
98275
  }, [_c('i', {
97852
98276
  staticClass: "el-icon-arrow-right el-cascader-node__icon-arrow"
@@ -97856,7 +98280,7 @@ var VirtualCascaderPanelvue_type_template_id_05f77638_render = function render()
97856
98280
  })], 1);
97857
98281
  }), 0);
97858
98282
  };
97859
- var VirtualCascaderPanelvue_type_template_id_05f77638_staticRenderFns = [];
98283
+ var VirtualCascaderPanelvue_type_template_id_7d8ff846_staticRenderFns = [];
97860
98284
 
97861
98285
  ;// ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"185687ec-vue-loader-template"}!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/cascader-panel-pro/VirtualList.vue?vue&type=template&id=43cb1148
97862
98286
  var VirtualListvue_type_template_id_43cb1148_render = function render() {
@@ -98340,6 +98764,11 @@ class SelectionStatePro {
98340
98764
  syncValueFromParent: {
98341
98765
  type: Boolean,
98342
98766
  default: true
98767
+ },
98768
+ // 下拉筛选字段名:有值时在节点名称后展示该字段内容
98769
+ filterField: {
98770
+ type: String,
98771
+ default: ''
98343
98772
  }
98344
98773
  },
98345
98774
  data() {
@@ -98456,7 +98885,8 @@ class SelectionStatePro {
98456
98885
  const width = CascaderUtilsPro.getCascaderColumnWidth(columnNodes, {
98457
98886
  minWidth: this.columnMinWidth,
98458
98887
  maxWidth: this.columnMaxWidth,
98459
- hasCheckbox: this.multiple || this.checkStrictly
98888
+ hasCheckbox: this.multiple || this.checkStrictly,
98889
+ filterField: this.filterField
98460
98890
  });
98461
98891
  return {
98462
98892
  width: width + 'px',
@@ -98464,6 +98894,17 @@ class SelectionStatePro {
98464
98894
  maxWidth: width + 'px'
98465
98895
  };
98466
98896
  },
98897
+ getFilterFieldText(item) {
98898
+ if (!this.filterField || !item) {
98899
+ return '';
98900
+ }
98901
+ const raw = item.raw || item;
98902
+ const val = raw[this.filterField];
98903
+ if (val === null || val === undefined || val === '') {
98904
+ return '';
98905
+ }
98906
+ return `(${val})`;
98907
+ },
98467
98908
  rebuildStore() {
98468
98909
  this.store = buildCascaderStore(this.options, this.disabledConfig, this.props, CascaderUtilsPro);
98469
98910
  this.selection = new SelectionStatePro(this.store);
@@ -98773,8 +99214,8 @@ class SelectionStatePro {
98773
99214
  ;
98774
99215
  var VirtualCascaderPanel_component = normalizeComponent(
98775
99216
  cascader_panel_pro_VirtualCascaderPanelvue_type_script_lang_js,
98776
- VirtualCascaderPanelvue_type_template_id_05f77638_render,
98777
- VirtualCascaderPanelvue_type_template_id_05f77638_staticRenderFns,
99217
+ VirtualCascaderPanelvue_type_template_id_7d8ff846_render,
99218
+ VirtualCascaderPanelvue_type_template_id_7d8ff846_staticRenderFns,
98778
99219
  false,
98779
99220
  null,
98780
99221
  null,
@@ -98930,6 +99371,15 @@ var VirtualCascaderPanel_component = normalizeComponent(
98930
99371
  columnMaxWidth: {
98931
99372
  type: Number,
98932
99373
  default: 420
99374
+ },
99375
+ /**
99376
+ * 下拉筛选配置。外部传入且 enabled 不为 false、并指定 field 时才展示下拉框。
99377
+ * { enabled, title, placeholder, options: [{ label, value }], field }
99378
+ * field 为数据中用于过滤和展示的字段名。
99379
+ */
99380
+ dropdownFilter: {
99381
+ type: Object,
99382
+ default: null
98933
99383
  }
98934
99384
  },
98935
99385
  data() {
@@ -98957,7 +99407,8 @@ var VirtualCascaderPanel_component = normalizeComponent(
98957
99407
  searchLeafSetCache: null,
98958
99408
  panelSyncTimer: null,
98959
99409
  // 外部 v-model 回显同步中,避免与用户操作冲突
98960
- isExternalSync: false
99410
+ isExternalSync: false,
99411
+ dropdownFilterValue: ''
98961
99412
  };
98962
99413
  },
98963
99414
  computed: {
@@ -99058,6 +99509,59 @@ var VirtualCascaderPanel_component = normalizeComponent(
99058
99509
  this.searchSelectedValues = value ? [value] : [];
99059
99510
  }
99060
99511
  }
99512
+ },
99513
+ showDropdownFilter() {
99514
+ const cfg = this.dropdownFilter;
99515
+ return !!(cfg && typeof cfg === 'object' && cfg.enabled !== false && cfg.field);
99516
+ },
99517
+ dropdownFilterPlaceholder() {
99518
+ return this.dropdownFilter && this.dropdownFilter.placeholder || '请选择';
99519
+ },
99520
+ dropdownFilterTitle() {
99521
+ const title = this.dropdownFilter && this.dropdownFilter.title;
99522
+ return title != null && String(title).trim() !== '' ? String(title).trim() : '';
99523
+ },
99524
+ dropdownFilterField() {
99525
+ return this.dropdownFilter && this.dropdownFilter.field || '';
99526
+ },
99527
+ normalizedDropdownFilterOptions() {
99528
+ const opts = this.dropdownFilter && this.dropdownFilter.options || [];
99529
+ return opts.map(opt => {
99530
+ if (opt != null && typeof opt === 'object') {
99531
+ return {
99532
+ label: opt.label != null ? opt.label : opt.value,
99533
+ value: opt.value != null ? opt.value : opt.label
99534
+ };
99535
+ }
99536
+ return {
99537
+ label: String(opt),
99538
+ value: opt
99539
+ };
99540
+ });
99541
+ },
99542
+ hasActiveDropdownFilter() {
99543
+ return this.showDropdownFilter && this.dropdownFilterValue !== '' && this.dropdownFilterValue !== null && this.dropdownFilterValue !== undefined;
99544
+ },
99545
+ displayOptions() {
99546
+ if (!this.hasActiveDropdownFilter) {
99547
+ return this.filteredOptions;
99548
+ }
99549
+ return CascaderUtilsPro.filterTreeByField(this.filteredOptions, this.dropdownFilterField, this.dropdownFilterValue, this.cascaderProps);
99550
+ },
99551
+ isFilterView() {
99552
+ if (this.searchInput !== '' && this.isShowSearch) {
99553
+ return true;
99554
+ }
99555
+ return this.hasActiveDropdownFilter;
99556
+ },
99557
+ viewOptions() {
99558
+ if (this.searchInput !== '' && this.isShowSearch) {
99559
+ return this.searchOptions;
99560
+ }
99561
+ if (this.hasActiveDropdownFilter) {
99562
+ return this.displayOptions;
99563
+ }
99564
+ return [];
99061
99565
  }
99062
99566
  },
99063
99567
  watch: {
@@ -99083,6 +99587,9 @@ var VirtualCascaderPanel_component = normalizeComponent(
99083
99587
  searchInput(val) {
99084
99588
  if (!val) {
99085
99589
  this.clearSearchState();
99590
+ if (this.hasActiveDropdownFilter) {
99591
+ this.prepareFilterView();
99592
+ }
99086
99593
  return;
99087
99594
  }
99088
99595
  this.scheduleSearch();
@@ -99110,6 +99617,9 @@ var VirtualCascaderPanel_component = normalizeComponent(
99110
99617
  } else if (panel && panel.store && panel.selection && this.aggregationMode) {
99111
99618
  this.isAllSelected = panel.selection.size() === panel.store.totalLeafCount && panel.store.totalLeafCount > 0;
99112
99619
  }
99620
+ if (this.hasActiveDropdownFilter) {
99621
+ this.updateFilterAllSelectedState();
99622
+ }
99113
99623
  } else {
99114
99624
  if (newVal.length > 1) {
99115
99625
  this.selectedItems = [newVal[newVal.length - 1]];
@@ -99124,6 +99634,11 @@ var VirtualCascaderPanel_component = normalizeComponent(
99124
99634
  if (val) {
99125
99635
  this.batchSearchVisible = false;
99126
99636
  }
99637
+ },
99638
+ showDropdownFilter(val) {
99639
+ if (!val) {
99640
+ this.dropdownFilterValue = '';
99641
+ }
99127
99642
  }
99128
99643
  },
99129
99644
  mounted() {
@@ -99177,6 +99692,9 @@ var VirtualCascaderPanel_component = normalizeComponent(
99177
99692
  this.selectedValues = selection.getCheckedPaths();
99178
99693
  }
99179
99694
  panel.bumpSelectionView();
99695
+ if (this.hasActiveDropdownFilter) {
99696
+ this.updateFilterAllSelectedState();
99697
+ }
99180
99698
  return;
99181
99699
  }
99182
99700
  if (selection.isCompactSelection()) {
@@ -99184,11 +99702,17 @@ var VirtualCascaderPanel_component = normalizeComponent(
99184
99702
  this.selectedCount = selection.size();
99185
99703
  this.isAllSelected = selection.size() === store.totalLeafCount;
99186
99704
  panel.bumpSelectionView();
99705
+ if (this.hasActiveDropdownFilter) {
99706
+ this.updateFilterAllSelectedState();
99707
+ }
99187
99708
  return;
99188
99709
  }
99189
99710
  this.selectedValues = selection.getCheckedPaths();
99190
99711
  this.updateSelectedItems();
99191
99712
  panel.bumpSelectionView();
99713
+ if (this.hasActiveDropdownFilter) {
99714
+ this.updateFilterAllSelectedState();
99715
+ }
99192
99716
  },
99193
99717
  /**
99194
99718
  * 用户操作(勾选/全选/清除/删除)统一提交:更新展示 + emit,标记内部更新防回显覆盖
@@ -99442,6 +99966,11 @@ var VirtualCascaderPanel_component = normalizeComponent(
99442
99966
  } else {
99443
99967
  this.updateSelectedItems();
99444
99968
  }
99969
+ if (this.searchInput) {
99970
+ this.scheduleSearch();
99971
+ } else if (this.hasActiveDropdownFilter) {
99972
+ this.prepareFilterView();
99973
+ }
99445
99974
  },
99446
99975
  // 处理选项数据,添加禁用状态(浅拷贝,避免 JSON 深拷贝大数据卡顿)
99447
99976
  processOptions(options) {
@@ -99527,13 +100056,20 @@ var VirtualCascaderPanel_component = normalizeComponent(
99527
100056
  const keyword = this.searchInput.trim();
99528
100057
  if (!keyword) {
99529
100058
  this.clearSearchState();
100059
+ if (this.hasActiveDropdownFilter) {
100060
+ this.prepareFilterView();
100061
+ }
99530
100062
  return;
99531
100063
  }
99532
- const panel = this.$refs.cascaderPanel;
99533
- if (panel && panel.store) {
99534
- this.searchOptions = CascaderUtilsPro.searchFromStore(panel.store, keyword, this.cascaderProps);
100064
+ if (this.hasActiveDropdownFilter) {
100065
+ this.searchOptions = CascaderUtilsPro.searchInTree(this.displayOptions, keyword, this.cascaderProps);
99535
100066
  } else {
99536
- this.searchOptions = CascaderUtilsPro.searchInTree(this.filteredOptions, keyword, this.cascaderProps);
100067
+ const panel = this.$refs.cascaderPanel;
100068
+ if (panel && panel.store) {
100069
+ this.searchOptions = CascaderUtilsPro.searchFromStore(panel.store, keyword, this.cascaderProps);
100070
+ } else {
100071
+ this.searchOptions = CascaderUtilsPro.searchInTree(this.filteredOptions, keyword, this.cascaderProps);
100072
+ }
99537
100073
  }
99538
100074
  this.searchLeafSetCache = new Set(CascaderUtilsPro.getLeafValues(this.searchOptions, this.cascaderProps));
99539
100075
  this.searchSelectedValues = this.getSearchSelectedPathsFromMain(this.searchLeafSetCache);
@@ -99565,7 +100101,7 @@ var VirtualCascaderPanel_component = normalizeComponent(
99565
100101
  if (this.searchLeafSetCache) {
99566
100102
  return this.searchLeafSetCache;
99567
100103
  }
99568
- return new Set(CascaderUtilsPro.getLeafValues(this.searchOptions, this.cascaderProps));
100104
+ return new Set(CascaderUtilsPro.getLeafValues(this.viewOptions, this.cascaderProps));
99569
100105
  },
99570
100106
  syncSearchPanelSelection() {
99571
100107
  const searchPanel = this.$refs.searchCascaderPanel;
@@ -99585,12 +100121,46 @@ var VirtualCascaderPanel_component = normalizeComponent(
99585
100121
  },
99586
100122
  // 搜索模式下的展开处理
99587
100123
  handleSearchExpand() {
99588
- if (this.$refs.searchCascaderPanel && this.searchOptions.length > 0) {
99589
- const firstOption = this.searchOptions[0];
100124
+ if (this.$refs.searchCascaderPanel && this.viewOptions.length > 0) {
100125
+ const firstOption = this.viewOptions[0];
99590
100126
  const valueKey = this.cascaderProps.value || 'value';
99591
100127
  this.$refs.searchCascaderPanel.expandPathValues([firstOption[valueKey]], true);
99592
100128
  }
99593
100129
  },
100130
+ prepareFilterView() {
100131
+ this.searchLeafSetCache = new Set(CascaderUtilsPro.getLeafValues(this.displayOptions, this.cascaderProps));
100132
+ this.$nextTick(() => {
100133
+ this.syncSearchPanelSelection();
100134
+ this.handleSearchExpand();
100135
+ });
100136
+ },
100137
+ handleDropdownFilterChange() {
100138
+ if (this.searchInput) {
100139
+ this.scheduleSearch();
100140
+ return;
100141
+ }
100142
+ this.clearSearchState();
100143
+ if (this.hasActiveDropdownFilter) {
100144
+ this.prepareFilterView();
100145
+ }
100146
+ },
100147
+ updateFilterAllSelectedState() {
100148
+ if (!this.hasActiveDropdownFilter) {
100149
+ return;
100150
+ }
100151
+ const viewPaths = CascaderUtilsPro.getAllLeafPaths(this.displayOptions, this.disabledConfig, this.cascaderProps);
100152
+ if (viewPaths.length === 0) {
100153
+ this.isAllSelected = false;
100154
+ return;
100155
+ }
100156
+ const panel = this.$refs.cascaderPanel;
100157
+ if (panel && panel.selection && panel.selection.selectedLeafSet) {
100158
+ this.isAllSelected = viewPaths.every(path => panel.selection.selectedLeafSet.has(path[path.length - 1]));
100159
+ return;
100160
+ }
100161
+ const selectedLeafSet = new Set(this.selectedValues.map(path => path[path.length - 1]));
100162
+ this.isAllSelected = viewPaths.every(path => selectedLeafSet.has(path[path.length - 1]));
100163
+ },
99594
100164
  // 值变化处理(面板勾选)
99595
100165
  handleValueChange() {
99596
100166
  this.commitUserSelectionChange();
@@ -99682,6 +100252,26 @@ var VirtualCascaderPanel_component = normalizeComponent(
99682
100252
  }
99683
100253
  const panel = this.$refs.cascaderPanel;
99684
100254
  const searchPanel = this.$refs.searchCascaderPanel;
100255
+ if (this.hasActiveDropdownFilter && panel && panel.selection && panel.store) {
100256
+ const viewPaths = CascaderUtilsPro.getAllLeafPaths(this.displayOptions, this.disabledConfig, this.cascaderProps);
100257
+ const viewLeafSet = new Set(viewPaths.map(path => path[path.length - 1]));
100258
+ if (this.isAllSelected) {
100259
+ viewLeafSet.forEach(leaf => {
100260
+ panel.selection.selectedLeafSet.delete(leaf);
100261
+ });
100262
+ } else {
100263
+ viewLeafSet.forEach(leaf => {
100264
+ panel.selection.selectedLeafSet.add(leaf);
100265
+ });
100266
+ }
100267
+ panel.selection._reconcileAllRoots();
100268
+ panel.bumpSelectionView();
100269
+ if (searchPanel && searchPanel.selection) {
100270
+ this.syncSearchPanelSelection();
100271
+ }
100272
+ this.commitUserSelectionChange();
100273
+ return;
100274
+ }
99685
100275
  if (this.isAllSelected) {
99686
100276
  this.clearPanelSelectionState(panel);
99687
100277
  this.clearPanelSelectionState(searchPanel);
@@ -99807,6 +100397,9 @@ var VirtualCascaderPanel_component = normalizeComponent(
99807
100397
  if (this.panelViewMode) return;
99808
100398
  this.searchInput = '';
99809
100399
  this.clearSearchState();
100400
+ if (this.hasActiveDropdownFilter) {
100401
+ this.prepareFilterView();
100402
+ }
99810
100403
  this.$emit('refresh');
99811
100404
  },
99812
100405
  // 处理批量搜索
@@ -99935,8 +100528,8 @@ var VirtualCascaderPanel_component = normalizeComponent(
99935
100528
  ;
99936
100529
  var ByCascaderPanelPro_component = normalizeComponent(
99937
100530
  cascader_panel_pro_ByCascaderPanelProvue_type_script_lang_js,
99938
- ByCascaderPanelProvue_type_template_id_961f637e_render,
99939
- ByCascaderPanelProvue_type_template_id_961f637e_staticRenderFns,
100531
+ ByCascaderPanelProvue_type_template_id_21ca97ff_render,
100532
+ ByCascaderPanelProvue_type_template_id_21ca97ff_staticRenderFns,
99940
100533
  false,
99941
100534
  null,
99942
100535
  null,