CRM_25-12-09#story#7474,服务商师傅和车辆修改的审批--曹智龙

This commit is contained in:
2025-12-08 09:56:53 +08:00
parent f7f9bb7fd0
commit 5a56d4fe1c
3 changed files with 338 additions and 9 deletions

View File

@@ -18,6 +18,15 @@ export function saveVehicle(data){
data data
}) })
} }
//提交审批车辆信息
export function saveSupplierApproval(data){
return request({
url:'/supplier/approval/saveSupplierDriverVehicleApproval',
method:'POST',
contentType:'application/json',
data
})
}
/*车辆更改状态 /supplierAppV2/dispatchApp/user/enableVehicle*/ /*车辆更改状态 /supplierAppV2/dispatchApp/user/enableVehicle*/
export function enableVehicle(data){ export function enableVehicle(data){
return request({ return request({

View File

@@ -335,10 +335,33 @@
</div> </div>
</div>--> </div>-->
</div> </div>
<two-common-btn class="btn" @cancelClick="h5GoBack" @submitClick="submitBtn" /> <two-common-btn class="btn" @cancelClick="h5GoBack" @submitClick="submitAuditHandle" />
<van-calendar v-model="showDatePicker" :min-date="minDate" <van-calendar v-model="showDatePicker" :min-date="minDate"
:max-date="maxDate" type="range" @confirm="onConfirm" /> :max-date="maxDate" type="range" @confirm="onConfirm" />
</div> </div>
<van-popup ref="success" v-model="approvalDialogShow">
<div class="pop_wrap">
<div class="pop_title">车辆提交审批</div>
<div class="pop_content">
<div class="iptWrap" v-if="vehicleInfoChange">
<div>车辆和服务备注</div>
<el-input placeholder="请输入车辆和服务备注" type="textarea" show-word-limit maxlength="200"
v-model="approvalForm.serviceRemark"></el-input>
</div>
<div class="iptWrap" v-if="insuranceChange">
<div>保单备注</div>
<el-input placeholder="请输入保单备注" type="textarea" show-word-limit maxlength="200"
v-model="approvalForm.insuranceRemark"></el-input>
</div>
</div>
<div class="tip_button_wrap">
<div class="continue close" @click="closeApproval">取消</div>
<div class="continue" :class="{'loading': loading}" @click="submitApprovalHandle">提交审批</div>
</div>
</div>
</van-popup>
</div> </div>
</template> </template>
@@ -347,7 +370,8 @@
import {Dialog} from "vant"; import {Dialog} from "vant";
import {formatDate1} from "@/utils/common" import {formatDate1} from "@/utils/common"
import {myMixins} from "@/utils/myMixins" import {myMixins} from "@/utils/myMixins"
import {vehicleTypeList,saveVehicle,getInfoById,supplierServiceTree, uploadImage, ocrHandler, userOperationPermissions} from "@/api/mine" import {vehicleTypeList,saveVehicle,getInfoById,supplierServiceTree, uploadImage, ocrHandler,
userOperationPermissions,saveSupplierApproval} from "@/api/mine"
import TwoCommonBtn from "@/components/twoBtnCommon.vue" import TwoCommonBtn from "@/components/twoBtnCommon.vue"
import CellGroup from "@/components/cellGroup.vue"; import CellGroup from "@/components/cellGroup.vue";
export default { export default {
@@ -378,6 +402,7 @@ export default {
typeList:[],//车辆类型列表 typeList:[],//车辆类型列表
selectedOption:[],//车辆类型 selectedOption:[],//车辆类型
id:'',//车辆Id id:'',//车辆Id
supplierId:'',//服务商Id
serviceIds:[],//车辆服务种类, serviceIds:[],//车辆服务种类,
supplierServiceList:[], supplierServiceList:[],
oldSupplierServiceList:[], oldSupplierServiceList:[],
@@ -505,7 +530,25 @@ export default {
}, { }, {
name: '其他', name: '其他',
value: 14 value: 14
}] }],
approvalForm:{
type:2,
supplierId:'',
vehicleId:'',
serviceChange:null,
serviceRemark:'',
insuranceChange:null,
insuranceRemark:'',
vehicleOtherChange:null,
vehicleOtherRemark:'',
},
originData:{},//记录更改之前的数据
changedFields: [], // 用于存储变更过的字段
approvalDialogShow:false,
vehicleInfoChange:false,
insuranceChange:false,
loading: false,
} }
}, },
computed: { computed: {
@@ -553,13 +596,25 @@ export default {
this.setDefault(); this.setDefault();
}, },
}, },
async mounted() { async mounted() {
this.id=this.$route.params?.id this.id=this.$route.params?.id
this.approvalForm.supplierId=this.$route.params?.supplierId
await this.getSupplierServiceTree(); await this.getSupplierServiceTree();
await this.getTypeList(); await this.getTypeList();
if( this.id){ if( this.id){
await this.vehicleInfo() await this.vehicleInfo()
}else{
this.originData={
vehicleType:'',
vehicleStatus:'',
virtualVehicle:'',
serviceIds:[],
hasLiabilityInsurance:'',
insuranceCorp:'',
liabilityInsuranceStartTime:'',
liabilityInsuranceEndTime:'',
insurancePicturePhoto:''
}
} }
}, },
methods:{ methods:{
@@ -592,6 +647,10 @@ export default {
const [start, end] = date; const [start, end] = date;
this.showDatePicker = false; this.showDatePicker = false;
this.dateVal = `${this.formatDate(start)} - ${this.formatDate(end)}`; this.dateVal = `${this.formatDate(start)} - ${this.formatDate(end)}`;
console.log('this.dateVal',this.dateVal)
let timeObj = this.formatDateTimeRange(this.dateVal)
console.log('timeObj',timeObj)
}, },
formatDateTimeRange(str) { formatDateTimeRange(str) {
const [startStr, endStr] = str.split(' - ').map(s => s.trim()); const [startStr, endStr] = str.split(' - ').map(s => s.trim());
@@ -805,6 +864,7 @@ export default {
let result=res.data; let result=res.data;
console.log("result",result) console.log("result",result)
this.id=result.vehicleId this.id=result.vehicleId
this.approvalForm.vehicleId=this.id
this.carNum=result.plateNumber this.carNum=result.plateNumber
this.isJoin=result.hasPolymerization.code this.isJoin=result.hasPolymerization.code
this.selectedOption=result.vehicleType?.split(',').map((item)=>{ this.selectedOption=result.vehicleType?.split(',').map((item)=>{
@@ -846,6 +906,17 @@ export default {
if( result.liabilityInsuranceEndTime && result.liabilityInsuranceStartTime ) { if( result.liabilityInsuranceEndTime && result.liabilityInsuranceStartTime ) {
this.dateVal = formatDate1(result.liabilityInsuranceStartTime) + ' - ' + formatDate1(result.liabilityInsuranceEndTime) this.dateVal = formatDate1(result.liabilityInsuranceStartTime) + ' - ' + formatDate1(result.liabilityInsuranceEndTime)
} }
this.originData={
vehicleType:result.vehicleType,
vehicleStatus:result.vehicleStatus,
virtualVehicle:result.virtualVehicle,
serviceIds:result.serviceIds,
hasLiabilityInsurance:result.hasLiabilityInsurance,
insuranceCorp:result.insuranceCorp,
liabilityInsuranceStartTime:result.liabilityInsuranceStartTime,
liabilityInsuranceEndTime:result.liabilityInsuranceEndTime,
insurancePicturePhoto:result.insurancePicturePhoto
}
}, },
isChange(e){ isChange(e){
this.hasLiabilityInsurance=e this.hasLiabilityInsurance=e
@@ -863,6 +934,183 @@ export default {
isVehicleChange(e) { isVehicleChange(e) {
this.vehicleStatus=e this.vehicleStatus=e
}, },
async submitAuditHandle(){//提交审核
let urls=[]
this.insurancePictureFiles?.forEach(item => urls.push(item.url))
let time =this.dateVal ? this.formatDateTimeRange(this.dateVal) : ''
// let time1=time.endTime?.split(' ')
let newFormValue={
vehicleStatus:this.vehicleStatus,
virtualVehicle:this.virtualVehicle,
serviceIds:this.$refs.tree.getCheckedKeys(true) || [],
vehicleType:this.selectedOption?.join(',') || '',
hasLiabilityInsurance:this.hasLiabilityInsurance,
insuranceCorp:this.insuranceCorp,
insurancePicturePhoto:urls?.join(','),
// liabilityInsuranceStartTime:time.startTime ? time.startTime : '',
liabilityInsuranceEndTime:time.endTime ? time.endTime : '',
}
console.log('newFormValue',newFormValue)
let oldFormValue={...this.originData,}
console.log('oldFormValue',oldFormValue)
this.compareObjects(newFormValue,oldFormValue);
if( this.changedFields && this.changedFields.length>0){
const arr1Set = new Set(this.changedFields);
const change1=['vehicleStatus','virtualVehicle','vehicleType','serviceIds']
const change2=['hasLiabilityInsurance','insurancePicturePhoto','insuranceCorp','liabilityInsuranceStartTime','liabilityInsuranceEndTime']
const serviceChangeItems = change1.filter(item => arr1Set.has(item));
console.log('serviceChangeItems',serviceChangeItems)
if(serviceChangeItems?.length>0){
this.vehicleInfoChange=true
this.approvalForm.serviceChange={}
change1.forEach(key => {
this.approvalForm.serviceChange[key] = this[key];
if(key=='serviceIds'){
this.approvalForm.serviceChange[key]=this.$refs.tree.getCheckedKeys(true)
}
});
}else {
this.vehicleInfoChange=false
this.approvalForm.serviceChange=null
}
const insuranceChangeItems = change2.filter(item => arr1Set.has(item));
console.log('insuranceChangeItems',insuranceChangeItems)
if(insuranceChangeItems?.length>0){
this.insuranceChange=true
this.approvalForm.insuranceChange={}
change2.forEach(key => {
this.approvalForm.insuranceChange[key] =this[key];
let time =this.dateVal ? this.formatDateTimeRange(this.dateVal) : ''
if(key=='liabilityInsuranceStartTime' && time && time.startTime){
this.approvalForm.insuranceChange[key]=time.startTime
}
if(key=='liabilityInsuranceEndTime' && time && time.endTime){
// let time1=time.endTime?.split(' ')
this.approvalForm.insuranceChange[key]= time.endTime
}
if(key=='insurancePicturePhoto' && this.insurancePictureFiles?.length>0){
let urls=[]
this.insurancePictureFiles?.forEach(item => urls.push(item.url))
this.approvalForm.insuranceChange[key]=urls?.join(',')
}
});
}else {
this.insuranceChange=false
this.approvalForm.insuranceChange=null
}
}
if(this.vehicleInfoChange || this.insuranceChange){
this.approvalDialogShow=true
console.log('11111',this.approvalForm.serviceChange)
console.log('2222',this.approvalForm.insuranceChange)
}else {
this.approvalDialogShow=false
await this.submitBtn();
}
},
async submitApprovalHandle(){//提交审批-走接口
if(this.vehicleInfoChange){
if(!(this.selectedOption.length > 0)){
this.$toast('车辆类别不能为空')
return
}
let res = this.checkDisabledItems();
if(!res) {
return false
}
if( !this.virtualVehicle ) {
this.$toast('车辆属性不能为空')
return
}
if( !this.vehicleStatus ) {
this.$toast('车辆状态不能为空')
return
}
if(!this.approvalForm.serviceRemark){
this.$toast('车辆和服务备注不能为空')
return
}
}
if(this.insuranceChange){
if(this.hasLiabilityInsurance === null || this.hasLiabilityInsurance === undefined || this.hasLiabilityInsurance === '') { // 有职业责任险,就需要有保单照片
this.$toast('救援职业责任险不能为空')
return
}
if(!this.insurancePicturePhoto && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('保单照片不能为空')
return
}
if(this.selectedOption?.length==1 && this.selectedOption.includes(1)){//选择小修车时需清除原本的拖车服务类型
let data=this.oldSupplierServiceList.filter(item => item.name ==='拖车服务')
this.serviceIds = this.serviceIds.filter(item => !data[0].children.some(obj => obj.id === item));
}
if(!this.insuranceCorp && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('承保保司不能为空')
return
}
if(!this.dateVal && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('保单有效期不能为空')
return
}
if(!this.approvalForm.insuranceRemark){
this.$toast('保单备注不能为空')
return
}
}
try {
this.loading = true;
await saveSupplierApproval({...this.approvalForm})
} finally {
this.loading = false;
}
this.$toast('提交审批成功')
this.closeApproval()
setTimeout(()=>{
this.$router.back();
},2000)
},
compareObjects(newObj, oldObj) {
this.changedFields=[]
for (let key in newObj) {
if( Array.isArray(newObj[key])){
if(newObj[key]?.length != oldObj[key]?.length){
this.changedFields.push(key);
}else {
// console.log('newObj[key]',newObj[key])
if(newObj[key][0]?.id){
let flag=newObj[key].every((item, index) => item.id == oldObj[key][index]?.id);
// console.log('flag',flag)
if(!flag){
this.changedFields.push(key);
}
}else{
let flag=newObj[key].every((value, index) => value == oldObj[key][index]);
if(!flag){
this.changedFields.push(key);
}
}
}
}else{
let isEqual = (
(newObj[key] == null && oldObj[key] == 0) ||
(newObj[key] == 0 && oldObj[key] == null) ||
(newObj[key] == oldObj[key])
);
if (!isEqual) {
this.changedFields.push(key);
}
}
}
},
closeApproval(){
this.approvalForm.serviceRemark=''
this.approvalForm.insuranceRemark=''
this.approvalForm.vehicleOtherRemark=''
this.approvalDialogShow=false
this.vehicleInfoChange=false
this.insuranceChange=false
},
async submitBtn(){ async submitBtn(){
if( !this.vehicleLicenseFront ) { if( !this.vehicleLicenseFront ) {
this.$toast('行驶证主页照片不能为空') this.$toast('行驶证主页照片不能为空')
@@ -1088,4 +1336,69 @@ export default {
pointer-events: none; pointer-events: none;
opacity: 0.6; opacity: 0.6;
} }
.pop_wrap {
width: 340px;
box-sizing: border-box;
padding: 10px 15px;
position: relative;
.pop_title {
font-size: 14px;
font-weight: 500;
}
.pop_content {
width: 304px;
font-size: 14px;
color: #4C5361;
margin-left: 6px;
line-height: 25px;
.iptWrap{
margin: 10px 0;
}
}
.tip_button_wrap {
display: flex;
justify-content: flex-end;
.close {
border: 1px solid #ccc;
color: black;
background-color: #FFFFFF;
}
.continue {
padding: 6px 10px;
border-radius: 4px;
}
div:last-child{
background-color: #3266be;
color: #FFFFFF;
margin-left: 8px;
margin-right: 4px;
}
}
}
.loading {
position: relative;
}
.loading::after{
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border: 2px solid #000;
border-top-color: transparent;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
</style> </style>

View File

@@ -95,6 +95,12 @@
<span class="common_cls" @click.stop="showTip(item.liabilityInsuranceAuditMsg)" :class="getClass(item.rescueInsurance)?.className">{{item.rescueInsurance}}</span> <span class="common_cls" @click.stop="showTip(item.liabilityInsuranceAuditMsg)" :class="getClass(item.rescueInsurance)?.className">{{item.rescueInsurance}}</span>
</span> </span>
</div> </div>
<div class="juhe flex-between">
<span class="zdJuhe">车辆信息</span>
<span class="flex-right" v-if="item.auditStatus">
<span class="common_cls" @click.stop="showTip(item.auditMsg)" :class="getClass(item.auditStatus)?.className">{{item.auditStatus}}</span>
</span>
</div>
<div class="juhe flex-between"> <div class="juhe flex-between">
<span class="zdJuhe">最近登录时间</span> <span class="zdJuhe">最近登录时间</span>
<span class="flex-right">{{item.lastLoginTime}}</span> <span class="flex-right">{{item.lastLoginTime}}</span>
@@ -326,7 +332,8 @@ export default {
this.$router.push({ this.$router.push({
name:'vehicleAdd', name:'vehicleAdd',
params:{ params:{
id:item.vehicleId id:item.vehicleId,
supplierId:item.supplierId
} }
}) })
} }