|  | @@ -0,0 +1,384 @@
 | 
	
		
			
				|  |  | +import { NPopover, NScrollbar } from 'naive-ui';
 | 
	
		
			
				|  |  | +import {
 | 
	
		
			
				|  |  | +  PropType,
 | 
	
		
			
				|  |  | +  computed,
 | 
	
		
			
				|  |  | +  defineComponent,
 | 
	
		
			
				|  |  | +  onMounted,
 | 
	
		
			
				|  |  | +  reactive,
 | 
	
		
			
				|  |  | +  ref,
 | 
	
		
			
				|  |  | +  toRefs,
 | 
	
		
			
				|  |  | +  watch
 | 
	
		
			
				|  |  | +} from 'vue';
 | 
	
		
			
				|  |  | +import styles from './index.module.less';
 | 
	
		
			
				|  |  | +import arrowDown from './images/icon-arrow-down.png';
 | 
	
		
			
				|  |  | +import arrowUp from './images/icon-arrow-up.png';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export default defineComponent({
 | 
	
		
			
				|  |  | +  name: 'c-cascader',
 | 
	
		
			
				|  |  | +  props: {
 | 
	
		
			
				|  |  | +    value: {
 | 
	
		
			
				|  |  | +      type: String,
 | 
	
		
			
				|  |  | +      default: ''
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    options: {
 | 
	
		
			
				|  |  | +      type: Array as PropType<any[]>,
 | 
	
		
			
				|  |  | +      default: () => []
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    placeholder: {
 | 
	
		
			
				|  |  | +      type: String,
 | 
	
		
			
				|  |  | +      default: '请选择'
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    placement: {
 | 
	
		
			
				|  |  | +      type: String,
 | 
	
		
			
				|  |  | +      default: 'bottom-start'
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  emits: ['update:value'],
 | 
	
		
			
				|  |  | +  setup(props, { emit }) {
 | 
	
		
			
				|  |  | +    const state = reactive({
 | 
	
		
			
				|  |  | +      popoverShow: false,
 | 
	
		
			
				|  |  | +      selectParents: {}, // 选中的数据
 | 
	
		
			
				|  |  | +      tagActiveId: '' as any,
 | 
	
		
			
				|  |  | +      tagActive: {} as any,
 | 
	
		
			
				|  |  | +      childSelectId: null as any
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // const formatParentCurrentValue = (ids: any, list: any) => {
 | 
	
		
			
				|  |  | +    //   for (const item of list) {
 | 
	
		
			
				|  |  | +    //     if (ids.includes(item.id)) {
 | 
	
		
			
				|  |  | +    //       if (item.children && item.children.length > 0) {
 | 
	
		
			
				|  |  | +    //         let lastId: any;
 | 
	
		
			
				|  |  | +    //         item.children.forEach((child: any) => {
 | 
	
		
			
				|  |  | +    //           if (ids.includes(child.id)) {
 | 
	
		
			
				|  |  | +    //             lastId = child.id;
 | 
	
		
			
				|  |  | +    //           }
 | 
	
		
			
				|  |  | +    //         });
 | 
	
		
			
				|  |  | +    //         item.activeIndex = lastId;
 | 
	
		
			
				|  |  | +    //       }
 | 
	
		
			
				|  |  | +    //     }
 | 
	
		
			
				|  |  | +    //     if (item.children && item.children.length > 0) {
 | 
	
		
			
				|  |  | +    //       formatParentCurrentValue(ids, item.children);
 | 
	
		
			
				|  |  | +    //     }
 | 
	
		
			
				|  |  | +    //   }
 | 
	
		
			
				|  |  | +    // };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const initParentSelect = (subject: any) => {
 | 
	
		
			
				|  |  | +      let children: any;
 | 
	
		
			
				|  |  | +      let columnName = '';
 | 
	
		
			
				|  |  | +      if (subject.children) {
 | 
	
		
			
				|  |  | +        children = [
 | 
	
		
			
				|  |  | +          {
 | 
	
		
			
				|  |  | +            columnName: subject.children[0].columnName,
 | 
	
		
			
				|  |  | +            name: '全部' + subject.children[0].columnName || '',
 | 
	
		
			
				|  |  | +            id: ''
 | 
	
		
			
				|  |  | +          },
 | 
	
		
			
				|  |  | +          ...subject.children
 | 
	
		
			
				|  |  | +        ];
 | 
	
		
			
				|  |  | +        columnName = subject.children[0].columnName;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        state.selectParents = {
 | 
	
		
			
				|  |  | +          ...subject,
 | 
	
		
			
				|  |  | +          columnName,
 | 
	
		
			
				|  |  | +          activeIndex: '',
 | 
	
		
			
				|  |  | +          children
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        state.selectParents = {};
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // watch(
 | 
	
		
			
				|  |  | +    //   () => state.popoverShow,
 | 
	
		
			
				|  |  | +    //   () => {
 | 
	
		
			
				|  |  | +    //     if (!state.popoverShow || !props.value) return;
 | 
	
		
			
				|  |  | +    //     let ids = formatParentId(props.value, props.options);
 | 
	
		
			
				|  |  | +    //     state.tagActiveId = ids[0].id;
 | 
	
		
			
				|  |  | +    //     props.options.forEach((item: any) => {
 | 
	
		
			
				|  |  | +    //       if (item.id === state.tagActiveId) {
 | 
	
		
			
				|  |  | +    //         initParentSelect(item);
 | 
	
		
			
				|  |  | +    //       }
 | 
	
		
			
				|  |  | +    //     });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //     //
 | 
	
		
			
				|  |  | +    //     const index = ids.findIndex((child: any) => child.id === props.value);
 | 
	
		
			
				|  |  | +    //     ids = ids.slice(0, index + 1);
 | 
	
		
			
				|  |  | +    //     const values = ids.map((item: any) => {
 | 
	
		
			
				|  |  | +    //       return item.id;
 | 
	
		
			
				|  |  | +    //     });
 | 
	
		
			
				|  |  | +    //     console.log(values, 'values');
 | 
	
		
			
				|  |  | +    //     formatParentCurrentValue(values, props.options);
 | 
	
		
			
				|  |  | +    //   }
 | 
	
		
			
				|  |  | +    // );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const valueText = computed(() => {
 | 
	
		
			
				|  |  | +      const id = props.value;
 | 
	
		
			
				|  |  | +      const values = getValues(id);
 | 
	
		
			
				|  |  | +      const names: any = [];
 | 
	
		
			
				|  |  | +      values.forEach((item: any) => {
 | 
	
		
			
				|  |  | +        names.push(item.name);
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +      return names.join(' / ');
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 递归获取数据
 | 
	
		
			
				|  |  | +    const formatParentId = (id: any, list: any, ids = [] as any) => {
 | 
	
		
			
				|  |  | +      for (const item of list) {
 | 
	
		
			
				|  |  | +        if (item.children && item.children.length > 0) {
 | 
	
		
			
				|  |  | +          const cIds: any = formatParentId(id, item.children, [
 | 
	
		
			
				|  |  | +            ...ids,
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +              name: item.name,
 | 
	
		
			
				|  |  | +              id: item.id
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          ]);
 | 
	
		
			
				|  |  | +          const index = cIds.findIndex((c: any) => c.id === id);
 | 
	
		
			
				|  |  | +          if (index > -1) {
 | 
	
		
			
				|  |  | +            return cIds;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (item.id === id) {
 | 
	
		
			
				|  |  | +          return [
 | 
	
		
			
				|  |  | +            ...ids,
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +              name: item.name,
 | 
	
		
			
				|  |  | +              id
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          ];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return ids;
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const getValues = (value: any) => {
 | 
	
		
			
				|  |  | +      let ids = formatParentId(value, props.options);
 | 
	
		
			
				|  |  | +      const index = ids.findIndex((child: any) => child.id === value);
 | 
	
		
			
				|  |  | +      ids = ids.slice(0, index + 1);
 | 
	
		
			
				|  |  | +      return ids;
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 重置
 | 
	
		
			
				|  |  | +    const onReset = () => {
 | 
	
		
			
				|  |  | +      state.childSelectId = null;
 | 
	
		
			
				|  |  | +      state.tagActiveId = '';
 | 
	
		
			
				|  |  | +      state.selectParents = {};
 | 
	
		
			
				|  |  | +      emit('update:value', '');
 | 
	
		
			
				|  |  | +      state.popoverShow = false;
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 提交
 | 
	
		
			
				|  |  | +    const onConfirm = () => {
 | 
	
		
			
				|  |  | +      emit('update:value', state.childSelectId || state.tagActiveId);
 | 
	
		
			
				|  |  | +      state.popoverShow = false;
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    return () => (
 | 
	
		
			
				|  |  | +      <NPopover
 | 
	
		
			
				|  |  | +        placement={props.placement as any}
 | 
	
		
			
				|  |  | +        v-model:show={state.popoverShow}
 | 
	
		
			
				|  |  | +        showArrow={false}
 | 
	
		
			
				|  |  | +        trigger="click"
 | 
	
		
			
				|  |  | +        displayDirective="show"
 | 
	
		
			
				|  |  | +        class={[styles.cascaderPopover, 'c-cascaderPopover']}>
 | 
	
		
			
				|  |  | +        {{
 | 
	
		
			
				|  |  | +          trigger: () => (
 | 
	
		
			
				|  |  | +            <div
 | 
	
		
			
				|  |  | +              class={[
 | 
	
		
			
				|  |  | +                styles.nBaseCascaser,
 | 
	
		
			
				|  |  | +                state.popoverShow ? styles.nBaseCascaserActive : ''
 | 
	
		
			
				|  |  | +              ]}>
 | 
	
		
			
				|  |  | +              <div class={styles['n-base-selection-tags']}>
 | 
	
		
			
				|  |  | +                <div class={styles['n-base-selection-input']}>
 | 
	
		
			
				|  |  | +                  <div class={styles['n-base-selection-input__content']}>
 | 
	
		
			
				|  |  | +                    {valueText.value}
 | 
	
		
			
				|  |  | +                  </div>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +                <div class={[styles['n-base-suffix']]}>
 | 
	
		
			
				|  |  | +                  <div class={[styles.arrow]}>
 | 
	
		
			
				|  |  | +                    <img src={state.popoverShow ? arrowUp : arrowDown} />
 | 
	
		
			
				|  |  | +                  </div>
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +              <div
 | 
	
		
			
				|  |  | +                class={[
 | 
	
		
			
				|  |  | +                  styles['n-base-selection-placeholder'],
 | 
	
		
			
				|  |  | +                  styles['n-base-selection-overlay']
 | 
	
		
			
				|  |  | +                ]}>
 | 
	
		
			
				|  |  | +                {!valueText.value && (
 | 
	
		
			
				|  |  | +                  <div class={styles.inner}>{props.placeholder}</div>
 | 
	
		
			
				|  |  | +                )}
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +              <div class={styles['n-base-selection__border']}></div>
 | 
	
		
			
				|  |  | +              <div class={styles['n-base-selection__state-border']}></div>
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +          ),
 | 
	
		
			
				|  |  | +          default: () => (
 | 
	
		
			
				|  |  | +            <div class={styles.baseContent}>
 | 
	
		
			
				|  |  | +              <NScrollbar
 | 
	
		
			
				|  |  | +                class={styles.baseScrollBar}
 | 
	
		
			
				|  |  | +                style={{ maxHeight: '400px' }}>
 | 
	
		
			
				|  |  | +                <div class={styles.baseContentTitle}>
 | 
	
		
			
				|  |  | +                  {props.options[0].columnName}
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +                <div class={styles.baseContentWrap}>
 | 
	
		
			
				|  |  | +                  {props.options.map((subject: any) => (
 | 
	
		
			
				|  |  | +                    <span
 | 
	
		
			
				|  |  | +                      class={[
 | 
	
		
			
				|  |  | +                        styles.tag,
 | 
	
		
			
				|  |  | +                        (state.tagActiveId || '') == subject.id &&
 | 
	
		
			
				|  |  | +                          styles.tagActive
 | 
	
		
			
				|  |  | +                      ]}
 | 
	
		
			
				|  |  | +                      onClick={() => {
 | 
	
		
			
				|  |  | +                        state.tagActiveId = subject.id;
 | 
	
		
			
				|  |  | +                        initParentSelect(subject);
 | 
	
		
			
				|  |  | +                      }}>
 | 
	
		
			
				|  |  | +                      {subject.name}
 | 
	
		
			
				|  |  | +                    </span>
 | 
	
		
			
				|  |  | +                  ))}
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +                <ChildNodeSearch
 | 
	
		
			
				|  |  | +                  activeRow={state.selectParents}
 | 
	
		
			
				|  |  | +                  onSelectChildTag={(val: any) => {
 | 
	
		
			
				|  |  | +                    state.childSelectId = val;
 | 
	
		
			
				|  |  | +                  }}
 | 
	
		
			
				|  |  | +                />
 | 
	
		
			
				|  |  | +              </NScrollbar>
 | 
	
		
			
				|  |  | +              <div class={styles.btnGroup}>
 | 
	
		
			
				|  |  | +                <div class={[styles.btn, styles.btnCancel]} onClick={onReset}>
 | 
	
		
			
				|  |  | +                  重置
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +                <div
 | 
	
		
			
				|  |  | +                  class={[styles.btn, styles.btnConfirm]}
 | 
	
		
			
				|  |  | +                  onClick={onConfirm}>
 | 
	
		
			
				|  |  | +                  确认
 | 
	
		
			
				|  |  | +                </div>
 | 
	
		
			
				|  |  | +              </div>
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +          )
 | 
	
		
			
				|  |  | +        }}
 | 
	
		
			
				|  |  | +      </NPopover>
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const ChildNodeSearch = defineComponent({
 | 
	
		
			
				|  |  | +  name: 'ChildNodeSearch',
 | 
	
		
			
				|  |  | +  props: {
 | 
	
		
			
				|  |  | +    activeRow: {
 | 
	
		
			
				|  |  | +      type: Object,
 | 
	
		
			
				|  |  | +      default: () => ({})
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    list: {
 | 
	
		
			
				|  |  | +      type: Array,
 | 
	
		
			
				|  |  | +      default: () => []
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    loading: {
 | 
	
		
			
				|  |  | +      type: Boolean,
 | 
	
		
			
				|  |  | +      default: false
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  },
 | 
	
		
			
				|  |  | +  emits: ['selectChildTag'],
 | 
	
		
			
				|  |  | +  setup(props, { emit }) {
 | 
	
		
			
				|  |  | +    const { activeRow } = toRefs(props);
 | 
	
		
			
				|  |  | +    const selectItem = ref({});
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    watch(
 | 
	
		
			
				|  |  | +      () => props.activeRow,
 | 
	
		
			
				|  |  | +      () => {
 | 
	
		
			
				|  |  | +        activeRow.value = props.activeRow;
 | 
	
		
			
				|  |  | +        initActiveRow();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const initActiveRow = () => {
 | 
	
		
			
				|  |  | +      if (activeRow.value.activeIndex) {
 | 
	
		
			
				|  |  | +        const childList = activeRow.value.children || [];
 | 
	
		
			
				|  |  | +        childList.forEach((subject: any) => {
 | 
	
		
			
				|  |  | +          if (subject.id === activeRow.value.activeIndex) {
 | 
	
		
			
				|  |  | +            let children: any;
 | 
	
		
			
				|  |  | +            let columnName = '';
 | 
	
		
			
				|  |  | +            if (subject.children) {
 | 
	
		
			
				|  |  | +              children = [
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                  columnName: subject.children[0].columnName,
 | 
	
		
			
				|  |  | +                  name: '全部' + subject.children[0].columnName || '',
 | 
	
		
			
				|  |  | +                  id: ''
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                ...subject.children
 | 
	
		
			
				|  |  | +              ];
 | 
	
		
			
				|  |  | +              columnName = subject.children[0].columnName;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +              selectItem.value = {
 | 
	
		
			
				|  |  | +                ...subject,
 | 
	
		
			
				|  |  | +                columnName,
 | 
	
		
			
				|  |  | +                activeIndex: subject.activeIndex || '',
 | 
	
		
			
				|  |  | +                children
 | 
	
		
			
				|  |  | +              };
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        selectItem.value = {};
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    onMounted(() => {
 | 
	
		
			
				|  |  | +      initActiveRow();
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return () => (
 | 
	
		
			
				|  |  | +      <>
 | 
	
		
			
				|  |  | +        {activeRow.value?.id && (
 | 
	
		
			
				|  |  | +          <>
 | 
	
		
			
				|  |  | +            <div class={styles.baseContentTitle}>
 | 
	
		
			
				|  |  | +              {activeRow.value.columnName}
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +            <div class={styles.baseContentWrap}>
 | 
	
		
			
				|  |  | +              {activeRow.value?.children.map((subject: any) => (
 | 
	
		
			
				|  |  | +                <span
 | 
	
		
			
				|  |  | +                  class={[
 | 
	
		
			
				|  |  | +                    styles.tag,
 | 
	
		
			
				|  |  | +                    (activeRow.value.activeIndex || '') == subject.id &&
 | 
	
		
			
				|  |  | +                      styles.tagActive
 | 
	
		
			
				|  |  | +                  ]}
 | 
	
		
			
				|  |  | +                  onClick={() => {
 | 
	
		
			
				|  |  | +                    if (props.loading) return;
 | 
	
		
			
				|  |  | +                    activeRow.value.activeIndex = subject.id;
 | 
	
		
			
				|  |  | +                    let children: any;
 | 
	
		
			
				|  |  | +                    let columnName = '';
 | 
	
		
			
				|  |  | +                    if (subject.children) {
 | 
	
		
			
				|  |  | +                      children = [
 | 
	
		
			
				|  |  | +                        {
 | 
	
		
			
				|  |  | +                          columnName: subject.children[0].columnName,
 | 
	
		
			
				|  |  | +                          name: '全部' + subject.children[0].columnName || '',
 | 
	
		
			
				|  |  | +                          id: ''
 | 
	
		
			
				|  |  | +                        },
 | 
	
		
			
				|  |  | +                        ...subject.children
 | 
	
		
			
				|  |  | +                      ];
 | 
	
		
			
				|  |  | +                      columnName = subject.children[0].columnName;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                      selectItem.value = {
 | 
	
		
			
				|  |  | +                        ...subject,
 | 
	
		
			
				|  |  | +                        columnName,
 | 
	
		
			
				|  |  | +                        activeIndex: '',
 | 
	
		
			
				|  |  | +                        children
 | 
	
		
			
				|  |  | +                      };
 | 
	
		
			
				|  |  | +                    } else {
 | 
	
		
			
				|  |  | +                      selectItem.value = {};
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    emit('selectChildTag', activeRow.value.activeIndex);
 | 
	
		
			
				|  |  | +                  }}>
 | 
	
		
			
				|  |  | +                  {subject.name}
 | 
	
		
			
				|  |  | +                </span>
 | 
	
		
			
				|  |  | +              ))}
 | 
	
		
			
				|  |  | +            </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            <ChildNodeSearch
 | 
	
		
			
				|  |  | +              activeRow={selectItem.value}
 | 
	
		
			
				|  |  | +              onSelectChildTag={(item: any) => {
 | 
	
		
			
				|  |  | +                emit('selectChildTag', item || activeRow.value.activeIndex);
 | 
	
		
			
				|  |  | +              }}
 | 
	
		
			
				|  |  | +            />
 | 
	
		
			
				|  |  | +          </>
 | 
	
		
			
				|  |  | +        )}
 | 
	
		
			
				|  |  | +      </>
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +});
 |