bash
复制代码
<template>
<view class="assetEdit_container">
<view class="type-box">
<uv-form
labelPosition="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"
borderBottom
v-if="item.formType == '0'"
:required="item.isRequire == '0'"
>
<uv-input
v-model="formData[item.prop]"
border="none"
:placeholder="`${item.placeholder || ''}`"
>
</uv-input>
</uv-form-item>
<!-- 多行文本 -->
<uv-form-item
:label="item.label"
:prop="item.prop"
borderBottom
v-if="item.formType == '1'"
:required="item.isRequire == '0'"
>
<uv-textarea
v-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"
borderBottom
v-if="item.formType == '2'"
:required="item.isRequire == '0'"
>
<uv-number-box
v-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"
borderBottom
v-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"
borderBottom
v-if="item.formType == '4'"
@click="showSelect(item)"
:required="item.isRequire == '0'"
>
<uv-input
v-model="formData[item.prop]"
disabled
disabledColor="#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"
borderBottom
v-if="item.formType == '5'"
@click="opendatetime(item)"
:required="item.isRequire == '0'"
>
<uv-input
v-model="formData[item.prop]"
border="none"
disabled
disabledColor="#ffffff"
suffixIcon="calendar"
suffixIconStyle="color: #909399"
>
</uv-input>
</uv-form-item>
<!-- 文件 -->
<uv-form-item
:label="item.label"
:prop="item.prop"
borderBottom
v-if="item.formType == '6'"
:required="item.isRequire == '0'"
>
<uni-section title="选择任意文件" type="line">
<view class="example-body">
<uni-file-picker
limit="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"
borderBottom
v-if="item.formType == '7'"
:required="item.isRequire == '0'"
>
<uni-section title="只选择图片" type="line">
<view class="example-body">
<uni-file-picker
limit="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-picker
ref="selectRef"
:keyName="selectLabel"
:columns="columns"
@confirm="confirmSelect"
@change="changeSelect"
></uv-picker>
<!-- 动态日期选择 -->
<uv-datetime-picker
ref="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获取动态字段 FieldExtras
FieldExtras.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: #f2f2fa;
display: flex;
flex-direction: column;
.type-box {
flex: 1;
width: 100vw;
overflow: auto;
padding: 24rpx;
.title {
font-weight: bold;
font-size: 28rpx;
color: #0a1629;
line-height: 42rpx;
}
.content-box {
background: #ffffff;
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: #ffffff;
justify-content: space-around;
align-items: center;
.btn {
width: 300rpx;
height: 70rpx;
}
}
}
</style>