Compare commits

...

6 Commits

Author SHA1 Message Date
xiaofajia
12916957f6 服务顾问只能编辑除配件外的工单信息,仓库只能编辑配件信息(isFinish=0) 2024-11-16 16:55:28 +08:00
xiaofajia
c2fbaeb2fa 对接上交车接口 2024-11-16 15:54:41 +08:00
xiaofajia
cfa1e585bc 服务顾问通知客户取车前,判断项目价格、配件价格是否已填写 2024-11-16 15:37:33 +08:00
xiaofajia
b49c27c10f 代码补正 2024-11-16 12:58:34 +08:00
xiaofajia
8dc907e992 代码补正 2024-11-16 12:56:05 +08:00
xiaofajia
9a74a8414f 车辆品牌型号拆分为品牌和型号,型号为输入框 2024-11-16 12:05:12 +08:00
10 changed files with 276 additions and 104 deletions

View File

@ -175,3 +175,20 @@ export function removeTicketById(id){
method: 'delete'
})
}
// 验证是否有项目或配件的价格为空或0
export function hasPrice(id){
return request({
url: preUrl + "/hasPrice?id=" + id,
method: 'get'
})
}
// 服务顾问交车
export function overOrder(data){
return request({
url: preUrl + '/overOrder',
method: "post",
data
})
}

View File

@ -1,64 +1,89 @@
<template>
<div class="block">
<el-cascader
placeholder="车辆品牌型号"
:options="options"
v-model="selectedValues"
filterable
/>
</div>
<div class="block">
<el-select v-model="selectedValues" filterable :filter-method="getData" placeholder="车辆品牌">
<el-option v-for="item in options" :key="item.id" :value="item.id" :label="item.brandName"/>
</el-select>
<!-- <el-cascader-->
<!-- placeholder="车辆品牌型号"-->
<!-- :options="options"-->
<!-- v-model="selectedValues"-->
<!-- filterable-->
<!-- />-->
</div>
</template>
<script>
import * as CarBrandSelectorApi from '@/layout/components/CarBrandSelector/Api';
</template>
<script>
import * as CarBrandSelectorApi from '@/layout/components/CarBrandSelector/Api';
import {getCarBrandPage, getCarBrand} from '@/api/base/carbrand'
export default {
name: 'CarBrandSelector',
export default {
name: 'CarBrandSelector',
props: {
//v-model
value: {
type: Array,
default: () => [],
},
props: {
//v-model
value: {
type: [Array, String],
// default: () => [],
},
},
data() {
return {
//
selectedValues:this.value,
options: [], //
};
},
data() {
return {
//
selectedValues: this.value,
options: [], //
};
},
watch: {
value: {
immediate: true,
handler(newVal) {
watch: {
value: {
immediate: true,
handler(newVal) {
if (newVal instanceof Array) {
this.selectedValues = newVal[0]
} else {
this.selectedValues = newVal;
}
},
selectedValues(newVal) {
this.$emit('input', newVal);
this.getData(this.selectedValues)
}
},
selectedValues(newVal) {
this.$emit('input', newVal);
}
},
created() {
this.getData();
},
methods: {
getData(keyword) {
// this.reset()
let param = {
modelName: keyword,
}
CarBrandSelectorApi.searchBrand(param).then(res => {
this.options = res.data
});
},
created() {
this.getData();
},
methods: {
//
getData(keyword) {
const query = {
brandName: keyword
}
getCarBrandPage(query).then(res => {
this.options = res.data.records
})
// idIDoptions
const data = this.options.filter(item => item.id === this.selectedValues)
if (!data || data.length === 0) {
getCarBrand(this.selectedValues).then(res => {
if (res.data) {
this.options.push(res.data)
}
})
}
// // this.reset()
// let param = {
// modelName: keyword,
// }
// CarBrandSelectorApi.searchBrand(param).then(res => {
// // console.log(res.data)
// this.options = res.data
// });
},
},
};
</script>
};
</script>

View File

@ -27,10 +27,15 @@
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="品牌型号" prop="brandAndModel">
<el-form-item label="车辆品牌" prop="brandAndModel">
<CarBrandSelector v-model="formData.brandAndModel" ref="brandForm"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车辆型号" prop="carModel">
<el-input v-model="formData.carModel" placeholder="车辆型号"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车辆类别" prop="carCategory">
<el-select v-model="formData.carCategory" placeholder="请选择车辆类别">
@ -39,6 +44,8 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="车辆性质" prop="carNature">
<el-select v-model="formData.carNature" placeholder="请选择车辆性质">
@ -47,8 +54,6 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="注册日期" prop="carRegisterDate" label-width="auto">
<el-date-picker clearable v-model="formData.carRegisterDate" type="date" value-format="timestamp"
@ -108,7 +113,9 @@
</el-form-item>
</el-col>
<el-col :span="16">
<el-button :loading="buttonLoading" icon="el-icon-date" @click="compute" size="small" type="primary">计算</el-button>
<el-button :loading="buttonLoading" icon="el-icon-date" @click="compute" size="small" type="primary">
计算
</el-button>
</el-col>
</el-row>
</el-collapse-item>
@ -198,8 +205,9 @@ export default {
nextInspectionDate: undefined,
nextMaintenanceDate: undefined,
nextMaintenanceMileage: undefined,
carModel: undefined
},
buttonLoading:false,
buttonLoading: false,
//
formRules: {
engineNumber: [{required: true, message: '发动机号码不能为空', trigger: 'blur'}],
@ -209,16 +217,20 @@ export default {
carNature: [{required: true, message: '车辆性质不能为空', trigger: 'blur'}],
carRegisterDate: [{required: true, message: '车辆注册日期不能为空', trigger: 'blur'}],
brandAndModel: [{required: true, message: '品牌型号不能为空', trigger: 'blur'}],
carModel: [{required: true, message: '车辆型号不能为空', trigger: 'blur'}]
},
};
},
methods: {
/**计算车辆信息*/
async compute(){
async compute() {
this.buttonLoading = true
try{
try {
const brand = this.formData.brandAndModel
if (typeof brand === 'string'){
this.formData.brandAndModel = [brand, this.formData?.carModel]
}
const data = this.formData;
console.log(data,'adadadad')
debugger
const res = await CarMainApi.compute(data);
const result = res.data;
@ -253,6 +265,10 @@ export default {
async submitForm() {
//
// await this.$refs["formRef"].validate();
const brand = this.formData.brandAndModel
if (typeof brand === 'string'){
this.formData.brandAndModel = [brand, this.formData?.carModel]
}
this.formLoading = true;
try {
const data = this.formData;
@ -290,6 +306,7 @@ export default {
carNature: undefined,
carRegisterDate: undefined,
carLicenseImg: undefined,
carModel: undefined
};
this.resetForm("formRef");
}

View File

@ -109,7 +109,7 @@
<el-table-column label="发动机号码" align="center" prop="engineNumber" width="180" />
<el-table-column label="车架号" align="center" prop="vin" width="180" />
<el-table-column label="车辆品牌" align="center" prop="brandStr" />
<el-table-column label="车辆型号" align="center" prop="modelStr" />
<el-table-column label="车辆型号" align="center" prop="carModel" />
<el-table-column label="车辆类别" align="center" prop="carCategory">
<template v-slot="scope">
<dict-tag :type="DICT_TYPE.DICT_CAR_CATEGORY" :value="scope.row.carCategory" />

View File

@ -28,7 +28,11 @@ export default {
watch: {
carSelected(val) {
if (val) {
const car = this.carList.find(item => item.id === val);
let car = this.carList.find(item => item.id === val);
car = {
...car,
modelStr: car?.brandStr + " " + car?.carModel
}
this.$emit('input', car);
}
},

View File

@ -39,7 +39,7 @@
<el-table-column label="车牌号" align="center" prop="carNo" width="180"/>
<el-table-column label="车系" align="center" prop="carBrandName" width="180"/>
<el-table-column label="手机号" align="center" prop="userMobile" width="180"/>
<el-table-column label="操作" fixed="right" align="center" width="200">
<el-table-column label="操作" fixed="right" align="center" width="200" v-if="userRole !== 'repair_warehouse'">
<template slot-scope="scope">
<!-- 都有 -->
<el-button size="mini" type="text" icon="el-icon-view" @click="handleShow(scope.row)"
@ -104,6 +104,16 @@
</el-dropdown>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" align="center" width="200" v-if="userRole === 'repair_warehouse'">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-view" @click="handleShow(scope.row)"
>查看
</el-button>
<el-button v-hasPermi="['repair:tkm:edit']" size="mini" type="text" icon="el-icon-setting" @click="handleEditTicket(scope.row)">
编辑工单
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"

View File

@ -1,6 +1,6 @@
<template>
<div class="app-container">
<el-tabs v-model="activeTab">
<el-tabs v-model="activeTab" v-if="userRole !== 'repair_warehouse'">
<el-tab-pane label="全部工单" name="finish">
<TicketManagerItem :is-type="'all'" :user-role="userRole"/>
</el-tab-pane>
@ -20,6 +20,11 @@
<GetAndBackWares :type="false" />
</el-tab-pane>
</el-tabs>
<el-tabs v-model="activeTab" v-if="userRole === 'repair_warehouse'">
<el-tab-pane label="未结束工单" name="finish">
<TicketManagerItem :is-type="'waiting'" :user-role="userRole"/>
</el-tab-pane>
</el-tabs>
</div>
</template>

View File

@ -162,7 +162,7 @@
</el-descriptions>
</div>
</el-card>
<el-card class="box-card">
<el-card class="box-card" v-if="userRole !== 'repair_warehouse'">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus"/>
@ -178,13 +178,13 @@
<TicketItemShow :is-edit="true" :list="projects" list-type="project" @remove="handleRemove" @success="open"/>
</div>
</el-card>
<el-card class="box-card">
<el-card class="box-card" v-if="!(userRole === 'service_advisor')">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus"/>
<span>配件信息</span>
<div style="float: right; padding: 3px 0">
<el-switch v-if="wares.length > 0"
<el-switch v-if="wares.length > 0 && userRole !== 'repair_warehouse'"
v-model="info.partShow"
active-text="客户可见"
inactive-text="客户不可见"
@ -203,7 +203,7 @@
<TicketItemShow :is-edit="true" :list="wares" list-type="ware" @remove="handleRemove" @success="open"/>
</div>
</el-card>
<el-card class="box-card">
<el-card class="box-card" v-if="userRole !== 'repair_warehouse'">
<!-- 卡片头 -->
<div slot="header" class="clearfix">
<i class="el-icon-plus"/>
@ -290,7 +290,7 @@
</template>
<script>
import {getTicketsById, updateShow, addItems, updateTicket} from "@/api/repair/tickets/Tickets";
import {getTicketsById, updateShow, addItems, updateTicket, getUserRole} from "@/api/repair/tickets/Tickets";
import {removeItemById} from "@/api/repair/tickets/TicketsItem";
import TicketItemShow from "@/views/repair/tickets/Components/TicketItemShow.vue";
import other from "@/views/repair/other/index.vue";
@ -333,6 +333,7 @@ export default {
threePackMoney: 0,
confirmFaultMoney: 0,
},
userRole: null,
}
},
methods: {
@ -348,10 +349,16 @@ export default {
this.wares = data.filter(item => item.ware)
this.others = data.filter(item => item.other)
this.info = res.data
await this.judgeUserRole()
} finally {
this.loadingInstance.close()
}
},
//
async judgeUserRole(){
const res = await getUserRole()
this.userRole = res.data
},
async changeShow(){
try {
await updateShow(this.info.id, this.info.partShow)

View File

@ -69,6 +69,10 @@
<el-dropdown-item command="noticeCus" type="text" icon="el-icon-finished" v-if="userRole === 'service_advisor' && scope.row.ticketsWorkStatus === '03'">
通知客户取车
</el-dropdown-item>
<!-- 服务顾问才有 -->
<el-dropdown-item command="carToCus" type="text" icon="el-icon-circle-check" v-if="userRole === 'service_advisor' && scope.row.ticketsWorkStatus === '03'">
交车
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
@ -140,6 +144,31 @@
</div>
</el-dialog>
<el-dialog title="交车" :visible.sync="carToCusDialog" width="60%" v-dialogDrag append-to-body>
<el-form v-model="carToCusForm" :inline="true" label-width="15rem">
<el-row :gutter="1">
<el-col :span="24">
<el-form-item label="描述" prop="remark">
<el-input style="width: 30rem" type="textarea" v-model="carToCusForm.remark"
:autosize="{ minRows: 4, maxRows: 8}"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="1">
<el-col :span="24">
<el-form-item label="附件" prop="image">
<!-- <FileUpload v-model="formData.image" />-->
<ImageUpload v-model="carToCusForm.image"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="doCarToCus">确定</el-button>
<el-button @click="carToCusDialog = false">取消</el-button>
</div>
</el-dialog>
<UpdateRepair ref="updateRepair" @success="getList" :user-role="userRole"/>
<EditTickets ref="editTickets" @success="getList"/>
<RecordSetting ref="recordSet" />
@ -147,7 +176,7 @@
</template>
<script>
import {getPageByRole, inspection, confirm, noticeCus} from "@/api/repair/tickets/Tickets";
import {getPageByRole, inspection, confirm, noticeCus, hasPrice, overOrder} from "@/api/repair/tickets/Tickets";
import TicketsShow from "@/views/repair/tickets/Components/TicketsShow.vue";
import UpdateRepair from "@/views/repair/tickets/form/UpdateRepair.vue";
import {getUserProfile} from "@/api/system/user";
@ -191,7 +220,13 @@ export default {
},
noticeLoading: false,
noticeDialog: false,
isNoticeChoose: false
isNoticeChoose: false,
carToCusDialog: false,
carToCusForm:{
id: null,
remark: null,
image: null
}
}
},
mounted() {
@ -260,36 +295,51 @@ export default {
this.$refs.updateRepair.open(row)
},
async noticeCus(row){
this.$confirm('请选择使用什么方式通知客户?', '选择', {
confirmButtonText: '短信通知',
cancelButtonText: '拨打电话',
type: 'info'
}).then(async () => {
this.isNoticeChoose = false
this.noticeData = {
time: [],
name: null,
mobile: null,
id: null,
remark: null,
}
this.noticeDialog = true
this.noticeData.id = row.id
try {
this.noticeLoading = true
const res = await getUserProfile()
this.noticeData.name = res.data.nickname
this.noticeData.mobile = res.data.mobile
} finally {
this.noticeLoading = false
}
}).catch(() => {
this.isNoticeChoose = true
this.noticeDialog = true
this.noticeData.name = row.userName
this.noticeData.mobile = row.userMobile
})
// 0
const flag = await hasPrice(row.id)
let choose = true
if (!flag.data){
await this.$confirm('有项目或配件的价格为0是否确认通知客户?', '选择', {
confirmButtonText: '是',
cancelButtonText: '否',
type: 'info'
}).then(() => {
choose = true
}).catch(() => {
choose = false
})
}
if (choose){
this.$confirm('请选择使用什么方式通知客户?', '选择', {
confirmButtonText: '短信通知',
cancelButtonText: '拨打电话',
type: 'info'
}).then(async () => {
this.isNoticeChoose = false
this.noticeData = {
time: [],
name: null,
mobile: null,
id: null,
remark: null,
}
this.noticeDialog = true
this.noticeData.id = row.id
try {
this.noticeLoading = true
const res = await getUserProfile()
this.noticeData.name = res.data.nickname
this.noticeData.mobile = res.data.mobile
} finally {
this.noticeLoading = false
}
}).catch(() => {
this.isNoticeChoose = true
this.noticeDialog = true
this.noticeData.name = row.userName
this.noticeData.mobile = row.userMobile
})
}
},
async doNotice(){
try {
@ -322,6 +372,27 @@ export default {
case 'noticeCus':
this.noticeCus(row)
break
case 'carToCus':
this.carToCus(row)
break
}
},
carToCus(row){
this.carToCusForm = {
id: null,
remark: null,
image: null
}
this.carToCusForm.id = row.id
this.carToCusDialog = true
},
async doCarToCus(){
try {
await overOrder(this.carToCusForm)
this.carToCusDialog = false
this.$modal.msgSuccess("交车成功")
await this.getList()
}catch{
}
}
}

View File

@ -115,10 +115,15 @@
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="品牌型号" prop="carInfo.brandAndModel">
<el-form-item label="车辆品牌" prop="carInfo.brandAndModel">
<CarBrandSelector v-model="formData.carInfo.brandAndModel" ref="brandForm"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车辆型号" prop="carInfo.carModel">
<el-input type="text" v-model="formData.carInfo.carModel" placeholder="请输入车辆型号" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="车辆类别" prop="carInfo.carCategory">
<el-select v-model="formData.carInfo.carCategory" placeholder="请选择车辆类别">
@ -127,6 +132,8 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="车辆性质" prop="carInfo.carNature">
<el-select v-model="formData.carInfo.carNature" placeholder="请选择车辆性质">
@ -135,8 +142,6 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="注册日期" prop="carInfo.carRegisterDate">
<el-date-picker clearable v-model="formData.carInfo.carRegisterDate" type="date" value-format="timestamp"
@ -303,6 +308,7 @@ export default {
nextInspectionDate: undefined,
nextMaintenanceDate: undefined,
nextMaintenanceMileage: undefined,
carModel: undefined
}
},
formRules: {
@ -311,7 +317,8 @@ export default {
'carInfo.licenseNumber': [{required: true, message: "车牌号不能为空", trigger: 'blur'}],
'carInfo.brandAndModel': [{required: true, message: "品牌型号不能为空", trigger: 'blur'}],
'carInfo.carCategory': [{required: true, message: '车辆类别不能为空', trigger: 'blur'}],
'carInfo.carNature': [{required: true, message: '车辆性质不能为空', trigger: 'blur'}]
'carInfo.carNature': [{required: true, message: '车辆性质不能为空', trigger: 'blur'}],
'carInfo.carModel': [{required: true, message: '车辆型号不能为空', trigger: 'blur'}]
},
formLoading: false,
//
@ -342,7 +349,8 @@ export default {
this.formData.carInfo = {
...this.formData.carInfo,
...data.carInfo,
brandAndModel: [data.carInfo?.carBrand, data.carInfo?.carModel]
brandAndModel: data.carInfo?.carBrand,
carModel: data.carInfo?.carModel
}
}
// await this.listLevel()
@ -354,7 +362,10 @@ export default {
this.buttonLoading = true
try{
const data = this.formData.carInfo;
debugger
const brand = data.brandAndModel
if (typeof brand === 'string'){
data.brandAndModel = [brand, data?.carModel]
}
const res = await CarMainApi.compute(data);
const result = res.data;
this.formData.carInfo.insuranceExpiryDate = result.insuranceExpiryDate
@ -368,6 +379,10 @@ export default {
async submitForm(){
await this.$refs["formRef"].validate();
this.formLoading = true
const brand = this.formData.carInfo.brandAndModel
if (typeof brand === 'string'){
this.formData.carInfo.brandAndModel = [brand, this.formData.carInfo?.carModel]
}
try {
await updateCustomerAndCar(this.formData)
this.$modal.msgSuccess(this.formData?.userInfo?.id ? "修改成功" : "新增成功")
@ -429,6 +444,7 @@ export default {
nextInspectionDate: undefined,
nextMaintenanceDate: undefined,
nextMaintenanceMileage: undefined,
carModel: undefined
}
}
this.resetForm("formRef")