import { CreateElement, VNode } from "vue";
import moment from "moment";
import { getToken } from "@/utils/auth";
import { deepCopy, formatFileSize, formatTime, debounce } from "@/utils/index";
import { uploadSize } from "@/settings";
import axios from "axios";
import { flowList } from "@/api/flow";
import MobilePicker from '@/components/MobilePicker/index.vue';
import MobileMultipleSelect from "@/components/MobileMultipleSelect/index.vue";
import { Message } from 'element-ui'
function isJSON(str) {
  if (typeof str !== 'string') return false;
  try {
    const result = JSON.parse(str);
    const type = Object.prototype.toString.call(result);
    return type === '[object Object]' || type === '[object Array]';
  } catch (e) {
    return false;
  }
}
/**
 * @param {String} device 'desktop' | 'mobile'
 * @param {Object} info field参数
 * @param {CreateElement} h
 * @param {Object} row 子表单的row
 * @param {Boolean} pWrite 主表单中子表单字段是否可写
 * @param {Boolean} pReadable
 * @return {VNode} 主表单包含el-form-item 子表单表单组件
 **/
export default function formBuilder(
  device,
  info,
  h,
  row,
  pWrite = false,
  pReadable = false,
  pname
) {
  let target = row ? row : this.form;
  let formItem;
  //下拉选项
  let options = [];
  if (info?.selection_model) {
    options = info.selection_model_items || [];
  } else if (info?.stub) {
    options = info?.stub?.split(/\r\n/) || [];
  }
  if (device === "desktop") {
    //  可写并且不为查看和子表单下
    if (
      info._writeable ||
      (info.type === "relation" && info._readable) ||
      pWrite
    ) {
      switch (info.type) {
        case "text":
          formItem = h("el-input", {
            props: {
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "textarea":
          formItem = h("el-input", {
            props: {
              type: "textarea",
              autosize: {
                minRows: 2,
              },
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "date":
          formItem = h("el-date-picker", {
            props: {
              type: "date",
              "value-format": "yyyy-MM-dd",
              format: "yyyy年MM月dd日",
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text,
              "picker-options": {
                shortcuts: this.shortcuts,
              },
            },
            attrs: {
              placeholder: info.help_text,
            },
            style: {
              width: "100%",
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "datetime":
          formItem = h("el-date-picker", {
            props: {
              type: "datetime",
              "value-format": "yyyy-MM-dd HH:mm:ss",
              format: "yyyy-MM-dd HH:mm",
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text,
              "picker-options": {
                shortcuts: this.shortcuts,
              },
            },
            style: {
              width: "100%",
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "choice":
        case "select":
          const getSelectValue = () => {
            if (!!info.multiple) {
              return target[info.name]
                ? target[info.name]
                    .toString()
                    ?.split(/,|\|/)
                    .map((i) => {
                      return ((isNaN(Number(i)) || !i) ? i : Number(i))
                    })
                : [];
            } else {
              return (isNaN(Number(target[info.name])) || !target[info.name])
                ? target[info.name]
                : Number(target[info.name]);
            }
          };
          formItem = h(
            "el-select",
            {
              props: {
                value: getSelectValue(),
                clearable: true,
                placeholder: info.help_text,
                multiple: !!info.multiple,
                "multiple-limit": info.multiple,
                filterable: true,
                "value-key": "id",
                "reserve-keyword": true,
                "allow-create": !!info.is_select2_tag,
                "default-first-option": true,
              },
              style: {
                width: "100%",
              },
              attrs: {
                placeholder: info.help_text,
              },
              on: {
                input: (e) => {
                  this.$set(target, info.name, e.toString());
                },
              },
            },
            options.map((option) =>
              h("el-option", {
                key: typeof option === "object" ? option.id : option,
                props: {
                  label: typeof option === "object" ? option.name : option,
                  value: typeof option === "object" ? option.id : option,
                },
              })
            )
          );
          break;
        case "radio":
          formItem = h(
            "el-radio-group",
            {
              props: {
                value: target[info.name],
              },
              attrs: {
                placeholder: info.help_text,
              },
              on: {
                input: (e) => {
                  this.$set(target, info.name, e);
                },
              },
            },
            options.map((option) =>
              h(
                "el-radio",
                {
                  props: {
                    label: typeof option === "object" ? option.id : option,
                  },
                },
                typeof option === "object" ? option.name : option
              )
            )
          );
          break;
        case "file":
          formItem = row
            ? h("vxe-upload", {
                props: {
                  value: row[info.name],
                  "progress-text": "{percent}%",
                  "more-config": { maxCount: 1, layout: "horizontal" },
                  "show-button-text": false,
                  "limit-size": uploadSize / 1024 / 1024, // vxeupload 单位Mb
                  "limit-count": info.multiple ? 20 : 1,
                  multiple: !!info.multiple,
                  "name-field": "original_name",
                  readonly: pReadable,
                  "upload-method": ({ file }) => {
                    const formData = new FormData();
                    formData.append("file", file);
                    window.$_uploading = true;
                    return axios
                      .post(process.env.VUE_APP_UPLOAD_API, formData, {
                        headers: {
                          Authorization: `Bearer ${getToken()}`,
                        },
                      })
                      .then((response) => {
                        window.$_uploading = false;
                        if (response.status === 200 && !response.data.code) {
                          if (!(row[info.name] instanceof Array)) {
                            row[info.name] = [];
                          }
                          row[info.name].push({
                            response: response.data.data,
                            name: response.data.data.original_name,
                            url: response.data.data.url,
                            original_name: response.data.data.original_name,
                          });
                          if (
                            row[info.name].length > (info.multiple ? 20 : 1)
                          ) {
                            row[info.name].shift();
                          }
                        } else {
                          this.$message.error("上传失败");
                        }
                      })
                      .catch((err) => {
                        window.$_uploading = false;
                      });
                  },
                  "remove-method": (_) => {
                    row[info.name] = [];
                  },
                },
              })
            : h(
                "el-upload",
                {
                  props: {
                    action: process.env.VUE_APP_UPLOAD_API,
                    headers: {
                      Authorization: `Bearer ${getToken()}`,
                    },
                    accept:
                      "application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    multiple: !!info.multiple,
                    limit: info.multiple ? 20 : 1,
                    fileList:
                      this.form[info.name] instanceof Array
                        ? this.form[info.name]?.map((i) => {
                            if (i.hasOwnProperty("original_name")) {
                              i.name = i.original_name;
                            }
                            return i;
                          })
                        : [],
                    beforeUpload: (file) => {
                      if (file.size > uploadSize) {
                        this.$message({
                          type: "warning",
                          message: `上传图片大小超过${formatFileSize(
                            uploadSize
                          )}！`,
                        });
                        return false;
                      }
                      window.$_uploading = true;
                    },
                    onSuccess: (response, file, fileList) => {
                      window.$_uploading = false;
                      fileList.forEach((file) => {
                        if (file.response?.data && !file.response?.code) {
                          file.response = file.response?.data;
                          file.url = file.response?.url;
                        }
                      });
                      this.form[info.name] = fileList;
                    },
                    onRemove: (file, fileList) => {
                      this.form[info.name] = fileList;
                    },
                    onError: (err, file, fileList) => {
                      window.$_uploading = false;
                      this.form[info.name] = fileList;
                      this.$message({
                        type: "warning",
                        message: err,
                      });
                    },
                  },
                  scopedSlots: {
                    file: (scope) => {
                      let { file } = scope;
                      return [
                        h("div", {}, [
                          h("i", {
                            class: {
                              "el-icon-circle-check": file.status === "success",
                              "el-icon-loading": file.status === "uploading",
                            },
                            style: {
                              color: file.status === "success" ? "green" : "",
                            },
                          }),
                          h(
                            "a",
                            {
                              class: {
                                "uploaded-a": file.status === "success",
                              },
                              style: {
                                padding: "0 4px",
                              },
                              on: {
                                click: (_) => {
                                  this.$bus.$emit("online-file", file.url);
                                },
                              },
                            },
                            file.original_name || file.name
                          ),
                        ]),
                        h("i", {
                          class: "el-icon-close",
                          on: {
                            ["click"]: () => {
                              if (file.status === "uploading") return;
                              this.form[info.name].splice(
                                this.form[info.name].indexOf(file),
                                1
                              );
                            },
                          },
                        }),
                      ];
                    },
                  },
                },
                [
                  h(
                    "el-button",
                    {
                      slot: "trigger",
                      props: {
                        size: "small",
                        type: "primary",
                      },
                    },
                    "选取文件"
                  ),
                  h(
                    "div",
                    {
                      class: "el-upload__tip",
                      slot: "tip",
                    },
                    `文件不超过${formatFileSize(uploadSize)}`
                  ),
                ]
              );
          break;
        case "label":
          formItem = h(
            "div",
            {
              props: {
                type: "primary",
              },
            },
            info.label
          );
          break;
        case "static":
          formItem = h(
            "el-link",
            {
              props: {
                type: "primary",
              },
              attrs: {
                href: target[info.name],
                target: "_blank",
              },
            },
            info.label
          );
          break;
        case "hr":
          formItem = h("el-divider", {}, info.label);
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            let extraParam = {}
            if (isJSON(info.stub)) {
              extraParam = JSON.parse(info.stub)
            }
            flowList("all", {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: isJSON(info.stub) ? '' : info.stub,
              is_auth: 1,
              ...extraParam
            }).then((res) => {
              this.$set(this.flows, info.name, res.data.data);
            });
          }
          formItem = h(
            "el-select",
            {
              ref: `relation-flow-${info.name}`,
              props: {
                value: target[info.name]
                  ? target[info.name]
                      .toString()
                      ?.split(",")
                      .map((i) => Number(i))
                  : [],
                clearable: true,
                placeholder: info.help_text || '输入标题或编号搜索流程..',
                multiple: true,
                filterable: true,
                "reserve-keyword": true,
                "filter-method": debounce((query) => {
                  this.tempFlowList = this.flows[info.name].filter(flow => new RegExp(query, 'i').test(flow.title + flow.no))
                  console.log(query)
                  if (this.tempFlowList.length === 0) {
                    Message.warning("未搜索到匹配流程")
                  }
                }, 500).bind(this)
              },
              attrs: {
                placeholder: info.help_text,
              },
              style: {
                width: "100%",
              },
              on: {
                input: (e) => {
                  this.$set(target, info.name, e.toString());
                  this.tempFlowList.length = 0;
                },
              },
            },
            (this.tempFlowList.length > 0 ? this.tempFlowList : this.flows[info.name])?.map((option) =>
              h("el-option", {
                props: {
                  label: option.title,
                  value: option.id,
                },
              }, [
                h("div", {
                }, [
                  h("span", {},option.title),
                  h("el-button", {
                    style: {
                      float: 'right'
                    },
                    props: {
                      type: 'primary',
                      size: 'mini',
                      icon: 'el-icon-search'
                    },
                    on: {
                      click: e => {
                        e.stopPropagation()
                        let target = this.$router.resolve({
                          path: "/flow/detail",
                          query: {
                            module_id: option.custom_model_id,
                            flow_id: option.id,
                            isSinglePage: 1,
                          },
                        });
                        this.modalRender = (h) =>
                          h("iframe", {
                            attrs: {
                              src: target.href,
                            },
                            style: {
                              border: "none",
                              width: "100%",
                              height: "100%",
                            },
                          });
                        this.isShowModal = true;
                        this.$refs[`relation-flow-${info.name}`]?.blur()
                      }
                    }
                  }, '查看')
                ])
              ])
            )
          );
          break;
        case "relation":
          formItem = h(
            "vxe-table",
            {
              ref: `subForm-${info.name}`,
              style: {
                "margin-top": "10px",
              },
              props: {
                "min-height": "200px",
                border: true,
                stripe: true,
                data:
                  this.form[info.name] &&
                  typeof this.form[info.name] !== "string"
                    ? this.form[info.name]
                    : [],
                "keep-source": true,
                "column-config": { resizable: true },
                "show-overflow": true,
                "edit-rules": info._writeable
                  ? this.subRules[`${info.name}_rules`]
                  : {},
                "edit-config": info._writeable
                  ? {
                      trigger: "click",
                      mode: "row",
                      showStatus: false,
                      isHover: true,
                      autoClear: false,
                    }
                  : {},
              },
              on: {
                "edit-closed": ({ row, column }) => {
                  const $table = this.$refs[`subForm-${info.name}`];
                  if ($table) {
                    this.$set(
                      this.form,
                      info.name,
                      this.$refs[`subForm-${info.name}`].tableData
                    );
                  }
                },
              },
            },
            [
              info._writeable
                ? h(
                    "vxe-column",
                    {
                      props: {
                        width: 56,
                        align: "center",
                      },
                      scopedSlots: {
                        default: ({ row }) => {
                          return h("el-button", {
                            slot: "default",
                            style: {
                              padding: "9px",
                            },
                            props: {
                              type: "danger",
                              size: "small",
                              icon: "el-icon-minus",
                            },
                            on: {
                              click: async (_) => {
                                const $table =
                                  this.$refs[`subForm-${info.name}`];
                                if ($table) {
                                  await $table.remove(row);
                                  this.form[info.name] =
                                    $table.getTableData()?.tableData;
                                }
                              },
                            },
                          });
                        },
                      },
                    },
                    [
                      h("el-button", {
                        slot: "header",
                        style: {
                          padding: "9px",
                        },
                        props: {
                          type: "primary",
                          size: "small",
                          icon: "el-icon-plus",
                        },
                        on: {
                          click: async (_) => {
                            const $table = this.$refs[`subForm-${info.name}`];
                            if ($table) {
                              const record = {};
                              this.form[info.name].unshift(record);
                              // 临时数据不好验证长度
                              // const { row: newRow } = await $table.insert(
                              //   record
                              // );
                              await this.$nextTick();
                              await $table.setEditRow(record);
                            }
                          },
                        },
                      }),
                    ]
                  )
                : "",
              ...this.subForm
                .get(info.sub_custom_model_id)
                ?.customModel?.fields?.map((subField, subIndex) =>
                  h("vxe-column", {
                    props: {
                      field: subField.name,
                      title: subField.label,
                      align: "center",
                      "min-width": "180",
                      "edit-render": {},
                    },
                    scopedSlots: {
                      edit: ({ row: myrow }) => {
                        return formBuilder.bind(this)(
                          device,
                          subField,
                          h,
                          myrow,
                          info._writeable,
                          false
                        );
                      },
                      [["file", "choices", "choice", "select", "radio"].indexOf(
                        subField.type
                      ) !== -1
                        ? "default"
                        : false]: ({ row: myrow }) => {
                        return formBuilder.bind(this)(
                          device,
                          subField,
                          h,
                          myrow,
                          false,
                          true
                        );
                      },
                    },
                  })
                ),
            ]
          );
          break;
      }
    } else if (info._readable || pReadable) {
      switch (info.type) {
        case "date":
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            target[info.name]
              ? moment(target[info.name]).format("YYYY年MM月DD日")
              : ""
          );
          break;
        case "datetime":
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            target[info.name]
              ? moment(target[info.name]).format("YYYY年MM月DD日 HH时mm分")
              : ""
          );
          break;
        case "choice":
        case "select":
          const getDetailSelectValue = () => {
            let res = "";
            if (!!info.multiple) {
              res = target[info.name]
                ? target[info.name]
                    .toString()
                    ?.split(/,|\|/)
                    .map((i) => ((isNaN(Number(i)) || !i) ? i : Number(i)))
                : [];
            } else {
              res =
                (isNaN(Number(target[info.name])) || !target[info.name])
                  ? target[info.name]
                  : Number(target[info.name]);
            }
            if (res instanceof Array) {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res.indexOf(i.id) !== -1)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            } else {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res === i.id)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            }
          };
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            getDetailSelectValue()
          );
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            let extraParam = {}
            if (isJSON(info.stub)) {
              extraParam = JSON.parse(info.stub)
            }
            flowList("all", {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: isJSON(info.stub) ? '' : info.stub,
              is_auth: 1,
              ...extraParam
            }).then((res) => {
              this.$set(this.flows, info.name, res.data.data);
            });
          }
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            target[info.name]
              ?.toString()
              ?.split(",")
              ?.map((j) => {
                let flow = this.flows[info.name]?.find((i) => i.id == j);
                return flow
                  ? h(
                      "el-link",
                      {
                        props: {
                          type: "primary",
                        },
                        style: {
                          "line-height": "1.5",
                        },
                        on: {
                          click: (_) => {
                            let target = this.$router.resolve({
                              path: "/flow/detail",
                              query: {
                                module_id: flow.custom_model_id,
                                flow_id: flow.id,
                                isSinglePage: 1,
                              },
                            });
                            this.modalRender = (h) =>
                              h("iframe", {
                                attrs: {
                                  src: target.href,
                                },
                                style: {
                                  border: "none",
                                  width: "100%",
                                  height: "100%",
                                },
                              });
                            this.isShowModal = true;
                          },
                        },
                      },
                      flow.title
                    )
                  : "";
              })
          );
          break;
        case "file":
          formItem = row
            ? h("vxe-upload", {
                props: {
                  value: row[info.name],
                  "name-field": "original_name",
                  "progress-text": "{percent}%",
                  "more-config": { maxCount: 1, layout: "horizontal" },
                  "show-button-text": false,
                  "limit-size": uploadSize / 1024 / 1024, //vxe upload单位为Mb
                  "limit-count": info.multiple ? 20 : 1,
                  readonly: true,
                },
              })
            : h(
                "el-upload",
                {
                  props: {
                    action: process.env.VUE_APP_UPLOAD_API,
                    headers: {
                      Authorization: `Bearer ${getToken()}`,
                    },
                    disabled: true,
                    accept:
                      "application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    multiple: true,
                    fileList:
                      this.form[info.name] instanceof Array
                        ? this.form[info.name]?.map((i) => {
                            if (i.hasOwnProperty("original_name")) {
                              i.name = i.original_name;
                            }
                            return i;
                          })
                        : [],
                  },
                  scopedSlots: {
                    file: (scope) => {
                      let { file } = scope;
                      return [
                        h("div", {}, [
                          h("i", {
                            class: "el-icon-circle-check",
                            style: {
                              color: "green",
                            },
                          }),
                          h(
                            "a",
                            {
                              class: {
                                "uploaded-a": file.status === "success",
                              },
                              style: {
                                padding: "0 4px",
                              },
                              on: {
                                click: (_) => {
                                  this.$bus.$emit("online-file", file.url);
                                },
                              },
                            },
                            file.name
                          ),
                        ]),
                      ];
                    },
                  },
                },
                [
                  h(
                    "span",
                    {
                      slot: "trigger",
                    },
                    `数量：${
                      this.form[info.name] instanceof Array
                        ? this.form[info.name]?.length
                        : 0
                    }`
                  ),
                ]
              );
          break;
        default:
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            target[info.name]
          );
      }
    }

    if (formItem) {
      let jointlySignContent = [];
      let isJointly = false;
      this.jointlySignLog.forEach((log) => {
        const data = JSON.parse(log.data);
        Object.entries(data)?.forEach(([key, value]) => {
          if (
            value.hasOwnProperty("custom_field_id") &&
            value["custom_field_id"] === info.id
          ) {
            isJointly = !!log.is_jointly_sign;
            if (log.status) {
              jointlySignContent.push(
                h("div", [
                  h("span", value.value),
                  h("br"),
                  info.is_sign
                    ? log.user.sign_file && log.user.sign_file.url
                      ? h("el-image", {
                          style: {
                            "max-height": "80px",
                            "max-width": "120px",
                          },
                          props: {
                            src: log.user?.sign_file?.url,
                            fit: "contain",
                            alt: log.user?.name,
                          },
                          attrs: {
                            src: log.user?.sign_file?.url,
                            alt: log.user?.name,
                          },
                        })
                      : h("span", log.user?.name)
                    : "",
                  info.is_sign ? h("br") : "",
                  h(
                    "span",
                    log.updated_at
                      ? this.$moment(log.updated_at).format("YYYY年MM月DD日")
                      : ""
                  ),
                ])
              );
            }
          }
        });
      });
      return row
        ? formItem
        : h(
            "el-form-item",
            {
              attrs: {
                'data-field-id': info.id
              },
              props: {
                prop: info.name,
                label: info.label_show ? info.label : "",
                "label-width": !info.label_show ? "0" : "",
              },
              style: {
                // +1为了工作标题往下顺延
                "grid-column-start": info.gs_x + 1,
                "grid-column-end": info.gs_x + 1 + info.gs_width,
                "grid-row-start":
                  info.gs_y + 1 + (info.name === "flow_title" ? 0 : 1),
                "grid-row-end":
                  info.gs_y +
                  1 +
                  (info.name === "flow_title" ? 0 : 1) +
                  info.gs_height,
              },
            },
            isJointly
              ? [info._writeable ? formItem : "", jointlySignContent]
              : [
                  (() => {
                    if (info.name === "flow_title") {
                      return formItem;
                    }
                    if (info._writeable) {
                      return formItem;
                    } else {
                      let log = this.logs.find(
                        (log) =>
                          log.node?.fields?.findIndex(
                            (field) =>
                              field?.field_id === info.id &&
                              field.type === "write"
                          ) !== -1 && target[info.name]
                      );
                      if ((log && log.status) || log?.user?.id === this.$store.state.user.adminId || this.logs.length === 0) {
                        return formItem;
                      }
                    }
                  })(),
                  (() => {
                    if (info.is_sign) {
                      let log = this.logs.find(
                        (log) =>
                          log.node?.fields?.findIndex(
                            (field) =>
                              field?.field_id === info.id &&
                              field.type === "write"
                          ) !== -1 && target[info.name]
                      );
                      if (log && log.status && log.user) {
                        return h("div", [
                          log.user.sign_file && log.user.sign_file.url
                            ? h("el-image", {
                                style: {
                                  "max-height": "80px",
                                  "max-width": "120px",
                                },
                                props: {
                                  src: log.user?.sign_file?.url,
                                  fit: "contain",
                                  alt: log.user?.name,
                                },
                                attrs: {
                                  src: log.user?.sign_file?.url,
                                  alt: log.user?.name,
                                },
                              })
                            : h("span", log.user?.name),
                          h(
                            "div",
                            this.$moment(log.updated_at).format(
                              "YYYY年MM月DD日"
                            )
                          ),
                        ]);
                      }
                    }
                  })(),
                ]
          );
    }
  }
  if (device === "mobile") {
    if (info._writeable || pWrite) {
      switch (info.type) {
        case "text":
          formItem = h("van-field", {
            props: {
              name: info.name,
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text || info.label,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => this.$set(target, info.name, e),
            },
          });
          break;
        case "textarea":
          formItem = h("van-field", {
            props: {
              name: info.name,
              rows: 2,
              type: "textarea",
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text || info.label,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => this.$set(target, info.name, e),
            },
          });
          break;
        case "radio":
          formItem = h(
            "van-radio-group",
            {
              props: {
                value: target[info.name],
              },
              on: {
                input: (e) => {
                  this.$set(target, info.name, e);
                },
              },
            },
            options.map((option) =>
              h(
                "van-radio",
                {
                  props: {
                    name: typeof option === "object" ? option.id : option,
                    "checked-color": "var(--theme-color)",
                  },
                },
                typeof option === "object" ? option.name : option
              )
            )
          );
          break;
        case "date":
          formItem = h("el-date-picker", {
            props: {
              type: "date",
              "value-format": "yyyy-MM-dd",
              format: "yyyy年MM月dd日",
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text || info.label,
              "picker-options": {
                shortcuts: this.shortcuts,
              },
            },
            attrs: {
              placeholder: info.help_text || info.label,
            },
            style: {
              width: "100%",
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "datetime":
          formItem = h("el-date-picker", {
            props: {
              type: "datetime",
              "value-format": "yyyy-MM-dd HH:mm:ss",
              format: "yyyy-MM-dd HH:mm",
              value: target[info.name],
              clearable: true,
              placeholder: info.help_text || info.label,
              "picker-options": {
                shortcuts: this.shortcuts,
              },
            },
            style: {
              width: "100%",
            },
            attrs: {
              placeholder: info.help_text || info.label,
            },
            on: {
              input: (e) => {
                this.$set(target, info.name, e);
              },
            },
          });
          break;
        case "choice":
        case "select":
          const getDetailMobileSelectValue = () => {
            let res = "";
            if (!!info.multiple) {
              res = target[info.name]
                ? target[info.name]
                  .toString()
                  ?.split(/,|\|/)
                  .map((i) => ((isNaN(Number(i)) || !i) ? i : Number(i)))
                : [];
            } else {
              res =
                (isNaN(Number(target[info.name])) || !target[info.name])
                  ? target[info.name]
                  : Number(target[info.name]);
            }
            if (res instanceof Array) {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res.indexOf(i.id) !== -1)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            } else {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res === i.id)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            }
          };
          formItem = h('div', [
            h('van-field', {
              props: {
                value: getDetailMobileSelectValue(),
                clickable: true,
                readonly: true,
                'label-width': 0,
                border: false
              },
              on: {
                click: _ => {
                  this.$refs[`popup-${info.name}-${row ? 'c' : 'b'}`].show()
                }
              }
            }),
            !!info.multiple ? h(MobileMultipleSelect, {
              ref: `popup-${info.name}-${row ? 'c' : 'b'}`,
              props: {
                outputType: 'string',
                selectDataOpts: options,
                options: {
                  label: 'name',
                  value: 'id'
                }
              },
              on: {
                confirm: e => {
                  this.$set(target, info.name, e)
                  this.$refs[`popup-${info.name}-${row ? 'c' : 'b'}`].hide()
                }
              }
            }) : h(MobilePicker, {
              ref: `popup-${info.name}-${row ? 'c' : 'b'}`,
              props: {
                columns: options,
              },
              on: {
                confirm: e => {
                  this.$set(target, info.name, typeof e === "object" ? e.id : e)
                  this.$refs[`popup-${info.name}-${row ? 'c' : 'b'}`].hide()
                }
              }
            })
          ])
          break;

        case "file":
          formItem = h(
            "el-upload",
            {
              props: {
                action: process.env.VUE_APP_UPLOAD_API,
                headers: {
                  Authorization: `Bearer ${getToken()}`,
                },
                accept:
                  "application/msword,image/jpeg,application/pdf,image/png,application/vnd.ms-powerpoint,text/plain,application/x-zip-compressed,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                multiple: !!info.multiple,
                limit: info.multiple ? 20 : 1,
                fileList:
                  this.form[info.name] instanceof Array
                    ? this.form[info.name]?.map((i) => {
                        if (i.hasOwnProperty("original_name")) {
                          i.name = i.original_name;
                        }
                        return i;
                      })
                    : [],
                beforeUpload: (file) => {
                  if (file.size > uploadSize) {
                    this.$message({
                      type: "warning",
                      message: `上传图片大小超过${formatFileSize(
                        uploadSize
                      )}！`,
                    });
                    return false;
                  }
                  window.$_uploading = true;
                },
                onSuccess: (response, file, fileList) => {
                  window.$_uploading = false;
                  fileList.forEach((file) => {
                    if (file.response?.data && !file.response?.code) {
                      file.response = file.response?.data;
                      file.url = file.response?.url;
                    }
                  });
                  target[info.name] = fileList;
                },
                onRemove: (file, fileList) => {
                  target[info.name] = fileList;
                },
                onError: (err, file, fileList) => {
                  window.$_uploading = false;
                  target[info.name] = fileList;
                  this.$message({
                    type: "warning",
                    message: err,
                  });
                },
              },
              scopedSlots: {
                file: (scope) => {
                  let { file } = scope;
                  return [
                    h("div", {}, [
                      h("i", {
                        class: {
                          "el-icon-circle-check": file.status === "success",
                          "el-icon-loading": file.status === "uploading",
                        },
                        style: {
                          color: file.status === "success" ? "green" : "",
                        },
                      }),
                      h(
                        "a",
                        {
                          class: {
                            "uploaded-a": file.status === "success",
                          },
                          style: {
                            padding: "0 4px",
                          },
                          on: {
                            click: (_) => {
                              this.$bus.$emit("online-file", file.url);
                            },
                          },
                        },
                        file.original_name || file.name
                      ),
                    ]),
                    h("i", {
                      class: "el-icon-close",
                      on: {
                        ["click"]: () => {
                          if (file.status === "uploading") return;
                          target[info.name].splice(
                            target[info.name].indexOf(file),
                            1
                          );
                        },
                      },
                    }),
                  ];
                },
              },
            },
            [
              h(
                "el-button",
                {
                  slot: "trigger",
                  props: {
                    size: "mini",
                    type: "primary",
                  },
                },
                "选取文件"
              ),
              h(
                "div",
                {
                  class: "el-upload__tip",
                  slot: "tip",
                },
                `文件不超过${formatFileSize(uploadSize)}`
              ),
            ]
          );
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            let extraParam = {}
            if (isJSON(info.stub)) {
              extraParam = JSON.parse(info.stub)
            }
            flowList("all", {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: isJSON(info.stub) ? '' : info.stub,
              is_auth: 1,
              ...extraParam
            }).then((res) => {
              this.$set(this.flows, info.name, res.data.data);
            });
          }
          formItem = h('div', [
            h('van-field', {
              props: {
                value: target[info.name]
                  ?.toString()
                  ?.split(",")
                  ?.map((j) => {
                    let flow = this.flows[info.name]?.find((i) => i.id == j)
                    return flow?.title
                  })?.toString(),
                clickable: true,
                readonly: true,
                'label-width': 0,
                border: false
              },
              on: {
                click: _ => {
                  this.$refs[`popup-${info.name}-${row ? 'c' : 'b'}`].show()
                }
              }
            }),
            h(MobileMultipleSelect, {
              ref: `popup-${info.name}-${row ? 'c' : 'b'}`,
              props: {
                outputType: 'string',
                selectDataOpts: this.flows[info.name],
                options: {
                  label: 'title',
                  value: 'id'
                }
              },
              on: {
                confirm: e => {
                  this.$set(target, info.name, e)
                  this.$refs[`popup-${info.name}-${row ? 'c' : 'b'}`].hide()
                }
              }
            })
          ])
          break;
        case "relation":
          let copySubForm = deepCopy(this.form[info.name][0]);
          formItem = h("div", [
            h(
              "van-cell",
              {
                props: {
                  title: info.label_show ? info.label : '',
                  "arrow-direction": "down",
                }
              },
              [
                h(
                  "van-button",
                  {
                    props: {
                      color: "var(--theme-color)",
                      icon: "plus",
                      size: "small",
                      'native-type': 'button'
                    },
                    on: {
                      click: (_) => {
                        this.form[info.name].push(copySubForm);
                      },
                    },
                  },
                  "新增"
                ),
              ]
            ),
            h(
              "div",
              this.form[info.name] instanceof Array
                ? this.form[info.name]?.map((sForm, sIndex) =>
                    h(
                      "van-cell",
                      {
                        props: {
                          inset: false,
                        },
                      },
                      [
                        h(
                          "van-cell",
                          {
                            props: {
                              title: info.label + "-" + (sIndex + 1),
                            },
                          },
                          [
                            h(
                              "van-button",
                              {
                                props: {
                                  size: "mini",
                                  type: "danger",
                                  icon: "minus",
                                  'native-type': 'button'
                                },
                                on: {
                                  click: (_) => {
                                    this.form[info.name].splice(sIndex, 1);
                                  },
                                },
                              },
                              "删除"
                            ),
                          ]
                        ),
                        h(
                          "el-form",
                          {
                            ref: "elSubForm-" + info.name + sIndex,
                            props: {
                              size: "mini",
                              model: sForm,
                              "label-position": "right",
                              rules: this.subRules[`${info.name}_rules`],
                              "inline-message": true,
                            },
                            style: {
                              margin: "0 10px",
                            },
                            attrs: {
                              ref: "elSubForm-" + info.name
                            }
                          },
                          this.subForm.get(info.sub_custom_model_id)?.customModel?.fields?.map((subField) =>
                              formBuilder.bind(this)(
                                device,
                                subField,
                                h,
                                sForm,
                                info._writeable,
                                null,
                                info.name
                              )
                            )
                        ),
                      ]
                    )
                  )
                : ""
            ),
          ]);
          break;
      }
    } else if (info._readable || pReadable) {
      switch (info.type) {
        case "date":
          formItem = h("van-field", {
            props: {
              readonly: true,
              value: target[info.name]
                ? moment(target[info.name]).format("YYYY年MM月DD日")
                : "",
            },
          });
          break;
        case "datetime":
          formItem = h("van-field", {
            props: {
              readonly: true,
              value: target[info.name]
                ? moment(target[info.name]).format(
                    "YYYY年MM月DD日 HH时mm分ss秒"
                  )
                : "",
            },
          });
          break;
        case "select":
        case "choice":
          const getDetailMobileSelectValue = () => {
            let res = "";
            if (!!info.multiple) {
              res = target[info.name]
                ? target[info.name]
                  .toString()
                  ?.split(/,|\|/)
                  .map((i) => (isNaN(Number(i)) || !i ? i : Number(i)))
                : [];
            } else {
              res =
                isNaN(Number(target[info.name])) || !target[info.name]
                  ? target[info.name]
                  : Number(target[info.name]);
            }
            if (res instanceof Array) {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res.indexOf(i.id) !== -1)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            } else {
              if (typeof options[0] === "object") {
                return options
                  ?.filter((i) => res === i.id)
                  ?.map((i) => i.name)
                  ?.toString();
              } else {
                return res;
              }
            }
          };
          formItem = h("van-field", {
            props: {
              readonly: true,
              value: getDetailMobileSelectValue(),
            },
          });
          break;
        case "file":
          let files = target[info.name];
          formItem = h(
            "div",
            {},
            (files && files !== "null" && files !== "undefined"
              ? files
              : []
            )?.map((file) =>
              h("div", {}, [
                h(
                  "a",
                  {
                    class: {
                      "uploaded-a": file.status === "success",
                    },
                    style: {
                      padding: "0 4px",
                    },
                    on: {
                      click: (_) => {
                        this.$bus.$emit("online-file", file.url);
                      },
                    },
                  },
                  file.original_name || file.name
                ),
              ])
            )
          );
          break;
        case "relation":
          formItem = h("div", [
            h("van-cell", {
              props: {
                title: info.label_show ? info.label : '',
              },
            }),
            h(
              "div",
              this.form[info.name] instanceof Array
                ? this.form[info.name]?.map((sForm, sIndex) =>
                    h(
                      "van-cell",
                      {
                        props: {
                          inset: false,
                        },
                      },
                      [
                        h("van-cell", {
                          props: {
                            title: info.label + "-" + (sIndex + 1),
                          },
                        }),
                        h(
                          "van-form",
                          {
                            ref: "elSubForm-"+sIndex,
                            props: {
                            },
                            style: {
                              margin: "0 10px",
                            },
                          },
                          Array.from(this.subForm)
                            .map((i) => i[1]?.customModel?.fields)
                            ?.flat()
                            .map((subField) =>
                              formBuilder.bind(this)(
                                device,
                                subField,
                                h,
                                sForm,
                                info._writeable,
                                info._readable
                              )
                            )
                        ),
                      ]
                    )
                  )
                : ""
            ),
          ]);
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            let extraParam = {}
            if (isJSON(info.stub)) {
              extraParam = JSON.parse(info.stub)
            }
            flowList("all", {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: isJSON(info.stub) ? '' : info.stub,
              is_auth: 1,
              ...extraParam
            }).then((res) => {
              this.$set(this.flows, info.name, res.data.data);
            });
          }
          formItem = h(
            "van-cell",
            {
              style: {
                width: '100%',
              },
              props: {
              },
            },
            target[info.name]
              ?.toString()
              ?.split(",")
              ?.map((j) => {
                let flow = this.flows[info.name]?.find((i) => i.id == j);
                return flow
                  ? h(
                      "el-link",
                      {
                        props: {
                          type: "primary",
                        },
                        style: {
                          "line-height": "1.5",
                        },
                        on: {
                          click: (_) => {
                            let target = this.$router.resolve({
                              path: "/flow/detail",
                              query: {
                                module_id: flow.custom_model_id,
                                flow_id: flow.id,
                                isSinglePage: 1,
                              },
                            });
                            this.modalRender = (h) =>
                              h("iframe", {
                                attrs: {
                                  src: target.href,
                                },
                                style: {
                                  border: "none",
                                  width: "100%",
                                  height: "100%",
                                },
                              });
                            this.isShowModal = true;
                          },
                        },
                      },
                      flow.title
                    )
                  : "";
              })
          );
          break;
        default:
          formItem = h("van-field", {
            props: {
              value: target[info.name],
              readonly: true
            },
          })
      }
    }

    if (formItem) {
      let jointlySignContent = [];
      let isJointly = false;
      this.jointlySignLog.forEach((log) => {
        const data = JSON.parse(log.data);
        Object.entries(data)?.forEach(([key, value]) => {
          if (
            value.hasOwnProperty("custom_field_id") &&
            value["custom_field_id"] === info.id
          ) {
            isJointly = !!log.is_jointly_sign;
            if (log.status) {
              jointlySignContent.push(
                h("div", [
                  h("span", value.value),
                  h("br"),
                  info.is_sign
                    ? log.user.sign_file && log.user.sign_file.url
                      ? h("el-image", {
                          style: {
                            "max-height": "40px",
                            "max-width": "60px",
                          },
                          props: {
                            src: log.user?.sign_file?.url,
                            fit: "contain",
                            alt: log.user?.name,
                          },
                          attrs: {
                            src: log.user?.sign_file?.url,
                            alt: log.user?.name,
                          },
                        })
                      : h("span", log.user?.name)
                    : "",
                  info.is_sign ? h("br") : "",
                  h(
                    "span",
                    log.updated_at
                      ? this.$moment(log.updated_at).format("YYYY年MM月DD日")
                      : ""
                  ),
                ])
              );
            }
          }
        });
      });
      return row
        ? h("el-form-item", {
          ref: info.name,
          props: {
            prop: info.name,
            label: (!info.label_show || info.type === 'relation') ? "" : info.label,
            "label-width": (!info.label_show || info.type === 'relation') ? "0" : "",
          }
        }, [formItem])
        : h(
            "el-form-item",
            {
              props: {
                prop: info.name,
                label: (!info.label_show || info.type === 'relation') ? "" : info.label,
                "label-width": (!info.label_show || info.type === 'relation') ? "0" : "",
              },
            },
            isJointly
              ? [info._writeable ? formItem : "", jointlySignContent]
              : [
                  (() => {
                    if (info.name === "flow_title") {
                      return formItem;
                    }
                    if (info._writeable) {
                      return formItem;
                    } else {
                      let log = this.logs.find(
                        (log) =>
                          log.node?.fields?.findIndex(
                            (field) =>
                              field?.field_id === info.id &&
                              field.type === "write"
                          ) !== -1 && target[info.name]
                      );
                      if ((log && log.status) || log?.user?.id === this.$store.state.user.adminId || this.logs.length === 0) {
                        return formItem;
                      }
                    }
                  })(),
                  (() => {
                    if (info.is_sign) {
                      let log = this.logs.find(
                        (log) =>
                          log.node?.fields?.findIndex(
                            (field) =>
                              field?.field_id === info.id &&
                              field.type === "write"
                          ) !== -1 && target[info.name]
                      );
                      if (log && log.status && log.user) {
                        return h("div", [
                          log.user.sign_file && log.user.sign_file.url
                            ? h("el-image", {
                                style: {
                                  "max-height": "40px",
                                  "max-width": "60px",
                                },
                                props: {
                                  src: log.user?.sign_file?.url,
                                  fit: "contain",
                                  alt: log.user?.name,
                                },
                                attrs: {
                                  src: log.user?.sign_file?.url,
                                  alt: log.user?.name,
                                },
                              })
                            : h("span", log.user?.name),
                          h(
                            "div",
                            this.$moment(log.updated_at).format(
                              "YYYY年MM月DD日"
                            )
                          ),
                        ]);
                      }
                    }
                  })(),
                ]
          );
    }
  }
}
