- 原来的框架使用的是taro3.1,开发自定义组件时想使用taro ui组件,由于taro ui组件的form表单的提交事件不能获取表单的值,这样所有表单的值获取与赋值需要自己维护。提高了开发的麻烦程度与困难程度。Taro UI | O2Team
- 参考设计集团任务流的自定义表单代码。
- 用的vue
- 组件是非常简单的,一个文件就写完了。对我们这个系统完全没有参考价值
- 唯一一点有参考价值的是用的京东的ui组件,他的form表单是可以正常获取到表单值并且可以复制的。NutUI - 移动端 React 小程序组件库
<template>
<nut-form class="layout" :model-value="formData.state" ref="ruleForm">
<nut-form-item
v-for="(item, index) in formData.formItems"
:key="index"
:label="item.name"
:prop="item.field"
>
<input
v-if="item.type === fieldType.Input"
class="nut-input-text"
placeholder="请输入"
type="text"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
/>
<input
v-if="item.type === fieldType.InputNumber"
class="nut-input-text"
placeholder="请输入数字"
type="digit"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
/>
<input-picker
v-if="
item.type === fieldType.Picker || item.type === fieldType.PickerCustom
"
title="请选择"
:columns="item.options ?? []"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
/>
<input-date-picker
v-if="item.type === fieldType.DatePicker"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
/>
<input-area
v-if="item.type === fieldType.Area"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
v-model:label="formData.state[item.field].label"
/>
<!-- <input-uploader
v-if="item.type === fieldType.Upload"
name="file"
multiple
capture
list-type="list"
maximum="9"
:url="uploadUrl"
:maximize="1024 * 1024 * 10"
:headers="headers"
:is-deletable="item.disabled"
:disabled="!item.disabled"
:before-delete="() => item.disabled"
@oversize="handleUploadOversize"
@success="handleUploadSuccess"
@file-item-click="handleFileItemClick"
v-model:file-list="formData.state[item.field].value"
>
<nut-button v-show="item.disabled" type="success" size="small"
>上传文件</nut-button
>
</input-uploader> -->
<!-- accept=".xlsx,.xls,image/*,.doc, .docx,.ppt, .pptx,.txt,.pdf"
multiple
capture="camera"
max-count="9" -->
<van-uploader
v-if="item.type === fieldType.Upload"
accept=".xlsx,.xls,image/*,.doc, .docx,.ppt, .pptx,.txt,.pdf"
result-type="file"
:max-size="1024 * 1024 * 10"
:deletable="item.disabled"
:before-delete="() => item.disabled"
:disabled="!item.disabled"
:after-read="afterRead"
@oversize="handleUploadOversize"
v-model="formData.state[item.field].value"
/>
<!-- <van-button icon="plus" type="primary">上传文件</van-button> -->
<!-- <nut-button v-show="item.disabled" type="success" size="small"
>上传文件</nut-button
> -->
<input-address
v-if="item.type === fieldType.Address"
:disabled="!item.disabled"
v-model="formData.state[item.field].value"
/>
</nut-form-item>
<nut-cell v-show="isValid">
<nut-button size="large" type="primary" color="#4076F6" @click="submit"
>登记信息</nut-button
>
<!-- <nut-button size="small" @click="reset">重置提示状态</nut-button> -->
</nut-cell>
</nut-form>
</template>
<script lang="ts">
import { defineComponent, ref, computed, reactive } from "vue";
import InputPicker from "./input/InputPicker.vue";
import InputDatePicker from "./input/InputDatePicker.vue";
import InputArea from "./input/InputArea.vue";
import InputAddress from "./input/InputAddress.vue";
import InputUploader from "./input/InputUploader.vue";
import { TaskFieldType, TaskStatus } from "@/common/type";
import { isEmpty } from "lodash";
import config from "@/utils/config";
import dd from "gdt-jsapi";
import { isValidTask } from "@/utils";
import { Toast } from "@/Library";
import { useStore } from "vuex";
// import moment from "moment";
export default defineComponent({
name: "custom-form",
components: {
InputPicker,
InputDatePicker,
InputArea,
InputAddress,
InputUploader
},
emits: ["submit"],
props: {
/**
* 是否折叠
*/
fieldList: {
type: Array
},
taskStatus: {
type: String
}
},
setup(props, { emit }) {
console.log("props: ", props);
const ruleForm = ref<any>(null);
const store = useStore();
const token = computed(() => store.state.user.token);
const uploadUrl = `${config.apiPrefix}/app/task/file/upload`;
const headers = {
"X-Access-Token": token.value,
"Content-Type": "multipart/form-data"
};
const isValid = computed(() => {
return isValidTask(props.taskStatus as TaskStatus);
});
const afterRead = async file => {
console.log("file: ", file);
file.status = "uploading";
file.message = "上传中...";
const formData = new FormData();
formData.append("file", file.file);
formData.append("type", file.type);
const res = await store.dispatch("app/uploadFile", formData);
if (res.success) {
file.status = "done";
file.message = "上传成功";
file.response = res;
} else {
file.status = "failed";
file.message = res.message;
}
};
const formData = computed(() => {
const state: any = {};
const formItems: any[] = [];
props.fieldList?.forEach((item: any) => {
try {
const attr = JSON.parse(item.jsonObj);
let defaultValue = item?.value ?? item?.defaultValue ?? "";
if (
item.type === TaskFieldType.Picker ||
item.type === TaskFieldType.PickerCustom
) {
defaultValue = [defaultValue];
} else if (item.type === TaskFieldType.Area) {
defaultValue = defaultValue.split(",") ?? [];
} else if (item.type === TaskFieldType.Upload) {
defaultValue = isEmpty(defaultValue)
? []
: defaultValue.split(",").map((item: any) => {
return {
name: item.replace(/^.*[\\\/]/, ""),
url: `${config.apiPrefix}${item}`,
status: "success",
message: "上传成功",
type: "image"
};
}) ?? [];
}
state[attr.field] = {
label: defaultValue,
value: defaultValue
};
console.log("attr.field: ", attr);
console.log("defaultValue: ", defaultValue);
formItems.push({
...attr,
...item,
// 如果是无效的任务,则禁用所有表单项
disabled: isValid.value ? attr.disabled : false
});
} catch (error) {
console.log("error: ", error);
}
});
return { state: reactive(state), formItems };
});
const handleFileItemClick = async ({ fileItem }) => {
console.log("fileItem: ", fileItem);
try {
await dd.openLink({
url: fileItem.url
});
} catch (error) {
console.log("error: ", error);
}
};
const handleUploadOversize = (files: File[]) => {
console.log("oversize 触发", files);
Toast.show({ title: "文件大小不能超过10M" });
};
const handleUploadSuccess = ({ data, fileItem }) => {
fileItem.response = data;
};
const submit = () => {
ruleForm.value.validate().then(({ valid, errors }: any) => {
if (!valid) {
console.log("errors: ", errors);
return;
}
console.log("success", formData.value.state);
// 遍历字段重新组装数据
const taskDellList: any[] = [];
const state = formData.value.state;
for (let key in state) {
let { label, value } = state[key];
const item = formData.value.formItems.find(
(item: any) => item.field === key
);
if (!item) {
continue;
}
// 后端存储字段为string类型,需要做转换
if (
item?.type === TaskFieldType.Picker ||
item?.type === TaskFieldType.PickerCustom
) {
value = value?.join("");
label = value;
} else if (item?.type === TaskFieldType.Area) {
// 这里不需要label赋值,因为组件支持了v-model:label
value = value?.join(",");
} else if (item?.type === TaskFieldType.Upload) {
const hasUploading = value?.some(
(item: any) => item.status === "uploading"
);
console.log("hasUploading: ", hasUploading);
if (hasUploading) {
Toast.show({ title: "请等待文件上传完成" });
return;
}
value = value
?.map((item: any) => {
console.log("upload item: ", item);
let url = "";
try {
// 如果是上传的文件,则从返回值中读取,否则截断路由前缀
if (item?.response) {
// const data = JSON.parse(item?.response);
url = item?.response?.data?.url ?? "";
} else {
url = item?.url?.substring(config.apiPrefix.length) ?? "";
}
} catch (error) {
console.log("error: ", error);
}
return url;
})
.join(",");
label = value;
} else {
label = value;
}
taskDellList.push({
taskId: item.taskId,
taskFieldId: item.id,
label: label,
value: value
});
}
console.log("taskDellList: ", taskDellList);
emit("submit", taskDellList);
});
};
const reset = () => {
ruleForm.value.reset();
};
return {
uploadUrl,
headers,
ruleForm,
formData,
isValid,
config: config,
fieldType: TaskFieldType,
afterRead,
handleUploadOversize,
handleUploadSuccess,
handleFileItemClick,
submit,
reset
};
}
});
</script>
-
添加京东组件的依赖,需要配置,其中有一个配置designWidth是需要taro3.4.13才可以使用的。于是开始升级框架。NutUI - 移动端 React 小程序组件库 编译配置详情 | Taro 文档
-
taro升级框架太繁琐,框架问题太多。中间出了很多问题(依赖安装源,node版本等等)。Taro 正式发布 3.4 版本 —— 全面支持 Preact 和 Vue3.2 | Taro 文档
-
现在升级完后有一个代码规范的报错,暂时还解决不了。看他们的issue上面也有很多人遇到这个问题。react ts提示异常 · Issue #11097 · NervJS/taro · GitHub
- 将@tarojs/webpack-runner依赖升级到3.4.14react ts提示异常 · Issue #11097 · NervJS/taro · GitHub
- 修改 tsconfig.jsonview不能用作jsx组件 版本为3.4.13 · Issue #12029 · NervJS/taro · GitHub
-
form表单数据录入的问题
-
uploader组件在form表单中使用的问题Form表单 Form.Item加上传组件,会触发表单提交事件 · Issue #2186 · jdf2e/nutui-react · GitHub
- 没人理我