<template>
  <view class="form">
    <view
      v-for="(item, index) in form"
      :key="item.key"
      :style="{ opacity: isReadOnly || item.disabled ? 0.9 : 1 }"
    >
      <view class="form-row">
        <view class="label">
          <text class="required" v-if="item.required">*</text>
          {{ item.label }}
          <view
            class="file"
            v-if="item.type == 'file' && !item.disabled && !isReadOnly"
          >
            <upload
              accept="image"
              v-if="uploadIsShow('image', item.fileType)"
              @uploadCallback="uploadCallback"
            >
              <view hover-class="navigator-hover">
                <image
                  class="image"
                  src="../static/file/image.png"
                  mode="heightFix"
                />
              </view>
            </upload>
            <upload
              accept="video"
              v-if="uploadIsShow('video', item.fileType)"
              @uploadCallback="uploadCallback"
            >
              <view hover-class="navigator-hover">
                <image
                  class="image"
                  src="../static/file/video.png"
                  mode="heightFix"
                />
              </view>
            </upload>
            <upload
              accept="file"
              v-if="uploadIsShow('file', item.fileType)"
              @uploadCallback="uploadCallback"
            >
              <view hover-class="navigator-hover">
                <image
                  class="image"
                  src="../static/file/folder.png"
                  mode="heightFix"
                />
              </view>
            </upload>
          </view>
        </view>
        <view v-if="item.type == 'radio'" class="value-box options">
          <view
            class="option"
            :class="option[item.showKey] == item.value ? 'active' : ''"
            v-for="option in item.options"
            :key="option[item.showKey]"
            :hover-class="isReadOnly || item.disabled ? '' : 'navigator-hover'"
            @click="
              isReadOnly || item.disabled
                ? ''
                : onRadio(option[item.showKey], index)
            "
          >
            {{ option[item.showKey] }}
          </view>
        </view>

        <view
          v-else-if="item.type == 'route'"
          class="value-box tag-box"
          style="justify-content: flex-start; padding-bottom: 6px"
        >
          <view
            class="tag"
            :hover-class="isReadOnly || item.disabled ? '' : 'navigator-hover'"
            v-for="(name, i) in item.value.showList"
            :key="name"
            @click="
              isReadOnly || item.disabled
                ? ''
                : routeHandleDetele(name, i, index)
            "
          >
            {{ name }}
            <text
              v-if="!(isReadOnly || item.disabled)"
              class="iconfont icon-dibu-diudan"
            />
          </view>
          <view
            class="tag"
            v-if="!(isReadOnly || item.disabled)"
            hover-class="navigator-hover"
            @click="routeToAdd(index)"
          >
            去选择
            <text class="iconfont" style="font-weight: bold; font-size: 14px"
              >+</text
            >
          </view>
          <view
            v-if="
              (isReadOnly || item.disabled) && item.value.showList.length == 0
            "
            style="font-size: 14px"
          >
            未添加{{ item.label }}
          </view>
        </view>

        <view
          v-else-if="item.type == 'file'"
          class="value-box"
          style="justify-content: flex-start"
        >
          <view v-if="!item.value.length" class="iconfont"> 暂未上传附件 </view>
          <My_Files
            v-else
            :ref="'My_Files' + index"
            :aDeletion="item.aDeletion"
            :isDelete="item.isDelete && !item.disabled && !isReadOnly"
            @onDeteleFiles="onDeteleFiles"
          />
        </view>
        <view
          v-else-if="item.type == 'location'"
          class="value-box"
          :hover-class="isReadOnly || item.disabled ? '' : 'navigator-hover'"
          style="justify-content: space-between"
          @click="geoLocation(item, index)"
        >
          <view v-if="item.value.address">
            {{ item.value.address }}
            <view style="color: #666; font-size: 12px; margin-top: 6px">
              {{ item.value.time }}
            </view>
          </view>
          <view v-else>
            <text class="iconfont icon-a-wodemendianxinxidizhi" />
            获取当前位置
          </view>
          <text
            v-if="item.value.address && !item.disabled && !isReadOnly"
            class="iconfont icon-dibu-diudan clear"
            @click.stop="clearRowValue(index)"
          />
        </view>

        <label :for="item.label" v-else class="value-box">
          <textarea
            :id="item.label"
            v-if="item.type == 'textarea'"
            class="input textarea"
            :value="item.value"
            auto-height
            @input="onInput($event, index)"
            placeholder-class="placeholder-class"
            :type="item.type"
            :disabled="isReadOnly || item.disabled"
            :password="item.password"
            :placeholder="item.placeholder || '请填写' + item.label"
            :maxlength="item.maxlength || '-1'"
          />
          <input
            :id="item.label"
            v-else
            class="input"
            :value="item.value"
            @input="onInput($event, index)"
            placeholder-class="placeholder-class"
            :type="item.type"
            :disabled="isReadOnly || item.disabled"
            :password="item.password"
            :placeholder="item.placeholder || '请填写' + item.label"
            :maxlength="item.maxlength || '-1'"
          />
          <text
            v-if="item.value && !item.disabled && !isReadOnly"
            class="iconfont icon-dibu-diudan clear"
            @click.stop="clearRowValue(index)"
          />
        </label>
      </view>
    </view>
  </view>
</template>

<script>
let form示例 = [
  {
    label: "工序说明", //标题
    disabled: false, //禁用
    type: "text", //类型
    password: false, //是否密码类型
    placeholder: "",
    value: "",
    maxlength: -1, //最大长度
    required: false, //是否必填
  },
  {
    label: "备注",
    disabled: false, //禁用
    type: "textarea", //类型
    placeholder: "",
    value: "",
    maxlength: -1, //最大长度
    required: false, //是否必填
  },
  {
    label: "是否确认",
    disabled: false, //禁用
    type: "radio", //类型
    value: "",
    options: [
      {
        name: "是",
        value: 1,
      },
      {
        name: "否",
        value: 0,
      },
    ],
    showKey: "name", //必传 唯一值
    selectKey: "", //传值key返回该key的值，不传返回整个选择数据
    required: false, //是否必填
  },
];
import upload from "./my-upload.vue";
import { formatTime } from "../utils/getTime.js";
export default {
  name: "My_form",
  components: { upload },
  computed: {
    uploadIsShow() {
      return function (name, list) {
        return list.some((v) => v == name);
      };
    },
  },
  props: {
    isReadOnly: Boolean,
    onConfirm: Function,
  },
  data() {
    return {
      form: [],
      attachmentids: [], //待绑定附件ID列表
      linksids: [], //待删除附件列表
    };
  },
  methods: {
    render(form, init = false) {
      try {
        if (init) {
          this.form = form.map((v) => {
            if (v.type == "location") {
              v.value = init[v.key] || {
                address: "",
              };
            } else if (v.type == "route") {
              v.value = init[v.key] || {
                showList: [],
                value: [],
              };
            } else {
              v.value = init[v.key] || v.value;
            }
            return v;
          });
          this.filesIndex = this.form.findIndex((v) => v.type == "file");
          if (this.filesIndex != -1 && this.form[this.filesIndex].value.length)
            setTimeout(() => {
              this.$refs["My_Files" + this.filesIndex][0].handleFiles(
                this.form[this.filesIndex].value,
                true
              );
            }, 500);
        } else {
          this.filesIndex = form.findIndex((v) => v.type == "file");
          this.form = form;
        }
      } catch (error) {
        console.log("init报错", error);
        this.form = form;
      }
      this.onComplete();
    },
    onInput(e, index) {
      this.$set(this.form[index], "value", e.detail.value);
      this.onComplete();
    },
    //清空行内容
    clearRowValue(index) {
      let data = this.form[index],
        that = this;
      uni.showModal({
        title: "提示",
        content: `是否确定清空“${data.label}”内容`,
        success: ({ confirm }) => {
          if (confirm) {
            if (data.type == "location") {
              that.form[index].value = {
                address: "",
              };
            } else {
              that.form[index].value = "";
            }
            that.onComplete();
          }
        },
      });
    },
    onRadio(value, index) {
      this.$set(this.form[index], "value", value);
      console.log(this.form[index]);
      this.onComplete();
    },
    //是否完成表单必填
    onComplete() {
      this.$emit(
        "onConfirm",
        this.form
          .filter((v) => v.required)
          .map((v) => {
            if (v.type == "file" && v.required) {
              return v.value.length !== 0;
            } else if (v.type == "location" && v.required) {
              return v.value.address ? v.value.address.length : 0;
            } else if (v.type == "route" && v.required) {
              return v.value.value.length;
            } else {
              return v.required && !(v.value == "");
            }
          })
          .some((v) => !v)
      );
    },
    uploadCallback(attachmentids) {
      this.handleFileLink(attachmentids);
    },
    handleFileLink(attachmentids, ownertable = "temporary", ownerid = 1, data) {
      return new Promise((resolve, reject) => {
        if (!attachmentids || attachmentids.length == 0) return resolve(true);
        this.$Http
          .basic({
            classname: "system.attachment.Attachment",
            method: "createFileLink",
            content: {
              ownertable,
              ownerid,
              usetype: "default",
              attachmentids,
            },
          })
          .then((res) => {
            console.log("跟进记录绑定附件", res);
            if (this.cutoff(res.msg)) return;
            resolve(res.data);
            if (ownertable == "temporary") {
              //临时文件
              console.log(this.form);
              console.log(this.filesIndex);
              if (this.filesIndex != -1)
                this.form[this.filesIndex].value = this.form[
                  this.filesIndex
                ].value.concat(res.data);
              this.attachmentids = this.attachmentids.concat(
                res.data.map((v) => v.attachmentid)
              );
              setTimeout(() => {
                this.$refs["My_Files" + this.filesIndex][0].handleFiles(
                  this.form[this.filesIndex].value,
                  true
                );
              }, 50);
            } else {
              //绑定数据
              this.attachmentids = [];
            }
            this.onComplete();
          });
      });
    },
    //删除附件
    onDeteleFiles({ deleteid, attachmentid }) {
      this.attachmentids = this.attachmentids.filter((v) => v != attachmentid);
      this.form[this.filesIndex].value = this.form[
        this.filesIndex
      ].value.filter((v) => v.attachmentid != attachmentid);
      this.$refs["My_Files" + this.filesIndex][0].handleFiles(
        this.form[this.filesIndex].value,
        true
      );
      if (this.form[this.filesIndex].aDeletion || false)
        this.linksids.push(deleteid);
      this.onComplete();
    },
    //去添加
    routeToAdd(index) {
      let data = this.form[index];
      this.$Http.route = { data, index };
      this.$Http.handleAdd = this.routeHandleAdd.bind(this);
      uni.navigateTo({ url: data.path });
    },
    routeHandleAdd(result) {
      const { data, index } = this.$Http.route;
      data.value = result;
      this.form[index] = data;
      uni.navigateBack();
      delete this.$Http.route;
      delete this.$Http.handleAdd;
      this.onComplete();
    },
    //移除route选项
    routeHandleDetele(name, i, index) {
      let that = this;
      uni.showModal({
        title: "提示",
        content: `是否确定移除"${name}"`,
        success: ({ confirm }) => {
          if (confirm) {
            that.form[index].value.showList.splice(i, 1);
            that.form[index].value.value.splice(i, 1);
            that.onComplete();
          }
        },
      });
    },
    //异步删除文件
    handleDeteleFiles(linksids) {
      return new Promise((resolve, reject) => {
        if (!linksids || linksids.length == 0) return resolve(true);
        this.$Http
          .basic({
            classname: "system.attachment.Attachment",
            method: "deleteFileLink",
            content: {
              linksids,
            },
          })
          .then((res) => {
            console.log("处理删除附件", res);
            if (this.cutoff(res.msg)) return;
            resolve(res);
          });
      });
    },
    geoLocation(item, index) {
      let that = this;
      if (item.value.longitude) {
        uni.showModal({
          title: "提示",
          content: "是否确定重新获取定位",
          success: ({ confirm }) => {
            if (confirm) handle();
          },
        });
      } else {
        handle();
      }
      function handle() {
        uni.showLoading({
          title: "定位中...",
          mask: true,
        });
        that.getLocation(true).then((res) => {
          console.log("定位", res);
          uni.hideLoading();
          if (res.errMsg != "getLocation:ok")
            return uni.showToast({
              title: "定位失败",
              icon: "none",
            });
          that.form[index].value = {
            longitude: res.longitude,
            latitude: res.latitude,
            address: res.result.formatted_address,
            time: formatTime(),
            result: res.result,
          };
          that.onComplete();
        });
      }
    },
    onSubmit() {
      let res = {};
      //是否存在附件
      if (this.filesIndex != -1) {
        res.attachmentids = this.attachmentids;
        res.linksids = this.linksids;
      }
      this.form.forEach((v) => {
        if (v.type == "radio") {
          v.value = v.options.find((s) => s[v.showKey] == v.value);
          if (v.selectKey) v.value = v.value[v.selectKey];
        }
        if (v.key) res[v.key] = v.value;
      });
      return res;
    },
  },
};
</script>

<style lang="scss" scoped>
.form {
  width: 355px;
  margin: 0 auto;

  .form-row {
    margin-top: 10px;

    .label {
      display: flex;
      color: #ddd;
      font-size: 12px;

      .required {
        color: #fa3534;
        margin-right: 3px;
      }

      .file {
        display: flex;
        flex: 1;
        justify-content: flex-end;

        /deep/ .u-upload {
          flex: 0 !important;
        }

        .image {
          height: 18px;
          margin-right: 10px;
        }
      }
    }

    .value-box {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 355px;
      background: #fff;
      margin-top: 10px;
      box-sizing: border-box;
      padding: 10px;
      border-radius: 4px;
      overflow: hidden;
      min-height: 40px;

      .input {
        flex: 1;
        font-size: 14px;
      }

      .iconfont {
        font-size: 14px;
      }

      .textarea {
        padding: 0 !important;
        margin: 0 !important;
      }

      .placeholder-class {
        font-size: 14px;
      }

      .clear {
        padding-left: 4px;
        font-size: 14px;
        opacity: 0.9;
      }

      .tag {
        display: flex;
        align-items: center;
        padding: 4px 6px;
        background: #0054e1;
        color: #fff;
        border-radius: 4px;
        font-size: 13px;
        margin-right: 6px;
        margin-bottom: 4px;

        .iconfont {
          margin-left: 5px;
          font-size: 12px !important;
        }
      }
    }

    .tag-box {
      flex-wrap: wrap;

      .tag {
        flex-shrink: 0;
      }
    }

    .options {
      flex-wrap: wrap;
      justify-content: flex-start;

      .option {
        font-size: 12px;
        padding: 4px 6px;
        border-radius: 4px;
        border: 1px solid #ddd;
        margin-right: 6px;
      }

      .active {
        border: 0;
        background: #0054e1;
        color: #fff;
      }
    }
  }
}
</style>