Compare commits
3 Commits
prod-26-01
...
fde16ed45c
| Author | SHA1 | Date | |
|---|---|---|---|
| fde16ed45c | |||
| 516841b000 | |||
| 4434ef0a58 |
@@ -1,160 +0,0 @@
|
|||||||
# 年终总结看板 Dashboard
|
|
||||||
|
|
||||||
道路救援服务年终数据可视化看板项目。
|
|
||||||
|
|
||||||
## 项目结构
|
|
||||||
|
|
||||||
```
|
|
||||||
dashboard-demo/
|
|
||||||
├── index.html # 主看板页面(支持URL参数动态加载数据)
|
|
||||||
├── data/
|
|
||||||
│ ├── 供应商年度KPI.xlsx # 服务商KPI数据(主数据源)
|
|
||||||
│ ├── 师傅案件top3.xlsx # 案件量TOP3师傅数据
|
|
||||||
│ ├── 师傅在线top3.xlsx # 在线时长TOP3师傅数据
|
|
||||||
│ ├── 拒单率最高地区.xlsx # 拒单率最高地区数据
|
|
||||||
│ └── 拒单率最高时段.xlsx # 拒单率最高时段数据
|
|
||||||
└── README.md # 项目说明
|
|
||||||
```
|
|
||||||
|
|
||||||
## 功能特性
|
|
||||||
|
|
||||||
- 深色主题数据可视化看板
|
|
||||||
- **直接读取Excel文件**,无需转换为JSON
|
|
||||||
- 支持通过URL参数 `?providerId=XXX` 切换不同服务商
|
|
||||||
- 右上角下拉框可实时切换服务商(自动从Excel读取服务商列表)
|
|
||||||
- 使用 Chart.js 实现饼状图和雷达图
|
|
||||||
- 使用 SheetJS (xlsx) 解析Excel文件
|
|
||||||
- 响应式布局,支持不同屏幕尺寸
|
|
||||||
- 数据与页面分离,便于维护
|
|
||||||
|
|
||||||
## 数据指标
|
|
||||||
|
|
||||||
看板展示以下数据指标:
|
|
||||||
|
|
||||||
1. **总案件量分布**(饼状图)
|
|
||||||
- 小修、困境、拖车三类案件占比
|
|
||||||
|
|
||||||
2. **年度聚合案件量**
|
|
||||||
|
|
||||||
3. **案件量TOP3师傅**
|
|
||||||
|
|
||||||
4. **车辆平均总在线时长**
|
|
||||||
|
|
||||||
5. **在线时长TOP3师傅**
|
|
||||||
|
|
||||||
6. **拒单率最高地区**
|
|
||||||
|
|
||||||
7. **拒单率最高时段**
|
|
||||||
|
|
||||||
8. **APP使用率**
|
|
||||||
- 年度APP使用率展示
|
|
||||||
|
|
||||||
## Excel数据结构
|
|
||||||
|
|
||||||
### 1. 供应商年度KPI.xlsx
|
|
||||||
|
|
||||||
| 列名 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 服务商id | 服务商唯一标识 |
|
|
||||||
| 服务商 | 服务商名称 |
|
|
||||||
| 完成案件量 | 总案件数量 |
|
|
||||||
| 拖车完成量 | 拖车案件数 |
|
|
||||||
| 小修完成量 | 小修案件数 |
|
|
||||||
| 困境完成量 | 困境案件数 |
|
|
||||||
| 聚合案件量 | 聚合案件数量 |
|
|
||||||
| APP使用率. | APP使用率(小数形式,如0.998) |
|
|
||||||
| 年度车辆平均总在线时长(小时) | 车辆平均在线时长 |
|
|
||||||
|
|
||||||
### 2. 师傅案件top3.xlsx
|
|
||||||
|
|
||||||
| 列名 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 服务商id | 服务商唯一标识 |
|
|
||||||
| 服务商 | 服务商名称 |
|
|
||||||
| 服务人员工号 | 师傅姓名/工号 |
|
|
||||||
| 完成案件量 | 该师傅完成的案件数 |
|
|
||||||
|
|
||||||
### 3. 师傅在线top3.xlsx
|
|
||||||
|
|
||||||
| 列名 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 服务商名称 | 服务商名称 |
|
|
||||||
| 司机姓名 | 师傅姓名 |
|
|
||||||
| 年度总在线时长(小时) | 在线时长 |
|
|
||||||
|
|
||||||
### 4. 拒单率最高地区.xlsx
|
|
||||||
|
|
||||||
| 列名 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 供应商名称 | 服务商名称 |
|
|
||||||
| 地区 | 拒单率最高的地区 |
|
|
||||||
| 拒单率 | 拒单率(小数形式) |
|
|
||||||
|
|
||||||
### 5. 拒单率最高时段.xlsx
|
|
||||||
|
|
||||||
| 列名 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| 供应商名称 | 服务商名称 |
|
|
||||||
| 时段 | 拒单率最高的时段 |
|
|
||||||
| 拒单率 | 拒单率(小数形式) |
|
|
||||||
|
|
||||||
## 使用方式
|
|
||||||
|
|
||||||
### 1. 启动本地服务器
|
|
||||||
|
|
||||||
由于页面使用 `fetch` 加载JSON数据,需要通过HTTP服务器访问:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd C:\Users\Administrator\dashboard-demo
|
|
||||||
|
|
||||||
# 使用 Python
|
|
||||||
python -m http.server 8080
|
|
||||||
|
|
||||||
# 或使用 Node.js
|
|
||||||
npx serve .
|
|
||||||
|
|
||||||
# 或使用 PHP
|
|
||||||
php -S localhost:8080
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 访问页面
|
|
||||||
|
|
||||||
- 默认服务商:`http://localhost:8080`(自动加载第一个服务商)
|
|
||||||
- 指定服务商:`http://localhost:8080?providerId=1128`(使用服务商id)
|
|
||||||
- 切换服务商:使用页面右上角的下拉框
|
|
||||||
|
|
||||||
### 3. 更新数据
|
|
||||||
|
|
||||||
直接替换 `data/` 目录下的Excel文件即可,页面会自动读取最新数据。
|
|
||||||
服务商列表从Excel自动生成,无需手动配置。
|
|
||||||
|
|
||||||
## 技术栈
|
|
||||||
|
|
||||||
- HTML5 / CSS3
|
|
||||||
- JavaScript (ES6+)
|
|
||||||
- Chart.js - 图表库(饼图、雷达图)
|
|
||||||
- SheetJS (xlsx) - Excel文件解析
|
|
||||||
- CSS Grid / Flexbox - 布局
|
|
||||||
|
|
||||||
## 后续优化方向
|
|
||||||
|
|
||||||
- [ ] 添加更多图表类型(柱状图、折线图等)
|
|
||||||
- [ ] 支持时间范围筛选
|
|
||||||
- [ ] 添加数据导出功能
|
|
||||||
- [ ] 移动端适配优化
|
|
||||||
- [ ] 添加数据加载骨架屏
|
|
||||||
- [ ] 支持主题切换(深色/浅色)
|
|
||||||
|
|
||||||
## 更新日志
|
|
||||||
|
|
||||||
### 2025-01-21
|
|
||||||
- 改为直接读取Excel文件,无需JSON转换
|
|
||||||
- 服务商列表从Excel自动生成
|
|
||||||
- 将"AB段里程对比"改为"APP使用率"展示
|
|
||||||
- 新增服务商选择下拉框
|
|
||||||
|
|
||||||
### 2025-01-20
|
|
||||||
- 初始版本
|
|
||||||
- 实现基础看板布局
|
|
||||||
- 支持URL参数切换服务商
|
|
||||||
- 数据JSON化,与页面分离
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"serviceProviderId": "SP001",
|
|
||||||
"serviceProviderName": "上海道路救援服务中心",
|
|
||||||
"year": 2025,
|
|
||||||
"summary": {
|
|
||||||
"totalCases": 100,
|
|
||||||
"caseBreakdown": {
|
|
||||||
"minorRepair": 20,
|
|
||||||
"predicament": 20,
|
|
||||||
"towing": 60
|
|
||||||
},
|
|
||||||
"aggregatedCases": 15
|
|
||||||
},
|
|
||||||
"topMastersByCases": [
|
|
||||||
{ "rank": 1, "name": "小王", "cases": 18 },
|
|
||||||
{ "rank": 2, "name": "小张", "cases": 16 },
|
|
||||||
{ "rank": 3, "name": "小李", "cases": 12 }
|
|
||||||
],
|
|
||||||
"onlineHours": {
|
|
||||||
"averageTotal": 2920,
|
|
||||||
"topMasters": [
|
|
||||||
{ "rank": 1, "name": "小王", "hours": 3230 },
|
|
||||||
{ "rank": 2, "name": "小张", "hours": 3028 },
|
|
||||||
{ "rank": 3, "name": "小李", "hours": 2996 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rejectionRate": {
|
|
||||||
"highestRegion": {
|
|
||||||
"name": "崇明",
|
|
||||||
"rate": 21.2
|
|
||||||
},
|
|
||||||
"highestTimeSlot": {
|
|
||||||
"period": "18:00-22:00",
|
|
||||||
"description": "晚高峰时段"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"abMileage": {
|
|
||||||
"highest": {
|
|
||||||
"region": "崇明",
|
|
||||||
"distance": 62
|
|
||||||
},
|
|
||||||
"lowest": {
|
|
||||||
"region": "黄浦",
|
|
||||||
"distance": 6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
{
|
|
||||||
"serviceProviderId": "SP002",
|
|
||||||
"serviceProviderName": "浦东汽车救援有限公司",
|
|
||||||
"year": 2025,
|
|
||||||
"summary": {
|
|
||||||
"totalCases": 156,
|
|
||||||
"caseBreakdown": {
|
|
||||||
"minorRepair": 35,
|
|
||||||
"predicament": 41,
|
|
||||||
"towing": 80
|
|
||||||
},
|
|
||||||
"aggregatedCases": 22
|
|
||||||
},
|
|
||||||
"topMastersByCases": [
|
|
||||||
{ "rank": 1, "name": "老陈", "cases": 28 },
|
|
||||||
{ "rank": 2, "name": "大刘", "cases": 24 },
|
|
||||||
{ "rank": 3, "name": "阿强", "cases": 19 }
|
|
||||||
],
|
|
||||||
"onlineHours": {
|
|
||||||
"averageTotal": 3150,
|
|
||||||
"topMasters": [
|
|
||||||
{ "rank": 1, "name": "老陈", "hours": 3580 },
|
|
||||||
{ "rank": 2, "name": "大刘", "hours": 3420 },
|
|
||||||
{ "rank": 3, "name": "阿强", "hours": 3210 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rejectionRate": {
|
|
||||||
"highestRegion": {
|
|
||||||
"name": "奉贤",
|
|
||||||
"rate": 18.5
|
|
||||||
},
|
|
||||||
"highestTimeSlot": {
|
|
||||||
"period": "07:00-09:00",
|
|
||||||
"description": "早高峰时段"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"abMileage": {
|
|
||||||
"highest": {
|
|
||||||
"region": "金山",
|
|
||||||
"distance": 55
|
|
||||||
},
|
|
||||||
"lowest": {
|
|
||||||
"region": "静安",
|
|
||||||
"distance": 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -77,15 +77,6 @@ export function updateOrderSettlement(data){
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 获取司机信息
|
|
||||||
export function getDriverInfo(data){
|
|
||||||
return request({
|
|
||||||
url:'/supplierAppV2/dispatchApp/order/getDriverInfo',
|
|
||||||
method:'POST',
|
|
||||||
contentType:'application/json',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 电瓶数量列表
|
// 电瓶数量列表
|
||||||
export function batteryCountList(){
|
export function batteryCountList(){
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
:border="false"
|
:border="false"
|
||||||
:fixed="true"
|
:fixed="true"
|
||||||
:safe-area-inset-top="true"
|
:safe-area-inset-top="true"
|
||||||
@click-left="back"
|
@click-left="h5GoBack"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="addContentWrap">
|
<div class="addContentWrap">
|
||||||
@@ -92,57 +92,6 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
|
|
||||||
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')" style="align-items: center">
|
|
||||||
<div class="titleType" style="width: 60px">
|
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
|
||||||
<span>保费</span>
|
|
||||||
</div>
|
|
||||||
<van-field
|
|
||||||
type="number"
|
|
||||||
class="vanIpt"
|
|
||||||
v-model="liabilityInsuranceAmount"
|
|
||||||
input-align="right"
|
|
||||||
>
|
|
||||||
<template slot="right-icon" >
|
|
||||||
<span style="white-space: nowrap;">元</span>
|
|
||||||
</template>
|
|
||||||
</van-field>
|
|
||||||
</div>
|
|
||||||
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
|
|
||||||
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')">
|
|
||||||
<div class="titleType">
|
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
|
||||||
<span>保额</span>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;align-items: center;justify-content: flex-end">
|
|
||||||
<el-select
|
|
||||||
v-model="liabilityInsuranceQuota"
|
|
||||||
value-key="name"
|
|
||||||
class="elSelect"
|
|
||||||
collapse-tags="collapse-tags"
|
|
||||||
placeholder="请选择" style="width: 55%"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in liabilityQuotaOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.value"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
</el-option>
|
|
||||||
</el-select><span style="margin-right: 16px;opacity: .5;">万元</span>
|
|
||||||
</div>
|
|
||||||
<!-- <van-field
|
|
||||||
type="number"
|
|
||||||
class="vanIpt"
|
|
||||||
v-model="liabilityInsuranceQuota"
|
|
||||||
input-align="right"
|
|
||||||
>
|
|
||||||
<template slot="right-icon" >
|
|
||||||
<span style="white-space: nowrap;">万元 </span>
|
|
||||||
</template>
|
|
||||||
</van-field>-->
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<common-btn title="保存" @submitClick="submitBtn"/>
|
<common-btn title="保存" @submitClick="submitBtn"/>
|
||||||
<van-calendar v-model="showDatePicker" :min-date="minDate"
|
<van-calendar v-model="showDatePicker" :min-date="minDate"
|
||||||
@@ -155,7 +104,7 @@
|
|||||||
import {Dialog} from "vant";
|
import {Dialog} from "vant";
|
||||||
import {myMixins} from "@/utils/myMixins"
|
import {myMixins} from "@/utils/myMixins"
|
||||||
import {formatDate1} from "@/utils/common"
|
import {formatDate1} from "@/utils/common"
|
||||||
import { uploadImage, updateInsurance, getInfoById,userOperationPermissions} from "@/api/mine"
|
import { uploadImage, updateInsurance, getInfoById} from "@/api/mine"
|
||||||
import CommonBtn from "@/components/commonBtn.vue"
|
import CommonBtn from "@/components/commonBtn.vue"
|
||||||
export default {
|
export default {
|
||||||
name: "vehicleAdd",
|
name: "vehicleAdd",
|
||||||
@@ -166,7 +115,6 @@ export default {
|
|||||||
children: 'children',
|
children: 'children',
|
||||||
label: 'name'
|
label: 'name'
|
||||||
},
|
},
|
||||||
liabilityQuotaOptions:[{value:10},{value:20},{value:30},{value:50},{value:70},{value:80},{value:100},{value:200}],
|
|
||||||
minDate: new Date(1970, 0, 1), // 设置最小可选日期(1970年1月1日)
|
minDate: new Date(1970, 0, 1), // 设置最小可选日期(1970年1月1日)
|
||||||
maxDate: new Date(2099, 11, 31), // 设置最大可选日期(2099年12月31日)
|
maxDate: new Date(2099, 11, 31), // 设置最大可选日期(2099年12月31日)
|
||||||
showDatePicker: false,
|
showDatePicker: false,
|
||||||
@@ -182,9 +130,6 @@ export default {
|
|||||||
insurancePicturePhoto: '', // 保单照片
|
insurancePicturePhoto: '', // 保单照片
|
||||||
isMultiple: false, // 是否支持多选
|
isMultiple: false, // 是否支持多选
|
||||||
insuranceCorp: '',
|
insuranceCorp: '',
|
||||||
liabilityInsuranceAmount:'',
|
|
||||||
liabilityInsuranceQuota:'',
|
|
||||||
permissonList:[],
|
|
||||||
insuranceOptions: [{
|
insuranceOptions: [{
|
||||||
name: '太平洋',
|
name: '太平洋',
|
||||||
value: 1
|
value: 1
|
||||||
@@ -238,24 +183,11 @@ export default {
|
|||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.id=this.$route.params?.id
|
this.id=this.$route.params?.id
|
||||||
await this.getPermissions()
|
|
||||||
if( this.id){
|
if( this.id){
|
||||||
// await this.vehicleInfo()
|
// await this.vehicleInfo()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
back() {
|
|
||||||
this.$router.push({
|
|
||||||
name:'vehicleAdd',
|
|
||||||
params:{
|
|
||||||
id: this.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async getPermissions(){
|
|
||||||
let res = await userOperationPermissions();
|
|
||||||
this.permissonList = res.data
|
|
||||||
},
|
|
||||||
async vehicleInfo(){
|
async vehicleInfo(){
|
||||||
let res= await getInfoById({
|
let res= await getInfoById({
|
||||||
vehicleId:this.id
|
vehicleId:this.id
|
||||||
@@ -327,14 +259,6 @@ export default {
|
|||||||
this.$toast('保单有效期不能为空')
|
this.$toast('保单有效期不能为空')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(this.hasLiabilityInsurance == 1 && this.permissonList?.includes('hasInsuranceAudit') && !this.liabilityInsuranceAmount && this.liabilityInsuranceAmount!=0){
|
|
||||||
this.$toast('保费不能为空')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(this.hasLiabilityInsurance == 1 && !this.liabilityInsuranceQuota && this.permissonList?.includes('hasInsuranceAudit')){
|
|
||||||
this.$toast('保额不能为空')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let timeObj;
|
let timeObj;
|
||||||
if(this.dateVal) {
|
if(this.dateVal) {
|
||||||
timeObj = this.formatDateTimeRange(this.dateVal)
|
timeObj = this.formatDateTimeRange(this.dateVal)
|
||||||
@@ -347,8 +271,6 @@ export default {
|
|||||||
insuranceCorp: this.hasLiabilityInsurance == 1 ? this.insuranceCorp : '',
|
insuranceCorp: this.hasLiabilityInsurance == 1 ? this.insuranceCorp : '',
|
||||||
liabilityInsuranceStartTime: this.hasLiabilityInsurance == 1 ? (timeObj?.startTime || '' ) : '',
|
liabilityInsuranceStartTime: this.hasLiabilityInsurance == 1 ? (timeObj?.startTime || '' ) : '',
|
||||||
liabilityInsuranceEndTime: this.hasLiabilityInsurance == 1 ? (timeObj?.endTime || '') : '',
|
liabilityInsuranceEndTime: this.hasLiabilityInsurance == 1 ? (timeObj?.endTime || '') : '',
|
||||||
liabilityInsuranceQuota:this.liabilityInsuranceQuota || '',
|
|
||||||
liabilityInsuranceAmount:this.liabilityInsuranceAmount || '',
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
await updateInsurance(params)
|
await updateInsurance(params)
|
||||||
@@ -358,8 +280,7 @@ export default {
|
|||||||
this.$toast('添加成功')
|
this.$toast('添加成功')
|
||||||
}
|
}
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
// this.$router.back();
|
this.$router.back();
|
||||||
this.back()
|
|
||||||
},2000)
|
},2000)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -264,10 +264,6 @@
|
|||||||
this.$toast('营业执照未上传')
|
this.$toast('营业执照未上传')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if( !this.licensePhoto ) {
|
|
||||||
this.$toast('开户许可证未上传')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if( !(this.form.serviceAreaCode.length > 0) ) {
|
if( !(this.form.serviceAreaCode.length > 0) ) {
|
||||||
this.$toast('服务区域不能为空')
|
this.$toast('服务区域不能为空')
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
:border="false"
|
:border="false"
|
||||||
:fixed="true"
|
:fixed="true"
|
||||||
:safe-area-inset-top="true"
|
:safe-area-inset-top="true"
|
||||||
@click-left="back"
|
@click-left="h5GoBack"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="addContentWrap">
|
<div class="addContentWrap">
|
||||||
@@ -311,83 +311,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
|
|
||||||
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')">
|
|
||||||
<div class="titleType">
|
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
|
||||||
<span>保费</span>
|
|
||||||
</div>
|
|
||||||
<van-field
|
|
||||||
type="number"
|
|
||||||
class="vanIpt"
|
|
||||||
v-model="liabilityInsuranceAmount"
|
|
||||||
input-align="right"
|
|
||||||
>
|
|
||||||
<template slot="right-icon" >
|
|
||||||
<span style="white-space: nowrap;">元</span>
|
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
|
||||||
</div>
|
|
||||||
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
|
|
||||||
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')">
|
|
||||||
<div class="titleType">
|
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
|
||||||
<span>保额</span>
|
|
||||||
</div>
|
|
||||||
<div style="display:flex;align-items: center;justify-content: flex-end">
|
|
||||||
<el-select
|
|
||||||
v-model="liabilityInsuranceQuota"
|
|
||||||
value-key="name"
|
|
||||||
class="elSelect"
|
|
||||||
collapse-tags="collapse-tags"
|
|
||||||
placeholder="请选择" style="width: 55%"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in liabilityQuotaOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.value"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
</el-option>
|
|
||||||
</el-select><span style="margin-right: 16px;opacity: .5;">万元</span>
|
|
||||||
</div>
|
|
||||||
<!-- <van-field
|
|
||||||
type="number"
|
|
||||||
class="vanIpt"
|
|
||||||
v-model="liabilityInsuranceQuota"
|
|
||||||
input-align="right"
|
|
||||||
>
|
|
||||||
<template slot="right-icon" >
|
|
||||||
<span style="white-space: nowrap;">万元 </span>
|
|
||||||
</template>
|
|
||||||
</van-field>-->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div class="lineBot"></div>
|
|
||||||
<div class="itemContent">
|
|
||||||
<div class="titleType">
|
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
|
||||||
<span>保单号(救援)</span>
|
|
||||||
</div>
|
|
||||||
<van-field
|
|
||||||
class="vanIpt"
|
|
||||||
style="width: 72%"
|
|
||||||
v-model="insuranceCode"
|
|
||||||
input-align="right"
|
|
||||||
> </van-field>
|
|
||||||
</div>
|
|
||||||
<div class="lineBot"></div>
|
|
||||||
<div class="itemContent">
|
|
||||||
<div class="titleType"> <span>保单号(中道物流)</span> </div>
|
|
||||||
<van-field
|
|
||||||
class="vanIpt"
|
|
||||||
style="width: 65%"
|
|
||||||
v-model="insuranceCodeZd"
|
|
||||||
input-align="right"
|
|
||||||
> </van-field>
|
|
||||||
</div>
|
|
||||||
<div class="lineBot"></div>-->
|
|
||||||
</template>
|
|
||||||
<div class="itemContent">
|
<div class="itemContent">
|
||||||
<div class="titleType">
|
<div class="titleType">
|
||||||
<img class="startImg" src="@/assets/start.png" />
|
<img class="startImg" src="@/assets/start.png" />
|
||||||
@@ -418,7 +344,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
<two-common-btn class="btn" @cancelClick="back" @submitClick="submitBtn" />
|
<two-common-btn class="btn" @cancelClick="h5GoBack" @submitClick="submitBtn" />
|
||||||
<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" />
|
||||||
|
|
||||||
@@ -614,7 +540,6 @@ export default {
|
|||||||
name: '其他',
|
name: '其他',
|
||||||
value: 14
|
value: 14
|
||||||
}],
|
}],
|
||||||
liabilityQuotaOptions:[{value:10},{value:20},{value:30},{value:50},{value:70},{value:80},{value:100},{value:200}],
|
|
||||||
approvalForm:{
|
approvalForm:{
|
||||||
type:2,
|
type:2,
|
||||||
supplierId:'',
|
supplierId:'',
|
||||||
@@ -632,10 +557,7 @@ export default {
|
|||||||
vehicleInfoChange:false,
|
vehicleInfoChange:false,
|
||||||
insuranceChange:false,
|
insuranceChange:false,
|
||||||
loading: false,
|
loading: false,
|
||||||
liabilityInsuranceAmount:'',
|
|
||||||
liabilityInsuranceQuota:'',
|
|
||||||
insuranceCode:'',
|
|
||||||
insuranceCodeZd:'',
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -1030,7 +952,7 @@ export default {
|
|||||||
isVehicleChange(e) {
|
isVehicleChange(e) {
|
||||||
this.vehicleStatus=e
|
this.vehicleStatus=e
|
||||||
},
|
},
|
||||||
/* async submitAuditHandle(){//提交审核
|
async submitAuditHandle(){//提交审核
|
||||||
let urls=[]
|
let urls=[]
|
||||||
this.insurancePictureFiles?.forEach(item => urls.push(item.url))
|
this.insurancePictureFiles?.forEach(item => urls.push(item.url))
|
||||||
let time =this.dateVal ? this.formatDateTimeRange(this.dateVal) : ''
|
let time =this.dateVal ? this.formatDateTimeRange(this.dateVal) : ''
|
||||||
@@ -1108,7 +1030,7 @@ export default {
|
|||||||
this.approvalDialogShow=false
|
this.approvalDialogShow=false
|
||||||
await this.submitBtn();
|
await this.submitBtn();
|
||||||
}
|
}
|
||||||
},*/
|
},
|
||||||
async submitApprovalHandle(){//提交审批-走接口
|
async submitApprovalHandle(){//提交审批-走接口
|
||||||
if(this.vehicleInfoChange){
|
if(this.vehicleInfoChange){
|
||||||
if(!(this.selectedOption.length > 0)){
|
if(!(this.selectedOption.length > 0)){
|
||||||
@@ -1211,14 +1133,6 @@ export default {
|
|||||||
this.vehicleInfoChange=false
|
this.vehicleInfoChange=false
|
||||||
this.insuranceChange=false
|
this.insuranceChange=false
|
||||||
},
|
},
|
||||||
back() {
|
|
||||||
this.$router.push({
|
|
||||||
name:'vehicleManage',
|
|
||||||
params:{
|
|
||||||
id: this.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async submitBtn(){
|
async submitBtn(){
|
||||||
if( !this.vehicleLicenseFront ) {
|
if( !this.vehicleLicenseFront ) {
|
||||||
this.$toast('行驶证主页照片不能为空')
|
this.$toast('行驶证主页照片不能为空')
|
||||||
@@ -1280,26 +1194,12 @@ export default {
|
|||||||
this.$toast('保单有效期不能为空')
|
this.$toast('保单有效期不能为空')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if( this.hasLiabilityInsurance == 1){
|
|
||||||
if(this.permissonList.includes('hasInsuranceAudit') && !this.liabilityInsuranceAmount && this.liabilityInsuranceAmount!=0){
|
|
||||||
this.$toast('保费不能为空')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(this.permissonList.includes('hasInsuranceAudit') && !this.liabilityInsuranceQuota){
|
|
||||||
this.$toast('保额不能为空')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
/* if(!this.insuranceCode){
|
|
||||||
this.$toast('保单号(救援)不能为空')
|
|
||||||
return
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
let timeObj;
|
let timeObj;
|
||||||
if(this.dateVal) {
|
if(this.dateVal) {
|
||||||
timeObj = this.formatDateTimeRange(this.dateVal)
|
timeObj = this.formatDateTimeRange(this.dateVal)
|
||||||
}
|
}
|
||||||
this.serviceIds = this.$refs.tree.getCheckedKeys(true)
|
this.serviceIds = this.$refs.tree.getCheckedKeys(true)
|
||||||
// console.log('1122',this.vehicleStatus)
|
console.log('1122',this.vehicleStatus)
|
||||||
// return
|
// return
|
||||||
await saveVehicle({
|
await saveVehicle({
|
||||||
vehicleId:this.id ? this.id : '',
|
vehicleId:this.id ? this.id : '',
|
||||||
@@ -1321,11 +1221,7 @@ export default {
|
|||||||
liabilityInsuranceEndTime: this.hasLiabilityInsurance == 1 ? (timeObj?.endTime || '') : '',
|
liabilityInsuranceEndTime: this.hasLiabilityInsurance == 1 ? (timeObj?.endTime || '') : '',
|
||||||
virtualVehicle: this.virtualVehicle,
|
virtualVehicle: this.virtualVehicle,
|
||||||
canSubmitApproval:true,
|
canSubmitApproval:true,
|
||||||
vehicleStatus:this.vehicleStatus,
|
vehicleStatus:this.vehicleStatus
|
||||||
liabilityInsuranceAmount:this.liabilityInsuranceAmount,
|
|
||||||
liabilityInsuranceQuota:this.liabilityInsuranceQuota,
|
|
||||||
insuranceCode:this.insuranceCode,
|
|
||||||
insuranceCodeZd:this.insuranceCodeZd,
|
|
||||||
})
|
})
|
||||||
if(this.id){
|
if(this.id){
|
||||||
this.$toast('修改成功')
|
this.$toast('修改成功')
|
||||||
@@ -1531,12 +1427,4 @@ export default {
|
|||||||
transform: translate(-50%, -50%) rotate(360deg);
|
transform: translate(-50%, -50%) rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.vanIpt{
|
|
||||||
width: 80%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.vanIpt1{
|
|
||||||
width: 72%;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -74,7 +74,6 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<span class="leftTitle fontColor">服务师傅:</span><span class="rightContent">{{ orderDetailInfo.driverName }} {{orderDetailInfo.drivePhone ? '/' : ''}} {{orderDetailInfo.drivePhone }}
|
<span class="leftTitle fontColor">服务师傅:</span><span class="rightContent">{{ orderDetailInfo.driverName }} {{orderDetailInfo.drivePhone ? '/' : ''}} {{orderDetailInfo.drivePhone }}
|
||||||
<span v-if="queryType == 5" class="driverPoiBtn" @click="noMultipleClicks(showMap)">查看司机位置</span>
|
<span v-if="queryType == 5" class="driverPoiBtn" @click="noMultipleClicks(showMap)">查看司机位置</span>
|
||||||
<span v-if="orderDetailInfo.driverName && orderDetailInfo.proprietary?.code==1" class="driverPoiBtn" @click="noMultipleClicks(createDriverInfo)">生成司机信息</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="item" v-if="queryType == 9 || queryType ==11 || queryType ==12">
|
<div class="item" v-if="queryType == 9 || queryType ==11 || queryType ==12">
|
||||||
@@ -115,7 +114,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import {myMixins} from '@/utils/myMixins'
|
import {myMixins} from '@/utils/myMixins'
|
||||||
import {getOrderDetail,showVehiclePositionInfo, getConfigByCode,getDriverInfo} from "@/api/order"
|
import {getOrderDetail,showVehiclePositionInfo, getConfigByCode} from "@/api/order"
|
||||||
import minePosition from '@/assets/minePosition.png';
|
import minePosition from '@/assets/minePosition.png';
|
||||||
import vehiclePosition from '@/assets/vehiclePosition.png';
|
import vehiclePosition from '@/assets/vehiclePosition.png';
|
||||||
import desitationPosition from '@/assets/desitationPosition.png'
|
import desitationPosition from '@/assets/desitationPosition.png'
|
||||||
@@ -162,30 +161,6 @@ export default {
|
|||||||
});
|
});
|
||||||
this.carTypeList = res?.data?.userVehicleType
|
this.carTypeList = res?.data?.userVehicleType
|
||||||
},
|
},
|
||||||
async getDriverInfo(){
|
|
||||||
let result=await getDriverInfo({
|
|
||||||
driverId:this.orderDetailInfo.driverId
|
|
||||||
})
|
|
||||||
if(result.data){
|
|
||||||
// console.log('--result--',result.data)
|
|
||||||
let params={
|
|
||||||
'姓名:':this.orderDetailInfo.driverName,
|
|
||||||
'身份证:':result.data.identityCardNumber,
|
|
||||||
'车牌:':this.orderDetailInfo.plateNumber,
|
|
||||||
'手机:':this.orderDetailInfo.driverPhone,
|
|
||||||
}
|
|
||||||
let data = {"action":"copyToClipboard","params":JSON.stringify(params)}
|
|
||||||
var u = navigator.userAgent;
|
|
||||||
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
|
|
||||||
if(isiOS){
|
|
||||||
window.webkit.messageHandlers.nativeObject.postMessage(data);
|
|
||||||
}else {
|
|
||||||
window.android.copyToClipboard(JSON.stringify(params));
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
this.$toast('未获取到司机信息')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async getDetail(){
|
async getDetail(){
|
||||||
let result=await getOrderDetail({
|
let result=await getOrderDetail({
|
||||||
queryType:this.queryType,
|
queryType:this.queryType,
|
||||||
@@ -201,9 +176,6 @@ export default {
|
|||||||
this.showPopup = true;
|
this.showPopup = true;
|
||||||
this.mapMarkers();
|
this.mapMarkers();
|
||||||
},
|
},
|
||||||
async createDriverInfo(){//生成司机信息
|
|
||||||
await this.getDriverInfo()
|
|
||||||
},
|
|
||||||
checkPhoto(){
|
checkPhoto(){
|
||||||
let isAllowImage = this.queryType == 9 ? 0 : 1
|
let isAllowImage = this.queryType == 9 ? 0 : 1
|
||||||
let data = {
|
let data = {
|
||||||
|
|||||||
Reference in New Issue
Block a user