|
@@ -0,0 +1,288 @@
|
|
|
+<script>
|
|
|
+import { REFER } from "./api/index";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "PopoverTreeSelect",
|
|
|
+ props: {
|
|
|
+ // v-model
|
|
|
+ value: {
|
|
|
+ type: [Array, String],
|
|
|
+ require: true,
|
|
|
+ },
|
|
|
+ // 参照类型 ,对应后端
|
|
|
+ referName: {
|
|
|
+ type: String,
|
|
|
+ require: true,
|
|
|
+ },
|
|
|
+ // 作为 value 唯一标识的键名,绑定值
|
|
|
+ valueKey: {
|
|
|
+ type: String,
|
|
|
+ dafault: () => {
|
|
|
+ return "code";
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // 默认查询参数
|
|
|
+ queryParams: {
|
|
|
+ type: Function,
|
|
|
+ default: () => {},
|
|
|
+ },
|
|
|
+ // 需映射源数据
|
|
|
+ source: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ // 参照内外映射
|
|
|
+ dataMapping: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ defaultProps: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {
|
|
|
+ return {
|
|
|
+ label: "name",
|
|
|
+ children: "children",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ },
|
|
|
+ onlyFinal: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ components: {},
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ size: "mini",
|
|
|
+ width: "50%",
|
|
|
+ visible: false,
|
|
|
+ loading: false,
|
|
|
+ model: {
|
|
|
+ search: "",
|
|
|
+ isPage: false,
|
|
|
+ },
|
|
|
+ isSure: true,
|
|
|
+ data: [],
|
|
|
+ selectData: [],
|
|
|
+ // defaultProps: {
|
|
|
+ // label: "name",
|
|
|
+ // children: "children",
|
|
|
+ // },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ innerValue: {
|
|
|
+ get() {
|
|
|
+ return this.value;
|
|
|
+ },
|
|
|
+ set(value) {
|
|
|
+ this.$emit("input", value);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ innerValue: {
|
|
|
+ handler: function (newValue) {
|
|
|
+ if (!newValue) {
|
|
|
+ const {
|
|
|
+ $props: { source, dataMapping },
|
|
|
+ } = this;
|
|
|
+ for (let key in dataMapping) {
|
|
|
+ source[key] = undefined;
|
|
|
+ }
|
|
|
+ this.$emit("update:source", source);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // "model.search": {
|
|
|
+ // handler: function (newValue) {
|
|
|
+ // this.$refs.tree.filter(newValue);
|
|
|
+ // },
|
|
|
+ // },
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // open dialog
|
|
|
+ async open() {
|
|
|
+ let { disabled } = this.$attrs;
|
|
|
+ if (!disabled) {
|
|
|
+ this.visible = true;
|
|
|
+ await this.useReset();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // hide dialog
|
|
|
+ async hide() {
|
|
|
+ this.visible = false;
|
|
|
+ },
|
|
|
+ // fetch list
|
|
|
+ async fetchList(prop) {
|
|
|
+ try {
|
|
|
+ this.loading = true;
|
|
|
+ const { referName: type, source, queryParams } = this.$props;
|
|
|
+ const { code, rows } = await REFER({
|
|
|
+ ...prop,
|
|
|
+ ...queryParams(source),
|
|
|
+ type: type,
|
|
|
+ });
|
|
|
+ if (code === 200) {
|
|
|
+ this.data = rows;
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ // catch
|
|
|
+ console.error(err);
|
|
|
+ } finally {
|
|
|
+ // finally
|
|
|
+ this.loading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // reset list
|
|
|
+ async useReset() {
|
|
|
+ this.data = [];
|
|
|
+ this.model.search = null;
|
|
|
+ await this.fetchList(this.model);
|
|
|
+ },
|
|
|
+ // query list
|
|
|
+ async useQuery(value) {
|
|
|
+ // await this.$refs.tree.filter(value);
|
|
|
+ await this.fetchList(this.model);
|
|
|
+ },
|
|
|
+ // auto
|
|
|
+ async useAutocomplete(prop, cb) {
|
|
|
+ if (prop) {
|
|
|
+ this.model.search = prop;
|
|
|
+ await this.fetchList(this.model);
|
|
|
+ await cb(this.data);
|
|
|
+ } else {
|
|
|
+ cb([]);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // select
|
|
|
+ useSelect(prop) {
|
|
|
+ if (this.$props.onlyFinal) {
|
|
|
+ this.isSure = prop.children ? false : true;
|
|
|
+ }
|
|
|
+ this.selectData = [prop];
|
|
|
+ },
|
|
|
+ // filter
|
|
|
+ useTreeFilter(value, data) {
|
|
|
+ if (!value) return true;
|
|
|
+ return data.name.indexOf(value) !== -1;
|
|
|
+ },
|
|
|
+ // confirm
|
|
|
+ useConfirm(prop) {
|
|
|
+ if (this.isSure) {
|
|
|
+ this.hide();
|
|
|
+ const {
|
|
|
+ $props: { source, valueKey, dataMapping },
|
|
|
+ } = this;
|
|
|
+ for (let key in dataMapping) {
|
|
|
+ source[key] = prop[0][dataMapping[key]];
|
|
|
+ }
|
|
|
+ this.innerValue = prop[0][valueKey];
|
|
|
+ console.log(valueKey, "valueKey");
|
|
|
+ console.log(prop[0][valueKey], "prop[0][valueKey]");
|
|
|
+ console.log(this.innerValue, "innerValue");
|
|
|
+ console.log(source, "source");
|
|
|
+ this.$emit("update:source", source);
|
|
|
+ this.$emit("change", prop, this.$props);
|
|
|
+ } else {
|
|
|
+ this.$message.warning({
|
|
|
+ message: "请选择最末级节点",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {},
|
|
|
+ mounted() {},
|
|
|
+ destroyed() {},
|
|
|
+};
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="popover-tree-select">
|
|
|
+ <el-autocomplete
|
|
|
+ v-show="false"
|
|
|
+ v-bind="$attrs"
|
|
|
+ v-model="innerValue"
|
|
|
+ :value-key="valueKey"
|
|
|
+ :fetch-suggestions="useAutocomplete"
|
|
|
+ @select="useConfirm"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <i class="el-icon-search" slot="suffix" @click="open"> </i>
|
|
|
+ <template slot-scope="{ item }">
|
|
|
+ <p
|
|
|
+ style="
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ overflow: hidden;
|
|
|
+ line-height: 15px;
|
|
|
+ margin: 5px 0;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ item.name }}
|
|
|
+ </p>
|
|
|
+ <p
|
|
|
+ style="
|
|
|
+ font-size: 12px;
|
|
|
+ color: #b4b4b4;
|
|
|
+ line-height: 15px;
|
|
|
+ margin: 5px 0;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ item.code }}
|
|
|
+ </p>
|
|
|
+ </template>
|
|
|
+ </el-autocomplete>
|
|
|
+
|
|
|
+ <el-button type="text" :size="$attrs.size" @click="open"> 增行</el-button>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ :width="width"
|
|
|
+ :show-close="false"
|
|
|
+ :visible.sync="visible"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :close-on-press-escape="false"
|
|
|
+ append-to-body
|
|
|
+ style="padding: 10px"
|
|
|
+ >
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ :size="$attrs.size"
|
|
|
+ :loading="loading"
|
|
|
+ @click="useConfirm(selectData)"
|
|
|
+ >确 认</el-button
|
|
|
+ >
|
|
|
+ <el-button :size="$attrs.size" :loading="loading" @click="hide"
|
|
|
+ >取 消</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <el-form
|
|
|
+ v-loading="loading"
|
|
|
+ :size="size"
|
|
|
+ :inline="true"
|
|
|
+ :model="model"
|
|
|
+ @submit.native.prevent
|
|
|
+ >
|
|
|
+ <el-form-item prop="search">
|
|
|
+ <el-input v-model="model.search" @change="useQuery"> </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button icon="el-icon-refresh" @click="useReset"></el-button>
|
|
|
+ </el-form-item>
|
|
|
+ <div style="height: 400px; overflow: auto">
|
|
|
+ <el-tree
|
|
|
+ v-loading="loading"
|
|
|
+ :data="data"
|
|
|
+ :props="defaultProps"
|
|
|
+ :filter-node-method="useTreeFilter"
|
|
|
+ ref="tree"
|
|
|
+ accordion
|
|
|
+ node-key="id"
|
|
|
+ @node-click="useSelect"
|
|
|
+ >
|
|
|
+ </el-tree>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style scoped></style>
|