index.vue 9.78 KB
<!--
 * @Date: 2022-07-18 10:22:22
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2022-11-17 16:02:16
 * @FilePath: /data-table/src/views/index.vue
 * @Description: 首页
-->
<template>
  <van-image v-if="table_cover" width="100%" height="200" :src="table_cover" />
  <div v-if="table_title" class="table-title">{{ table_title }}</div>
  <div class="table-box">
    <van-form @submit="onSubmit">
      <van-cell-group>
        <component
          :ref="item.component_props.name"
          v-for="(item, index) in formData"
          :key="index"
          :is="item.component"
          :item="item"
          @active="onActive"
        />
      </van-cell-group>
      <div style="margin: 16px">
        <van-button round block type="primary" native-type="submit"> 提交 </van-button>
      </div>
    </van-form>
  </div>
</template>

<script setup>
import { createComponentType } from "@/hooks/useComponentType";
import _ from "lodash";
import { useRoute } from "vue-router";
import { queryFormAPI } from "@/api/form.js";
import { addFormDataAPI } from "@/api/data.js";

const $route = useRoute();
const table_cover = ref("");
const table_title = ref("");
const mockData = ref([]);
const formData = ref([]);
const postData = ref({});

// 格式化表单数据结构
const formatData = (data) => {
  const arr = [];
  data.forEach((field) => {
    // 解析组件属性
    const component_props = {
      name: field.component_code,
    };
    field.property_list.forEach((prop) => {
      const key = prop["property_code"];
      const obj = {
        [key]:
          prop["setting_value"].length > 1
            ? prop["setting_value"]
            : prop["setting_value"][0],
      };
      Object.assign(component_props, obj);
    });
    arr.push({
      key: field.field_name,
      value: "",
      component: "",
      component_props,
    });
  });
  return arr;
};

onMounted(async () => {
  const { data } = await queryFormAPI({ form_code: $route.query.code });
  const form_data = data[0];
  table_cover.value = "https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg";
  table_title.value = form_data.name;
  formData.value = formatData(form_data.field_list);
  // mockData.value = [
  //   {
  //     key: "phone",
  //     value: "",
  //     component: "",
  //     component_props: {
  //       name: "phone",
  //       label: "手机号",
  //       placeholder: "请输入手机号",
  //       required: true,
  //     },
  //   },
  //   {
  //     key: "field_1",
  //     value: "test",
  //     component: "",
  //     component_props: {
  //       name: "text",
  //       label: "用户名",
  //       placeholder: "请输入用户名",
  //       required: true,
  //       readonly: true,
  //       disabled: true,
  //       align: "left",
  //     },
  //   },
  //   // {
  //   //   key: 'email',
  //   //   value: '',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'email',
  //   //     label: '邮箱',
  //   //     placeholder: '请输入邮箱',
  //   //     required: true,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'id_code',
  //   //   value: '',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'id_code',
  //   //     label: '身份证号码',
  //   //     placeholder: '请输入身份证号码',
  //   //     required: true,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'age',
  //   //   value: '',
  //   //   component: '',
  //   //   component_props: {
  //   //     label: '年龄',
  //   //     placeholder: '请输入年龄',
  //   //     name: 'number',
  //   //     required: true,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'gender',
  //   //   value: '',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'radio',
  //   //     label: '性别',
  //   //     placeholder: '',
  //   //     direction: 'horizontal',
  //   //     options: [{
  //   //       key: '男',
  //   //       value: '男'
  //   //     }, {
  //   //       key: '女',
  //   //       value: '女'
  //   //     }],
  //   //     required: true,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'hobby',
  //   //   value: [],
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'checkbox',
  //   //     label: '兴趣爱好',
  //   //     placeholder: '',
  //   //     direction: 'horizontal',
  //   //     max: '3',
  //   //     options: [{
  //   //       key: '足球',
  //   //       value: '足球'
  //   //     }, {
  //   //       key: '篮球',
  //   //       value: '篮球'
  //   //     }, {
  //   //       key: '羽毛球',
  //   //       value: '羽毛球'
  //   //     }, {
  //   //       key: '乒乓球',
  //   //       value: '乒乓球'
  //   //     }],
  //   //   },
  //   // },
  //   // {
  //   //   key: 'message',
  //   //   value: '一种可以用来记录,展示文字信息的载体,有比较强的时效性。一般以黑板、木板为载体。用来留言。各种各样的留言使用。留言板还有引申的“网络留言板”。这个和网络留言本不一样的地方是留言板一般比较集中的反应信息的。',
  //   //   label: '留言',
  //   //   placeholder: '请输入留言',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'textarea',
  //   //     rows: 3,
  //   //     maxlength: null,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'vehicle',
  //   //   value: '自行车',
  //   //   label: '交通工具',
  //   //   placeholder: '请选择交通工具',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'picker'
  //   //   },
  //   //   options: [
  //   //     { text: '自行车', value: '自行车' },
  //   //     { text: '汽车', value: '汽车' },
  //   //     { text: '地铁', value: '地铁' },
  //   //   ],
  //   //   required: true,
  //   // },
  //   // {
  //   //   key: 'sign',
  //   //   value: '',
  //   //   label: '电子签名',
  //   //   placeholder: '',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'sign',
  //   //   },
  //   //   required: true,
  //   // },
  //   // {
  //   //   key: 'city',
  //   //   value: '天津市/天津市/和平区',
  //   //   city_code: '120101',
  //   //   label: '地址',
  //   //   address: '',
  //   //   placeholder: '请选择省市区',
  //   //   component_props: {
  //   //     name: 'area_picker'
  //   //   },
  //   // },
  //   // {
  //   //   key: 'date',
  //   //   value: '2022-10',
  //   //   label: '日期选择',
  //   //   placeholder: '请选择日期',
  //   //   component_props: {
  //   //     name: 'date_picker',
  //   //     title: '请选择',
  //   //     min_date: new Date(),
  //   //     columns_type: ['year', 'month']
  //   //   },
  //   // },
  //   // {
  //   //   key: 'time',
  //   //   value: '',
  //   //   label: '时间选择',
  //   //   placeholder: '请选择时间',
  //   //   component_props: {
  //   //     name: 'time_picker',
  //   //     title: '请选择',
  //   //     columns_type: ['hour', 'minute']
  //   //   },
  //   //   required: true,
  //   // },
  //   // {
  //   //   key: 'image_src',
  //   //   value: '',
  //   //   label: '图片上传',
  //   //   component_props: {
  //   //     name: 'image_uploader',
  //   //     image_type: ['jpg', 'png'],
  //   //     multiple: false
  //   //   }
  //   // }
  //   // {
  //   //   key: 'datetime',
  //   //   value: '2022-06-01 12:00',
  //   //   component_props: {
  //   //     name: 'datetime_picker',
  //   //     title: '请选择',
  //   //     label: '日期时间',
  //   //     placeholder: '请选择日期时间',
  //   //     minDate: new Date(),
  //   //     required: true,
  //   //   },
  //   // },
  //   // {
  //   //   key: 'date',
  //   //   value: '',
  //   //   label: '日历选择',
  //   //   placeholder: '请选择日历日期',
  //   //   component: '',
  //   //   component_props: {
  //   //     name: 'calendar',
  //   //     type: 'range', // 日期区间 ['multiple', 'range']
  //   //     minDate: new Date(2022, 0, 1), // 最小日期
  //   //     maxDate: new Date(2023, 0, 31), // 最大日期
  //   //     maxRange: 5, // 最大可选天数
  //   //   },
  //   //   required: false,
  //   // },
  //   // {
  //   //   key: 'rate',
  //   //   value: '',
  //   //   label: '评分',
  //   //   placeholder: '请选择评分',
  //   //   component_props: {
  //   //     name: 'rate_picker',
  //   //     count: 10
  //   //   },
  //   //   required: true,
  //   // }
  // ];
  // 生成自定义组件
  createComponentType(formData.value);
});

const sign = ref(null);
const rate_picker = ref(null);

const onSubmit = async (values) => {
  // 合并自定义字段到提交表单字段
  postData.value = _.assign(postData.value, values);
  // console.warn(mockData.value);
  // 检查非表单输入项
  if (validOther()) {
    // 通过验证
    const result = await addFormDataAPI({
      form_code: $route.query.code,
      data: JSON.stringify(postData.value),
    });
    console.warn(result);
    // if (code) {
    //   console.warn("提交成功");
    //   console.warn(data);
    // }
    // console.warn("通过验证");
  } else {
    console.warn("不通过验证");
  }
};

const onActive = (item) => {
  // 返回自定义字段
  if (item.key === "sign") {
    postData.value["sign"] = item.value;
  }
  if (item.key === "rate") {
    postData.value["rate"] = item.value;
  }
};

const validOther = () => {
  // 检验没有绑定name的输入项
  let flag = true;
  if (sign.value) {
    // 检验电子签名
    flag = sign.value[0].validSign();
  }
  if (rate_picker.value) {
    // 检验评分
    flag = rate_picker.value[0].validRate();
  }
  return flag;
};
</script>

<style lang="less" scoped>
.table-title {
  padding: 1rem;
}
.table-box {
  padding: 1rem;
}
</style>