This commit is contained in:
ChuShiZ 2024-10-13 23:24:23 +08:00
parent d7dc1d403f
commit e9eb9005c4
51 changed files with 14536 additions and 2834 deletions

View File

@ -1,5 +1,5 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
@ -24,4 +24,8 @@
body {
height: 100%;
}
</style>
* {
box-sizing: border-box;
}
</style>

View File

@ -1,112 +1,113 @@
<template>
<!-- header -->
<view :style="{ backgroundColor, paddingTop: homeHeaderPaddingTop + 'px', height: homeHeaderMenuHeight + 'px' }"
class="navigationBar" :class="{leftTitle: leftTitle}">
<template v-if="leftTitle">
<view class="navigationBarTitle" :style="{ color: titleColor }">
{{ title ? title : '' }}
</view>
</template>
<template v-else>
<view class="navigationBarBack" @click="back" >
<slot name="back">
<uni-icons size="24" type="left"
:color="titleColor"></uni-icons>
</slot>
</view>
<view class="navigationBarTitle" :style="{ color: titleColor }">
{{ title }}
</view>
</template>
<view class="navigationBarBackExtra">
<slot name="extra">
</slot?>
</view>
</view>
<!-- header -->
<view>
<view :style="{ height: homeHeaderPaddingTop + 'px', backgroundColor }"></view>
<view :class="{leftTitle: leftTitle}"
:style="{ backgroundColor, height: homeHeaderMenuHeight + 'px' }" class="navigationBar">
<template v-if="leftTitle">
<view :style="{ color: titleColor }" class="navigationBarTitle">
{{ title ? title : '' }}
</view>
</template>
<template v-else>
<view class="navigationBarBack" @click="back">
<slot name="back">
<uni-icons :color="titleColor" size="24"
type="left"></uni-icons>
</slot>
</view>
<view :style="{ color: titleColor }" class="navigationBarTitle">
{{ title }}
</view>
</template>
<view class="navigationBarBackExtra">
<slot name="extra">
</slot>
</view>
</view>
</view>
</template>
<script>
/* 计算标题位置 */
import {
getWXStatusHeight
} from "@/utils/utils";
/* 计算标题位置 */
import {getWXStatusHeight} from "@/utils/utils";
export default {
props: {
backgroundColor: {
type: String,
default: '#317DFA'
},
title: String,
titleColor: {
type: String,
default: '#fff'
},
leftTitle: {
type: Boolean,
default: false
}
},
mounted() {
// #ifdef MP
const {
barHeight,
barTop,
menuButtonLeft
} = getWXStatusHeight()
console.log('barHeight, barTop, menuButtonLeft: ', barHeight, barTop, menuButtonLeft);
this.homeHeaderPaddingTop = barTop || 0
this.homeHeaderMenuHeight = barHeight
this.homeHeaderMenuLeft = menuButtonLeft - 6
// #endif
},
data() {
return {
// #ifdef MP
homeHeaderPaddingTop: 0,
homeHeaderMenuHeight: 0,
homeHeaderMenuLeft: 0,
// #endif
// #ifdef APP || H5
homeHeaderPaddingTop: 20,
homeHeaderMenuHeight: 50,
homeHeaderMenuLeft: 0
// #endif
}
},
methods: {
back() {
uni.navigateBack()
}
}
}
export default {
props: {
backgroundColor: {
type: String,
default: '#317DFA'
},
title: String,
titleColor: {
type: String,
default: '#fff'
},
leftTitle: {
type: Boolean,
default: false
}
},
mounted() {
// #ifdef MP
const {
barHeight,
barTop,
menuButtonLeft
} = getWXStatusHeight()
console.log('barHeight, barTop, menuButtonLeft: ', barHeight, barTop, menuButtonLeft);
this.homeHeaderPaddingTop = barTop || 0
this.homeHeaderMenuHeight = barHeight
this.homeHeaderMenuLeft = menuButtonLeft - 6
// #endif
},
data() {
return {
// #ifdef MP
homeHeaderPaddingTop: 0,
homeHeaderMenuHeight: 0,
homeHeaderMenuLeft: 0,
// #endif
// #ifdef APP || H5
homeHeaderPaddingTop: 20,
homeHeaderMenuHeight: 50,
homeHeaderMenuLeft: 0
// #endif
}
},
methods: {
back() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.navigationBar {
position: relative;
display: flex;
align-items: center;
justify-content: center;
.navigationBar {
position: relative;
display: flex;
align-items: center;
justify-content: center;
&.leftTitle {
justify-content: start;
padding-left: 28rpx;
}
&.leftTitle {
justify-content: start;
padding-left: 28rpx;
}
.navigationBarBack {
position: absolute;
left: 20rpx;
}
.navigationBarBack {
position: absolute;
left: 20rpx;
}
.navigationBarBackExtra {
position: absolute;
right: 20rpx;
}
.navigationBarBackExtra {
position: absolute;
right: 20rpx;
}
.navigationBarTitle {
font-size: 36rpx;
font-weight: bold;
}
}
</style>
.navigationBarTitle {
font-size: 36rpx;
font-weight: bold;
}
}
</style>

229
components/orderCard.vue Normal file
View File

@ -0,0 +1,229 @@
<template>
<view class="orderCard">
<view class="order-top">
<view class="orderNo">
订单编号{{ order.orderNo }}
</view>
<view :style="{ color: getFlagColor(order.flag) }" class="flag">
{{ order.flagStr }}
</view>
</view>
<view class="order-body">
<view class="carNum">
{{ order.carNum }}
</view>
<view class="carModel">
{{ order.carModel }}
</view>
<view class="project">
<view class="project-left">
<view class="title">
<image class="titleIcon" mode="aspectFit" src="/static/icons/order-icon1.png"></image>
维修项目
</view>
<view class="desc">
{{ projectName }}
</view>
</view>
<view v-if="order.flag == 2" class="project-right">
<image class="rightIcon" mode="aspectFit" src="/static/icons/success.png"></image>
<text class="rightText">已派工</text>
</view>
</view>
<view class="baseInfo">
<view>
客户信息{{ order.userName }} {{ order.userPhone }}
</view>
<view>
预约时间{{ order.appointDate }}
</view>
<view>
服务顾问{{ order.counselorName }}
</view>
</view>
<view class="footer">
<view @click="gotoDetail" v-if="order.flag == 1" class="btn pg">
项目派工
</view>
<view @click="gotoDetail" v-else-if="order.flag == 2" class="btn qc">
告知取车
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "orderCard",
props: {
order: {
type: Object,
default: () => {
return {}
}
}
},
computed: {
projectName() {
if (this.order && this.order.projectList && this.order.projectList.length > 0) {
return this.order.projectList.map(m => m.name).join(',')
}
return ''
}
},
data() {
return {}
},
methods: {
getFlagColor(flag) {
if (flag == 1) {
return '#E8A321'
} else if (flag === 2) {
return '#999'
}
},
gotoDetail() {
uni.navigateTo({
url: '/pages-order/orderDetail/orderDetail?id=' + this.order.id
})
}
}
}
</script>
<style lang="less" scoped>
.orderCard {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
border-left: 4rpx solid #FFB323;
padding: 0 30rpx;
}
.order-top {
padding: 20rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #F3F5F7;
.orderNo {
font-weight: 500;
font-size: 24rpx;
color: #858BA0;
}
.flag {
font-family: PingFang SC, PingFang SC;
font-weight: 500;
font-size: 24rpx;
}
}
.order-body {
.carNum {
margin: 20rpx 0;
}
.carModel {
margin: 20rpx 0;
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
}
.project {
padding: 20rpx 10rpx;
background: #F2F2F7;
border-radius: 4rpx 4rpx 4rpx 4rpx;
display: flex;
align-items: center;
.project-left {
flex: 1;
width: 0;
}
.project-right {
padding: 0 16rpx;
display: flex;
flex-direction: column;
align-items: center;
border-left: 1rpx solid #DDDDDD;
.rightIcon {
width: 40rpx;
height: 40rpx;
}
.rightText {
font-weight: 500;
font-size: 24rpx;
color: #17DBB1;
}
}
.title {
font-weight: 500;
font-size: 24rpx;
color: #0174F6;
display: flex;
align-items: center;
column-gap: 8rpx;
}
.titleIcon {
width: 24rpx;
height: 24rpx;
}
.desc {
font-weight: 500;
font-size: 24rpx;
color: #333333;
margin-top: 10rpx;
}
}
.baseInfo {
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
& > view {
margin: 30rpx 0;
}
}
.footer {
display: flex;
align-items: center;
justify-content: flex-end;
column-gap: 10rpx;
padding-bottom: 30rpx;
.btn {
width: 172rpx;
height: 60rpx;
border-radius: 30rpx 30rpx 30rpx 30rpx;
border: 2rpx solid #0174F6;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
&.qc {
background: #0174F6;
color: #fff;
}
}
}
}
</style>

View File

@ -0,0 +1,275 @@
<template>
<view>
<uni-popup ref="popup" type="bottom">
<view class="popupContent">
<view class="header">
<text class="cancel" @click="cancel">取消</text>
<text class="title">选择维修项目</text>
<text class="submit" @click="confirm">确定</text>
</view>
<view class="chooseProj">
<view class="desc">
已经选择{{ selectedProj.length }}项维修项目
</view>
<view class="selectedProj">
<view v-for="(item, index) in selectedProj" :key="index" class="selectedProjItem">
<text>{{ item.name }}</text>
<image class="itemIcon" mode="aspectFit" src="/static/icons/x.png" @click="removeProj(index)"></image>
</view>
</view>
</view>
<view v-if="typeList && typeList.length > 0" class="projPicker">
<view class="type">
<view v-for="item in typeList" :key="item.id" :class="{'active': typeId === item.id}" class="typeItem"
@click="chooseType(item)">
{{ item.name }}
</view>
</view>
<view class="container">
<view v-for="item in groupList" :key="item.id" class="groupList">
<view class="groupHeader">
<view class="line"></view>
<text>{{ item.name }}</text>
<view class="line"></view>
</view>
<view class="projList">
<view v-for="(proj, index) in item.projList" :key="proj.id" class="projItem" @click="chooseProj(proj)">
<text class="projName">{{ proj.name }}</text>
<image v-if="selectedProj && selectedProj.find(f => f.id === proj.id)" class="projChooseIcon"
mode="aspectFit" src="/static/icons/duihao.png"></image>
</view>
</view>
</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
name: "projectPicker",
data() {
return {
selectedProj: [
{name: '精洗内饰', id: 1},
{name: '内饰精洗除臭', id: 2},
{
name: '烘干底板胶及脚垫',
id: 3
},
{name: '精致洗车(轿车)', id: 4},
{name: '人保核销洗车劵', id: 5},
{name: '人保核销洗车劵', id: 6}
],
typeList: [
{
name: '洗车',
id: 1,
groupList: [
{
name: '精洗',
id: 'groupId1',
projList: [{name: '清洗内饰', id: 1}, {name: '内饰精洗除臭', id: 2}]
}
]
},
{
name: '二手车',
id: 2
}
],
typeId: 1,
groupList: [
{
name: '精洗',
id: 'groupId1',
projList: [{name: '清洗内饰', id: 1}, {name: '内饰精洗除臭', id: 2}]
}
]
}
},
methods: {
open(selectedProj = []) {
this.$refs.popup.open()
this.selectedProj = JSON.parse(JSON.stringify(selectedProj))
},
removeProj(index) {
this.selectedProj.splice(index, 1)
},
chooseProj(proj) {
const findIndex = this.selectedProj.findIndex(f => f.id === proj.id)
if (findIndex > -1) {
this.selectedProj.splice(findIndex, 1)
} else {
this.selectedProj.push(proj)
}
},
chooseType(type) {
this.groupList = type.groupList
this.typeId = type.id
},
confirm() {
this.$emit('confirm', this.selectedProj)
this.cancel()
},
cancel() {
this.selectedProj = []
this.groupList = this.typeList[0].groupList
this.$refs.popup.close()
}
}
}
</script>
<style lang="scss" scoped>
.popupContent {
height: 86vh;
background-color: #fff;
border-radius: 32rpx 32rpx 0rpx 0rpx;
display: flex;
flex-direction: column;
}
.header {
padding: 40rpx;
display: flex;
align-items: center;
font-size: 32rpx;
border-bottom: 1rpx solid #EEEEEE;
.title {
flex: 1;
width: 0;
text-align: center;
font-weight: bold;
color: #333333;
}
.cancel {
font-weight: 500;
color: #999999;
}
.submit {
font-weight: 500;
color: #0174F6;
}
}
.chooseProj {
padding: 30rpx 32rpx;
.desc {
font-weight: 500;
font-size: 24rpx;
color: #999999;
}
.selectedProj {
display: flex;
align-items: center;
gap: 20rpx;
flex-wrap: wrap;
padding: 30rpx 0;
.selectedProjItem {
display: flex;
align-items: center;
column-gap: 10rpx;
padding: 10rpx 16rpx;
border-radius: 4rpx 4rpx 4rpx 4rpx;
border: 2rpx solid #0174F6;
font-weight: 500;
font-size: 24rpx;
color: #0174F6;
.itemIcon {
width: 16rpx;
height: 16rpx;
}
}
}
}
.projPicker {
flex: 1;
height: 0;
overflow: auto;
border-top: 1rpx solid #EEEEEE;
display: flex;
.type {
width: 200rpx;
background: #FFFFFF;
.typeItem {
width: 100%;
background: #F2F2F7;
padding: 40rpx 32rpx;
&.active {
background-color: #fff;
}
}
}
.container {
flex: 1;
width: 0;
padding: 30rpx;
.groupList {
.groupHeader {
display: flex;
align-items: center;
column-gap: 4rpx;
font-weight: 500;
font-size: 24rpx;
color: #999999;
.line {
flex: 1;
width: 0;
height: 2rpx;
background-color: #DDDDDD;
}
}
.projList {
padding: 40rpx 0;
display: flex;
flex-direction: column;
row-gap: 40rpx;
.projItem {
display: flex;
align-items: center;
justify-content: space-between;
.projName {
flex: 1;
width: 0;
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
.projChooseIcon {
width: 36rpx;
height: 36rpx;
}
}
}
}
}
}
</style>

View File

@ -12,7 +12,7 @@
<image mode="aspectFit" src="@/static/icons/tabbar/order.png" v-show="aindex != 2"></image>
<image mode="aspectFit" src="@/static/icons/tabbar/order-checked.png" v-show="aindex == 2"></image>
</view>
<view class="">订单</view>
<view class="">工单处理</view>
</view>
<view class="box" :class="{active: aindex == 3}" @click="getgogo(3)">
<view class="imgs">

View File

@ -1,394 +1,364 @@
<template>
<view class="container">
<VNavigationBar style="position: relative;z-index: 99;" leftTitle="true" backgroundColor="rgba(0,0,0,0)" title-color="#fff" title="车辆检测维修"></VNavigationBar>
<template v-if="bannerList && bannerList.length > 0" >
<view class="bannerBg1"></view>
<view class="bannerBg" :style="{backgroundImage: `url(${bannerList[bannerIndex].url})`}"></view>
<view class="bannerBottom"></view>
</template>
<view class="body">
<view class="body-top-banner">
<!-- <image class="banner" src="@/static/images/banner.jpg" mode="aspectFit" />-->
<!-- <image class="banner" v-for="banner in bannerList" :key="banner.id" :src="banner.url" @click="toContent(banner.id)" mode="scaleToFill" />-->
<swiper style="height: 400rpx;" class="swiper" circular indicator-dots="true" autoplay="true" interval="2000" duration="500"
@change="swiperChangeFun">
<swiper-item v-for="banner in bannerList" :key="banner.id" @click="toContent(banner.id)">
<image class="banner" :src="banner.url" mode="aspectFill" />
</swiper-item>
</swiper>
</view>
<view class="menus">
<view @click="gotoPage(menu)" v-for="(menu, index) in menus" :key="index" class="menu-item">
<image class="menu-icon" :src="menu.icon" mode="aspectFit"></image>
<text class="menu-title">{{menu.title}}</text>
</view>
</view>
<view class="info">
<image class="info-icon" src="@/static/icons/homeInfo.png" mode="aspectFit"></image>
<view class="infoList">
<view v-for="(item, index) in infoList" :key="item.id" class="infoItem">
<view class="infoIndex"></view>
<view class="infoText">{{item.title}}</view>
</view>
</view>
<image class="more-icon" src="../../static/icons/homeInfoMore.png" mode="aspectFit"></image>
</view>
<view class="repairShop">
<view class="title">推荐修理厂</view>
<view class="shopList">
<view v-for="(item, index) in shopList" :key="index" class="shopItem" @click="gotoShopDetail(item)">
<image class="shopImg" :src="item.image" mode="aspectFill"></image>
<view class="shopInfo">
<view class="shopTitle">{{item.corpName}}</view>
<view class="shopDetail">
<view class="shopAddress">{{item.address}}</view>
<view class="line"></view>
<view class="shopDistance">{{item.distance}}</view>
</view>
</view>
</view>
</view>
</view>
</view>
<tabBarVue msg="1"></tabBarVue>
</view>
<view class="container">
<!--<VNavigationBar style="position: relative;z-index: 99;" leftTitle="true" backgroundColor="rgba(0,0,0,0)" title-color="#fff" title=" "></VNavigationBar>-->
<view class="bodyTopBg"></view>
<view class="body">
<view class="body-top-grid">
<view v-for="(item, index) in menuList" :key="index" class="body-top-item" @click="gotoPage(item)">
<view>
<view class="title">{{ item.title }}</view>
<view class="desc">{{ item.desc }}</view>
<image class="btn" mode="aspectFit" src="@/static/icons/homeMenuIcon/menuBtn.png"></image>
</view>
<image :src="item.icon" class="icon" mode="aspectFit"></image>
</view>
</view>
<view class="todoListBox">
<view class="title">
待办工单
<text class="titleDesc">当前共
<text class="titleCount">2</text>
项工单需要处理
</text>
</view>
<view class="todoList">
<order-card v-for="(item, index) in orderList" :key="index" :order="item"></order-card>
</view>
</view>
</view>
<tabBarVue msg="1"></tabBarVue>
</view>
</template>
<script>
import tabBarVue from '@/components/tabBar/tabBar.vue'
import VNavigationBar from '@/components/VNavigationBar.vue'
import request from "../../utils/request";
import config from "@/config";
export default {
components: {
tabBarVue,
VNavigationBar
},
data() {
return {
bannerIndex: 0,
menus: [{
title: '预约记录',
icon: require('@/static/icons/homeMenuIcon/menu1.png'),
path: '/pages/myReservation/myReservation'
},
{
title: '我的车辆',
icon: require('@/static/icons/homeMenuIcon/menu2.png'),
path: '/pages/myCar/myCar'
},
{
title: '活动礼包',
icon: require('@/static/icons/homeMenuIcon/menu3.png'),
path: '/pages-home/home/active'
},
{
title: '操作指南',
icon: require('@/static/icons/homeMenuIcon/menu4.png'),
path: '/pages/guideList/guideList'
},
],
infoList: [{
id: 1,
title: '暖心!深夜汽车高速路上爆胎 彝良交警化身“修理工”帮忙换胎'
},
{
id: 2,
title: '车辆机件“焕新上岗”,武汉公交修旧创效出实招'
},
],
// shopList: [{
// id: 1,
// title: '',
// address: '',
// distance: '1.9km',
// image: ''
// },
// {
// id: 2,
// title: '',
// address: '',
// distance: '1.9km',
// image: ''
// },
// {
// id: 3,
// title: '',
// address: '',
// distance: '1.9km',
// image: ''
// },
// ]
shopList: [],
bannerList: [],
richTextHtml: null
}
},
onShow() {
this.getCompanyPage()
this.getBannerList()
},
methods: {
swiperChangeFun(e) {
console.log('e', e)
this.bannerIndex = e.detail.current
},
toContent(id) {
uni.navigateTo({
url: "/pages-home/home/content?id=" + id,
})
},
async getBannerList() {
const res = await request({
url: '/userClient/banner/list?type=weixiu',
method: "get",
})
this.bannerList = res.data
this.bannerList.forEach(item => {
item.url = config.baseImageUrl + item.url
})
},
gotoShopDetail(row) {
//
uni.navigateTo({
url: '/pages-shop/shopDetail/shopDetail?info=' + encodeURIComponent(JSON.stringify(row))
})
},
gotoPage(menu) {
uni.navigateTo({
url: menu.path
})
},
//
async getCompanyPage() {
const res = await request({
url: "/userClient/base/company/page",
method: "get",
params: {
serviceCodes: "weixiu"
}
})
this.shopList = res.data.records
this.shopList.forEach(item => {
item['image'] = require("../static/outImage.jpg")
})
}
}
}
import tabBarVue from '@/components/tabBar/tabBar.vue'
import VNavigationBar from '@/components/VNavigationBar.vue'
import OrderCard from "@/components/orderCard.vue";
export default {
components: {
OrderCard,
tabBarVue,
VNavigationBar
},
data() {
return {
menuList: [
{
title: '新建工单',
desc: '直接添加客户订单',
icon: require('@/static/icons/homeMenuIcon/menu1.png'),
path: '/pages-order/addOrder/addOrder'
},
{title: '预约开单', desc: '查询预约记录', icon: require('@/static/icons/homeMenuIcon/menu1.png'), path: '/pages-order/appointOrder/appointOrder'}
],
bannerIndex: 0,
shopList: [],
bannerList: [],
richTextHtml: null,
orderList: [
{
orderNo: '1209840149750105501',
flag: 1, flagStr: '待处理', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
},
{
orderNo: '1209840149750105501',
flag: 1, flagStr: '待处理', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
}
]
}
},
onShow() {
},
methods: {
gotoPage(menu) {
uni.navigateTo({
url: menu.path
})
},
}
}
</script>
<style scoped lang="less">
.container {
height: 100%;
background-color: #fff;
//background: linear-gradient(180deg, #0174F6 0%, rgba(1, 116, 246, 0) 100%);
color: #333333;
display: flex;
flex-direction: column;
position: relative;
<style lang="less" scoped>
* {
box-sizing: border-box;
}
.bannerBg1 {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 800rpx;
background-color: #999;
filter: blur(20rpx);
z-index: 1;
}
.bannerBg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 800rpx;
background-size: 100% 100%;
background-repeat: no-repeat;
/* 应用背景模糊滤镜 */
-webkit-backdrop-filter: blur(10px);
/* 兼容Webkit内核浏览器如Chrome、Safari */
// backdrop-filter: blur(10px);
filter: blur(20rpx);
/* 设置透明度 */
opacity: 0.5;
// -webkit-filter: brightness(150%);
// filter: brightness(150%);
transition: all 0.5s;
z-index: 2;
}
.bannerBottom {
z-index: 3;
position: absolute;
left: 0;
top: 600rpx;
width: 100%;
height: 300rpx;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.6) 50%, rgba(255, 255, 255, 1) 100%);
}
.body {
position: relative;
z-index: 10;
flex: 1;
height: 0;
overflow: auto;
padding-bottom: 30rpx;
}
.container {
height: 100%;
//background: linear-gradient(180deg, #0174F6 0%, rgba(1, 116, 246, 0) 100%);
display: flex;
flex-direction: column;
position: relative;
padding-top: 60rpx;
background-color: #F3F5F7;
.body-top-banner {
text-align: center;
}
.bodyTopBg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 500rpx;
background: rgba(1, 116, 246, 0.2);
}
.banner {
margin: 24rpx 0 0;
width: 686rpx;
height: 100%;
border-radius: 12rpx 12rpx 12rpx 12rpx;
background-color: #0174F6;
}
.body {
position: relative;
z-index: 10;
flex: 1;
height: 0;
overflow: auto;
padding-bottom: 30rpx;
}
.menus {
margin: 30rpx auto 0;
box-sizing: border-box;
width: 686rpx;
padding: 40rpx 38rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(10, 54, 104, 0.1);
border-radius: 12rpx 12rpx 12rpx 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.body-top-grid {
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 30rpx;
margin: 0 32rpx;
.menu-item {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
row-gap: 22rpx;
font-size: 24rpx;
.body-top-item {
position: relative;
display: flex;
align-items: center;
padding: 30rpx 0 30rpx 20rpx;
background: linear-gradient(360deg, #FFFFFF 0%, #D7EAFF 100%);
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid;
border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(202, 223, 247, 1)) 2 2;
.menu-icon {
width: 48rpx;
height: 48rpx;
}
}
& > view:first-child {
flex: 1;
width: 0;
display: flex;
flex-direction: column;
row-gap: 30rpx;
}
.info {
width: 686rpx;
margin: 38rpx auto 0;
display: flex;
align-items: center;
column-gap: 20rpx;
.title {
font-weight: bold;
font-size: 32rpx;
color: #113A68;
}
.info-icon {
width: 80rpx;
height: 80rpx;
}
.desc {
font-weight: 500;
font-size: 24rpx;
color: #858BA0;
}
.infoList {
flex: 1;
width: 0;
.btn {
width: 40rpx;
height: 30rpx;
}
.infoItem {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 10rpx;
}
.icon {
width: 136rpx;
height: 136rpx;
}
}
}
.infoIndex {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background-color: #333;
}
.todoListBox {
margin: 40rpx 32rpx;
.infoText {
flex: 1;
width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 24rpx;
}
}
.title {
margin-bottom: 30rpx;
font-weight: bold;
font-size: 32rpx;
color: #113A68;
.more-icon {
width: 24rpx;
height: 24rpx;
}
}
.titleDesc {
margin-left: 20rpx;
font-weight: 500;
font-size: 24rpx;
color: #858BA0;
}
.repairShop {
width: 686rpx;
margin: 38rpx auto 0;
.titleCount {
color: #0174F6;
}
}
.title {
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.todoList {
display: flex;
flex-direction: column;
row-gap: 20rpx;
}
}
.shopList {
.shopItem {
padding: 30rpx 0;
border-bottom: 1rpx solid #DDDDDD;
display: flex;
align-items: center;
column-gap: 20rpx;
}
.body-top-banner {
text-align: center;
}
.shopImg {
width: 160rpx;
height: 100rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
background-color: #999;
}
.banner {
margin: 24rpx 0 0;
width: 686rpx;
height: 100%;
border-radius: 12rpx 12rpx 12rpx 12rpx;
background-color: #0174F6;
}
.shopInfo {
flex: 1;
width: 0;
}
.menus {
margin: 30rpx auto 0;
box-sizing: border-box;
width: 686rpx;
padding: 40rpx 38rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(10, 54, 104, 0.1);
border-radius: 12rpx 12rpx 12rpx 12rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.shopTitle {
font-weight: 500;
font-size: 28rpx;
color: #333333;
margin-bottom: 20rpx;
}
.menu-item {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
row-gap: 22rpx;
font-size: 24rpx;
.shopDetail {
display: flex;
align-items: center;
font-size: 24rpx;
color: #666666;
column-gap: 10rpx;
}
.menu-icon {
width: 48rpx;
height: 48rpx;
}
}
.shopAddress {
flex: 1;
width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.info {
width: 686rpx;
margin: 38rpx auto 0;
display: flex;
align-items: center;
column-gap: 20rpx;
.line {
width: 2rpx;
height: 24rpx;
background-color: #858BA0;
}
.info-icon {
width: 80rpx;
height: 80rpx;
}
.shopDistance {
flex-shrink: 0;
}
}
}
}
.infoList {
flex: 1;
width: 0;
.infoItem {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 10rpx;
}
.infoIndex {
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background-color: #333;
}
.infoText {
flex: 1;
width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 24rpx;
}
}
.more-icon {
width: 24rpx;
height: 24rpx;
}
}
.repairShop {
width: 686rpx;
margin: 38rpx auto 0;
.title {
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.shopList {
.shopItem {
padding: 30rpx 0;
border-bottom: 1rpx solid #DDDDDD;
display: flex;
align-items: center;
column-gap: 20rpx;
}
.shopImg {
width: 160rpx;
height: 100rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
background-color: #999;
}
.shopInfo {
flex: 1;
width: 0;
}
.shopTitle {
font-weight: 500;
font-size: 28rpx;
color: #333333;
margin-bottom: 20rpx;
}
.shopDetail {
display: flex;
align-items: center;
font-size: 24rpx;
color: #666666;
column-gap: 10rpx;
}
.shopAddress {
flex: 1;
width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.line {
width: 2rpx;
height: 24rpx;
background-color: #858BA0;
}
.shopDistance {
flex-shrink: 0;
}
}
}
}
</style>

View File

@ -0,0 +1,531 @@
<template>
<view class="container">
<view class="containerBody">
<VNavigationBar background-color="rgba(0,0,0,0)" title="新建工单" title-color="#333"></VNavigationBar>
<view class="body">
<view class="card phone">
<view class="phoneHeader">
<view class="title">查找手机号</view>
<view class="desc">根据手机号查找/建立客户信息</view>
</view>
<view class="phoneBody">
<view class="searchBox">
<input v-model="phone" placeholder="请输入手机号码" type="tel">
</view>
<view class="btn">
<image class="btnIcon" mode="aspectFit" src="/pages-order/static/search.png"></image>
确认查找
</view>
</view>
</view>
<view :class="{ 'none': !carList || carList.length === 0 }" class="card cardInfo carCard">
<template v-if="!carList || carList.length === 0">
<image class="cardNoneIcon" mode="widthFix" src="/pages-order/static/carNoneIcon.png"></image>
<view class="btn">
<image mode="aspectFit" src="/pages-order/static/addIcon.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="editCarInfo()">添加车辆信息</text>
</view>
</template>
<template v-else>
<view class="carTitle">车辆信息</view>
<view class="carListTab">
<view v-for="(item, index) in carList" :key="index" :class="{'active': activeCarIndex === index}"
class="carTabItem" @click="() => activeCarIndex = index">
<image :src="item.image" class="carImage" mode="aspectFit"></image>
<text>{{ item.licenseNumber }}</text>
</view>
</view>
<view class="carDetail">
<view class="carHeader">
<image :src="carList[activeCarIndex].image" class="carImage" mode="aspectFill"></image>
<view class="carHeaderRight">
<text class="carNumber">{{ carList[activeCarIndex].licenseNumber }}</text>
<text class="carType">{{ carList[activeCarIndex].carCategory }}</text>
</view>
</view>
<view class="carBody">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<view class="label">车架号</view>
<view class="value">{{ carList[activeCarIndex].cjNo }}</view>
</view>
<view class="infoItem" style="flex: 1">
<view class="label">发动机号</view>
<view class="value">{{ carList[activeCarIndex].fdjNo }}</view>
</view>
</view>
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<view class="label">年检时间</view>
<view class="value">{{ carList[activeCarIndex].njDate }}</view>
</view>
<view class="infoItem" style="flex: 1">
<view class="label">保险时间</view>
<view class="value">{{ carList[activeCarIndex].bxDate }}</view>
</view>
</view>
<view class="infoItem">
<view class="label">注册日期</view>
<view class="value">{{ carList[activeCarIndex].zcrqDate }}</view>
</view>
</view>
<view class="carFoot">
<image mode="aspectFit" src="/static/icons/edit.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="editCarInfo(activeCarIndex)">修改信息</text>
</view>
</view>
</template>
</view>
<view :class="{ 'none': !userInfo }" class="card cardInfo userCard">
<template v-if="!userInfo">
<image class="cardNoneIcon" mode="widthFix" src="/pages-order/static/userNone.png"></image>
<view class="btn">
<image mode="aspectFit" src="/pages-order/static/addIcon.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="editUserInfo()">添加客户信息</text>
</view>
</template>
<template v-else>
<view class="userTitle">客户信息</view>
<view class="userContainer">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<text class="label">姓名</text>
<text class="value">{{ userInfo.name }}</text>
</view>
<view class="infoItem" style="flex: 1">
<text class="label">性别</text>
<text class="value">{{ userInfo.sex === '1' ? '女' : '男' }}</text>
</view>
</view>
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<text class="label">联系方式</text>
<text class="value">{{ userInfo.phone }}</text>
</view>
<view class="infoItem" style="flex: 1">
<text class="label">出生年月</text>
<text class="value">{{ userInfo.birthday }}</text>
</view>
</view>
<view class="infoItem">
<text class="label">联系地址</text>
<text class="value">
{{ userInfo.provinceName }} {{ userInfo.cityName }} {{ userInfo.areaName }} {{ userInfo.address }}
</text>
</view>
</view>
<view class="userFoot">
<image mode="aspectFit" src="/static/icons/edit.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="editUserInfo(userInfo)">修改信息</text>
</view>
</template>
</view>
<view :class="{ 'none': !selectedProj || selectedProj.length === 0 }" class="card cardInfo projCard">
<template v-if="!selectedProj || selectedProj.length === 0">
<image class="cardNoneIcon" mode="widthFix" src="/pages-order/static/projectNone.png"></image>
<view class="btn">
<image mode="aspectFit" src="/pages-order/static/addIcon.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="addProj()">添加维修项目</text>
</view>
</template>
<template v-else>
<view class="projTitle">维修项目</view>
<view class="projList">
<view v-for="item in selectedProj" :key="item.id" class="projItem">
{{ item.name }}
</view>
</view>
<view class="projFoot">
<image mode="aspectFit" src="/static/icons/edit.png" style="width: 28rpx;height: 28rpx"></image>
<text @click="addProj(selectedProj)">修改信息</text>
</view>
</template>
</view>
<project-picker ref="proj" @confirm="projConfirm"></project-picker>
</view>
<view class="footer">
<view class="btn" @click="submit">创建工单</view>
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
import ProjectPicker from "@/components/projectPicker.vue";
import {bus} from "@/utils/eventBus";
export default {
components: {
ProjectPicker,
VNavigationBar,
},
data() {
return {
phone: '',
carList: [
{
licenseNumber: '川A 184AO1',
carCategory: '一汽奥迪 2024款 A6L',
cjNo: '124105112425',
fdjNo: '124109581905',
njDate: '2024年',
bxDate: '2024年',
zcrqDate: '2023-10-20',
image: ''
},
{
licenseNumber: '川A 34225A',
carCategory: '一汽奥迪 2024款 A6L',
cjNo: '124105112425',
fdjNo: '124109581905',
njDate: '2024年',
bxDate: '2024年',
zcrqDate: '2023-10-20',
image: ''
},
{
licenseNumber: '川A 34225A',
carCategory: '一汽奥迪 2024款 A6L',
cjNo: '124105112425',
fdjNo: '124109581905',
njDate: '2024年',
bxDate: '2024年',
zcrqDate: '2023-10-20',
image: ''
}
],
activeCarIndex: 0,
userInfo: null,
selectedProj: []
}
},
onLoad(data) {
},
methods: {
submit() {
uni.showToast({
title: '创建成功',
icon: 'success'
})
setTimeout(() => {
uni.navigateBack();
}, 600)
},
editCarInfo(index) {
bus.$off('updateCarInfo')
bus.$on('updateCarInfo', (carInfo) => {
console.log('Car', carInfo)
if (index) {
this.carList[index] = carInfo
} else {
this.carList.push(carInfo)
}
})
uni.navigateTo({
url: `/pages/myCar/carDetail?car=${index >= 0 ? encodeURIComponent(JSON.stringify(this.carList[index])) : ''}`
})
},
editUserInfo(userInfo) {
bus.$off('updateUserInfo')
bus.$on('updateUserInfo', (userInfo) => {
console.log('userInfo', userInfo)
this.userInfo = userInfo
})
uni.navigateTo({
url: `/pages/userInfo/editUserInfo?userInfo=${userInfo ? encodeURIComponent(JSON.stringify(userInfo)) : ''}`
})
},
addProj(projList = []) {
this.$refs.proj.open(projList)
},
projConfirm(proj) {
this.selectedProj = proj
}
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
background-color: #F3F5F7;
.containerBody {
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(193, 222, 255, 0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
}
.body {
flex: 1;
height: 0;
overflow: auto;
.card {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
margin: 20rpx 32rpx;
}
.phone {
background: #0174F6;
.phoneHeader {
padding: 20rpx 30rpx;
.title {
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
margin-bottom: 10rpx;
}
.desc {
font-weight: 500;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.phoneBody {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
padding: 0 30rpx;
.searchBox {
padding: 40rpx 0;
border-bottom: 1rpx solid #EEEEEE;
}
.btn {
padding: 40rpx 0;
display: flex;
align-items: center;
justify-content: center;
column-gap: 10rpx;
font-weight: 500;
font-size: 32rpx;
color: #0174F6;
.btnIcon {
width: 32rpx;
height: 32rpx;
}
}
}
}
.cardInfo {
&.none {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.cardNoneIcon {
width: 336rpx;
}
.btn {
position: absolute;
bottom: 40rpx;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
column-gap: 10rpx;
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
}
}
}
.projTitle, .userTitle, .carTitle {
padding: 30rpx;
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.carCard {
.carListTab {
display: flex;
align-items: center;
column-gap: 32rpx;
padding: 0 26rpx 22rpx;
.carTabItem {
display: flex;
flex-direction: column;
align-items: center;
row-gap: 10rpx;
font-weight: 500;
font-size: 24rpx;
color: #333333;
&.active {
.carImage {
border: 2rpx solid #0174F6;
}
color: #0174F6;
}
.carImage {
width: 128rpx;
height: 80rpx;
background: #F2F2F7;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
}
}
.carDetail {
background: linear-gradient(180deg, rgba(1, 116, 246, 0.15) 0%, rgba(255, 255, 255, 0) 100%) no-repeat;
background-size: 100% 184rpx;
padding: 30rpx 30rpx 0;
.carHeader {
border-radius: 8rpx 8rpx 8rpx 8rpx;
display: flex;
align-items: center;
column-gap: 20rpx;
padding-bottom: 30rpx;
.carImage {
width: 192rpx;
height: 120rpx;
background: #F2F2F7;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
.carHeaderRight {
display: flex;
flex-direction: column;
row-gap: 20rpx;
font-weight: bold;
font-size: 32rpx;
color: #333333;
.carType {
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
}
}
}
.carBody {
display: flex;
flex-direction: column;
row-gap: 30rpx;
padding-top: 30rpx;
border-top: 1rpx solid #DDDDDD;
}
.carFoot {
}
}
}
.projCard {
.projList {
padding: 0 30rpx;
display: flex;
gap: 20rpx;
flex-wrap: wrap;
.projItem {
padding: 10rpx 16rpx;
border-radius: 4rpx 4rpx 4rpx 4rpx;
border: 2rpx solid #0174F6;
font-weight: 500;
font-size: 24rpx;
color: #0174F6;
}
}
}
.userCard {
.userContainer {
display: flex;
flex-direction: column;
row-gap: 30rpx;
margin: 0 30rpx;
}
}
.infoItem {
display: flex;
flex-direction: column;
.label {
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
}
.value {
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
}
.projFoot, .userFoot, .carFoot {
padding: 30rpx;
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
display: flex;
align-items: center;
justify-content: center;
column-gap: 6rpx;
}
}
.footer {
width: 750rpx;
height: 136rpx;
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
display: flex;
align-items: center;
justify-content: center;
.btn {
width: 510rpx;
height: 76rpx;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>

View File

@ -0,0 +1,163 @@
<template>
<view class="container">
<view class="containerBody">
<VNavigationBar background-color="rgba(0,0,0,0)" title="新建工单" title-color="#333"></VNavigationBar>
<view class="body">
<view class="card phone">
<view class="phoneHeader">
<view class="title">查找手机号</view>
<view class="desc">根据手机号查找/建立客户信息</view>
</view>
<view class="phoneBody">
<view class="searchBox">
<input v-model="phone" placeholder="请输入手机号码" type="tel">
</view>
<view class="btn">
<image class="btnIcon" mode="aspectFit" src="/pages-order/static/search.png"></image>
确认查找
</view>
</view>
</view>
<view class="orderList">
<view v-for="item in orderList" :key="item.id" class="orderItem">
<order-card :order="item"></order-card>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
import OrderCard from "@/components/orderCard.vue";
export default {
components: {
OrderCard,
VNavigationBar,
},
data() {
return {
orderList: [
{
orderNo: '1209840149750105501',
flag: 1, flagStr: '待处理', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
},
{
orderNo: '1209840149750105501',
flag: 1, flagStr: '待处理', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
}
]
}
},
onLoad(data) {
},
methods: {}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
background-color: #F3F5F7;
.containerBody {
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(193, 222, 255, 0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
}
.body {
flex: 1;
height: 0;
overflow: auto;
.card {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
margin: 20rpx 32rpx;
}
.phone {
background: #0174F6;
.phoneHeader {
padding: 20rpx 30rpx;
.title {
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
margin-bottom: 10rpx;
}
.desc {
font-weight: 500;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.phoneBody {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
padding: 0 30rpx;
.searchBox {
padding: 40rpx 0;
border-bottom: 1rpx solid #EEEEEE;
}
.btn {
padding: 40rpx 0;
display: flex;
align-items: center;
justify-content: center;
column-gap: 10rpx;
font-weight: 500;
font-size: 32rpx;
color: #0174F6;
.btnIcon {
width: 32rpx;
height: 32rpx;
}
}
}
}
.orderList {
.orderItem {
margin: 20rpx 32rpx;
}
}
}
}
</style>

View File

@ -1,368 +1,655 @@
<template>
<view class="container">
<view class="containerBody">
<VNavigationBar title="订单详情" background-color="rgba(0,0,0,0)" title-color="#333"></VNavigationBar>
<view class="body" v-if="orderInfo.id">
<view class="orderStatus card">
<template v-if="orderInfo.status === '1'">
<image class="statusIcon" src="@/static/icons/order-icon8.png" mode="aspectFit"></image>
<text>维修中</text>
</template>
<template v-else-if="orderInfo.status === '0'">
<image class="statusIcon" src="@/static/icons/order-icon9.png" mode="aspectFit"></image>
<text>等待维修</text>
</template>
</view>
<view class="reservationOrder card">
<reservationOrder :hideFooter="orderInfo.status === '0'" :order-info="orderInfo" :isDetail="true">
</reservationOrder>
</view>
<view v-if="orderInfo.status !== '0' && !ticketsInfo" class="progress card">
<view v-for="(item, index) in processList" :key="index" class="processItem">
<view class="row1">
<view v-if="item.status !== '3'" class="processIndex">{{ index + 1 }}</view>
<view v-if="item.status === '3'" class="processIndex end">
<uni-icons type="checkmarkempty" color="#fff"></uni-icons>
</view>
<text class="processTitle">{{ item.title }}</text>
</view>
<view class="row2">
<view class="lineBox">
<view v-if="index < processList.length - 1" class="line"></view>
</view>
<view class="row2_body">
<view class="desc">{{item.desc}}</view>
<view class="imageList">
<image class="imageItem" v-for="(img, imgIndex) in item.imageList" :key="imgIndex"
:src="img" mode="aspectFill"></image>
</view>
</view>
</view>
</view>
</view>
<view v-else class="progress card">
<TicketsItem v-if="projects && projects.length > 0" :list="projects" :title='"project"' />
<TicketsItem v-if="wares && wares.length > 0" :list="wares" :title='"wares"' />
<TicketsItem v-if="others && others.length > 0" :list="others" :title='"other"' />
<view class="container">
<view class="containerBody">
<VNavigationBar background-color="#fff" title="工单详情" title-color="#333"></VNavigationBar>
<view class="body">
<view v-if="carInfo" class="card cardInfo carCard">
<view class="orderFlag" :class="{'end': orderInfo.flag == 5}">
<template>
<image style="width: 48rpx;height: 48rpx" v-if="orderInfo.flag == 5" src="/static/icons/orderEnd.png" mode="aspectFit"></image>
<image style="width: 48rpx;height: 48rpx" v-else src="/static/icons/orderIng.png" mode="aspectFit"></image>
<view class="flagBody">
<text>{{ orderInfo.flag == 5 ? '已完成': '待处理' }}</text>
<text class="flagDesc">当前工单维修项目{{ orderInfo.flag == 5 ? '已全部完成' : '正在进行维修' }}</text>
</view>
</template>
</view>
<view class="carTitle">车辆信息</view>
<view class="carDetail">
<view class="carHeader">
<image :src="carInfo.image" class="carImage" mode="aspectFill"></image>
<view class="carHeaderRight">
<text class="carNumber">{{ carInfo.licenseNumber }}</text>
<text class="carType">{{ carInfo.carCategory }}</text>
</view>
</view>
<view class="carBody">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<view class="label">车架号</view>
<view class="value">{{ carInfo.cjNo }}</view>
</view>
<view class="infoItem" style="flex: 1">
<view class="label">发动机号</view>
<view class="value">{{ carInfo.fdjNo }}</view>
</view>
</view>
<template v-if="carInfo.showAll">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<view class="label">年检时间</view>
<view class="value">{{ carInfo.njDate }}</view>
</view>
<view class="infoItem" style="flex: 1">
<view class="label">保险时间</view>
<view class="value">{{ carInfo.bxDate }}</view>
</view>
</view>
<view class="infoItem">
<view class="label">注册日期</view>
<view class="value">{{ carInfo.zcrqDate }}</view>
</view>
</template>
</view>
<view class="carFoot">
<template v-if="!carInfo.showAll">
<text @click="() => $set(carInfo, 'showAll', true)">展开</text>
<image mode="aspectFit" src="/static/icons/bottom.png" style="width: 28rpx;height: 28rpx"></image>
</template>
<template v-else>
<text @click="() => carInfo.showAll = false">收起</text>
<!--<image mode="aspectFit" src="/static/icons/bottom.png" style="width: 28rpx;height: 28rpx"></image>-->
</template>
</view>
</view>
</view>
<view class="reservationInfo card">
<view class="row">
<text class="col1">姓名</text>
<text class="col2">{{orderInfo.userName}}</text>
</view>
<view class="row">
<text class="col1">联系电话</text>
<text class="col2">{{orderInfo.userMobile}}</text>
</view>
<view class="row">
<text class="col1">预约项目</text>
<text class="col2">{{orderInfo.servicePackage.name}}</text>
</view>
<view class="row">
<text class="col1">预约时间</text>
<text class="col2">{{orderInfo.bookingTime}}</text>
</view>
</view>
</view>
<view class="body" v-else-if="ticketsId">
<view class="progress card">
<TicketsItem v-if="projects && projects.length > 0" :list="projects" :title='"project"' />
<TicketsItem v-if="wares && wares.length > 0" :list="wares" :title='"wares"' />
<TicketsItem v-if="others && others.length > 0" :list="others" :title='"other"' />
<view v-if="userInfo" class="card cardInfo userCard">
<view class="userTitle">客户信息</view>
<view class="userContainer">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<text class="label">姓名</text>
<text class="value">{{ userInfo.name }}</text>
</view>
<view class="infoItem" style="flex: 1">
<text class="label">性别</text>
<text class="value">{{ userInfo.sex === '1' ? '女' : '男' }}</text>
</view>
</view>
<template v-if="userInfo.showAll">
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
<text class="label">联系方式</text>
<text class="value">{{ userInfo.phone }}</text>
</view>
<view class="infoItem" style="flex: 1">
<text class="label">出生年月</text>
<text class="value">{{ userInfo.birthday }}</text>
</view>
</view>
<view class="infoItem">
<text class="label">联系地址</text>
<text class="value">
{{ userInfo.provinceName }} {{ userInfo.cityName }} {{ userInfo.areaName }} {{ userInfo.address }}
</text>
</view>
</template>
</view>
<view class="userFoot">
<template v-if="!userInfo.showAll">
<text @click="() => $set(userInfo, 'showAll', true)">展开</text>
<image mode="aspectFit" src="/static/icons/bottom.png" style="width: 28rpx;height: 28rpx"></image>
</template>
<template v-else>
<text @click="() => userInfo.showAll = false">收起</text>
<!--<image mode="aspectFit" src="/static/icons/bottom.png" style="width: 28rpx;height: 28rpx"></image>-->
</template>
</view>
</view>
<view v-if="selectedProj && selectedProj.length > 0" class="card cardInfo projCard">
<view class="projTitle">维修项目</view>
<view class="projList">
<view v-if="role == 'admin'" v-for="item in selectedProj" :key="item.id" class="projItem">
<view class="projTop">
<text class="projName">{{ item.projName }}</text>
<text class="projAmount">${{ item.amount }}</text>
</view>
<view class="projBody">
<view class="projDate">
<image mode="aspectFit" src="/static/icons/date.png" style="width: 24rpx;height: 24rpx"></image>
<text class="projDateText">{{ item.date }}</text>
</view>
<view class="projDesc">
{{ item.desc }}
</view>
<view class="projImg">
<image v-for="(img, imgIndex) in item.imageList" :key="imgIndex" :src="img.filePath"
class="projImgItem"></image>
</view>
<view class="projSend">
<template v-if="item.isSend">
<image mode="aspectFit" src="/static/icons/sendSuccess.png"
style="width: 28rpx;height: 28rpx"></image>
<text style="color: #858BA0">已发送客户</text>
</template>
<template v-else>
<image mode="aspectFit" src="/static/icons/send.png" style="width: 28rpx;height: 28rpx"></image>
<text style="color: #0174F6">发送给客户</text>
</template>
</view>
</view>
</view>
<view v-else v-for="item in selectedProj" :key="item.id" class="projEditItem">
<view class="projEditLine1">
<text>{{ item.projName }}</text>
<text class="projAmount">{{ item.amount }}</text>
</view>
<view class="projBaseInfo">
<view>规格{{'轿车'}}</view>
<view>售价{{'280'}}</view>
<view>数量{{'1'}}</view>
<view>单位{{'辆'}}</view>
<view>折扣{{'10'}}</view>
<view>金额{{'280.00'}}</view>
</view>
<view class="projEditFoot">
<view class="block1">
<template v-if="!orderInfo.salesman || !orderInfo.salesman.id">
<image style="width: 28rpx;height: 28rpx" src="/pages-order/static/addIcon.png"></image>
<text class="addText">添加销售人员</text>
</template>
<template v-else>
<view class="editPeople">
<view class="editForm">
<text class="label">销售人员</text>
<text>{{ orderInfo.salesman.name }}</text>
</view>
<image style="width: 28rpx;height: 28rpx" src="/static/icons/edit.png" @click="editPeople('xs', orderInfo.salesman.id)"></image>
</view>
</template>
</view>
<view class="line"></view>
<view class="block2">
<template v-if="!orderInfo.constructor || !orderInfo.constructor.id">
<image style="width: 28rpx;height: 28rpx" src="/pages-order/static/addIcon.png"></image>
<text class="addText">添加施工人员</text>
</template>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="footer" v-if="['0', '2'].includes(orderInfo.status)">
<view v-if="orderInfo.status === '2'" class="footerBtn" @click="gotoEvaluate">服务评价</view>
<template v-else-if="orderInfo.status === '0'">
<view class="footerBtn phone">
<image class="footerBtnIcon" src="../../static/icons/order-icon7.png" mode="aspectFit"></image>
拨打电话
</view>
<view class="footerBtn address">
<image class="footerBtnIcon" src="../../static/icons/order-icon6.png" mode="aspectFit"></image>地址导航
</view>
</template>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
import reservationOrder from '@/components/reservationOrder/reservationOrder.vue'
import TicketsItem from "@/pages-order/ticketsItem/ticketsItem.vue";
import request from "../../utils/request";
export default {
components: {
VNavigationBar,
reservationOrder,
TicketsItem
},
data() {
return {
// orderInfo: {
// title: '',
// address: '',
// phone: '15726506879',
// busiTypeStr: '15726506879',
// status: '1'
// },
orderInfo: {},
processList: [{
title: '接收车辆',
desc: '车辆已到维修厂,工作人员正准备开始维修',
imageList: ['', '', ''],
status: '1'
},
{
title: '开始维修轮胎',
desc: '工作人员开始对车辆轮胎进行维修',
imageList: [],
status: '2'
},
{
title: '车辆维修完成',
desc: '车辆维修完成,请选择合适时间到店提车',
imageList: [],
status: '3'
}
],
ticketsInfo: {},
projects: [],
wares: [],
others: [],
ticketsId: null
};
},
onLoad(data){
if (data.info){
this.orderInfo = JSON.parse(decodeURIComponent(data.info))
this.ticketsId = this.orderInfo?.ticketsId
}
if (data.ticketsId){
this.ticketsId = data.ticketsId
}
if (this.ticketsId){
this.getTicketsInfo(this.ticketsId)
}
},
methods: {
gotoEvaluate() {
uni.navigateTo({
url: '/pages-order/orderDetail/evaluate'
})
},
async getTicketsInfo(id){
const res = await request({
url: "/userClient/repair/tickets/get?id=" + id,
method: "get"
})
this.ticketsInfo = res.data
this.projects = this.ticketsInfo.items.filter(item => item.project)
this.wares = this.ticketsInfo.items.filter(item => item.ware)
this.others = this.ticketsInfo.items.filter(item => item.other)
}
}
}
import VNavigationBar from '@/components/VNavigationBar.vue'
import request from "../../utils/request";
export default {
components: {
VNavigationBar,
},
data() {
return {
// role: 'admin',
role: 'yewu',
orderId: '',
orderInfo: {
//
salesman: {
name: '魏书豪',
id: '11111'
},
//
constructor: {
name: '',
id: ''
}
},
carInfo: {
licenseNumber: '川A 184AO1',
carCategory: '一汽奥迪 2024款 A6L',
cjNo: '124105112425',
fdjNo: '124109581905',
njDate: '2024年',
bxDate: '2024年',
zcrqDate: '2023-10-20',
image: ''
},
userInfo: {
name: '2其',
sex: '1',
phone: '131111111',
birthday: '2000-01-01',
provinceName: '山东省',
cityName: '泰安市',
areaName: 'xx区',
address: 'xxxxxx'
},
selectedProj: [
{
projName: '清洗内饰',
amount: '280',
date: '2024-10-20 12:00',
desc: '车辆已到维修厂,工作人员正准备开始维修',
imageList: [{filePath: ''}, {filePath: ''}, {filePath: ''}, {filePath: ''}, {filePath: ''}],
isSend: true,
//
examinePart: [],
id: 'projId1'
},
{
projName: '清洗内饰',
amount: '280',
date: '2024-10-20 12:00',
desc: '车辆已到维修厂,工作人员正准备开始维修',
imageList: [{filePath: ''}, {filePath: ''}, {filePath: ''}, {filePath: ''}, {filePath: ''}],
isSend: false,
//
examinePart: [],
id: 'projId1'
}
]
};
},
onLoad(data) {
if (data.id) {
this.orderId = data.id
}
},
methods: {
editPeople(type, id) {
}
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
background-color: #F3F5F7;
.container {
height: 100%;
background-color: #F3F5F7;
.containerBody {
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(193, 222, 255, 0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
}
.containerBody {
height: 100%;
display: flex;
flex-direction: column;
}
.body {
flex: 1;
height: 0;
overflow: auto;
}
.body {
flex: 1;
height: 0;
overflow: auto;
}
.card {
box-sizing: border-box;
width: 686rpx;
margin: 30rpx auto;
}
.card {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
margin: 20rpx 32rpx;
}
.orderStatus {
font-weight: bold;
font-size: 36rpx;
color: #0174F6;
.phone {
background: #0174F6;
display: flex;
align-items: center;
column-gap: 20rpx;
.phoneHeader {
padding: 20rpx 30rpx;
.statusIcon {
width: 48rpx;
height: 48rpx;
}
}
.title {
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
margin-bottom: 10rpx;
}
.reservationOrder {
box-sizing: border-box;
width: 686rpx;
margin: 20rpx auto;
}
.desc {
font-weight: 500;
font-size: 24rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.progress {
padding: 30rpx;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
.phoneBody {
background: #FFFFFF;
border-radius: 8rpx 8rpx 8rpx 8rpx;
padding: 0 30rpx;
display: flex;
flex-direction: column;
row-gap: 20rpx;
.searchBox {
padding: 40rpx 0;
border-bottom: 1rpx solid #EEEEEE;
}
.processItem {
.row1 {
display: flex;
align-items: center;
column-gap: 10rpx;
}
.btn {
padding: 40rpx 0;
.processIndex {
width: 44rpx;
height: 44rpx;
background: #E1EFFF;
border-radius: 22rpx 22rpx 22rpx 22rpx;
display: flex;
align-items: center;
justify-content: center;
column-gap: 10rpx;
font-size: 28rpx;
text-align: center;
color: #0174F6;
line-height: 44rpx;
font-weight: 500;
font-size: 32rpx;
color: #0174F6;
&.end {
background: #0174F6;
}
}
.btnIcon {
width: 32rpx;
height: 32rpx;
}
}
}
}
.processTitle {
font-size: 28rpx;
color: #333333;
line-height: 44rpx;
}
.cardInfo {
&.none {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
.row2 {
display: flex;
align-items: stretch;
column-gap: 10rpx;
.cardNoneIcon {
width: 336rpx;
}
.lineBox {
width: 44rpx;
position: relative;
padding-top: 10rpx;
}
.btn {
position: absolute;
bottom: 40rpx;
left: 50%;
transform: translateX(-50%);
.line {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 2rpx;
height: 100%;
background-color: #0174F6;
}
display: flex;
align-items: center;
column-gap: 10rpx;
.row2_body {
padding-bottom: 20rpx;
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
}
}
}
.desc {
font-size: 24rpx;
color: #858BA0;
margin-bottom: 16rpx;
}
.projTitle, .userTitle, .carTitle {
padding: 30rpx;
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.imageList {
display: flex;
row-gap: 20rpx;
column-gap: 20rpx;
}
.carCard {
.orderFlag {
display: flex;
align-items: center;
column-gap: 14rpx;
padding: 40rpx 30rpx;
background: #FFFBF3;
border-radius: 8rpx 8rpx 0rpx 0rpx;
border-top: 8rpx solid #E8A321;
.imageItem {
width: 120rpx;
height: 120rpx;
background-color: #efefef;
}
}
}
}
}
&.end {
border-top: 8rpx solid #17DBB1;
background-color: #E3FFF9;
}
.flagBody {
display: flex;
flex-direction: column;
row-gap: 10rpx;
font-weight: bold;
font-size: 32rpx;
color: #333333;
.flagDesc {
font-weight: 500;
font-size: 24rpx;
color: #999999;
}
}
.reservationInfo {
padding: 30rpx;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
}
.carDetail {
background-size: 100% 184rpx;
padding: 0 30rpx;
display: flex;
flex-direction: column;
row-gap: 40rpx;
.carHeader {
border-radius: 8rpx 8rpx 8rpx 8rpx;
.row {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
display: flex;
align-items: center;
column-gap: 20rpx;
.col1 {
color: #333333;
}
padding-bottom: 30rpx;
.col2 {
color: #858BA0;
}
}
}
.carImage {
width: 192rpx;
height: 120rpx;
background: #F2F2F7;
border-radius: 8rpx 8rpx 8rpx 8rpx;
}
.footer {
background: #FFFFFF;
border-radius: 0rpx 0rpx 0rpx 0rpx;
padding: 12rpx 32rpx;
.carHeaderRight {
display: flex;
flex-direction: column;
row-gap: 20rpx;
font-weight: bold;
font-size: 32rpx;
color: #333333;
display: flex;
align-items: center;
column-gap: 22rpx;
.carType {
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
}
}
}
.footerBtn {
flex: 1;
width: 0;
height: 76rpx;
margin: 0 auto;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
.carBody {
display: flex;
flex-direction: column;
row-gap: 30rpx;
padding-top: 30rpx;
border-top: 1rpx solid #DDDDDD;
}
font-size: 32rpx;
color: #FFFFFF;
.carFoot {
display: flex;
align-items: center;
justify-content: center;
column-gap: 8rpx;
line-height: 1.5;
}
}
}
&.phone {
background: #E8A321;
}
.projCard {
padding-bottom: 30rpx;
&.address {
.projList {
padding: 0 30rpx;
display: flex;
flex-direction: column;
gap: 20rpx;
}
.projItem {
background: #FFFFFF;
border-radius: 4rpx 4rpx 4rpx 4rpx;
border: 2rpx solid #DDDDDD;
padding: 0 20rpx;
.footerBtnIcon {
width: 32rpx;
height: 32rpx;
}
}
}
}
.projTop {
padding: 20rpx 0;
border-bottom: 1rpx solid #DDDDDD;
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 500;
font-size: 28rpx;
color: #333333;
.projAmount {
font-weight: bold;
color: #0174F6;
}
}
.projBody {
padding-bottom: 20rpx;
.projDate {
font-weight: 500;
font-size: 24rpx;
color: #858BA0;
display: flex;
align-items: center;
column-gap: 10rpx;
padding: 20rpx 0;
}
.projDesc {
font-weight: 500;
font-size: 24rpx;
color: #858BA0;
}
.projImg {
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fill, 120rpx);
justify-content: space-between;
gap: 20rpx;
padding: 20rpx 0;
.projImgItem {
width: 120rpx;
height: 120rpx;
background-color: #efefef;
}
}
.projSend {
display: flex;
align-items: center;
font-weight: 500;
font-size: 28rpx;
column-gap: 8rpx;
}
}
}
.projEditItem {
padding: 0 20rpx;
background: #F2F2F7;
border-radius: 4rpx 4rpx 4rpx 4rpx;
.projEditLine1 {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 500;
font-size: 28rpx;
color: #333333;
padding: 30rpx 0;
.projAmount {
color: #0174F6;
}
}
.projBaseInfo {
display: grid;
grid-template-columns: 1fr 1fr;
font-size: 24rpx;
color: #999999;
gap: 20rpx;
margin-bottom: 20rpx;
}
.projEditFoot {
padding: 30rpx 0;
border-top: 1px solid #DDDDDD;
display: flex;
align-items: center;
column-gap: 10rpx;
.block1, .block2 {
flex: 1;
width: 0;
display: flex;
align-items: center;
justify-content: center;
column-gap: 8rpx;
font-size: 28rpx;
color: #0174F6;
line-height: 28rpx;
.editPeople {
flex: 1;
width: 0;
display: flex;
justify-content: space-between;
align-items: center;
.editForm {
display: flex;
flex-direction: column;
row-gap: 10rpx;
font-size: 28rpx;
color: #333333;
.label {
font-size: 24rpx;
color: #999999;
}
}
}
}
.line {
height: 28rpx;
width: 2rpx;
background-color: #DDDDDD;
}
}
}
}
}
.userCard {
.userContainer {
display: flex;
flex-direction: column;
row-gap: 30rpx;
margin: 0 30rpx;
}
}
.infoItem {
display: flex;
flex-direction: column;
.label {
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
}
.value {
font-weight: 500;
font-size: 28rpx;
color: #333333;
}
}
.projFoot, .userFoot, .carFoot {
padding: 30rpx;
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
display: flex;
align-items: center;
justify-content: center;
column-gap: 6rpx;
}
}
</style>

View File

@ -1,61 +1,24 @@
<template>
<view class="container">
<VNavigationBar titleColor="rgba(0,0,0,0.9)" leftTitle="true" backgroundColor="transparent" title="我的订单">
</VNavigationBar>
<view class="header">
<view class="searchBox">
<input class="searchInput" type="text" placeholder="车牌号查询工单" placeholder-style="font-size: 28rpx">
<text class="searchBtn">搜索</text>
</view>
</view>
<view class="body">
<view class="tabList">
<view @click="changeTabFun(item.id)" v-for="(item, index) in tabList" :key="index" class="tabItem"
:class="{actived: item.id === activeKey}">
<view v-for="(item, index) in tabList" :key="index" :class="{actived: item.id === activeKey}" class="tabItem"
@click="changeTabFun(item.id)">
{{ item.title }}
<view v-if="activeKey === item.id" class="activeLine"></view>
</view>
</view>
<view class="orderList">
<view v-for="(item, index) in orderList" :key="index" class="orderItem">
<view class="line1">
<view class="orderNo">
订单编号{{ item.orderNo }}
</view>
<text class="orderStatus" :class="['status_' + item.status]">
{{ getStatus(item.orderStatus) }}
</text>
</view>
<view class="orderInfo">
<image class="orderInfoIcon" src="@/static/icons/Frame28.png" mode="aspectFit"></image>
<text class="orderInfoText">{{ item.goodsTitle }}</text>
</view>
<view class="orderInfo">
<image class="orderInfoIcon" src="@/static/icons/Frame27.png" mode="aspectFit"></image>
<text class="orderInfoText">{{ item.tenantName | 蓝安-中鑫之宝 }}</text>
</view>
<view class="line2">
<view>
共计
<text class="orderAmountUnit"></text>
<text class="orderAmount">{{ item.payMoney }}</text>
</view>
<text>{{ formatTimestamp(item.createTime) }}</text>
</view>
<view class="line3">
<view v-if="item.orderStatus == '0'" @click="goPay(item)" class="showOrder">支付</view>
<view v-if="item.goodsType == '2'" @click="gotoDetail(item)" class="showOrder">查看订单</view>
<view @click="gotoEvaluate(item)" class="evaluate" v-if="item.goodsType == '2' && item.orderStatus === '1' && !item.commentDesc">评价订单</view>
</view>
<order-card :order="item"></order-card>
</view>
</view>
<uni-popup ref="popup" type="center" border-radius="10px 10px 0 0" @change="popupChange">
<view
style="position: relative;padding: 30rpx;border-radius:20rpx;width: 600rpx;background-color: #fff;display: flex;align-items: center;row-gap: 10rpx;flex-direction: column;">
<canvas style="width:200px; height: 200px;"
canvas-id="myQrcode"></canvas>
<img id="dl-pay-img" style="width: 200px; height: 200px;position: absolute;top: 30rpx;" :key="imageUrl"
:src="imageUrl"/>
<view class="popup-title">长按识别图中二维码支付</view>
</view>
</uni-popup>
</view>
<tabBarVue msg="2"></tabBarVue>
</view>
@ -65,10 +28,11 @@
import request from '../../utils/request';
import VNavigationBar from '@/components/VNavigationBar.vue'
import tabBarVue from '@/components/tabBar/tabBar.vue'
import drawQrcode from 'weapp-qrcode';
import OrderCard from "@/components/orderCard.vue";
export default {
components: {
OrderCard,
tabBarVue,
VNavigationBar
},
@ -79,26 +43,52 @@ export default {
pageNum: 1,
totalPages: 0,
imageUrl: '',
tabList: [{
id: 0,
title: '全部订单'
},
tabList: [
{
id: 0,
title: '待处理'
},
{
id: 1,
title: '维修中'
},
{
id: 2,
title: '待评价'
title: '已完成'
},
],
orderList: [],
orderList: [
{
orderNo: '1209840149750105501',
flag: 1, flagStr: '待处理', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
},
{
orderNo: '1209840149750105501',
flag: 2, flagStr: '已完成', carNum: '川A 184AO1',
carModel: '一汽奥迪 2024款 A6L',
projectList: [
{ name: '清洗内饰', id: 1 },
{ name: '内饰精洗除臭', id: 2 },
{ name: '烘干底板胶及脚垫', id: 3 }
],
userName: '张三',
userPhone: '157****6879',
appointDate: '2024-10-20 12:00',
counselorName: '李相东'
}
],
changeActive: false
}
},
onShow() {
this.orderList = []
this.getList()
// this.orderList = []
// this.getList()
},
onReachBottom() {
if (this.pageNum >= this.totalPages) {
@ -112,19 +102,6 @@ export default {
}
},
methods: {
formatTimestamp(timestamp) {
// Date
const date = new Date(timestamp);
//
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
//
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
async getList() {
let data = {
pageSize: 20,
@ -142,7 +119,7 @@ export default {
default:
break
}
if (this.changeActive){
if (this.changeActive) {
this.orderList = []
}
this.changeActive = false
@ -181,24 +158,24 @@ export default {
params: {orderId: data.id}
}).then((ress) => {
wx.requestPayment({
timeStamp: ress.data.timeStamp, // 19701100:00:00
nonceStr: ress.data.nonceStr, // 32
package: ress.data.package, // prepay_id prepay_id=*
signType: ress.data.signType, // MD5RSA
paySign: ress.data.paySign, //
success: function (res) {
console.log('成功',res);
if( res.errMsg = 'requestPayment:ok'){
uni.showToast({
title:'支付成功'
})
this.getList()
}
// res.errMsg = 'requestPayment:ok'
},
wx.requestPayment({
timeStamp: ress.data.timeStamp, // 19701100:00:00
nonceStr: ress.data.nonceStr, // 32
package: ress.data.package, // prepay_id prepay_id=*
signType: ress.data.signType, // MD5RSA
paySign: ress.data.paySign, //
success: function (res) {
console.log('成功', res);
if (res.errMsg = 'requestPayment:ok') {
uni.showToast({
title: '支付成功'
})
this.getList()
}
// res.errMsg = 'requestPayment:ok'
},
})
})
})
},
@ -222,11 +199,11 @@ export default {
}
},
gotoDetail(row) {
if (row.goodsType === '2'){
if (row.goodsType === '2') {
uni.navigateTo({
url: '/pages-order/orderDetail/orderDetail?ticketsId=' + row.goodsId
})
}else {
} else {
uni.navigateTo({
url: '/pages-order/orderDetail/orderDetail'
})
@ -241,7 +218,7 @@ export default {
}
</script>
<style scoped lang="less">
<style lang="less" scoped>
.container {
height: 100%;
background: #F3F5F7;
@ -249,6 +226,29 @@ export default {
flex-direction: column;
color: #333333;
.header {
padding: 40rpx 32rpx 20rpx;
background-color: #fff;
.searchBox {
background: #F3F5F7;
padding: 20rpx 32rpx;
border-radius: 12rpx 12rpx 12rpx 12rpx;
display: flex;
align-items: center;
column-gap: 12rpx;
.searchInput {
flex: 1;
width: 0;
}
.searchBtn {
font-weight: 500;
font-size: 28rpx;
color: #0174F6;
}
}
}
.body {
flex: 1;
height: 0;
@ -294,92 +294,6 @@ export default {
row-gap: 20rpx;
.orderItem {
padding: 30rpx;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
}
.line1 {
margin-bottom: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 24rpx;
.orderNo {
flex: 1;
width: 0;
font-weight: 500;
color: #858BA0;
}
.status_1 {
color: #0174F6;
}
.status_2 {
color: #999999;
}
}
.orderInfo {
margin-bottom: 20rpx;
display: flex;
align-items: center;
column-gap: 10rpx;
.orderInfoIcon {
width: 28rpx;
height: 28rpx;
}
.orderInfoText {
font-weight: bold;
font-size: 28rpx;
color: #333333;
}
}
.line2 {
margin: 30rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
color: #858BA0;
.orderAmountUnit {
color: #F92C2C;
}
.orderAmount {
color: #F92C2C;
font-weight: bold;
font-size: 40rpx;
}
}
.line3 {
display: flex;
align-items: center;
justify-content: flex-end;
.showOrder, .evaluate {
width: 172rpx;
height: 60rpx;
border-radius: 30rpx 30rpx 30rpx 30rpx;
border: 2rpx solid #0174F6;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #0174F6;
}
.evaluate {
border: 1rpx solid #EEEEEE;
color: #333333;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -1,362 +0,0 @@
<template>
<view class="container">
<view class="body">
<view class="body-top">
<view style="z-index: 2;position: relative;">
<VNavigationBar titleColor="#fff" backgroundColor="rgba(0,0,0,0)">
<template v-slot:back>
<image style="width: 56rpx;height: 56rpx;" src="../../static/icons/backIcon.png"
mode="aspectFit"></image>
</template>
</VNavigationBar>
</view>
<image class="shopImg" src="../static/outImage.jpg" mode="aspectFill"></image>
</view>
<view class="shopBody">
<view class="shopDetail">
<!-- <view class="shopTitle">顺捷汽车维修搭电救援补胎中心</view>-->
<view class="shopTitle">{{ info.corpName }}</view>
<view class="rate">
<view class="rateNumBox">
<text>4.5</text>
<image style="width: 28rpx;height: 28rpx;" src="../../static/icons/rateIcon.png"
mode="aspectFit"></image>
</view>
<text>强烈推荐</text>
</view>
<view class="shopDetailText">
<mote-lines-divide :line="3" expandText="全部" foldHint="收起" v-if="info && info.corpContent">
<text class="shopDetailTextLabel">厂家介绍</text>
<!-- <text class="shopDetailTextValue">-->
<!-- 正安汽车维修服务有限公司成立于1993年10月25日属东莞市成立最早规模最大的民营汽修企业之一现在莞城区及桥头镇开设有二家连锁经营分厂及直属汽车销售部主要从事汽车销售售后-->
<!-- </text>-->
<text class="shopDetailTextValue">
{{ info.corpContent }}
</text>
</mote-lines-divide>
</view>
<view class="shopDetailFooter">
<view class="shopAddress">
<image style="width: 32rpx;height: 32rpx;" src="../../static/icons/order-icon1.png"
mode="aspectFit"></image>
<!-- <text>济南市历下区福瑞达历下护理院东南门旁</text>-->
<text>{{ info.address }}</text>
</view>
<view class="shopPhone">
<image style="width: 32rpx;height: 32rpx;" src="../../static/icons/order-icon2.png"
mode="aspectFit"></image>
<text>电话</text>
</view>
</view>
</view>
<view class="busiDetail">
<!-- <view class="busiDetailTitle">顺捷汽车维修搭电救援补胎中心</view>-->
<view class="busiDetailTitle">{{info.corpName}}</view>
<view class="busiList">
<view v-for="(item, index) in busiList" :key="index" class="busiItem">
<image class="busiTypeImg" :src="item.image" mode="aspectFill"></image>
<view class="busiItemInfo">
<view class="busiItemTitle">{{ item.name }}</view>
<view class="busiItemDesc">{{ item.desc }}</view>
</view>
<!-- <view class="busiItemBtn">查看</view>-->
</view>
</view>
</view>
</view>
</view>
<view class="footer">
<view class="btn" @click="gotoReservation">开始预约</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
import request from "../../utils/request";
import {getToken} from '@/utils/auth.js'
export default {
components: {
VNavigationBar
},
data() {
return {
// busiList: [{
// title: '',
// desc: '',
// image: ''
// }, {
// title: '',
// desc: '',
// image: ''
// }, {
// title: '',
// desc: '',
// image: ''
// }, {
// title: '',
// desc: '',
// image: ''
// }, ]
busiList: [],
info: {}
};
},
onLoad(data) {
this.info = JSON.parse(decodeURIComponent(data.info))
},
onShow() {
this.getServer()
},
methods: {
//
gotoReservation() {
if(getToken()){
uni.navigateTo({
url: '/pages/myReservation/addReservation?info=' + encodeURIComponent(JSON.stringify(this.info))
})
}else{
uni.navigateTo({
url: '/pages/login/login'
})
}
},
//
async getServer() {
const res = await request({
url: "/userClient/base/company/get",
method: 'get',
params: {
id: this.info.id
}
})
this.busiList = res.data.servicePackages
this.busiList.forEach(item => {
item['image'] = require("../static/inImage.jpg")
item['desc'] = this.info.business
})
}
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
display: flex;
flex-direction: column;
background-color: #fff;
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
.body {
flex: 1;
height: 0;
overflow: auto;
}
.body-top {
position: relative;
width: 750rpx;
height: 468rpx;
.shopImg {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: #eee;
}
.back {}
}
.shopBody {
position: relative;
top: -50rpx;
overflow: auto;
padding-bottom: 20rpx;
}
.shopDetail {
position: relative;
z-index: 2;
padding: 30rpx 32rpx;
background: #FFFFFF;
box-shadow: 0rpx 8rpx 16rpx 0rpx rgba(10, 54, 104, 0.1);
border-radius: 32rpx 32rpx 0rpx 0rpx;
.shopTitle {
font-weight: bold;
font-size: 36rpx;
color: #333333;
}
.rate {
margin: 30rpx 0;
box-sizing: border-box;
width: 282rpx;
height: 56rpx;
background: #FFF1DB;
border-radius: 30rpx 30rpx 30rpx 30rpx;
padding-right: 30rpx;
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 500;
font-size: 28rpx;
color: #E8A321;
.rateNumBox {
width: 120rpx;
height: 56rpx;
background: linear-gradient(180deg, #FFD187 0%, #FEB33A 100%);
border-radius: 30rpx 30rpx 30rpx 30rpx;
display: flex;
align-items: center;
justify-content: center;
column-gap: 4rpx;
font-size: 32rpx;
color: #FFFFFF;
line-height: 1.5;
}
}
.shopDetailText {
padding-bottom: 30rpx;
border-bottom: 1rpx solid #EEEEEE;
margin-bottom: 30rpx;
.shopDetailTextLabel {
font-weight: bold;
font-size: 28rpx;
color: #333333;
}
.shopDetailTextValue {
font-size: 28rpx;
color: #666666;
}
}
.shopDetailFooter {
display: flex;
align-items: center;
.shopAddress {
flex: 1;
width: 0;
display: flex;
align-items: center;
column-gap: 8rpx;
font-size: 28rpx;
color: #666666;
border-right: 1rpx solid #EEEEEE;
margin-right: 20rpx;
}
.shopPhone {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
row-gap: 4rpx;
font-size: 24rpx;
color: #333333;
}
}
}
.busiDetail {
padding: 30rpx 32rpx;
background: #FFFFFF;
.busiDetailTitle {
font-weight: bold;
font-size: 36rpx;
color: #333333;
}
.busiList {
.busiItem {
padding: 30rpx 0;
display: flex;
align-items: center;
border-bottom: 1rpx solid #DDDDDD;
column-gap: 20rpx;
}
.busiTypeImg {
width: 112rpx;
height: 112rpx;
background-color: #eee;
}
.busiItemInfo {
flex: 1;
width: 0;
}
.busiItemTitle {
font-size: 28rpx;
color: #333333;
}
.busiItemDesc {
font-size: 24rpx;
color: #858BA0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-break: break-all;
}
.busiItemBtn {
width: 100rpx;
height: 48rpx;
background: #0174F6;
border-radius: 24rpx 24rpx 24rpx 24rpx;
font-size: 28rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.footer {
padding: 12rpx;
background: #FFFFFF;
box-shadow: 0rpx -8rpx 16rpx 0rpx rgba(10, 54, 104, 0.1);
border-radius: 0rpx 0rpx 0rpx 0rpx;
position: relative;
.btn {
width: 510rpx;
height: 76rpx;
margin: 0 auto;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #FFFFFF;
}
}
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 KiB

View File

@ -1,177 +1,121 @@
{
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
},
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/my",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myReservation/myReservation",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myCar/myCar",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/myInfo",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myCar/carDetail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/myEquity",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/register",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myReservation/addReservation",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/message",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/cardRoll",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myReservation/reservationSuccess",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/guideList/guideList",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/guideList/guideDetail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/login/bindPhoe",
"style": {
"navigationBarTitleText": ""
}
}
],
"subPackages": [
{
"root": "pages-order",
"pages": [
{
"path": "orderList/orderList",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "orderDetail/evaluate",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "orderDetail/orderDetail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "my/evaluate",
"style": {
"navigationBarTitleText": ""
}
}
]
},
{
"root": "pages-shop",
"pages": [
{
"path": "shopDetail/shopDetail",
"style": {
"navigationBarTitleText": ""
}
}
]
},
{
"root": "pages-home",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "home/active",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "home/content",
"style": {
"navigationBarTitleText": ""
}
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom"
},
"uniIdRouter": {}
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
"pages": [
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
},
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/my",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/myInfo",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/myCar/carDetail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/register",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/message",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/my/cardRoll",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/login/bindPhoe",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/userInfo/editUserInfo",
"style": {
"navigationBarTitleText": ""
}
}
],
"subPackages": [
{
"root": "pages-order",
"pages": [
{
"path": "orderList/orderList",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "addOrder/addOrder"
},
{
"path": "appointOrder/appointOrder"
},
{
"path": "orderDetail/orderDetail"
}
]
},
{
"root": "pages-home",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "home/active",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "home/content",
"style": {
"navigationBarTitleText": ""
}
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"navigationStyle": "custom"
},
"uniIdRouter": {}
}

View File

@ -1,47 +0,0 @@
<template>
<view class="container">
<VNavigationBar background-color="rgba(0,0,0,0)" title-color="rgba(0,0,0,0)"></VNavigationBar>
<view class="body">
<view class="title">如何在小程序上下单车辆维修</view>
<view class="content"></view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
export default {
components: {
VNavigationBar
},
data() {
return {
};
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
display: flex;
flex-direction: column;
background-color: #f1f1f1;
.body {
background-color: #fff;
flex: 1;
height: 0;
margin: 32rpx;
padding: 30rpx;
display: flex;
flex-direction: column;
row-gap: 20rpx;
.title {
text-align: center;
}
}
}
</style>

View File

@ -1,75 +0,0 @@
<template>
<view class="container">
<v-navigation-bar title="操作指南" background-color="#fff" title-color="#333"></v-navigation-bar>
<view class="body">
<view @click="gotoDetail(item)" v-for="(item,index) in data" :key="index" class="guideItem">
<text class="guide_content">如何在小程序上下单车辆维修</text>
<image class="guideIcon" src="../../static/icons/homeInfoMore.png" mode="aspectFit"></image>
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
export default {
components: {
VNavigationBar
},
data() {
return {
data: [{}, {}]
};
},
methods: {
gotoDetail() {
uni.navigateTo({
url: '/pages/guideList/guideDetail'
})
}
}
}
</script>
<style lang="less" scoped>
.container {
background-color: #F3F5F7;
height: 100%;
display: flex;
flex-direction: column;
.body {
flex: 1;
height: 0;
padding: 0 0 20rpx;
display: flex;
flex-direction: column;
.guideItem {
margin: 20rpx 32rpx 0;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
padding: 40rpx 30rpx;
display: flex;
align-items: center;
column-gap: 10rpx;
font-size: 32rpx;
color: #333333;
.guide_content {
flex: 1;
width: 0;
}
.guideIcon {
width: 24rpx;
height: 24rpx;
}
}
}
}
</style>

View File

@ -1,86 +1,121 @@
<template>
<view class="container">
<VNavigationBar title="车辆详情" background-color="#fff" title-color="#333"></VNavigationBar>
<VNavigationBar :title="pageTitle" background-color="#fff" title-color="#333"></VNavigationBar>
<view class="body">
<view class="card">
<view class="formItem">
<text class="formLabel">车牌号</text>
<input type="text" style="text-align: right" placeholder="请输入文本" v-model="car.licenseNumber"/>
<u-form labelPosition="top">
<view class="card">
<u-form-item borderBottom label="上传图片" labelWidth="200">
<u-upload></u-upload>
</u-form-item>
<u-form-item borderBottom label="车牌号" labelWidth="200" @click="carInputClick(); hideKeyboard()">
<u-input
v-model="car.licenseNumber"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请输入车牌号"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
<u-form-item label="车辆型号" labelWidth="200" @click="showType = true; hideKeyboard()">
<u-input
v-model="car.carCategory"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择车辆型号"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
</view>
<view class="formItem">
<text class="formLabel">品牌</text>
<picker @change="brandChange" :value="brandIndex" :range="brandNamesComputed">
<view class="uni-input">{{ brandNamesComputed[brandIndex] }}</view>
</picker>
</view>
<view class="formItem">
<text class="formLabel">型号</text>
<input type="text" style="text-align: right" placeholder="请输入文本" v-model="car.carModelInput"/>
</view>
<view class="formItem">
<text class="formLabel">车辆类别</text>
<picker @change="categoryChange" :value="categoryIndex" :range="categoryNamesComputed">
<view class="uni-input">{{ categoryNamesComputed[categoryIndex] }}</view>
</picker>
</view>
<view class="formItem">
<text class="formLabel">车辆性质</text>
<picker @change="natureChange" :value="natureIndex" :range="natureNamesComputed">
<view class="uni-input">{{ natureNamesComputed[natureIndex] }}</view>
</picker>
</view>
<view class="formItem">
<text class="formLabel">注册日期</text>
<picker
mode="date"
:value="car.carRegisterDate"
start="2020-01-01"
end="2030-12-31"
@change="bindDateChange1">
<view style="margin-left: 10rpx">
{{ car.carRegisterDate}}
</view>
</picker>
</view>
<!-- <view class="formItem">-->
<!-- <text class="formLabel">车辆图片</text>-->
<!-- <u-upload-->
<!-- :action="uploadUrl"-->
<!-- :headers="headers"-->
<!-- :file-list="fileList"-->
<!-- :max-count="3"-->
<!-- :show-upload-btn="true"-->
<!-- @after-read="afterRead"-->
<!-- @delete="deleteFile"-->
<!-- @success="uploadSuccess"-->
<!-- @fail="uploadFail"-->
<!-- ></u-upload>-->
<view class="card">
<u-form-item borderBottom label="车架号" labelWidth="200">
<u-input v-model="car.cjNo" border="none" placeholder="请输入车架号"></u-input>
</u-form-item>
<u-form-item borderBottom label="发动机号" labelWidth="200">
<u-input v-model="car.fdjNo" border="none" placeholder="请输入发动机号"></u-input>
</u-form-item>
<u-form-item borderBottom label="年检时间" labelWidth="200" @click="openDatePicker('nj'); hideKeyboard()">
<u-input
v-model="car.njDate"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择年检时间"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
<u-form-item borderBottom label="保险时间" labelWidth="200" @click="openDatePicker('bx'); hideKeyboard()">
<u-input
v-model="car.bxDate"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择保险时间"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
<u-form-item label="注册日期时间" labelWidth="200" @click="openDatePicker('zcrq'); hideKeyboard()">
<u-input
v-model="car.zcrqDate"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择注册日期时间"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
</view>
</u-form>
<!-- </view>-->
</view>
<!-- 车辆型号 -->
<u-action-sheet
:actions="typeList"
:show="showType"
title="请选择车辆型号"
@close="showType = false"
@select="typeSelect"
>
</u-action-sheet>
<keyboard-plate ref="plateNumber" :plateNum.sync='car.licenseNumber' isShow
@change="getPlateNum"></keyboard-plate>
<u-datetime-picker
v-model="datePickerValue"
:formatter="formatter"
:show="datePickerShow"
mode="date"
@cancel="datePickerCancel"
@confirm="datePickerConfirm"
></u-datetime-picker>
</view>
<view class="footer">
<view class="btnItem edit" @click="submit" v-if="bo2">
<view class="btnItem edit" @click="submit">
确定
</view>
<view class="btnItem delete" v-if="bo1" @click="del">
<uni-icons type="trash" color="#F92C2C"></uni-icons>
删除
</view>
<view class="line" v-if="bo1"></view>
<view class="btnItem edit" v-if="bo1" @click="update">
<uni-icons type="compose" color="#0174F6"></uni-icons>
保存
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue';
import request from "../../utils/request";
import {bus} from "@/utils/eventBus";
export default {
components: {
@ -88,52 +123,37 @@ export default {
},
data() {
return {
// uploadUrl: 'https://your-server.com/upload',
// headers: {},
// fileList: [],
pageTitle: '',
car: {
//
licenseNumber: '',
//
carModelInput: '',
// id
carBrand:'',
carBrand: '',
//
carCategory:'',
carCategory: '',
//
carNature:'',
carNature: '',
//
carRegisterDate:'2024-09-24',
carRegisterDate: '2024-09-24',
},
bo1: false,
bo2: true,
categoryIndex: 0,
natureIndex: 0,
brandIndex: 0,
categoryList: [],
natureList: [],
brandList: []
datePickerShow: false,
datePickerValue: new Date().getTime(),
pickerConfirmField: 'njDate',
showType: false,
typeList: [
{
name: '一汽奥迪 2024款 A6L',
value: '1'
},
],
};
},
//
computed: {
// picker range
brandNamesComputed() {
return this.brandList.map(item => item.brandName);
},
natureNamesComputed() {
return this.natureList.map(item => item.label);
},
categoryNamesComputed() {
return this.categoryList.map(item => item.label);
}
},
onLoad(options) {
//
if (options.car) {
@ -142,169 +162,75 @@ export default {
console.log('初始化页面数据', this.car)
this.bo1 = true;
this.bo2 = false;
this.pageTitle = '修改车辆信息'
} else {
//
this.bo1 = false;
this.bo2 = true;
this.pageTitle = '添加车辆信息'
}
//
this.getCategoryList();
this.getNatureList();
this.getBrandList();
},
methods: {
// afterRead(file) {
// console.log('');
// },
// deleteFile(file, index) {
// console.log('');
// this.fileList.splice(index, 1);
// },
// uploadSuccess(res, file) {
// console.log('', res);
// },
// uploadFail(error, file) {
// console.log('', error);
// },
//
brandChange(event) {
//
const newIndex = event.detail.value;
this.brandIndex = newIndex;
//
this.car.carBrand = this.brandList[newIndex].id;
},
//
categoryChange(event) {
const newIndex = event.detail.value;
this.categoryIndex = newIndex;
//
this.car.carCategory = this.categoryList[newIndex].value;
},
//
natureChange(event) {
const newIndex = event.detail.value;
this.natureIndex = newIndex;
//
this.car.carNature = this.natureList[newIndex].value;
typeSelect(e) {
console.log('e', e)
},
//
bindDateChange1(e) {
this.car.carRegisterDate = e.target.value; // datadate
//
carInputClick() {
this.$refs.plateNumber.open();
},
getPlateNum(e) {
},
//
async getCategoryList() {
let res = await request({
url: '/admin-api/system/dict-data/type?type=car_category',
method: 'get',
noTenantId: false
})
if (res.code == 200) {
console.log('车辆类别', res.data)
this.categoryList = res.data;
if (this.bo2 == true){
this.car.carCategory = res.data[0].value;
}
else {
// index
this.categoryList.forEach((item, index) => {
if (item.value == this.car.carCategory) {
this.categoryIndex = index;
}
})
}
openDatePicker(picker) {
if (picker === 'nj') {
this.pickerConfirmField = 'njDate'
} else if (picker === 'bx') {
this.pickerConfirmField = 'bxDate'
} else if (picker === 'zcrq') {
this.pickerConfirmField = 'zcrqDate'
}
this.datePickerShow = true
},
//
async getNatureList() {
let res = await request({
url: '/admin-api/system/dict-data/type?type=car_nature',
method: 'get',
noTenantId: false
})
if (res.code == 200) {
console.log('车辆性质', res.data)
this.natureList = res.data;
if (this.bo2 == true){
this.car.carNature = res.data[0].value;
}
else {
// index
this.natureList.forEach((item, index) => {
if (item.value == this.car.carNature) {
this.natureIndex = index;
}
})
}
}
datePickerConfirm({value}, field, picker) {
const date = new Date(value)
this.car[this.pickerConfirmField] = date.getFullYear() + '-' + (Number(date.getMonth()) + 1 + '').padStart(2, '0') + '-' + (date.getDate() + '').padStart(2, '0')
this.datePickerCancel(picker)
},
//
async getBrandList() {
let res = await request({
url: '/userClient/base/carBrand/list',
method: 'get',
})
if (res.code == 200) {
console.log('车辆品牌', res.data)
this.brandList = res.data;
if (this.bo2 == true){
this.car.carBrand= res.data[0].id;
}else {
// index
this.brandList.forEach((item, index) => {
if (item.id == this.car.carBrand) {
this.brandIndex = index;
}
})
}
datePickerCancel(picker) {
this.datePickerValue = new Date().getTime()
this.datePickerShow = false
},
formatter(type, value) {
if (type === 'year') {
return `${value}`
}
if (type === 'month') {
return `${value}`
}
if (type === 'day') {
return `${value}`
}
console.log('for value', value)
return value
},
//
async submit() {
let res = await request({
url: '/userClient/base/myCar/create',
method: 'POST',
data: this.car,
})
if (res.code == 200) {
//
uni.navigateBack();
}
bus.$emit('updateCarInfo', this.car)
uni.navigateBack();
// let res = await request({
// url: '/userClient/base/myCar/create',
// method: 'POST',
// data: this.car,
// })
// if (res.code == 200) {
// //
// bus.$emit('updateCarInfo', res.result)
// uni.navigateBack();
// }
},
//
async del() {
let res = await request({
url: `/userClient/base/myCar/delete?id=${this.car.id}`,
method: 'Delete',
})
if (res.code == 200) {
//
uni.navigateBack();
}
},
//
async update() {
let res = await request({
url: `/userClient/base/myCar/update`,
data: this.car,
method: 'Put',
})
if (res.code == 200) {
}
}
}
}
</script>
@ -325,63 +251,9 @@ export default {
overflow: auto;
.card {
margin: 20rpx 0;
padding: 0 32rpx;
margin: 20rpx 30rpx;
padding: 0 30rpx;
background-color: #fff;
.formItem {
box-sizing: border-box;
width: 686rpx;
margin: 0 auto;
padding: 40rpx;
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 20rpx;
border-bottom: 1rpx solid #dddddd;
&:last-child {
border: none;
}
}
.labelVal {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 20rpx;
}
.formLabel {
font-size: 32rpx;
color: #333333;
}
.formValue {
flex: 1;
width: 0;
text-align: right;
font-size: 32rpx;
color: #999999;
}
.carImg {
width: 240rpx;
height: 150rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
background-color: #efefef;
}
.formImg {
margin-top: 30rpx;
width: 240rpx;
height: 150rpx;
border-radius: 12rpx 12rpx 12rpx 12rpx;
background-color: #efefef;
}
}
}
@ -389,30 +261,21 @@ export default {
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
.line {
width: 2rpx;
background-color: #dddddd;
}
padding: 30rpx 0;
.btnItem {
flex: 1;
width: 0;
padding: 34rpx 0;
display: flex;
align-items: center;
justify-content: center;
width: 510rpx;
height: 76rpx;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
font-size: 32rpx;
color: #FFFFFF;
&.delete {
color: #f92c2c;
}
&.edit {
color: #0174f6;
}
line-height: 76rpx;
text-align: center;
}
}
}

View File

@ -1,601 +0,0 @@
<template>
<view class="container">
<VNavigationBar background-color="rgba(0,0,0,0)" title-color="#333" title="提交预约"></VNavigationBar>
<view class="body">
<view class="carInfo">
<view class="cardInfoHeader">
<view class="carInfoLeftTop">
<image class="carInfoLeftTopIcon" src="../../static/icons/order-icon10.png" mode="widthFix">
</image>
车辆信息
</view>
<view class="carInfoRightTop">
<!-- <uni-icons type="compose" color="#0174F6"></uni-icons> -->
<span style="color: #0174F6;" @click="selectCar">选择车辆</span>
</view>
</view>
<view class="cardInfoBody">
<view class="cardInfoBody_content">
<view class="carForm">
<view class="carForm_num">车牌号{{car.licenseNumber}}</view>
<view class="carForm_carName">车辆持有人{{cusInfo.cusName}}</view>
<view class="carForm_carPhone">持有人电话{{cusInfo.phoneNumber}}</view>
</view>
<image class="carImg" src="" mode="aspectFill" :src="config.baseImageUrl + car.logoImg"></image>
</view>
<view class="cardInfoBody_footer">
<view class="nj">
年检时间<text class="date">{{car.insuranceDate || '未获取到'}}</text>
<image class="cardInfoBody_footerIcon" src="../../static/icons/icon2.png" mode="aspectFit">
</image>
</view>
<view class="bx">
保险时间<text class="date">{{car.nextInspectionDate || '未获取到'}}</text>
<image class="cardInfoBody_footerIcon" src="../../static/icons/icon2.png" mode="aspectFit">
</image>
</view>
</view>
</view>
</view>
<view class="baseInfo">
<view class="formItem">
<view class="formItem_content">
<view class="label">姓名</view>
<input class="formItemInput" placeholder="请输入姓名" type="text" v-model="formData.userName" />
</view>
</view>
<view class="formItem">
<view class="formItem_content">
<view class="label">联系电话</view>
<input class="formItemInput" placeholder="请输入联系电话" type="text" v-model="formData.userMobile"/>
</view>
</view>
<view class="formItem">
<!-- <picker mode="selector" :range="['汽车维修']" @change="">
<view class="formItem_content">
<view class="label">预约项目</view>
<input disabled class="formItemInput" placeholder="请选择预约项目" type="text" />
<image class="formItemBtn" src="../../static/icons/homeInfoMore.png" mode="aspectFit">
</image>
</view>
</picker> -->
<view class="formItem_content" @click="selectServer">
<view class="label">预约项目</view>
<input disabled class="formItemInput" placeholder="请选择预约项目" type="text" v-model="service.name" />
<image v-if="!service.name" class="formItemBtn" src="../../static/icons/homeInfoMore.png" mode="aspectFit">
</image>
</view>
</view>
</view>
<view class="dateCard">
<view class="cardTitle">预约时间</view>
<view class="datePicker">
<view v-for="(date, index) in dateList" :key="date.date" class="dateItem"
:class="{active: chooseDate === date.date, disabled: date.disabled}"
@click="chooseDateFun(date)">
<text>{{date.date}}</text>
<text>{{date.title}}</text>
<image v-if="chooseDate === date.date" class="activeIcon"
src="../../static/icons/order-icon11.png" mode="aspectFit"></image>
</view>
</view>
<view class="timerPicker">
<view v-for="(time, index) in timeList" :key="index" class="timeItem"
:class="{active: chooseTime === time.time, disabled: time.disabled}"
@click="chooseTimeFun(time)">
<text>{{time.time}}</text>
<image v-if="chooseTime === time.time" class="activeIcon"
src="../../static/icons/order-icon11.png" mode="aspectFit"></image>
</view>
</view>
</view>
</view>
<view class="footer">
<view class="footerBtn" @click="submit">提交预约</view>
</view>
</view>
</template>
<script>
import request from '../../utils/request';
import VNavigationBar from '@/components/VNavigationBar.vue'
import config from "@/config";
import {getUserInfoRequest} from "@/utils/common.js";
import {getToken,getUserInfo} from '@/utils/auth.js'
export default {
components: {
VNavigationBar,
},
computed: {
config() {
return config
}
},
data() {
return {
// dateList: [{
// date: '06-05',
// title: '',
// disabled: true
// }, {
// date: '06-06',
// title: '',
// disabled: false
// }, {
// date: '06-07',
// title: '',
// disabled: false
// }, {
// date: '06-08',
// title: '',
// disabled: false
// }, {
// date: '06-09',
// title: '',
// disabled: false
// }, ],
dateList:[],
chooseDate: '06-06',
chooseTime: '11:00',
timeList: [{
time: '09:00',
disabled: false
},
{
time: '11:00',
disabled: false
},
{
time: '14:00',
disabled: false
},
{
time: '15:00',
disabled: false
},
{
time: '16:00',
disabled: false
},
{
time: '17:00',
disabled: false
},
],
carList: [],
car:{},
cusInfo: {},
formData:{
userName: null,
userMobile: null,
projectId: null,
carId: null,
carNo: null,
bookingTime: null,
corpId: null
},
serviceList: [],
service:{},
info: {}
};
},
onLoad(data){
this.info = JSON.parse(decodeURIComponent(data.info))
this.formData.corpId = this.info.id
this.getServer(this.info.id)
},
onShow() {
if(!getToken()){
uni.reLaunch({
url: '/pages/login/login'
})
}else{
console.log("已登录")
this.getUserInfos()
}
this.initCarList()
this.initDateList()
},
methods: {
//
async getUserInfos() {
console.log("获取用户信息")
getUserInfo()
},
initDateList(){
const daysOfWeek = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const currentDate = new Date();
const weekDates = [];
// 01
const todayDayOfWeek = currentDate.getDay();
//
currentDate.setDate(currentDate.getDate() - todayDayOfWeek);
for (let i = 0; i < 7; i++) {
// 'MM-DD'
let dateStr = `${currentDate.getMonth() + 1}-${currentDate.getDate()}`;
//
let title = daysOfWeek[currentDate.getDay()];
// disabledtruedisabledfalse
let disabled = currentDate < new Date(); //
//
weekDates.push({ date: dateStr, title, disabled });
//
currentDate.setDate(currentDate.getDate() + 1);
}
//
this.chooseDate = weekDates.find(day => day.disabled === false).date;
this.dateList = weekDates;
},
chooseTimeFun(time) {
if (time.disabled) {
return
}
this.chooseTime = time.time
},
chooseDateFun(date) {
if (date.disabled) {
return
}
this.chooseDate = date.date
},
submit() {
this.formData.bookingTime = new Date((new Date().getFullYear() + "-" + this.chooseDate + " " + this.chooseTime + ":00")).getTime()
request({
url: "/userClient/repair/booking/update",
method: "post",
data: this.formData
}).then(res => {
uni.redirectTo({
url: '/pages/myReservation/reservationSuccess?info=' + encodeURIComponent(JSON.stringify(this.info))
})
}).catch(() => {})
},
async initCarList() {
const res = await request({
url: "/userClient/base/myCar/get",
method: "get"
})
this.carList = res.data
if(this.carList && this.carList.length > 0){
this.car = this.carList[0]
this.formData.carId = this.car.id
this.formData.carNo = this.car.licenseNumber
this.selectCusInfo(this.car.id)
}
},
//
selectCar() {
const carNos = this.carList.map(item => item.licenseNumber)
uni.showActionSheet({
itemList: carNos,
success: (res) => {
this.car = this.carList[res.tapIndex]
this.formData.carId = this.car.id
this.formData.carNo = this.car.licenseNumber
this.selectCusInfo(this.car.id)
},
fail: (err) => {
console.error('选择框显示失败:', err);
}
});
},
//
async selectCusInfo(carId){
const res = await request({
url: "/userClient/customer/getByCarId?carId=" + carId,
method: "get"
})
this.cusInfo = res.data
this.formData.userName = this.cusInfo.userName
this.formData.userMobile = this.cusInfo.userMobile
},
//
async getServer(corpId) {
const res = await request({
url: "/userClient/base/company/get",
method: 'get',
params: {
id: corpId
}
})
this.serviceList = res.data.servicePackages
},
//
selectServer(){
const servers = this.serviceList.map(item => item.name)
uni.showActionSheet({
itemList: servers,
success: (res) => {
this.service = this.serviceList[res.tapIndex]
this.formData.projectId = this.service.id
this.info.serviceName = this.service.name
},
fail: (err) => {
console.error('选择框显示失败:', err);
}
});
}
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(193, 222, 255, 0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
}
.body {
flex: 1;
height: 0;
overflow: auto;
background: linear-gradient(180deg, rgba(193, 222, 255, 0) 0%, #F3F5F7 50%, #F3F5F7 100%);
.carInfo {
margin: 20rpx 32rpx 30rpx;
background: #022B9A;
box-shadow: 0rpx 8rpx 16rpx 0rpx rgba(10, 54, 104, 0.1);
border-radius: 16rpx 16rpx 16rpx 16rpx;
overflow: hidden;
.cardInfoHeader {
display: flex;
align-items: stretch;
}
.carInfoLeftTop {
display: flex;
align-items: center;
column-gap: 10rpx;
padding: 20rpx;
color: #fff;
.carInfoLeftTopIcon {
width: 36rpx;
}
}
.carInfoRightTop {
flex: 1;
width: 0;
background-color: #fff;
text-align: right;
padding-right: 20rpx;
display: flex;
align-items: center;
justify-content: flex-end;
border: 10rpx;
clip-path: polygon(20rpx 0, 100% 0, 100% 0, 100% 100%, 100% 100%, 0 100%, 10rpx 10rpx);
}
.cardInfoBody {
padding: 30rpx;
background-color: #fff;
border-radius: 16rpx 0rpx 0 0;
}
.cardInfoBody_content {
display: flex;
align-items: stretch;
column-gap: 32rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx dashed #858BA0;
.carForm {
padding: 10rpx 0;
display: flex;
flex-direction: column;
justify-content: space-between;
font-weight: 500;
font-size: 28rpx;
color: #858BA0;
flex: 1;
width: 0;
}
.carForm_num {
font-weight: bold;
font-size: 36rpx;
color: #333333;
}
.carImg {
width: 240rpx;
height: 150rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
background-color: #efefef;
}
}
.cardInfoBody_footer {
display: flex;
align-items: center;
font-weight: 500;
font-size: 28rpx;
color: #333333;
padding-top: 20rpx;
.nj {
border-right: 1rpx solid #ddd;
margin-right: 20rpx;
}
.nj,
.bx {
flex: 1;
width: 0;
display: flex;
align-items: center;
column-gap: 10rpx;
}
.date {
color: #0174F6;
}
.cardInfoBody_footerIcon {
width: 28rpx;
height: 28rpx;
}
}
}
.baseInfo {
margin: 20rpx 32rpx 30rpx;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
padding: 0 30rpx;
font-weight: 500;
font-size: 28rpx;
color: #333333;
.formItem {
padding: 40rpx 0;
border-bottom: 1rpx solid #EEEEEE;
&:last-child {
border: none;
}
}
.formItem_content {
display: flex;
align-items: center;
column-gap: 10rpx;
}
.formItemInput {
flex: 1;
width: 0;
text-align: right;
}
.formItemBtn {
width: 24rpx;
height: 24rpx;
}
}
.dateCard {
margin: 20rpx 32rpx 30rpx;
padding: 22rpx 30rpx;
background: #FFFFFF;
border-radius: 16rpx 16rpx 16rpx 16rpx;
.cardTitle {
font-weight: bold;
font-size: 28rpx;
color: #333333;
}
.datePicker {
display: flex;
column-gap: 20rpx;
overflow: auto;
padding: 30rpx 0;
border-bottom: 1rpx solid #EEEEEE;
.dateItem {
padding: 20rpx 40rpx;
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 1rpx solid rgba(0, 0, 0, 0.1);
font-size: 24rpx;
color: #666666;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
}
.timerPicker {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20rpx;
padding-top: 30rpx;
.timeItem {
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 1rpx solid rgba(0, 0, 0, 0.1);
padding: 30rpx 0;
text-align: center;
}
}
.timeItem,
.dateItem {
position: relative;
overflow: hidden;
&.active {
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 2rpx solid #0174F6;
color: #0174F6;
}
&.disabled {
border-radius: 8rpx 8rpx 8rpx 8rpx;
border: 1rpx solid rgba(0, 0, 0, 0.1);
color: rgba(51, 51, 51, 0.4);
}
.activeIcon {
position: absolute;
right: 0;
top: 0;
width: 36rpx;
height: 24rpx;
}
}
}
}
.footer {
background: #FFFFFF;
padding: 12rpx 0;
padding-bottom: calc(12rpx + env(safe-area-inset-bottom));
.footerBtn {
width: 80%;
margin: 0 auto;
padding: 22rpx 0;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
}
}
</style>

View File

@ -1,123 +0,0 @@
<template>
<view class="container">
<VNavigationBar titleColor="rgba(0,0,0,0.9)" backgroundColor="transparent" title="我的预约">
</VNavigationBar>
<view class="body">
<scroll-view style="height: 100%;" scroll-y="true">
<view class="orderList">
<reservationOrderVue v-for="(item, index) in orderList" :key="index" :orderInfo="item">
</reservationOrderVue>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
import tabBarVue from '@/components/tabBar/tabBar.vue'
import reservationOrderVue from '../../components/reservationOrder/reservationOrder.vue'
import request from "@/utils/request";
import {getUserInfoRequest} from "@/utils/common.js";
import {getToken,setUserInfo} from '@/utils/auth.js'
export default {
components: {
tabBarVue,
VNavigationBar,
reservationOrderVue
},
data() {
return {
// orderList: [{
// title: '',
// status: '1',
// address: '',
// phone: '15726506879',
// busiTypeStr: ''
// },
// {
// title: '',
// status: '1',
// address: '',
// phone: '15726506879',
// busiTypeStr: ''
// }
// ]
orderList:[]
}
},
onShow() {
if(!getToken()){
uni.reLaunch({
url: '/pages/login/login'
})
}else{
console.log("已登录")
this.getUserInfos()
}
this.getBookingPage()
},
methods: {
//
async getUserInfos() {
getUserInfoRequest()
},
async getBookingPage(){
const res = await request({
url: "/userClient/repair/booking/page",
method: "get",
params:{
pageNo: 1,
pageSize: 10
}
})
const data = res.data.records
const ids = data.map(item => item.id)
const response = await request({
url: "/userClient/repair/booking/map?ids=" + ids,
method: "get",
})
const list = response.data
this.orderList = list.map(item => {
return {
...item,
title: item.company.corpName,
address: item.company.address,
phone: item.company.mobilePhone,
busiTypeStr: item.servicePackage.name,
status: item.bookingStatus
}
})
}
}
}
</script>
<style scoped lang="less">
.container {
height: 100%;
background: #F3F5F7;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(#F3F5F7, 0) 100%);
background-size: 100% 600rpx;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
color: #333333;
.body {
flex: 1;
height: 0;
padding: 16rpx 0 30rpx;
overflow: auto;
}
.orderList {
width: 686rpx;
margin: 0 auto;
display: flex;
flex-direction: column;
row-gap: 20rpx;
}
}
</style>

View File

@ -1,171 +0,0 @@
<template>
<view class="container">
<v-navigation-bar background-color="rgba(0,0,0,0)" title-color="#333" title="预约成功"></v-navigation-bar>
<view class="body">
<view class="card">
<view class="success">
<image class="successIcon" src="../../static/icons/success.png" mode="aspectFit"></image>
<text>预约成功</text>
</view>
<view class="orderInfo">
<!-- <view class="shopName">顺捷汽车维修搭电救援补胎中心</view> -->
<view class="shopName">{{info.corpName}}</view>
<view class="baseInfo">
<image class="baseInfoIcon" src="../../static/icons/order-icon1.png" mode=""></image>
<!-- 济南市历下区福瑞达历下护理院东南门旁 -->
{{info.address}}
</view>
<view class="baseInfo">
<image class="baseInfoIcon" src="../../static/icons/order-icon2.png" mode=""></image>
<!-- 15726506879 -->
{{info.mobilePhone}}
</view>
<view class="baseInfo">
<image class="baseInfoIcon" src="../../static/icons/order-icon3.png" mode=""></image>
<!-- 汽车维修 -->
{{info.serviceName || "维修"}}
</view>
</view>
</view>
<view class="footer">
<view class="showOrder" @click="showOrder">查看订单</view>
<view class="back" @click="back">完成</view>
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
export default {
components: {
VNavigationBar,
},
data() {
return {
info: {}
};
},
onLoad(data) {
this.info = JSON.parse(decodeURIComponent(data.info))
},
methods: {
back() {
uni.navigateBack({
delta: 1
})
},
showOrder() {
uni.redirectTo({
url: '/pages/myReservation/myReservation'
})
}
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
background: linear-gradient(180deg, #C1DEFF 0%, rgba(193, 222, 255, 0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
.body {
flex: 1;
height: 0;
overflow: auto;
position: relative;
z-index: 1;
background: linear-gradient(180deg, rgba(193, 222, 255, 0) 0%, #f1f1f1 100%);
}
.card {
margin: 40rpx 32rpx;
padding: 60rpx 30rpx;
background: #FFFFFF;
border-radius: 12rpx 12rpx 12rpx 12rpx;
}
.success {
font-weight: bold;
font-size: 32rpx;
color: #333333;
padding-bottom: 60rpx;
display: flex;
flex-direction: column;
align-items: center;
row-gap: 30rpx;
border-bottom: 1rpx solid #DDDDDD;
}
.successIcon {
width: 120rpx;
height: 120rpx;
}
.orderInfo {
padding: 40rpx 0 60rpx;
}
.shopName {
font-weight: bold;
font-size: 32rpx;
color: #333333;
}
.baseInfo {
font-weight: 500;
font-size: 24rpx;
color: #999999;
margin-top: 30rpx;
display: flex;
align-items: center;
column-gap: 12rpx;
.baseInfoIcon {
width: 28rpx;
height: 28rpx;
}
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
row-gap: 40rpx;
.showOrder, .back {
width: 510rpx;
height: 76rpx;
border-radius: 38rpx 38rpx 38rpx 38rpx;
display: flex;
align-items: center;
justify-content: center;
}
.showOrder {
background: #0174F6;
font-weight: bold;
font-size: 32rpx;
color: #FFFFFF;
}
.back {
border-radius: 38rpx 38rpx 38rpx 38rpx;
border: 2rpx solid #0174F6;
font-weight: bold;
font-size: 32rpx;
color: #0174F6;
}
}
}
</style>

View File

@ -0,0 +1,243 @@
<template>
<view class="container">
<VNavigationBar :title="pageTitle" background-color="#fff" title-color="#333"></VNavigationBar>
<view class="body">
<u-form labelPosition="top">
<view class="card">
<u-form-item borderBottom label="姓名" label-width="200">
<u-input v-model="userInfo.name" border="none" placeholder="请输入客户姓名"></u-input>
</u-form-item>
<u-form-item borderBottom label="性别" label-width="200">
<u-radio-group
v-model="userInfo.sex"
placement="row"
>
<u-radio key="0" label="男" name="0" style="margin-right: 100rpx"></u-radio>
<u-radio key="1" label="女" name="1"></u-radio>
</u-radio-group>
</u-form-item>
<u-form-item borderBottom label="联系方式" label-width="200">
<u-input v-model="userInfo.phone" border="none" placeholder="请输入联系方式" type="number"></u-input>
</u-form-item>
<u-form-item borderBottom label="出生年月" labelWidth="200" @click="openDatePicker(); hideKeyboard()">
<u-input
v-model="userInfo.birthday"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择出生年月"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
<u-form-item borderBottom label="选择所在地区" labelWidth="200" @click="areaOpen">
<u-input
v-model="userInfo.area"
border="none"
disabled
disabledColor="#ffffff"
placeholder="请选择所在省/市/区"
></u-input>
<u-icon
slot="right"
name="arrow-right"
></u-icon>
</u-form-item>
<u-form-item label="详细地址" label-width="200">
<u-input v-model="userInfo.address" border="none" placeholder="请输入详细地址"></u-input>
</u-form-item>
</view>
</u-form>
<!-- 车辆型号 -->
<u-action-sheet
:actions="typeList"
:show="showType"
title="请选择车辆型号"
@close="showType = false"
@select="typeSelect"
>
</u-action-sheet>
<u-datetime-picker
v-model="datePickerValue"
:formatter="formatter"
:show="datePickerShow"
mode="date"
@cancel="datePickerCancel"
@confirm="datePickerConfirm"
></u-datetime-picker>
</view>
<view class="footer">
<view v-if="bo2" class="btnItem edit" @click="submit">
确定
</view>
</view>
<cityPicker :column="3" default-value="" :mask-close-able="true" :visible="areaVisible"
@cancel="areaCancel" @confirm="areaConfirm"/>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue';
import cityPicker from '@/uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker'
import {bus} from "@/utils/eventBus";
export default {
components: {
VNavigationBar,
cityPicker
},
data() {
return {
pageTitle: '',
userInfo: {
name: ''
},
bo1: false,
bo2: true,
datePickerShow: false,
datePickerValue: new Date().getTime(),
pickerConfirmField: 'njDate',
showType: false,
typeList: [
{
name: '一汽奥迪 2024款 A6L',
value: '1'
},
],
areaVisible: false
};
},
onLoad(options) {
//
console.log('options', options)
if (options.userInfo) {
//
this.userInfo = JSON.parse(decodeURIComponent(options.userInfo));
console.log('初始化页面数据', this.userInfo)
this.bo1 = true;
this.bo2 = false;
this.pageTitle = '修改用户信息'
} else {
//
this.bo1 = false;
this.bo2 = true;
this.pageTitle = '添加用户信息'
}
},
methods: {
typeSelect(e) {
console.log('e', e)
},
openDatePicker() {
this.datePickerShow = true
},
datePickerConfirm({value}) {
const date = new Date(value)
this.userInfo.birthday = date.getFullYear() + '-' + (Number(date.getMonth()) + 1 + '').padStart(2, '0') + '-' + (date.getDate() + '').padStart(2, '0')
this.datePickerCancel()
},
datePickerCancel() {
this.datePickerValue = new Date().getTime()
this.datePickerShow = false
},
formatter(type, value) {
if (type === 'year') {
return `${value}`
}
if (type === 'month') {
return `${value}`
}
if (type === 'day') {
return `${value}`
}
console.log('for value', value)
return value
},
areaOpen() {
this.areaVisible = true
},
areaConfirm(e) {
console.log('e', e)
this.userInfo.area = e.name
this.userInfo.provinceName = e.provinceName
this.userInfo.cityName = e.cityName
this.userInfo.areaName = e.areaName
this.areaCancel()
},
areaCancel() {
this.areaVisible = false
},
//
async submit() {
bus.$emit('updateUserInfo', this.userInfo)
uni.navigateBack()
// let res = await request({
// url: '/userClient/base/myCar/create',
// method: 'POST',
// data: this.userInfo,
// })
// if (res.code == 200) {
// //
// uni.navigateBack();
// bus.$emit('updateUserInfo')
// }
},
}
}
</script>
<style lang="less" scoped>
.container {
box-sizing: border-box;
height: 100%;
background-color: #f3f5f7;
display: flex;
flex-direction: column;
.body {
flex: 1;
height: 0;
overflow: auto;
.card {
margin: 20rpx 30rpx;
padding: 0 30rpx;
background-color: #fff;
}
}
.footer {
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
.btnItem {
width: 510rpx;
height: 76rpx;
background: #0174F6;
border-radius: 38rpx 38rpx 38rpx 38rpx;
font-size: 32rpx;
color: #FFFFFF;
line-height: 76rpx;
text-align: center;
}
}
}
</style>

48
pages/模板.vue Normal file
View File

@ -0,0 +1,48 @@
<template>
<view class="container">
<view class="containerBody">
<VNavigationBar title="新建工单" background-color="rgba(0,0,0,0)" title-color="#333"></VNavigationBar>
<view class="body">
</view>
</view>
</view>
</template>
<script>
import VNavigationBar from '@/components/VNavigationBar.vue'
export default {
components: {
VNavigationBar,
},
data() {
return {}
},
onLoad(data){
},
methods: {
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
background-color: #F3F5F7;
.containerBody {
height: 100%;
display: flex;
flex-direction: column;
background: linear-gradient( 180deg, #C1DEFF 0%, rgba(193,222,255,0) 100%);
background-size: 100% 500rpx;
background-repeat: no-repeat;
}
.body {
flex: 1;
height: 0;
overflow: auto;
}
}
</style>

BIN
static/icons/bottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

BIN
static/icons/date.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
static/icons/duihao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

BIN
static/icons/edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
static/icons/orderEnd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
static/icons/orderIng.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
static/icons/send.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
static/icons/x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

View File

@ -0,0 +1,2 @@
## 1.0.02023-03-26
初版发布

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,398 @@
<template>
<!-- 车牌组件 -->
<view class="plate-content">
<view class="plate-popup" v-show="plateShow">
<view class="plate-close" @click="close">{{ plateNumber.length > 6 ? '确定' : '关闭' }}</view>
<view class="numbox" v-if="isShow">
<block v-for="(item, index) in 7" :key="index">
<input v-model="plateNumber[index]" disabled class="numInput" maxlength="1" type="text" value="" @click="carInputClick(index)"/>
</block>
<input v-model="plateNumber[7]" disabled class="newnumInput" maxlength="1" type="text" value="" placeholder="新能源" placeholder-class="newpl" @click="carInputClick(7)" />
</view>
<!-- 汉字键盘 -->
<view v-show="!plateNumber" :class="safeArea ? 'isPhoneX' : ''">
<view class="plate-popup-item">
<view class="plate-popup-item-list" v-for="(item, itemIndex) in keyVehicle1" :key="itemIndex" @click="plateHead(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" v-for="(item, itemIndex) in keyVehicle2" :key="itemIndex" @click="plateHead(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" v-for="(item, itemIndex) in keyVehicle3" :key="itemIndex" @click="plateHead(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" v-for="(item, itemIndex) in keyVehicle4" :key="itemIndex" @click="plateHead(item)">{{ item }}</view>
<!-- 删除 -->
<view class="plate-popup-item-list delImg" @click="plateDel">
<image :src="src" />
</view>
</view>
</view>
<!-- 数字字母键盘 -->
<view v-show="plateNumber" :class="safeArea ? 'isPhoneX' : '' ">
<view class="plate-popup-item">
<!-- 数字选择 -->
<view class="plate-popup-item-list" :class="plateNumber.length < 2 || isInputZh ? 'plate-popup-item-disabled' : ''" v-for="(item, itemIndex) in keyNumber" :key="itemIndex" @click="plateNum(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" :class="!isInputZh ? '' : 'plate-popup-item-disabled'" v-for="(item, itemIndex) in keyEnInput1" :key="itemIndex" @click="plateInput(item)"> <view :class="item =='I' || item == 'O' ? 'plate-popup-item-disabled' : ''">{{ item }}</view></view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" :class="!isInputZh ? '' : 'plate-popup-item-disabled'" v-for="(item, itemIndex) in keyEnInput2" :key="itemIndex" @click="plateInput(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<view class="plate-popup-item-list" :class="!isInputZh ? '' : 'plate-popup-item-disabled'" v-for="(item, itemIndex) in keyEnInput3" :key="itemIndex" @click="plateInput(item)">{{ item }}</view>
</view>
<view class="plate-popup-item">
<!-- 车牌最后一位-->
<view class="plate-popup-item-list del2" :class="(plateNumber.length === 6 || plateNumber.length === 7) && !isInputZh ? '' : 'plate-popup-item-disabled'" v-for="(item, itemIndex) in keyEnInput4" :key="itemIndex" @click="plateLast(item)">{{ item }}</view>
<!-- 删除 -->
<view class="plate-popup-item-list delImg" @click="plateDel">
<image :src="src" />
</view>
</view>
</view>
</view>
</view>
</template>
<script>
/*
* @change By:CkCode
* @logs:
* 1:将键盘和输入框整合到了一起
* 2:适配苹果X
* 3:增加校验规则
* 4:增加了错误提示
* @Last Modified time: 2022-10-17
*/
import plateDel from './KeyboardDelete.png'
export default {
data() {
return {
plateNumber: '', //
plateShow: false, //
keyVehicle1: ['京', '沪', '粤', '津', '冀', '豫', '云', '辽', '黑', '湘'],
keyVehicle2: ['皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘'],
keyVehicle3: ['晋', '蒙', '陕', '吉', '闽', '贵', '渝', '川'],
keyVehicle4: ['青', '藏', '琼', '宁', '使'],
keyNumber: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
keyEnInput1: ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
keyEnInput2: ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
keyEnInput3: ['Z', 'X', 'C', 'V', 'B', 'N', 'M'],
keyEnInput4: ['港', '澳', '学', '警', '临','挂'],
isInputZh: false, //
src: '',
};
},
props: {
//
isShow:{
type:Boolean,
default:true
},
//线iphone X
safeArea: {
type:Boolean,
default:false
},
},
mounted() {
this.src = plateDel;
},
onShow() {},
watch:{
plateNumber(num){
this.$emit('update:plateNum', num);
}
},
methods: {
/**
* @desc 初始化
*/
init() {
this.plateNumber = '';
},
/**
* @desc 打开下拉栏
*/
open() {
this.plateShow = true;
},
/**
* @desc 关闭弹出的车牌
*/
close() {
if (this.plateNumber && this.plateNumber.length < 7 ) {
return uni.showModal({
title: '温馨提示',
content: '关闭将会清空您已输入的内容',
success: res => {
if (res.confirm) {
this.init();
this.plateShow = false;
//
this.$emit('change', {
value:this.plateNumber
})
} else if (res.cancel) {
}
},
});
}
if(this.isVehicleNumber(this.plateNumber)){
this.plateShow = false;
//,便
this.$emit('change', {
value:this.plateNumber
})
}else if(this.plateNumber){
uni.showToast({
title: '车牌号输入错误,请重新输入',
duration: 2000,icon:'none'
});
}else{
this.plateShow = false;
}
},
/**
* @desc 车牌号验证方法
*/
isVehicleNumber(vehicleNumber) {
var xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/;
var creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳临]{1}$/;
if (vehicleNumber.length == 7) {
return creg.test(vehicleNumber);
} else if (vehicleNumber.length == 8) {
return xreg.test(vehicleNumber);
} else {
return false;
}
},
/**
* @desc 汉字选择
*/
plateHead(plate) {
if (!this.plateNumber) {
this.plateNumber = this.plateNumber + plate;
}
},
/**
* @desc 字母选择
*/
plateInput(plate) {
//
if (this.isInputZh || plate =='I' || plate == 'O') {
return;
}
if (this.plateNumber.length < 8) {
this.plateNumber = this.plateNumber + plate;
}
},
/**
* @desc 数字选择
*/
plateNum(plate) {
//
if (this.isInputZh) {
return;
}
if (this.plateNumber.length >= 2 && this.plateNumber.length < 8) {
this.plateNumber = this.plateNumber + plate;
}
},
/**
* @desc 最后一位选择
*/
plateLast(plate) {
//
if (this.isInputZh) {
return;
}
if (this.plateNumber.length === 6 || this.plateNumber.length === 7) {
this.plateNumber = this.plateNumber + plate;
this.isInputZh = true;
}
},
/**
* @desc 删除
*/
plateDel() {
if (this.plateNumber) {
this.plateNumber = this.plateNumber.substring(0, this.plateNumber.length - 1);
}
if (this.plateNumber.length === 6 || this.plateNumber.length === 7) {
this.isInputZh = false;
}
},
},
};
</script>
<style lang="scss">
/*宽度转换vw*/
@function vww($number) {
@return ($number / 375) * 750 + rpx;
}
.isPhoneX {
padding-bottom: env(safe-area-inset-bottom);
}
.numbox {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
padding: 0 24rpx 32rpx;
.numInput {
width: 76rpx;
height: 96rpx;
line-height: 92rpx;
text-align: center;
background: #ffffff;
border-radius: 4rpx;
border: 2rpx solid #e6e6e6;
font-size: 44rpx;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
color: #333333;
}
.numInputon {
position: relative;
border: 2rpx solid #377cff;
&::after {
width: 56rpx;
height: 4rpx;
background: #377cff;
border-radius: 2rpx;
content: '';
position: absolute;
bottom: 6rpx;
left: 12rpx;
}
}
.newnumInput {
width: 76rpx;
height: 96rpx;
line-height: 92rpx;
text-align: center;
border-radius: 4rpx;
font-size: 44rpx;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
background: #e7faf1;
border: 2rpx dashed #0fd07e;
color: #0fd07e;
}
.newnumInputon {
position: relative;
border: 2rpx solid #0fd07e;
&::after {
width: 56rpx;
height: 4rpx;
background: #0fd07e;
border-radius: 2rpx;
content: '';
position: absolute;
bottom: 6rpx;
left: 12rpx;
}
}
.newpl {
font-size: 24rpx;
font-family: SourceHanSansCN-Regular, SourceHanSansCN;
font-weight: 400;
color: #00bf6e;
line-height: 36rpx;
}
}
.plate-popup {
position: fixed;
z-index: 999;
background-color: #e3e2e7;
-webkit-box-shadow: 0 0 30upx rgba(0, 0, 0, 0.1);
box-shadow: 0 0 30upx rgba(0, 0, 0, 0.1);
bottom: 0;
width: 100%;
overflow: hidden;
text-align: center;
$height: vww(35);
//
.plate-close {
width: calc(100% - vww(10));
background: #ffffff;
line-height: vww(30);
font-size: vww(12);
text-align: right;
padding-right: vww(10);
color: #00a7ea;
}
//-
.plate-popup-item {
margin: 0 auto;
overflow: hidden;
display: inline-block;
display: table;
&:last-child {
margin-bottom: 2vw;
}
}
//-
.plate-popup-item-list {
float: left;
font-size: vww(14);
width: 8vw;
margin: 0 1vw;
margin-top: 2vw;
height: $height;
line-height: $height;
background: #ffffff;
border-radius: 5px;
color: #4a4a4a;
overflow: hidden;
//
&.del {
width: 14vw;
}
&.del2 {
width: 12vw;
}
&.delImg {
width: 14vw;
display: flex;
//
image {
width: 48rpx;
height: 48rpx;
margin: 0 auto;
display: block;
vertical-align: middle;
align-self: center;
}
}
//
&.special {
background: #f0f2f4;
}
}
.plate-popup-item-disabled {
background: #f0f2f4;
}
}
</style>

View File

@ -0,0 +1,81 @@
{
"id": "keyboard-plate",
"displayName": "车牌号键盘、车牌号输入、新能源车牌、车牌键盘,车牌校验",
"version": "1.0.0",
"description": "一款适用于uniapp车牌号输入的组件",
"keywords": [
"车牌"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,41 @@
# keyboard-plate是一款适用于uniapp车牌号输入的组件
# ### 本组件目前兼容微信小程序、H5
### 本组件自带车牌号输入框支持新能源适配各种屏幕适配苹果x系列支持车牌号检验
### 使用方式
``` html
<button @click="carInputClick">打开车牌输入</button>
<keyboard-plate ref="plateNumber" :plateNum.sync='plateNum' @change="getPlateNum" isShow></keyboard-plate>
```
``` javascript
export default {
data() {
return {
plateNum:''
};
},
watch:{
plateNum(e){
console.log(e)
}
},
methods: {
//获取车牌
getPlateNum(e){
console.log('车牌号是:'+ e)
},
// 打开车牌选择器
carInputClick() {
this.$refs.plateNumber.open();
},
}
}
```
### 属性说明
| 名称 | 类型 | 默认值 | 描述 |
| ----------------------------|--------------- | ---------------------- | ---------------|
| isShow | Boolean | true | 是否开启输入框
| safeArea | Boolean | false | 是否适配安全线iphone X

View File

@ -0,0 +1,20 @@
## 1.1.62024-08-20
更新本地数据源为最新数据源
## 1.1.52024-06-12
使用说明文档优化
## 1.1.42024-06-12
增加问题反馈描述
## 1.1.32024-02-29
更新使用文档
## 1.1.22024-01-16
解决Vue3项目导入导出报错问题
## 1.1.12023-12-06
defaultValue可以传入defaultValue:['河北省','唐山市','丰南区']数组类型以及defaultValue: '420103'地区编码字符串类型
## 1.1.02023-12-05
即默认值传入地区编码,也支持传入中文省市区数组
## 1.0.92023-12-04
优化
## 1.0.82023-10-24
修复东菀市和中山市下各镇的行政编码错误问题
## 1.0.42023-09-15
改为uni_modules规范

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,281 @@
<template>
<view class="pupop">
<view class="popup-box" :animation="animationData">
<view class="pupop-btn">
<view @tap="cancel">取消</view>
<view @tap="confirm" style="color: #2979ff;">确定</view>
</view>
<picker-view :value="value" :indicator-style="indicatorStyle" @change="bindChange" class="picker-view">
<picker-view-column>
<view class="item" v-for="(item,index) in provinceList" :key="index">{{item.name}}</view>
</picker-view-column>
<picker-view-column>
<view class="item" v-for="(item,index) in cityList" :key="index">{{item.name}}</view>
</picker-view-column>
<picker-view-column v-if="column == 3">
<view class="item" v-for="(item,index) in areaList" :key="index">{{item.name}}</view>
</picker-view-column>
</picker-view>
</view>
<view @tap="close" @touchmove.stop.prevent :class="visible ? 'pupop-model' : 'pupop-models'"></view>
</view>
</template>
<script>
import {
addressList
} from './cityData.js'
export default {
data() {
return {
value: [],
addressList,
provinceList: [],
cityList: [],
areaList: [],
indicatorStyle: `height: 50px;`,
provinceIndex: 0,
cityIndex: 0,
areaIndex: 0,
animationData: {}
}
},
props: {
column: {
type: Number,
default: 3
},
defaultValue: {
default: () => ''
},
visible: {
type: Boolean,
default: () => false
},
maskCloseAble: {
type: Boolean,
default: () => true
},
},
watch: {
visible (val) {
this.changeActive()
},
defaultValue() {
this.init()
}
},
created() {
this.init()
},
methods: {
init () {
var provinceList = []
addressList.filter(item => {
provinceList.push({
code: item.code,
name: item.name
})
})
this.provinceList = [...provinceList]
if (!this.defaultValue) {
this.cityList = addressList[0].children
this.areaList = addressList[0].children[0].children
} else {
var city = {11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江 ",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北 ",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏 ",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外 "}
if (Array.isArray(this.defaultValue) && this.defaultValue.length >= 2) {
console.log(this.defaultValue)
var province = this.defaultValue[0]
var city = this.defaultValue[1]
this.provinceIndex = 0
this.cityIndex = 0
this.areaIndex = 0
this.provinceIndex = addressList.findIndex(obj => {
return obj.name == province
})
this.provinceIndex = this.provinceIndex >= 0 ? this.provinceIndex : 0
this.cityList = addressList[this.provinceIndex].children
this.cityIndex = this.cityList.findIndex(obj => {
return obj.name == city
})
this.cityIndex = this.cityIndex >= 0 ? this.cityIndex : 0
this.areaList = this.cityList[this.cityIndex].children
if (this.defaultValue.length > 2) {
this.areaIndex = this.areaList.findIndex(obj => {
return obj.name == this.defaultValue[2]
})
}
this.areaIndex = this.areaIndex >= 0 ? this.areaIndex : 0
this.$nextTick(() => {
if (this.column == 3) {
this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex, this.areaIndex]))
} else if (this.column == 2) {
this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex]))
}
})
} else if (/^\d{6}$/.test(this.defaultValue)) {
var province = this.defaultValue.substr(0, 2)
var city = this.defaultValue.substr(0, 4)
this.provinceIndex = 0
this.cityIndex = 0
this.areaIndex = 0
this.provinceIndex = addressList.findIndex(obj => {
return obj.code == province
})
this.provinceIndex = this.provinceIndex >= 0 ? this.provinceIndex : 0
this.cityList = addressList[this.provinceIndex].children
this.cityIndex = this.cityList.findIndex(obj => {
return obj.code == city
})
this.cityIndex = this.cityIndex >= 0 ? this.cityIndex : 0
this.areaList = this.cityList[this.cityIndex].children
this.areaIndex = this.areaList.findIndex(obj => {
return obj.code == this.defaultValue
})
this.areaIndex = this.areaIndex >= 0 ? this.areaIndex : 0
this.$nextTick(() => {
if (this.column == 3) {
this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex, this.areaIndex]))
} else if (this.column == 2) {
this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex]))
}
})
} else {
uni.showToast({
title: '地区编码格式不正确',
icon: 'none'
})
console.log('地区编码格式不正确')
}
}
this.changeActive()
},
confirm () {
if (this.column == 3) {
this.$emit('confirm', {
code: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].code,
name: addressList[this.provinceIndex].name + addressList[this.provinceIndex].children[this.cityIndex].name + addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].name,
provinceName: addressList[this.provinceIndex].name,
cityName: addressList[this.provinceIndex].children[this.cityIndex].name,
areaName: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].name
})
} else if (this.column == 2) {
this.$emit('confirm', {
code: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].code.substring(0, 4) + '00',
name: addressList[this.provinceIndex].name + addressList[this.provinceIndex].children[this.cityIndex].name,
provinceName: addressList[this.provinceIndex].name,
cityName: addressList[this.provinceIndex].children[this.cityIndex].name
})
} else {
uni.showToast({
title: '目前column只能传2和3',
icon: 'none'
})
}
},
cancel () {
this.$emit('cancel')
},
//
changeActive () {
var active = '-315px'
if (this.visible) {
active = 0
}
var animation = uni.createAnimation({
duration: 400,
timingFunction: 'linear'
})
animation.bottom(active).step()
this.animationData = animation.export()
},
bindChange(e) {
e.detail.value[0] = e.detail.value[0] || 0
e.detail.value[1] = e.detail.value[1] || 0
e.detail.value[2] = e.detail.value[2] || 0
if (e.detail.value[0] != this.provinceIndex) {
// console.log('')
this.provinceChange(e.detail.value[0])
} else if (e.detail.value[1] != this.cityIndex) {
// console.log('')
this.cityChange(e.detail.value[1])
} else if (e.detail.value[2] != this.areaIndex) {
// console.log('')
this.areaChange(e.detail.value[2])
}
},
//
provinceChange (e) {
this.provinceIndex = e
this.cityIndex = 0
this.areaIndex = 0
this.value = [...[e, 0, 0]]
this.cityList = addressList[e].children
this.areaList = addressList[e].children[0].children
},
//
cityChange (e) {
this.cityIndex = e
this.areaIndex = 0
// console.log(this.cityIndex, this.areaIndex)
this.value = [...[this.provinceIndex, e, 0]]
this.cityList = addressList[this.provinceIndex].children
this.areaList = addressList[this.provinceIndex].children[e].children
},
//
areaChange (e) {
this.areaIndex = e
},
//
close () {
if (this.maskCloseAble) {
this.cancel()
}
}
}
}
</script>
<style scoped lang="scss">
.pupop {
.popup-box {
position: fixed;
left: 0;
bottom: -315px;
z-index: 99999;
background: #fff;
padding-bottom: 50px;
.pupop-btn{
height: 40px;
display: flex;
align-items: center;
padding: 0 30upx;
justify-content: space-between;
}
}
.pupop-model {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 9999;
background: rgba(0, 0, 0, .5);
}
.pupop-models{
display: none;
}
.picker-view {
width: 750rpx;
height: 225px;
margin-top: 20rpx;
}
.item {
height: 50px;
align-items: center;
justify-content: center;
text-align: center;
line-height: 50px;
}
}
</style>

View File

@ -0,0 +1,17 @@
{
"id": "piaoyi-cityPicker",
"name": " data-cityPicker省市区地址选择器",
"displayName": " data-cityPicker省市区地址选择器(兼容vue3)",
"version": "1.1.6",
"description": "常用省市区选择器可反选自定义模态框、兼容vue3",
"keywords": [
"省市区",
"选择器",
"可反选",
"自定义模态框和弹框",
"兼容vue3"
],
"dcloudext": {
"type": "component-vue"
}
}

View File

@ -0,0 +1,106 @@
## 1.0.72023-09-15
改为uni_modules规范
### cityPicker 省市区选择器兼容vue3
**使用方法:**
```
<template>
<view>
<button @tap="open">打开</button>
<cityPicker :column="column" :default-value="defaultValue" :mask-close-able="maskCloseAble" @confirm="confirm" @cancel="cancel" :visible="visible"/>
<view>{{str}}</view>
</view>
</template>
<script>
import cityPicker from '@/uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker'
export default {
data() {
return {
visible: false,
maskCloseAble: true,
str: '',
defaultValue: '420103',
// defaultValue: ['河北省','唐山市','丰南区'],
column: 3
}
},
components: {
cityPicker
},
methods: {
open () {
this.visible = true
},
confirm (val) {
console.log(val)
this.str = JSON.stringify(val)
this.visible = false
},
cancel () {
this.visible = false
}
},
onShareAppMessage(res) {
if (res.from === 'button') { // 来自页面内分享按钮
console.log(res.target)
}
return {
title: 'data-cityPicker省市区地址选择器',
path: '/pages/cityPicker/cityPicker'
}
},
onShareTimeline(res) {
if (res.from === 'button') { // 来自页面内分享按钮
console.log(res.target)
}
return {
title: 'data-cityPicker省市区地址选择器'
}
}
}
</script>
<style lang="scss">
</style>
```
### 注:近期收到使用用户反馈,存在以下一个问题(如有好的建议,期待私信,谢谢)
1、之前只支持默认值传入地区编码已更新可以支持传入中文省市区数组
defaultValue可以传入defaultValue:['河北省','唐山市','丰南区']数组类型以及defaultValue: '420103'地区编码字符串类型
可以使用const reg =/([\u4e00-\u9fa5]+省|自治区|[\u4e00-\u9fa5]+市|[\u4e00-\u9fa5]+区)/g;将自己的省市区数据进行处理为数组再传入
2、有些用户反馈vue3下watch监听有问题
我自己创建一个vue项目导入插件后按照示例原封不动进行测试没有发现问题; 发现有问题的朋友可以提供一下可以复现的demo给我我这边看看具体什么情况
3、有些用户返回无法关闭弹框
不要把插件放到scroll-view里面请务必放到最外层进行使用
#### 事件说明
| 事件名 | 返回值 | 描述 |
| :---------: | :----: | :------------: |
| @confirm | 对象(code,完整地区名称) | 点击确定的回调 |
| @cancel | 无 | 点击取消的回调 |
#### Prop
| 参数名称 | 描述 |
| -------- | ------------------------------ |
| visible | 控制选择器显示和隐藏 |
| column | 可选值2和32是省市两列选择3是省市区三列选择 |
| maskCloseAble | 点击模态框是否关闭弹框 |
| defaultValue | 初始地区编码(例:420102或者['河北省','唐山市','丰南区'] |
### 数据来源:[点击查看省市区数据来源](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pca-code.json)
### 可接定制化组件开发
### 右侧有本人代表作小程序二维码,可以扫码体验
### 如使用过程中有问题或有一些好的建议欢迎加QQ群互相学习交流120594820

2
utils/eventBus.js Normal file
View File

@ -0,0 +1,2 @@
import vue from 'vue'
export const bus = new vue()