import formBuilderMap from "./formBuilderMap";
import { CreateElement, VNode } from "vue";
import moment from "moment";
import { getToken } from "@/utils/auth";
import {deepCopy, formatFileSize, formatTime} from "@/utils/index";
import { uploadSize } from "@/settings";
import axios from 'axios';
import { flowList } from "@/api/flow";
/**
 * @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 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(formBuilderMap(device).get(info.type), {
            props: {
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "textarea":
          formItem = h(formBuilderMap(device).get(info.type), {
            props: {
              type: "textarea",
              autosize: {
                minRows: 2,
              },
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "date":
          formItem = h(formBuilderMap(device).get(info.type), {
            props: {
              type: "date",
              "value-format": "yyyy-MM-dd",
              format: "yyyy年MM月dd日",
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              "picker-options": {
                shortcuts: [
                  {
                    text: "一年前",
                    onClick(picker) {
                      picker.$emit(
                        "pick",
                        moment().subtract(1, "years").toDate()
                      );
                    },
                  },
                  {
                    text: "一月前",
                    onClick(picker) {
                      picker.$emit(
                        "pick",
                        moment().subtract(1, "months").toDate()
                      );
                    },
                  },
                  {
                    text: "一周前",
                    onClick(picker) {
                      picker.$emit(
                        "pick",
                        moment().subtract(1, "weeks").toDate()
                      );
                    },
                  },
                  {
                    text: "今天",
                    onClick(picker) {
                      picker.$emit("pick", new Date());
                    },
                  },
                  {
                    text: "一周后",
                    onClick(picker) {
                      picker.$emit("pick", moment().add(1, "weeks").toDate());
                    },
                  },
                  {
                    text: "一月后",
                    onClick(picker) {
                      picker.$emit("pick", moment().add(1, "months").toDate());
                    },
                  },
                  {
                    text: "一年后",
                    onClick(picker) {
                      picker.$emit("pick", moment().add(1, "years").toDate());
                    },
                  },
                ],
              },
            },
            attrs: {
              placeholder: info.help_text,
            },
            style: {
              width: "100%",
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "datetime":
          formItem = h(formBuilderMap(device).get(info.type), {
            props: {
              type: "datetime",
              "value-format": "yyyy-MM-dd HH:mm:ss",
              format: this.datetimeFormat,
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              "picker-options": {
                shortcuts: this.shortcuts
              },
            },
            style: {
              width: "100%",
            },
            attrs: {
              placeholder: info.help_text,
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "select":
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                value: row ? row[info.name] : this.form[info.name],
                clearable: true,
                placeholder: info.help_text,
                multiple: !!info.multiple,
                'multiple-limit': info.multiple,
                filterable: true
              },
              style: {
                width: "100%",
              },
              attrs: {
                placeholder: info.help_text,
              },
              on: {
                input: (e) => {
                  row
                    ? this.$set(row, info.name, e)
                    : this.$set(this.form, info.name, e);
                },
              },
            },
            options.map((option) =>
              h("el-option", {
                props: {
                  label: typeof option === "object" ? option.name : option,
                  value: typeof option === "object" ? option.id : option,
                },
              })
            )
          );
          break;
        case "radio":
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                value: row ? row[info.name] : this.form[info.name],
              },
              attrs: {
                placeholder: info.help_text,
              },
              on: {
                input: (e) => {
                  row
                    ? this.$set(row, info.name, e)
                    : this.$set(this.form, 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,
                  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
                        })
                      } else {
                        this.$message.error("上传失败")
                      }
                    }).catch(err => {
                      window.$_uploading = false
                    })
                  }
                }
              }
            ) :
            h(
            formBuilderMap(device).get(info.type),
            {
              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].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;
                    }
                  });
                  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(
            formBuilderMap(device).get(info.type),
            {
              props: {
                type: "primary",
              },
            },
            info.label
          );
          break;
        case "static":
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                type: "primary",
              },
              attrs: {
                href: row ? row[info.name] : this.form[info.name],
                target: "_blank",
              },
            },
            info.label
          );
          break;
        case "hr":
          formItem = h(formBuilderMap(device).get(info.type), {}, info.label);
          break;
        case "choice":
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                value: row ? row[info.name] : this.form[info.name],
                clearable: true,
                placeholder: info.help_text,
                multiple: !!info.multiple,
                'multiple-limit': info.multiple,
                filterable: true
              },
              attrs: {
                placeholder: info.help_text,
              },
              style: {
                width: "100%",
              },
              on: {
                input: (e) => {
                  row
                    ? this.$set(row, info.name, e)
                    : this.$set(this.form, info.name, e);
                },
              },
            },
            options.map((option) =>
              h("el-option", {
                props: {
                  label: typeof option === "object" ? option.name : option,
                  value: typeof option === "object" ? option.id : option,
                },
              })
            )
          );
          break;
        case "choices":
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                value: row ? row[info.name] : this.form[info.name],
                clearable: true,
                placeholder: info.help_text,
                multiple: true,
                filterable: true
              },
              attrs: {
                placeholder: info.help_text,
              },
              style: {
                width: '100%'
              },
              on: {
                input: (e) => {
                  row
                    ? this.$set(row, info.name, e)
                    : this.$set(this.form, info.name, e);
                },
              },
            },
            options.map((option) =>
              h("el-option", {
                props: {
                  label: option,
                  value: option,
                },
              })
            )
          );
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            flowList('all', {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: info.stub
            }).then(res => {
              this.$set(this.flows, info.name, res.data.data)
            })
          }
          formItem = h(
            formBuilderMap(device).get(info.type),
            {
              props: {
                value: row ? (row[info.name] ? row[info.name].toString()?.split(',').map(i => Number(i)) : []) : (this.form[info.name] ? this.form[info.name].toString()?.split(',').map(i => Number(i)) : []),
                clearable: true,
                placeholder: info.help_text,
                multiple: true,
                filterable: true,
                'reserve-keyword': true,
                loading: this.flowSelectLoading
              },
              attrs: {
                placeholder: info.help_text,
              },
              style: {
                width: '100%'
              },
              on: {
                input: (e) => {
                  row
                    ? this.$set(row, info.name, e.toString())
                    : this.$set(this.form, info.name, e.toString());
                }
              },
            },
            this.flows[info.name]?.map((option) =>
              h("el-option", {
                props: {
                  label: option.title,
                  value: option.id,
                },
              })
            )
          );
          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],
                "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,
                        );
                      },
                      [subField.type === 'file' ? 'default' : false]: ({ row: myrow }) => {
                        return formBuilder.bind(this)(
                          device,
                          subField,
                          h,
                          myrow,
                          info._writeable,
                          true,
                        );
                      }
                    },
                  })
                ),
            ]
          );
          break;
      }
    } else if (info._readable || pReadable) {
      switch (info.type) {
        case "date":
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日") : ''
          );
          break;
        case "datetime":
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日 HH时mm分") : ''
          );
          break;
        case "select":
          let findValue = options.find((i) =>
            typeof i === "object"
              ? i.id == this.form[info.name]
              : i === this.form[info.name]
          );
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            info.multiple ? this.form[info.name]?.toString()?.split('|')?.map(j => {
              return options.find((i) =>
                typeof i === "object"
                  ? i.id == j
                  : i === j
              )?.name;
            })?.toString() : typeof findValue === "object" ? findValue.name : findValue
          );
          break;
        case "choice":
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            this.form[info.name]?.toString()?.split('|').map(j => {
              return options.find((i) => i.id == j)?.name;
            })?.toString()
          );
          break;
        case "choices":
          let findChoicesValue = options.find((i) =>
            typeof i === "object"
              ? i.id == this.form[info.name]
              : i === this.form[info.name]
          );
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            info.multiple ? this.form[info.name]?.toString()?.split('|').map(j => {
              return options.find((i) =>
                typeof i === "object"
                  ? i.id == j
                  : i === j
              )?.name;
            })?.toString() : typeof findChoicesValue === "object" ? findChoicesValue.name : findChoicesValue
          );
          break;
        case "relation-flow":
          if (!this.flows[info.name]) {
            flowList('all', {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: info.stub
            }).then(res => {
              this.$set(this.flows, info.name, res.data.data)
            })
          }
          formItem = h(
            "span",
            {
              style: {
                color: "#333",
              },
            },
            this.form[info.name]?.toString()?.split(',').map(j => {
              return this.flows[info.name]?.find((i) =>
                i.id == j
              )?.title;
            })?.toString()
          );
          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(
            formBuilderMap(device).get(info.type),
            {
              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",
              },
            },
            this.form[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
            jointlySignContent.push(h('div',[
              h('span', value.value),
              h('br'),
              info.is_sign ? 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
                }
              }) : '',
              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",
            {
              props: {
                prop: info.name,
                label: info.label_show ? info.label : '',
                'label-width': !info.label_show ? '0': '',
              },
              style: {
                "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 ? [(/\/detail/.test(this.$route.path) && this.$route.query.flow_id && jointlySignContent.length > 0) ? '' : formItem,(() => {
              if (info.is_sign && !(/\/detail/.test(this.$route.path && this.$route.query.flow_id && jointlySignContent.length > 0))) {
                let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name) !== -1) && (row ? row[info.name] : this.form[info.name])
                if (log && log.user) {
                  return h('div',[
                    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('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
                  ])
                }
              }
            })(),jointlySignContent] : [formItem,(() => {
              if (info.is_sign) {
                let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name) !== -1 && (row ? row[info.name] : this.form[info.name]))
                if (log && log.user) {
                  return h('div',[
                    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('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
                  ])
                }
              }
            })()]
          );
    }
  }
  if (device === "mobile") {
    if (info._writeable || pWrite) {
      let myRules = []
      if (row && this.subRules && this.subRules[`${pname}_rules`] && this.subRules[`${pname}_rules`][info.name]) {
        myRules = this.subRules[`${pname}_rules`][info.name]
      } else {
        myRules = this.rules[info.name]
      }
      switch (info.type) {
        case "text":
          formItem = h(formBuilderMap(device).get(info.type), {
            props: {
              name: info.name,
              label: info.label,
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              rules: myRules.map(rule => {
                if (rule.hasOwnProperty('required')) {
                  return rule
                } else if (rule.hasOwnProperty('pattern')) {
                  return {
                    pattern: rule.pattern,
                    message: rule.message
                  }
                } else {
                  return rule
                }
              }),
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              placeholder: info.help_text,
              for: info.name
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "textarea":
          formItem = h(formBuilderMap(device).get(info.type), {
            props: {
              name: info.name,
              label: info.label,
              type: "textarea",
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              placeholder: info.help_text,
              for: info.name
            },
            on: {
              input: (e) => {
                row
                  ? this.$set(row, info.name, e)
                  : this.$set(this.form, info.name, e);
              },
            },
          });
          break;
        case "date":
          formItem = h("van-field", {
            props: {
              readonly: true,
              clickable: true,
              name: info.name,
              label: info.label,
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              placeholder: info.help_text,
              for: info.name
            },
            on: {
              click: (_) => {
                this.vanCalendarOption.forFormName = info.name;
                this.vanCalendarOption.originalObj = row;
                this.vanCalendarOption.isShow = true;
              },
            },
          });
          break;
        case "datetime":
          formItem = h("van-field", {
            props: {
              readonly: true,
              clickable: true,
              name: info.name,
              label: info.label,
              value: row ? row[info.name] : this.form[info.name],
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              for: info.name
            },
            on: {
              click: (_) => {
                this.vanTimePickerOption.forFormName = info.name;
                this.vanTimePickerOption.originalObj = row;
                this.vanTimePickerOption.isShow = true
              },
            },
          });
          break;
        case "select":
          let findSelect = options?.find((i) =>
            typeof i === "object"
              ? i.id === (row ? row[info.name] : this.form[info.name])
              : i === (row ? row[info.name] : this.form[info.name])
          );
          formItem = h("van-field", {
            props: {
              readonly: true,
              clickable: true,
              name: info.name,
              label: info.label,
              value: typeof findSelect === "object" ? findSelect.name : findSelect,
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              for: info.name
            },
            on: {
              click: (_) => {
                this.vanPopupOption.forFormName = info.name;
                this.vanPopupOption.originalObj = row;
                this.$set(this.vanPopupOption, "columns", options);
                this.vanPopupOption.isShow = true;
              },
            },
          });
          break;
        case "choice":
          let findChoice = info.multiple ? options?.filter((i) =>
            typeof i === "object"
              ? (row ? row[info.name].indexOf(i.id) !== -1 : this.form[info.name].indexOf(i.id) !== -1)
              : i === (row ? row[info.name] : this.form[info.name])
          ) : options?.find((i) =>
            typeof i === "object"
              ? i.id === (row ? row[info.name] : this.form[info.name])
              : i === (row ? row[info.name] : this.form[info.name])
          );
          formItem = h("van-field", {
            props: {
              readonly: true,
              clickable: true,
              name: info.name,
              label: info.label,
              value: (findChoice instanceof Array) ? (findChoice.map(i => typeof i === "object" ? i.name : i).toString()) : (typeof findChoice === "object" ? findChoice.name : findChoice),
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              for: info.name
            },
            on: {
              click: (_) => {
                this.multipleSelectOption.forFormName = info.name;
                this.multipleSelectOption.originalObj = row;
                this.multipleSelectOption.outputType = 'array';
                this.$set(this.multipleSelectOption, "columns", options);
                this.$set(this.multipleSelectOption, "options", {
                  label: 'name',
                  value: 'id'
                });
                this.$set(this.multipleSelectOption, "multipleLimit", info.multiple);
                this.multipleSelectOption.isShow = true;
              },
            },
          });
          break;
        case "file":
          formItem = h('van-cell',{
            props: {
              title: info.label,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              for: info.name
            },
          },[
            h(
              formBuilderMap(device).get(info.type),
              {
                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,
                  fileList: row ? row[info.name].map(i => {
                    if (i.hasOwnProperty('original_name')) {
                      i.name = i.original_name
                    }
                    return i
                  }) : 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;
                      }
                    });
                    row ? row[info.name] = fileList : this.form[info.name] = fileList;
                  },
                  onRemove: (file, fileList) => {
                    row ? row[info.name] = fileList : this.form[info.name] = fileList;
                  },
                  onError: (err, file, fileList) => {
                    window.$_uploading = false
                    row ? row[info.name] = fileList : 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.name
                        ),
                      ]),
                      h("i", {
                        class: "el-icon-close",
                        on: {
                          ["click"]: () => {
                            this.$set(
                              this.file,
                              info.field,
                              this.file[info.field].filter(
                                (item) => item !== file
                              )
                            );
                          },
                        },
                      }),
                    ];
                  },
                },
              },
              [
                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]) {
            flowList('all', {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: info.stub
            }).then(res => {
              this.$set(this.flows, info.name, res.data.data)
            })
          }
          formItem = h("van-field", {
            props: {
              readonly: true,
              clickable: true,
              name: info.name,
              label: info.label,
              value: row ? row[info.name]?.toString()?.split(',').map(j => {
                return this.flows[info.name]?.find((i) =>
                  i.id == j
                )?.title;
              })?.toString() : this.form[info.name]?.toString()?.split(',').map(j => {
                return this.flows[info.name]?.find((i) =>
                  i.id == j
                )?.title;
              })?.toString(),
              clearable: true,
              placeholder: info.help_text,
              rules: this.rules[info.name],
              required: !!myRules?.find(j => j.required)
            },
            attrs: {
              for: info.name
            },
            on: {
              click: (_) => {
                this.multipleSelectOption.forFormName = info.name;
                this.multipleSelectOption.originalObj = row;
                this.multipleSelectOption.outputType = 'string';
                this.$set(this.multipleSelectOption, "columns", this.flows[info.name]);
                this.$set(this.multipleSelectOption, "options", {
                  label: 'title',
                  value: 'id'
                });
                this.$set(this.multipleSelectOption, "multipleLimit", info.multiple);
                this.multipleSelectOption.isShow = true
              },
            },
          });
          break;
        case "relation":
          let copySubForm = deepCopy(this.form[info.name][0])
          formItem = h("div", [
            h("van-cell", {
              props: {
                "arrow-direction": "down",
                title: info.label,
              },
              attrs: {
                for: info.name
              }
            },[
              h('van-button',{
                props: {
                  color: 'var(--theme-color)',
                  icon: 'plus',
                  size: 'small'
                },
                on: {
                  'click':_ => {
                    this.form[info.name].push(copySubForm)
                  }
                }
              },'新增')
            ]),
            h(
              "div",
              this.form[info.name].map((sForm, sIndex) =>
                h(
                  "van-cell-group",
                  {
                    props: {
                      inset: false
                    }
                  },
                  [
                    h("van-cell", {
                      props: {
                        title: info.label + "-" + (sIndex + 1)
                      }
                    },[
                      h('van-button',{
                        props: {
                          size: 'mini',
                          type: 'danger',
                          icon: 'minus'
                        },
                        on: {
                          click: _ => {
                            this.form[info.name].splice(sIndex, 1)
                          }
                        }
                      },'删除')
                    ]),
                    h(
                      "van-form",
                      {
                        ref: "subVanForm-"+sIndex,
                        props: {
                          "scroll-to-error": true,
                        },
                        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,
                            null,
                            info.name
                          )
                        )
                    ),
                  ]
                )
              )
            ),
          ]);
          break;
      }
    } else if(info._readable || pReadable) {
      switch (info.type) {
        case "date":
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
                value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日") : ''
              }
            }
          );
          break;
        case "datetime":
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
                value: this.form[info.name] ? moment(this.form[info.name]).format("YYYY年MM月DD日 HH时mm分ss秒") : ''
              }
            },
          );
          break;
        case "select":
          let findSelect = options.find((i) =>
            typeof i === "object"
              ? i.id === this.form[info.name]
              : i === this.form[info.name]
          );
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
                value: typeof findSelect === "object" ? findSelect.name : findSelect
              }
            },
          );
          break;
        case 'choice':
          let findChoice = options.find((i) =>
            typeof i === "object"
              ? i.id === this.form[info.name]
              : i === this.form[info.name]
          );
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
                value: typeof findChoice === "object" ? findChoice.name : findChoice
              }
            },
          );
          break;
        case 'file':
          let files = (row ? row[info.name] : this.form[info.name])
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
              }
            },
            ((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: {
                "arrow-direction": "down",
                title: info.label,
              },
            }),
            h(
              "div",
              this.form[info.name]?.map((sForm, sIndex) =>
                h(
                  "van-cell-group",
                  {
                    props: {
                      inset: false
                    }
                  },
                  [
                    h("van-cell", {
                      props: {
                        title: info.label + "-" + (sIndex + 1)
                      }
                    }),
                    h(
                      "van-form",
                      {
                        ref: "subVanForm",
                        props: {
                          "scroll-to-error": true,
                        },
                        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]) {
            flowList('all', {
              page: 1,
              page_size: 9999,
              is_simple: 1,
              custom_model_id: info.stub
            }).then(res => {
              this.$set(this.flows, info.name, res.data.data)
            })
          }
          formItem = h(
            "van-cell",
            {
              attrs: {
                for: info.name
              },
              props: {
                title: info.label,
                value: row ? row[info.name]?.toString()?.split(',').map(j => {
                  return this.flows[info.name]?.find((i) =>
                    i.id == j
                  )?.title;
                })?.toString() : this.form[info.name]?.toString()?.split(',').map(j => {
                  return this.flows[info.name]?.find((i) =>
                    i.id == j
                  )?.title;
                })?.toString()
              }
            },
          );
          break;
        default:
          formItem = h('van-cell',{
            attrs: {
              for: info.name
            },
            props: {
              title: info.label,
              value: row ? row[info.name] : this.form[info.name]
            }
          })
      }
    }

    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
          jointlySignContent.push(h('div',[
            h('span', value.value),
            h('br'),
            info.is_sign ? 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
              }
            }) : '',
            info.is_sign ? h('br') : '',
            h('span', log.updated_at ? this.$moment(log.updated_at).format('YYYY年MM月DD') : '')
          ]))
        }
      })
    })
    return isJointly ? [(/\/detail/.test(this.$route.path) && this.$route.query.flow_id && jointlySignContent.length > 0) ? '' : formItem,(() => {
      if (info.is_sign && !(/\/detail/.test(this.$route.path && this.$route.query.flow_id && jointlySignContent.length > 0))) {
        let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name) !== -1) && (row ? row[info.name] : this.form[info.name])
        if (log && log.user) {
          return h('van-cell',[
            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('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
          ])
        }
      }
    })(),jointlySignContent] : [formItem,(() => {
      if (info.is_sign) {
        let log = this.logs.find(log => log.node?.fields?.findIndex(field => field?.field?.name === info.name) !== -1 && (row ? row[info.name] : this.form[info.name]))
        if (log && log.user) {
          return h('van-cell',[
            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('div', this.$moment(log.updated_at).format('YYYY年MM月DD日 HH时mm分'))
          ])
        }
      }
    })()]
  }
}
