<template>
  <el-row :gutter="20">
    <el-col :span="20">
      <MdView>
        <template>
          # 输入框
          常见的输入框，Element-UI已经有较为完整的组件库及相应的开发手册了，但是在通过这些组件来构建页面时，对于组件的显示、隐藏，常规或者特殊的校验，
          组件之间的联动、级联、计算等等，都需要自行实现，所以Hotent-UI就是在Element-UI的基础上增强了组件这方面能力。
        </template>
      </MdView>

      <CodeBox name="单行文本" alias="singleText" :code="code.singleText" desc="单行文本。">
        <ht-input v-model="data.name" permission="b" placeholder="姓名" :clearable="false" />
      </CodeBox>

      <CodeBox name="数字输入框" alias="numberText" :code="code.numberText" desc="数字输入框。">
        <ht-input type="number" v-model="data.age" placeholder="年龄" :step="2" :min="12" :max="99" />
      </CodeBox>

      <CodeBox name="多行文本" alias="multipleText" :code="code.multipleText" desc="多行文本。">
        <ht-input
          type="textarea"
          v-model="data.memo"
          :cols="80"
          :autosize="{ minRows: 2, maxRows: 4}"
          placeholder="备注"
        />
      </CodeBox>

      <CodeBox
        name="数学计算"
        alias="mathCalculation"
        :code="code.math"
        desc="这个功能实现了输入框之间的数学计算。特别注意：如果在子表的多条数据中进行计算时，需要指定data-subname属性，并为每条数据指定data-index索引。"
      >
        <div v-form>
          <label class="item-label">相加:</label>
          <div class="flex">
            <ht-input class="m-r" v-model="data.math1" placeholder="数字1" />
            <span class="m-r">+</span>
            <ht-input class="m-r" v-model="data.math2" placeholder="数字2" />
            <span class="m-r">=</span>
            <ht-input
              class="m-r"
              v-model="data.math3"
              disabled
              placeholder="数字1 + 数字2"
              math-exp="{数字1(data.math1)} + {数字2(data.math2)}"
            />
          </div>
          <el-divider />
          <div>
            <label class="item-label">子表每行分别计算，再对列求和:</label>
            <br />
            <ul class="math-ul">
              <li
                v-for="(row, index) in data.sub"
                :key="index"
                :data-index="index"
                data-subname="data.sub"
              >
                <div class="flex">
                  <ht-input class="m-r" v-model="row.dj" placeholder="单价" />
                  <ht-input class="m-r" v-model="row.sl" placeholder="数量" />
                  <ht-input
                    class="m-r"
                    v-model="row.xj"
                    placeholder="小计"
                    math-exp="{单价(row.dj)} * {数量(row.sl)}"
                  />
                  <el-link type="danger" class="m-r" @click="data.sub.remove(row)">删除</el-link>
                </div>
              </li>
              <li>
                <div class="flex">
                  <el-button
                    type="primary"
                    class="m-r"
                    size="small"
                    @click="data.sub.push({})"
                  >添加一行数据</el-button>
                  <label class="item-label">对子表小计求和:</label>
                  <ht-input
                    class="m-r"
                    v-model="data.math4"
                    placeholder="对子表中的小计求和"
                    math-exp="FormMath.sum([{小计(data.sub.xj)}])"
                  />
                </div>
              </li>
            </ul>
          </div>
        </div>
      </CodeBox>

      <CodeBox
        name="联动"
        alias="linkage"
        :code="code.linkage"
        desc="当下拉框、复选框、单选按钮选择相应的选项时，可以按照配置的规则联动其他的控件，例如隐藏/显示，必填/非必填，置空，校验规则等联动效果。这种联动是遵循轨迹回弹的，即：如果选择A时显示该控件，则选非A时不显示该控件，无需再配置选B、C时隐藏该控件。"
      >
        <template>
          <div class="flex">
            <label class="item-label">兴趣爱好(后面的输入框在显示和隐藏之间切换):</label>
            <ht-select
              v-model="data.ah"
              class="m-r"
              :options="[{ key: '1', value: '爬山' },{ key: '2', value: '游泳' },{ key: '3', value: '下棋' }]"
              :linkage="[{'value':'1','effect':[{'target':'permission.shan', 'type': '=','value':'w'}]},
              {'value':'2','effect':[{'target': 'permission.yong', 'type': '=', 'value': 'b'},{target: 'validate.yong',type:'+',value:'is:仰泳'}]},{'value':'3','effect':[{'target': 'permission.qi', 'type': '=', 'value': 'w'}]}]"
            />
            <ht-input :permission="permission.shan" v-model="data.shan" placeholder="喜欢爬哪座山" />
            <ht-input
              :permission="permission.yong"
              v-model="data.yong"
              :validate="validate.yong"
              placeholder="喜欢哪种泳姿"
            />
            <ht-input :permission="permission.qi" v-model="data.qi" placeholder="喜欢哪种棋" />
          </div>
          <el-divider />
          <div class="flex">
            <label class="item-label">联系方式(后面的输入框会切换不同的校验规则):</label>
            <ht-radio
              v-model="data.lxfs"
              :options="[{ key: '1', value: 'Email' },{ key: '2', value: '手机' }]"
              :linkage="[{'value':'1','effect':[{'target':'validate.lxdz', 'type': '+','value':'email'}]},{'value':'2','effect':[{'target':'validate.lxdz', 'type': '+','value':'mobile'}]}]"
            />
            <ht-input v-model="data.lxdz" :validate="validate.lxdz" />
          </div>
          <el-divider />
          <div class="flex">
            <label class="item-label">领款方式(后面的输入框的内容会置空):</label>
            <ht-checkbox
              v-model="data.lkfs"
              :options="[{ key: '1', value: '银行卡' },{ key: '2', value: '现金' }]"
              :linkage="[{'value':'2','effect':[{'target':'data.yhkh', 'type': '=','value':''}]}]"
            />
            <ht-input v-model="data.yhkh" />
          </div>
        </template>
      </CodeBox>

      <CodeBox
        name="校验规则"
        alias="validation"
        :code="code.validation"
        desc="支持常见的检验规则、正则表达式、后台校验、js方法四种校验模式。"
      >
        <template>
          <div class="flex">
            <label class="item-label">选择校验规则：</label>
            <ht-select class="m-r" :options="validate.dic" v-model="validate.current" />
            <div class="m-r" v-if="currentValidateArgsNumber > 0">
              <label class="item-label">第一个参数：</label>
              <ht-input v-model="validate.arg1" placeholder="校验规则的第一个参数" />
            </div>
            <div class="m-r" v-if="currentValidateArgsNumber > 1">
              <label class="item-label">第二个参数：</label>
              <ht-input v-model="validate.arg2" placeholder="校验规则的第二个参数" />
            </div>
            <div class="m-r" v-if="currentValidateHasTarget">
              <label class="item-label">检验关联对象：</label>
              <ht-select
                :options="[{key: 'wb2', value: '输入框二'},{key: 'rq2', value: '结束时间'}]"
                v-model="validate.target"
              />
            </div>
            <div class="m-r" v-if="validate.current=='method'">
              <label class="item-label">自定义方法：</label>
              <ht-input class="m-r" type="textarea" :rows="4" v-model="validate.method" />
              <label class="item-label">提示信息：</label>
              <ht-input v-model="validate.message" />
            </div>
          </div>
          <el-divider />
          <div style="margin-bottom: 15px">
            <el-tooltip class="m-r" v-if="validateExp" content="生成的校验规则">
              <i class="icon-tips" style="font-size: 14px; font-weight: bold;" />
            </el-tooltip>
            <span>{{validateExp}}</span>
          </div>
          <label class="item-label">输入框一：</label>
          <ht-input v-model="data.wb1" :validate="validateExp" />
          <div v-if="currentValidateHasTarget && currentValidateHasTarget!='date'">
            <label class="item-label">输入框二：</label>
            <ht-input v-model="data.wb2" name="wb2" />
          </div>
          <el-divider />
          <div v-if="currentValidateHasTarget=='date'">
            <label class="item-label">开始时间：</label>
            <ht-date class="m-r" v-model="data.rq1" :validate="validateExp" />
            <label class="item-label">结束时间：</label>
            <ht-date v-model="data.rq2" name="rq2" />
          </div>
        </template>
      </CodeBox>

      <CodeBox
        name="权限控制"
        alias="permission"
        :code="code.permission"
        desc="这个单行文本实现了控件的只读、编辑、必填权限，而且权限在变更后对输入框的影响会立即生效。"
      >
        <div>
          <label class="item-label">权限控制:</label>
          <ht-radio
            v-model="permission.xm"
            :options="[{key:'r',value:'只读'},{key:'w',value:'编辑'},{key:'b',value:'必填'}]"
          />
          <el-divider />
          <ht-input v-model="data.xm" :permission="permission.xm" placeholder="请输入您的姓名" />
        </div>
      </CodeBox>

      <CodeBox
        name="下拉框权限控制"
        alias="selectPermission"
        :code="code.selectPermission"
        desc="对下拉框的权限控制。"
      >
        <div>
          <label class="item-label">权限控制:</label>
          <ht-radio
            v-model="permission.xlk"
            :options="[{key:'r',value:'只读'},{key:'w',value:'编辑'},{key:'b',value:'必填'}]"
          />
          <el-divider />
          <ht-select v-model="data.xlk" :permission="permission.xlk" :options="options.xlk" />

          <el-button
            size="small"
            style="margin-left:10px"
            type="danger"
            @click="options.xlk=[]"
          >清空下拉框选项</el-button>
        </div>
      </CodeBox>

      <MdView id="api">
        <template>
          # API
          ## Options
          | 参数 | 说明 | 类型 | 可选值 | 默认值 |
          | :------ | :------ | :------ | :------ | :------ |
          | validate | 校验规则 | string/object | 请参照[校验规则](validation)查看可选值 | - |
          | name | 名称 | string | - | - |
          | permission | 权限 | string | n/r/w/b，分别表示：无权限、只读、编辑、必填权限 | w |
          | type | 类型 | string | number,textarea,text和其他[原生input的type值](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types) | text |
          | clearable | 是否可清空 | boolean | - | true |
          | show-password | 是否为密码 | boolean | - | false |
          | math-exp | 数学计算表达式 | string | 请参照[数学计算](math)查看表达式语法 | - |
          | date-calc-exp | 日期计算表达式 | string | 请参照[日期计算](http://www.baidu.com)查看表达式语法 | - |
          | linkage | 联动表达式 | arrry/object | 请参照[联动](linkage)查看联动介绍，只有`ht-select,ht-radio,ht-checkbox`有该属性 | - |
          | placeholder | 输入提示语 | string | - | 请输入内容 |
          | readonly | 是否只读 | boolean | - | false |
          | disabled | 是否不可用 | boolean | - | false |
          | min | 数字最小值 | number | - | - |
          | max | 数字最大值 | number | - | - |
          | step | 数字的步长（type为number时才生效） | number | - | 1 |
          | step-strictly | 是否只能输入 step 的倍数 （type为number时才生效）| boolean | - | false |
          | precision | 数字精度（type为number时才生效）| number | - | - |
          | cols | 文本列数（type为textarea时才生效） | number | - | 60 |
          | rows | 文本的行数（type为textarea时才生效） | number | - | 2 |
          | autosize | 自适应内容高度（type为textarea时才生效），可传入对象，如，{ minRows: 2, maxRows: 6 } | boolean/object | - | false |
          | prefix-icon | 输入框头部图标 | string | - | - |
          | suffix-icon | 输入框尾部图标 | string | - | - |
          | tabindex | 输入框的tabindex | string | - | - |
          ## slots
          | name | 说明 |
          | :------ | :------ |
          | prefix | 输入框头部内容，只对 type="text" 有效 |
          | suffix | 输入框尾部内容，只对 type="text" 有效 |
          | prepend | 输入框前置内容，只对 type="text" 有效 |
          | append | 输入框后置内容，只对 type="text" 有效 |
          ## input events
          | 事件名称 | 说明 | 参数 |
          | :------ | :------ | :------ |
          |blur| 在 Input 失去焦点时触发| (event: Event) |
          |focus| 在 Input 获得焦点时触发| (event: Event) |
          |change| 仅在输入框失去焦点或用户按下回车时触发| (value: string | number) |
          |input| 在 Input 值改变时触发| (value: string | number) |
          |clear| 在点击由`clearable`属性生成的清空按钮时触发 | - |
        </template>
      </MdView>
    </el-col>
    <el-col :span="4">
      <AnchorWrapper :anchors="code.anchors" />
    </el-col>
  </el-row>
</template>
<script>
import CodeBox from "@/components/CodeBox.vue";
import AnchorWrapper from "@/components/AnchorWrapper.vue";
import MdView from "@/views/MdView.vue";
import InputCode from "@/demo/html/input.code.js";
import ValidateDic from "@/demo/html/validate.dic.js";

export default {
  name: "Form",
  components: { CodeBox, AnchorWrapper, MdView },
  data() {
    return {
      data: {
        name: null,
        xm: null,
        age: null,
        ah: null,
        shan: null,
        yong: null,
        qi: null,
        yz: null,
        lxfs: "1",
        lxdz: "13912345678@139.com",
        lkfs: null,
        yhkh: null,
        memo: null,
        math1: null,
        math2: null,
        math3: null,
        xlk: "3",
        sub: [{ dj: null, sl: null, xj: null }],
      },
      options: {
        xlk: [
          { key: "1", value: "选项一" },
          { key: "2", value: "选项二" },
          { key: "3", value: "选项三" },
        ],
      },
      permission: {
        xm: "w",
        shan: "n",
        yong: "n",
        qi: "n",
      },
      validate: {
        dic: ValidateDic,
        current: null,
        arg1: null,
        arg2: null,
        target: null,
        method: null,
        message: null,
        yong: "required",
        lxdz: null,
      },
      code: InputCode,
    };
  },
  computed: {
    currentValidateArgsNumber: function () {
      return this.validate.current
        ? this.validate.dic.find((m) => m.key == this.validate.current)["args"]
        : 0;
    },
    currentValidateHasTarget: function () {
      return this.validate.current
        ? this.validate.dic.find((m) => m.key == this.validate.current)[
            "target"
          ]
        : false;
    },
    validateExp: function () {
      if (this.validate.current == "method" && this.validate.method) {
        let _method = null;
        try {
          _method = eval(`(${this.validate.method})`);
        } catch (e) {}
        if (_method && typeof _method == "function") {
          if (this.validate.message) {
            return {
              method: { callback: _method, message: this.validate.message },
            };
          } else {
            return { method: _method };
          }
        }
        return null;
      }
      if (this.currentValidateHasTarget) {
        return this.validate.target
          ? `${this.validate.current}:${this.validate.target}`
          : this.validate.current;
      }
      if (this.currentValidateArgsNumber == 1) {
        return this.validate.arg1
          ? `${this.validate.current}:${this.validate.arg1}`
          : this.validate.current;
      }
      if (this.currentValidateArgsNumber == 2) {
        return this.validate.arg1 && this.validate.arg2
          ? `${this.validate.current}:${this.validate.arg1},${this.validate.arg2}`
          : this.validate.current;
      }
      return this.validate.current;
    },
  },
};
</script>
<style scoped>
.m-r {
  margin-right: 15px;
}

.math-ul {
  list-style: none;
  padding: 0px;
  display: inline-block;
}

.math-ul > li {
  border: 1px solid #ededed;
  margin: 10px 0;
  padding: 10px;
}
</style>
