app-ey-mpicker.vue 13.0 KB
Newer Older
1 2
<template>
    <div class="app-ey-mpicker">
3
        <div class="app-ey-mpicker__item" v-for="count in selectCount" :key="count">
4 5 6 7 8 9 10 11 12 13 14 15 16
            <el-select
                :value="valueItems[count - 1]"
                filterable
                remote
                :remote-method="onSearch"
                size="small"
                @change="onSelect($event, valueItems[count - 1])"
                @clear="onRemove(valueItems[count - 1], true)"
                @visible-change="onSelectOpen($event, count - 1)"
                :clearable="selectCount == 1"
                :disabled="disabled"
            >
                <el-option v-for="(item, index) in items" :key="index" :label="item[deMajorField]" :value="item[deKeyField]"></el-option>
17 18
            </el-select>
            <span class="app-ey-mpicker__search">
19
                <i class="el-icon-search" @click="openView(valueItems[count - 1])"></i>
20 21
            </span>
            <div class="app-ey-mpicker__button">
22 23
                <img v-if="count === selectCount" src="assets/img/ic_add_circle.svg" @click="selectCount++" />
                <img v-else src="assets/img/remove_circle.svg" @click="onRemove(valueItems[count - 1])" />
24 25
            </div>
        </div>
26 27
    </div>
</template>
28 29 30
<script lang="ts">
import { Component, Vue, Prop, Watch } from "vue-property-decorator";
import { Subject } from "rxjs";
31

32
@Component({})
33
export default class AppEYMPicker extends Vue {
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
    /**
     * 传入url
     */
    @Prop() url?: any;

    /**
     * 表单数据
     */
    @Prop() activeData?: any;

    /**
     * 是否禁用
     */
    @Prop() disabled?: boolean;

    /**
     * 编辑器参数
     */
    @Prop() editorParams?: any;

    /**
     * 表单项值
     */
    @Prop() curvalue?: any;

    /**
     * 值项
     */
    @Prop() valueitem?: any;

    /**
     * 局部上下文导航参数
66
     *
67
     * @type {any}
68
     * @memberof AppEYMPicker
69
     */
70
    @Prop() public localContext!: any;
71 72 73

    /**
     * 局部导航参数
74
     *
75
     * @type {any}
76
     * @memberof AppEYMPicker
77
     */
78
    @Prop() public localParam!: any;
79 80 81 82 83

    /**
     * 表单项名称
     */
    @Prop() name: any;
84

85 86 87 88
    /**
     * 视图上下文
     *
     * @type {*}
89
     * @memberof AppEYMPicker
90 91 92 93 94 95 96
     */
    @Prop() public context!: any;

    /**
     * 视图参数
     *
     * @type {*}
97
     * @memberof AppEYMPicker
98 99 100 101 102 103 104
     */
    @Prop() public viewparams!: any;

    /**
     * AC参数
     *
     * @type {*}
105
     * @memberof AppEYMPicker
106
     */
107
    @Prop({ default: () => {} }) public acParams?: any;
108 109 110 111 112

    /**
     * 应用实体主信息属性名称
     *
     * @type {string}
113
     * @memberof AppEYMPicker
114
     */
115
    @Prop({ default: "srfmajortext" }) public deMajorField!: string;
116 117 118 119 120

    /**
     * 应用实体主键属性名称
     *
     * @type {string}
121
     * @memberof AppEYMPicker
122
     */
123
    @Prop({ default: "srfkey" }) public deKeyField!: string;
124 125 126 127 128

    /**
     * 表单服务
     *
     * @type {*}
129
     * @memberof AppEYMPicker
130 131 132 133 134 135 136 137 138 139 140
     */
    @Prop() public service?: any;

    /**
     * 打开对应的选择视图
     */
    @Prop() pickupView?: any;

    /**
     * 当前表单项绑定值key的集合
     */
141
    public valueItems: any = [];
142 143 144 145 146 147 148 149

    /**
     * 所有操作过的下拉选选项
     */
    public items: Array<any> = [];

    /**
     * 选中项key-value键值对
150
     *
151 152 153
     */
    public selectItems: Array<any> = [];

154 155
    /**
     * 选项框数量
156
     *
157 158 159
     */
    public selectCount: number = 1;

160
    /**
161
     * 获取选中label
162
     *
163 164 165 166 167 168 169 170
     */
    public getSelectLabel(index: number) {
        const selection = this.selectItems[index];
        if (selection) {
            return selection[this.deMajorField];
        }
    }

171 172
    /**
     * 监听curvalue值
173 174
     * @param newVal
     * @param val
175
     */
176
    @Watch("curvalue", { immediate: true, deep: true })
177
    oncurvalueChange(newVal: any, val: any) {
178
        this.valueItems = [];
179 180 181
        this.selectItems = [];
        if (newVal) {
            try {
182 183 184 185
                this.selectItems = this.parseValue(JSON.parse(newVal));
                this.selectItems.forEach((item: any) => {
                    this.valueItems.push(item[this.deKeyField]);
                });
186
            } catch (error) {
187 188 189 190 191 192 193 194 195 196 197 198
                if ((error as any).name === "SyntaxError") {
                    let srfkeys: any = newVal.split(",");
                    let srfmajortexts: any = null;
                    if (this.valueitem && this.activeData[this.valueitem]) {
                        srfmajortexts = this.activeData[this.valueitem].split(",");
                    }
                    if (srfkeys.length && srfkeys.length > 0 && srfmajortexts.length && srfmajortexts.length > 0 && srfkeys.length == srfmajortexts.length) {
                        srfkeys.forEach((id: any, index: number) => {
                            this.valueItems.push(id);
                            this.selectItems.push({ [this.deKeyField]: id, [this.deMajorField]: srfmajortexts[index] });
                        });
                    }
199 200 201 202 203 204
                }
            }
        }
        this.$forceUpdate();
    }

205 206 207 208 209 210 211 212 213 214 215 216 217
    /**
     * 下拉切换回调
     * @param boolean
     */
    public onSelectOpen(visible: boolean, index: number): void {
        if (visible) {
            const label = this.getSelectLabel(index);
            if (this.items.length == 0 || !label) {
                this.onSearch(label);
            }
        }
    }

218 219 220 221
    /**
     * 远程执行搜索
     *
     * @param {*} query
222
     * @memberof AppEYMPicker
223 224 225 226 227 228 229 230 231 232 233
     */
    public onSearch(query: any) {
        // 公共参数处理
        let data: any = {};
        const bcancel: boolean = this.handlePublicParams(data);
        if (!bcancel) {
            return;
        }
        // 参数处理
        let _context = data.context;
        let _param = data.param;
234
        Object.assign(_param, { query: query });
235 236 237 238
        if (this.activeData) {
            Object.assign(_param, { srfreferdata: this.activeData });
        }
        // 错误信息国际化
239 240 241 242 243 244 245 246 247
        let error: string = this.$t("components.appMpicker.error") as any;
        let miss: string = this.$t("components.appMpicker.miss") as any;
        let requestException: string = this.$t("components.appMpicker.requestException") as any;
        if (!this.service) {
            this.$Notice.error({ title: error, desc: miss + "service" });
        } else if (!this.acParams.serviceName) {
            this.$Notice.error({ title: error, desc: miss + "serviceName" });
        } else if (!this.acParams.interfaceName) {
            this.$Notice.error({ title: error, desc: miss + "interfaceName" });
248
        } else {
249 250 251 252 253 254 255 256 257 258 259 260
            this.service
                .getItems(this.acParams.serviceName, this.acParams.interfaceName, _context, _param)
                .then((response: any) => {
                    if (!response) {
                        this.$Notice.error({ title: error, desc: requestException });
                    } else {
                        this.items = [...response];
                    }
                })
                .catch((error: any) => {
                    console.log(error);
                });
261 262 263 264 265 266
        }
    }

    /**
     * 下拉选中回调
     *
267
     * @param {*} value
268
     * @memberof AppEYMPicker
269
     */
270 271 272 273
    public onSelect(value: string, valueItem: string) {
        const item = this.items.find((item) => Object.is(item[this.deKeyField], value));
        if (item) {
            this.computeItemSelect([item], valueItem);
274 275 276 277 278 279 280
        }
    }

    /**
     * 移除标签回调
     *
     * @param {*} tag
281
     * @memberof AppEYMPicker
282
     */
283 284
    public onRemove(value: string, isClear: boolean = false) {
        let index = this.selectItems.findIndex((item: any) => Object.is(item[this.deKeyField], value));
285 286
        if (index >= 0) {
            this.selectItems.splice(index, 1);
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
            let value = this.selectItems.length > 0 ? JSON.stringify(this.formatValue(this.selectItems)) : "";
            this.$emit("formitemvaluechange", { name: this.name, value: value });
        }
        if (!isClear) {
            this.selectCount--;
        }
    }

    /**
     * 移除标签回调
     *
     * @param {*} items
     * @memberof AppEYMPicker
     */
    public computeItemSelect(items: any[], value: string) {
        if (value) {
            const index = this.selectItems.findIndex((item: any) => Object.is(item[this.deKeyField], value));
            if (index != -1) {
                this.selectItems.splice(index, 1, ...items);
            }
        } else {
            this.selectItems.push(...items);
        }
        if (this.name && this.activeData) {
            let value = this.selectItems.length > 0 ? JSON.stringify(this.formatValue(this.selectItems)) : "";
            this.$emit("formitemvaluechange", { name: this.name, value: value });
313 314 315 316 317 318 319 320
        }
    }

    /**
     * 公共参数处理
     *
     * @param {*} arg
     * @returns
321
     * @memberof AppEYMPicker
322 323 324
     */
    public handlePublicParams(arg: any): boolean {
        if (!this.activeData) {
325
            this.$Notice.error({ title: this.$t("components.AppMpicker.error") as any, desc: this.$t("components.AppMpicker.formdataException") as any });
326 327 328 329 330 331
            return false;
        }
        // 合并表单参数
        arg.param = this.viewparams ? JSON.parse(JSON.stringify(this.viewparams)) : {};
        arg.context = this.context ? JSON.parse(JSON.stringify(this.context)) : {};
        // 附加参数处理
332 333 334
        if (this.localContext && Object.keys(this.localContext).length > 0) {
            let _context = this.$util.computedNavData(this.activeData, arg.context, arg.param, this.localContext);
            Object.assign(arg.context, _context);
335
        }
336 337 338
        if (this.localParam && Object.keys(this.localParam).length > 0) {
            let _param = this.$util.computedNavData(this.activeData, arg.param, arg.param, this.localParam);
            Object.assign(arg.param, _param);
339 340 341 342 343 344 345 346
        }
        return true;
    }

    /**
     * 打开视图
     *
     * @returns
347
     * @memberof AppEYMPicker
348
     */
349
    public openView(value: string) {
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
        if (this.disabled) {
            return;
        }
        if (this.pickupView && Object.keys(this.pickupView).length > 0) {
            // 参数处理
            const view = { ...this.pickupView };
            // 公共参数处理
            let data: any = {};
            const bcancel: boolean = this.handlePublicParams(data);
            if (!bcancel) {
                return;
            }
            // 参数处理
            let _context = data.context;
            let _viewparams = data.param;
            let _selectItems = JSON.parse(JSON.stringify(this.selectItems));
366 367
            if (!Object.is(this.deKeyField, "srfkey")) {
                _selectItems.forEach((item: any, index: number) => {
368 369 370
                    _selectItems[index].srfkey = item[this.deKeyField];
                });
            }
371 372
            _context = Object.assign(_context, { srfparentdata: { srfparentkey: this.activeData[this.deKeyField] } });
            _viewparams = Object.assign(_viewparams, { selectedData: [..._selectItems] });
373
            let formdata = this.activeData;
374
            const modal: Subject<any> = this.$appmodal.openModal(view, _context, _viewparams);
375
            modal.subscribe((result: any) => {
376
                if (!result || !Object.is(result.ret, "OK")) {
377 378 379 380 381 382 383 384
                    return;
                }
                let selects: Array<any> = [];
                if (result.datas && Array.isArray(result.datas)) {
                    result.datas.forEach((select: any) => {
                        selects.push({ [this.deKeyField]: select[this.deKeyField], [this.deMajorField]: select[this.deMajorField] });
                    });
                }
385 386
                this.computeItemSelect(selects, value);
            });
387 388 389 390 391 392 393
        }
    }

    /**
     * 解析值,把srfkey和srfmajortext解析成实体属性名
     *
     * @param {any[]} value 需要转换的数组
394
     * @memberof AppEYMPicker
395
     */
396
    public parseValue(value: any[]) {
397
        let result = [];
398
        if (this.deKeyField !== "srfkey" || this.deMajorField !== "srfmajortext") {
399
            value.forEach((item: any) => {
400
                result.push({ [this.deMajorField]: item.srfmajortext, [this.deKeyField]: item.srfkey });
401
            });
402
        } else {
403 404 405 406 407 408 409 410 411
            result = value;
        }
        return result;
    }

    /**
     * 格式化值,把实体属性名格式化成srfkey和srfmajortext
     *
     * @param {any[]} value 需要转换的数组
412
     * @memberof AppEYMPicker
413
     */
414
    public formatValue(value: any[]) {
415
        let result = [];
416
        if (this.deKeyField !== "srfkey" || this.deMajorField !== "srfmajortext") {
417
            value.forEach((item: any) => {
418
                result.push({ srfmajortext: item[this.deMajorField], srfkey: item[this.deKeyField] });
419
            });
420
        } else {
421 422
            result = value;
        }
423 424
        const res = new Map();
        return result.filter((item: any) => !res.has(item.srfmajortext) && res.set(item.srfmajortext, item.srfkey));
425 426 427 428
    }
}
</script>
<style lang="scss">
429 430
@import "./app-ey-mpicker.scss";
</style>