1099 lines
25 KiB
Vue
1099 lines
25 KiB
Vue
<template>
|
|
<view class="detail-page">
|
|
<!-- 自定义导航栏 -->
|
|
<wd-navbar :bordered="false"
|
|
custom-style="background: transparent !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;"
|
|
safeAreaInsetTop fixed placeholder>
|
|
<template #left>
|
|
<view class="navbar-content">
|
|
<text v-if="hasMultiplePages" class="ri-arrow-left-s-line li-text-70"
|
|
@click="toPages({type:'nav'})"></text>
|
|
<text v-if="!hasMultiplePages" class="ri-home-5-line li-text-55 li-mr-6 li-mb-8"
|
|
@click="toPages({type:'home'})"></text>
|
|
<text class="li-text-42">工单详情</text>
|
|
</view>
|
|
</template>
|
|
</wd-navbar>
|
|
<!-- 导航栏背景 -->
|
|
<view class="nav-bg-layer"></view>
|
|
|
|
<!-- 工单状态卡片 -->
|
|
<view class="ticket-card">
|
|
<view class="ticket-header">
|
|
<view class="ticket-info">
|
|
<view class="ticket-id">
|
|
<text class="ri-file-list-line id-icon"></text>
|
|
<text class="id-text">{{ticketInfo.ticket_no}}</text>
|
|
<text class="ri-file-copy-line copy-icon"></text>
|
|
</view>
|
|
<view class="create-time">创建时间: {{ticketInfo.create_time}}</view>
|
|
</view>
|
|
|
|
<view class="ticket-type" :class="'type-'+ticketInfo.type">
|
|
<text v-if="ticketInfo.type == 'F2'">配送</text>
|
|
<text v-if="ticketInfo.type == 'F4'">量房</text>
|
|
<text v-if="ticketInfo.type == 'F6'">维修</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="ticket-status">
|
|
<view class="status-icon" :class="'status-'+ticketInfo.status">
|
|
<text v-if="ticketInfo.status == 2 || ticketInfo.status == 1"
|
|
class="ri-checkbox-circle-fill"></text>
|
|
<text v-else-if="ticketInfo.status == 3" class="ri-close-circle-fill"></text>
|
|
<text v-else class="ri-time-line"></text>
|
|
</view>
|
|
<view class="status-text">
|
|
<text class="status-title">
|
|
{{ticketInfo.status == 0 ? '待接单' :
|
|
ticketInfo.status == 1 ? '已接单' :
|
|
ticketInfo.status == 2 ? '已完结' :
|
|
ticketInfo.status == 3 ? '已取消' : ''}}
|
|
</text>
|
|
<text class="status-desc">
|
|
{{ticketInfo.status == 0 ? '等待服务人员接单' :
|
|
ticketInfo.status == 1 ? '服务人员已接单' :
|
|
ticketInfo.status == 2 ? '工单已完成' :
|
|
ticketInfo.status == 3 ? '工单已取消' : ''}}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 联系信息 -->
|
|
<view class="info-card">
|
|
<view class="card-title">
|
|
<text class="ri-user-3-line title-icon"></text>
|
|
<text>联系信息</text>
|
|
</view>
|
|
|
|
<view class="info-content">
|
|
<view class="info-item">
|
|
<text class="item-label">小区名称</text>
|
|
<text class="item-value">{{ticketInfo?.order?.village_name}}</text>
|
|
</view>
|
|
|
|
<view class="info-item">
|
|
<text class="item-label">联系人</text>
|
|
<text class="item-value">{{ticketInfo?.order?.name}}</text>
|
|
</view>
|
|
|
|
<view class="info-item">
|
|
<text class="item-label">联系电话</text>
|
|
<view @click="btnPhone(ticketInfo?.order?.mobile)" class="phone-value">
|
|
<text class="ri-phone-line phone-icon"></text>
|
|
<text class="phone-number">{{ticketInfo?.order?.mobile}}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view v-if="ticketInfo?.type == 'F2' " class="info-item product-info">
|
|
<text class="item-label">商品信息</text>
|
|
<view class="product-list-full">
|
|
<!-- 商品列表 -->
|
|
<view v-for="(product, index) in ticketInfo?.product" :key="index" class="product-card-full">
|
|
<view class="product-main">
|
|
<image class="product-image" :src="product.picture" mode="aspectFill" @click="product.picture && previewImages(product.picture, [product.picture])"></image>
|
|
<view class="product-details">
|
|
<text class="product-name">{{product.product_name}}</text>
|
|
<text class="product-spec">{{product.spec_name}}</text>
|
|
<view class="price-quantity">
|
|
<text class="price">¥{{product.price}}</text>
|
|
<text class="quantity">x{{product.num}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 商品总数和总价 -->
|
|
<view class="order-summary">
|
|
<text class="summary-count">共{{ticketInfo?.product.length}}件商品</text>
|
|
<text class="summary-price">合计: ¥{{getTotalPrice()}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 报修信息 -->
|
|
<view v-if="ticketInfo?.type == 'F6'" class="info-card">
|
|
<view class="card-title">
|
|
<text class="ri-tools-line title-icon"></text>
|
|
<text>报修信息</text>
|
|
</view>
|
|
|
|
<view class="info-content">
|
|
<view class="info-item">
|
|
<text class="item-label">报修位置</text>
|
|
<text
|
|
class="item-value">{{ticketInfo?.order?.region_name}}{{ticketInfo?.order?.cell_name}}{{ticketInfo?.order?.house_name}}{{ticketInfo?.order?.address}}</text>
|
|
</view>
|
|
|
|
<view class="info-item">
|
|
<text class="item-label">问题描述</text>
|
|
<text class="item-value">{{ticketInfo?.order?.content}}</text>
|
|
</view>
|
|
|
|
<view v-if="ticketInfo?.order?.images" class="info-item">
|
|
<text class="item-label">现场照片</text>
|
|
<view class="scene-images">
|
|
<image v-for="(item) in ticketInfo?.order?.images?.split(',')" :key="item" class="scene-image"
|
|
:src="item" mode="aspectFill">
|
|
</image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 量房信息 -->
|
|
<view v-if="ticketInfo?.type == 'F4'" class="info-card">
|
|
<view class="card-title">
|
|
<text class="ri-tools-line title-icon"></text>
|
|
<text>量房信息</text>
|
|
</view>
|
|
|
|
<view class="info-content">
|
|
<view class="info-item">
|
|
<text class="item-label">量房位置</text>
|
|
<text
|
|
class="item-value">{{ticketInfo?.order?.village_name}}{{ticketInfo?.order?.region_name}}{{ticketInfo?.order?.cell_name}}{{ticketInfo?.order?.house_name}}{{ticketInfo?.order?.address}}</text>
|
|
</view>
|
|
<view class="info-item">
|
|
<text class="item-label">预约时间</text>
|
|
<text class="item-value">{{ticketInfo?.order?.appoint_date}}
|
|
{{ticketInfo?.order?.appoint_time}}</text>
|
|
</view>
|
|
<view class="info-item">
|
|
<text class="item-label">量房备注</text>
|
|
<text class="item-value">{{ticketInfo?.order?.remark?ticketInfo?.order?.remark:'暂无备注'}}</text>
|
|
</view>
|
|
<view v-if='ticketInfo?.order?.building_area' class="info-item">
|
|
<text class="item-label">面积(平方)</text>
|
|
<text class="item-value">{{ticketInfo?.order?.building_area}}</text>
|
|
</view>
|
|
|
|
<view v-if="ticketInfo?.order?.images" class="info-item">
|
|
<text class="item-label">现场照片</text>
|
|
<view class="scene-images">
|
|
<image v-for="(item) in ticketInfo?.order?.images?.split(',')" :key="item" class="scene-image"
|
|
:src="item" mode="aspectFill">
|
|
</image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 工单记录 -->
|
|
<view v-if="ticketInfo?.record?.length>0" class="info-card">
|
|
<view class="card-title">
|
|
<text class="ri-history-line title-icon"></text>
|
|
<text>工单记录</text>
|
|
</view>
|
|
|
|
<view class="timeline">
|
|
<view class="timeline-item" v-for="(item,index) in ticketInfo.record">
|
|
<view class="timeline-dot"></view>
|
|
<view class="timeline-content">
|
|
<view class="timeline-time">{{item.create_time}}</view>
|
|
<view class="timeline-text">{{item.remark}}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 结单信息模块 -->
|
|
<view v-if="ticketInfo.images || ticketInfo.remark" class="info-card">
|
|
<view class="card-title">
|
|
<text class="ri-check-double-line title-icon"></text>
|
|
<text>结单信息</text>
|
|
</view>
|
|
<view class="info-content">
|
|
<view v-if="ticketInfo.images" class="info-item">
|
|
<text class="item-label">结单照片</text>
|
|
<view class="scene-images">
|
|
<image v-for="(img, idx) in ticketInfo.images.split(',')"
|
|
:key="img"
|
|
class="scene-image"
|
|
:src="img"
|
|
mode="aspectFill"
|
|
@click="previewImages(img, ticketInfo.images.split(','))"
|
|
/>
|
|
</view>
|
|
</view>
|
|
<view v-if="ticketInfo.remark" class="info-item">
|
|
<text class="item-label">结单备注</text>
|
|
<text class="item-value">{{ticketInfo.remark}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 底部按钮 -->
|
|
<view class="footer-actions" v-if="!showCompleteSheet && ticketInfo?.status!=2">
|
|
<view class="action-buttons">
|
|
<wd-button @click="revert" class="action-btn cancel-btn" type="error" :round="true">退单</wd-button>
|
|
<view class="li-ml-20">
|
|
<wd-button class="action-btn confirm-btn" :round="true"
|
|
@click="showCompleteSheet = true">结单</wd-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<wd-message-box />
|
|
|
|
<!-- 结单底部弹出框 -->
|
|
<wd-popup v-model="showCompleteSheet" position="bottom" custom-class="complete-sheet">
|
|
<view class="complete-sheet-content">
|
|
<view class="sheet-header">
|
|
<text class="sheet-title">完成工单</text>
|
|
<text class="ri-close-line close-icon" @click="showCompleteSheet = false"></text>
|
|
</view>
|
|
|
|
<view class="sheet-body">
|
|
<!-- 照片上传区域 -->
|
|
<view class="upload-section">
|
|
<text class="section-title">上传照片(选填)</text>
|
|
<view class="upload-list">
|
|
<view v-for="(item, index) in uploadImages" :key="index" class="upload-item">
|
|
<image :src="item" mode="aspectFill" class="preview-image" @click="previewImages(item, uploadImages)" />
|
|
<text class="ri-close-circle-fill delete-icon" @click="deleteImage(index)"></text>
|
|
</view>
|
|
<view v-if="uploadImages.length < 9" class="upload-btn" @click="chooseImage">
|
|
<text class="ri-add-line add-icon"></text>
|
|
<text class="upload-text">添加照片</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 备注输入区域 -->
|
|
<view class="remark-section">
|
|
<text class="section-title">备注信息(选填)</text>
|
|
<textarea v-model="completeRemark" class="remark-input" placeholder="请输入备注信息"
|
|
maxlength="200"></textarea>
|
|
<text class="word-count">{{completeRemark.length}}/200</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 底部按钮 -->
|
|
<view class="sheet-footer">
|
|
<wd-button type="primary" block @click="handleComplete">确认完成</wd-button>
|
|
</view>
|
|
</view>
|
|
</wd-popup>
|
|
<!-- 上传图片ActionSheet -->
|
|
<wd-action-sheet v-model="showImageActionSheet" :actions="imageActions" @select="handleImageAction"
|
|
cancel-text="取消" />
|
|
|
|
<wd-toast />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed } from 'vue'
|
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
import { useNavigation } from '@/hooks/useNavigation'
|
|
import { myTicketInfo, ticketRevert, ticketFinish } from '@/api/ticket'
|
|
import { useToast, useMessage } from '@/uni_modules/wot-design-uni'
|
|
import { fileUpload } from '@/utils/common'
|
|
|
|
|
|
const Toast = useToast()
|
|
const Message = useMessage()
|
|
|
|
const loading = ref<boolean>(false)
|
|
const bntloading = ref<boolean>(false)
|
|
|
|
const ticketInfo = ref<any>({
|
|
ticket_no: '',
|
|
create_time: '',
|
|
status: undefined,
|
|
type: '',
|
|
order: {
|
|
name: '',
|
|
mobile: '',
|
|
region_name: '',
|
|
cell_name: '',
|
|
house_name: '',
|
|
address: '',
|
|
appoint_date: '',
|
|
appoint_time: '',
|
|
building_area: '',
|
|
status: 0,
|
|
images: '',
|
|
remark: '',
|
|
products: [] // 商品列表
|
|
}
|
|
})
|
|
|
|
// 计算商品总价
|
|
const getTotalPrice = () => {
|
|
let total = 0
|
|
ticketInfo.value?.product.forEach(product => {
|
|
total += product.price * product.num
|
|
})
|
|
return total.toFixed(2)
|
|
}
|
|
|
|
// 使用导航 composable
|
|
const {
|
|
hasMultiplePages, // 是否有多个页面在路由栈中
|
|
isTabBarPage, // 当前页面是否为 tabBar 页面
|
|
checkRouteStack // 检查当前路由栈状态的方法
|
|
} = useNavigation()
|
|
|
|
onLoad((q) => {
|
|
checkRouteStack()
|
|
if (q.ticket_id) {
|
|
loadInfo(q.ticket_id)
|
|
}
|
|
})
|
|
|
|
const loadInfo = async (ticket_id) => {
|
|
const res = await myTicketInfo({ ticket_id })
|
|
ticketInfo.value = res.data
|
|
}
|
|
|
|
// 状态文字配置
|
|
const getStatusText = (status) => {
|
|
const textMap = {
|
|
1: '待配送',
|
|
2: '已完成',
|
|
3: '未入库',
|
|
4: '已取消'
|
|
}
|
|
return textMap[status] || '未知状态'
|
|
}
|
|
|
|
const toPages = (item) => {
|
|
console.log(item);
|
|
switch (item.type) {
|
|
case 'nav':
|
|
uni.navigateBack({
|
|
delta: 1
|
|
});
|
|
break;
|
|
case 'home':
|
|
uni.switchTab({
|
|
url: '/pages/index/index'
|
|
})
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
const handleAction = (action) => {
|
|
console.log(action);
|
|
}
|
|
|
|
const revert = () => {
|
|
Message.confirm({
|
|
msg: '提示',
|
|
title: '确定退单吗?'
|
|
})
|
|
.then(() => {
|
|
getTicketRevert()
|
|
})
|
|
|
|
}
|
|
const getTicketRevert = async () => {
|
|
uni.showLoading({
|
|
title: '退单中...'
|
|
})
|
|
const res = await ticketRevert({
|
|
ticket_id: ticketInfo.value.ticket_id
|
|
})
|
|
uni.hideLoading()
|
|
Toast.success('退单成功')
|
|
setTimeout(() => {
|
|
uni.navigateBack()
|
|
}, 400)
|
|
}
|
|
|
|
const btnPhone = (value : any) => {
|
|
uni.makePhoneCall({
|
|
phoneNumber: value
|
|
})
|
|
}
|
|
|
|
// 结单相关状态
|
|
const showCompleteSheet = ref(false)
|
|
const uploadImages = ref([])
|
|
const completeRemark = ref('')
|
|
|
|
// 新增:上传图片弹窗与选项
|
|
const showImageActionSheet = ref(false)
|
|
const imageActions = [
|
|
{ name: '从相册选择' },
|
|
{ name: '拍照' }
|
|
]
|
|
|
|
// 打开上传图片选择面板
|
|
const chooseImage = () => {
|
|
showImageActionSheet.value = true
|
|
}
|
|
|
|
// 处理图片选择
|
|
const handleImageAction = (action) => {
|
|
if (action.index === 0) {
|
|
handleSelectAlbum()
|
|
} else if (action.index === 1) {
|
|
handleTakePhoto()
|
|
}
|
|
}
|
|
|
|
// 从相册选择
|
|
const handleSelectAlbum = () => {
|
|
uni.chooseImage({
|
|
count: 9 - uploadImages.value.length,
|
|
sizeType: ['compressed'],
|
|
sourceType: ['album'],
|
|
success: async (res) => {
|
|
showImageActionSheet.value = false
|
|
const tempFilePath = res.tempFilePaths[0]
|
|
const fileUrl = await fileUpload(tempFilePath)
|
|
uploadImages.value.push(fileUrl)
|
|
Toast.success('上传成功')
|
|
}
|
|
})
|
|
}
|
|
|
|
// 拍照
|
|
const handleTakePhoto = () => {
|
|
uni.chooseImage({
|
|
count: 1,
|
|
sizeType: ['compressed'],
|
|
sourceType: ['camera'],
|
|
success: async (res) => {
|
|
showImageActionSheet.value = false
|
|
const tempFilePath = res.tempFilePaths[0]
|
|
const fileUrl = await fileUpload(tempFilePath)
|
|
uploadImages.value.push(fileUrl)
|
|
Toast.success('上传成功')
|
|
}
|
|
})
|
|
}
|
|
|
|
// 删除图片
|
|
const deleteImage = (index) => {
|
|
uploadImages.value.splice(index, 1)
|
|
}
|
|
|
|
// 处理结单
|
|
const handleComplete = async () => {
|
|
try {
|
|
uni.showLoading({ title: '提交中...' })
|
|
const res = await ticketFinish({
|
|
ticket_id: ticketInfo.value.ticket_id,
|
|
images: uploadImages.value.join(','),
|
|
remark: completeRemark.value
|
|
})
|
|
uni.hideLoading()
|
|
if (res.code == 200) {
|
|
Toast.success('工单已完成')
|
|
showCompleteSheet.value = false
|
|
setTimeout(() => {
|
|
uni.navigateBack()
|
|
}, 1500)
|
|
}
|
|
} catch (error) {
|
|
uni.hideLoading()
|
|
uni.showToast({ title: '操作失败', icon: 'error' })
|
|
}
|
|
}
|
|
|
|
// 图片预览
|
|
const previewImages = (current, images) => {
|
|
uni.previewImage({
|
|
current,
|
|
urls: images
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.detail-page {
|
|
width: 100%;
|
|
min-height: 100vh;
|
|
background: linear-gradient(to bottom,
|
|
rgba(233, 245, 255, 0.9) 0%,
|
|
rgba(245, 250, 255, 0.9) 30%,
|
|
rgba(245, 250, 255, 0.9) 70%,
|
|
rgba(233, 245, 255, 0.9) 100%);
|
|
background-attachment: fixed;
|
|
padding-bottom: 180rpx;
|
|
}
|
|
|
|
.navbar-content {
|
|
display: flex;
|
|
align-items: center;
|
|
padding-left: 20rpx;
|
|
|
|
.back-icon,
|
|
.home-icon {
|
|
font-size: 70rpx;
|
|
color: #333;
|
|
margin-right: 10rpx;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 42rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
/* 导航栏背景层 */
|
|
.nav-bg-layer {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: var(--window-top);
|
|
background: linear-gradient(to bottom,
|
|
rgba(217, 237, 255, 0.95),
|
|
rgba(217, 237, 255, 0.85));
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
z-index: 998;
|
|
}
|
|
|
|
/* 卡片通用样式 */
|
|
.ticket-card,
|
|
.info-card {
|
|
width: 92%;
|
|
margin: 0 auto;
|
|
margin-bottom: 30rpx;
|
|
border-radius: 20rpx;
|
|
background: #fff;
|
|
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.05);
|
|
overflow: hidden;
|
|
|
|
&:active {
|
|
transform: scale(0.99);
|
|
transition: transform 0.2s;
|
|
}
|
|
}
|
|
|
|
/* 工单状态卡片 */
|
|
.ticket-card {
|
|
margin-top: 40rpx;
|
|
padding-bottom: 30rpx;
|
|
|
|
.ticket-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
padding: 20rpx;
|
|
background-color: #f8faff;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
|
|
.ticket-info {
|
|
.ticket-id {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 12rpx;
|
|
|
|
.id-icon {
|
|
font-size: 32rpx;
|
|
color: #666;
|
|
margin-right: 8rpx;
|
|
}
|
|
|
|
.id-text {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.copy-icon {
|
|
font-size: 28rpx;
|
|
color: #009aff;
|
|
margin-left: 15rpx;
|
|
}
|
|
}
|
|
|
|
.create-time {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.ticket-type {
|
|
padding: 6rpx 20rpx;
|
|
border-bottom-left-radius: 20rpx;
|
|
font-size: 26rpx;
|
|
font-weight: 500;
|
|
color: #37A5FF;
|
|
background-color: #e8f4ff;
|
|
|
|
&.type-F2 {
|
|
color: #ff9d00;
|
|
background-color: #fff6e9;
|
|
}
|
|
|
|
&.type-F6 {
|
|
color: #00b42a;
|
|
background-color: #e8ffea;
|
|
}
|
|
|
|
&.type-F4 {
|
|
color: #7e3ff2;
|
|
background-color: #f0e8ff;
|
|
}
|
|
}
|
|
}
|
|
|
|
.ticket-status {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 20rpx;
|
|
|
|
.status-icon {
|
|
margin-right: 20rpx;
|
|
font-size: 40rpx;
|
|
color: #009aff;
|
|
|
|
&.status-2 {
|
|
color: #00b42a;
|
|
}
|
|
|
|
&.status-3 {
|
|
color: #f42429;
|
|
}
|
|
|
|
&.status-0 {
|
|
color: #ff9d00;
|
|
}
|
|
}
|
|
|
|
.status-text {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.status-title {
|
|
font-size: 32rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
|
|
.status-desc {
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 详情卡片样式 */
|
|
.info-card {
|
|
padding: 0 0 20rpx 0;
|
|
|
|
.card-title {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 25rpx 30rpx;
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
|
|
.title-icon {
|
|
margin-right: 10rpx;
|
|
color: #009aff;
|
|
}
|
|
}
|
|
|
|
.info-content {
|
|
padding: 20rpx 30rpx;
|
|
|
|
.info-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 25rpx;
|
|
|
|
.item-label {
|
|
width: 150rpx;
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.item-value {
|
|
width: 400rpx;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
text-align: right;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.phone-value {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
|
|
.phone-icon {
|
|
color: #009aff;
|
|
margin-right: 8rpx;
|
|
}
|
|
|
|
.phone-number {
|
|
font-size: 26rpx;
|
|
color: #009aff;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
&.product-info {
|
|
display: block;
|
|
margin-top: 30rpx;
|
|
|
|
.item-label {
|
|
display: block;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.product-list-full {
|
|
width: 100%;
|
|
background-color: #f9f9f9;
|
|
border-radius: 12rpx;
|
|
margin-bottom: 15rpx;
|
|
padding: 16rpx 0;
|
|
|
|
.product-card-full {
|
|
width: 92%;
|
|
margin: 16rpx auto;
|
|
padding-bottom: 16rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
border-bottom: none;
|
|
}
|
|
|
|
.product-main {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
width: 100%;
|
|
|
|
.product-image {
|
|
width: 140rpx;
|
|
height: 140rpx;
|
|
border-radius: 10rpx;
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
background-color: #fff;
|
|
}
|
|
|
|
.product-details {
|
|
flex: 1;
|
|
padding-left: 20rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
min-height: 140rpx;
|
|
|
|
.product-name {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 1.4;
|
|
margin-bottom: 8rpx;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.product-spec {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.price-quantity {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-top: auto;
|
|
|
|
.price {
|
|
font-size: 30rpx;
|
|
color: #FF6B00;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.quantity {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.order-summary {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
width: 92%;
|
|
margin: 16rpx auto 8rpx;
|
|
border-top: solid 1px #f0f0f0;
|
|
padding-top: 16rpx;
|
|
|
|
.summary-count {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.summary-price {
|
|
font-size: 30rpx;
|
|
color: #FF6B00;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.scene-images {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
flex-wrap: wrap;
|
|
width: 400rpx;
|
|
|
|
.scene-image {
|
|
width: 110rpx;
|
|
height: 110rpx;
|
|
border-radius: 10rpx;
|
|
margin-left: 20rpx;
|
|
margin-bottom: 10rpx;
|
|
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 时间线样式 */
|
|
.timeline {
|
|
padding: 10rpx 30rpx 10rpx 40rpx;
|
|
position: relative;
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 50rpx;
|
|
width: 2rpx;
|
|
height: 100%;
|
|
background-color: rgba(0, 154, 255, 0.2);
|
|
z-index: 1;
|
|
}
|
|
|
|
.timeline-item {
|
|
position: relative;
|
|
padding: 15rpx 0 15rpx 30rpx;
|
|
|
|
.timeline-dot {
|
|
position: absolute;
|
|
left: -12rpx;
|
|
top: 25rpx;
|
|
width: 24rpx;
|
|
height: 24rpx;
|
|
border-radius: 50%;
|
|
background-color: #009aff;
|
|
border: 4rpx solid rgba(0, 154, 255, 0.3);
|
|
z-index: 2;
|
|
}
|
|
|
|
.timeline-content {
|
|
.timeline-time {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-bottom: 6rpx;
|
|
}
|
|
|
|
.timeline-text {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 底部按钮样式 */
|
|
.footer-actions {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
padding: 30rpx 30rpx;
|
|
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
background-color: #fff;
|
|
box-shadow: 0 -4rpx 10rpx rgba(0, 0, 0, 0.05);
|
|
z-index: 99;
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
|
|
.action-btn {
|
|
min-width: 180rpx !important;
|
|
height: 80rpx !important;
|
|
border-radius: 40rpx !important;
|
|
font-size: 28rpx !important;
|
|
box-shadow: 0 6rpx 10rpx rgba(0, 0, 0, 0.1);
|
|
|
|
&.cancel-btn {
|
|
background: linear-gradient(to right, #ff6b6b, #ff4757) !important;
|
|
}
|
|
|
|
&.confirm-btn {
|
|
background: linear-gradient(to right, #5eafff, #4090ff) !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ::v-deep .wd-button {
|
|
// width: auto !important;
|
|
// height: 80rpx !important;
|
|
// min-width: 180rpx !important;
|
|
// margin-right: 20rpx !important;
|
|
// }
|
|
::v-deep .wd-message-box__flex {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.complete-sheet {
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
|
|
.complete-sheet-content {
|
|
width: 90%;
|
|
margin: 30rpx auto 10rpx;
|
|
padding-bottom: calc(30rpx + constant(safe-area-inset-bottom));
|
|
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
|
|
}
|
|
|
|
.sheet-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 30rpx;
|
|
|
|
.sheet-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.close-icon {
|
|
font-size: 40rpx;
|
|
color: #999;
|
|
padding: 10rpx;
|
|
}
|
|
}
|
|
|
|
.sheet-body {
|
|
.section-title {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
margin-bottom: 20rpx;
|
|
display: block;
|
|
}
|
|
|
|
.upload-section {
|
|
margin-bottom: 30rpx;
|
|
|
|
.upload-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
margin: 0 -8rpx;
|
|
}
|
|
|
|
.upload-item {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
margin: 8rpx;
|
|
position: relative;
|
|
|
|
.preview-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 10rpx;
|
|
}
|
|
|
|
.delete-icon {
|
|
position: absolute;
|
|
top: -10rpx;
|
|
right: -10rpx;
|
|
font-size: 32rpx;
|
|
color: #ff4d4f;
|
|
background: #fff;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
|
|
.upload-btn {
|
|
width: 160rpx;
|
|
height: 160rpx;
|
|
margin: 8rpx;
|
|
background: #f7f8fa;
|
|
border: 2rpx dashed #ddd;
|
|
border-radius: 10rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.add-icon {
|
|
font-size: 40rpx;
|
|
color: #999;
|
|
margin-bottom: 6rpx;
|
|
}
|
|
|
|
.upload-text {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
|
|
.remark-section {
|
|
position: relative;
|
|
|
|
.remark-input {
|
|
width: 100%;
|
|
min-height: 120rpx;
|
|
max-height: 260rpx;
|
|
background: #f7f8fa;
|
|
border-radius: 12rpx;
|
|
padding: 24rpx;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
border: 2rpx solid #f0f0f0;
|
|
box-sizing: border-box;
|
|
resize: none;
|
|
transition: border-color 0.2s;
|
|
}
|
|
|
|
.remark-input:focus {
|
|
border-color: #5eafff;
|
|
background: #fff;
|
|
outline: none;
|
|
}
|
|
|
|
.word-count {
|
|
position: absolute;
|
|
right: 20rpx;
|
|
bottom: 20rpx;
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
|
|
.sheet-footer {
|
|
margin-top: 40rpx;
|
|
}
|
|
}
|
|
</style> |