|
|
@@ -1,9 +1,18 @@
|
|
|
<template>
|
|
|
- <Cascader :value="innerValue" :options="options" placeholder="全部" :field-names="{
|
|
|
- label: 'departName',
|
|
|
- value: 'id',
|
|
|
- children: 'childDepart',
|
|
|
- }" :show-search="showSearch" :allow-clear="allowClear" :change-on-select="changeOnSelect" @change="handleChange">
|
|
|
+ <Cascader
|
|
|
+ :value="innerValue"
|
|
|
+ :options="options"
|
|
|
+ placeholder="全部"
|
|
|
+ :field-names="{
|
|
|
+ label: 'departName',
|
|
|
+ value: 'id',
|
|
|
+ children: 'childDepart',
|
|
|
+ }"
|
|
|
+ :show-search="showSearch"
|
|
|
+ :allow-clear="allowClear"
|
|
|
+ :change-on-select="changeOnSelect"
|
|
|
+ @change="handleChange"
|
|
|
+ >
|
|
|
<template #displayRender="{ labels }">
|
|
|
{{ labels[labels.length - 1] }}
|
|
|
</template>
|
|
|
@@ -12,111 +21,119 @@
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
-import { last } from 'lodash';
|
|
|
-import { defineComponent, ref, watch } from 'vue';
|
|
|
-// import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
-import { propTypes } from '/@/utils/propTypes';
|
|
|
-import { useMineDepartmentStore } from '/@/store/modules/mine';
|
|
|
-import { Cascader } from 'ant-design-vue';
|
|
|
+ import { last } from 'lodash';
|
|
|
+ import { defineComponent, ref, watch } from 'vue';
|
|
|
+ // import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
+ import { propTypes } from '/@/utils/propTypes';
|
|
|
+ import { useMineDepartmentStore } from '/@/store/modules/mine';
|
|
|
+ import { Cascader } from 'ant-design-vue';
|
|
|
|
|
|
-/**
|
|
|
- * 矿区级联选择器,该组件会根据配置从store中获取初始数据
|
|
|
- *
|
|
|
- * 组件数据流梳理:初始化数据及选项 -> 更新数据 -> 同步STORE -> 计算组件内依赖
|
|
|
- *
|
|
|
- * 本组件在初始化后不再监听STORE中的数据变化,因为这样可能导致用户通过Tabs切换时出现数据混乱
|
|
|
- */
|
|
|
-export default defineComponent({
|
|
|
- name: 'MineCascader',
|
|
|
- components: { Cascader },
|
|
|
- props: {
|
|
|
- value: propTypes.string.def(''),
|
|
|
- placeholder: propTypes.string.def('全部'),
|
|
|
- /** 根节点ID,如果传入,组件将过滤该节点下的节点 */
|
|
|
- rootId: propTypes.string,
|
|
|
- /** 是否从已存储的信息中初始化组件值 */
|
|
|
- initFromStore: propTypes.bool.def(true),
|
|
|
- /** 是否从将值同步至STORE */
|
|
|
- syncToStore: propTypes.bool.def(true),
|
|
|
- showSearch: propTypes.bool.def(true),
|
|
|
- allowClear: propTypes.bool.def(true),
|
|
|
- changeOnSelect: propTypes.bool.def(true),
|
|
|
- // clearOnDestroy: propTypes.bool.def(false),
|
|
|
- },
|
|
|
- emits: ['change', 'update:value'],
|
|
|
- setup(props, { emit }) {
|
|
|
- // const { createMessage } = useMessage();
|
|
|
- const mineStore = useMineDepartmentStore();
|
|
|
- const innerValue = ref<string[]>([]);
|
|
|
- const options = ref(mineStore.getDepartTree);
|
|
|
+ /**
|
|
|
+ * 矿区级联选择器,该组件会根据配置从store中获取初始数据
|
|
|
+ *
|
|
|
+ * 组件数据流梳理:初始化数据及选项 -> 更新数据 -> 同步STORE -> 计算组件内依赖
|
|
|
+ *
|
|
|
+ * 本组件在初始化后不再监听STORE中的数据变化,因为这样可能导致用户通过Tabs切换时出现数据混乱
|
|
|
+ */
|
|
|
+ export default defineComponent({
|
|
|
+ name: 'MineCascader',
|
|
|
+ components: { Cascader },
|
|
|
+ props: {
|
|
|
+ value: propTypes.string.def(''),
|
|
|
+ placeholder: propTypes.string.def('全部'),
|
|
|
+ /** 根节点ID,如果传入,组件将过滤该节点下的节点 */
|
|
|
+ rootId: propTypes.string,
|
|
|
+ /** 是否从已存储的信息中初始化组件值 */
|
|
|
+ initFromStore: propTypes.bool.def(true),
|
|
|
+ /** 是否从将值同步至STORE */
|
|
|
+ syncToStore: propTypes.bool.def(true),
|
|
|
+ showSearch: propTypes.bool.def(true),
|
|
|
+ allowClear: propTypes.bool.def(true),
|
|
|
+ changeOnSelect: propTypes.bool.def(true),
|
|
|
+ // clearOnDestroy: propTypes.bool.def(false),
|
|
|
+ },
|
|
|
+ emits: ['change', 'update:value'],
|
|
|
+ setup(props, { emit }) {
|
|
|
+ // const { createMessage } = useMessage();
|
|
|
+ const mineStore = useMineDepartmentStore();
|
|
|
+ const innerValue = ref<string[]>([]);
|
|
|
+ const options = ref(mineStore.getDepartTree);
|
|
|
|
|
|
- // if (props.clearOnDestroy) {
|
|
|
- // const raw = getDepartId.value;
|
|
|
- // onUnmounted(() => {
|
|
|
- // mineStore.setDepartById(raw);
|
|
|
- // });
|
|
|
- // }
|
|
|
+ // if (props.clearOnDestroy) {
|
|
|
+ // const raw = getDepartId.value;
|
|
|
+ // onUnmounted(() => {
|
|
|
+ // mineStore.setDepartById(raw);
|
|
|
+ // });
|
|
|
+ // }
|
|
|
|
|
|
- if (props.rootId) {
|
|
|
- options.value = mineStore.filterDepartTree((e) => e.parentId === props.rootId);
|
|
|
- }
|
|
|
-
|
|
|
- // 如果从STORE里初始化数据需要触发一次watcher以初始化组件状态
|
|
|
- if (props.initFromStore) {
|
|
|
- handleWatch(mineStore.getDepartId);
|
|
|
- // 为了让使用该组件的各个页面能够第一时间使用到该组件传递的值,手动触发一次emit
|
|
|
- handleChange([mineStore.getDepartId]);
|
|
|
- } else {
|
|
|
- handleWatch(props.value);
|
|
|
- // 为了让使用该组件的各个页面能够第一时间使用到该组件传递的值,手动触发一次emit
|
|
|
- handleChange([props.value]);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * change事件
|
|
|
- * @param e
|
|
|
- */
|
|
|
- function handleChange(value: any[] = []) {
|
|
|
- console.log(value, 'value===')
|
|
|
- if (!value.length) {
|
|
|
- emit('update:value', null);
|
|
|
- emit('change', null);
|
|
|
- } else if (!mineStore.findDepartById(last(value), options.value)) {
|
|
|
- console.warn('[Change] The value provided is not included in MineOptions');
|
|
|
- const val = mineStore.calcMineCodeByDepart(options.value);
|
|
|
- emit('update:value', val);
|
|
|
- emit('change', val);
|
|
|
- } else {
|
|
|
- emit('update:value', last(value));
|
|
|
- emit('change', last(value));
|
|
|
+ if (props.rootId) {
|
|
|
+ options.value = mineStore.filterDepartTree((e) => e.parentId === props.rootId);
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- function handleWatch(id: string = '') {
|
|
|
- // rootId提供了选项过滤功能,任何传入的值都应该检查
|
|
|
- if (!mineStore.findDepartById(id, options.value)) {
|
|
|
- console.warn('[Watch] The id provided is not included in MineOptions');
|
|
|
- innerValue.value = [];
|
|
|
+ // 如果从STORE里初始化数据需要触发一次watcher以初始化组件状态
|
|
|
+ if (props.initFromStore) {
|
|
|
+ // handleWatch(mineStore.getDepartId);
|
|
|
+ // 为了让使用该组件的各个页面能够第一时间使用到该组件传递的值,手动触发一次emit
|
|
|
+ handleChange([mineStore.getDepartId]);
|
|
|
} else {
|
|
|
- const path = mineStore.calcDepartPathById(id, options.value, (e) => e.id);
|
|
|
- innerValue.value = path;
|
|
|
+ // handleWatch(props.value);
|
|
|
+ // 为了让使用该组件的各个页面能够第一时间使用到该组件传递的值,手动触发一次emit
|
|
|
+ handleChange([props.value]);
|
|
|
}
|
|
|
|
|
|
- if (props.syncToStore) {
|
|
|
- mineStore.setDepartById(id);
|
|
|
+ /**
|
|
|
+ * change事件
|
|
|
+ * @param e
|
|
|
+ */
|
|
|
+ function handleChange(value: any[] = []) {
|
|
|
+ if (!mineStore.findDepartById(last(value), options.value)) {
|
|
|
+ console.warn('[Change] The value provided is not included in MineOptions');
|
|
|
+ const val = mineStore.calcMineCodeByDepart(options.value);
|
|
|
+ emit('update:value', val);
|
|
|
+ emit('change', val);
|
|
|
+ } else {
|
|
|
+ emit('update:value', last(value));
|
|
|
+ emit('change', last(value));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- const path = mineStore.calcDepartPathById(id, options.value, (e) => e.id);
|
|
|
- innerValue.value = path;
|
|
|
- }
|
|
|
+ function handleWatch(id: string = '') {
|
|
|
+ // rootId提供了选项过滤功能,任何传入的值都应该检查
|
|
|
+ if (!mineStore.findDepartById(id, options.value)) {
|
|
|
+ console.warn('[Watch] The id provided is not included in MineOptions');
|
|
|
+ innerValue.value = [];
|
|
|
+ } else {
|
|
|
+ const path = mineStore.calcDepartPathById(id, options.value, (e) => e.id);
|
|
|
+ innerValue.value = path;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (props.syncToStore) {
|
|
|
+ mineStore.setDepartById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ const path = mineStore.calcDepartPathById(id, options.value, (e) => e.id);
|
|
|
+ innerValue.value = path;
|
|
|
+ }
|
|
|
|
|
|
- watch(() => props.value, handleWatch);
|
|
|
+ watch(
|
|
|
+ () => props.value,
|
|
|
+ (nv) => {
|
|
|
+ // 触发事件的顺序应该是 change -> watch
|
|
|
+ if (nv === '') {
|
|
|
+ // 因此当监听到的数据为空时,99%的情况是外部操作导致,因此触发一次 change -> watch
|
|
|
+ handleChange([nv]);
|
|
|
+ } else {
|
|
|
+ // 反之则为内部正常数据触发 change 后来到这里走 watch 的逻辑
|
|
|
+ handleWatch(nv);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
|
|
|
- return {
|
|
|
- innerValue,
|
|
|
- options,
|
|
|
- handleChange,
|
|
|
- };
|
|
|
- },
|
|
|
-});
|
|
|
+ return {
|
|
|
+ innerValue,
|
|
|
+ options,
|
|
|
+ handleChange,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ });
|
|
|
</script>
|