代码拉取完成,页面将自动刷新
<template>
<el-form
class="form-container"
ref="ruleFormRef"
:model="form"
:label-width="labelWidth"
:style="{ width: size }"
>
<el-row :align="'middle'" :justify="'center'">
<template v-for="item in formItems">
<el-col v-bind="itemColLayout">
<el-form-item
:label="item.label"
:prop="item.prop"
:style="{
itemStyle: true,
alignItems: item.type !== 'upload' ? 'center' : 'top',
}"
:rules="item.rules"
>
<el-input
v-if="item.type == 'number'"
v-model="form[`${item.prop}`]"
oninput="if(value.length > 11) value=value.slice(0, 11)"
:type="item.type"
:disabled="item.disabled"
:placeholder="`请输入${item.label}`"
v-bind="item.otherOptions"
onkeypress="return /[\d]/.test(String.fromCharCode(event.keyCode))"
/>
<el-input
v-if="
item.type == 'input' ||
item.type == 'textarea' ||
item.type == 'password'
"
v-model="form[`${item.prop}`]"
:type="item.type"
:disabled="item.disabled"
:maxlength="item.maxlength"
:show-word-limit="item.showWordLimit"
:placeholder="`请输入${item.label.replace(':', '')}`"
:show-password="item.type === 'password'"
v-bind="item.otherOptions"
/>
<!-- 下拉筛选 -->
<el-select
v-if="item.type == 'select'"
v-model="form[`${item.prop}`]"
v-bind="item.otherOptions"
style="width: 100%"
:placeholder="`请选择${item.label.replace(':', '')}`"
:disabled="item.disabled"
>
<el-option
v-for="option in optionItem[`${item.prop}`] || item.valueEnum"
:key="option.key"
:label="option.value"
:value="option.key"
></el-option>
</el-select>
<!-- 日期 -->
<el-date-picker
v-if="item.type == 'datepicker'"
v-model="form[`${item.prop}`]"
v-bind="item.otherOptions"
placeholder="请选择日期"
:disabled="item.disabled"
></el-date-picker>
<!-- 上传 -->
<div v-if="item.type == 'upload'" style="width: 100%">
<el-upload
class="upload-demo"
drag
ref="upload"
:limit="1"
v-model="form[`${item.prop}`]"
:before-upload="beforeUpload"
:on-exceed="handleExceed"
:on-remove="
(uploadFile, uploadFileList) =>
handleRemove(uploadFile, uploadFileList, item)
"
:http-request="(option: any) => requestUpload(option, item)"
:on-change="handleProgress"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
<em>点击</em>
或将文件
<em>拖拽</em>
到这里上传
</div>
<template #tip>
<div class="el-upload__tip">请上传xls或者xlsx的文件</div>
</template>
</el-upload>
<el-progress v-if="showProcess" :percentage="processLen" />
</div>
</el-form-item>
</el-col>
</template>
</el-row>
<div class="footer" v-if="showSubmit">
<slot name="footer">
<el-button type="primary" @click="resetBtnClick">重置</el-button>
<el-button
type="primary"
:loading="loading"
@click="searchBtnClick(ruleFormRef)"
>
提交
</el-button>
</slot>
</div>
</el-form>
</template>
<script setup lang="ts">
import { RuleItem } from "async-validator";
import { delEmpty } from "@/utils/delEmpty";
import {
FormInstance,
UploadFile,
UploadFiles,
UploadInstance,
UploadProps,
UploadRawFile,
UploadRequestOptions,
} from "element-plus";
import { UploadAjaxError } from "element-plus/es/components/upload/src/ajax";
import { StyleValue } from "vue";
// import { uploadFileList } from "@/api/dashboard";
const showProcess = ref(false);
const processLen = ref(0);
const upload = ref<UploadInstance>();
const ruleFormRef = ref<FormInstance>();
interface FormItems {
label?: string;
type?: string;
placeholder?: string;
rules?: RuleItem;
prop?: string;
valueEnum?: Object;
clearable?: boolean;
maxlength?: number;
disabled?: boolean;
multiple?: boolean;
uploadRequest?: () => Promise<any[]>;
optionList?: () => Promise<any[]>;
width?: number;
otherOptions?: any;
callback?: (props: any) => void;
}
const props = withDefaults(
defineProps<{
formItems: Array<FormItems | any>;
labelWidth?: string;
itemColLayout?: object;
itemStyle?: StyleValue;
uploadRequest?: any;
showSubmit?: boolean;
size?: string;
request: any;
callback?: (props: any) => void;
}>(),
{
labelWidth: "100px",
showSubmit: true,
itemStyle: () => ({
padding: "0",
}),
},
);
const formParams = computed(() => {
let params: any = {};
props.formItems.map((item) => {
params[item.prop] = item.value ?? "";
if (item.type == "upload") {
params[item.prop] = item.value ?? "";
}
});
return params;
});
const form = reactive({ ...formParams.value });
const optionItem = reactive<any>({});
const handleExceed: UploadProps["onExceed"] = (files: any, fileList: any) => {};
// 文件移除
const handleRemove = (
uploadFile: UploadFile,
uploadFiles: UploadFiles,
item: any,
) => {
showProcess.value = false;
// const index = form[item.prop].findIndex(
// (it: any) => it.uid == uploadFile.uid
// );
form[item.prop] = "";
};
// 上传之前的判断
const beforeUpload = (rawFile: UploadRawFile) => {
const { name } = rawFile;
const arr = name.split(".");
const afterName = arr[arr.length - 1];
if (afterName !== "xls" && afterName !== "xlsx") {
showProcess.value = false;
ElMessage.error("请输入正确的格式(.xls或者.xlsx文件)");
return false;
}
return true;
};
// 进度条
const handleProgress = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
if (uploadFile.status == "ready") {
processLen.value = 0;
showProcess.value = true;
const interval = setInterval(() => {
if (processLen.value >= 99) {
clearInterval(interval);
return;
}
processLen.value += 1;
}, 80);
}
if (uploadFile.status == "success" || uploadFile.status == "fail") {
processLen.value = 100;
showProcess.value = false;
}
};
const removeFile = (name: string, field: string) => {
const idx =
form[field] && form[field].findIndex((item: any) => item.name == name);
form[field].splice(idx, 1);
};
const uploadMethods = (
file: File,
field: any,
onError?: (res: UploadAjaxError) => void,
) => {
return props
.uploadRequest({ file: file })
.then((res: any) => {
if (res.errno == 0 || res.errno == 200) {
form[field] = res?.data;
ElMessage.success("文件上传成功");
}
})
.catch((err: any) => {
onError && onError(err);
removeFile(file.name, field);
ElMessage.error("文件上传失败,请筛选时间并进行上传!");
});
};
// 请求接口
const requestUpload = (options: UploadRequestOptions, item: any) => {
const { onError, file } = options;
// const fileInfo: any = file;
// form[item.prop].push({ uid: fileInfo.uid, name: fileInfo.name });
// console.log("’12345676", form[item.prop]);
return uploadMethods(file, item.prop, onError);
};
const loading = ref(false);
// 提交按钮
const searchBtnClick = async (formEl: FormInstance | undefined) => {
if (props.showSubmit) {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
const handleForm = delEmpty(form);
if (JSON.stringify(handleForm) == "{}") return;
loading.value = true;
props.request &&
props
.request(form)
.then(() => {
loading.value = false;
props.callback && props.callback({ success: "ok" });
})
.finally(() => (loading.value = false));
} else {
console.log("error submit!", valid, fields);
loading.value = false;
}
});
} else {
return await props.request(form).then(() => {
loading.value = false;
props.callback && props.callback({ success: "ok" });
});
}
};
// 获取下拉数据
const getOptionList = () => {
props.formItems.map(async (item) => {
if (!item.optionList) return;
optionItem[item.prop] = [];
const res = await item.optionList!();
optionItem[item.prop].push(...res);
});
};
getOptionList();
// 重置按钮
const resetBtnClick = () => {
ruleFormRef.value?.resetFields();
};
defineExpose({ searchBtnClick, ruleFormRef, loading, processLen });
</script>
<style lang="scss">
@media screen and (max-width: 1700px) {
.form-container {
width: 90% !important;
}
}
.el-popper {
transform-origin: left top;
transform: scale(var(--scale));
}
.form-container {
margin: 0 auto 18px;
.el-input {
height: 40px;
}
.upload-demo {
width: 100%;
}
}
.footer {
text-align: right;
}
.el-upload-dragger .el-icon--upload {
color: var(--el-color-primary);
}
.el-progress__text {
color: #000;
}
.el-dialog .el-select .el-input .el-select__caret {
color: #000 !important;
}
input::placeholder {
color: rgb(168, 171, 178) !important;
}
.el-form .el-input__prefix {
color: rgb(168, 171, 178);
}
.el-form .el-input__wrapper {
height: 100%;
}
</style>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。