Commit f6126ee0 by liangjianmin

feat(orderTrack): 新增采购合作框架协议电子签署功能

- 替换签署协议弹窗界面,新增上传签章协议PDF功能
- 支持协议版本展示及上传文件预览下载
- 新增协议有效期设置,支持长期有效与自定义日期范围选择
- 增加文件上传前类型校验,只允许上传PDF文件
- 实现上传成功回调,自动更新协议文件信息
- 提交协议时校验文件上传及有效期范围,且自定义有效期需大于等于两年
- 提交成功后重置表单并关闭弹窗,失败时提供错误提示
- 更新组件依赖,新增使用Element UI的Radio、Upload、Link组件
- 新增协议表单验证规则及日期选择器快捷选项
- 优化协议弹窗样式,提升用户操作体验
parent 8cc3b2f4
Showing with 315 additions and 11 deletions
......@@ -157,17 +157,45 @@
</el-table>
</el-dialog>
<!--签署合作协议-->
<el-dialog :title="title" :close-on-click-modal="false" :visible.sync="dialogVisibleSign" width="656px">
<div class="dialog-form">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="备注">
<el-input type="textarea" v-model="ruleForm.remark" placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<el-dialog :title="title" :close-on-click-modal="false" :visible.sync="dialogVisibleSign" width="680px">
<div class="agreement-content">
<p>与猎芯签订【采购合作框架协议】后,采购合同可使用电子签签署,无需重复上传下载合同文件。若有需要,请下载协议模板,并在签署完成后上传已签署协议,待审核通过方可进行电子签流程。</p>
<div class="agreement-form">
<el-form :model="agreementForm" :rules="agreementRules" ref="agreementForm" label-width="121px">
<div class="form-section">
<el-form-item label="协议版本:">
<el-link type="primary" :underline="false" href="#">采购合作框架协议</el-link>
</el-form-item>
<el-form-item label="上传签章协议:" prop="file_url">
<div class="upload-area">
<el-upload :data="fileData" :action="uploadUrl" :on-success="handleUploadSuccess" :before-upload="beforeUpload" accept=".pdf" :show-file-list="false">
<el-button icon="el-icon-upload2" type="primary">上传</el-button>
<span class="upload-tip">仅支持PDF格式</span>
</el-upload>
<div v-if="agreementForm.file_url" class="uploaded-file">
<i class="el-icon-document"></i>
<span>{{ agreementForm.file_name }}</span>
<a href="javascript:;" @click="previewFile" class="file-link">查看</a>
</div>
</div>
</el-form-item>
<el-form-item label="有效期:" prop="validity_type">
<div class="validity-area" :style="{ marginTop: agreementForm.validity_type === 1 ? '7px' : '0px' }">
<el-radio v-model="agreementForm.validity_type" :label="1">长期有效</el-radio>
<el-radio v-model="agreementForm.validity_type" :label="2">自定义</el-radio>
<el-date-picker v-if="agreementForm.validity_type === 2" v-model="validityRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 300px; margin-left: 20px;" :picker-options="pickerOptions" format="yyyy-MM-dd" clearable :unlink-panels="true"></el-date-picker>
</div>
</el-form-item>
<el-form-item label="状态:">
<span></span>
</el-form-item>
</div>
</el-form>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"></el-button>
<el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
<el-button @click="cancelAgreement"></el-button>
<el-button type="primary" @click="submitAgreement">提交审核</el-button>
</div>
</el-dialog>
</section>
......@@ -175,14 +203,14 @@
<script>
import Vue from 'vue';
import Menu from "@/components/menu.vue";
import { Autocomplete, Button, Cascader, DatePicker, Dialog, Form, FormItem, Input, Message, Option, Pagination, Popover, Select, Table, TableColumn, Tag } from 'element-ui'
import { Autocomplete, Button, Cascader, DatePicker, Dialog, Form, FormItem, Input, Link, Message, Option, Pagination, Popover, Radio, Select, Table, TableColumn, Tag, Upload } from 'element-ui'
import Tool from "@/tool";
import { NODE_ENVS } from "@/ajax";
import qs from 'qs';
Vue.prototype.$message = Message;
Vue.use(Button).use(Form).use(Select).use(Option).use(Input).use(FormItem).use(Dialog).use(Pagination);
Vue.use(TableColumn).use(Table).use(Cascader).use(Autocomplete).use(DatePicker).use(Tag).use(Popover);
Vue.use(TableColumn).use(Table).use(Cascader).use(Autocomplete).use(DatePicker).use(Tag).use(Popover).use(Radio).use(Upload).use(Link);
export default {
name: "orderTrackGoods",
data() {
......@@ -210,6 +238,64 @@
currency: '',
create_time: ''
},
// 签署协议表单数据
agreementForm: {
type: 'cooperation_agreement',//附件类型
file_url: '',//文件地址
file_name: '',//文件名称
validity_type: 1,//时效类型,1是永久,2是有区间
validity_start: '',//有效期开始
validity_end: ''//有效期结束
},
// 有效期日期范围
validityRange: '',
// 日期选择器配置
pickerOptions: {
shortcuts: [
{
text: '两年',
onClick(picker) {
var start = new Date();
var end = new Date();
end.setFullYear(start.getFullYear() + 2);
picker.$emit('pick', [start, end]);
}
},
{
text: '三年',
onClick(picker) {
var start = new Date();
var end = new Date();
end.setFullYear(start.getFullYear() + 3);
picker.$emit('pick', [start, end]);
}
},
{
text: '五年',
onClick(picker) {
var start = new Date();
var end = new Date();
end.setFullYear(start.getFullYear() + 5);
picker.$emit('pick', [start, end]);
}
}
]
},
// 文件上传相关
uploadUrl: 'http://file.liexindev.net/uploadFile?sys_type=2',
fileData: {},
// 表单验证规则
agreementRules: {
file_url: [
{ required: true, message: '请上传签章协议', trigger: 'change' }
],
validity_type: [
{ required: true, message: '请选择有效期类型', trigger: 'change' }
],
validity_range: [
{ required: true, message: '请选择有效期时间范围', trigger: 'change' }
]
},
tableData: "",
multipleSelection: []
};
......@@ -226,6 +312,16 @@
this.formInline.quote_sn = this.$route.query.quote_sn || '';
this.getData();
}
},
// 监听有效期日期范围变化
validityRange(newVal) {
if (newVal && newVal.length === 2) {
this.agreementForm.validity_start = newVal[0];
this.agreementForm.validity_end = newVal[1];
} else {
this.agreementForm.validity_start = '';
this.agreementForm.validity_end = '';
}
}
},
methods: {
......@@ -390,6 +486,103 @@
}
})
},
/**
* 文件上传前的校验
*/
beforeUpload(file) {
var isValidType = file.type === 'application/pdf';
if (!isValidType) {
this.$message.error('只能上传PDF格式的文件!');
return false;
}
return true;
},
/**
* 文件上传成功回调
*/
handleUploadSuccess(response, file) {
if (response.code === 0) {
this.agreementForm.file_url = response.data.oss_file_url;
this.agreementForm.file_name = response.data.file_name;
this.$message.success('文件上传成功!');
} else {
this.$message.error(response.msg || '文件上传失败!');
}
},
/**
* 预览文件
*/
previewFile() {
if (this.agreementForm.file_url) {
window.open(this.agreementForm.file_url);
}
},
/**
* 取消协议
*/
cancelAgreement() {
this.dialogVisibleSign = false;
this.resetAgreementForm();
},
/**
* 重置协议表单
*/
resetAgreementForm() {
this.agreementForm = {
type: 'cooperation_agreement',
file_url: '',
file_name: '',
validity_type: 1,
validity_start: '',
validity_end: ''
};
this.validityRange = '';
if (this.$refs.agreementForm) {
this.$refs.agreementForm.resetFields();
}
},
/**
* 提交协议
*/
submitAgreement() {
// 检查文件是否上传
if (!this.agreementForm.file_url) {
this.$message.error('请先上传签章协议文件');
return;
}
// 如果是自定义有效期,检查日期范围是否选择
if (this.agreementForm.validity_type === 2) {
if (!this.validityRange) {
this.$message.error('请选择有效期时间范围');
return;
}
// 校验有效期必须大于等于两年
var startDate = new Date(this.validityRange[0]);
var endDate = new Date(this.validityRange[1]);
var diffTime = endDate.getTime() - startDate.getTime();
var diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays < 730) { // 两年约等于730天
this.$message.error('自定义有效期必须大于等于两年');
return;
}
}
this.$http('POST', '/api/attachment/applyAttachmentAudit', this.agreementForm).then(res => {
if (res.code === 0) {
this.$message.success('提交成功!');
this.dialogVisibleSign = false;
this.resetAgreementForm();
} else {
this.$message.error(res.msg || '提交失败!');
}
}).catch(err => {
this.$message.error('网络错误,请稍后重试!');
});
}
},
components: {
Menu
......@@ -415,4 +608,114 @@
margin-right: 15px;
}
}
.agreement-content {
font-size: 14px;
>p {
color: #666;
margin-bottom: 20px;
}
}
.agreement-form {
.form-section {
margin-bottom: 20px;
}
.upload-area {
position: relative;
.el-upload {
display: inline-block;
margin-right: 10px;
}
.upload-tip {
color: #999;
font-size: 12px;
margin-left: 10px;
}
}
.validity-area {
display: flex;
align-items: center;
flex-wrap: wrap;
.el-radio {
margin-right: 20px;
}
}
}
.uploaded-file {
margin-top: 10px;
padding: 8px 12px;
background: #f0f9ff;
border: 1px solid #b3d8ff;
border-radius: 4px;
display: flex;
align-items: center;
gap: 8px;
i {
color: #409eff;
font-size: 16px;
}
span {
flex: 1;
color: #333;
}
.file-link {
color: #409eff;
text-decoration: none;
font-size: 12px;
&:hover {
text-decoration: underline;
}
}
}
.warning-section {
margin-top: 20px;
.warning-box {
background: #fff9e6;
border: 1px solid #ffe58f;
border-radius: 4px;
padding: 16px;
.warning-title {
color: #d48806;
font-weight: 600;
margin-bottom: 8px;
}
.warning-content {
color: #874d00;
font-size: 12px;
line-height: 1.5;
p {
margin: 4px 0;
}
}
}
}
.dialog-footer {
text-align: right;
.el-button {
margin-left: 10px;
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment