|
@@ -0,0 +1,278 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="org-select el-select major-select el-select--small"
|
|
|
+ @click="switchOpen"
|
|
|
+ >
|
|
|
+ <div v-if="multiple" class="el-select__tags">
|
|
|
+ <el-tag
|
|
|
+ v-for="item in selectedList"
|
|
|
+ :key="item.id"
|
|
|
+ @close="deleteTag($event, item)"
|
|
|
+ >{{ item.name }}</el-tag
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ :class="[
|
|
|
+ 'el-input el-input--small el-input--suffix',
|
|
|
+ { 'is-focus': isFocus },
|
|
|
+ ]"
|
|
|
+ @mouseenter="inputHovering = true"
|
|
|
+ @mouseleave="inputHovering = false"
|
|
|
+ >
|
|
|
+ <input
|
|
|
+ ref="inputRef"
|
|
|
+ type="text"
|
|
|
+ autocomplete="off"
|
|
|
+ :placeholder="placeholder"
|
|
|
+ class="el-input__inner"
|
|
|
+ :value="selectedOrg.name"
|
|
|
+ readonly
|
|
|
+ />
|
|
|
+ <span class="el-input__suffix">
|
|
|
+ <span class="el-input__suffix-inner">
|
|
|
+ <i
|
|
|
+ v-show="!showClose"
|
|
|
+ :class="[
|
|
|
+ 'el-select__caret',
|
|
|
+ 'el-input__icon',
|
|
|
+ 'el-icon-arrow-up',
|
|
|
+ { 'is-reverse': visible },
|
|
|
+ ]"
|
|
|
+ ></i>
|
|
|
+ <i
|
|
|
+ v-if="showClose"
|
|
|
+ class="el-select__caret el-input__icon el-icon-circle-close"
|
|
|
+ @click="handleClearClick"
|
|
|
+ ></i>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-popover
|
|
|
+ popper-class="org-popover"
|
|
|
+ placement="bottom-start"
|
|
|
+ trigger="manual"
|
|
|
+ v-model="visible"
|
|
|
+ >
|
|
|
+ <div ref="popoverRef" slot="reference"></div>
|
|
|
+ <div class="org-popover-tree" v-clickoutside="handleClose">
|
|
|
+ <el-tree
|
|
|
+ ref="OrgTree"
|
|
|
+ :data="orgs"
|
|
|
+ default-expand-all
|
|
|
+ node-key="id"
|
|
|
+ :props="defaultProps"
|
|
|
+ check-on-click-node
|
|
|
+ :expand-on-click-node="false"
|
|
|
+ @node-click="nodeClick"
|
|
|
+ >
|
|
|
+ <span
|
|
|
+ :class="['custom-tree-node', { 'is-select': checkSelected(data) }]"
|
|
|
+ slot-scope="{ node, data }"
|
|
|
+ >
|
|
|
+ <span>{{ node.label }}</span>
|
|
|
+ <span>
|
|
|
+ <i class="el-icon-check"></i>
|
|
|
+ </span>
|
|
|
+ </span>
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { trainingPlanRequirementListPage } from "../../api";
|
|
|
+import Clickoutside from "element-ui/src/utils/clickoutside";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "org-select",
|
|
|
+ props: {
|
|
|
+ value: {
|
|
|
+ type: [Array, String],
|
|
|
+ },
|
|
|
+ placeholder: { type: String, default: "请选择" },
|
|
|
+ multiple: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ disabled: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ clearable: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+ filterParam: {
|
|
|
+ type: Object,
|
|
|
+ default() {
|
|
|
+ return {};
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ directives: { Clickoutside },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ selectedOrg: {},
|
|
|
+ selectedOrgList: [],
|
|
|
+ selectedOrgIds: [],
|
|
|
+ visible: false,
|
|
|
+ isFocus: false,
|
|
|
+ inputHovering: false,
|
|
|
+ orgs: [],
|
|
|
+ defaultProps: {
|
|
|
+ label: "label",
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ showClose() {
|
|
|
+ let hasValue = this.multiple
|
|
|
+ ? Array.isArray(this.value) && this.value.length > 0
|
|
|
+ : this.value !== undefined && this.value !== null && this.value !== "";
|
|
|
+ let criteria = this.clearable && this.inputHovering && hasValue;
|
|
|
+ return criteria;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ value(val, oldval) {
|
|
|
+ if (val !== oldval) this.initSelected(val);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async getList() {
|
|
|
+ const data = await trainingPlanRequirementListPage({
|
|
|
+ cultureProgramId: this.instance.cultureProgramId,
|
|
|
+ });
|
|
|
+ this.orgs = (data || []).map((item) => {
|
|
|
+ item.label = `${item.sortNum}.${item.name}`;
|
|
|
+ item.children = item.subRequirementList.map((elem) => {
|
|
|
+ const nelem = { ...elem };
|
|
|
+ nelem.label = `指标点${item.sortNum}-${elem.sortNum}`;
|
|
|
+ nelem.parentName = item.name;
|
|
|
+ delete nelem.subRequirementList;
|
|
|
+ return nelem;
|
|
|
+ });
|
|
|
+ return item;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (this.value) this.initSelected(this.value);
|
|
|
+ },
|
|
|
+ switchOpen() {
|
|
|
+ if (this.visible) {
|
|
|
+ this.handleClose();
|
|
|
+ } else {
|
|
|
+ this.handleOpen();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleOpen() {
|
|
|
+ this.isFocus = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.visible = true;
|
|
|
+ }, 200);
|
|
|
+ },
|
|
|
+ handleClose() {
|
|
|
+ this.visible = false;
|
|
|
+ this.isFocus = false;
|
|
|
+ },
|
|
|
+ getSelectedData(selectedIds) {
|
|
|
+ let selectedData = [];
|
|
|
+ if (!selectedIds.length) return [];
|
|
|
+
|
|
|
+ const findTree = (list) => {
|
|
|
+ list.forEach((item) => {
|
|
|
+ if (selectedIds.includes(item.id)) {
|
|
|
+ selectedData.push({ ...item });
|
|
|
+ }
|
|
|
+ if (item.children && item.children.length) {
|
|
|
+ findTree(item.children);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ findTree(this.orgs);
|
|
|
+
|
|
|
+ return selectedData;
|
|
|
+ },
|
|
|
+ initSelected(val) {
|
|
|
+ if (!this.orgs.length) return;
|
|
|
+ if (this.multiple) {
|
|
|
+ const selectedIds = val || [];
|
|
|
+ const selectedData = this.getSelectedData(selectedIds);
|
|
|
+ this.selectedOrg = {};
|
|
|
+ this.selectedOrgList = selectedData;
|
|
|
+ } else {
|
|
|
+ const selectedIds = val ? [val] : [];
|
|
|
+ const selectedData = this.getSelectedData(selectedIds);
|
|
|
+ if (selectedData.length) {
|
|
|
+ this.selectedOrg = { ...selectedData[0] };
|
|
|
+ this.selectedOrgList = selectedData;
|
|
|
+ } else {
|
|
|
+ this.selectedOrg = {};
|
|
|
+ this.selectedOrgList = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.updateSelectOrgIds();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ nodeClick(data) {
|
|
|
+ if (!this.multiple) {
|
|
|
+ this.selectedOrg = { ...data };
|
|
|
+ this.selectedOrgList = [{ ...data }];
|
|
|
+ this.updateSelectOrgIds();
|
|
|
+ this.visible = false;
|
|
|
+ this.emitChange();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.selectedOrgIds.includes(data.id)) {
|
|
|
+ this.selectedOrgList = this.selectedOrgList.filter(
|
|
|
+ (item) => item.id !== data.id
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ this.selectedOrgList.push({ ...data });
|
|
|
+ }
|
|
|
+ this.updateSelectOrgIds();
|
|
|
+ this.emitChange();
|
|
|
+ },
|
|
|
+ updateSelectOrgIds() {
|
|
|
+ this.selectedOrgIds = this.selectedOrgList.map((item) => item.id);
|
|
|
+ },
|
|
|
+ checkSelected(data) {
|
|
|
+ return this.selectedOrgIds.includes(data.id);
|
|
|
+ },
|
|
|
+ deleteTag(event, data) {
|
|
|
+ if (this.selectedOrgIds.includes(data.id)) {
|
|
|
+ this.selectedOrgList = this.selectedOrgList.filter(
|
|
|
+ (item) => item.id !== data.id
|
|
|
+ );
|
|
|
+ this.updateSelectOrgIds();
|
|
|
+ this.emitChange();
|
|
|
+ }
|
|
|
+ event.stopPropagation();
|
|
|
+ },
|
|
|
+ handleClearClick(event) {
|
|
|
+ event.stopPropagation();
|
|
|
+ this.selectedOrgList = [];
|
|
|
+ this.selectedOrg = {};
|
|
|
+ this.updateSelectOrgIds();
|
|
|
+ this.emitChange();
|
|
|
+ this.handleClose();
|
|
|
+ },
|
|
|
+ emitChange() {
|
|
|
+ this.$emit(
|
|
|
+ "input",
|
|
|
+ this.multiple ? this.selectedOrgIds : this.selectedOrgIds[0]
|
|
|
+ );
|
|
|
+ this.$emit(
|
|
|
+ "change",
|
|
|
+ this.multiple ? this.selectedOrgList : this.selectedOrgList[0]
|
|
|
+ );
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|