## 维度选择器  MyDemension.vue

+ `my-demension`组件 
- props属性
|prop | 类型 |  默认值 | 说明|
|:-------|:-------|:-------|:-------|
|validate | String, Object | - | 校验规则|
|value | String |  | v-model绑定的值|
|name | String | - | name|
|placeholder | String | - | placeholder|
|permission | String | 权限校验 | 可选值 [r,b,w,n] r只读, b必填，w编辑,n无权限|
|single | Boolean | false | 是否单选|
|config | Object | - | 数据回填配置|
|select-label | String | - | 已选数据显示指定的属性|

- MyDemension.vue 代码

```html
<template>
  <ht-demension
    v-model="value"
    :validate="validate"
    :name="name"
    select-label="name"
    :placeholder="placeholder"
    :permission="permission"
    :single="single"
    :config="config"
    :data="data"
    :table-columns="tableColumns"
    :pagination="pagination"
    @load="handleLoad"
    @valueChange="valueChange"
  />
</template>
<script>
import selector from "@/api/selector.js";

export default {
  name: "my-demension",
  props: {
    validate: [String, Object],
    value: String,
    name: String,
    placeholder: String,
    permission: String,
    single: Boolean,
    config: Object
  },
  data() {
    return {
      data: [],
      tableColumns:[
        {prop:"name",label:"名称",width:"300"},
        {prop:"code",label:"编码"}
      ],
      pagination: {
        page: 1,
        pageSize: 50,
        total: 0
      }
    };
  },
  methods: {
    handleLoad(param, cb) {
      selector
        .getDem(param)
        .then(response => {
          this.data = response.result;
          this.pagination = response.pagination;
          cb();
        })
        .catch(err => {
          cb();
        });
    },
    valueChange(value) {
      this.$emit("input", value);
    }
  }
};
</script>

```
# ht-demension组件说明
- props 属性说明

|prop | 类型 |  默认值 | 说明|
|:-------|:-------|:-------|:-------|
|validate | String, Object | - | 校验规则|
|value | String |  | v-model绑定的值|
|name | String | [] | name|
|placeholder | String | - | placeholder|
|permission | String | 权限校验 | 可选值 ["b", "w", "r", "n"] r只读, b必填，w编辑 n无权限|
|single | Boolean | false | 是否单选|
|config | Object | - | 数据回填配置|
|select-label | String | - | 已选数据显示指定的属性|
|data | Array | [] | 列表数据|
|table-columns | Array | [] | 自定义列表列|
|pagination | Object |{page: 1,pageSize: 50, total: 0} | 分页参数|

- 事件方法

|事件 | 参数 | 说明|
|:-------|:-------|:-------|
|valueChange | result | 选中值改变时触发 |
|load | params,cb | 加载类表数据 |

- HtDemension.vue 代码
```html
<template>
  <div class="inputs">
    <div style="width: 100%; min-width:180px;" class="el-select" @click="showDialog">
      <div
        ref="tagSpans"
        style="width: calc(100% - 25px);"
        :class="{'el-select__tags_readonly':!inputWriteable, 'el-select__tags':inputWriteable}"
      >
        <span>
          <span
            class="el-tag el-tag--info el-tag--small"
            @click.stop
            v-for="(item,index) in demensions"
            :key="index"
          >
            <span class="el-select__tags-text">{{item.name}}</span>
            <i
              v-if="inputWriteable"
              class="el-tag__close el-icon-close"
              @click="handleRemove(item)"
            ></i>
          </span>
        </span>
      </div>
      <div v-if="inputWriteable" class="el-input el-input--suffix">
        <input
          ref="inputEl"
          type="text"
          readonly="readonly"
          v-validate="inputValidate"
          v-model="value"
          :name="inputName"
          autocomplete="off"
          class="el-input__inner"
          :placeholder="placeholder"
          :style="{height: inputSuffixHeight + 'px'}"
        />
        <span class="el-input__suffix">
          <span class="el-input__suffix-inner">
            <i
              class="el-input__icon icon-department"
              :style="{fontSize:'17px',lineHeight: inputSuffixHeight + 'px'}"
            ></i>
          </span>
        </span>
      </div>
    </div>
    <ht-field-tail :fieldName="inputName" :inputValue="value" />
    <el-dialog
      title="选择维度"
      :visible.sync="dialogVisible"
      width="1000px"
      top="8vh"
      :before-close="handleClose"
      :close-on-click-modal="false"
    >
      <selector
        ref="demSelector"
        @load="load"
        :data="data"
        :pagination="pagination"
        :table-columns="tableColumns"
        :select-label="selectLabel"
        search-placeholder="名称、编码"
        v-model="demensions"
      />
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" size="small" @click="handleDialogSure">确 定</el-button>
        <el-button size="small" @click="handleDialogCancel">取 消</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import utils from "@/utils.js";
import HtFieldTail from "@/components/HtFieldTail.vue";
import Selector from "@/components/common/Selector.vue";
import { setTimeout } from "timers";

export default {
  name: "ht-demension",
  props: {
    validate: [String, Object],
    value: String,
    name: String,
    selectLabel: String,
    placeholder: {
      type: String,
      default: "请输入内容"
    },
    permission: {
      type: String,
      default: "w",
      validator: function(value) {
        return ["b", "w", "r", "n"].indexOf(value) !== -1;
      }
    },
    single: {
      type: Boolean,
      default: false
    },
    config: Object,
    data: {
      type: Array,
      default: () => {
        return [];
      }
    },
    tableColumns: {
      type: Array,
      default: () => {
        return [];
      }
    },
    pagination: {
      type: Object,
      default: () => {
        return {
          page: 1,
          pageSize: 50,
          total: 0
        };
      }
    }
  },
  components: {
    HtFieldTail,
    Selector
  },
  data() {
    return {
      inputName: null,
      inputSuffixHeight: 30,
      demensions: [],
      dialogVisible: false
    };
  },
  computed: {
    inputWriteable: function() {
      return utils.getWriteable(this.permission);
    },
    inputValidate: function() {
      return utils.addRequiredOrNot(this.permission, this.validate, this);
    }
  },
  watch: {
    // 当所选择的数据发生变化时，同步到v-model中
    demensions: function(newVal) {
      let ary = [],
        idAry = [],
        codeAry = [];
      if (newVal && newVal.constructor === Array && newVal.length > 0) {
        newVal.forEach(m => {
          ary.push(m.name);
          if (m.hasOwnProperty("id")) {
            idAry.push(m.id);
          }
          if (m.hasOwnProperty("code")) {
            codeAry.push(m.code);
          }
        });
      }
      if (this.config) {
        // 配置了id的绑定关系，则回填到指定属性上
        if (this.config.hasOwnProperty("id")) {
          utils.setValueByConfigKey(this, this.config, "id", idAry.join(","));
        }
        // 配置了code的绑定关系，则回填到指定的属性上
        if (this.config.hasOwnProperty("code")) {
          utils.setValueByConfigKey(
            this,
            this.config,
            "code",
            codeAry.join(",")
          );
        }
      }
      // 通过valueChange事件发布值变更消息
      this.$emit("valueChange", ary.join(","));
      setTimeout(() => {
        this.calacInputSuffixHeight();
        if (this.$refs.inputEl) {
          this.$refs.inputEl.focus();
          this.$refs.inputEl.blur();
        }
      }, 10);
    },
    value: function(newVal) {
      // 父级传递进来的value发生变更时，需要同步到当前所选数据中
      this.valueInit();
    }
  },
  mounted() {
    // 组件第一次挂载时，同步value到当前所选数据中
    this.valueInit();
  },
  created() {
    this.inputName = this.name ? this.name : utils.getName();
    this.$validator = this.$root.$validator;
  },
  methods: {
    // 同步value到当前所选数据中
    valueInit() {
      let tmpAry = [];
      if (this.value) {
        let idAry = [],
          codeAry = [];
        if (this.config) {
          // 配置了id绑定关系，则获取id的值
          if (this.config.hasOwnProperty("id")) {
            let idVal = utils.getValueByConfigKey(this, this.config, "id");
            if (idVal) {
              idAry = idVal.split(",").trim();
            }
          }
          // 配置了code绑定关系，则获取code的值
          if (this.config.hasOwnProperty("code")) {
            let codeVal = utils.getValueByConfigKey(this, this.config, "code");
            if (codeVal) {
              codeAry = codeVal.split(",").trim();
            }
          }
        }
        // 将name、id、code从逗号分割的字符串解析为json对象格式的数组
        let valAry = this.value.split(",").trim();
        valAry.forEach((m, index) => {
          let item = { name: m };
          if (idAry.length > index) {
            item["id"] = idAry[index];
          }
          if (codeAry.length > index) {
            item["code"] = codeAry[index];
          }
          tmpAry.push(item);
        });
      }
      // 对数组做深度对比，如果值不完全相等，则进行赋值操作
      if (!utils.arrayEquals(tmpAry, this.demensions)) {
        this.demensions = tmpAry;
      }
    },
    showDialog() {
      if (!this.inputWriteable) {
        return;
      }
      this.dialogVisible = true;
      setTimeout(() => {
        this.$refs.demSelector.onShow();
      });
    },
    handleClose(done) {
      this.$refs.demSelector.onHide();
      done && done();
    },
    handleDialogSure() {
      this.dialogVisible = false;
      this.$refs.demSelector.onHide(true);
    },
    handleDialogCancel() {
      this.dialogVisible = false;
      this.$refs.demSelector.onHide();
    },
    handleRemove(item) {
      this.demensions.remove(item);
    },
    // 更新当前输入框的高度来适配已选数据的高度
    calacInputSuffixHeight() {
      if (!this.$refs.tagSpans) return;
      if (this.$refs.tagSpans.offsetHeight) {
        this.inputSuffixHeight = this.$refs.tagSpans.offsetHeight + 5;
      } else {
        this.inputSuffixHeight = 30;
      }
    },
    load(param, cb) {
      this.$emit("load", param, cb);
    }
  }
};
</script>
<style lang="stylus" scoped>
.inputs {
  display: block;
}

.el-select__tags {
  background: #fff;
  margin-left: 1px;
}

.el-select__tags_readonly {
  position: relative;
  top: 50%;
}

.el-input__inner[aria-invalid='true'] {
  border-color: #f56c6c;
}

>>> .el-dialog__header {
  background: #F8F8F8;
  padding: 10px 20px;
  height: 24px;
  line-height: 24px;
  border-bottom: 1px solid #eee;
  border-radius: 2px 2px 0 0;
}

>>> .el-dialog__title {
  font-size: 15px;
  color: #333;
}

>>> .el-dialog__headerbtn {
  top: 14px;
}

>>> .el-dialog__body {
  padding-top: 10px;
  padding-bottom: 10px;
}
</style>

```

## 用户选择器 MyUserSelector.vue HtUserSelector.vue api 与维度选择器基本一致一样
+ 维度 ，组织数据 可参考用户对话框api

## 角色选择器 MyRoleSelector.vue HtRoleSelector.vue  api 与维度选择器一样

## 组织选择器 MyOrgSelector.vue HtOrgSelector.vue  api 与维度选择器一样

## 岗位选择器 MyPostSelector.vue HtPostSelector.vue api 与维度选择器一样

## 职务选择器 MyJobSelector.vue HtJobSelector.vue api 与维度选择器一样