更新记录
1.0.0(2023-10-07) 下载此版本
可根据后端格式自定义步骤条内容,自行改插件代码来展示步骤条当前节点的颜色,目前定义的颜色有完成、审核中、未通过、通过四种状态,可以自定重新定义状态颜色
平台兼容性
Vue2 | Vue3 |
---|---|
× | √ |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
× | × | √ | × | × | × | × |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
× | × | × | × |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | × | × | × | √ | √ | √ | √ | √ |
步骤条流程组件
组件使用vue3开发兼容微信小程序、H5、pc端,pc端需调整样式单位
使用示例
<template>
<div class="container_right">
<p class="title" v-if="props.title">{{ props.title }}</p>
<div class="timeline_box">
<ul>
<li class="font_h6 timeline_list_item" :class="{
'timeline_pass': item.workOrderBizStatus === 'INSTALLATION_TECHNOLOGY|PASS',
'timeline_reject': item.workOrderBizStatus === 'INSTALLATION_TECHNOLOGY|REJECT',
'timeline_finish': item.workOrderBizStatus === 'OPERATOR|FINISH'
}" v-for="(item, index) in data" :key="index">
<!-- 若传值可使用props.data或自定义 -->
<div class="timeline_timeLine">
<div class="timeline_timeLine_point">
<!-- <image style="width: 20rpx; height: 20rpx;" mode="scaleToFill" :src="imgUrl"></image> -->
<!-- <img src={u21718Img} class=" timeline_icon" /> -->
</div>
<div class="timeline_timeLine_line"></div>
</div>
<div class="timeline_container">
<div class="conter_box">
<div class="timeline_left text_bold">{{ workOrderBizStatusMap[item.workOrderBizStatus] }}{{
item.actionType === 'APPOINTMENT' ? "(约车)" : '' }}
</div>
<div class="timeline_right text_bold">{{ item.startTime }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">操作人 </div>
<div class="timeline_right">{{ item.handlerName || '--' }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">备注 </div>
<div class="timeline_right">{{ item.remark || '--' }}</div>
</div>
<template v-if="item.actionType === 'APPOINTMENT'">
<div class="conter_box">
<div class="timeline_left">联系人 </div>
<div class="timeline_right">{{ item.contactName }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">预约时间 </div>
<div class="timeline_right">{{ item.appointmentTime }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">预约地址 </div>
<div class="timeline_right">{{ item.appointmentAddress }}</div>
</div>
</template>
<template v-if="item.handlerContentJson && JSON.parse(item.handlerContentJson)?.patrolModels"
v-for="(it, i) in JSON.parse(item.handlerContentJson)?.patrolModels">
<div class="conter_box">
<div class="timeline_left">故障问题:</div>
<div class="timeline_right">{{ it.faultType || '--' }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">是否更换零件</div>
<div class="timeline_right">{{ it.isChangePart ? '是' : '否' || '--' }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">更换零件名称</div>
<div class="timeline_right">{{ it.partName || '--' }}</div>
</div>
<div class="conter_box">
<div class="timeline_left">描述</div>
<div class="timeline_right">{{ it.description || '--' }}</div>
</div>
</template>
<view v-if="item.handlerContentJson" class="conter_box_image">
<view class="timeline_left">附件</view>
<view class="conter_box_image_item">
<view v-if="item.deliveryType === 1 || item.deliveryType === 2 || item.deliveryType === 4"
class="image_item">
<view style="margin-bottom: 20rpx;" @click="previewImage(it.url)"
v-for="(it, index) in JSON.parse(item.handlerContentJson).allImages" :key="index">
<image mode="scaleToFill" style="width: 174rpx;height: 174rpx;border-radius: 8rpx;"
:src="it.url"></image>
<view class="timeline_left timeline_left_name">{{ it.fieldName }}</view>
</view>
</view>
<view v-if="item.deliveryType === 3" class="image_item">
<view style="margin-bottom: 20rpx;" @click="previewImage(it.url)"
v-for="(it, index) in JSON.parse(item.handlerContentJson).allImages" :key="index">
<image mode="scaleToFill" style="width: 174rpx;height: 174rpx;border-radius: 8rpx;"
:src="it.url"></image>
<view class="timeline_left timeline_left_name">{{ it.fieldName }}</view>
</view>
<view style="margin-bottom: 20rpx;" @click="previewImage(it.url)"
v-for="(it, index) in JSON.parse(item.handlerContentJson).updateImages"
:key="index">
<image mode="scaleToFill" style="width: 174rpx;height: 174rpx;border-radius: 8rpx;"
:src="it.url"></image>
<view class="timeline_left timeline_left_name">{{ it.fieldName }}</view>
</view>
</view>
</view>
</view>
</div>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import { workOrderBizStatusMap } from '@/enums/index'
type Props = {
data: any,
title: string
}
const props = defineProps<Props>()
const data = [
{
finishTime: "2023-09-14 14:35:17",
handlerContentJson: null,
handlerId: "1698599287165333506",
handlerName: "xxx",
id: "1702209168411787266",
remark: null,
startTime: "2023-09-14 14:34:26",
workOrderBizStatus: "OPERATOR|PROCESSING",
}, {
afterSaleName: "xxx",
currentNodeOptUserRoleType: "SERVICE_PROVIDER",
deliveryType: 1,
finishTime: "2023-09-14 14:38:03",
handlerContentJson: null,
handlerId: "1698981756778655745",
handlerName: "xxx",
id: "1702210004378517506",
remark: "开始接单安装单测试",
serviceProviderName: "xxx",
startTime: "2023-09-14 14:37:45",
workOrderBizStatus: "INSTALLATION_TECHNOLOGY|REJECT",
},
{
actionReasonType: "不喜欢",
actionType: "REJECT",
afterSaleName: "xxx",
currentNodeOptUserRoleType: "SERVICE_PROVIDER",
deliveryType: 1,
finishTime: "2023-09-14 14:39:37",
handlerId: "1698600798050103298",
handlerName: "陈应林",
id: "1702210333413277698",
remark: null,
serviceProviderName: "xxx",
startTime: "2023-09-14 14:39:04",
workOrderBizStatus: "INSTALLATION_TECHNOLOGY|PASS",
},
{
afterSaleName: "xxx",
currentNodeOptUserRoleType: "OPERATOR",
finishTime: "2023-09-14 14:34:26",
id: "1702209159314341890",
remark: "新增售后工单的---描述;运维人员:xxx",
serviceProviderName: "xxx",
startTime: "2023-09-14 14:34:24",
workOrderBizStatus: "OPERATOR|FINISH",
},
]
//预览图片
const previewImage = (url: string) => {
const urls = [];
urls.push(url)
uni.previewImage({
current: urls[0],
urls: urls,
indicator: "number"
})
}
</script>
<style lang="scss" scoped>
.container_right {
padding: 20rpx;
border-radius: 16rpx;
background-color: #fff;
}
.title {
margin-bottom: 30rpx;
font-size: 34rpx;
font-weight: 600;
}
.ac {
border: 2rpx solid #f00;
:focus {
outline: #FF0000 solid 4rpx;
}
}
.timeline_box {
.timeline_list_item {
list-style-type: none;
display: flex;
.timeline_timeLine {
width: 32rpx;
position: relative;
top: 8rpx;
display: flex;
flex-direction: column;
align-items: center;
.timeline_timeLine_point {
width: 20rpx;
height: 20rpx;
background: #FFFFFF;
border: 4rpx solid #0E5DD4;
border-radius: 50%;
// background-color: var(--line);
position: relative;
z-index: 9;
.timeline_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24rpx;
line-height: 24rpx;
}
}
.timeline_timeLine_line {
width: 6rpx;
height: 100%;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
background: #eee;
background-position: left;
background-size: 4rpx 12rpx;
background-repeat: repeat-y;
}
}
.timeline_container {
flex: 1;
padding: 10rpx 20rpx;
background: #f5f5f5;
border-radius: 12rpx;
margin: 12rpx 0px 12rpx 12rpx;
.text_bold {
font-weight: bold;
font-size: 28rpx;
}
.conter_box {
display: flex;
justify-content: space-between;
font-size: 24rpx;
line-height: 48rpx;
.conter_box:hover {
color: red;
}
.timeline_right {
font-size: 24rpx;
color: #333;
display: flex;
align-items: center;
.timeline_right_ico {
font-size: 24rpx;
margin-right: 3px;
color: #ea9c47;
}
.timeline_right_text {
font-size: 26rpx;
font-weight: 700;
color: #333;
}
}
}
.timeline_corpName {
color: #333;
}
}
}
.timeline_pass {
.timeline_timeLine_point {
width: 20rpx;
height: 20rpx;
background: #FFFFFF;
border: 4rpx solid #00B042 !important;
border-radius: 50%;
position: relative;
z-index: 9;
.timeline_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24rpx;
line-height: 24rpx;
}
}
}
.timeline_finish {
.timeline_timeLine_point {
border: 4rpx solid #B3B5B9 !important;
}
}
.timeline_reject {
.timeline_timeLine_point {
width: 20rpx;
height: 20rpx;
background: #FFFFFF;
border: 4rpx solid #f00 !important;
border-radius: 50%;
position: relative;
z-index: 9;
.timeline_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24rpx;
line-height: 24rpx;
}
}
}
}
.conter_box_image {
.conter_box_image_item {
.image_item {
display: flex;
flex-wrap: wrap;
&>view:not(:nth-child(3n)) {
margin-right: 30rpx;
}
}
}
}
.timeline_left_name {
width: 174rpx;
text-align: center;
font-size: 20rpx;
}
</style>
根据后端返回的字段类型来展示步骤原点颜色,或自定义步骤原点颜色
通过状态
'timeline_pass': item.workOrderBizStatus === 'INSTALLATION_TECHNOLOGY|PASS'
拒绝状态
'timeline_reject': item.workOrderBizStatus === 'INSTALLATION_TECHNOLOGY|REJECT'
完成状态
'timeline_finish': item.workOrderBizStatus === 'OPERATOR|FINISH'