<script setup lang="ts">
|
import { onMounted, ref, reactive } from "vue";
|
import ReCol from "@/components/ReCol";
|
import { message } from "@/utils/message";
|
import { TenderProps } from "./utils/types";
|
import { useDetail } from "./utils/detail";
|
import { usePublicHooks } from "../hooks";
|
import type {
|
FormInstance,
|
FormRules,
|
UploadProps,
|
UploadInstance,
|
UploadRawFile
|
} from "element-plus";
|
import { baseUrlApi } from "@/api/util";
|
import { genFileId } from "element-plus";
|
const { openUploadDialog, state, generateTimestampWithRandom } = useDetail();
|
import { getUploadToken, uploadFileAli, uploadFileAli11 } from "@/api/upload";
|
const props = withDefaults(defineProps<TenderProps>(), {
|
formInline: () => ({
|
id: "", // 主键Id(必填)
|
projectName: "",
|
toubiaoStartDate: "", // 投标报名开始时间(必填,格式:yyyy-MM-dd HH:mm:ss)
|
toubiaoEndDate: "", // 投标报名结束时间(必填,格式:yyyy-MM-dd HH:mm:ss)
|
kaibiaoDate: "", // 开标时间(必填,格式:yyyy-MM-dd HH:mm:ss)
|
zhaobiaowenjian: "", // 招标文件(必填,长度1-512字符)
|
biangengwenjian: "",
|
fujian: "", // 附件(可选,最大长度512字符,可为空)
|
kaibiaodidian: "" // 开标地点(必填,长度1-250字符)
|
}),
|
isChange: null
|
});
|
interface FormInlineType {
|
// 项目标题
|
projectName: string | null | undefined;
|
// 投标报名开始时间(通常为ISO日期字符串格式)
|
toubiaoStartDate: string | null | undefined;
|
// 投标报名结束时间
|
toubiaoEndDate: string | null | undefined;
|
// 开标时间
|
kaibiaoDate: string | null | undefined;
|
// 招标文件(可能是文件路径、ID或文件对象)
|
zhaobiaowenjian: string | null | undefined;
|
// 变更文件
|
biangengwenjian: string | null | undefined;
|
// 附件(文本描述或路径)
|
fujian: string | null | undefined;
|
// 开标地点
|
kaibiaodidian: string | null | undefined;
|
}
|
const gonggaoRules = reactive<FormRules<FormInlineType>>({
|
projectName: [{ required: true, message: "请输入标题", trigger: "change" }],
|
toubiaoStartDate: [
|
{ required: true, message: "请选择投标报名开始时间", trigger: "change" }
|
],
|
toubiaoEndDate: [
|
{ required: true, message: "请选择投标报名结束时间", trigger: "change" },
|
{
|
validator: (rule, value, callback) => {
|
if (value && newFormInline.value.toubiaoStartDate) {
|
if (
|
new Date(value).getTime() <
|
new Date(newFormInline.value.toubiaoStartDate).getTime()
|
) {
|
callback(new Error("结束时间不能早于开始时间"));
|
} else {
|
callback();
|
}
|
} else {
|
callback();
|
}
|
},
|
trigger: "change"
|
}
|
],
|
kaibiaoDate: [
|
{ required: true, message: "请选择开标时间", trigger: "change" },
|
{
|
validator: (rule, value, callback) => {
|
if (value && newFormInline.value.toubiaoEndDate) {
|
if (
|
new Date(value).getTime() <
|
new Date(newFormInline.value.toubiaoEndDate).getTime()
|
) {
|
callback(new Error("开标时间不能早于投标结束时间"));
|
} else {
|
callback();
|
}
|
} else {
|
callback();
|
}
|
},
|
trigger: "change"
|
}
|
],
|
zhaobiaowenjian: [
|
{ required: true, message: "请上传招标文件", trigger: "blur" }
|
],
|
biangengwenjian: [
|
{ required: true, message: "请上传变更文件", trigger: "blur" }
|
],
|
fujian: [{ max: 512, message: "附件长度不能超过512个字符", trigger: "blur" }],
|
kaibiaodidian: [
|
{ required: true, message: "请输入开标地点", trigger: "blur" }
|
]
|
});
|
const isLoading = ref(false);
|
const ruleFormRef = ref();
|
const { switchStyle } = usePublicHooks();
|
const newFormInline = ref(props.formInline);
|
const validateForm = reactive({
|
fileList: [],
|
date: ""
|
});
|
const upload = ref<UploadInstance>();
|
const file = ref(null);
|
const uploadedUrl = ref("");
|
function getRef() {
|
return ruleFormRef.value;
|
}
|
const handleAvatarSuccess: UploadProps["onSuccess"] = (
|
response,
|
uploadFile
|
) => {
|
if (response.code == "200") {
|
// state.ruleForm.businessLicense = URL.createObjectURL(uploadFile.raw!);
|
if (props.isChange) {
|
newFormInline.value.biangengwenjian = response.result;
|
} else {
|
newFormInline.value.zhaobiaowenjian = response.result;
|
}
|
} else {
|
message(response.message, {
|
type: "error"
|
});
|
}
|
isLoading.value = false;
|
};
|
const handleChange = file => {
|
console.log(file);
|
|
if (file.status !== "ready") return;
|
let suffName = file.name.substring(file.name.lastIndexOf(".") + 1);
|
const extension = suffName === "pdf";
|
// const isLt10M = file.size / 1024 / 1024 < 10;
|
if (!extension) {
|
message(`仅支持pdf格式,请上传pdf`, {
|
type: "error"
|
});
|
validateForm.fileList = [];
|
return false;
|
}
|
fetchCredentials(file);
|
// upload.value!.submit();
|
};
|
// state.formDataNew = {
|
// policy: res.result.policy, //表单域
|
// "x-oss-signature-version": res.result.x_oss_signature_version, //指定签名的版本和算法
|
// "x-oss-credential": res.result.x_oss_credential, //指明派生密钥的参数集
|
// "x-oss-date": res.result.x_oss_date, //请求的时间
|
// "x-oss-signature": res.result.signature, //签名认证描述信息
|
// "x-oss-security-token": res.result.security_token, //安全令牌
|
// success_action_status: "200" //上传成功后响应状态码
|
// };
|
const fetchCredentials = async file => {
|
// 这里应调用你自己的后端接口获取临时凭证
|
let res = await getUploadToken();
|
if (res.code == 200) {
|
let keyVal = generateTimestampWithRandom(res.result.DirPath, file.name);
|
let upUrl = res.result.url;
|
let upPath = res.result.DirPath;
|
let formData = new FormData();
|
formData.append("policy", res.result.policy);
|
formData.append(
|
"x-oss-signature-version",
|
res.result.x_oss_signature_version
|
);
|
formData.append("x-oss-credential", res.result.x_oss_credential);
|
formData.append("x-oss-date", res.result.x_oss_date);
|
// formData.append("Signature", res.result.signature);
|
formData.append("x-oss-signature", res.result.signature);
|
formData.append("x-oss-security-token", res.result.security_token);
|
// formData.append("x-oss-content-type", "application/pdf");
|
formData.append("success_action_status", "200");
|
formData.append("key", keyVal); // 文件名
|
formData.append("file", file.raw); // file 必须为最后一个表单域
|
uploadFileAli(formData, res.result.url).then(res => {
|
let path = `${upUrl}"/"${upPath}${upPath};`;
|
if (props.isChange) {
|
newFormInline.value.biangengwenjian = path;
|
} else {
|
newFormInline.value.zhaobiaowenjian = path;
|
}
|
});
|
}
|
};
|
const beforeAvatarUpload: UploadProps["beforeUpload"] = rawFile => {
|
isLoading.value = true;
|
if (rawFile.type !== "application/pdf") {
|
message(`仅支持pdf格式,请上传pdf`, {
|
type: "error"
|
});
|
return false;
|
}
|
|
// else if (rawFile.size / 1024 / 1024 > 2) {
|
// message(`图片大小不能超过 2MB!`, {
|
// type: "error"
|
// });
|
// return false;
|
// }
|
return true;
|
};
|
const handleExceed: UploadProps["onExceed"] = (files, fileList) => {
|
upload.value!.clearFiles();
|
const file = files[0] as UploadRawFile;
|
file.uid = genFileId();
|
upload.value!.handleStart(file);
|
};
|
defineExpose({ getRef });
|
onMounted(async () => {});
|
</script>
|
|
<template>
|
<el-form
|
ref="ruleFormRef"
|
:model="newFormInline"
|
:rules="gonggaoRules"
|
label-width="140px"
|
>
|
<el-row :gutter="30">
|
<div v-if="props.isChange">
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="标题" prop="projectName">
|
<el-input
|
v-model="newFormInline.projectName"
|
clearable
|
placeholder="请输入标题"
|
/>
|
</el-form-item>
|
</re-col>
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="变更文件" prop="biangengwenjian">
|
<el-upload
|
ref="upload"
|
v-model:file-list="validateForm.fileList"
|
:limit="1"
|
:on-exceed="handleExceed"
|
:on-success="handleAvatarSuccess"
|
:before-upload="beforeAvatarUpload"
|
:headers="state.headers"
|
:auto-upload="false"
|
accept=".pdf"
|
@change="handleChange"
|
>
|
<el-button type="primary">点击上传</el-button>
|
<template #tip>
|
<div class="el-upload__tip">
|
只能上传单个文件,仅支持pdf格式
|
</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</re-col>
|
</div>
|
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="投标报名开始时间" prop="toubiaoStartDate">
|
<el-date-picker
|
v-model="newFormInline.toubiaoStartDate"
|
type="datetime"
|
clearable
|
placeholder="请选择投标报名开始时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</el-form-item>
|
</re-col>
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="投标报名结束时间" prop="toubiaoEndDate">
|
<el-date-picker
|
v-model="newFormInline.toubiaoEndDate"
|
type="datetime"
|
clearable
|
placeholder="请选择投标报名结束时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</el-form-item>
|
</re-col>
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="开标时间" prop="kaibiaoDate">
|
<el-date-picker
|
v-model="newFormInline.kaibiaoDate"
|
type="datetime"
|
clearable
|
placeholder="请选择开标时间"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
/>
|
</el-form-item>
|
</re-col>
|
<re-col v-if="!props.isChange" :value="24" :xs="24" :sm="24">
|
<el-form-item label="招标文件" prop="zhaobiaowenjian">
|
<el-upload
|
ref="upload"
|
v-model:file-list="validateForm.fileList"
|
:limit="1"
|
:on-exceed="handleExceed"
|
:auto-upload="false"
|
:on-success="handleAvatarSuccess"
|
:before-upload="beforeAvatarUpload"
|
:headers="state.headers"
|
accept=".pdf"
|
@change="handleChange"
|
>
|
<el-button type="primary">点击上传</el-button>
|
<template #tip>
|
<div class="el-upload__tip">只能上传单个文件,仅支持pdf格式</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</re-col>
|
<re-col :value="24" :xs="24" :sm="24">
|
<el-form-item label="开标地点" prop="kaibiaodidian">
|
<el-input
|
v-model="newFormInline.kaibiaodidian"
|
clearable
|
placeholder="请输入开标地点"
|
/>
|
</el-form-item>
|
</re-col>
|
</el-row>
|
</el-form>
|
</template>
|
|
<style lang="scss" scoped>
|
:deep .el-date-editor.el-input,
|
.el-date-editor.el-input__wrapper {
|
width: 100%;
|
}
|
.upload__tip {
|
width: 100%;
|
}
|
</style>
|