VUE實現的三級聯動通用組件

 業務上有共性的功能模塊,可以提煉爲單獨的組件,用的時候只需要聲明和引入即可。

 組件代碼

 

<template>
    <div class="el-form-item el-form-item--mini">
        <el-form-item
                :prop="areaItemName.areaProvince"
                :label="title"
                class="inline-item city">
            <el-select
                    v-model.number="areaForm.areaProvince"
                    :loading="cityLoading"
                    @change="cityChange"
                    placeholder="請選擇"
                    clearable
                    :style="{ width: itemCfg.inputWidth }">
                <el-option
                        v-for="cty in cityList"
                        :key="cty.prcName"
                        :label="cty.prcName"
                        :value="cty.prcId">
                    <template v-if="cityLoading" slot="prefix">
                        <i class="el-icon-loading"></i>
                    </template>
                </el-option>
            </el-select>
        </el-form-item>
        <el-form-item
                :prop="areaItemName.areaCity"
                label-width="20px"
                class="inline-item street">
            <el-select
                    v-model.number="areaForm.areaCity"
                    :loading="streetLoading"
                    @change="streetChange"
                    placeholder="請選擇"
                    clearable
                    :style="{ width: itemCfg.inputWidth }">
                <el-option
                        v-for="cty in streetList"
                        :key="cty.prcName"
                        :label="cty.prcName"
                        :value="cty.prcId">
                    <template v-if="streetLoading" slot="prefix">
                        <i class="el-icon-loading"></i>
                    </template>
                </el-option>
            </el-select>
        </el-form-item>
        <el-form-item
                :prop="areaItemName.areaArea"
                label-width="20px"
                class="inline-item village">
            <el-select
                    v-model.number="areaForm.areaArea"
                    :loading="villageLoading"
                    placeholder="請選擇"
                    clearable
                    :style="{ width: itemCfg.inputWidth }">
                <el-option
                        v-for="cty in villageList"
                        :key="cty.prcName"
                        :label="cty.prcName"
                        :value="cty.prcId">
                </el-option>
                <template v-if="villageLoading" slot="prefix">
                    <i class="el-icon-loading"></i>
                </template>
            </el-select>
        </el-form-item>
    </div>
</template>

<script>
    import {getProvinces} from "@/api/common.js";
    import {getChildrenOfProvincial} from "@/api/common.js";

    export default {
        name: "City",
        props: {
            title: String,
            areaForm: {
                type: Object,
                default: () => {
                    return {
                        areaProvince: "",
                        areaCity: "",
                        areaArea: "",
                    };
                }
            },
            itemCfg: {//基礎配置
                type: Object,
                default: () => {
                    return {
                        inputWidth: "110px",//默認input寬度
                        labelWidth: "" //label寬度
                    };
                }
            },
            // 配置字段名稱
            areaItemName: {
                type: Object,
                default: () => {
                    return {
                        areaProvince: "areaProvince",
                        areaCity: "areaCity",
                        areaArea: "areaArea",
                    };
                }
            }
        },
        computed: {},
        created() {
            this.resetFormItemVal();
            getProvinces().then(res => {
                this.cityList = res.data;
                this.cityLoading = false;
            });
            ;
        },
        data() {
            return {
                cityLoading: false,
                streetLoading: false,
                villageLoading: false,
                cityList: [],
                streetList: [],
                villageList: []
            };
        },
        methods: {
            toNum(val) {
                if (val && !isNaN(val)) {
                    return Number(val);
                } else {
                    return "";
                }
            },
            resetFormItemVal() {
                this.areaForm.areaProvince = this.toNum(this.areaForm.areaProvince);
                this.areaForm.areaCity = this.toNum(this.areaForm.areaCity);
                this.areaForm.areaArea = this.toNum(this.areaForm.areaArea);
            },
            async cityChange(data) {
                try {
                    this.streetLoading = true;
                    this.villageList = this.streetList = [];
                    this.areaForm.areaArea = this.areaForm.areaCity = null;
                    this.streetLoading = false;
                    if (!data || data === '') {
                        this.streetLoading = false;
                        return;
                    }
                    getChildrenOfProvincial({"type": 1, "parentId": data, "sign": "asdasda"}).then(res => {
                        this.streetList = res.data;
                        this.streetLoading = false;
                    });
                } catch (error) {
                    this.streetLoading = false;
                }
            },
            async streetChange(data) {
                try {
                    this.villageLoading = true;
                    this.villageList = [];
                    this.areaForm.areaArea = null;
                    this.villageLoading = false;
                    if (!data || data === '') {
                        this.villageLoading = false;
                        return;
                    }
                    getChildrenOfProvincial({"type": 1, "parentId": data, "sign": "asdasda"}).then(res => {
                        this.villageList = res.data;
                        this.villageLoading = false;
                    });
                } catch (error) {
                    this.villageLoading = false;
                }
            },
        }
    };
</script>

common.js

import request from "@/utils/request";

export function getArea(data) {
    return request({
        url: "/api/company/findCompanyList",
        method: "post",
        data
    });
}

export function getProvinces() {
    return request({
        url: "/api/company/findProvinces",
        method: "post"
    });
}

export function getChildrenOfProvincial(data) {
    return request({
        url: "/api/company/findChildrenOfProvincial",
        method: "post",
        data
    });
}

let subFormFields = ["cityCompanyId", "branchCompanyId", "serviceCenterId", "areaArea", "areaCity", "areaProvince"];

/**
 * 封裝組件form參數字段
 * @param postData
 * @param areaCondition
 * @param cityCondition
 * @returns {*}
 */
export function initForm(postData, area, city) {
    let areaCondition, cityCondition;
    if (area) {
        areaCondition = area.areaForm;
    }
    if (city)
        cityCondition = city.areaForm

    if (postData)
        for (let i = 0; i < subFormFields.length; i++) {
            delete postData[subFormFields[i]];
        }

    if (areaCondition)
        for (var key in areaCondition) {
            if (areaCondition[key])
                postData[key] = areaCondition[key];
        }

    if (cityCondition)
        for (key in cityCondition) {
            if (cityCondition[key])
                postData[key] = cityCondition[key];
        }

    return postData
}

 request.js

import axios from "axios";
import store from "@/store";
import {Message, MessageBox} from "element-ui";

var Base64 = {
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    encode: function (e) {
        var t = "";
        var n, r, i, s, o, u, a;
        var f = 0;
        e = Base64._utf8_encode(e);
        while (f < e.length) {
            n = e.charCodeAt(f++);
            r = e.charCodeAt(f++);
            i = e.charCodeAt(f++);
            s = n >> 2;
            o = (n & 3) << 4 | r >> 4;
            u = (r & 15) << 2 | i >> 6;
            a = i & 63;
            if (isNaN(r)) {
                u = a = 64
            } else if (isNaN(i)) {
                a = 64
            }
            t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
        }
        return t
    },
    _utf8_encode: function (e) {
        e = e.replace(/rn/g, "n");
        var t = "";
        for (var n = 0; n < e.length; n++) {
            var r = e.charCodeAt(n);
            if (r < 128) {
                t += String.fromCharCode(r)
            } else if (r > 127 && r < 2048) {
                t += String.fromCharCode(r >> 6 | 192);
                t += String.fromCharCode(r & 63 | 128)
            } else {
                t += String.fromCharCode(r >> 12 | 224);
                t += String.fromCharCode(r >> 6 & 63 | 128);
                t += String.fromCharCode(r & 63 | 128)
            }
        }
        return t
    }
}

var Convert = {
    convert: function (data) {
        var userInfo = {};
        if (data) {
            data = eval("(" + data + ")")
            userInfo["userId"] = data["global_user_id"];
            userInfo["displayName"] = data["display_name"];
            userInfo["loginName"] = data["login_name"];
        }
        return JSON.stringify(userInfo);
    }
}

const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
    // withCredentials: true, // send cookies when cross-domain requests
    // crossDomain: true,
    timeout: 60000,// request timeout
    headers: {
        "uInfo": Base64.encode(!localStorage ? "{}" : Convert.convert(localStorage.getItem("uInfo")))
    } //用戶json信息
});

service.interceptors.response.use(
    response => {
        const res = response.data;

        // if the custom code is not 20000, it is judged as an error.
        if (res.result !== 0) {
            Message({
                message: res.message || "Error",
                type: "error",
                duration: 5 * 1000
            });

            // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
            if (res.result === 50008 || res.result === 50012 || res.result === 50014) {
                // to re-login
                MessageBox.confirm("You have been logged out, you can cancel to stay on this page, or log in again", "Confirm logout", {
                    confirmButtonText: "Re-Login",
                    cancelButtonText: "Cancel",
                    type: "warning"
                }).then(() => {
                    store.dispatch("user/resetToken").then(() => {
                        location.reload();
                    });
                });
            }
            return Promise.reject(new Error(res.message || "Error"))
        } else {
            return res;
        }
    },
    error => {
        console.log("err" + error);
        Message({
            message: error.message,
            type: "error",
            duration: 5 * 1000
        });
        return Promise.reject(error);
    }
);

export default service;



 表單引用

   <el-form :inline="true" :model="query" class="demo-form-inline">
                <City title="省市區" ref="city"></City> 
                  .....
                <el-form-item>
                    <el-button type="primary" @click="loadData">查詢</el-button>
                </el-form-item>
   </el-form>
    <script>
    import City from "@/components/City.vue";

    export default {
        name: "userList",
        components: {City},

    loadData() {
                this.tbLoading = true;
                let postData = this.query;
                postData.currentPage = this.currentPage;
                postData.pageSize = this.pageSize;

                postData = initForm(postData,this.$refs.city)

                searchData(postData)
                    .then(res => {
                        .....
                    })
                    .finally(() => {
                        this.tbLoading = false;
                    });
            },

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章