<template><view class="assetEdit_container"><view class="type-box"><uv-formlabelPosition="left"labelWidth="140rpx":model="formData"ref="formRef":rules="rulesAll"><view class="content-box"><!-- 白框 --><view class="formbox"><!-- 扩展字段================================================================= --><template v-for="item in ExtrasAll" :key="item.id"><!-- 单行文本 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '0'":required="item.isRequire == '0'"><uv-inputv-model="formData[item.prop]"border="none":placeholder="`${item.placeholder || ''}`"></uv-input></uv-form-item><!-- 多行文本 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '1'":required="item.isRequire == '0'"><uv-textareav-model="formData[item.prop]"count:customStyle="{'min-height': '240rpx',}"autoHeight:maxlength="item.length":placeholder="`${item.placeholder || ''}`"></uv-textarea></uv-form-item><!-- 数字输入框 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '2'":required="item.isRequire == '0'"><uv-number-boxv-model="formData[item.prop]"inputWidth="100":min="0"@change="changeNum(item.prop)"></uv-number-box></uv-form-item><!-- 单选框组 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '3'":required="item.isRequire == '0'"><uv-radio-group v-model="formData[item.prop]"><uv-radio:customStyle="{ margin: '8px' }"v-for="i in item.options.split(',')":key="i":label="i":name="i"></uv-radio></uv-radio-group></uv-form-item><!-- 下拉单选 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '4'"@click="showSelect(item)":required="item.isRequire == '0'"><uv-inputv-model="formData[item.prop]"disableddisabledColor="#ffffff":placeholder="`${item.placeholder || ''}`"border="none"></uv-input><template v-slot:right><uv-icon name="arrow-right"></uv-icon></template></uv-form-item><!-- 日期选择 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '5'"@click="opendatetime(item)":required="item.isRequire == '0'"><uv-inputv-model="formData[item.prop]"border="none"disableddisabledColor="#ffffff"suffixIcon="calendar"suffixIconStyle="color: #909399"></uv-input></uv-form-item><!-- 文件 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '6'":required="item.isRequire == '0'"><uni-section title="选择任意文件" type="line"><view class="example-body"><uni-file-pickerlimit="5"file-mediatype="all"@select="(e) => uploadFile(e, item)":value="formatFile(formData[item.prop])"@delete="({ index }) => deleteFile(index, item)"></uni-file-picker></view></uni-section></uv-form-item><!-- 图片 --><uv-form-item:label="item.label":prop="item.prop"borderBottomv-if="item.formType == '7'":required="item.isRequire == '0'"><uni-section title="只选择图片" type="line"><view class="example-body"><uni-file-pickerlimit="9"title=""@select="(e) => uploadFilePic(e, item)":value="formatPic(formData[item.prop])"@delete="({ index }) => deleteFilePic(index, item)"></uni-file-picker></view></uni-section></uv-form-item></template></view></view></uv-form></view><view class="btns"><view class="btn"><uv-button type="primary" text="提交" shape="circle"></uv-button></view></view><!-- 动态选择框 --><uv-pickerref="selectRef":keyName="selectLabel":columns="columns"@confirm="confirmSelect"@change="changeSelect"></uv-picker><!-- 动态日期选择 --><uv-datetime-pickerref="datetimeRef"v-model="datetimevalue"mode="date":formatter="formatter"@confirm="confirmDatetime"></uv-datetime-picker></view>
</template><script setup>
import { onLoad } from "@dcloudio/uni-app";
import { ref, onMounted, computed, getCurrentInstance } from "vue";
import { getExtras, getFieldExtras } from "../../api/common";
import { getToken } from "@/utils/auth.js";
import dayjs from "dayjs";
import config from "@/config/index.js";
const { proxy } = getCurrentInstance();
// 主要是获取不同的动态字段,并且根据动态字段创建校验信息
onMounted(async () => {// 获取全局动态字段Extras.value = (await getExtras()).data;// 获取动态校验内容getRule();
});
onLoad(async ({ id }) => {// 根据分类id获取动态字段 FieldExtrasFieldExtras.value = (await getFieldExtras(formData.value.typeId)).data;// 获取动态校验内容getRule();
});// 静态字段校验规则
let rules = ref({typeName: {type: "string",required: true,message: "提示信息",trigger: ["change"],},
});
// 动态校验数据
let FieldRules = ref({});
// 所有的校验:静态+动态
let rulesAll = computed(() => {return { ...rules.value, ...FieldRules.value };
});
// 通用的动态字段
let Extras = ref([]);
// 指定的动态字段
let FieldExtras = ref([]);
// 所有动态字段:通用的动态字段+指定的动态字段
let ExtrasAll = computed(() => {return Extras.value.concat(FieldExtras.value); //动态字段拼接
});
// 动态校验
// 根据扩展字段的属性配置获取校验规则
let getRule = () => {FieldRules.value = {};ExtrasAll.value.forEach((item) => {if (item.formType == "2" || item.formType == "3" || item.formType == "4") {FieldRules.value[item.prop] = {type: item.formType == "2" ? "number" : "string",required: item.isRequire == "0",message: `${item.label}${proxy.$t("AssetList.Cannotbeempty")}`,trigger: ["change"],};} else {FieldRules.value[item.prop] = {type: "string",required: item.isRequire == "0",message: `${item.label}${proxy.$t("AssetList.Cannotbeempty")}`,trigger: ["blur"],};}});
};
// ======================================================================
// 3、动态字段下拉框自定义配置
let columns = ref([]);
// 选择弹窗
let selectRef = ref(null);
// 定义一个和选择弹窗绑定的中间件
let selectProp = ref("");
// 点击状态选择输入框弹出选项
let showSelect = (item) => {selectRef.value.open(); //打开弹窗columns.value = [item.options.split(",")]; //下拉框数据selectProp.value = item.prop; //绑定键名
};
let confirmSelect = (e) => {console.log(e.value[0], 244);// 确认选择之后的赋值操作formData.value[selectProp.value] = e.value[0];formRef.value?.validateField(selectProp.value);
};
// 数字改变
let changeNum = (prop) => {formRef.value?.validateField(prop);
};
// 4、动态日期下拉框自定义配置
let datetimeRef = ref(null);
let datetimeProp = ref("");
let datetimevalue = ref(Number(new Date())); //当前打开选择器的时间
let opendatetime = (item) => {datetimeRef.value.open(); //打开弹窗datetimeProp.value = item.prop; //绑定键名console.log(item, 267);if (formData.value[item.prop]) {// 如果时间存在则回显时间,如果没值则选择器定位到当前时间datetimevalue.value = new Date(formData.value[item.prop]);}
};
let confirmDatetime = (e) => {formData.value[datetimeProp.value] = dayjs(e.value).format("YYYY-MM-DD");formRef.value?.validateField(datetimeProp.value);
};
let formatter = (type, value) => {if (type === "year") {return `${value}${proxy.$t("AssetList.year")}`;}if (type === "month") {return `${value}${proxy.$t("AssetList.month")}`;}if (type === "day") {return `${value}${proxy.$t("AssetList.day")}`;}return value;
};
// 5、动态文件上传
let formatFile = (UrlString) => {if (UrlString) {return UrlString.split(",").map((item) => {return {url:config.baseUrl +item.split("/").slice(0, item.split("/").length - 1).join("/"),extname: item.split(".").pop(),name: item.split("/").pop(),};});} else {return [];}
};
let uploadFile = (e, item) => {const file = e;if (file.tempFilePaths.length === 0) {uni.showToast({title: proxy.$t("AssetList.Nofileselected"),icon: "none",});return;}const uploadTask = uni.uploadFile({url: config.baseUrl + "/admin/sys-file/upload",filePath: file.tempFilePaths[0],name: "file", // 这里根据后端API的字段来定义header: {Authorization: "Bearer " + getToken(),"TENANT-ID": uni.getStorageSync("tenantId"),},success: (uploadRes) => {// 一个上传返回的字段,逗号拼接所有文件地址if (formData.value[item.prop]) {formData.value[item.prop] += "," + JSON.parse(uploadRes.data).data.url;} else {formData.value[item.prop] = JSON.parse(uploadRes.data).data.url;}formRef.value?.validateField(item.prop);uni.showToast({title: proxy.$t("AssetList.UploadSuccessfully"),icon: "success",});},fail: (err) => {uni.showToast({title: proxy.$t("AssetList.Uploadfailed"),icon: "none",});},});// 如果需要监听上传进度可以使用 uploadTask.onProgressUpdate// uploadTask.onProgressUpdate((res) => {// console.log('上传进度', res.progress);// console.log('已经上传的数据长度', res.totalBytesSent);// console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend);// });
};
let deleteFile = (index, item) => {// 删除第index项if (formData.value[item.prop].split(",").length > 1) {formData.value[item.prop] = formData.value[item.prop].split(",");formData.value[item.prop].splice(index, 1);formData.value[item.prop] = formData.value[item.prop].join(",");} else {formData.value[item.prop] = "";}
};
// 动态上传图片
let formatPic = (UrlString) => {if (UrlString) {return UrlString.split(",").map((item) => {return {url:config.baseUrl +item.split("/").slice(0, item.split("/").length - 1).join("/"),extname: item.split(".").pop(),name: item.split("/").pop(),};});} else {return [];}
};
let uploadFilePic = (e, item) => {const file = e;if (file.tempFilePaths.length === 0) {uni.showToast({title: proxy.$t("AssetList.Nofileselected"),icon: "none",});return;}z;const uploadTask = uni.uploadFile({url: config.baseUrl + "/admin/sys-file/upload",filePath: file.tempFilePaths[0],name: "file", // 这里根据后端API的字段来定义header: {Authorization: "Bearer " + getToken(),"TENANT-ID": uni.getStorageSync("tenantId"),},success: (uploadRes) => {console.log(formData.value[item.prop], 521);// 一个上传返回的字段,逗号拼接所有文件地址if (formData.value[item.prop]) {formData.value[item.prop] += "," + JSON.parse(uploadRes.data).data.url;} else {formData.value[item.prop] = JSON.parse(uploadRes.data).data.url;}formRef.value?.validateField(item.prop);uni.showToast({title: proxy.$t("AssetList.UploadSuccessfully"),icon: "success",});},fail: (err) => {uni.showToast({title: proxy.$t("AssetList.Uploadfailed"),icon: "none",});},});// 如果需要监听上传进度可以使用 uploadTask.onProgressUpdate// uploadTask.onProgressUpdate((res) => {// console.log('上传进度', res.progress);// console.log('已经上传的数据长度', res.totalBytesSent);// console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend);// });
};
let deleteFilePic = (index, item) => {// 删除第index项console.log(formData.value[item.prop], 542);if (formData.value[item.prop].split(",").length > 1) {formData.value[item.prop] = formData.value[item.prop].split(",");formData.value[item.prop].splice(index, 1);formData.value[item.prop] = formData.value[item.prop].join(",");} else {formData.value[item.prop] = "";}
};
</script><style lang="scss" scoped>
.assetEdit_container {height: 100vh;width: 100vw;background-color: display: flex;flex-direction: column;.type-box {flex: 1;width: 100vw;overflow: auto;padding: 24rpx;.title {font-weight: bold;font-size: 28rpx;color: line-height: 42rpx;}.content-box {background: padding: 10rpx 24rpx;box-shadow: 0rpx 12rpx 116rpx 0rpx rgba(196, 203, 214, 0.1);border-radius: 20rpx;margin: 38rpx 0;}}.btns {height: 146rpx;width: 100%;display: flex;background-color: justify-content: space-around;align-items: center;.btn {width: 300rpx;height: 70rpx;}}
}
</style>