@ -0,0 +1,17 @@ | |||
import request from '@/utils/request' | |||
// 获取订单列表 | |||
export function getAppOrderList() { | |||
return request({ | |||
headers: { | |||
"isToken": true | |||
}, | |||
url: "/applet/order/getAppOrderList", | |||
method: 'get' | |||
}) | |||
} | |||
export default { | |||
getAppOrderList | |||
} |
@ -1,62 +1,63 @@ | |||
{ | |||
"name" : "uni-vuu3", | |||
"appid" : "__UNI__08423D1", | |||
"description" : "", | |||
"versionName" : "1.0.0", | |||
"versionCode" : "100", | |||
"transformPx" : false, | |||
"app-plus" : { | |||
/* 5+App特有相关 */ | |||
"usingComponents" : true, | |||
"nvueCompiler" : "uni-app", | |||
"nvueStyleCompiler" : "uni-app", | |||
"splashscreen" : { | |||
"alwaysShowBeforeRender" : true, | |||
"waiting" : true, | |||
"autoclose" : true, | |||
"delay" : 0 | |||
}, | |||
"modules" : {}, | |||
/* 模块配置 */ | |||
"distribute" : { | |||
/* 应用发布信息 */ | |||
"android" : { | |||
/* android打包配置 */ | |||
"permissions" : [ | |||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", | |||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", | |||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", | |||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", | |||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", | |||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.CAMERA\"/>", | |||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", | |||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", | |||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", | |||
"<uses-feature android:name=\"android.hardware.camera\"/>", | |||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" | |||
] | |||
}, | |||
"ios" : {}, | |||
/* ios打包配置 */ | |||
"sdkConfigs" : {} | |||
} | |||
}, | |||
/* SDK配置 */ | |||
"quickapp" : {}, | |||
/* 快应用特有相关 */ | |||
"mp-weixin" : { | |||
"appid" : "wx01f0f43759922fda", | |||
"setting" : { | |||
"urlCheck" : false, | |||
"postcss" : true, | |||
"minified" : true | |||
}, | |||
"usingComponents" : true, | |||
"mergeVirtualHostAttributes" : true | |||
}, | |||
"vueVersion" : "3" | |||
} | |||
"name": "uni-vuu3", | |||
"appid": "", | |||
"description": "", | |||
"versionName": "1.0.0", | |||
"versionCode": "100", | |||
"transformPx": false, | |||
"app-plus": { | |||
/* 5+App特有相关 */ | |||
"usingComponents": true, | |||
"nvueCompiler": "uni-app", | |||
"nvueStyleCompiler": "uni-app", | |||
"splashscreen": { | |||
"alwaysShowBeforeRender": true, | |||
"waiting": true, | |||
"autoclose": true, | |||
"delay": 0 | |||
}, | |||
"modules": {}, | |||
/* 模块配置 */ | |||
"distribute": { | |||
/* 应用发布信息 */ | |||
"android": { | |||
/* android打包配置 */ | |||
"permissions": [ | |||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", | |||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", | |||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", | |||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", | |||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", | |||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.CAMERA\"/>", | |||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", | |||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", | |||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", | |||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", | |||
"<uses-feature android:name=\"android.hardware.camera\"/>", | |||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" | |||
] | |||
}, | |||
"ios": {}, | |||
/* ios打包配置 */ | |||
"sdkConfigs": {} | |||
} | |||
}, | |||
/* SDK配置 */ | |||
"quickapp": {}, | |||
/* 快应用特有相关 */ | |||
"mp-weixin": { | |||
/* 小程序特有相关 */ | |||
"appid": "wx01f0f43759922fda", | |||
"setting": { | |||
"urlCheck": false, | |||
"postcss": true, | |||
"minified": true | |||
}, | |||
"usingComponents": true, | |||
"mergeVirtualHostAttributes": true | |||
}, | |||
"vueVersion": "3" | |||
} |
@ -0,0 +1,415 @@ | |||
<template> | |||
<up-list @scrolltolower="scrolltolower"> | |||
<template v-for="(item, index) in orderList" :key="index"> | |||
<view class="date-label"> | |||
<view class="date-box">{{ item.date }}</view> | |||
<view class="order-tag"> | |||
<template v-if="item.orders[0].status === 'completed'">已完成{{ item.orders.length }}单</template> | |||
<template v-else>待上门{{ item.orders.length }}单</template> | |||
</view> | |||
</view> | |||
<view class="timeline-container"> | |||
<view class="timeline-line" :class="{'timeline-line-completed': item.orders[0].status === 'completed'}"> | |||
</view> | |||
<up-list-item v-for="(order, orderIndex) in item.orders" :key="orderIndex"> | |||
<view class="timeline-item" :class="{'item-completed': order.status === 'completed'}"> | |||
<view class="timeline-dot"></view> | |||
<view class="mb28 container-list-item"> | |||
<view class="order-time-tag" | |||
:class="{'order-time-tag-completed' : order.status === 'completed'}"> | |||
<view class="time-box">{{ order.time }}</view> | |||
<view class="order-status"> | |||
<view class="status-icon"></view> | |||
<view> | |||
<template v-if="order.status === 'completed'">已完成{{ order.count }}单</template> | |||
<template v-else>待上门{{ order.count }}单</template> | |||
</view> | |||
</view> | |||
</view> | |||
<view class="container-list"> | |||
<view class="flex-between flex"> | |||
<view class="address-info flex"> | |||
<view class="address-icon"></view> | |||
<view class="address-text">{{ order.address }}</view> | |||
</view> | |||
<view class="expand-btn" @click="toggleExpand(index, orderIndex)"> | |||
{{ order.isExpanded ? '收起' : '展开' }} <text | |||
class="expand-icon">{{ order.isExpanded ? '∧' : '∨' }}</text> | |||
</view> | |||
</view> | |||
<view v-if="order.isExpanded" class="pet-info"> | |||
<view class="pet-title">陪伴对象</view> | |||
<view class="pet-list"> | |||
<view v-for="(pet, petIndex) in order.pets" :key="petIndex" class="pet-item"> | |||
<view class="pet-avatar"> | |||
<up-image width="70px" height="70px" :src="pet.avatar" | |||
shape="circle"></up-image> | |||
</view> | |||
<view class="pet-detail"> | |||
<view class="pet-name">{{ pet.name }} <text | |||
class="pet-tag">{{ pet.tag }}</text></view> | |||
<view class="pet-desc">{{ pet.desc }}</view> | |||
</view> | |||
</view> | |||
</view> | |||
<view class="address-detail mb28">{{ order.fullAddress }}</view> | |||
<view class="action-buttons flex flex-between"> | |||
<up-button type="primary" text="打卡" v-if="false" @click="toClock" shape="circle" | |||
class="mr20" color="var(--status-color)"></up-button> | |||
<up-button type="primary" text="查看订单详情" @click="toDetail" shape="circle" | |||
class="mr20" color="var(--status-color)"></up-button> | |||
<up-button type="primary" text="查看宠物档案" @click="toPet" shape="circle" | |||
class="mr20" color="var(--status-color)"></up-button> | |||
<up-button type="primary" text="服务档案" @click="toService" shape="circle" | |||
color="var(--status-color)"></up-button> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
</view> | |||
</up-list-item> | |||
</view> | |||
</template> | |||
</up-list> | |||
</template> | |||
<script setup> | |||
import { | |||
ref, | |||
reactive, | |||
defineProps | |||
} from 'vue'; | |||
const { | |||
list | |||
} = defineProps({ | |||
list: { | |||
type: Array, | |||
required: true | |||
}, | |||
}); | |||
// 模拟订单数据 | |||
const orderList = reactive([{ | |||
date: '12-04', | |||
orders: [{ | |||
time: '12-04', | |||
count: 2, | |||
status: 'completed', // 已完成状态 | |||
address: '湖南省长沙市雨花区人民东路', | |||
fullAddress: '湖南省长沙市雨花区人民东路88号', | |||
isExpanded: true, | |||
pets: [{ | |||
avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png', | |||
name: '小咪', | |||
tag: '猫', | |||
desc: '中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩' | |||
}, | |||
{ | |||
avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png', | |||
name: 'Billion', | |||
tag: '狗', | |||
desc: '狗狗(小型狗) | 上门喂养+陪玩' | |||
} | |||
] | |||
}] | |||
}, | |||
{ | |||
date: '12-05', | |||
orders: [{ | |||
time: '12-05', | |||
count: 1, | |||
status: 'completed', // 已完成状态 | |||
address: '湖南省长沙市雨花区人民东路', | |||
fullAddress: '湖南省长沙市雨花区人民东路88号', | |||
isExpanded: false, | |||
pets: [{ | |||
avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png', | |||
name: '小黑', | |||
tag: '狗', | |||
desc: '中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩' | |||
}] | |||
}] | |||
}, | |||
{ | |||
date: '12-08', | |||
orders: [{ | |||
time: '12-08', | |||
count: 1, | |||
status: 'pending', // 待上门状态 | |||
address: '湖南省长沙市雨花区人民东路', | |||
fullAddress: '湖南省长沙市雨花区人民东路88号', | |||
isExpanded: false, | |||
pets: [{ | |||
avatar: 'https://cdn.catmdogd.com/Work/image/work/tx.png', | |||
name: '小白', | |||
tag: '猫', | |||
desc: '中华田园猫 | 专业喂养+提前熟悉+陪玩' | |||
}] | |||
}] | |||
} | |||
]); | |||
// 展开/收起订单详情 | |||
function toggleExpand(dateIndex, orderIndex) { | |||
orderList[dateIndex].orders[orderIndex].isExpanded = !orderList[dateIndex].orders[orderIndex].isExpanded; | |||
} | |||
// 滚动到底部加载更多 | |||
const scrolltolower = () => { | |||
// 实际项目中这里应该调用API加载更多数据 | |||
console.log('加载更多数据'); | |||
} | |||
// 页面跳转函数 | |||
function toClock() { | |||
uni.navigateTo({ | |||
url: "/otherPages/myOrdersManage/clock/index" | |||
}) | |||
} | |||
function toDetail() { | |||
uni.navigateTo({ | |||
url: "/otherPages/orderTakingManage/detail/index" | |||
}) | |||
} | |||
function toPet() { | |||
uni.navigateTo({ | |||
url: "/otherPages/orderTakingManage/pet/index" | |||
}) | |||
} | |||
function toService() { | |||
uni.navigateTo({ | |||
url: "/otherPages/myOrdersManage/service/index" | |||
}) | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
@import "../index"; | |||
.date-label { | |||
display: flex; | |||
align-items: center; | |||
margin: 20rpx 0; | |||
position: relative; | |||
z-index: 3; | |||
.date-box { | |||
background: #333333; | |||
color: #FFFFFF; | |||
padding: 8rpx 16rpx; | |||
border-radius: 8rpx; | |||
font-size: 24rpx; | |||
margin-right: 20rpx; | |||
} | |||
.order-tag { | |||
color: #7D8196; | |||
font-size: 24rpx; | |||
} | |||
} | |||
.order-time-tag { | |||
display: flex; | |||
align-items: center; | |||
background: rgba(#FFAA48, 0.2); | |||
padding: 22rpx 42rpx; | |||
.time-box { | |||
background: var(--status-color); | |||
color: #FFFFFF; | |||
padding: 4rpx 12rpx; | |||
border-radius: 8rpx; | |||
font-size: 24rpx; | |||
margin-right: 20rpx; | |||
} | |||
.order-status { | |||
display: flex; | |||
align-items: center; | |||
font-size: 24rpx; | |||
.status-icon { | |||
width: 24rpx; | |||
height: 24rpx; | |||
background: var(--status-color); | |||
border-radius: 50%; | |||
margin-right: 10rpx; | |||
} | |||
.status-icon-completed { | |||
background: #4CD964; | |||
} | |||
} | |||
} | |||
.order-time-tag-completed { | |||
background: rgba(#4CD964, 0.2); | |||
} | |||
.time-box-completed { | |||
background: #4CD964; | |||
} | |||
.address-info { | |||
display: flex; | |||
align-items: center; | |||
margin: 20rpx 0; | |||
.address-icon { | |||
width: 36rpx; | |||
height: 36rpx; | |||
background: var(--status-color); | |||
border-radius: 50%; | |||
margin-right: 12rpx; | |||
} | |||
.address-icon-completed { | |||
background: #4CD964; | |||
} | |||
.address-text { | |||
font-size: 28rpx; | |||
color: #333333; | |||
font-weight: 500; | |||
} | |||
} | |||
.expand-btn { | |||
font-size: 26rpx; | |||
color: #FFAA48; | |||
font-weight: 500; | |||
.expand-icon { | |||
margin-left: 8rpx; | |||
} | |||
} | |||
.expand-btn-completed { | |||
color: #4CD964; | |||
} | |||
.pet-info { | |||
margin-top: 20rpx; | |||
.pet-title { | |||
font-size: 28rpx; | |||
color: #333333; | |||
margin-bottom: 16rpx; | |||
} | |||
.pet-list { | |||
.pet-item { | |||
display: flex; | |||
margin-bottom: 20rpx; | |||
.pet-avatar { | |||
margin-right: 20rpx; | |||
flex-shrink: 0; | |||
} | |||
.pet-detail { | |||
.pet-name { | |||
font-size: 28rpx; | |||
color: #333333; | |||
margin-bottom: 10rpx; | |||
.pet-tag { | |||
background: var(--status-color); | |||
color: #FFFFFF; | |||
padding: 2rpx 10rpx; | |||
border-radius: 20rpx; | |||
font-size: 20rpx; | |||
margin-left: 10rpx; | |||
} | |||
} | |||
.pet-desc { | |||
font-size: 24rpx; | |||
color: #7D8196; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
.address-detail { | |||
background: #F6FAFC; | |||
border-radius: 8rpx; | |||
padding: 14rpx 20rpx; | |||
font-size: 24rpx; | |||
color: #7D8196; | |||
margin: 20rpx 0; | |||
} | |||
.action-buttons { | |||
display: flex; | |||
justify-content: space-between; | |||
margin-top: 20rpx; | |||
} | |||
\t | |||
/* 时间线样式 */ | |||
.timeline-container { | |||
position: relative; | |||
padding-left: 40rpx; | |||
margin-bottom: 30rpx; | |||
z-index: 1; | |||
} | |||
.timeline-line { | |||
position: absolute; | |||
left: 20rpx; | |||
top: 0; | |||
height: 100%; | |||
width: 2rpx; | |||
background-color: #FFAA48; | |||
z-index: 0; | |||
} | |||
.timeline-line-completed { | |||
background-color: #4CD964; | |||
} | |||
.timeline-item { | |||
position: relative; | |||
padding-left: 30rpx; | |||
margin-bottom: 20rpx; | |||
} | |||
.timeline-dot { | |||
position: absolute; | |||
left: -10rpx; | |||
top: 30rpx; | |||
width: 20rpx; | |||
height: 20rpx; | |||
border-radius: 50%; | |||
background-color: #FFAA48; | |||
z-index: 2; | |||
border: 4rpx solid #FFF; | |||
} | |||
.timeline-dot-completed { | |||
background-color: #4CD964; | |||
} | |||
/* 默认状态颜色变量 */ | |||
.timeline-item { | |||
--status-color: #FFAA48; | |||
} | |||
/* 添加状态类,集中控制样式 */ | |||
.item-completed { | |||
--status-color: #4CD964; | |||
} | |||
</style> |
@ -1,73 +1,91 @@ | |||
<template> | |||
<up-list | |||
@scrolltolower="scrolltolower" | |||
> | |||
<up-list-item> | |||
<view class="mb28 container-list-item"> | |||
<view class="flex-between flex" style="background: #FFF4E5;padding: 22rpx 42rpx"> | |||
<view>待接单</view> | |||
<view>本单酬劳 | |||
<text style="color: #FF530A">¥260</text> | |||
</view> | |||
</view> | |||
<view class="container-list"> | |||
<view class="flex-between flex mb28"> | |||
<up-image style="flex-shrink:0" class="mr20" width="70px" height="70px" | |||
src="https://cdn.catmdogd.com/Work/image/work/tx.png" | |||
shape="circle"></up-image> | |||
<view> | |||
<view class="font28 col3">服务天数: 共2天 I 12-07,12-08</view> | |||
<view style="margin: 18rpx 0">期望上门时间:早</view> | |||
<view>中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩</view> | |||
</view> | |||
<up-list @scrolltolower="scrolltolower"> | |||
<up-list-item> | |||
<view class="mb28 container-list-item" | |||
v-for="(item, index) in 1"> | |||
<view class="flex-between flex" style="background: #FFF4E5;padding: 22rpx 42rpx"> | |||
<view>待接单</view> | |||
<view>本单酬劳 | |||
<text style="color: #FF530A">¥{{ item.orderAmount }}</text> | |||
</view> | |||
</view> | |||
<view class="container-list"> | |||
<view class="flex-between flex mb28"> | |||
<up-image style="flex-shrink:0" class="mr20" width="70px" height="70px" | |||
src="https://cdn.catmdogd.com/Work/image/work/tx.png" shape="circle"></up-image> | |||
<view> | |||
<view class="font28 col3">服务天数: 共{{ item.orderServiceTime }}天 I {{ item.orderServiceDate }}</view> | |||
<view style="margin: 18rpx 0">期望上门时间:早</view> | |||
<view>中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩</view> | |||
</view> | |||
</view> | |||
<view class="mb28 address">{{ item.orderVisitAddress }}</view> | |||
<view class="mb28">订单为系统派发,请确认订单信息后再抢单</view> | |||
<view class="flex flex-between"> | |||
<up-button type="primary" | |||
v-if="true" | |||
text="打卡" @click="toClock" shape="circle" class="mr20" | |||
color="#FFAA48"></up-button> | |||
</view> | |||
<view class="mb28 address">重庆市南岸区长嘉汇</view> | |||
<view class="mb28">订单为系统派发,请确认订单信息后再抢单</view> | |||
<view class="flex flex-between"> | |||
<up-button type="primary" text="查看订单详情" shape="circle" class="mr20" color="#FFAA48"></up-button> | |||
<up-button type="primary" text="查看宠物档案" shape="circle" class="mr20" color="#FFAA48"></up-button> | |||
<up-button type="primary" text="查看服务档案" shape="circle" color="#FFAA48"></up-button> | |||
</view> | |||
</view> | |||
</view> | |||
<view class="mb28 container-list-item"> | |||
<view class="flex-between flex" style="background: #FFF4E5;padding: 22rpx 42rpx"> | |||
<view>待接单</view> | |||
<view>本单酬劳 | |||
<text style="color: #FF530A">¥260</text> | |||
</view> | |||
</view> | |||
<view class="container-list"> | |||
<view class="flex-between flex mb28"> | |||
<up-image style="flex-shrink:0" class="mr20" width="70px" height="70px" | |||
src="https://cdn.catmdogd.com/Work/image/work/tx.png" | |||
shape="circle"></up-image> | |||
<view> | |||
<view class="font28 col3">服务天数: 共2天 I 12-07,12-08</view> | |||
<view style="margin: 18rpx 0">期望上门时间:早</view> | |||
<view>中华田园犬(小型犬) | 专业喂养+提前熟悉+陪玩</view> | |||
</view> | |||
<up-button type="primary" | |||
v-else | |||
text="查看订单详情" @click="toDetail" shape="circle" class="mr20" | |||
color="#FFAA48"></up-button> | |||
</view> | |||
<view class="mb28 address">重庆市南岸区长嘉汇</view> | |||
<view class="mb28">订单为系统派发,请确认订单信息后再抢单</view> | |||
<view class="flex flex-between"> | |||
<up-button type="primary" text="查看订单详情" shape="circle" class="mr20" color="#FFAA48"></up-button> | |||
<up-button type="primary" text="查看宠物档案" shape="circle" class="mr20" color="#FFAA48"></up-button> | |||
<up-button type="primary" text="查看服务档案" shape="circle" color="#FFAA48"></up-button> | |||
</view> | |||
</view> | |||
</view> | |||
</up-list-item> | |||
</up-list> | |||
<up-button type="primary" text="查看宠物档案" @click="toPet" shape="circle" class="mr20" | |||
color="#FFAA48"></up-button> | |||
<up-button type="primary" text="查看服务档案" @click="toService" shape="circle" | |||
color="#FFAA48"></up-button> | |||
</view> | |||
</view> | |||
</view> | |||
</up-list-item> | |||
</up-list> | |||
</template> | |||
<script setup> | |||
const scrolltolower = () => { | |||
const scrolltolower = () => { | |||
} | |||
import { | |||
defineProps | |||
} from 'vue'; | |||
const { list } = defineProps({ | |||
list: { | |||
type: Array, | |||
required: true | |||
}, | |||
}); | |||
function toClock() { | |||
uni.navigateTo({ | |||
url: "/otherPages/myOrdersManage/clock/index" | |||
}) | |||
} | |||
function toDetail() { | |||
uni.navigateTo({ | |||
url: "/otherPages/orderTakingManage/detail/index" | |||
}) | |||
} | |||
function toPet() { | |||
uni.navigateTo({ | |||
url: "/otherPages/orderTakingManage/pet/index" | |||
}) | |||
} | |||
} | |||
function toService() { | |||
uni.navigateTo({ | |||
url: "/otherPages/myOrdersManage/service/index" | |||
}) | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
@import "../index"; | |||
@import "../index"; | |||
</style> |
@ -1,67 +1,119 @@ | |||
<template> | |||
<view> | |||
<view class="header-buts flex flex-center"> | |||
<view class="flex buts-box"> | |||
<view class="buts" :class="{'buts-active':activeIndex===1}" @click="activeIndex=1">总订单</view> | |||
<view class="buts" :class="{'buts-active':activeIndex===2}" @click="activeIndex=2">日订单</view> | |||
</view> | |||
</view> | |||
<up-sticky bgColor="#fff"> | |||
<view class="container-tabs"> | |||
<up-tabs :list="list" lineWidth="68rpx" | |||
:activeStyle="{ | |||
color: '#FFFFFF', | |||
fontWeight: 'bold', | |||
transform: 'scale(1.05)' | |||
}" | |||
:inactiveStyle="{ | |||
color: '#FFFFFF', | |||
transform: 'scale(1)' | |||
}" | |||
:itemStyle="{height:'88rpx',padding:'0 52rpx'}" | |||
lineColor="#FFFFFF"></up-tabs> | |||
</view> | |||
</up-sticky> | |||
<view> | |||
<view class="header-buts flex flex-center"> | |||
<view class="flex buts-box"> | |||
<view class="buts" :class="{'buts-active':activeIndex===1}" @click="activeIndex=1">总订单</view> | |||
<view class="buts" :class="{'buts-active':activeIndex===2}" @click="activeIndex=2">日订单</view> | |||
</view> | |||
</view> | |||
<up-sticky bgColor="#fff" v-if="activeIndex == 1"> | |||
<view class="container-tabs"> | |||
<up-tabs :list="tabList1" lineWidth="68rpx" :activeStyle="{ | |||
color: '#FFFFFF', | |||
fontWeight: 'bold', | |||
transform: 'scale(1.05)' | |||
}" :inactiveStyle="{ | |||
color: '#FFFFFF', | |||
transform: 'scale(1)' | |||
}" :itemStyle="{height:'88rpx',padding:'0 52rpx'}" lineColor="#FFFFFF"></up-tabs> | |||
</view> | |||
</up-sticky> | |||
<up-sticky bgColor="#fff" v-else> | |||
<view class="container-tabs"> | |||
<up-tabs :list="tabList2" | |||
lineWidth="68rpx" | |||
:activeStyle="{ | |||
color: '#FFFFFF', | |||
fontWeight: 'bold', | |||
transform: 'scale(1.05)' | |||
}" | |||
:inactiveStyle="{ | |||
color: '#FFFFFF', | |||
transform: 'scale(1)' | |||
}" | |||
:itemStyle="{height:'88rpx',padding:'0 52rpx', width : '400rpx'}" | |||
lineColor="#FFFFFF"></up-tabs> | |||
</view> | |||
</up-sticky> | |||
<view class="container"> | |||
<systemOrder v-if="current===0"/> | |||
<personOrder v-if="current===1"/> | |||
<lossOrder v-if="current===2"/> | |||
</view> | |||
</view> | |||
<view class="container"> | |||
<systemOrder :list="list" v-if="activeIndex == 1"/> | |||
<orderListByData :list="list" v-else/> | |||
</view> | |||
</view> | |||
</template> | |||
<script setup> | |||
import {reactive, ref} from "vue"; | |||
import systemOrder from "./components/systemOrder.vue"; | |||
import personOrder from "./components/personOrder.vue"; | |||
import lossOrder from "./components/lossOrder.vue"; | |||
import { | |||
reactive, | |||
ref | |||
} from "vue"; | |||
import systemOrder from "./components/systemOrder.vue"; | |||
import orderListByData from "./components/orderListByData.vue"; | |||
// import personOrder from "./components/personOrder.vue"; | |||
// import lossOrder from "./components/lossOrder.vue"; | |||
import { | |||
getAppOrderList, | |||
} from "@/api/order/order.js" | |||
const current = ref(0) | |||
const activeIndex = ref(1) | |||
const list = reactive([ | |||
{ | |||
name: '系统派单', | |||
badge: { | |||
value: 5, | |||
} | |||
}, | |||
{ | |||
name: '个人订单', | |||
badge: { | |||
value: 5, | |||
} | |||
}, | |||
{ | |||
name: '流失订单', | |||
badge: { | |||
value: 5, | |||
} | |||
}, | |||
]) | |||
const current = ref(0) | |||
const activeIndex = ref(1) | |||
const list = ref([]) | |||
const tabList1 = reactive([{ | |||
name: '待服务', | |||
badge: { | |||
// value: 5, | |||
} | |||
}, | |||
{ | |||
name: '进行中', | |||
badge: { | |||
// value: 5, | |||
} | |||
}, | |||
{ | |||
name: '已完成', | |||
badge: { | |||
// value: 5, | |||
} | |||
}, | |||
]) | |||
const tabList2 = reactive([ | |||
{ | |||
name: '待上门', | |||
badge: { | |||
// value: 5, | |||
} | |||
}, | |||
{ | |||
name: '已完成', | |||
badge: { | |||
// value: 5, | |||
} | |||
}, | |||
]) | |||
function getList(){ | |||
getAppOrderList() | |||
.then(res => { | |||
if(res.code == 200){ | |||
list.value = res.rows | |||
} | |||
}) | |||
} | |||
getList() | |||
</script> | |||
<style scoped lang="scss"> | |||
@import "index.scss"; | |||
</style> | |||
@import "index.scss"; | |||
</style> |
@ -0,0 +1,95 @@ | |||
export const Base64 = { | |||
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", | |||
encode: function(input) { | |||
var output = ""; | |||
var chr1, chr2, chr3, enc1, enc2, enc3, enc4; | |||
var i = 0; | |||
input = Base64._utf8_encode(input); | |||
while (i < input.length) { | |||
chr1 = input.charCodeAt(i++); | |||
chr2 = input.charCodeAt(i++); | |||
chr3 = input.charCodeAt(i++); | |||
enc1 = chr1 >> 2; | |||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); | |||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); | |||
enc4 = chr3 & 63; | |||
if (isNaN(chr2)) { | |||
enc3 = enc4 = 64; | |||
} else if (isNaN(chr3)) { | |||
enc4 = 64; | |||
} | |||
output = output + | |||
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + | |||
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); | |||
} | |||
return output; | |||
}, | |||
decode: function(input) { | |||
var output = ""; | |||
var chr1, chr2, chr3; | |||
var enc1, enc2, enc3, enc4; | |||
var i = 0; | |||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); | |||
while (i < input.length) { | |||
enc1 = this._keyStr.indexOf(input.charAt(i++)); | |||
enc2 = this._keyStr.indexOf(input.charAt(i++)); | |||
enc3 = this._keyStr.indexOf(input.charAt(i++)); | |||
enc4 = this._keyStr.indexOf(input.charAt(i++)); | |||
chr1 = (enc1 << 2) | (enc2 >> 4); | |||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |||
chr3 = ((enc3 & 3) << 6) | enc4; | |||
output = output + String.fromCharCode(chr1); | |||
if (enc3 != 64) { | |||
output = output + String.fromCharCode(chr2); | |||
} | |||
if (enc4 != 64) { | |||
output = output + String.fromCharCode(chr3); | |||
} | |||
} | |||
output = Base64._utf8_decode(output); | |||
return output; | |||
}, | |||
_utf8_encode: function(string) { | |||
string = string.replace(/\r\n/g, "\n"); | |||
var utftext = ""; | |||
for (var n = 0; n < string.length; n++) { | |||
var c = string.charCodeAt(n); | |||
if (c < 128) { | |||
utftext += String.fromCharCode(c); | |||
} else if ((c > 127) && (c < 2048)) { | |||
utftext += String.fromCharCode((c >> 6) | 192); | |||
utftext += String.fromCharCode((c & 63) | 128); | |||
} else { | |||
utftext += String.fromCharCode((c >> 12) | 224); | |||
utftext += String.fromCharCode(((c >> 6) & 63) | 128); | |||
utftext += String.fromCharCode((c & 63) | 128); | |||
} | |||
} | |||
return utftext; | |||
}, | |||
_utf8_decode: function(utftext) { | |||
var string = ""; | |||
var i = 0; | |||
var c = c1 = c2 = 0; | |||
while (i < utftext.length) { | |||
c = utftext.charCodeAt(i); | |||
if (c < 128) { | |||
string += String.fromCharCode(c); | |||
i++; | |||
} else if ((c > 191) && (c < 224)) { | |||
c2 = utftext.charCodeAt(i + 1); | |||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); | |||
i += 2; | |||
} else { | |||
c2 = utftext.charCodeAt(i + 1); | |||
c3 = utftext.charCodeAt(i + 2); | |||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); | |||
i += 3; | |||
} | |||
} | |||
return string; | |||
} | |||
} |
@ -0,0 +1,117 @@ | |||
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |||
let Crypto = {}; | |||
var util = Crypto.util = { | |||
rotl: function(n, b) { | |||
return (n << b) | (n >>> (32 - b)); | |||
}, | |||
rotr: function(n, b) { | |||
return (n << (32 - b)) | (n >>> b); | |||
}, | |||
endian: function(n) { | |||
if (n.constructor == Number) { | |||
return util.rotl(n, 8) & 0x00FF00FF | | |||
util.rotl(n, 24) & 0xFF00FF00; | |||
} | |||
for (var i = 0; i < n.length; i++) | |||
n[i] = util.endian(n[i]); | |||
return n; | |||
}, | |||
randomBytes: function(n) { | |||
for (var bytes = []; n > 0; n--) | |||
bytes.push(Math.floor(Math.random() * 256)); | |||
return bytes; | |||
}, | |||
stringToBytes: function(str) { | |||
var bytes = []; | |||
for (var i = 0; i < str.length; i++) | |||
bytes.push(str.charCodeAt(i)); | |||
return bytes; | |||
}, | |||
bytesToString: function(bytes) { | |||
var str = []; | |||
for (var i = 0; i < bytes.length; i++) | |||
str.push(String.fromCharCode(bytes[i])); | |||
return str.join(""); | |||
}, | |||
stringToWords: function(str) { | |||
var words = []; | |||
for (var c = 0, b = 0; c < str.length; c++, b += 8) | |||
words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32); | |||
return words; | |||
}, | |||
bytesToWords: function(bytes) { | |||
var words = []; | |||
for (var i = 0, b = 0; i < bytes.length; i++, b += 8) | |||
words[b >>> 5] |= bytes[i] << (24 - b % 32); | |||
return words; | |||
}, | |||
wordsToBytes: function(words) { | |||
var bytes = []; | |||
for (var b = 0; b < words.length * 32; b += 8) | |||
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); | |||
return bytes; | |||
}, | |||
bytesToHex: function(bytes) { | |||
var hex = []; | |||
for (var i = 0; i < bytes.length; i++) { | |||
hex.push((bytes[i] >>> 4).toString(16)); | |||
hex.push((bytes[i] & 0xF).toString(16)); | |||
} | |||
return hex.join(""); | |||
}, | |||
hexToBytes: function(hex) { | |||
var bytes = []; | |||
for (var c = 0; c < hex.length; c += 2) | |||
bytes.push(parseInt(hex.substr(c, 2), 16)); | |||
return bytes; | |||
}, | |||
bytesToBase64: function(bytes) { | |||
if (typeof btoa == "function") return btoa(util.bytesToString(bytes)); | |||
var base64 = [], | |||
overflow; | |||
for (var i = 0; i < bytes.length; i++) { | |||
switch (i % 3) { | |||
case 0: | |||
base64.push(base64map.charAt(bytes[i] >>> 2)); | |||
overflow = (bytes[i] & 0x3) << 4; | |||
break; | |||
case 1: | |||
base64.push(base64map.charAt(overflow | (bytes[i] >>> 4))); | |||
overflow = (bytes[i] & 0xF) << 2; | |||
break; | |||
case 2: | |||
base64.push(base64map.charAt(overflow | (bytes[i] >>> 6))); | |||
base64.push(base64map.charAt(bytes[i] & 0x3F)); | |||
overflow = -1; | |||
} | |||
} | |||
if (overflow != undefined && overflow != -1) | |||
base64.push(base64map.charAt(overflow)); | |||
while (base64.length % 4 != 0) base64.push("="); | |||
return base64.join(""); | |||
}, | |||
base64ToBytes: function(base64) { | |||
if (typeof atob == "function") return util.stringToBytes(atob(base64)); | |||
base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); | |||
var bytes = []; | |||
for (var i = 0; i < base64.length; i++) { | |||
switch (i % 4) { | |||
case 1: | |||
bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) | | |||
(base64map.indexOf(base64.charAt(i)) >>> 4)); | |||
break; | |||
case 2: | |||
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) | | |||
(base64map.indexOf(base64.charAt(i)) >>> 2)); | |||
break; | |||
case 3: | |||
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) | | |||
(base64map.indexOf(base64.charAt(i)))); | |||
break; | |||
} | |||
} | |||
return bytes; | |||
} | |||
}; | |||
Crypto.mode = {}; | |||
export default Crypto; |
@ -0,0 +1,29 @@ | |||
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js'; | |||
(function() { | |||
// Shortcut | |||
var util = Crypto.util; | |||
Crypto.HMAC = function(hasher, message, key, options) { | |||
// Allow arbitrary length keys | |||
key = key.length > hasher._blocksize * 4 ? | |||
hasher(key, { | |||
asBytes: true | |||
}) : | |||
util.stringToBytes(key); | |||
// XOR keys with pad constants | |||
var okey = key, | |||
ikey = key.slice(0); | |||
for (var i = 0; i < hasher._blocksize * 4; i++) { | |||
okey[i] ^= 0x5C; | |||
ikey[i] ^= 0x36; | |||
} | |||
var hmacbytes = hasher(util.bytesToString(okey) + | |||
hasher(util.bytesToString(ikey) + message, { | |||
asString: true | |||
}), { | |||
asBytes: true | |||
}); | |||
return options && options.asBytes ? hmacbytes : | |||
options && options.asString ? util.bytesToString(hmacbytes) : | |||
util.bytesToHex(hmacbytes); | |||
}; | |||
})(); |
@ -0,0 +1,59 @@ | |||
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js'; | |||
(function() { | |||
// Shortcut | |||
var util = Crypto.util; | |||
// Public API | |||
var SHA1 = Crypto.SHA1 = function(message, options) { | |||
var digestbytes = util.wordsToBytes(SHA1._sha1(message)); | |||
return options && options.asBytes ? digestbytes : | |||
options && options.asString ? util.bytesToString(digestbytes) : | |||
util.bytesToHex(digestbytes); | |||
}; | |||
// The core | |||
SHA1._sha1 = function(message) { | |||
var m = util.stringToWords(message), | |||
l = message.length * 8, | |||
w = [], | |||
H0 = 1732584193, | |||
H1 = -271733879, | |||
H2 = -1732584194, | |||
H3 = 271733878, | |||
H4 = -1009589776; | |||
// Padding | |||
m[l >> 5] |= 0x80 << (24 - l % 32); | |||
m[((l + 64 >>> 9) << 4) + 15] = l; | |||
for (var i = 0; i < m.length; i += 16) { | |||
var a = H0, | |||
b = H1, | |||
c = H2, | |||
d = H3, | |||
e = H4; | |||
for (var j = 0; j < 80; j++) { | |||
if (j < 16) w[j] = m[i + j]; | |||
else { | |||
var n = w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16]; | |||
w[j] = (n << 1) | (n >>> 31); | |||
} | |||
var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + ( | |||
j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 : | |||
j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 : | |||
j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 : | |||
(H1 ^ H2 ^ H3) - 899497514); | |||
H4 = H3; | |||
H3 = H2; | |||
H2 = (H1 << 30) | (H1 >>> 2); | |||
H1 = H0; | |||
H0 = t; | |||
} | |||
H0 += a; | |||
H1 += b; | |||
H2 += c; | |||
H3 += d; | |||
H4 += e; | |||
} | |||
return [H0, H1, H2, H3, H4]; | |||
}; | |||
// Package private blocksize | |||
SHA1._blocksize = 16; | |||
})(); |
@ -0,0 +1,51 @@ | |||
import Crypto from '@/utils/oss-upload/common/crypto/crypto.js.js'; | |||
import '@/utils/oss-upload/common/crypto/hmac.js'; | |||
import '@/utils/oss-upload/common/crypto/sha1.js'; | |||
import { Base64 } from '@/utils/oss-upload/common/crypto/base64.js'; | |||
// 阿里云配置 | |||
const ossConfig = { | |||
url: 'https://image.hhlm1688.com/', | |||
config: { | |||
//桶的地址 | |||
region: 'oss-cn-guangzhou', | |||
//id | |||
accessKeyId: 'LTAI5tQSs47izVy8DLVdwUU9', | |||
//密钥 | |||
accessKeySecret: 'qHI7C3PaXYZySr84HTToviC71AYlFq', | |||
//桶的名字 | |||
bucket: 'hanhaiimage', | |||
endpoint: 'oss-cn-shenzhen.aliyuncs.com', | |||
} | |||
} | |||
let date = new Date() | |||
date = date.setHours(date.getHours() + 1) | |||
let extime = "" + new Date(date).toISOString() | |||
let policyText = { | |||
"expiration": extime, | |||
"conditions": [ | |||
["content-length-range", 0, 1024 * 1024 * 100] // 设置上传文件的大小限制 | |||
] | |||
}; | |||
let config = { | |||
accessid: ossConfig.config.accessKeyId, | |||
accesskey: ossConfig.config.accessKeySecret, | |||
osshost: ossConfig.url, | |||
policyBase64: Base64.encode(JSON.stringify(policyText)) | |||
} | |||
let message = config.policyBase64; | |||
let bytes = Crypto.HMAC(Crypto.SHA1, message, config.accesskey, { | |||
asBytes: true | |||
}); | |||
let signature = Crypto.util.bytesToBase64(bytes); | |||
let timetamp = new Date().getTime(); | |||
let OSSConfig = { | |||
name: 'aliyun', | |||
host: config.osshost, | |||
accessid: config.accessid, | |||
signature: signature, | |||
policyBase64: config.policyBase64, | |||
} | |||
export default OSSConfig; |
@ -0,0 +1,132 @@ | |||
/** | |||
* 阿里云OSS工具类 | |||
*/ | |||
import OSSConfig from "@/utils/oss-upload/oss/OSSConfig.js" | |||
/** | |||
* 生成一个随机的Key | |||
*/ | |||
function storeKey() { | |||
let s = []; | |||
let hexDigits = "0123456789abcdef"; | |||
for (let i = 0; i < 36; i++) { | |||
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); | |||
} | |||
s[14] = "4"; | |||
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); | |||
s[8] = s[13] = s[18] = s[23] = "-"; | |||
return s.join(""); | |||
} | |||
/** | |||
* 根据当天日期在OSS端生成文件夹 | |||
*/ | |||
function storeFolder() { | |||
const date = new Date(); | |||
const formatNumber = n => { | |||
n = n.toString() | |||
return n[1] ? n : '0' + n | |||
} | |||
return [date.getFullYear(), date.getMonth() + 1, date.getDate()].map(formatNumber).join('-') | |||
} | |||
/** | |||
* 阿里云OSS上传文件, 所有具体功能的工具函数均基于此 | |||
* 注意, resolve时一定为上传成功, 返回OSS上的Key | |||
* @param filePath 待上传文件的URI | |||
* @param key 存储桶中的目标文件名 | |||
* @param folder 存储桶中的目标文件夹 | |||
*/ | |||
export function ossUpload(filePath, key = storeKey(), folder = storeFolder()) { | |||
return new Promise((resolve, reject) => { | |||
if (folder && folder?.length > 0) { | |||
if (folder[0] == "/") folder = folder.slice(1, folder.length) | |||
if (folder[folder.length - 1] != "/") folder += "/" | |||
key = folder + key | |||
} | |||
const filePrefixArr = filePath.split(".") | |||
key += `.${filePrefixArr[filePrefixArr.length - 1]}` | |||
let config = { | |||
url: OSSConfig.host, | |||
name: 'file', | |||
filePath, | |||
formData: { | |||
key, | |||
policy: OSSConfig.policyBase64, | |||
OSSAccessKeyId: OSSConfig.accessid, | |||
success_action_status: '200', | |||
signature: OSSConfig.signature, | |||
}, | |||
success(res) { | |||
if (res.errMsg.includes("uploadFile:ok")) { | |||
resolve(OSSConfig.host + key) | |||
} else { | |||
reject(res) | |||
} | |||
}, | |||
fail(err) { | |||
reject(err) | |||
} | |||
} | |||
uni.uploadFile(config) | |||
}) | |||
} | |||
/** | |||
* 阿里云OSS上传图片 | |||
* @param {compressed, key, folder, success, fail} compressed: 是否压缩 key: 存储桶中的目标文件名 folder: 存储桶中的目标文件夹 | |||
*/ | |||
export function ossUploadImage({ | |||
key, | |||
folder, | |||
compressed = true, //是否压缩 | |||
}) { | |||
const sizeType = [compressed ? 'compressed' : 'original'] | |||
return new Promise((success, fail) => { | |||
uni.chooseImage({ | |||
count: 1, | |||
sizeType, | |||
success(res) { | |||
ossUpload(res.tempFilePaths[0], key, folder).then(success).catch(fail) | |||
}, | |||
fail | |||
}) | |||
}) | |||
} | |||
/** | |||
* 阿里云OSS上传视频 | |||
* @param { key, folder, sourceType, compressed, maxDuration, camera, success, fail} | |||
* key: 存储桶中的目标文件名 folder: 存储桶中的目标文件夹 其它参数同uni.chooseVideo(mpWeixin) | |||
*/ | |||
export function ossUploadVideo({ | |||
key, | |||
folder, | |||
sourceType = ['album', 'camera'], //album 从相册选视频, camera 使用相机拍摄 | |||
compressed = true, //是否压缩所选的视频源文件 | |||
maxDuration = 60, //拍摄视频最长拍摄时间, 单位秒。最长支持 60 秒 | |||
camera = 'back', //调用相机方向, 'front'、'back', 默认'back' | |||
}) { | |||
return new Promise((success, fail) => { | |||
uni.chooseVideo({ | |||
sourceType, | |||
compressed, | |||
maxDuration, | |||
camera, | |||
success(res) { | |||
ossUpload(res.tempFilePath, key, folder).then(success).catch(fail) | |||
}, | |||
fail | |||
}) | |||
}) | |||
} | |||
const OSS = { | |||
ossUploadVideo, | |||
ossUploadImage, | |||
ossUpload | |||
} | |||
export default OSS; |