vue2+ts el-dialog+el-table 实现价格
2023-09-04 本文已影响0人
阡陌昏晨
<template>
<div class="organ-config-form">
<el-form ref="form" :model="formData" :rules="formRules">
<el-dialog :visible.sync="dialogVisible"
:title="dialogTitle"
:before-close="closeDialog"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="80%">
<div class="contentBox">
<div class="topBox">
<div><span style="font-weight: bold;">合计金额:</span><span style="color:red;">{{totalPrice.toFixed(2)}}元</span></div>
<div v-if="!isLook"><el-button type="primary" @click="addProject">添加项目</el-button></div>
</div>
<el-table :data="formData.gridData" class="middelTable" style="width:100%;">
<el-table-column prop="xuhao" label="序号" width="50">
<template slot-scope="scope">
<div style="margin-bottom:20px"> {{ scope.$index + 1}}</div>
</template>
</el-table-column>
<el-table-column prop="name" label="项目名称" width="200" >
<template slot="header">
<span><span style="color: red">*</span>项目名称</span>
</template>
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-form-item :prop="'gridData.' + scope.$index + '.name'" :rules="formRules.name">
<el-tooltip class="tooltip-item" effect="dark" content="请输入30位以内字符" placement="top-start">
<el-input v-model="scope.row.name" placeholder="请输入"></el-input>
</el-tooltip>
</el-form-item>
</template>
<template v-else>
{{ scope.row.name }}
</template>
</template>
</el-table-column>
<el-table-column prop="unit" label="计量单位" width="120">
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-tooltip class="tooltip-item" effect="dark" content="请输入10位以内字符" placement="top-start">
<el-input v-model="scope.row.unit" placeholder="请输入" :maxlength="10" style="margin-bottom:20px"></el-input>
</el-tooltip>
</template>
<template v-else>
{{ scope.row.unit }}
</template>
</template>
</el-table-column>
<el-table-column prop="number" label="数量" width="120">
<template slot="header">
<span><span style="color: red">*</span>数量</span>
</template>
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-form-item :prop="'gridData.' + scope.$index + '.number'" :rules="formRules.number" >
<el-tooltip class="tooltip-item" effect="dark" content="请输入4位以内正整数" placement="top-start">
<el-input v-model="scope.row.number" placeholder="请输入" :maxlength="4"></el-input>
</el-tooltip>
</el-form-item>
</template>
<template v-else>
{{ scope.row.number }}
</template>
</template>
</el-table-column>
<el-table-column prop="unitPrice" label="单价" width="120">
<template slot="header">
<span><span style="color: red">*</span>单价</span>
</template>
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-form-item :prop="'gridData.' + scope.$index + '.unitPrice'" :rules="formRules.unitPrice" >
<el-tooltip class="tooltip-item" effect="dark" content="请输入7位以内数字 小数点只支持2位" placement="top-start">
<el-input v-model="scope.row.unitPrice" placeholder="请输入" :maxlength="10"></el-input>
</el-tooltip>
</el-form-item>
</template>
<template v-else>
{{ scope.row.unitPrice }}
</template>
</template>
</el-table-column>
<el-table-column prop="remnant" label="残值" width="120">
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-form-item :prop="'gridData.' + scope.$index + '.remnant'" :rules="formRules.remnant" >
<el-tooltip class="tooltip-item" effect="dark" content="请输入10位以内数字 小数点只支持2位" placement="top-start">
<el-input v-model="scope.row.remnant" placeholder="请输入" :maxlength="10" type="number"></el-input>
</el-tooltip>
</el-form-item>
</template>
<template v-else>
{{ scope.row.remnant }}
</template>
</template>
</el-table-column>
<el-table-column prop="subTotal" label="金额小计" width="120">
<template slot-scope="scope">
<div style="margin-bottom:20px"> {{ (scope.row.unitPrice * scope.row.number).toFixed(2) }}</div>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" >
<template slot-scope="scope">
<template v-if="scope.row.editable">
<el-tooltip class="tooltip-item" effect="dark" content="请输入50位以内的字符" placement="top-start">
<el-input v-model="scope.row.remark" placeholder="请输入" :maxlength="50" style="margin-bottom:20px"></el-input>
</el-tooltip>
</template>
<template v-else>
{{ scope.row.remark }}
</template>
</template>
</el-table-column>
<el-table-column label="操作" width="80" v-if="!isLook">
<template slot-scope="scope">
<el-link
v-if="isModifyPrice"
type="danger"
class="operation-delete"
:underline="false"
@click="deleteData(scope.row)"
style="margin-bottom:20px"
>删除</el-link >
</template>
</el-table-column>
</el-table>
<div class="inputBox">
<div class="txt-tip">报价说明(非必填)</div>
<el-input
type="textarea"
maxlength="200"
:disabled="isLook"
placeholder="请输入"
:autosize="{minRows: 5, maxRows: 10}"
v-model="iptReason">
</el-input>
</div>
</div>
<div
v-if="!isLook"
slot="footer"
class="dialog-footer"
style="margin-top: 10px;">
<!-- 待派单/待报价审核 显示 取消和确认派单-->
<div class="dispatcc-check-btn-box" v-if="isDispatchCheck">
<el-button @click="dialogVisible=false"
size="medium">取消</el-button>
<el-button type="primary"
@click="confirmDispatch"
size="medium"
style="margin-left:10px;"
:loading="loading"
>确认派单</el-button>
</div>
<!-- 维修中状态 取消 提交报价-->
<div v-else-if="isDealing">
<el-button
@click="dialogVisible=false"
size="medium">取消</el-button>
<el-button type="primary"
size="medium"
@click="rePrice"
>提交报价</el-button>
</div>
<!-- 待验收状态 修改报价 确认通过 -->
<div v-else-if="isAuditing">
<el-button
@click="modifyPrice(true)"
size="medium" >修改报价</el-button>
<el-button type="primary"
size="medium"
@click="confirmPass"
>确认通过</el-button>
</div>
<!-- 维修中状态 、应答中 显示 取消 暂存 提交报价-->
<div v-else-if="isYingDa">
<el-button
@click="dialogVisible=false"
size="medium">取消</el-button>
<el-button
@click="tempSave"
size="medium">暂存</el-button>
<el-button type="primary"
size="medium"
@click="submitPrice"
:loading="loading"
>提交报价</el-button>
</div>
</div>
</el-dialog>
</el-form>
</div>
</template>
<style lang="scss" scoped>
/** @format */
</style>
<script lang="ts">
/** @format */
import { Component, Vue, Watch, Prop } from 'vue-property-decorator';
import { NUMBER_4,PRICE_7_with_2decimal } from '@/utils/Reg';
import { queryDamageQuote ,reQuote,takeOrder,dispatchOrder,temporarySave,checkApprove
,queryTaskQuote,checkDispatchOrder,queryQuote } from '@/api/easyrepaire2';
@Component({
name: 'MaterialDamageDialog',
components: {
},
})
export default class extends Vue {
private dialogVisible= false
private dialogTitle:String='物损维修清单'
private loading = false
//总价
private totalPrice=0
//输入框
private iptReason=''
private orderDetail:any
//根据状态显示不同ui
private orderStatus=''
private thirdUserId=''
//是否点击了修改报价
private isModifyPrice=false
//报价方案只能查看
private isLook:any=false;
//
private isLookPriceDetail=false;
//原始表格数据
private originalTableData=[]
//表格数据在form数据对象中 才能让输入框失去焦点触发
private formData:any = {
unit: '',
number: 0,
gridData: [],
};
@Watch('formData.gridData', { deep: true })
private onFormDataChange(newVal: any) {
let total = 0;
for (let item of newVal) {
if (item.unitPrice && item.number) {
total += item.unitPrice * item.number;
//新增一个subTotal字段
item.subTotal=item.unitPrice * item.number;
}
}
this.totalPrice = total;
}
private formRules = {
//项目名称,必填,任意字符,30字符以内,超出后自动换行
name: [ { required: true, message: '请输入30字符以内',max: 30,trigger: 'blur' } ],
//数量,必填,仅数字,10字符以内,超出后自动分行;
number: [ { required: true, message: '请输入正确的值',pattern: NUMBER_4,trigger: 'blur' } ],
//单价,必填,仅数字和小数点,10字符以内,需满足小数校验逻辑,小数后仅支持2位数字;
unitPrice: [ { required: true, message: '请输入正确的值',pattern: PRICE_7_with_2decimal,trigger: 'blur' } ],
//残值,非必填,默认0,删除未填写时则默认0,仅数字和小数点,10字符以内,需满足小数校验逻辑,小数后仅支持2位数字;
};
private closeDialog(done:any) {
done();
}
public init(data:any){
this.dialogVisible= true;
this.orderDetail=data;
this.orderStatus=this.orderDetail.orderStatus;
this.thirdUserId=this.orderDetail.thirdUserId;
this.isLook=data.isLook;
this.isLookPriceDetail=data.isLookPriceDetail;
//如果是维修中 和应答中 进来就要默认为输入框可编辑
// if(this.isDealing||this.isYingDa){
// this.modifyPrice(true);
// }
this.reqList();
}
//待派单/待报价审核状态
private get isDispatchCheck(){
if(this.orderStatus==='1'||this.orderStatus==='2'){
return '应答成功'===this.orderDetail.replyStatus;
}
return false;
}
//待报价审核
private get isOrderStatus2(){
return this.orderStatus==='2';
}
//维修中
private get isDealing(){
return this.orderStatus==='4';
}
//待审核
private get isAuditing(){
return this.orderStatus==='5';
}
//待派单 应答中
private get isYingDa(){
if(this.orderStatus==='1'||this.orderStatus==='2'){
return '应答中'===this.orderDetail.replyStatus;
}
return false;
}
private addProject(){
const emptyItem={
name: '',
unit: '',
number: '',
unitPrice: '',
remnant: '0',
subTotal: '',
editable: true,
remark: '',
};
this.formData.gridData.push(emptyItem);
}
private modifyPrice(isEditable:boolean){
this.isModifyPrice=isEditable;
this.formData.gridData.forEach((item:any) => {
item.editable = isEditable;
});
}
private deleteData(row:any){
// 在这里处理删除数据的逻辑
const index = this.formData.gridData.indexOf(row);
if (index !== -1) {
this.formData.gridData.splice(index, 1);
}
}
private checkInputValidate():boolean{
//金额为0需要提示
if(this.totalPrice<=0){
this.$message.error('物损报价金额不可为0,请修改后重试');
return false;
}
let isValidate=false;
const form: any = this.$refs.form; // 添加类型声明
form.validate((valid: boolean) => {
console.log('form',form,valid);
if (!valid) {
return;
}
isValidate= this.validateNon();
});
return isValidate;
}
// 校验非必填的
private validateNon():boolean {
let isValidate=true;
//残值非必填,默认0,删除未填写时则默认0,仅数字和小数点,10字符以内,需满足小数校验逻辑,小数后仅支持2位数字;
const remnantReg=/^(?=.*[0-9])\d{1,10}(\.\d{1,2})?$/;
this.formData.gridData.forEach((e:any) => {
if(!e.remnant){
e.remnant='0';
return true;
}
if(e.remnant!==''){
if (!remnantReg.test(e.remnant)) {
// 单价格式不符合要求,进行相应的提示或处理
this.$message.error('残值输入不正确');
isValidate=false;
return;
}
}
});
return isValidate;
}
private cancelModify(){
this.modifyPrice(false);
this.formData.gridData = JSON.parse(JSON.stringify(this.originalTableData));
}
private confirmModify(){
if(this.checkInputValidate()){
//保存修改
this.modifyPrice(false);
}
}
private confirmDispatch(){
if(!this.checkInputValidate()){
return ;
}
this.$confirm(
'请确定是否派单该物损机构作业?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
closeOnPressEscape: false,
},
).then(async() => {
if('2'===this.orderStatus){
this.confirmCheckDispatchReq();
}else{
this.confirmDispatchReq();
}
});
}
//派单
private async confirmDispatchReq(){
this.loading=true;
const res=await dispatchOrder(this.getReqDispatchOrderParaObj());
this.loading=false;
if(res.isSuccess()){
this.dialogVisible=false;
this.$emit('refresh');
}
}
//审核派单
private async confirmCheckDispatchReq(){
this.loading=true;
const res = await checkDispatchOrder(
this.getReqCheckDispatchOrderParaObj(),
);
this.loading=false;
if(res.isSuccess()){
this.dialogVisible=false;
this.$emit('refresh');
}
}
//确认通过
private confirmPass(){
if(!this.checkInputValidate()){
return ;
}
this.$confirm(
'验收前请确认该物损项目是否已按要求完成,是否提交验收通过?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
closeOnPressEscape: false,
},
).then(async() => {
this.confirmPassReq();
});
}
private async confirmPassReq(){
this.loading=true;
const res=await checkApprove(this.getReqConfirmPassParaObj());
console.log('checkApprove');
this.loading=false;
if(res.isSuccess()){
this.dialogVisible=false;
this.$emit('refresh');
}
}
//提交报价 接单接口 需校验物损金额,若金额小于0则限制提交,页面toast提示“物损报价金额不可为0,请修改后重试”,应答成功。
private submitPrice(){
if(!this.checkInputValidate()){
return ;
}
this.$confirm(
'请确定是否提交报价方案?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
closeOnClickModal: false,
closeOnPressEscape: false,
},
).then(async() => {
this.submitPriceReq();
});
}
private async submitPriceReq(){
this.loading=true;
const res=await takeOrder(this.getReqTakeOrderParaObj());
this.loading=false;
if(res.isSuccess()){
this.dialogVisible=false;
this.$emit('refresh');
}
}
//维修中 重新报价
private async rePrice(){
if(!this.checkInputValidate()){
return ;
}
const para=this.getReqReQuoteParaObj();
this.loading=true;
const res= await reQuote(para);
this.loading=false;
if(res.isSuccess()){
this.dialogVisible=false;
this.$emit('refresh');
}
}
//暂存
private async tempSave(){
if(!this.checkInputValidate()){
return ;
}
const para=this.getReqTempSaveParaObj();
this.loading=true;
const res= await temporarySave(para);
this.loading=false;
if(res.isSuccess()){
this.$message.success('暂存成功');
}
}
//查询列表数据 维修中查询
private async reqList(){
let res:any;
//报价方案
if(this.isLook){
if(this.isLookPriceDetail){
res=await queryTaskQuote({ taskId: this.orderDetail.id });
}else{
res=await queryQuote({ taskId: this.orderDetail.id ,repairOrgId: this.orderDetail.repairOrgId
,replyId: this.orderDetail.replyId });
}
}else{
if(this.isDealing||this.isOrderStatus2){
res=await queryTaskQuote({ taskId: this.orderDetail.id ,repairOrgId: this.orderDetail.repairOrgId
,replyId: this.orderDetail.replyId });
}else{
res=await queryDamageQuote({ taskId: this.orderDetail.id ,repairOrgId: this.orderDetail.repairOrgId
,replyId: this.orderDetail.replyId });
}
}
if(res.isSuccess()){
let list=res.getData().damageSubPojectList;
this.iptReason=res.getData().remark||'';
if(list){
this.formData.gridData=[];
this.formData.gridData.push(...list);
this.originalTableData= JSON.parse(JSON.stringify(this.formData.gridData));
}
if(this.isLook){
this.modifyPrice(false);
}else{
this.modifyPrice(true);
}
}
}
//重新报价请求参数对象
private getReqParaObj(){
const para={
changeReason: this.iptReason,
id: this.orderDetail.id,
damageSubPojectList: this.formData.gridData,
replyPrice: this.totalPrice,
};
return para;
}
//接单请求参数对象
private getReqTakeOrderParaObj(){
const para={
remark: this.iptReason,
id: this.orderDetail.replyId,
damageSubPojectList: this.formData.gridData,
replyPrice: this.totalPrice,
};
return para;
}
//派单请求参数对象
private getReqDispatchOrderParaObj(){
const para={
changeReason: this.iptReason,
id: this.orderDetail.id,
orderId: this.orderDetail.orderId,
subPojectList: this.formData.gridData,
repairPrice: this.totalPrice,
repairOrgId: this.orderDetail.repairOrgId,
repairOrgName: this.orderDetail.repairOrgName,
};
return para;
}
//审核派单请求参数对象
private getReqCheckDispatchOrderParaObj(){
const para={
approveModifyReason: this.iptReason,
id: this.orderDetail.id,
orderId: this.orderDetail.orderId,
subPojectList: this.formData.gridData,
finalQuote: this.totalPrice,
userId: Number(this.thirdUserId),
};
return para;
}
//重新报价请求参数对象
private getReqReQuoteParaObj(){
const para={
changeReason: this.iptReason,
id: this.orderDetail.id,
reQuotePrice: this.totalPrice,
damageSubPojectList: this.formData.gridData,
};
return para;
}
//暂存请求参数对象
private getReqTempSaveParaObj(){
const para={
remark: this.iptReason,
id: this.orderDetail.replyId,
damageSubPojectList: this.formData.gridData,
replyPrice: this.totalPrice,
};
return para;
}
//确认通过请求参数对象
private getReqConfirmPassParaObj(){
const para={
approveAction: '2',
changeReason: this.iptReason,
id: this.orderDetail.id,
orderId: this.orderDetail.orderId,
subPojectList: this.formData.gridData,
repairPrice: this.totalPrice,
};
return para;
}
}
</script>
<style lang="scss" scoped>
.contentBox{
margin-left: 20px;
margin-right: 20px;
.topBox{
margin-bottom: 30px;
display: flex;
justify-content: space-between;
}
.inputBox{
margin-top: 58px;
}
.txt-tip{
margin-bottom: 10px;
}
}
.dispatcc-check-btn-box{
display: flex;
justify-content: flex-end; // 将子元素靠右对齐
}
</style>