|
|
- <template>
- <view class="page">
- <navbar title="订单详情" leftClick @leftClick="$utils.navigateBack" />
- <view class="content">
- <!-- 订单状态卡片 -->
- <view class="status-card">
- <view class="status-header">
- <view class="status-icon" :class="orderInfo.status">
- <uv-icon :name="getStatusIcon(orderInfo.status)" size="30" color="#fff"></uv-icon>
- </view>
- <view class="status-info">
- <view class="status-text">{{ getStatusText(orderInfo.status) }}</view>
- <view class="status-desc">{{ getStatusDesc(orderInfo.status) }}</view>
- </view>
- </view>
-
- <!-- 进度条 -->
- <view v-if="orderInfo.status === 'processing'" class="progress-container">
- <view class="progress-bar">
- <view class="progress-fill" :style="{width: orderInfo.progress + '%'}"></view>
- </view>
- <view class="progress-text">{{ orderInfo.progress }}%</view>
- </view>
- </view>
-
- <!-- 订单基本信息 -->
- <view class="order-info-card">
- <view class="section-title">
- <view class="title-bar"></view>
- <text>订单信息</text>
- </view>
-
- <view class="info-item">
- <view class="label">订单编号</view>
- <view class="value order-no-value">
- <text>{{ orderInfo.orderNo }}</text>
- <uv-icon name="copy" size="16" color="#007AFF" @click="copyOrderNo"></uv-icon>
- </view>
- </view>
-
- <view class="info-item">
- <view class="label">项目名称</view>
- <view class="value">{{ orderInfo.projectName }}</view>
- </view>
-
- <view class="info-item">
- <view class="label">工作地址</view>
- <view class="value address-value">
- <text>{{ orderInfo.workAddress }}</text>
- <uv-icon name="map-pin" size="16" color="#007AFF" @click="openMap"></uv-icon>
- </view>
- </view>
-
- <view class="info-item">
- <view class="label">服务类型</view>
- <view class="value">{{ orderInfo.serviceType }}</view>
- </view>
-
- <view class="info-item">
- <view class="label">工作时间</view>
- <view class="value">{{ orderInfo.workTime }}</view>
- </view>
-
- <view class="info-item">
- <view class="label">混凝土方量</view>
- <view class="value">{{ orderInfo.volume }}m³</view>
- </view>
-
- <view class="info-item">
- <view class="label">预计趟数</view>
- <view class="value">{{ orderInfo.tripCount }}趟</view>
- </view>
- </view>
-
- <!-- 联系人信息 -->
- <view class="contact-card">
- <view class="section-title">
- <view class="title-bar"></view>
- <text>联系人信息</text>
- </view>
-
- <view class="contact-info">
- <view class="contact-item">
- <view class="contact-label">联系人</view>
- <view class="contact-value">{{ orderInfo.contactName }}</view>
- </view>
- <view class="contact-item">
- <view class="contact-label">联系电话</view>
- <view class="contact-value">
- <text>{{ orderInfo.contactPhone }}</text>
- <uv-icon name="phone" size="20" color="#007AFF" @click="makeCall"></uv-icon>
- </view>
- </view>
- </view>
- </view>
-
- <!-- 司机信息 -->
- <view v-if="orderInfo.driverInfo" class="driver-card">
- <view class="section-title">
- <view class="title-bar"></view>
- <text>司机信息</text>
- </view>
-
- <view class="driver-info">
- <view class="driver-avatar">
- <image :src="orderInfo.driverInfo.avatar" mode="aspectFill"></image>
- </view>
- <view class="driver-details">
- <view class="driver-name">{{ orderInfo.driverInfo.name }}</view>
- <view class="driver-phone">{{ orderInfo.driverInfo.phone }}</view>
- <view class="driver-vehicle">车牌号:{{ orderInfo.driverInfo.vehicleNo }}</view>
- <view class="driver-rating">
- <text>评分:{{ orderInfo.driverInfo.rating }}分</text>
- <text>完成订单:{{ orderInfo.driverInfo.completedOrders }}单</text>
- </view>
- </view>
- <view class="driver-actions">
- <view class="action-btn" @click="callDriver">
- <uv-icon name="phone" size="20" color="#fff"></uv-icon>
- </view>
- </view>
- </view>
- </view>
-
- <!-- 订单步骤 -->
- <view class="steps-container">
- <view class="section-title">
- <view class="title-bar"></view>
- <text>订单进度</text>
- <view v-if="orderInfo.status === 'processing' || orderInfo.status === 'completed'" class="track-btn" @click="viewTrack">
- <text>查看轨迹</text>
- <uv-icon name="arrow-right" size="14" color="#007AFF"></uv-icon>
- </view>
- </view>
- <uv-steps
- activeColor="#007AFF"
- :current="stepsCurrent"
- direction="column">
- <uv-steps-item
- v-for="(item, index) in steps"
- :key="index"
- :title="item.title"
- :desc="item.desc">
- </uv-steps-item>
- </uv-steps>
- </view>
-
- <!-- 费用明细 -->
- <view class="cost-card">
- <view class="section-title">
- <view class="title-bar"></view>
- <text>费用明细</text>
- </view>
-
- <view class="cost-item">
- <view class="cost-label">单价</view>
- <view class="cost-value">{{ orderInfo.unitPrice }}元/趟</view>
- </view>
-
- <view class="cost-item">
- <view class="cost-label">预计趟数</view>
- <view class="cost-value">{{ orderInfo.tripCount }}趟</view>
- </view>
-
- <view class="cost-item">
- <view class="cost-label">小计</view>
- <view class="cost-value">{{ orderInfo.subtotal }}元</view>
- </view>
-
- <view class="cost-item total">
- <view class="cost-label">总金额</view>
- <view class="cost-value total-amount">¥{{ orderInfo.totalAmount }}</view>
- </view>
- </view>
-
- <!-- 快捷操作 -->
- <view class="quick-actions">
- <view class="action-item" @click="shareOrder">
- <uv-icon name="share" size="24" color="#007AFF"></uv-icon>
- <text>分享</text>
- </view>
- <view class="action-item" @click="copyOrderNo">
- <uv-icon name="copy" size="24" color="#007AFF"></uv-icon>
- <text>复制</text>
- </view>
- <view v-if="orderInfo.status === 'processing' || orderInfo.status === 'completed'" class="action-item" @click="viewTrack">
- <uv-icon name="map" size="24" color="#007AFF"></uv-icon>
- <text>轨迹</text>
- </view>
- <view class="action-item" @click="contactCustomer">
- <uv-icon name="phone" size="24" color="#007AFF"></uv-icon>
- <text>联系</text>
- </view>
- </view>
-
- <!-- 操作按钮 -->
- <view class="action-buttons">
- <view v-if="orderInfo.status === 'pending'" class="btn-group">
- <view class="btn secondary" @click="cancelOrder">取消订单</view>
- <view class="btn primary" @click="confirmOrder">确认接单</view>
- </view>
-
- <view v-if="orderInfo.status === 'processing'" class="btn-group">
- <view class="btn secondary" @click="contactCustomer">联系客户</view>
- <view class="btn primary" @click="completeOrder">完成订单</view>
- </view>
-
- <view v-if="orderInfo.status === 'completed'" class="btn-group">
- <view class="btn secondary" @click="rateOrder">评价订单</view>
- <view class="btn primary" @click="reorder">再次下单</view>
- </view>
-
- <view v-if="orderInfo.status === 'cancelled'" class="btn-group">
- <view class="btn primary full-width" @click="reorder">重新下单</view>
- </view>
- </view>
- </view>
- </view>
- </template>
-
- <script>
- import navbar from '@/components/base/navbar.vue'
-
- export default {
- name: 'OrderDetail',
- components: {
- navbar
- },
- data() {
- return {
- orderId: '',
- stepsCurrent: 2,
- orderInfo: {
- orderNo: 'ORD202401150001',
- projectName: '长沙市雨花区建设项目混凝土运输',
- workAddress: '长沙市雨花区某某路123号建设工地',
- serviceType: '泵车运输',
- workTime: '2024-01-16 08:00 - 18:00',
- volume: '200',
- tripCount: '8',
- unitPrice: '350',
- subtotal: '2800',
- totalAmount: '2800',
- contactName: '张工',
- contactPhone: '13800138000',
- status: 'processing', // pending, processing, completed, cancelled
- progress: 65,
- driverInfo: {
- name: '李师傅',
- phone: '13900139000',
- avatar: '/static/re/logo.png',
- vehicleNo: '湘A12345',
- rating: 4.8,
- completedOrders: 156
- }
- },
- steps: [
- {
- title: '订单确认',
- desc: '2024-01-15 14:30'
- },
- {
- title: '司机接单',
- desc: '2024-01-15 15:00'
- },
- {
- title: '前往工地',
- desc: '2024-01-16 07:30'
- },
- {
- title: '开始运输',
- desc: '预计 2024-01-16 08:00'
- },
- {
- title: '运输完成',
- desc: '预计 2024-01-16 18:00'
- }
- ]
- }
- },
- onLoad(options) {
- this.orderId = options.id || '1';
- uni.setNavigationBarTitle({
- title: '订单详情'
- });
- // 根据订单ID加载订单详情
- this.loadOrderDetail();
- },
- methods: {
- loadOrderDetail() {
- // 模拟加载订单详情
- console.log('加载订单详情:', this.orderId);
- // 根据订单ID设置不同的订单状态和信息
- if (this.orderId === '1') {
- this.orderInfo.status = 'pending';
- this.stepsCurrent = 0;
- } else if (this.orderId === '2') {
- this.orderInfo.status = 'processing';
- this.stepsCurrent = 2;
- } else if (this.orderId === '3') {
- this.orderInfo.status = 'completed';
- this.stepsCurrent = 4;
- }
- },
- getStatusIcon(status) {
- switch(status) {
- case 'pending': return 'clock';
- case 'processing': return 'play-circle';
- case 'completed': return 'checkmark-circle';
- case 'cancelled': return 'close-circle';
- default: return 'help-circle';
- }
- },
- getStatusText(status) {
- switch(status) {
- case 'pending': return '待接单';
- case 'processing': return '运输中';
- case 'completed': return '已完成';
- case 'cancelled': return '已取消';
- default: return '未知状态';
- }
- },
- getStatusDesc(status) {
- switch(status) {
- case 'pending': return '等待司机接单';
- case 'processing': return '司机正在运输中';
- case 'completed': return '订单已完成';
- case 'cancelled': return '订单已取消';
- default: return '';
- }
- },
- openMap() {
- uni.openLocation({
- latitude: 28.2282,
- longitude: 112.9388,
- name: this.orderInfo.projectName,
- address: this.orderInfo.workAddress
- });
- },
- makeCall() {
- uni.makePhoneCall({
- phoneNumber: this.orderInfo.contactPhone
- });
- },
- callDriver() {
- uni.makePhoneCall({
- phoneNumber: this.orderInfo.driverInfo.phone
- });
- },
- cancelOrder() {
- uni.showModal({
- title: '确认取消',
- content: '确定要取消这个订单吗?',
- success: (res) => {
- if (res.confirm) {
- uni.showToast({
- title: '订单已取消',
- icon: 'success'
- });
- this.orderInfo.status = 'cancelled';
- }
- }
- });
- },
- confirmOrder() {
- uni.showModal({
- title: '确认接单',
- content: '确定要接取这个订单吗?',
- success: (res) => {
- if (res.confirm) {
- uni.showToast({
- title: '接单成功',
- icon: 'success'
- });
- this.orderInfo.status = 'processing';
- this.stepsCurrent = 2;
- }
- }
- });
- },
- contactCustomer() {
- this.makeCall();
- },
- completeOrder() {
- uni.showModal({
- title: '确认完成',
- content: '确定已完成这个订单吗?',
- success: (res) => {
- if (res.confirm) {
- uni.showToast({
- title: '订单已完成',
- icon: 'success'
- });
- this.orderInfo.status = 'completed';
- this.stepsCurrent = 4;
- }
- }
- });
- },
- rateOrder() {
- uni.showToast({
- title: '评价功能开发中',
- icon: 'none'
- });
- },
- reorder() {
- uni.navigateTo({
- url: '/pages_order/staff/create'
- });
- },
- // 分享订单
- shareOrder() {
- uni.share({
- provider: 'weixin',
- scene: 'WXSceneSession',
- type: 0,
- title: '订单详情',
- summary: `订单号:${this.orderInfo.orderNo}`,
- targetUrl: `pages_order/order/orderDetail?id=${this.orderId}`,
- success: function (res) {
- uni.showToast({
- title: '分享成功',
- icon: 'success'
- });
- },
- fail: function (err) {
- console.log('分享失败:', err);
- }
- });
- },
- // 复制订单号
- copyOrderNo() {
- uni.setClipboardData({
- data: this.orderInfo.orderNo,
- success: function () {
- uni.showToast({
- title: '订单号已复制',
- icon: 'success'
- });
- }
- });
- },
- // 查看运输轨迹
- viewTrack() {
- if (this.orderInfo.status === 'processing' || this.orderInfo.status === 'completed') {
- uni.navigateTo({
- url: `/pages_order/order/track?id=${this.orderId}`
- });
- } else {
- uni.showToast({
- title: '订单未开始运输',
- icon: 'none'
- });
- }
- }
- }
- }
- </script>
-
- <style scoped lang="scss">
- .page {
- display: flex;
- flex-direction: column;
- height: 100vh;
- background-color: #f5f5f5;
- }
-
- .content {
- padding: 20rpx;
- min-height: 100vh;
- background-color: #f5f5f5;
- padding-bottom: 120rpx;
- }
-
- .status-card {
- background-color: #fff;
- border-radius: 15rpx;
- padding: 30rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
-
- .status-header {
- display: flex;
- align-items: center;
- gap: 20rpx;
-
- .status-icon {
- width: 80rpx;
- height: 80rpx;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
-
- &.pending {
- background-color: #ff9500;
- }
-
- &.processing {
- background-color: #007AFF;
- }
-
- &.completed {
- background-color: #34c759;
- }
-
- &.cancelled {
- background-color: #ff3b30;
- }
- }
-
- .status-info {
- flex: 1;
-
- .status-text {
- font-size: 36rpx;
- font-weight: bold;
- color: #333;
- margin-bottom: 8rpx;
- }
-
- .status-desc {
- font-size: 28rpx;
- color: #666;
- }
- }
- }
-
- .progress-container {
- margin-top: 30rpx;
-
- .progress-bar {
- height: 8rpx;
- background-color: #f0f0f0;
- border-radius: 4rpx;
- overflow: hidden;
- margin-bottom: 10rpx;
-
- .progress-fill {
- height: 100%;
- background-color: #007AFF;
- transition: width 0.3s;
- }
- }
-
- .progress-text {
- font-size: 24rpx;
- color: #007AFF;
- text-align: right;
- }
- }
- }
-
- .section-title {
- display: flex;
- align-items: center;
- gap: 15rpx;
- margin-bottom: 30rpx;
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- justify-content: space-between;
-
- .title-bar {
- width: 8rpx;
- height: 30rpx;
- background-color: #007AFF;
- border-radius: 4rpx;
- }
-
- .track-btn {
- display: flex;
- align-items: center;
- gap: 5rpx;
- font-size: 26rpx;
- color: #007AFF;
- font-weight: normal;
- }
- }
-
- .order-info-card,
- .contact-card,
- .driver-card,
- .steps-container,
- .cost-card {
- background-color: #fff;
- border-radius: 15rpx;
- padding: 30rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
- }
-
- .info-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 20rpx 0;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:last-child {
- border-bottom: none;
- }
-
- .label {
- font-size: 28rpx;
- color: #666;
- width: 200rpx;
- }
-
- .value {
- flex: 1;
- font-size: 28rpx;
- color: #333;
- text-align: right;
-
- &.address-value {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- gap: 10rpx;
- }
-
- &.order-no-value {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- gap: 10rpx;
- }
- }
- }
-
- .contact-info {
- .contact-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15rpx 0;
-
- .contact-label {
- font-size: 28rpx;
- color: #666;
- }
-
- .contact-value {
- display: flex;
- align-items: center;
- gap: 15rpx;
- font-size: 28rpx;
- color: #333;
- }
- }
- }
-
- .driver-info {
- display: flex;
- align-items: center;
- gap: 20rpx;
-
- .driver-avatar {
- width: 120rpx;
- height: 120rpx;
- border-radius: 60rpx;
- overflow: hidden;
-
- image {
- width: 100%;
- height: 100%;
- }
- }
-
- .driver-details {
- flex: 1;
-
- .driver-name {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- margin-bottom: 8rpx;
- }
-
- .driver-phone,
- .driver-vehicle {
- font-size: 26rpx;
- color: #666;
- margin-bottom: 5rpx;
- }
-
- .driver-rating {
- display: flex;
- gap: 20rpx;
- font-size: 24rpx;
- color: #999;
- }
- }
-
- .driver-actions {
- .action-btn {
- width: 80rpx;
- height: 80rpx;
- background-color: #007AFF;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- }
- }
-
- .cost-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 20rpx 0;
- border-bottom: 1rpx solid #f0f0f0;
-
- &:last-child {
- border-bottom: none;
- }
-
- &.total {
- padding-top: 30rpx;
- border-top: 2rpx solid #f0f0f0;
- margin-top: 20rpx;
- }
-
- .cost-label {
- font-size: 28rpx;
- color: #666;
- }
-
- .cost-value {
- font-size: 28rpx;
- color: #333;
-
- &.total-amount {
- font-size: 36rpx;
- font-weight: bold;
- color: #ff3b30;
- }
- }
- }
-
- .quick-actions {
- background-color: #fff;
- border-radius: 15rpx;
- padding: 30rpx;
- margin-bottom: 20rpx;
- box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
- display: flex;
- justify-content: space-around;
-
- .action-item {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 10rpx;
- padding: 20rpx;
- border-radius: 10rpx;
- transition: background-color 0.3s;
-
- &:active {
- background-color: #f0f0f0;
- }
-
- text {
- font-size: 24rpx;
- color: #333;
- }
- }
- }
-
- .action-buttons {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- background-color: #fff;
- padding: 20rpx;
- box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
-
- .btn-group {
- display: flex;
- gap: 20rpx;
-
- .btn {
- flex: 1;
- height: 80rpx;
- border-radius: 40rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 28rpx;
- font-weight: bold;
-
- &.primary {
- background-color: #007AFF;
- color: #fff;
- }
-
- &.secondary {
- background-color: #f8f8f8;
- color: #333;
- border: 1rpx solid #e0e0e0;
- }
-
- &.full-width {
- width: 100%;
- }
- }
- }
- }
- </style>
|