index.vue 7.18 KB
<!--
 * @Date: 2022-07-18 10:22:22
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2022-11-22 17:59:56
 * @FilePath: /data-table/src/views/index.vue
 * @Description: 首页
-->
<template>
  <div class="table-box">
    <van-image
      v-if="PHeader.type === '单张图'"
      width="100%"
      :height="PHeaderHeight"
      :src="PHeader.cover"
      fit="cover"
    />
    <template v-if="PHeader.type === '轮播图'">
      <van-swipe class="my-swipe" lazy-render indicator-color="white">
        <van-swipe-item v-for="image in PHeader.cover" :key="index"
          ><img :src="image" style="height: 12rem; width: 100%; object-fit: cover"
        /></van-swipe-item>
      </van-swipe>
    </template>
    <div v-if="PHeader.label" class="table-title">{{ PHeader.label }}</div>
    <div v-if="PHeader.description" class="table-desc" v-html="PHeader.description" />
    <van-config-provider :theme-vars="themeVars">
      <van-form @submit="onSubmit">
        <van-cell-group :border="false">
          <component
            :id="item.key"
            :ref="item.component_props.name"
            v-for="(item, index) in formData"
            :key="index"
            :is="item.component"
            :item="item"
            @active="onActive"
          />
        </van-cell-group>
        <div v-if="formData.length" style="margin: 16px">
          <van-button v-if="model === 'edit'" round block type="primary">
            提交
          </van-button>
          <van-button v-else round block type="primary" native-type="submit">
            提交
          </van-button>
        </div>
      </van-form>
    </van-config-provider>
  </div>
</template>

<script setup>
import "@vant/touch-emulator";
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";
import { showSuccessToast, showFailToast } from "vant";
import { wxInfo } from "@/utils/tools";
import { styleColor } from "@/constant.js";
// web端判断封面图片高度
const is_pc = computed(() => wxInfo().isPC);
const PHeaderHeight = computed(() => {
  if (is_pc.value) {
    return "35vh";
  } else {
    return "20vh";
  }
});
// TAG: 自定义主题颜色
const themeVars = {
  buttonPrimaryBackground: styleColor.baseColor,
  buttonPrimaryBorderColor: styleColor.baseColor,
};

const $route = useRoute();
const PHeader = ref({});
const PHeader_cover = ref("");
const PHeader_title = ref("");
const mockData = ref([]);
const formData = ref([]);
const postData = ref({});

// 编辑模式不能提交操作
const model = $route.query.model;

// 格式化表单数据结构
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);
    });
    // 绑定组件名称标识
    const temp = {
      key: field.field_name,
      value: component_props.default ? component_props.default : "",
      component: field.component_code,
      component_props,
    };
    arr.push(temp);
  });
  return arr;
};

onMounted(async () => {
  const { data } = await queryFormAPI({ form_code: $route.query.code });
  const form_data = data[0];
  // 重构数据结构
  let page_header = {};
  let page_form = [];
  form_data.field_list.forEach((element) => {
    if (element.component_code === "page_header") {
      // 页眉组件
      const list = element.property_list;
      list.forEach((ele) => {
        page_header[ele["property_code"]] =
          ele.setting_value.length > 1 ? ele.setting_value : ele.setting_value[0];
      });
    } else {
      page_form.push(element);
    }
  });
  // TODO: 后期需要适配多种图片展示方式,展示只显示单张图片模式
  /** 页眉属性
   * @param label 表单标题
   * @param banner_type 页眉类型:["文字", "单张图", "轮播图"]
   * @param banner_url 页眉图片地址
   * @param description 描述内容
   * @param invisible 页眉展示
   */
  if (page_header) {
    PHeader.value = {
      label: page_header.label,
      description: page_header.description,
      type: page_header.banner_type,
      cover: page_header.banner_url,
    };
  }
  formData.value = formatData(page_form);
  // mockData.value = [
  //   {
  //     key: "",
  //     value: "",
  //     component: "",
  //     component_props: {
  //       name: "multi_rule",
  //       label: "同意活动规则之后才可提交",
  //       required: "1",
  //       count: "2",
  //     },
  //   },
  // ];
  // 生成自定义组件
  // createComponentType(mockData.value);
  createComponentType(formData.value);
});

// 处理没有绑定值的组件的赋值
// 图片上传,电子签名,评分组件
const image_uploader = ref(null);
const sign = ref(null);
const rate_picker = ref(null);

// 操作绑定自定义字段回调
const onActive = (item) => {
  if (item.key === "image_uploader") {
    postData.value[item.filed_name] = item.value;
  }
  if (item.key === "sign") {
    postData.value[item.filed_name] = item.value;
  }
  if (item.type === "rate") {
    postData.value = _.assign(postData.value, { [item.key]: item.value });
  }
};

// 检验没有绑定name的输入项
const validOther = () => {
  let valid = {
    status: true,
    key: "",
  };
  if (image_uploader.value) {
    // 图片上传
    valid = {
      status: image_uploader.value[0].validImageUploader(),
      key: "image_uploader",
    };
  }
  if (sign.value) {
    // 电子签名
    valid = {
      status: sign.value[0].validSign(),
      key: "sign",
    };
  }
  if (rate_picker.value) {
    // 评分组件
    valid = {
      status: rate_picker.value[0].validRate(),
      key: "rate_picker",
    };
  }
  return valid;
};

const onSubmit = async (values) => {
  // 合并自定义字段到提交表单字段
  postData.value = _.assign(postData.value, values);
  // 格式化value值为json格式, 提交格式有问题
  // for (let key in postData.value) {
  //   key = JSON.stringify(key);
  //   // postData.value[key] = postData.value[key];
  // }
  // 检查非表单输入项
  if (validOther().status) {
    // 通过验证
    const result = await addFormDataAPI({
      form_code: $route.query.code,
      // data: JSON.stringify(postData.value),
      data: postData.value,
    });
    if (result.code) {
      showSuccessToast("提交成功");
    }
    // console.warn(postData.value);
    // console.warn("通过验证");
  } else {
    console.warn(validOther().key + "不通过验证");
    // 图片上传控件报错提示
    if (validOther().key === "image_uploader") {
      showFailToast("图片上传为空");
    }
  }
};
</script>

<style lang="less" scoped>
.table-title {
  padding: 1rem;
  font-size: 1.15rem;
  text-align: center;
}
.table-desc {
  padding: 0rem 1rem;
  color: #666;
  font-size: 0.9rem;
}
.table-box {
  margin: 1rem;
  background-color: #ffffff;
  padding-bottom: 1rem;
}
</style>