Accept Merge Request #42: (feature/dgg -> develop)

Merge Request: feat: 初版合并

Created By: @大狗哥
Accepted By: @大狗哥
URL: https://g-bcrc3009.coding.net/p/allocatr/d/wanyu_frontend/git/merge/42
This commit is contained in:
大狗哥 2025-05-09 15:09:23 +08:00 committed by Coding
commit 88670032af
62 changed files with 4410 additions and 490 deletions

34
App.vue
View File

@ -1,27 +1,53 @@
<script setup>
import {onLaunch, onShow, onHide} from '@dcloudio/uni-app'
import {reactive, provide, inject} from 'vue'
import api from "./api/api";
//
const globalData = reactive({
appName: '超邦手工单系统',
appIcon: 'https://jl-td.oss-cn-chengdu.aliyuncs.com/uploads/20230621/444e73968f4c666bdadbe2e1f8e3ba63.png',
appIcon: '/static/img/logo.png',
statusBarH: '',
customBarH: ''
})
provide('globalData', globalData)
onLaunch(() => {
// console.log('App Launch')
initSysInfo()
setInterval(() => {
updateUserLocation()
}, 60 * 1000)
})
onShow(() => {
// console.log('App Show')
updateUserLocation()
})
onHide(() => {
// console.log('App Hide')
updateUserLocation()
})
/**
* 更新用户位置
*/
const updateUserLocation = () => {
let token = uni.getStorageSync('token')
//
if (!token) {
return
}
uni.getLocation({
type: 'gcj02',
success(res) {
let data = {longitude: res.longitude, latitude: res.latitude}
api.updateUserLocation(data).then(() => {
}).catch(() => {})
},
fail() {
}
});
}
const initSysInfo = () => {
//
let statusBar = uni.getWindowInfo().statusBarHeight

132
api/api.js Normal file
View File

@ -0,0 +1,132 @@
import fetch from './fetch.js';
import config from './config.js';
class Api {
// 微信登录
static wechatLogin(data) {
let url = `${config.host}/worker/worker/login`;
return fetch.request('postFrom', url, data, false)
}
// 绑定手机号
static bindPhoneNumber(data) {
let url = `${config.host}/worker/worker/bindPhoneNumber`;
return fetch.request('postFrom', url, data, false)
}
// 游客登录
static guestLogin() {
let url = `${config.host}/worker/worker/guestLogin`;
return fetch.request('postFrom', url, {}, false)
}
// 退出登录
static logout() {
let url = `${config.host}/worker/worker/logout`;
return fetch.request('postFrom', url, {}, true)
}
// 获取用户信息
static userInfo() {
let url = `${config.host}/worker/worker/show`;
return fetch.request('postFrom', url, {}, true)
}
// 接单列表
static orderDispatchList(data) {
let url = `${config.host}/worker/order_dispatch/index`;
return fetch.request('GET', url, data, true)
}
// 接单/拒接
static orderConfirm(data) {
let url = `${config.host}/worker/order_dispatch/orderConfirm`;
return fetch.request('postFrom', url, data, true)
}
// 工作台列表
static workbenchOrderList(data) {
let url = `${config.host}/worker/order_dispatch/workbenchOrderList`;
return fetch.request('GET', url, data, true)
}
// 统计工作台订单
static countWorkbenchOrder() {
let url = `${config.host}/worker/order_dispatch/countWorkbenchOrder`;
return fetch.request('GET', url, {}, true)
}
// 订单详情
static orderInfo(data) {
let url = `${config.host}/worker/order_dispatch/info`;
return fetch.request('GET', url, data, true)
}
// 预约上门时间
static appointmentTime(data) {
let url = `${config.host}/worker/order_dispatch/appointmentTime`;
return fetch.request('postFrom', url, data, true)
}
// 获取 OSS 上传文件参数
static getOssParams(data) {
let url = `${config.host}/worker/common/ossParams`;
return fetch.request('postFrom', url, data, true)
}
// 完成上门
static arrivedOnSite(data) {
let url = `${config.host}/worker/order_dispatch/arrivedOnSite`;
return fetch.request('postFrom', url, data, true)
}
// 完成服务
static completeService(data) {
let url = `${config.host}/worker/order_dispatch/completeService`;
return fetch.request('postFrom', url, data, true)
}
// 异常原因列表
static findExceptionTypeList() {
let url = `${config.host}/worker/abnormal/index`;
return fetch.request('GET', url, {}, true)
}
// 获取订单异常详情
static orderAbnormalInfo(data) {
let url = `${config.host}/worker/order_abnormal/info`;
return fetch.request('GET', url, data, true)
}
// 上报异常
static createOrderAbnormal(data) {
let url = `${config.host}/worker/order_abnormal/create`;
return fetch.request('postFrom', url, data, true)
}
// 保存师傅备注
static saveWorkerRemark(data) {
let url = `${config.host}/worker/order_dispatch/saveWorkerRemark`;
return fetch.request('postFrom', url, data, true)
}
// 保存师傅备注
static updateUserLocation(data) {
let url = `${config.host}/worker/worker/updateWorkerLocation`;
return fetch.request('postFrom', url, data, true)
}
// 获取配置
static getConfig(data) {
let url = `${config.host}/worker/common/config`;
return fetch.request('GET', url, {}, false)
}
// 修改上门时间
static updatePlanTime(data) {
let url = `${config.host}/worker/order_dispatch/updatePlanTime`;
return fetch.request('postFrom', url, data, true)
}
}
export default Api

16
api/config.js Normal file
View File

@ -0,0 +1,16 @@
let accountInfo = wx.getAccountInfoSync();
let envVersion = accountInfo.miniProgram.envVersion
//手动指定版本
// envVersion = 'trial'
let hosts = {
"develop": 'http://wanyu.test',
"trial": 'https://www.yilingjiang.com',
"release": 'https://release',
}
let host = hosts[envVersion]
export default {host};

40
api/fetch.js Normal file
View File

@ -0,0 +1,40 @@
import helpers from "../utils/helpers";
class Fetch {
static request(methods, url, data, needToken = true, showErrorMsg = true) {
return new Promise((resolve, reject) => {
var headers = {
'content-type': methods === 'postFrom' ? 'application/x-www-form-urlencoded' :
'application/json',
'Accept': 'application/json'
}
if (needToken) {
headers.token = uni.getStorageSync('token');
}
uni.request({
url: url,
method: methods === 'postFrom' ? 'POST' : methods,
data: data,
header: headers,
success(res) {
if (res.data.code === 1) {
resolve(res.data.data) // 成功,返回数据
} else {
if (res.data.code === 0 && showErrorMsg) {
helpers.showToast(res.data.msg) // 失败且需显示错误提示
} else if (res.data.code === 401) {
helpers.jumpToPage('login')
}
reject(res.data) // 统一 reject 错误数据
}
},
fail(err) {
helpers.showToast(err.errMsg)
reject(err)
}
})
})
}
}
export default Fetch

View File

@ -0,0 +1,164 @@
<template>
<view class="btn-container"
:style="{width, marginTop, marginBottom}"
:hover-class="isActive ? 'fixed-mask-layer-radius8' : 'none'"
hover-start-time="0"
hover-stay-time="50"
@click="submit()"
>
<!--线框按钮-->
<view v-if="isBorderButton"
class="wireframe-btn">
<view class="btn flex-c" :style="{color: iconColor}">
<view class="icon" v-if="iconType">
<me-icon :color="iconColor" :type="iconType" size="44rpx"></me-icon>
</view>
<text class="text">{{ text }}</text>
</view>
</view>
<!--纯色按钮-->
<view v-else
:class="['flex-c', 'btn', isActive ? '' : 'btn-default']"
:style="{backgroundColor: btnBgColor, color: textColor}"
>
<view class="icon" v-if="iconType">
<me-icon :color="iconColor" :type="iconType" size="44rpx"></me-icon>
</view>
<text class="text">{{ text }}</text>
</view>
</view>
</template>
<script setup>
import {computed} from 'vue';
import MeIcon from "../../components/me-icon/me-icon";
const emit = defineEmits(["click"]);
const props = defineProps({
//
text: {
type: String,
required: false,
default: '保 存',
},
// icon
iconType: {
type: String,
required: false,
default: '',
},
//
isActive: {
type: Boolean,
required: false,
default: true,
},
//线
isBorderButton: {
type: Boolean,
required: false,
default: false,
},
//
width: {
type: String,
required: true,
},
//
marginTop: {
type: String,
required: false,
default: '0',
},
//
marginBottom: {
type: String,
required: false,
default: '0',
},
//
activeColor: {
type: String,
required: false,
default: 'var(--themeColor)',
},
//
textColor: {
type: String,
required: false,
default: '#FFFFFF',
},
//icon
customIconColor: {
type: String,
required: false,
default: '',
}
});
const btnBgColor = computed(() => {
if (!props.isActive) {
return 'var(--contentBgColor)'
}
return props.activeColor;
})
// icon
const iconColor = computed(() => {
if (props.customIconColor) {
return props.customIconColor
}
if (!props.isActive) {
return 'var(--descriptionColor)'
}
if (props.isBorderButton) {
return 'var(--themeColor)'
}
return '#FFFFFF';
})
//
const submit = () => {
emit("click");
};
</script>
<style lang="scss" scoped>
.btn-container {
.icon {
margin-right: 8rpx;
}
.btn {
width: 100%;
height: 96rpx;
border-radius: 16rpx;
font-size: 30rpx;
line-height: 112rpx;
text-align: center;
.text {
height: 96rpx;
line-height: 96rpx;
}
}
.btn-active {
color: #FFFFFF;
}
.btn-default {
color: var(--descriptionColor);
}
.wireframe-btn {
.btn {
border: 1px solid var(--contentBgColor);
box-sizing: border-box;
}
}
}
</style>

View File

@ -0,0 +1,19 @@
<template>
<view class="me-empty-space" :style="{height: height + 'rpx'}"></view>
</template>
<script setup>
const props = defineProps({
height: {
type: [Number, String],
required: false,
default: 100,
}
});
</script>
<style lang="scss">
.me-empty-space {
width: 100%;
}
</style>

View File

@ -0,0 +1,40 @@
<template>
<view class="me-empty flex-direction-column" :style="{marginTop}">
<view class="image"></view>
<view class="empty-text">{{text}}</view>
</view>
</template>
<script setup>
const props = defineProps({
text: {
type: String,
required: false,
default: '暂无任何数据',
},
marginTop: {
type: String,
required: false,
default: '176rpx',
}
});
</script>
<style lang="scss" scoped>
.me-empty {
.image {
width: 400rpx;
height: 400rpx;
background: var(--emptyData)
}
.empty-text {
width: 400rpx;
height: 72rpx;
font-size: 28rpx;
color: var(--descriptionColor);
line-height: 72rpx;
text-align: center;
}
}
</style>

View File

@ -0,0 +1,57 @@
.icon-progress-2-line:before {
content: "\e900";
}
.icon-money-cny-circle-line:before {
content: "\e901";
}
.icon-user:before {
content: "\e902";
}
.icon-upload-cloud-fill:before {
content: "\e903";
}
.icon-time:before {
content: "\e904";
}
.icon-reset-left-line:before {
content: "\e905";
}
.icon-reset-left-fill:before {
content: "\e906";
}
.icon-navigation:before {
content: "\e907";
}
.icon-logout:before {
content: "\e908";
}
.icon-info:before {
content: "\e909";
}
.icon-flashlight:before {
content: "\e90a";
}
.icon-edit-line:before {
content: "\e90b";
}
.icon-close-circle-fill:before {
content: "\e90c";
}
.icon-checkbox-circle:before {
content: "\e90d";
}
.icon-checkbox-blank-circle:before {
content: "\e90e";
}
.icon-call:before {
content: "\e90f";
}
.icon-arrow-up-line:before {
content: "\e910";
}
.icon-arrow-right:before {
content: "\e911";
}
.icon-arrow-right-circle:before {
content: "\e912";
}

Binary file not shown.

View File

@ -0,0 +1,48 @@
<template>
<view class="flex-c">
<text :style="styleObj()" class="me-icon" :class="[type]" @click="_onClick">
</text>
</view>
</template>
<script setup>
const emit = defineEmits(["click"]);
const props = defineProps({
type: {
type: String,
default: ''
},
color: {
type: String,
default: 'var(--summaryColor)'
},
size: {
type: [Number, String],
default: '48rpx'
}
});
const _onClick = () => {
emit("click");
};
const styleObj = () => {
return `color: ${props.color}; font-size: ${props.size}; line-height: ${props.size};`
};
</script>
<style lang="scss" scoped>
@import './me-icon.css';
@font-face {
font-family: me-icon;
src: url('./me-icon.ttf');
}
.me-icon {
font-family: me-icon;
text-decoration: none;
text-align: center;
}
</style>

View File

@ -0,0 +1,52 @@
<template>
<view class="me-top">
<view class="status-bar" :style="{height: inject('globalData').statusBarH+'px'}"></view>
<view class="capsule flex-c" :style="{height: inject('globalData').customBarH - inject('globalData').statusBarH+'px'}">
<view class="icon-ctr flex-c" v-if="isShowIcon">
<image class="icon" mode="aspectFill" :src="inject('globalData').appIcon"></image>
</view>
<text class="title">{{title}}</text>
</view>
</view>
</template>
<script setup>
import {inject} from 'vue'
const props = defineProps({
//
title: {
type: String,
required: true,
},
isShowIcon: {
type: Boolean,
required: false,
default: true
}
});
</script>
<style lang="scss" scoped>
.me-top {
.capsule {
.icon-ctr {
width: 60rpx;
height: 60rpx;
border: 1px solid #E9F1FE;
border-radius: 50%;
position: absolute;
left: 0;
.icon {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.title {
font-weight: 500;
font-size: 32rpx;
color: var(--titleColor);
}
}
}
</style>

View File

@ -1,10 +1,8 @@
import App from './App'
import store from './store'
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
app.use(store)
return {
app
}

View File

@ -51,6 +51,12 @@
/* */
"mp-weixin" : {
"appid" : "wx6172ec67683d31b9",
"requiredPrivateInfos" : [ "getLocation" ],
"permission" : {
"scope.userLocation" : {
"desc" : "计算接单距离、调用导航功能"
}
},
"setting" : {
"urlCheck" : false
},

View File

@ -4,30 +4,90 @@
"path" : "pages/index/index",
"style" :
{
"navigationBarTitleText" : "接单大厅"
"navigationBarTitleText" : "接单大厅",
"navigationBarBackgroundColor": "@backgroundColor",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/workbench/workbench",
"style" :
{
"navigationBarTitleText" : "工作台"
}
},
{
"path" : "pages/user/user",
"style" :
{
"navigationBarTitleText" : "我的"
"navigationBarTitleText" : "",
"navigationStyle": "custom"
}
},
{
"path" : "pages/user/login",
"style" :
{
"navigationBarTitleText" : "",
"navigationBarTitleText" : "登录",
"disableScroll": true
}
},
{
"path" : "pages/user/user",
"style" :
{
"navigationBarTitleText" : "我的",
"navigationStyle": "custom"
}
},
{
"path" : "pages/order/order-info",
"style" :
{
"navigationBarTitleText" : "工单详情"
}
},
{
"path" : "pages/order/select-time",
"style" :
{
"navigationBarTitleText" : "已和客户沟通"
}
},
{
"path" : "pages/order/arrived-on-site",
"style" :
{
"navigationBarTitleText" : "完成上门"
}
},
{
"path" : "pages/order/complete-service",
"style" :
{
"navigationBarTitleText" : "完成服务"
}
},
{
"path" : "pages/order/report-order-exception",
"style" :
{
"navigationBarTitleText" : "上报异常"
}
},
{
"path" : "pages/order/worker-remark",
"style" :
{
"navigationBarTitleText" : "工单备注"
}
},
{
"path" : "pages/user/user-agreement",
"style" :
{
"navigationBarTitleText" : "用户协议"
}
},
{
"path" : "pages/user/privacy-policy",
"style" :
{
"navigationBarTitleText" : "隐私协议"
}
}
],
"globalStyle": {

View File

@ -0,0 +1,369 @@
<template name="skeleton">
<view class="sk-container">
<view class="ctr ctr data-v-1cf27b2a data-v-1cf27b2a">
<view class="list list data-v-1cf27b2a data-v-1cf27b2a">
<view class="order-item order-item data-v-1cf27b2a data-v-1cf27b2a">
<view class="top top flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="type flex-l data-v-1cf27b2a sk-transparent sk-text-14-2857-11 sk-text"></view>
<view class="price flex-r important-color data-v-1cf27b2a sk-transparent sk-text-14-2857-661 sk-text"></view>
</view>
<view class="content content flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="left left data-v-1cf27b2a data-v-1cf27b2a">
<view class="address-name flex-l data-v-1cf27b2a sk-transparent sk-text-15-9091-8 sk-text">安徽省蚌埠市禹会区钓鱼台街道迎河路</view>
<view class="address flex-l data-v-1cf27b2a sk-transparent sk-text-18-1818-59 sk-text">安徽省蚌埠市禹会区</view>
<view class="time-ctr time-ctr flex-l flex-l data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-icon/me-icon" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-time icon--icon-time sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text style="line-height: 60rpx;" class="time data-v-1cf27b2a sk-transparent sk-text-18-1818-121 sk-text">周日 25年3月23日 14:30</text>
</view>
</view>
<view class="right right data-v-1cf27b2a data-v-1cf27b2a">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-icon/me-icon" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-navigation icon--icon-navigation sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 30px; line-height: 30px;"></text>
</view>
</view>
</view>
<view class="distance flex-c data-v-1cf27b2a sk-transparent sk-text-18-1818-876 sk-text">7.54公里</view>
</view>
</view>
<view class="discount flex-l data-v-1cf27b2a sk-transparent sk-text-14-2857-318 sk-text">已支付订金123.00元抵扣200元</view>
<view class="btn-ctr btn-ctr flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-button/me-button" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="btn-container button--btn-container data-v-c61a7656 button--data-v-c61a7656" style="width:230px;margin-top:0;margin-bottom:0">
<view class="data-v-c61a7656 button--data-v-c61a7656 flex-c button--flex-c btn button--btn" style="background-color:var(--auxiliaryBgColor);color:#FFFFFF">
<view class="icon button--icon data-v-c61a7656 button--data-v-c61a7656">
<view is="components/me-icon/me-icon" class="data-v-c61a7656 button--data-v-c61a7656">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
</view>
</view>
</view>
</view>
</view>
</view>
<view is="components/me-button/me-button" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="btn-container button--btn-container data-v-c61a7656 button--data-v-c61a7656" style="width:83px;margin-top:0;margin-bottom:0">
<view class="data-v-c61a7656 button--data-v-c61a7656 flex-c button--flex-c btn button--btn" style="background-color:var(--auxiliaryBgColor);color:var(--titleColor)">
</view>
</view>
</view>
</view>
</view>
<view class="order-item order-item data-v-1cf27b2a data-v-1cf27b2a">
<view class="top top flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="type flex-l data-v-1cf27b2a sk-transparent sk-text-14-2857-11 sk-text"></view>
<view class="price flex-r important-color data-v-1cf27b2a sk-transparent sk-text-14-2857-661 sk-text"></view>
</view>
<view class="content content flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="left left data-v-1cf27b2a data-v-1cf27b2a">
<view class="address-name flex-l data-v-1cf27b2a sk-transparent sk-text-15-9091-8 sk-text">安徽省蚌埠市禹会区钓鱼台街道迎河路</view>
<view class="address flex-l data-v-1cf27b2a sk-transparent sk-text-18-1818-59 sk-text">安徽省蚌埠市禹会区</view>
<view class="time-ctr time-ctr flex-l flex-l data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-icon/me-icon" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-time icon--icon-time sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text style="line-height: 60rpx;" class="time data-v-1cf27b2a sk-transparent sk-text-18-1818-121 sk-text">周日 25年3月23日 14:30</text>
</view>
</view>
<view class="right right data-v-1cf27b2a data-v-1cf27b2a">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-icon/me-icon" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-navigation icon--icon-navigation sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 30px; line-height: 30px;"></text>
</view>
</view>
</view>
<view class="distance flex-c data-v-1cf27b2a sk-transparent sk-text-18-1818-876 sk-text">7.54公里</view>
</view>
</view>
<view class="discount flex-l data-v-1cf27b2a sk-transparent sk-text-14-2857-318 sk-text">已支付订金123.00元抵扣200元</view>
<view class="btn-ctr btn-ctr flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-button/me-button" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="btn-container button--btn-container data-v-c61a7656 button--data-v-c61a7656" style="width:230px;margin-top:0;margin-bottom:0">
<view class="data-v-c61a7656 button--data-v-c61a7656 flex-c button--flex-c btn button--btn" style="background-color:var(--auxiliaryBgColor);color:#FFFFFF">
<view class="icon button--icon data-v-c61a7656 button--data-v-c61a7656">
<view is="components/me-icon/me-icon" class="data-v-c61a7656 button--data-v-c61a7656">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
</view>
</view>
</view>
</view>
</view>
</view>
<view is="components/me-button/me-button" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="btn-container button--btn-container data-v-c61a7656 button--data-v-c61a7656" style="width:83px;margin-top:0;margin-bottom:0">
<view class="data-v-c61a7656 button--data-v-c61a7656 flex-c button--flex-c btn button--btn" style="background-color:var(--auxiliaryBgColor);color:var(--titleColor)">
</view>
</view>
</view>
</view>
</view>
<view class="order-item order-item data-v-1cf27b2a data-v-1cf27b2a">
<view class="top top flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="type flex-l data-v-1cf27b2a sk-transparent sk-text-14-2857-955 sk-text">灶台维修</view>
<view class="price flex-r important-color data-v-1cf27b2a sk-transparent sk-text-14-2857-608 sk-text"></view>
</view>
<view style="min-height: auto" class="content content flex-sb flex-sb data-v-1cf27b2a data-v-1cf27b2a">
<view class="left left data-v-1cf27b2a data-v-1cf27b2a">
<view class="address-name flex-l data-v-1cf27b2a sk-transparent sk-text-15-9091-504 sk-text">安徽省蚌埠市禹会区钓鱼台街道迎河路</view>
</view>
<view class="right right data-v-1cf27b2a data-v-1cf27b2a">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-1cf27b2a data-v-1cf27b2a">
<view is="components/me-icon/me-icon" class="data-v-1cf27b2a data-v-1cf27b2a">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-navigation icon--icon-navigation sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 30px; line-height: 30px;"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
@import '../../components/me-icon/me-icon.css';
@font-face {
font-family: me-icon;
src: url('../../components/me-icon/me-icon.ttf');
}
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
.btn-container {
.icon {
margin-right: 8rpx;
}
.btn {
width: 100%;
height: 96rpx;
border-radius: 16rpx;
font-size: 30rpx;
line-height: 112rpx;
text-align: center;
.text {
height: 96rpx;
line-height: 96rpx;
}
}
.btn-active {
color: #FFFFFF;
}
.btn-default {
color: var(--descriptionColor);
}
.wireframe-btn {
.btn {
border: 1px solid var(--contentBgColor);
box-sizing: border-box;
}
}
}
.me-icon {
font-family: me-icon;
text-decoration: none;
text-align: center;
}
.me-top {
.capsule {
.icon-ctr {
width: 60rpx;
height: 60rpx;
border: 1px solid #E9F1FE;
border-radius: 50%;
position: absolute;
left: 0;
.icon {
width: 80%;
height: 80%;
border-radius: 50%;
}
}
.title {
font-weight: 500;
font-size: 32rpx;
color: var(--titleColor);
}
}
}
.fixed-top {
position: fixed;
top: 0;
background-color: var(--pageBgColor);
width: 686rpx;
}
.refresh {
width: 108rpx;
height: 108rpx;
background: var(--themeColor);
border-radius: 50%;
position: fixed;
bottom: 64rpx;
right: 32rpx;
}
.rotate {
animation: spin 0.5s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
.order-item {
.discount {
padding: 0!important;
}
}
.me-top .capsule .icon-ctr {
border: 1px solid var(--auxiliaryBgColor)!important;
}
}
</style>
<style>
.sk-transparent {
color: transparent !important;
}
.sk-text-14-2857-544 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
background-size: 100% 44.8000rpx;
position: relative !important;
}
.sk-text {
background-origin: content-box !important;
background-clip: content-box !important;
background-color: transparent !important;
color: transparent !important;
background-repeat: repeat-y !important;
}
.sk-text-14-2857-11 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-661 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-15-9091-8 {
background: linear-gradient(transparent 15.9091%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 84.0909%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-59 {
background-image: linear-gradient(transparent 18.1818%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-876 {
background-image: linear-gradient(transparent 18.1818%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-318 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
background-size: 100% 39.2000rpx;
position: relative !important;
}
.sk-text-34-3750-426 {
background-image: linear-gradient(transparent 34.3750%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)65.6250%, transparent 0%) !important;
background-size: 100% 96.0000rpx;
position: relative !important;
}
.sk-text-34-3750-763 {
background-image: linear-gradient(transparent 34.3750%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)65.6250%, transparent 0%) !important;
background-size: 100% 96.0000rpx;
position: relative !important;
}
.sk-text-14-2857-151 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-853 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-15-9091-270 {
background-image: linear-gradient(transparent 15.9091%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)84.0909%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-826 {
background-image: linear-gradient(transparent 18.1818%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-121 {
background-image: linear-gradient(transparent 18.1818%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-983 {
background-image: linear-gradient(transparent 18.1818%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-100 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
background-size: 100% 39.2000rpx;
position: relative !important;
}
.sk-text-34-3750-322 {
background-image: linear-gradient(transparent 34.3750%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)65.6250%, transparent 0%) !important;
background-size: 100% 96.0000rpx;
position: relative !important;
}
.sk-text-34-3750-439 {
background-image: linear-gradient(transparent 34.3750%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)65.6250%, transparent 0%) !important;
background-size: 100% 96.0000rpx;
position: relative !important;
}
.sk-text-14-2857-955 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-608 {
background-image: linear-gradient(transparent 14.2857%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-15-9091-504 {
background-image: linear-gradient(transparent 15.9091%,var(--auxiliaryBgColor)0%,var(--auxiliaryBgColor)84.0909%, transparent 0%) !important;
position: relative !important;
}
.sk-image {
background: var(--auxiliaryBgColor) !important;
}
.sk-pseudo::before, .sk-pseudo::after {
background: var(--auxiliaryBgColor) !important;
background-image: none !important;
color: transparent !important;
border-color: transparent !important;
}
.sk-pseudo-rect::before, .sk-pseudo-rect::after {
border-radius: 0 !important;
}
.sk-pseudo-circle::before, .sk-pseudo-circle::after {
border-radius: 50% !important;
}
.sk-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: transparent;
}
</style>
<script setup lang="ts">
</script>

View File

@ -1,22 +1,213 @@
<template>
<view>
</view>
<!-- <IndexSkeleton v-if="data.is_show_skeleton"></IndexSkeleton>-->
<template v-if="data.list !== null">
<view class="ctr">
<view class="list" v-if="data.list.length > 0">
<view class="order-item" v-for="(item, index) in data.list" :key="index">
<view class="top flex-sb" @click="toDetail(item.id)">
<view class="type flex-l">{{item.order_info.item_title}}</view>
<view class="price flex-r important-color" v-if="item.order_info.receive_type === 1">上门报价</view>
<view class="price flex-r" v-else>平台已收款</view>
</view>
<view class="content flex-sb">
<view class="left" @click="toDetail(item.id)">
<view class="address-name flex-l" v-if="item.order_info.address !== ''">
{{item.order_info.address}}
</view>
<view class="address flex-l">
{{helpers.removeCommas(item.order_info.area.merge_name)}}
</view>
<view class="time-ctr flex-l" v-if="item.order_info.plan_time !== null">
<me-icon type="icon-time" color="var(--themeColor)" size="40rpx"></me-icon>
<text class="time">{{helpers.formatDate(item.order_info.plan_time)}}</text>
</view>
</view>
<view class="right" @click="helpers.openLocation(item.order_info.lat, item.order_info.lng)">
<view class="icon-ctr flex-c">
<me-icon type="icon-navigation" color="var(--descriptionColor)" size="60rpx"></me-icon>
</view>
<view class="distance flex-c" v-if="item.order_info.lng == 0 || item.order_info.lat == 0">未知距离</view>
<view class="distance flex-c" v-else>{{formatDistance(item.order_info.lat, item.order_info.lng)}}</view>
</view>
</view>
<view class="discount flex-l" @click="toDetail(item.id)" v-if="item.order_info.receive_type === 1">已支付订金{{item.order_info.online_amount}}元抵扣{{item.order_info.discount_amount}}</view>
<view class="btn-ctr flex-sb">
<me-button @click="acceptOrder(index, item.id)" text="确认接单" width="460rpx" icon-type="icon-flashlight"></me-button>
<me-button @click="rejectOrder(index, item.id)" active-color="var(--contentBgColor)" text="拒 接" width="166rpx" text-color="var(--titleColor)"></me-button>
</view>
</view>
</view>
<me-empty v-else text="暂无数据"></me-empty>
<me-empty-space height="100"></me-empty-space>
</view>
</template>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
<script setup>
import {onReachBottom, onShow, onPullDownRefresh} from '@dcloudio/uni-app'
import {reactive} from 'vue'
import MeIcon from "../../components/me-icon/me-icon";
import MeButton from "../../components/me-button/me-button";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space";
import helpers from "../../utils/helpers";
import api from "../../api/api";
import IndexSkeleton from "./index-skeleton";
onPullDownRefresh(() => {
data.page = 1
getList()
})
const acceptOrder = (index, id) => {
uni.showModal({
title: '接单提示',
confirmText: '确认',
content: '接单后请及时和客户联系,确认接单?',
success: function (res) {
if (res.confirm) {
uni.showLoading({
title: '接单中'
});
api.orderConfirm({type: 'accept', order_dispatch_id: id}).then(res => {
helpers.delayHideLoading()
helpers.showToast('已接单')
data.list.splice(index, 1)
}).catch(() => {})
}
}
});
}
const rejectOrder = (index, id) => {
uni.showModal({
title: '拒接提示',
confirmText: '确认',
editable: true,
placeholderText: '请输入拒接原因',
success: function (res) {
if (res.confirm) {
if (!res.content) {
return helpers.showToast('请输入拒接原因')
}
uni.showLoading({
title: '拒接中'
});
api.orderConfirm({type: 'reject', order_dispatch_id: id, reject_reason: res.content}).then(() => {
helpers.delayHideLoading()
helpers.showToast('已拒接')
data.list.splice(index, 1)
}).catch(() => {})
}
}
});
}
const toDetail = (id) => {
helpers.jumpToPage('order-info', `id=${id}`)
}
onShow(() => {
if (data.list === null) {
init()
}
})
const data = reactive({
page: 1,
page_size: 10,
last_page: 0,
is_show_skeleton: true,
list: null
})
const getList = () => {
if (data.page > 1) {
uni.showLoading({
title: '加载中'
});
}
api.orderDispatchList({page: data.page, page_size: data.page_size}).then(res => {
data.last_page = res.last_page
if (data.page === 1) {
data.list = res.data;
} else {
data.list = data.list.concat(helpers.deepObj(res.data))
}
data.is_show_skeleton = false
helpers.delayHideLoading()
}).catch(() => {}).finally(() => {
uni.stopPullDownRefresh();
})
}
const userLocation = reactive({
lng: null,
lat: null,
})
//
const init = () => {
//
uni.getLocation({
type: 'gcj02',
success(res) {
userLocation.lng = res.longitude
userLocation.lat = res.latitude
data.page = 1
getList()
},
fail(err) {
uni.showToast({
title: '请授权位置权限',
icon: "error"
})
}
});
}
const formatDistance = (lat, lng) => {
const res = helpers.getDistances(userLocation.lat, userLocation.lng, lat, lng);
return `${res.distance}${res.unit}`;
}
onReachBottom(() => {
if (data.page < data.last_page) {
data.page = data.page + 1
getList()
}
})
</script>
<style>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
.fixed-top {
position: fixed;
top: 0;
background-color: var(--pageBgColor);
width: 686rpx;
}
.refresh {
width: 108rpx;
height: 108rpx;
background: var(--themeColor);
border-radius: 50%;
position: fixed;
bottom: 64rpx;
right: 32rpx;
}
.rotate {
animation: spin 0.5s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<view class="ctr" v-if="data !== null">
<view class="form-group">
<view class="group-name flex-l line-after">
<me-icon class="icon" type="icon-info" color="#E18F00" size="40rpx"></me-icon>
<text class="text">上门后请提交信息</text>
</view>
<view class="item upload">
<view class="info flex-l">
<view class="title flex-l">拍照打卡</view>
<view class="desc flex-l">请上传上门的打卡照片最多 10 </view>
</view>
<view class="imgs-ctr">
<view class="img-item" v-for="(imgUrl, index) in images" :key="index">
<view @click="helpers.previewImage(imgUrl)" class="img-ctr" :style="{marginRight: (index+1) % 4 === 0 ? '0' : '55rpx'}">
<image class="img" mode="aspectFit" :src="imgUrl"></image>
</view>
<view class="del" @click="delImg(index)">
<me-icon class="icon" type="icon-close-circle-fill" color="var(--importantColor)" size="40rpx"></me-icon>
</view>
</view>
<view @click="upload()" class="up-ctr flex-direction-column" hover-class="auto-mask-layer-radius4"
hover-start-time="0" hover-stay-time="50">
<me-icon class="icon" type="icon-upload-cloud-fill" color="var(--summaryColor)" size="36rpx"></me-icon>
<view class="up flex-c">点击上传</view>
</view>
</view>
</view>
</view>
<me-empty-space height="376"></me-empty-space>
<view class="bottom">
<me-button @click="submit()" text="完成上门" width="686rpx" icon-type="icon-checkbox-circle" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeIcon from "../../components/me-icon/me-icon.vue";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import helpers from "../../utils/helpers";
import {ref} from 'vue'
import {onLoad} from '@dcloudio/uni-app'
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
import enums from "../../utils/enums";
const images = ref([])
const upload = () => {
if (images.value.length >= 10) {
return helpers.showToast('最多上传 10 张图片')
}
uni.chooseImage({
count: 1,
sizeType: ['original'],
sourceType: ['camera'],
success: (chooseImageRes) => {
if (chooseImageRes.tempFiles[0].size / 1024 / 1024 > 10) {
return helpers.showToast('照片不能超过10M')
}
uni.showLoading({
title: '上传中'
});
let tempFilePath = chooseImageRes.tempFilePaths[0]
api.getOssParams({name: tempFilePath}).then(res => {
uni.uploadFile({
url: res.cdnurl,
filePath: tempFilePath,
name: 'file',
timeout: 30 * 1000,
formData: {
'signature': res.signature,
'ossAccessKeyId': res.OSSAccessKeyId,
'policy': res.policy,
'key': res.key,
},
success(r) {
if (r.statusCode === undefined || r.statusCode !== 204) {
helpers.showToast('上传文件失败')
return
}
let fullUrl = res.cdnurl + '/' + res.key
images.value.push(fullUrl)
helpers.showToast('上传成功')
},
fail(e) {
helpers.showToast('上传文件失败')
console.log(e)
},
complete() {
helpers.delayHideLoading()
}
});
}).catch(() => {})
}
});
}
const delImg = (idx) => {
images.value.splice(idx, 1)
helpers.showToast('图片已删除')
}
//
const submit = throttle(() => {
if (images.value.length === 0) {
return helpers.showToast('请上传上门的打卡照片')
}
uni.showModal({
title: '提示信息',
confirmText: '确认',
content: '确认已到达客户地址?',
success: function (res) {
if (res.confirm) {
uni.showLoading({
title: '提交中'
});
let imagesStr = (images.value).join(',')
api.arrivedOnSite({order_dispatch_id: id.value, images: imagesStr}).then(() => {
helpers.delayHideLoading()
uni.showToast({
title: '已上门',
icon: "success"
})
setTimeout(() => {
uni.navigateBack();
}, 1000)
}).catch(() => {})
}
}
});
})
const id = ref(null)
onLoad((params) => {
id.value = params.id
init()
})
const data = ref(null)
const init = () => {
api.orderInfo({order_dispatch_id: id.value}).then(res => {
if (res.status !== enums.ORDER_DISPATCH_STATUS.STATUS_PLANIT) {
return helpers.showToast('该订单不可上门')
}
data.value = res
}).catch(() => {})
}
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

View File

@ -0,0 +1,324 @@
<template>
<view class="ctr" v-if="data !== null">
<view class="form-group">
<view class="group-name flex-l line-after">
<me-icon class="icon" type="icon-info" color="#E18F00" size="40rpx"></me-icon>
<text class="text">服务完成后请提交信息</text>
</view>
<view class="item upload">
<view class="info flex-l">
<view class="title flex-l">拍照打卡</view>
<view class="desc flex-l">请上传完成图片最多 10 </view>
</view>
<view class="imgs-ctr">
<view class="img-item" v-for="(imgUrl, index) in submitData.complete_images" :key="index">
<view @click="helpers.previewImage(imgUrl)" class="img-ctr" :style="{marginRight: (index+1) % 4 === 0 ? '0' : '55rpx'}">
<image class="img" mode="aspectFit" :src="imgUrl"></image>
</view>
<view class="del" @click="delImg(index)">
<me-icon class="icon" type="icon-close-circle-fill" color="var(--importantColor)" size="40rpx"></me-icon>
</view>
</view>
<view @click="upload('complete')" class="up-ctr flex-direction-column" hover-class="auto-mask-layer-radius4"
hover-start-time="0" hover-stay-time="50">
<me-icon class="icon" type="icon-upload-cloud-fill" color="var(--summaryColor)" size="36rpx"></me-icon>
<view class="up flex-c">点击上传</view>
</view>
</view>
</view>
</view>
<view class="form-group" v-if="data.order_info.receive_type === 1">
<view class="group-name flex-l line-after">
<me-icon class="icon" type="icon-info" color="#E18F00" size="40rpx"></me-icon>
<text class="text">提交收款信息</text>
</view>
<view class="item input flex-sb line-after" v-if="data.order_info.receive_type === 1">
<view class="title flex-l">优惠信息</view>
<view class="uni-input flex-r">{{data.order_info.online_amount}}元抵扣{{data.order_info.discount_amount}}</view>
</view>
<view class="item input flex-sb line-after" @click="selectFinalPaymentMethod()">
<view class="title flex-l">收款方式</view>
<view v-if="submitData.final_payment_method === null" class="select-ctr flex-r">请选择收款方式</view>
<view v-else class="select-ctr flex-r select">{{submitData.final_payment_method === 1 ? '线下尾款' : '线上尾款'}}</view>
</view>
<!-- 线下收款需选择尾款收款方-->
<view v-if="submitData.final_payment_method === 1" class="item input flex-sb line-after" @click="selectOfflineTotalType()">
<view class="title flex-l">尾款收款方</view>
<view v-if="submitData.offline_total_type === 0" class="select-ctr flex-r">请选择尾款收款方</view>
<view v-else class="select-ctr flex-r select">{{submitData.offline_total_type === 1 ? '师傅收' : '公司收'}}</view>
</view>
<view class="item input flex-sb line-after">
<view class="title flex-l">收款金额</view>
<view class="input-ctr">
<input type="digit" v-model="submitData.amount" class="uni-input" placeholder-class="placeholder-class" placeholder="请输入收款金额"/>
</view>
</view>
<view class="item upload">
<view class="info flex-l">
<view class="title flex-l">收款信息</view>
<view class="desc flex-l">请上传收款成功图片最多 1 </view>
</view>
<view class="imgs-ctr">
<view v-if="submitData.payment_image === ''" @click="upload('collectPayment')" class="up-ctr flex-direction-column" hover-class="auto-mask-layer-radius4"
hover-start-time="0" hover-stay-time="50">
<me-icon class="icon" type="icon-upload-cloud-fill" color="var(--summaryColor)" size="36rpx"></me-icon>
<view class="up flex-c">点击上传</view>
</view>
<view v-else class="img-item">
<view @click="helpers.previewImage(submitData.payment_image)" class="img-ctr">
<image class="img" mode="aspectFit" :src="submitData.payment_image"></image>
</view>
<view class="del" @click="delPaymentImg()">
<me-icon class="icon" type="icon-close-circle-fill" color="var(--importantColor)" size="40rpx"></me-icon>
</view>
</view>
</view>
</view>
</view>
<me-empty-space height="376"></me-empty-space>
<view class="bottom">
<me-button @click="submit()" text="提 交" width="686rpx" icon-type="icon-checkbox-circle" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeIcon from "../../components/me-icon/me-icon.vue";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import helpers from "../../utils/helpers";
import {ref, reactive} from 'vue'
import {onLoad} from '@dcloudio/uni-app'
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
import enums from "../../utils/enums";
/**
* 上传完成图片
* @param type 上传类型:complete=完成图片,collectPayment=收款图片
*/
const upload = (type) => {
uni.chooseImage({
count: 1,
sizeType: ['original'],
sourceType: ['camera'],
success: (chooseImageRes) => {
if (chooseImageRes.tempFiles[0].size / 1024 / 1024 > 10) {
return helpers.showToast('照片不能超过10M')
}
uni.showLoading({
title: '上传中'
});
let tempFilePath = chooseImageRes.tempFilePaths[0]
api.getOssParams({name: tempFilePath}).then(res => {
uni.uploadFile({
url: res.cdnurl,
filePath: tempFilePath,
name: 'file',
timeout: 30 * 1000,
formData: {
'signature': res.signature,
'ossAccessKeyId': res.OSSAccessKeyId,
'policy': res.policy,
'key': res.key,
},
success(r) {
if (r.statusCode === undefined || r.statusCode !== 204) {
helpers.showToast('上传文件失败')
return
}
let fullUrl = res.cdnurl + '/' + res.key
if (type === 'complete') {
submitData.complete_images.push(fullUrl)
}
if (type === 'collectPayment') {
submitData.payment_image = fullUrl
}
helpers.showToast('上传成功')
},
fail(e) {
helpers.showToast('上传文件失败')
console.log(e)
},
complete() {
helpers.delayHideLoading()
}
});
}).catch(() => {})
}
});
}
//
const delImg = (idx) => {
submitData.complete_images.splice(idx, 1)
helpers.showToast('图片已删除')
}
//
const delPaymentImg = () => {
submitData.payment_image = ''
helpers.showToast('图片已删除')
}
//
const submit = throttle(() => {
if (!validate()) {
return false
}
uni.showModal({
title: '提示信息',
confirmText: '确认',
content: '确认已完成所有服务?',
success: function (res) {
if (res.confirm) {
uni.showLoading({
title: '提交中'
});
let data = helpers.deepObj(submitData)
data.complete_images = (submitData.complete_images).join(',')
data.order_dispatch_id = id.value
api.completeService(data).then(() => {
helpers.delayHideLoading()
uni.showToast({
title: '已完成服务',
icon: "success"
})
setTimeout(() => {
uni.navigateBack();
}, 1000)
}).catch(() => {})
}
}
});
})
const id = ref(null)
onLoad((params) => {
id.value = params.id
init()
})
const data = ref(null)
const init = () => {
api.orderInfo({order_dispatch_id: id.value}).then(res => {
if (res.status !== enums.ORDER_DISPATCH_STATUS.STATUS_CLOCK) {
return helpers.showToast('该订单不可完成')
}
data.value = res
submitData.receive_type = res.order_info.receive_type
}).catch(() => {})
}
//
const submitData = reactive({
complete_images: [],//
final_payment_method: null,//1=线,2=线
offline_total_type: 0,//1=,2=
amount: '',//
payment_image: '',//
receive_type: null,//1=,2=
})
const selectFinalPaymentMethod = () => {
uni.showActionSheet({
itemList: ['线下尾款', '线上尾款'],
success: function (res) {
submitData.final_payment_method = res.tapIndex + 1
},
fail: function (res) {
console.log(res.errMsg);
}
});
}
const selectOfflineTotalType = () => {
uni.showActionSheet({
itemList: ['公司收', '师傅收'],
success: function (res) {
submitData.offline_total_type = res.tapIndex === 0 ? 2 : 1;
},
fail: function (res) {
console.log(res.errMsg);
}
});
}
//
const validate = () => {
if (submitData.complete_images.length === 0) {
helpers.showToast('请上传完成图片')
return false
}
if (data.value.order_info.receive_type === 2) {
return true
}
if (submitData.final_payment_method === null) {
helpers.showToast('请选择收款方式')
return false
}
if (submitData.final_payment_method === 1 && submitData.offline_total_type === 0) {
helpers.showToast('请选择尾款收款方')
return false
}
if (submitData.amount === '') {
helpers.showToast('请输入收款金额')
return false
}
if (submitData.payment_image === '') {
helpers.showToast('请上传收款信息')
return false
}
return true
}
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

503
pages/order/order-info.vue Normal file
View File

@ -0,0 +1,503 @@
<template>
<view class="ctr" v-if="data !== null">
<view class="price-ctr">
<view class="price flex-c" v-if="data.order_info.receive_type === 1">上门报价</view>
<view class="price flex-c" v-else>平台已收款</view>
<view class="desc flex-c">{{ getPriceDescText() }}</view>
</view>
<view class="info" v-if="data.status !== enums.ORDER_DISPATCH_STATUS.STATUS_TOGET">
<view class="item-multi-line">
<view class="title flex-l title-class">我的备注 <text v-if="data.worker_remark" class="description flex-l">仅自己可见点击备注可修改</text></view>
<view @click="updateWorkerRemark()">
<view class="value flex-l placeholder-class" v-if="data.worker_remark === ''">您可在此处输入备注信息该备注信息仅自己可见</view>
<view class="value flex-l" v-else>{{ data.worker_remark }}</view>
</view>
</view>
</view>
<view class="info">
<view class="item-row flex-sb line-after">
<view class="title flex-l">当前状态</view>
<view class="value flex-r order-status">
<text>{{getOrderStatusText(data.status)}}</text>
</view>
</view>
<view class="item-row flex-sb line-after">
<view class="title flex-l">服务类型</view>
<view class="value flex-r">
<text>{{data.order_info.item_title}}</text>
</view>
</view>
<template v-if="data.status !== enums.ORDER_DISPATCH_STATUS.STATUS_TOGET">
<view class="item-row flex-sb line-after">
<view class="title flex-l">客户姓名</view>
<view class="value flex-r">
<text>{{ data.order_info.customer }}</text>
</view>
</view>
<view class="item-row flex-sb line-after">
<view class="title flex-l">客户电话</view>
<view v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_FINISH" class="value flex-r">
<text>{{ data.order_info.tel }}</text>
</view>
<view v-else class="value flex-r value-theme" @click="helpers.makePhoneCall(data.order_info.tel)">
<text>{{ data.order_info.tel }}</text>
<me-icon class="icon" type="icon-call" color="var(--themeColor)" size="40rpx"></me-icon>
</view>
</view>
</template>
<view class="item-row flex-sb line-after">
<view class="title flex-l">预约上门时间</view>
<view class="value flex-r value-theme" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_PLANIT">
<uni-datetime-picker type="datetime" :start="Date.now()" :hide-second="true" @change="changePlanTime">
<view class="flex-r">
<text>{{data.plan_time}}</text>
<me-icon class="icon" type="icon-edit-line" color="var(--themeColor)" size="40rpx"></me-icon>
</view>
</uni-datetime-picker>
</view>
<view v-else class="value flex-r">
<text>{{data.plan_time}}</text>
</view>
</view>
<view class="item-multi-line line-after">
<view class="title flex-l">客户地址</view>
<view class="value flex-l">{{helpers.removeCommas(data.order_info.area.merge_name)}}{{ data.order_info.address }}</view>
</view>
<view class="item-multi-line line-after">
<view class="title flex-l">详情</view>
<view class="value flex-l">{{data.order_info.detail ? data.order_info.detail : '暂无详情'}}</view>
</view>
<view class="images line-after" v-if="data.order_info.images.length > 0">
<view class="title flex-l">图片</view>
<view class="imgs-ctr">
<view @click="helpers.previewImage(imgUrl)" v-for="(imgUrl, index) in data.order_info.images" :key="index" class="img-ctr" :style="{marginRight: (index+1) % 4 === 0 ? '0' : '55rpx'}">
<image class="img" mode="aspectFit" :src="imgUrl"></image>
</view>
</view>
</view>
<view class="item-multi-line line-after">
<view class="title flex-l">客户备注</view>
<view class="value flex-l">{{data.order_info.remark ? data.order_info.remark : '无备注信息'}}</view>
</view>
<view class="report-order-exception flex-c" v-if="canReportOrderException">
<view @click="reportOrderException(data.order_info.id)" class="report-ctr flex-c" hover-class="auto-mask-layer-radius4" hover-start-time="0" hover-stay-time="50">
<me-icon type="icon-arrow-up-line" color="var(--importantColor)" size="36rpx"></me-icon>
<text class="text">上报异常</text>
</view>
</view>
</view>
<!-- 已拒接-->
<view class="info" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_REFUSED">
<view class="item-multi-line">
<view class="title flex-l">拒接原因</view>
<view class="value flex-l">{{data.reject_reason ? data.reject_reason : '未填写原因'}}</view>
</view>
</view>
<!-- 已上门已完成 显示上门时间-->
<view class="info" v-if="[enums.ORDER_DISPATCH_STATUS.STATUS_CLOCK, enums.ORDER_DISPATCH_STATUS.STATUS_FINISH].includes(data.status)">
<view class="item-row flex-sb line-after">
<view class="title flex-l">上门时间</view>
<view class="value flex-r">
<text>{{data.arrive_time}}</text>
</view>
</view>
<view class="images">
<view class="title flex-l">上门图片</view>
<view class="imgs-ctr">
<view @click="helpers.previewImage(imgUrl)" v-for="(imgUrl, index) in data.arrive_images" :key="index" class="img-ctr" :style="{marginRight: (index+1) % 4 === 0 ? '0' : '55rpx'}">
<image class="img" mode="aspectFit" :src="imgUrl"></image>
</view>
</view>
</view>
</view>
<!-- 已完成 -->
<view class="info" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_FINISH">
<view class="item-row flex-sb line-after">
<view class="title flex-l">完成时间</view>
<view class="value flex-r">
<text>{{data.finish_time}}</text>
</view>
</view>
<view :class="[data.order_info.receive_type === 1 ? 'line-after' : '', 'images']">
<view class="title flex-l">完成图片</view>
<view class="imgs-ctr">
<view @click="helpers.previewImage(imgUrl)" v-for="(imgUrl, index) in data.images" :key="index" class="img-ctr" :style="{marginRight: (index+1) % 5 === 0 ? '0' : '36rpx'}">
<image class="img" mode="aspectFit" :src="imgUrl"></image>
</view>
</view>
</view>
<template v-if="data.order_info.receive_type === 1">
<view class="item-row flex-sb line-after" v-if="data.order_info.receive_type === 1">
<view class="title flex-l">优惠信息</view>
<view class="value flex-r">
<text>{{data.order_info.online_amount}}元抵扣{{data.order_info.discount_amount}}</text>
</view>
</view>
<view class="item-row flex-sb line-after" v-if="data.offline_total_type !== 0">
<view class="title flex-l">尾款收款方</view>
<view class="value flex-r">
<text>{{ data.offline_total_type === 1 ? '师傅收' : '公司收' }}</text>
</view>
</view>
<view class="item-row flex-sb line-after">
<view class="title flex-l">收款金额</view>
<view class="value flex-r">
<text>¥{{ data.total > 0 ? data.total : data.online_total }}</text>
</view>
</view>
<view class="images">
<view class="title flex-l">收款凭证</view>
<view class="imgs-ctr">
<view @click="helpers.previewImage(data.image)" :key="index" class="img-ctr">
<image class="img" mode="aspectFit" :src="data.image"></image>
</view>
</view>
</view>
</template>
</view>
<me-empty-space height="376"></me-empty-space>
<!-- 待接单-->
<view class="bottom" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_TOGET">
<me-button @click="acceptOrder()" text="确认接单" width="686rpx" icon-type="icon-flashlight"></me-button>
<me-button @click="rejectOrder()" active-color="rgba(0, 0, 0, 0)" margin-top="32rpx" text="拒 绝" width="686rpx" text-color="var(--titleColor)"></me-button>
</view>
<!-- 待和客户确认上门时间-->
<view class="bottom" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_GOTIT">
<me-button @click="selectTime()" text="已和客户沟通" width="686rpx" icon-type="icon-arrow-right-circle" margin-top="32rpx"></me-button>
</view>
<!-- 待上门-->
<view class="bottom" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_PLANIT">
<me-button @click="helpers.openLocation(data.order_info.lat, data.order_info.lng)" active-color="var(--contentBgColor)" icon-type="icon-navigation" text="导航至客户地址" width="686rpx" text-color="var(--titleColor)" custom-icon-color="var(--titleColor)"></me-button>
<me-button @click="arrivedOnSite()" text="到达现场" width="686rpx" icon-type="icon-arrow-right-circle" margin-top="32rpx"></me-button>
</view>
<!-- 完成服务-->
<view class="bottom" v-if="data.status === enums.ORDER_DISPATCH_STATUS.STATUS_CLOCK">
<me-button @click="completeService()" text="完成服务" width="686rpx" icon-type="icon-arrow-right-circle" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeIcon from "../../components/me-icon/me-icon.vue";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import helpers from "../../utils/helpers";
import {onLoad, onShow} from '@dcloudio/uni-app'
import {ref, computed} from 'vue'
import api from "../../api/api";
import enums from "../../utils/enums";
//
const canReportOrderException = computed(() => {
return data.value.status !== enums.ORDER_DISPATCH_STATUS.STATUS_TOGET && data.value.status !== enums.ORDER_DISPATCH_STATUS.STATUS_REFUSED
})
const changePlanTime = (time) => {
uni.showModal({
title: '提示信息',
content: '修改前需和客户约定,确定修改上门时间?',
success: function (res) {
if (res.confirm) {
api.updatePlanTime({order_dispatch_id: id.value, plan_time: time}).then(() => {
helpers.delayHideLoading()
uni.showToast({
title: '修改成功',
icon: "success"
})
data.value.plan_time = time + ':00'
}).catch(() => {})
}
}
});
}
//
const updateWorkerRemark = () => {
helpers.jumpToPage('worker-remark', `id=${id.value}&worker_remark=${data.value.worker_remark}`)
}
//
const reportOrderException = (orderId) => {
helpers.jumpToPage('report-order-exception', `order_id=${orderId}`)
}
//
const arrivedOnSite = () => {
//
uni.getLocation({
type: 'gcj02',
success(res) {
let envVersion = wx.getAccountInfoSync().miniProgram.envVersion
let distances = helpers.getDistances(res.latitude, res.longitude, data.value.order_info.lat, data.value.order_info.lng);
if (envVersion === 'release' && (distances.unit === '公里' || distances.distance > 500)) {
uni.showModal({
title: '上门失败',
showCancel: false,
content: `距离客户地址超过 500 米,当前距离:${distances.distance}${distances.unit}`,
success: function (res) {
}
});
return
}
helpers.jumpToPage('arrived-on-site', 'id=' + id.value)
},
fail(err) {
uni.showToast({
title: '请授权位置权限',
icon: "error"
})
}
});
}
//
const completeService = () => {
helpers.jumpToPage('complete-service', 'id=' + id.value)
}
//
const selectTime = () => {
helpers.jumpToPage('select-time', 'id=' + id.value)
}
const acceptOrder = () => {
uni.showModal({
title: '接单提示',
confirmText: '确认',
content: '接单后请及时和客户联系,确认接单?',
success: function (res) {
if (res.confirm) {
api.orderConfirm({type: 'accept', order_dispatch_id: id.value}).then(() => {
helpers.showToast('已接单')
init()
}).catch(() => {})
}
}
});
}
const rejectOrder = () => {
uni.showModal({
title: '拒接提示',
confirmText: '确认',
editable: true,
placeholderText: '请输入拒接原因',
success: function (res) {
if (res.confirm) {
if (!res.content) {
return helpers.showToast('请输入拒接原因')
}
api.orderConfirm({type: 'reject', order_dispatch_id: id.value, reject_reason: res.content}).then(() => {
helpers.showToast('已拒接')
init()
}).catch(() => {})
}
}
});
}
const id = ref(null)
onLoad((params) => {
id.value = params.id
})
onShow(() => {
init()
})
const data = ref(null)
const init = () => {
uni.showLoading({
title: '加载中'
});
api.orderInfo({order_dispatch_id: id.value}).then(res => {
data.value = res
helpers.delayHideLoading()
}).catch(() => {})
}
//
const getPriceDescText = () => {
let orderInfo = data.value
if (orderInfo.order_info.receive_type === 2) {
return '服务价格'
}
if (orderInfo.status === 60) {
let tailText = orderInfo.total > 0 ? '线下收款¥' + orderInfo.total : '线上收款¥' + orderInfo.online_total
return `服务价格(订金¥${orderInfo.order_info.online_amount}+${tailText})`
}
return `服务价格(已收订金¥${orderInfo.order_info.online_amount})`
}
//
const getOrderStatusText = (status) => {
return enums.WORKBENCH_STATUS_TEXT[status]
}
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.price-ctr {
min-height: 200rpx;
width: 100%;
padding: 32rpx 20rpx;
box-sizing: border-box;
.price {
width: 100%;
height: 80rpx;
font-weight: 500;
font-size: 36rpx;
color: var(--titleColor);
}
.desc {
width: 100%;
min-height: 56rpx;
font-size: 34rpx;
color: var(--summaryColor);
}
}
.info {
width: 100%;
background: var(--containerBgColor);
border-radius: 16rpx;
padding: 20rpx;
box-sizing: border-box;
margin-bottom: 32rpx;
.item-row {
width: 100%;
height: 80rpx;
position: relative;
.title {
width: 200rpx;
height: 100%;
font-size: 30rpx;
color: var(--summaryColor);
}
.value {
width: 446rpx;
height: 100%;
font-size: 30rpx;
color: var(--titleColor);
.icon {
margin-left: 4rpx;
}
}
.order-status {
color: #E18F00 !important;
}
.value-theme {
color: var(--themeColor) !important;
}
}
.item-multi-line {
width: 100%;
position: relative;
padding-bottom: 8rpx;
box-sizing: border-box;
.title {
width: 100%;
height: 80rpx;
font-size: 30rpx;
color: var(--summaryColor);
.description {
margin-left: 8rpx;
height: 80rpx;
font-size: 30rpx;
color: var(--descriptionColor);
font-weight: 400;
}
}
.value {
width: 100%;
font-size: 30rpx;
color: var(--titleColor);
line-height: 48rpx;
}
}
.report-order-exception {
width: 100%;
height: 80rpx;
margin-top: 20rpx;
.report-ctr {
width: 198rpx;
height: 64rpx;
border-radius: 8rpx;
.text {
font-size: 28rpx;
color: var(--importantColor);
}
}
}
.images {
width: 100%;
position: relative;
.title {
width: 100%;
height: 80rpx;
font-size: 30rpx;
color: var(--summaryColor);
}
.imgs-ctr {
width: 100%;
min-height: 100rpx;
display: flex;
flex-wrap: wrap;
.img-ctr {
width: 120rpx;
height: 120rpx;
margin-right: 36rpx;
margin-top: 16rpx;
margin-bottom: 16rpx;
.img {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.up-ctr {
width: 100rpx;
height: 100rpx;
background: var(--contentBgColor);
border-radius: 8rpx;
margin-top: 16rpx;
margin-bottom: 16rpx;
.up {
width: 100%;
height: 36rpx;
font-size: 20rpx;
color: var(--summaryColor);
}
}
}
}
}
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

View File

@ -0,0 +1,151 @@
<template>
<view class="ctr">
<view class="form-group">
<picker @change="bindPickerChange" range-key="title" :range="typeList">
<view class="item input flex-sb line-after">
<view class="title flex-l">异常原因</view>
<view v-if="submitData.abnormal_id === 0" class="select-ctr flex-r">请选择异常原因</view>
<view v-else class="select-ctr flex-r select">{{typeList[typeListIndex].title}}</view>
</view>
</picker>
<view class="textarea">
<view class="title flex-l">异常说明</view>
<view class="value">
<textarea maxlength="200" :disable-default-padding="true" class="input-textarea" v-model="submitData.detail" placeholder-class="placeholder-class" placeholder="请输入异常说明200字以内"/>
</view>
</view>
</view>
<me-empty-space height="376"></me-empty-space>
<view class="bottom">
<me-button @click="submit()" text="立即上报" width="686rpx" icon-type="icon-arrow-up-line" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import helpers from "../../utils/helpers";
import {ref, reactive} from 'vue'
import {onLoad} from '@dcloudio/uni-app'
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
const bindPickerChange = (e) => {
typeListIndex.value = e.detail.value;
submitData.abnormal_id = typeList.value[e.detail.value].id
}
const typeListIndex = ref(0)
//
const submit = throttle(() => {
if (!validate()) {
return false
}
uni.showModal({
title: '提示信息',
confirmText: '确认',
content: '确认上报异常?',
success: function (res) {
if (res.confirm) {
uni.showLoading({
title: '提交中'
});
submitData.order_id = orderId.value
api.createOrderAbnormal(submitData).then(() => {
helpers.delayHideLoading()
uni.showModal({
title: '提示信息',
showCancel: false,
content: '异常已上报',
success: function (res) {
if (res.confirm) {
uni.navigateBack();
}
}
});
init()
}).catch(() => {})
}
}
});
})
const init = () => {
api.findExceptionTypeList().then(res => {
typeList.value = res
}).catch(() => {}).finally(() => {
helpers.delayHideLoading()
})
}
const orderId = ref(null)
onLoad((params) => {
orderId.value = params.order_id
uni.showLoading({
title: '加载中'
})
init()
})
const typeList = ref(null)
//
const submitData = reactive({
abnormal_id: 0,
detail: '',
})
//
const validate = () => {
if (submitData.abnormal_id === 0) {
helpers.showToast('请选择异常原因')
return false
}
if (submitData.detail === '') {
helpers.showToast('请输入异常详情')
return false
}
return true
}
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

111
pages/order/select-time.vue Normal file
View File

@ -0,0 +1,111 @@
<template>
<view class="ctr" v-if="data !== null">
<view class="form-group">
<view class="group-name flex-l line-after">
<me-icon class="icon" type="icon-info" color="#E18F00" size="40rpx"></me-icon>
<text class="text">沟通后请提交信息</text>
</view>
<view class="item time">
<view class="item-row flex-sb">
<view class="title flex-l">上门时间</view>
<uni-datetime-picker v-model="data.plan_time" :start="Date.now()" type="datetime" :hide-second="true">
<view class="value flex-r value-empty" v-if="data.plan_time === null">点击选择上门时间</view>
<view class="value flex-r" v-else>{{ helpers.removeSeconds(data.plan_time) }}</view>
</uni-datetime-picker>
</view>
<view class="desc flex-l">点击时间可更改请确认和客户沟通的上门时间</view>
</view>
</view>
<me-empty-space height="376"></me-empty-space>
<view class="bottom">
<me-button @click="submit()" text="确认上门时间" width="686rpx" icon-type="icon-checkbox-circle" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeIcon from "../../components/me-icon/me-icon.vue";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import helpers from "../../utils/helpers";
import {ref} from 'vue'
import {onLoad} from '@dcloudio/uni-app'
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
import enums from "../../utils/enums";
//
const submit = throttle(() => {
uni.showModal({
title: '提示信息',
confirmText: '确认',
content: '确认已和客户约定上门时间?',
success: function (res) {
if (res.confirm) {
uni.showLoading({
title: '提交中'
});
api.appointmentTime({order_dispatch_id: id.value, plan_time: data.value.plan_time}).then(() => {
helpers.delayHideLoading()
uni.showToast({
title: '预约成功',
icon: "success"
})
setTimeout(() => {
uni.navigateBack();
}, 1000)
}).catch(() => {})
}
}
});
})
const id = ref(null)
onLoad((params) => {
id.value = params.id
init()
})
const data = ref(null)
const init = () => {
api.orderInfo({order_dispatch_id: id.value}).then(res => {
if (res.status !== enums.ORDER_DISPATCH_STATUS.STATUS_GOTIT) {
return helpers.showToast('该订单不可预约上门时间')
}
data.value = res
}).catch(() => {})
}
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<view class="ctr">
<view class="form-group">
<view class="textarea">
<view class="title flex-l">备注信息</view>
<view class="value">
<textarea maxlength="500" :disable-default-padding="true" class="input-textarea" v-model="submitData.worker_remark" placeholder-class="placeholder-class" placeholder="您可在此处输入备注信息该备注信息仅自己可见500字以内"/>
</view>
</view>
</view>
<me-empty-space height="376"></me-empty-space>
<view class="bottom">
<me-button @click="submit()" text="保 存" width="686rpx" icon-type="icon-checkbox-circle" margin-top="32rpx"></me-button>
</view>
</view>
</template>
<script setup>
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeButton from "../../components/me-button/me-button.vue";
import {ref, reactive} from 'vue'
import {onLoad} from '@dcloudio/uni-app'
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
import helpers from "../../utils/helpers";
//
const submit = throttle(() => {
uni.showLoading({
title: '保存中'
});
submitData.order_dispatch_id = orderDispatchId.value
api.saveWorkerRemark(submitData).then(() => {
helpers.delayHideLoading()
uni.showToast({
title: '已保存',
icon: "success"
})
setTimeout(()=>{
uni.navigateBack();
}, 1500)
}).catch(() => {})
})
const orderDispatchId = ref(null)
onLoad((params) => {
orderDispatchId.value = params.id
submitData.worker_remark = params.worker_remark
})
//
const submitData = reactive({
worker_remark: '',
})
</script>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
height: 100vh;
.value {
height: 300rpx !important;
}
.bottom {
width: 100%;
padding-top: 20rpx;
padding-bottom: 68rpx;
background: var(--pageBgColor);
box-sizing: border-box;
position: fixed;
bottom: 0;
}
}
</style>

View File

@ -1,11 +1,148 @@
<template>
<view>
测试
<view class="container">
<view class="info">
<view class="top flex-c">
<view class="icon-container flex-c">
<image class="img" mode="aspectFit" :src="inject('globalData').appIcon"></image>
</view>
</view>
<view class="bottom">超邦手工单系统</view>
</view>
<view class="login-area">
<view :class="[isShake ? 'animation-shake' : '', 'agreement flex-c']">
<view class="clickable-area flex-r" @click="select()">
<me-icon v-if="checked" class="icon" type="icon-checkbox-circle" size="40rpx" color="var(--themeColor)"></me-icon>
<me-icon v-else class="icon" type="icon-checkbox-blank-circle" size="40rpx" color="var(--summaryColor)"></me-icon>
阅读并同意
</view>
<view class="text">&nbsp<text @click="userAgreement()">用户协议</text><text @click="privacyPolicy()">隐私协议</text></view>
</view>
<view class="btn-area flex-c">
<view hover-class="auto-mask-layer-radius8" hover-start-time="0" hover-stay-time="50">
<button v-show="!isLogin" @click="login()" type="default" class="login flex-c"
>微信一键登录</button>
<button v-show="isLogin" open-type="getPhoneNumber" @getphonenumber="bindPhoneNumber" class="login flex-c" type="default"
>绑定手机号</button>
</view>
</view>
</view>
<view class="visitor-ctr flex-c">
<view class="visitor flex-c" @click="visitor()" hover-class="auto-mask-layer-radius8" hover-start-time="0" hover-stay-time="50">体验一下</view>
</view>
</view>
</template>
<script setup>
import MeIcon from "../../components/me-icon/me-icon.vue";
import { ref, inject } from 'vue'
import helpers from "../../utils/helpers";
import api from "../../api/api";
import {throttle} from "../../utils/throttle";
const userAgreement = () => {
helpers.jumpToPage('user-agreement')
}
const privacyPolicy = () => {
helpers.jumpToPage('privacy-policy')
}
const visitor = () => {
api.guestLogin().then(res => {
storageUserInfo(res)
setTimeout(() => {
helpers.jumpToPage('index','', 'switchTab')
}, 1000)
}).catch(() => {})
}
//
const checked = ref(false)
//
const isShake = ref(false)
//
const isLogin = ref(false)
//token
const vendorToken = ref('')
//
const bindPhoneNumber = throttle((e) => {
if (e.detail.code === undefined) {
return helpers.showToast("请授权手机号")
}
uni.showLoading({
title: '绑定中…'
});
api.bindPhoneNumber({code: e.detail.code, vendor_token: vendorToken.value}).then(res => {
helpers.showToast('绑定成功')
storageUserInfo(res)
setTimeout(() => {
helpers.jumpToPage('index','', 'switchTab')
}, 1000)
}).catch(() => {}).finally(() => {
helpers.delayHideLoading()
})
})
//
const login = throttle(() => {
if (checked.value === false) {
helpers.showToast("请阅读并同意用户协议")
isShake.value = true
setTimeout(() => {
isShake.value = false
}, 1000)
return false
}
uni.login({
provider: 'weixin',
success: function (res) {
uni.showLoading({
title: '登录中…'
});
if (!res.code) {
helpers.delayHideLoading()
return helpers.showToast('登录失败:' + res.errMsg)
}
api.wechatLogin({code: res.code}).then(res => {
helpers.showToast('登录成功')
storageUserInfo(res)
setTimeout(() => {
helpers.jumpToPage('index','', 'switchTab')
}, 1000)
}).catch(err => {
vendorToken.value = err.data.vendor_token
isLogin.value = true
}).finally(() => {
helpers.delayHideLoading()
})
}
});
}, 500)
//
const select = () => {
checked.value = !checked.value
}
//
const storageUserInfo = (userInfo) => {
uni.setStorageSync('token', userInfo.token)
uni.setStorageSync('user_info', userInfo)
}
</script>
<style>
page {
@ -15,5 +152,110 @@ page {
</style>
<style lang="scss" scoped>
.container {
padding: 0 32rpx;
box-sizing: border-box;
.info {
margin-top: 40rpx;
width: 100%;
.top {
width: 100%;
height: 160rpx;
.icon-container {
width: 160rpx;
height: 160rpx;
border-radius: 80rpx;
border: 1px solid #E9F1FE;
.img {
width: 160rpx;
height: 160rpx;
border-radius: 80rpx;
}
}
}
.bottom {
width: 100%;
height: 50rpx;
font-weight: 500;
font-size: 34rpx;
color: var(--titleColor);
line-height: 50rpx;
text-align: center;
margin-top: 36rpx;
}
}
.login-area {
width: 100%;
margin-top: 264rpx;
.agreement {
width: 100%;
height: 80rpx;
font-weight: 500;
font-size: 28rpx;
color: var(--titleColor);
line-height: 80rpx;
.clickable-area {
height: 80rpx;
.icon {
margin-left: 8rpx;
margin-right: 8rpx;
}
}
.text {
height: 80rpx;
text {
color: var(--themeColor);
}
}
}
.animation-shake{
animation: shake 800ms ease-in-out;
}
/* 水平抖动特效*/
@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}
20%, 80% {
transform: translate3d(+2px, 0, 0);
}
30%, 70% {
transform: translate3d(-4px, 0, 0);
}
40%, 60% {
transform: translate3d(+4px, 0, 0);
}
50% {
transform: translate3d(-4px, 0, 0);
}
}
.btn-area {
width: 100%;
height: 96rpx;
margin-top: 32rpx;
.login {
width: 590rpx;
height: 96rpx;
color: #FFFFFF;
background: var(--themeColor);
border-radius: 16rpx;
font-size: 30rpx;
}
}
}
.visitor-ctr {
width: 100%;
height: 104rpx;
position: fixed;
bottom: 68rpx;
left: 0;
.visitor {
width: 176rpx;
height: 72rpx;
font-size: 28rpx;
color: var(--summaryColor);
}
}
}
</style>

View File

@ -0,0 +1,26 @@
<template>
<view class="ctr">
<rich-text :nodes="data"></rich-text>
</view>
</template>
<script setup>
import { ref } from 'vue'
import {onShow} from '@dcloudio/uni-app'
import api from "../../api/api";
const data = ref('')
onShow(() => {
api.getConfig().then(res => {
data.value = res.privacy_policy
}).catch(() => {})
})
</script>
<style lang="scss" scoped>
.ctr {
background-color: var(--containerBgColor);
padding: 32rpx 32rpx 100rpx 32rpx;
color: var(--titleColor);
}
</style>

View File

@ -0,0 +1,26 @@
<template>
<view class="ctr">
<rich-text :nodes="data"></rich-text>
</view>
</template>
<script setup>
import { ref } from 'vue'
import {onShow} from '@dcloudio/uni-app'
import api from "../../api/api";
const data = ref('')
onShow(() => {
api.getConfig().then(res => {
data.value = res.user_agreement
}).catch(() => {})
})
</script>
<style lang="scss" scoped>
.ctr {
background-color: var(--containerBgColor);
padding: 32rpx 32rpx 100rpx 32rpx;
color: var(--titleColor);
}
</style>

View File

@ -1,22 +1,161 @@
<template>
<view>
</view>
<view class="ctr" v-if="userInfo.id !== undefined">
<view class="fixed-top">
<me-top title="我的" :is-show-icon="false"></me-top>
</view>
<me-empty-space :height="listMarginTop"></me-empty-space>
<view class="header flex-l">
<view class="avatar" :style="{background: 'var(--defaultUserAvatar)'}"></view>
<view class="info">
<view class="name">{{ userInfo.name }}</view>
<view class="phone">{{ userInfo.tel }}</view>
</view>
<view class="decorate"></view>
</view>
<view class="menus">
<view class="item flex-sb" @click="logout()" hover-class="auto-mask-layer-radius8" hover-start-time="0" hover-stay-time="50">
<view class="icon flex-c">
<me-icon type="icon-logout" color="var(--descriptionColor)" size="56rpx"></me-icon>
</view>
<view class="menu flex-sb">
<view class="left flex-l">退出登录</view>
<view class="right flex-r">
<me-icon type="icon-arrow-right" color="var(--contentBgColor)" size="56rpx"></me-icon>
</view>
</view>
</view>
</view>
<me-empty-space height="100"></me-empty-space>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
<script setup>
import {onShow} from '@dcloudio/uni-app'
import {ref, computed, inject} from 'vue'
import MeIcon from "../../components/me-icon/me-icon";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space.vue";
import MeTop from "../../components/me-top/me-top.vue";
import api from "../../api/api";
import helpers from "../../utils/helpers";
const listMarginTop = computed(() => {
return (inject('globalData').statusBarH + (inject('globalData').customBarH - inject('globalData').statusBarH)) * 2
})
const userInfo = ref({})
onShow(() => {
updateUserInfo()
})
const updateUserInfo = () => {
api.userInfo().then((res) => {
uni.setStorageSync('user_info', res)
userInfo.value = res
}).catch(() => {})
}
//退
const logout = () => {
uni.showLoading({
title: '退出中…'
});
api.logout().then(() => {
uni.removeStorageSync('token')
uni.removeStorageSync('user_info')
helpers.jumpToPage('login', '', 'reLaunch')
}).catch(() => {}).finally(() => {
helpers.delayHideLoading()
})
}
</script>
<style>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
.fixed-top {
position: fixed;
top: 0;
background-color: var(--pageBgColor);
width: 686rpx;
}
.header {
width: 100%;
height: 200rpx;
background: var(--containerBgColor);
border-radius: 16rpx;
padding: 40rpx 32rpx;
margin-top: 20rpx;
box-sizing: border-box;
position: relative;
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
}
.info {
margin-left: 20rpx;
width: 482rpx;
height: 120rpx;
.name,.phone {
width: 100%;
height: 60rpx;
line-height: 60rpx;
text-align: left;
}
.name {
font-weight: 500;
font-size: 34rpx;
color: var(--titleColor);
}
.phone {
font-size: 30rpx;
color: var(--summaryColor);
}
}
.decorate {
width: 240rpx;
height: 200rpx;
position: absolute;
right: 0;
background: url("/static/img/user-bg.png") no-repeat center / 100%;
border-radius: 0 16rpx 16rpx 0;
}
}
.menus {
margin-top: 32rpx;
width: 100%;
background: var(--containerBgColor);
border-radius: 16rpx;
padding: 20rpx;
box-sizing: border-box;
.item {
width: 100%;
height: 120rpx;
.icon {
width: 100rpx;
height: 120rpx;
}
.menu {
width: 546rpx;
height: 120rpx;
.left {
width: 266rpx;
height: 100%;
font-size: 30rpx;
color: var(--titleColor);
}
.right {
width: 280rpx;
height: 100%;
}
}
}
}
}
</style>

View File

@ -0,0 +1,392 @@
<template name="skeleton">
<view class="sk-container">
<view class="ctr ctr data-v-cda3a350 data-v-cda3a350">
<view class="fixed-top fixed-top data-v-cda3a350 data-v-cda3a350">
<view is="components/me-top/me-top" class="data-v-cda3a350 data-v-cda3a350">
<view class="me-top top--me-top data-v-e4d1a339 top--data-v-e4d1a339">
<view class="status-bar top--status-bar data-v-e4d1a339 top--data-v-e4d1a339" style="height:47px"></view>
<view class="capsule top--capsule flex-c top--flex-c data-v-e4d1a339 top--data-v-e4d1a339" style="height:40px">
<view class="icon-ctr top--icon-ctr flex-c top--flex-c data-v-e4d1a339 top--data-v-e4d1a339">
<image class="icon top--icon data-v-e4d1a339 top--data-v-e4d1a339 sk-image" mode="aspectFit"></image>
</view>
<text class="title top--title data-v-e4d1a339 top--data-v-e4d1a339 sk-transparent sk-text-14-2857-32 sk-text">工作台</text>
</view>
</view>
</view>
<view class="filter flex-sb line-after data-v-cda3a350 sk-pseudo sk-pseudo-circle">
<view class="filter-item filter-item flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="data-v-cda3a350 title flex-c sk-transparent sk-text-0-0000-179 sk-text">进行中(1)</view>
</view>
<view class="filter-item filter-item flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="data-v-cda3a350 title flex-c sk-transparent sk-text-0-0000-567 sk-text">今日(0)</view>
</view>
<view class="filter-item filter-item flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="data-v-cda3a350 title flex-c sk-transparent sk-text-0-0000-602 sk-text">明日(0)</view>
</view>
<view class="filter-item filter-item flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="data-v-cda3a350 title flex-c sk-transparent sk-text-0-0000-602 sk-text">全部(0)</view>
</view>
</view>
</view>
<view is="components/me-empty-space/me-empty-space" class="data-v-cda3a350 data-v-cda3a350">
<view class="me-empty-space space--me-empty-space" style="height:137px"></view>
</view>
<view class="list list data-v-cda3a350 data-v-cda3a350">
<view class="order-item order-item data-v-cda3a350 data-v-cda3a350">
<view class="top top flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="type flex-l data-v-cda3a350 sk-transparent sk-text-14-2857-977 sk-text">乳胶漆</view>
<view class="price flex-r important-color data-v-cda3a350 sk-transparent sk-text-14-2857-990 sk-text"></view>
</view>
<view class="content content flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="left left data-v-cda3a350 data-v-cda3a350">
<view class="address-name flex-l data-v-cda3a350 sk-transparent sk-text-15-9091-41 sk-text">222</view>
<view class="address data-v-cda3a350 sk-transparent sk-text-18-1818-14 sk-text">四川省成都市双流区</view>
<view class="time-ctr time-ctr flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-time icon--icon-time sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="time data-v-cda3a350 sk-transparent sk-text-18-1818-755 sk-text">周一 25年3月31日 11:33</text>
</view>
</view>
<view class="right right data-v-cda3a350 data-v-cda3a350">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-navigation icon--icon-navigation sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 30px; line-height: 30px;"></text>
</view>
</view>
</view>
<view class="distance flex-c data-v-cda3a350 sk-transparent sk-text-18-1818-111 sk-text">未知距离</view>
</view>
</view>
<view class="user user flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="left left data-v-cda3a350 data-v-cda3a350">
<view class="user-name user-name flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-user icon--icon-user sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 18px; line-height: 18px;"></text>
</view>
</view>
<view class="name data-v-cda3a350 sk-transparent sk-text-0-0000-613 sk-text">wwww</view>
</view>
<view class="phone flex-l data-v-cda3a350 sk-transparent sk-text-0-0000-533 sk-text">11111</view>
</view>
<view class="right right flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-cda3a350 data-v-cda3a350" hover-class="auto-mask-layer-radius8" hover-stay-time="100">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-call icon--icon-call sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 40px; line-height: 40px;"></text>
</view>
</view>
</view>
</view>
</view>
<view class="operate-ctr operate-ctr flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="status-ctr status-ctr flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-progress-2-line icon--icon-progress-2-line sk-pseudo sk-pseudo-circle" style="color: #E18F00; font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="text data-v-cda3a350 sk-transparent sk-text-14-2857-371 sk-text">待联系客户</text>
</view>
<view class="operate operate flex-r flex-r data-v-cda3a350 data-v-cda3a350">
<view class="btn btn flex-c flex-c data-v-cda3a350 data-v-cda3a350" hover-class="auto-mask-layer-radius8" hover-start-time="0" hover-stay-time="50">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-arrow-up-line icon--icon-arrow-up-line sk-pseudo sk-pseudo-circle" style="color: #FFFFFF; font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="data-v-cda3a350 sk-transparent sk-text-14-2857-25 sk-text">上报异常</text>
</view>
</view>
</view>
</view>
<view class="order-item order-item data-v-cda3a350 data-v-cda3a350">
<view class="top top flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="type flex-l data-v-cda3a350 sk-transparent sk-text-14-2857-977 sk-text">乳胶漆</view>
<view class="price flex-r important-color data-v-cda3a350 sk-transparent sk-text-14-2857-990 sk-text"></view>
</view>
<view class="content content flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="left left data-v-cda3a350 data-v-cda3a350">
<view class="address-name flex-l data-v-cda3a350 sk-transparent sk-text-15-9091-41 sk-text">222</view>
<view class="address data-v-cda3a350 sk-transparent sk-text-18-1818-14 sk-text">四川省成都市双流区</view>
<view class="time-ctr time-ctr flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-time icon--icon-time sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="time data-v-cda3a350 sk-transparent sk-text-18-1818-755 sk-text">周一 25年3月31日 11:33</text>
</view>
</view>
<view class="right right data-v-cda3a350 data-v-cda3a350">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-navigation icon--icon-navigation sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 30px; line-height: 30px;"></text>
</view>
</view>
</view>
<view class="distance flex-c data-v-cda3a350 sk-transparent sk-text-18-1818-111 sk-text">未知距离</view>
</view>
</view>
<view class="user user flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="left left data-v-cda3a350 data-v-cda3a350">
<view class="user-name user-name flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-user icon--icon-user sk-pseudo sk-pseudo-circle" style="color: var(--descriptionColor); font-size: 18px; line-height: 18px;"></text>
</view>
</view>
<view class="name data-v-cda3a350 sk-transparent sk-text-0-0000-613 sk-text">wwww</view>
</view>
<view class="phone flex-l data-v-cda3a350 sk-transparent sk-text-0-0000-533 sk-text">11111</view>
</view>
<view class="right right flex-c flex-c data-v-cda3a350 data-v-cda3a350">
<view class="icon-ctr icon-ctr flex-c flex-c data-v-cda3a350 data-v-cda3a350" hover-class="auto-mask-layer-radius8" hover-stay-time="100">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-call icon--icon-call sk-pseudo sk-pseudo-circle" style="color: var(--themeColor); font-size: 40px; line-height: 40px;"></text>
</view>
</view>
</view>
</view>
</view>
<view class="operate-ctr operate-ctr flex-sb flex-sb data-v-cda3a350 data-v-cda3a350">
<view class="status-ctr status-ctr flex-l flex-l data-v-cda3a350 data-v-cda3a350">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-progress-2-line icon--icon-progress-2-line sk-pseudo sk-pseudo-circle" style="color: #E18F00; font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="text data-v-cda3a350 sk-transparent sk-text-14-2857-371 sk-text">待联系客户</text>
</view>
<view class="operate operate flex-r flex-r data-v-cda3a350 data-v-cda3a350">
<view class="btn btn flex-c flex-c data-v-cda3a350 data-v-cda3a350" hover-class="auto-mask-layer-radius8" hover-start-time="0" hover-stay-time="50">
<view is="components/me-icon/me-icon" class="data-v-cda3a350 data-v-cda3a350">
<view class="flex-c icon--flex-c data-v-f0c409e8 icon--data-v-f0c409e8">
<text class="me-icon icon--me-icon data-v-f0c409e8 icon--data-v-f0c409e8 icon-arrow-up-line icon--icon-arrow-up-line sk-pseudo sk-pseudo-circle" style="color: #FFFFFF; font-size: 20px; line-height: 20px;"></text>
</view>
</view>
<text class="data-v-cda3a350 sk-transparent sk-text-14-2857-25 sk-text">上报异常</text>
</view>
</view>
</view>
</view>
<view class="order-item order-item data-v-cda3a350 data-v-cda3a350"></view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
@import '../../components/me-icon/me-icon.css';
@font-face {
font-family: me-icon;
src: url('../../components/me-icon/me-icon.ttf');
}
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
.btn-container {
.icon {
margin-right: 8rpx;
}
.btn {
width: 100%;
height: 96rpx;
border-radius: 16rpx;
font-size: 30rpx;
line-height: 112rpx;
text-align: center;
.text {
height: 96rpx;
line-height: 96rpx;
}
}
.btn-active {
color: #FFFFFF;
}
.btn-default {
color: var(--descriptionColor);
}
.wireframe-btn {
.btn {
border: 1px solid var(--contentBgColor);
box-sizing: border-box;
}
}
}
.me-icon {
font-family: me-icon;
text-decoration: none;
text-align: center;
}
.me-top {
.capsule {
.icon-ctr {
width: 60rpx;
height: 60rpx;
border: 1px solid #E9F1FE;
border-radius: 50%;
position: absolute;
left: 0;
.icon {
width: 80%;
height: 80%;
border-radius: 50%;
}
}
.title {
font-weight: 500;
font-size: 32rpx;
color: var(--titleColor);
}
}
}
.fixed-top {
position: fixed;
top: 0;
background-color: var(--pageBgColor);
width: 686rpx;
.filter {
width: 686rpx;
height: 100rpx;
.filter-item {
width: 170rpx;
height: 100%;
position: relative;
.title {
width: 120rpx;
font-size: 28rpx;
color: var(--summaryColor);
line-height: 40rpx;
}
.title-active {
color: var(--themeColor) !important;
}
.select-style {
position: absolute;
bottom: 0;
width: 122rpx;
height: 4rpx;
background: var(--themeColor);
border-radius: 2rpx;
}
}
}
}
.order-item .operate-ctr .operate .btn {
background-color: var(--auxiliaryBgColor);
}
.me-top .capsule .icon-ctr {
border: 1px solid var(--auxiliaryBgColor)!important;
}
}
</style>
<style>
.sk-transparent {
color: transparent !important;
}
.sk-text-14-2857-32 {
background-image: linear-gradient(transparent 14.2857%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 85.7143%, transparent 0%) !important;
background-size: 100% 44.8000rpx;
position: relative !important;
}
.sk-text {
background-origin: content-box !important;
background-clip: content-box !important;
background-color: transparent !important;
color: transparent !important;
background-repeat: repeat-y !important;
}
.sk-text-0-0000-179 {
background-image: linear-gradient(transparent 0.0000%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 100.0000%, transparent 0%) !important;
background-size: 100% 28.0000rpx;
position: relative !important;
}
.sk-text-0-0000-567 {
background-image: linear-gradient(transparent 0.0000%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 100.0000%, transparent 0%) !important;
background-size: 100% 28.0000rpx;
position: relative !important;
}
.sk-text-0-0000-602 {
background-image: linear-gradient(transparent 0.0000%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 100.0000%, transparent 0%) !important;
background-size: 100% 28.0000rpx;
position: relative !important;
}
.sk-text-14-2857-977 {
background-image: linear-gradient(transparent 14.2857%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-990 {
background-image: linear-gradient(transparent 14.2857%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-15-9091-41 {
background-image: linear-gradient(transparent 15.9091%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 84.0909%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-14 {
background-image: linear-gradient(transparent 18.1818%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-755 {
background-image: linear-gradient(transparent 18.1818%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-18-1818-111 {
background-image: linear-gradient(transparent 18.1818%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 81.8182%, transparent 0%) !important;
position: relative !important;
}
.sk-text-0-0000-613 {
background-image: linear-gradient(transparent 0.0000%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 100.0000%, transparent 0%) !important;
background-size: 100% 28.0000rpx;
position: relative !important;
}
.sk-text-0-0000-533 {
background-image: linear-gradient(transparent 0.0000%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 100.0000%, transparent 0%) !important;
background-size: 100% 28.0000rpx;
position: relative !important;
}
.sk-text-14-2857-371 {
background-image: linear-gradient(transparent 14.2857%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 85.7143%, transparent 0%) !important;
position: relative !important;
}
.sk-text-14-2857-25 {
background-image: linear-gradient(transparent 14.2857%, var(--auxiliaryBgColor) 0%, var(--auxiliaryBgColor) 85.7143%, transparent 0%) !important;
background-size: 100% 39.2000rpx;
position: relative !important;
}
.sk-image {
background: var(--auxiliaryBgColor) !important;
}
.sk-pseudo::before, .sk-pseudo::after {
background: var(--auxiliaryBgColor) none !important;
color: transparent !important;
border-color: transparent !important;
}
.sk-pseudo-circle::before, .sk-pseudo-circle::after {
border-radius: 50% !important;
}
.sk-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: transparent;
}
</style>
<script setup lang="ts">
</script>

View File

@ -1,22 +1,426 @@
<template>
<view>
</view>
<!-- <WorkbenchSkeleton v-if="data.is_show_skeleton"></WorkbenchSkeleton>-->
<view class="ctr" v-if="data.list !== null">
<view class="fixed-top">
<me-top title="工作台"></me-top>
<view class="filter flex-sb line-after">
<view v-for="(item, type) in filterType" :key="type" class="filter-item flex-c" @click="filter(type)">
<view :class="['title', 'flex-c', data.type === type ? 'title-active' : '']">{{item.name}}{{ countOrderByType(type) }}</view>
<view class="select-style" v-if="data.type === type"></view>
</view>
</view>
<view class="date flex-l" v-if="data.type === 'need_visit'">
<view @click="filterNeedVisit(type)" :class="['item', 'flex-c', data.need_visit_type === type ? 'item-selected' : '']" v-for="(item, type) in needVisitType" :key="type">{{item.name}}{{ countOrderByType(type) }}</view>
</view>
</view>
<me-empty-space :height="listMarginTop"></me-empty-space>
<view class="list" :style="{ transform: data.type === 'need_visit' ? 'translateY(100rpx)' : 'translateY(0)' }" v-if="data.list.length > 0">
<view class="item" v-for="(item, index) in data.list" :key="index" @click="toDetail(item.id)">
<view class="top flex-sb">
<view class="time flex-l">
<me-icon type="icon-time" color="var(--themeColor)" size="44rpx"></me-icon>
<text class="time-text" v-if="item.order_info.plan_time !== null">{{helpers.formatDate(item.plan_time)}}</text>
<text class="time-text" v-else>未预约时间</text>
</view>
<view class="status flex-r">{{getOrderStatusText(item.status)}}</view>
</view>
<view class="title flex-l">{{item.order_info.item_title}}</view>
<view class="address-ctr flex-sb">
<view class="left">
<view class="detail flex-l" v-if="item.order_info.address !== ''">{{item.order_info.address}}</view>
<view class="area flex-l">{{helpers.removeCommas(item.order_info.area.merge_name)}}</view>
</view>
<view class="right" @click.stop="helpers.openLocation(item.order_info.lat, item.order_info.lng)">
<view class="icon-ctr flex-c">
<me-icon type="icon-navigation" color="var(--descriptionColor)" size="60rpx"></me-icon>
</view>
<view class="distance flex-c" v-if="item.order_info.lng == 0 || item.order_info.lat == 0">未知距离</view>
<view class="distance flex-c" v-else>{{formatDistance(item.order_info.lat, item.order_info.lng)}}</view>
</view>
</view>
<view class="user-ctr flex-sb">
<view class="user-name flex-l">
<me-icon type="icon-user" color="var(--descriptionColor)" size="36rpx"></me-icon>
<view class="name flex-l">{{ item.order_info.customer }}</view>
</view>
<view class="phone flex-r">{{ item.order_info.tel }}</view>
</view>
<view class="operate-ctr flex-sb">
<view class="left flex-l">
<me-icon type="icon-money-cny-circle-line" color="var(--summaryColor)" size="44rpx"></me-icon>
<view class="name flex-l" v-if="item.order_info.receive_type === 1">上门报价</view>
<view class="name flex-l" v-else>平台已收款</view>
</view>
<view class="right flex-r" @click.stop="helpers.makePhoneCall(item.order_info.tel)">
<me-icon type="icon-call" color="var(--themeColor)" size="44rpx"></me-icon>
<view class="name flex-l">联系客户</view>
</view>
</view>
</view>
</view>
<me-empty v-else text="暂无数据"></me-empty>
<me-empty-space height="100"></me-empty-space>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
<script setup>
import {onShow, onReachBottom} from '@dcloudio/uni-app'
import {ref, reactive, computed, inject} from 'vue'
import MeIcon from "../../components/me-icon/me-icon";
import MeEmptySpace from "../../components/me-empty-space/me-empty-space";
import MeTop from "../../components/me-top/me-top.vue";
import api from "../../api/api";
import helpers from "../../utils/helpers";
import enums from "../../utils/enums";
import WorkbenchSkeleton from "./workbench-skeleton";
onReachBottom(() => {
if (data.page < data.last_page) {
data.page = data.page + 1
getList()
}
})
//
const toDetail = (id) => {
helpers.jumpToPage('order-info', `id=${id}`)
}
//
const reportOrderException = (orderId) => {
helpers.jumpToPage('report-order-exception', `order_id=${orderId}`)
}
//
const isShowSkeleton = computed(() => {
return data.list === null || countOrder === undefined
})
const getOrderStatusText = (status) => {
return enums.WORKBENCH_STATUS_TEXT[status]
}
onShow(() => {
init()
})
const userLocation = reactive({
lng: null,
lat: null,
})
const formatDistance = (lat, lng) => {
const res = helpers.getDistances(userLocation.lat, userLocation.lng, lat, lng);
return `${res.distance}${res.unit}`;
}
//
const init = () => {
//
uni.getLocation({
type: 'gcj02',
success(res) {
userLocation.lng = res.longitude
userLocation.lat = res.latitude
data.page = 1
getList()
countWorkbenchOrder()
},
fail(err) {
uni.showToast({
title: '请授权位置权限',
icon: "error"
})
}
});
}
const countOrder = ref({})
const countWorkbenchOrder = () => {
api.countWorkbenchOrder().then(res => {
countOrder.value = res
}).catch(() => {})
}
const countOrderByType = (type) => {
if (Object.keys(countOrder.value).length === 0 || countOrder.value[type] === 0) {
return ''
}
return '(' + (countOrder.value[type] > 99 ? '99+' : countOrder.value[type]) + ')'
}
const data = reactive({
type: 'pending',
need_visit_type: 'today',
page: 1,
page_size: 10,
last_page: 0,
is_show_skeleton: false,//
list: null
})
const getList = () => {
if (data.page > 1) {
uni.showLoading({
title: '加载中'
});
}
let params = {
page: data.page,
page_size: data.page_size,
workbench_type: data.type,
need_visit_type: data.need_visit_type,
}
api.workbenchOrderList(params).then(res => {
data.last_page = res.last_page
if (data.page === 1) {
data.list = res.data;
} else {
data.list = data.list.concat(helpers.deepObj(res.data))
}
data.is_show_skeleton = false
helpers.delayHideLoading()
}).catch(() => {})
}
const listMarginTop = computed(() => {
let globalData = inject('globalData')
let res = (globalData.statusBarH + (globalData.customBarH - globalData.statusBarH) + 50) * 2
if (data.type !== 'need_visit') {
res += 20
}
return res
})
const filterType = reactive({
'pending': {
name: '待沟通',
},
'need_visit': {
name: '待上门',
},
'ongoing': {
name: '服务中',
},
'finished': {
name: '已完成',
},
})
const needVisitType = reactive({
'today': {
name: '今日',
},
'tomorrow': {
name: '明日',
},
'all': {
name: '全部',
}
})
const filter = (type) => {
data.type = type
if (type === 'need_visit') {
data.need_visit_type = 'today'
}
data.page = 1
uni.showLoading({
title: '加载中'
});
getList()
}
const filterNeedVisit = (type) => {
data.need_visit_type = type
data.page = 1
uni.showLoading({
title: '加载中'
});
getList()
}
</script>
<style>
<style lang="scss" scoped>
.ctr {
padding: 0 32rpx;
box-sizing: border-box;
.list {
transition: transform 0.3s ease;
.item:first-child {
margin-top: 0!important;
}
.item {
width: 686rpx;
background: var(--containerBgColor);
border-radius: 16rpx;
padding: 20rpx;
box-sizing: border-box;
margin-top: 20rpx;
.top {
width: 100%;
height: 80rpx;
.time {
width: 456rpx;
height: 80rpx;
.time-text {
font-weight: 500;
font-size: 34rpx;
color: var(--themeColor);
margin-left: 8rpx;
}
}
.status {
width: 190rpx;
height: 80rpx;
font-weight: 500;
font-size: 34rpx;
color: #E18F00;
}
}
.title {
width: 100%;
min-height: 60rpx;
line-height: 48rpx;
font-weight: 500;
font-size: 30rpx;
color: var(--titleColor);
}
.address-ctr {
width: 100%;
.left {
width: 466rpx;
.detail, .area {
width: 100%;
min-height: 60rpx;
line-height: 44rpx;
font-size: 28rpx;
}
.detail {
color: var(--titleColor);
}
.area {
color: var(--summaryColor);
}
}
.right {
width: 180rpx;
.icon-ctr {
height: 60rpx;
width: 100%
}
.distance {
width: 100%;
min-height: 44rpx;
line-height: 44rpx;
font-size: 28rpx;
color: var(--titleColor);
margin-top: 16rpx;
}
}
}
.user-ctr {
width: 646rpx;
height: 90rpx;
background: var(--auxiliaryBgColor);
border-radius: 16rpx;
padding: 20rpx;
box-sizing: border-box;
margin-top: 10rpx;
.user-name {
width: 50%;
.name, {
font-size: 28rpx;
color: var(--titleColor);
margin-left: 8rpx;
}
}
.phone {
width: 50%;
font-size: 28rpx;
color: var(--titleColor);
}
}
.operate-ctr {
width: 100%;
height: 80rpx;
margin-top: 20rpx;
.left, .right {
width: 50%;
font-weight: 500;
font-size: 30rpx;
.name {
margin-left: 8rpx;
}
}
.left {
color: var(--summaryColor);
}
.right {
color: var(--themeColor);
}
}
}
}
.fixed-top {
position: fixed;
top: 0;
background-color: var(--pageBgColor);
width: 686rpx;
z-index: 100;
.filter {
width: 686rpx;
height: 100rpx;
position: relative;
.filter-item {
width: 170rpx;
height: 100%;
position: relative;
.title {
width: 100%;
font-size: 28rpx;
color: var(--summaryColor);
line-height: 28rpx;
}
.title-active {
color: var(--themeColor) !important;
}
.select-style {
position: absolute;
bottom: 0;
width: 122rpx;
height: 4rpx;
background: var(--themeColor);
border-radius: 2rpx;
}
}
}
.date {
width: 686rpx;
height: 100rpx;
animation: animation-fade-out .3s ease-out 0s 1;
.item {
height: 60rpx;
border-radius: 8rpx;
background-color: var(--auxiliaryBgColor);
color: var(--summaryColor);
font-size: 28rpx;
padding: 0 24rpx;
margin-left: 20rpx;
}
.item-selected {
background-color: var(--themeColor10);
color: var(--themeColor);
}
}
}
}
</style>

View File

@ -56,7 +56,7 @@
position: absolute;
width: 200%;
height: 1px;
background: var(--dividingLineColor);
background: var(--dividerColor);
transform: scale(0.5);
transform-origin: 0 0;
}
@ -78,7 +78,7 @@
position: absolute;
width: 1px;
height: 200%;
background: var(--dividingLineColor);
background: var(--dividerColor);
transform: scale(0.5);
transform-origin: 0 0;
}
@ -152,7 +152,7 @@
}
.auto-mask-layer-radius0::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 0;
}
.auto-mask-layer-radius4{
@ -160,7 +160,7 @@
}
.auto-mask-layer-radius4::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 8rpx;
}
@ -169,16 +169,25 @@
}
.auto-mask-layer-radius8::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 16rpx;
}
.auto-mask-layer-radius100{
position: relative;
}
.auto-mask-layer-radius100::after {
@include auto-mask-layer();
background-color: var(--contentBgColor);
border-radius: 200rpx;
}
.auto-mask-layer-radius-b8{
position: relative;
}
.auto-mask-layer-radius-b8::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 0rpx 0rpx 16rpx 16rpx;
}
@ -187,7 +196,7 @@
}
.auto-mask-layer-radius-lb8::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 0rpx 0rpx 0rpx 16rpx;
}
@ -196,7 +205,7 @@
}
.auto-mask-layer-radius-rb8::after {
@include auto-mask-layer();
background-color: var(--hotZoneBgColor);
background-color: var(--contentBgColor);
border-radius: 0rpx 0rpx 16rpx 0rpx;
}
@ -234,12 +243,14 @@
.clickable-text {
color: var(--themeColor);
}
.clickable-text:active {
color: var(--themeColorClick);
}
.placeholder-class {
color: var(--contentColor30);
color: var(--descriptionColor) !important;
}
.title-class {
color: var(--titleColor) !important;
font-weight: 500;
}
swiper .wx-swiper-dots .wx-swiper-dot{
@ -248,3 +259,153 @@ swiper .wx-swiper-dots .wx-swiper-dot{
border-radius: 5rpx;
margin-bottom: 20rpx;
}
.order-item {
width: 100%;
background: var(--containerBgColor);
border-radius: 16rpx;
padding: 20rpx;
box-sizing: border-box;
margin-top: 32rpx;
.top {
min-height: 80rpx;
.type,.price {
width: 323rpx;
min-height: 80rpx;
padding: 8rpx 0;
box-sizing: border-box;
}
.type {
font-weight: 500;
font-size: 34rpx;
color: var(--titleColor);
line-height: 48rpx;
}
.price {
font-size: 30rpx;
color: var(--summaryColor);
font-weight: 500;
}
.important-color {
color: var(--importantColor) !important;
}
}
.content {
width: 100%;
min-height: 160rpx;
.left {
width: 466rpx;
.address-name {
width: 100%;
min-height: 60rpx;
font-size: 30rpx;
color: var(--titleColor);
line-height: 44rpx;
}
.address {
width: 100%;
min-height: 60rpx;
font-size: 28rpx;
color: var(--summaryColor);
line-height: 44rpx;
}
.time-ctr {
width: 100%;
min-height: 80rpx;
font-size: 28rpx;
color: var(--themeColor);
line-height: 44rpx;
.time {
margin-left: 8rpx;
}
}
}
.right {
width: 180rpx;
.icon-ctr {
width: 100%;
height: 60rpx;
}
.distance {
width: 100%;
height: 44rpx;
font-size: 28rpx;
color: var(--titleColor);
line-height: 44rpx;
margin-top: 32rpx;
}
}
}
.discount {
width: 100%;
height: 64rpx;
background: rgba(230,82,31,0.1);
border-radius: 16rpx;
font-size: 28rpx;
color: var(--importantColor);
padding: 0 16rpx;
box-sizing: border-box;
}
.btn-ctr {
width: 100%;
height: 126rpx;
box-sizing: border-box;
margin-top: 10rpx;
}
.user {
width: 100%;
height: 140rpx;
background: var(--auxiliaryBgColor);
border-radius: 16rpx;
padding: 20rpx 20rpx 20rpx 32rpx;
box-sizing: border-box;
.left {
.user-name,.phone {
width: 422rpx;
height: 50rpx;
font-size: 28rpx;
color: var(--titleColor);
line-height: 28rpx;
}
.user-name {
.name {
margin-left: 8rpx;
}
}
}
.right {
width: 140rpx;
height: 100rpx;
.icon-ctr {
width: 100rpx;
height: 100rpx;
}
}
}
.operate-ctr {
width: 100%;
height: 80rpx;
font-size: 28rpx;
margin-top: 20rpx;
.status-ctr,.operate {
width: 50%;
}
.status-ctr {
.text {
margin-left: 8rpx;
font-size: 30rpx;
color: #E18F00;
}
}
.operate {
.btn {
width: 186rpx;
height: 76rpx;
background: #E18F00;
border-radius: 16rpx;
font-size: 28rpx;
color: #FFFFFF;
}
}
}
}

View File

@ -1,404 +1,164 @@
.form-area {
margin-top: 20rpx;
.form-group {
width: 100%;
padding: 20rpx 40rpx;
box-sizing: border-box;
background: var(--blockBgColor);
background: var(--containerBgColor);
border-radius: 16rpx;
.form-area-title {
padding: 20rpx;
box-sizing: border-box;
margin-top: 32rpx;
.group-name {
width: 100%;
height: 60rpx;
font-size: 34rpx;
color: var(--contentColor50);
line-height: 60rpx;
text-align: left;
margin-bottom: 20rpx;
}
.uni-forms-item {
margin-bottom: 0 !important;
.uni-forms-item__content {
width: 100%;
height: 80rpx;
position: relative;
.text {
font-size: 30rpx;
color: #E18F00;
margin-left: 8rpx;
}
}
.input-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
margin-bottom: 20rpx;
.item {
width: 100%;
}
.textarea {
width: 100%;
.title {
width: 100%;
height: 60rpx;
font-weight: 500;
height: 80rpx;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 60rpx;
text-align: left;
.left {
height: 100%;
width: 300rpx;
}
.right {
width: 300rpx;
height: 100%;
//添加项目
.add-project {
width: 140rpx;
height: 60rpx;
background: var(--themeColor10);
border-radius: 8rpx;
font-weight: 500;
font-size: 24rpx;
color: var(--themeColor);
}
.setting {
width: 140rpx;
height: 100%;
font-size: 28rpx;
font-weight: 400;
}
}
}
.required::before {
content: '*';
font-weight: 500;
font-size: 32rpx;
color: #E6521F;
left: -24rpx;
position: absolute;
color: var(--titleColor);
}
.value {
width: 100%;
min-height: 100rpx;
height: 120rpx;
.input-textarea {
height: 120rpx;
padding: 20rpx 0;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 40rpx;
width: 100%;
}
.mixed-payment-items {
width: 100%;
margin-bottom: 20rpx;
animation: animation-fade-out 0.3s ease-out 0s 1;
.item {
width: 100%;
.icon {
width: 56rpx;
height: 80rpx;
}
.content {
width: 558rpx;
height: 80rpx;
.title {
width: 202rpx;
height: 80rpx;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 80rpx;
text-align: left;
font-weight: 400;
.help {
width: 50rpx;
height: 80rpx;
}
}
.detail {
width: 372rpx;
height: 80rpx;
font-size: 28rpx;
color: var(--contentColor90);
line-height: 56rpx;
.price {
width: 160rpx;
height: 56rpx;
background: var(--contentColor05);
border-radius: 8rpx;
.unit {
width: 40rpx;
height: 56rpx;
text-align: center;
}
.val {
width: 120rpx;
height: 56rpx;
.uni-input {
width: 100%;
min-height: 56rpx;
text-align: center;
padding: 0 8rpx;
box-sizing: border-box;
}
}
}
}
}
}
}
.uni-input {
width: 100%;
min-height: 100rpx;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 100rpx;
text-align: left;
}
.item-image {
margin-top: 20rpx;
margin-bottom: 24rpx;
.empty-image {
width: 630rpx;
height: 384rpx;
border-radius: 40rpx;
border: 1rpx solid var(--contentColor10);
box-sizing: border-box;
.upload-image {
width: 120rpx;
height: 128rpx;
.icon {
width: 100%;
height: 80rpx;
}
.upload-text {
width: 100%;
height: 48rpx;
font-size: 30rpx;
color: var(--contentColor30);
line-height: 48rpx;
text-align: center;
}
}
}
.image-container {
width: 630rpx;
height: 384rpx;
.image {
height: 100%;
width: 100%;
border-radius: 40rpx;
}
}
}
.select-project {
.empty-project {
animation: animation-fade-out 0.3s ease-out 0s 1;
.input-or-select {
width: 100%;
height: 100rpx;
.input-area {
height: 100%;
width: 100%;
}
}
}
.project-list {
margin-top: 16rpx;
margin-bottom: 16rpx;
.project {
width: 100%;
min-height: 80rpx;
.name {
min-height: 80rpx;
width: 314rpx;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 48rpx;
text-align: left;
}
.other {
height: 100%;
width: 316rpx;
.price,.balance {
width: 110rpx;
height: 48rpx;
}
.price {
border-bottom: 1rpx solid var(--themeColor);
.uni-input {
width: 100%;
height: 48rpx;
font-size: 28rpx;
color: var(--themeColor);
line-height: 48rpx;
text-align: center;
min-height: 48rpx;
}
}
.balance {
font-size: 24rpx;
color: var(--contentColor50);
line-height: 48rpx;
text-align: center;
}
.num-area {
height: 100%;
width: 176rpx;
.reduce,.add {
width: 48rpx;
height: 48rpx;
}
.num {
width: 80rpx;
height: 100%;
font-weight: 500;
font-size: 28rpx;
color: var(--contentColor90);
line-height: 80rpx;
text-align: center;
}
}
}
}
}
}
.val-area {
height: 100%;
width: 350rpx;
font-size: 30rpx;
line-height: 100rpx;
text-align: left;
color: var(--titleColor);
}
.val-hint {
height: 100%;
width: 280rpx;
.hint {
height: 100%;
width: 224rpx;
font-size: 28rpx;
color: var(--contentColor50);
line-height: 100rpx;
text-align: right;
}
}
.unit {
width: 280rpx;
}
}
.time {
.item-row {
width: 100%;
height: 100rpx;
.title {
width: 200rpx;
height: 100rpx;
font-size: 30rpx;
height: 100rpx;
color: var(--contentColor90);
text-align: right;
line-height: 100rpx;
color: var(--titleColor);
font-weight: 500;
}
//区间筛选
.section-value {
width: 100%;
.value {
width: 446rpx;
height: 100rpx;
.min,.max {
width: 280rpx;
height: 100rpx;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 100rpx;
text-align: left;
}
.parting {
width: 70rpx;
height: 100rpx;
font-size: 30rpx;
color: var(--contentColor50);
line-height: 100rpx;
text-align: center;
}
.max {
text-align: right;
.uni-input {
text-align: right;
}
}
font-size: 30rpx;
color: var(--titleColor);
}
.value-empty {
color: var(--summaryColor);
}
}
.desc {
width: 100%;
height: 60rpx;
text-align: left;
min-height: 50rpx;
font-size: 28rpx;
color: var(--contentColor30);
color: var(--descriptionColor);
line-height: 48rpx;
}
}
.input-item-switch {
width: 100%;
min-height: 120rpx;
position: relative;
.content-area {
margin-bottom: 20rpx;
}
.left {
height: 100%;
.upload {
.info {
width: 100%;
height: 80rpx;
.title {
font-weight: 500;
font-size: 30rpx;
color: var(--contentColor90);
line-height: 120rpx;
text-align: left;
}
.help {
width: 56rpx;
height: 56rpx;
}
.title-area {
width: 460rpx;
height: 120rpx;
.title-val {
height: 60rpx;
line-height: 60rpx;
width: 100%;
}
.desc {
height: 48rpx;
font-size: 28rpx;
color: var(--contentColor30);
line-height: 48rpx;
text-align: left;
width: 100%;
}
}
}
.right {
width: 140rpx;
height: 100%;
position: absolute;
right: -12rpx;
}
}
.input-avatar {
.avatar {
width: 100%;
height: 100rpx;
margin-bottom: 20rpx;
.desc {
width: 500rpx;
height: 100%;
font-size: 30rpx;
color: var(--contentColor30);
line-height: 100rpx;
text-align: left;
}
.store-avatar {
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
font-size: 30rpx;
color: var(--titleColor);
font-weight: 500;
}
.desc {
margin-left: 8rpx;
height: 80rpx;
font-size: 30rpx;
color: var(--descriptionColor);
}
}
.imgs-ctr {
width: 100%;
min-height: 100rpx;
display: flex;
flex-wrap: wrap;
.img-item {
position: relative;
.del {
position: absolute;
top: 0;
left: 94rpx;
width: 48rpx;
height: 48rpx;
}
}
.img-ctr {
width: 120rpx;
height: 120rpx;
margin-top: 16rpx;
margin-bottom: 16rpx;
.img {
width: 100%;
height: 100%;
border-radius: 8rpx;
}
}
.up-ctr {
width: 120rpx;
height: 120rpx;
background: var(--contentBgColor);
border-radius: 8rpx;
margin-top: 16rpx;
margin-bottom: 16rpx;
.up {
width: 100%;
height: 36rpx;
font-size: 20rpx;
color: var(--summaryColor);
}
}
}
}
.input-select {
.value {
width: 100%;
.input {
width: 100%;
min-height: 100rpx;
position: relative;
.title {
width: 200rpx;
height: 100rpx;
.val {
width: 566rpx;
height: 100%;
font-size: 30rpx;
line-height: 100rpx;
text-align: left;
}
font-size: 30rpx;
font-weight: 500;
color: var(--titleColor);
}
.input-ctr {
width: 446rpx;
height: 100rpx;
}
.uni-input {
text-align: right;
width: 100%;
height: 100%;
font-size: 30rpx;
color: var(--titleColor);
}
.select-ctr {
font-size: 30rpx;
color: var(--descriptionColor);
width: 100%;
min-height: 100rpx;
line-height: 48rpx;
padding: 16rpx 0;
box-sizing: border-box;
}
.select {
color: var(--titleColor);
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
static/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
static/img/user-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -1,21 +0,0 @@
import { createStore } from 'vuex'
const store = createStore({
state:{
filterMembersCondition: {},
filterOrderCondition: {},
currentMember: {},
},
mutations: {
updateFilterMembersCondition(state, payload) {
state.filterMembersCondition = payload
},
updateFilterOrderCondition(state, payload) {
state.filterOrderCondition = payload
},
updateCurrentMember(state, payload) {
state.currentMember = payload
}
}
})
export default store

1
svg_icons/README.md Normal file
View File

@ -0,0 +1 @@
图标原 svg 文件,可通过这些 svg 文件,修改或新增图标,生成新的 ttf 文件。

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_3661_7331"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3661_7331)"><g><path d="M12,11L12,8L16,12L12,16L12,13L8,13L8,11L12,11ZM12,2C17.52,2,22,6.48,22,12C22,17.52,17.52,22,12,22C6.48,22,2,17.52,2,12C2,6.48,6.48,2,12,2ZM12,20C16.42,20,20,16.42,20,12C20,7.58,16.42,4,12,4C7.58,4,4,7.58,4,12C4,16.42,7.58,20,12,20Z" fill="#FFFFFF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 597 B

1
svg_icons/arrow-right.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="28" height="28" viewBox="0 0 28 28"><defs><clipPath id="master_svg0_3661_3688"><rect x="0" y="28" width="28" height="28" rx="0"/></clipPath></defs><g transform="matrix(0,-1,1,0,-28,28)" clip-path="url(#master_svg0_3661_3688)"><g><path d="M8.291405375,37.793207L14.583984375,44.08579L20.876884375,37.792893Q21.017484375000002,37.652241,21.201284375,37.57612Q21.385084374999998,37.5,21.583984375,37.5Q21.682484375,37.5,21.779084375,37.519215Q21.875684375,37.53843,21.966684375,37.576121Q22.057684375,37.613812,22.139584375,37.66853Q22.221484375,37.723249,22.291084375,37.792893Q22.360684374999998,37.862537,22.415484375,37.94443Q22.470184375000002,38.026322,22.507884375,38.117317Q22.545584375,38.208311,22.564784375000002,38.30491Q22.583984375,38.4015086,22.583984375,38.5Q22.583984375,38.698912,22.507884375,38.882683Q22.431784375,39.066455,22.291084375,39.207107L22.290684374999998,39.207534L15.291094375,46.20711Q15.150434375,46.34776,14.966664375,46.42388Q14.782894375,46.5,14.583984375,46.5Q14.385074375,46.5,14.201304375,46.42388Q14.017524375,46.34776,13.876874375,46.20711L6.876877375,39.207107Q6.736225375,39.066454,6.6601043749999995,38.882683Q6.583984375,38.698912,6.583984375,38.5Q6.583984375,38.4015086,6.603199375,38.30491Q6.622414375,38.208311,6.660105375,38.117317Q6.697796375,38.026322,6.752514375,37.94443Q6.807233375,37.862537,6.876877375,37.792893Q6.946521375,37.723249,7.028414375,37.66853Q7.110306375,37.613812,7.201301375,37.576121Q7.292295375,37.53843,7.388894375,37.519215Q7.485492975,37.5,7.583984375,37.5Q7.782896375,37.5,7.966667375,37.57612Q8.150439375,37.652241,8.291091375,37.792893L8.291405375,37.793207Z" fill-rule="evenodd" fill="#000000" fill-opacity="0.10000000149011612"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

1
svg_icons/arrow-up-line.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3870_3751"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3870_3751)"><g><path d="M10.83339951171875,6.5237340234375L10.83339951171875,16.6666740234375L9.16672951171875,16.6666740234375L9.16672951171875,6.5237340234375L4.69676951171875,10.9937040234375L3.51824951171875,9.8152040234375L10.000069511718749,3.3333740234375L16.48184951171875,9.8152040234375L15.30334951171875,10.9937040234375L10.83339951171875,6.5237340234375Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

After

Width:  |  Height:  |  Size: 743 B

1
svg_icons/call.svg Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3824_3963"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3824_3963)"><g><path d="M10.00001701171875,18.333356494140624C5.39764701171875,18.333356494140624,1.66668701171875,14.602356494140626,1.66668701171875,9.999986494140625C1.66668701171875,5.397616494140625,5.39764701171875,1.666656494140625,10.00001701171875,1.666656494140625C14.60238701171875,1.666656494140625,18.33338701171875,5.397616494140625,18.33338701171875,9.999986494140625C18.33338701171875,14.602356494140626,14.60238701171875,18.333356494140624,10.00001701171875,18.333356494140624ZM10.00001701171875,16.666656494140625C13.68198701171875,16.666656494140625,16.66668701171875,13.681956494140625,16.66668701171875,9.999986494140625C16.66668701171875,6.318086494140625,13.68198701171875,3.333326494140625,10.00001701171875,3.333326494140625C6.31811701171875,3.333326494140625,3.33335701171875,6.318086494140625,3.33335701171875,9.999986494140625C3.33335701171875,13.681956494140625,6.31811701171875,16.666656494140625,10.00001701171875,16.666656494140625Z" fill="#000000" fill-opacity="0.5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
svg_icons/checkbox-circle.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3824_3967"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3824_3967)"><g><path d="M10.00001701171875,18.333356494140624C5.39764701171875,18.333356494140624,1.66668701171875,14.602356494140626,1.66668701171875,9.999986494140625C1.66668701171875,5.397616494140625,5.39764701171875,1.666656494140625,10.00001701171875,1.666656494140625C14.60238701171875,1.666656494140625,18.33338701171875,5.397616494140625,18.33338701171875,9.999986494140625C18.33338701171875,14.602356494140626,14.60238701171875,18.333356494140624,10.00001701171875,18.333356494140624ZM10.00001701171875,16.666656494140625C13.68198701171875,16.666656494140625,16.66668701171875,13.681956494140625,16.66668701171875,9.999986494140625C16.66668701171875,6.318086494140625,13.68198701171875,3.333326494140625,10.00001701171875,3.333326494140625C6.31811701171875,3.333326494140625,3.33335701171875,6.318086494140625,3.33335701171875,9.999986494140625C3.33335701171875,13.681956494140625,6.31811701171875,16.666656494140625,10.00001701171875,16.666656494140625ZM9.16885701171875,13.333356494140626L5.63334701171875,9.797826494140624L6.81185701171875,8.619236494140626L9.16885701171875,10.976326494140626L13.88288701171875,6.262256494140625L15.06138701171875,7.440766494140625L9.16885701171875,13.333356494140626Z" fill="#2772F0" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_3954_4136"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3954_4136)"><g><path d="M12,22C6.47715,22,2,17.5228,2,12C2,6.47715,6.47715,2,12,2C17.5228,2,22,6.47715,22,12C22,17.5228,17.5228,22,12,22ZM12,10.5858L9.17157,7.75736L7.75736,9.17157L10.5858,12L7.75736,14.8284L9.17157,16.2426L12,13.4142L14.8284,16.2426L16.2426,14.8284L13.4142,12L16.2426,9.17157L14.8284,7.75736L12,10.5858Z" fill="#E6521F" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 663 B

1
svg_icons/edit-line.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3986_4676"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3986_4676)"><g><path d="M3.333333,3L9.16667,3Q9.215910000000001,3,9.26421,2.990393Q9.31251,2.980785,9.35801,2.9619400000000002Q9.403500000000001,2.943094,9.44445,2.915735Q9.4854,2.888375,9.52022,2.853553Q9.55504,2.818731,9.5824,2.777785Q9.60976,2.736839,9.628599999999999,2.691342Q9.64745,2.645845,9.657060000000001,2.5975451Q9.66667,2.5492457,9.66667,2.5Q9.66667,2.4507543,9.657060000000001,2.4024549Q9.64745,2.354155,9.628599999999999,2.308658Q9.60976,2.263161,9.5824,2.222215Q9.55504,2.181269,9.52022,2.146447Q9.4854,2.111625,9.44445,2.084265Q9.403500000000001,2.056906,9.35801,2.0380599999999998Q9.31251,2.019215,9.26421,2.009607Q9.215910000000001,2,9.16667,2L3.333333,2Q2.781048,2,2.390524,2.390524Q2,2.781048,2,3.333333L2,16.6667Q2,17.219,2.390526,17.6095Q2.781048,18,3.333333,18L16.6667,18Q17.219,18,17.6095,17.6095Q18,17.219,18,16.6667L18,10.83333Q18,10.78409,17.9904,10.73579Q17.980800000000002,10.68749,17.9619,10.64199Q17.9431,10.59649,17.9157,10.55555Q17.8884,10.5146,17.8536,10.47978Q17.8187,10.44496,17.7778,10.4176Q17.736800000000002,10.39024,17.6913,10.37139Q17.6458,10.35255,17.5975,10.342939999999999Q17.5492,10.33333,17.5,10.33333Q17.4508,10.33333,17.4025,10.342939999999999Q17.3542,10.35255,17.3087,10.37139Q17.263199999999998,10.39024,17.2222,10.4176Q17.1813,10.44496,17.1464,10.47978Q17.1116,10.5146,17.0843,10.55555Q17.0569,10.59649,17.0381,10.64199Q17.019199999999998,10.68749,17.0096,10.73579Q17,10.78409,17,10.83333L17,16.6667Q17,17,16.6667,17L3.333333,17Q3,17,3,16.6667L3,3.333333Q3,3,3.333333,3Z" fill-rule="evenodd" fill="#2772F0" fill-opacity="1"/></g><g><path d="M14.102731953125,2.146369L14.102441953125,2.146658L5.479486953125,10.77995Q5.409257953125,10.85026,5.371254953125,10.94209Q5.333251953125,11.03391,5.333251953125,11.13329L5.333251953125,14.1667Q5.333251953125,14.2159,5.342858953125,14.2642Q5.352466953125,14.3125,5.371311953125,14.358Q5.390157953125,14.4035,5.417516953125,14.4445Q5.444876953125,14.4854,5.479698953125,14.5202Q5.514520953125,14.555,5.555466953125,14.5824Q5.596412953125,14.6098,5.641909953125,14.6286Q5.687406953125,14.6475,5.735706853125,14.6571Q5.784006253125,14.6667,5.833251953125,14.6667L8.882081953125,14.6667Q8.981571953125,14.6667,9.073481953125,14.6286Q9.165381953125,14.5905,9.235711953125,14.5201L17.853551953125,5.8985199999999995Q17.888351953125,5.8637,17.915651953125,5.822760000000001Q17.943051953125,5.78182,17.961851953125,5.736330000000001Q17.980751953125,5.69085,17.990351953125,5.64256Q17.999951953125,5.59427,17.999951953125,5.54504Q17.999951953125,5.4958100000000005,17.990351953125,5.44752Q17.980751953125,5.39924,17.961851953125,5.35375Q17.943051953125,5.308260000000001,17.915651953125,5.26732Q17.888351953125,5.22639,17.853551953125,5.1915700000000005L14.809841953125,2.146524Q14.739531953125,2.076182,14.647651953125,2.038102Q14.555771953125,2.000022,14.456321953125,2Q14.356861953125,1.999978,14.264971953125,2.0380190000000002Q14.173071953125,2.076059,14.102731953125,2.146369ZM14.456341953125,3.207396L6.333251953125,11.34022L6.333251953125,13.6667L8.674911953125001,13.6667L16.792951953124998,5.54504L14.456341953125,3.207396Z" fill-rule="evenodd" fill="#2772F0" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

1
svg_icons/flashlight.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="24" height="24" viewBox="0 0 24 24"><defs><clipPath id="master_svg0_3610_04090"><rect x="0" y="0" width="24" height="24" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3610_04090)"><g><path d="M13,9L21,9L11,24L11,15L4,15L13,0L13,9ZM11,11L11,7.22063L7.53238,13L13,13L13,17.3944L17.262999999999998,11L11,11Z" fill="#FFFFFF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 480 B

1
svg_icons/info.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3661_8379"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3661_8379)"><g><path d="M10.000078046875,18.3333259765625C5.397708046875,18.3333259765625,1.666748046875,14.6023259765625,1.666748046875,9.9999559765625C1.666748046875,5.3975859765625,5.397708046875,1.6666259765625,10.000078046875,1.6666259765625C14.602448046875,1.6666259765625,18.333448046875,5.3975859765625,18.333448046875,9.9999559765625C18.333448046875,14.6023259765625,14.602448046875,18.3333259765625,10.000078046875,18.3333259765625ZM10.000078046875,16.6666259765625C13.682048046875,16.6666259765625,16.666748046875,13.6819259765625,16.666748046875,9.9999559765625C16.666748046875,6.3180559765625,13.682048046875,3.3332959765625,10.000078046875,3.3332959765625C6.318178046875,3.3332959765625,3.333418046875,6.3180559765625,3.333418046875,9.9999559765625C3.333418046875,13.6819259765625,6.318178046875,16.6666259765625,10.000078046875,16.6666259765625ZM9.166748046875,5.8332959765625L10.833418046875,5.8332959765625L10.833418046875,7.4999559765625L9.166748046875,7.4999559765625L9.166748046875,5.8332959765625ZM9.166748046875,9.1666259765625L10.833418046875,9.1666259765625L10.833418046875,14.1666259765625L9.166748046875,14.1666259765625L9.166748046875,9.1666259765625Z" fill="#E18F00" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
svg_icons/logout.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="28" height="28" viewBox="0 0 28 28"><defs><clipPath id="master_svg0_3661_3927"><rect x="0" y="0" width="28" height="28" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3661_3927)"><g><path d="M11.66603982421875,12.8333740234375L2.39031982421875,12.8333740234375C2.97565982421875,6.9378340234375,7.94979982421875,2.3333740234375,13.99941982421875,2.3333740234375C20.44271982421875,2.3333740234375,25.66611982421875,7.5567140234375,25.66611982421875,14.0000740234375C25.66611982421875,20.4432740234375,20.44271982421875,25.6666740234375,13.99941982421875,25.6666740234375C7.94979982421875,25.6666740234375,2.97565982421875,21.0621740234375,2.39031982421875,15.1666740234375L11.66603982421875,15.1666740234375L11.66603982421875,18.6666740234375L17.499419824218748,14.0000740234375L11.66603982421875,9.3333740234375L11.66603982421875,12.8333740234375Z" fill="#000000" fill-opacity="0.30000001192092896"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="22" height="22" viewBox="0 0 22 22"><defs><clipPath id="master_svg0_3992_4344"><rect x="0" y="0" width="22" height="22" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3992_4344)"><g><path d="M11.0044585546875,20.168993359375C5.9418285546875,20.168993359375,1.8377685546875,16.064993359375002,1.8377685546875,11.002313359375C1.8377685546875,5.939743359375,5.9418285546875,1.835693359375,11.0044585546875,1.835693359375C16.067068554687502,1.835693359375,20.1711685546875,5.939743359375,20.1711685546875,11.002313359375C20.1711685546875,16.064993359375002,16.067068554687502,20.168993359375,11.0044585546875,20.168993359375ZM11.0044585546875,18.335693359375C15.0545685546875,18.335693359375,18.3377685546875,15.052393359375,18.3377685546875,11.002313359375C18.3377685546875,6.952273359375,15.0545685546875,3.669023359375,11.0044585546875,3.669023359375C6.9543485546875,3.669023359375,3.6710985546875,6.952273359375,3.6710985546875,11.002313359375C3.6710985546875,15.052393359375,6.9543485546875,18.335693359375,11.0044585546875,18.335693359375ZM11.9211685546875,11.918993359375L14.6711685546875,11.918993359375L14.6711685546875,13.752293359375L11.9211685546875,13.752293359375L11.9211685546875,15.585693359375L10.0877885546875,15.585693359375L10.0877885546875,13.752293359375L7.3377685546875,13.752293359375L7.3377685546875,11.918993359375L10.0877885546875,11.918993359375L10.0877885546875,11.002313359375L7.3377685546875,11.002313359375L7.3377685546875,9.168983359375L9.708108554687499,9.168983359375L7.7635285546875,7.224483359375L9.0598885546875,5.928113359375L11.0044585546875,7.872653359375L12.9489685546875,5.928113359375L14.2453685546875,7.224483359375L12.3007685546875,9.168983359375L14.6711685546875,9.168983359375L14.6711685546875,11.002313359375L11.9211685546875,11.002313359375L11.9211685546875,11.918993359375Z" fill="#000000" fill-opacity="0.5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

1
svg_icons/navigation.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="30" height="30" viewBox="0 0 30 30"><defs><clipPath id="master_svg0_3610_03349"><rect x="30" y="0" width="30" height="30" rx="0"/></clipPath></defs><g transform="matrix(0,1,-1,0,30,-30)" clip-path="url(#master_svg0_3610_03349)"><g><path d="M33.624308671875,2.87478630234375L57.131513671875,10.71052240234375C57.459013671875,10.81967240234375,57.636013671875,11.17363240234375,57.526913671875,11.50110240234375C57.468713671875,11.67550240234375,57.336713671875,11.81547240234375,57.166013671875,11.88375240234375L46.250213671875,16.250112402343753L40.718763671875,27.31301240234375C40.564383671875,27.62171240234375,40.188973671875,27.74691240234375,39.880233671875,27.59251240234375C39.723533671875,27.51411240234375,39.606913671875,27.37361240234375,39.558783671875,27.20511240234375L32.825721471875,3.6394114023437503C32.730896471875,3.30751140234375,32.923071671875,2.96158640234375,33.254971671875,2.86676140234375C33.376083671875,2.83216120234375,33.504821671875,2.83494890234375,33.624308671875,2.87478630234375Z" fill="#000000" fill-opacity="0.30000001192092896"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
svg_icons/progress-2-line.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="22" height="22" viewBox="0 0 22 22"><defs><clipPath id="master_svg0_3870_3877"><rect x="0" y="0" width="22" height="22" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3870_3877)"><g><path d="M1.8333740234375,10.999921953125C1.8333740234375,16.062451953125,5.9374240234375,20.166551953125,11.0000440234375,20.166551953125C16.0625740234375,20.166551953125,20.1666740234375,16.062451953125,20.1666740234375,10.999921953125C20.1666740234375,5.937301953125,16.0625740234375,1.833251953125,11.0000440234375,1.833251953125C5.9374240234375,1.833251953125,1.8333740234375,5.937301953125,1.8333740234375,10.999921953125ZM18.3333740234375,10.999921953125C18.3333740234375,15.050051953125,15.0501740234375,18.333251953125,11.0000440234375,18.333251953125C6.9499540234375,18.333251953125,3.6667040234375,15.050051953125,3.6667040234375,10.999921953125C3.6667040234375,6.949831953125,6.9499540234375,3.666581953125,11.0000440234375,3.666581953125C15.0501740234375,3.666581953125,18.3333740234375,6.949831953125,18.3333740234375,10.999921953125ZM11.0000440234375,10.999921953125L11.0000440234375,5.499921953125C14.0375740234375,5.499921953125,16.5000740234375,7.962351953125,16.5000740234375,10.999921953125L11.0000440234375,10.999921953125Z" fill="#E18F00" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

1
svg_icons/reset-left-fill.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="30" height="30" viewBox="0 0 30 30"><defs><clipPath id="master_svg0_3864_3850"><rect x="0" y="0" width="30" height="30" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3864_3850)"><g><path d="M27.5,15C27.5,21.9035,21.9036,27.5,15,27.5C8.096499999999999,27.5,2.5,21.9035,2.5,15C2.5,8.096440000000001,8.096499999999999,2.5,15,2.5L15,5C9.47712,5,5,9.47715,5,15C5,20.5229,9.47712,25,15,25C20.5229,25,25,20.5229,25,15C25,11.92018,23.6078,9.16554,21.4182,7.33115L18.75,10L18.75,2.5L26.25,2.5L23.1919,5.558199999999999C25.8311,7.85003,27.5,11.23013,27.5,15Z" fill="#FFFFFF" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 724 B

1
svg_icons/reset-left-line.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="30" height="30" viewBox="0 0 30 30"><defs><clipPath id="master_svg0_3864_4099"><rect x="0" y="0" width="30" height="30" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3864_4099)"><g><path d="M27.5,15C27.5,21.9035,21.9036,27.5,15,27.5C8.096499999999999,27.5,2.5,21.9035,2.5,15C2.5,8.096440000000001,8.096499999999999,2.5,15,2.5L15,5C9.47712,5,5,9.47715,5,15C5,20.5229,9.47712,25,15,25C20.5229,25,25,20.5229,25,15C25,11.56278,23.2659,8.53059,20.6248,6.73064L20.625,10L18.125,10L18.125,2.5L25.625,2.5L25.625,5L22.501,4.99986C25.5366,7.28043,27.5,10.91091,27.5,15Z" fill="#FFFFFF" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

After

Width:  |  Height:  |  Size: 770 B

1
svg_icons/time.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="20" height="20" viewBox="0 0 20 20"><defs><clipPath id="master_svg0_3610_03345"><rect x="0" y="0" width="20" height="20" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3610_03345)"><g><path d="M9.999994123535156,18.3333259765625C5.397624123535156,18.3333259765625,1.6666641235351562,14.6023259765625,1.6666641235351562,9.9999559765625C1.6666641235351562,5.3975859765625,5.397624123535156,1.6666259765625,9.999994123535156,1.6666259765625C14.602364123535157,1.6666259765625,18.333364123535155,5.3975859765625,18.333364123535155,9.9999559765625C18.333364123535155,14.6023259765625,14.602364123535157,18.3333259765625,9.999994123535156,18.3333259765625ZM9.999994123535156,16.6666259765625C13.681964123535156,16.6666259765625,16.666664123535156,13.6819259765625,16.666664123535156,9.9999559765625C16.666664123535156,6.3180559765625,13.681964123535156,3.3332959765625,9.999994123535156,3.3332959765625C6.318094123535157,3.3332959765625,3.333334123535156,6.3180559765625,3.333334123535156,9.9999559765625C3.333334123535156,13.6819259765625,6.318094123535157,16.6666259765625,9.999994123535156,16.6666259765625ZM10.833334123535156,9.9999559765625L14.166664123535156,9.9999559765625L14.166664123535156,11.6666259765625L9.166664123535156,11.6666259765625L9.166664123535156,5.8332959765625L10.833334123535156,5.8332959765625L10.833334123535156,9.9999559765625Z" fill="#2772F0" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="18" height="18" viewBox="0 0 18 18"><defs><clipPath id="master_svg0_3661_8444"><rect x="0" y="0" width="18" height="18" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3661_8444)"><g><path d="M5.25,15.7358C2.73284,15.5443,0.75,13.4412,0.75,10.875C0.75,9.1287,1.6682169999999998,7.59682,3.04819,6.7359C3.42352,3.783,5.94514,1.5,9,1.5C12.0548,1.5,14.5765,3.783,14.9518,6.7359C16.3318,7.59682,17.25,9.1287,17.25,10.875C17.25,13.4412,15.2671,15.5443,12.75,15.7358L12.75,15.75L5.25,15.75L5.25,15.7358ZM9.75,9.75L12,9.75L9,6L6,9.75L8.25,9.75L8.25,12.75L9.75,12.75L9.75,9.75Z" fill="#000000" fill-opacity="0.5"/></g></g></svg>

After

Width:  |  Height:  |  Size: 744 B

1
svg_icons/user.svg Executable file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="18" height="18" viewBox="0 0 18 18"><defs><clipPath id="master_svg0_3661_4798"><rect x="0" y="0" width="18" height="18" rx="0"/></clipPath></defs><g clip-path="url(#master_svg0_3661_4798)"><g><path d="M3,16.5C3,13.1863,5.68629,10.5,9,10.5C12.31371,10.5,15,13.1863,15,16.5L3,16.5ZM9,9.75C6.51375,9.75,4.5,7.73625,4.5,5.25C4.5,2.76375,6.51375,0.75,9,0.75C11.48625,0.75,13.5,2.76375,13.5,5.25C13.5,7.73625,11.48625,9.75,9,9.75Z" fill="#000000" fill-opacity="0.30000001192092896"/></g></g></svg>

After

Width:  |  Height:  |  Size: 607 B

View File

@ -3,16 +3,19 @@
--summaryColor: rgba(0, 0, 0, 0.5); // 摘要
--descriptionColor: rgba(0, 0, 0, 0.3); // 描述
--contentBgColor: rgba(0, 0, 0, 0.1); // 内容区块
--auxiliaryBgColor: rgba(0, 0, 0, 0.05); // 辅助背景色
--dottedBorderColor: rgba(0, 0, 0, 0.15); // 虚线
--dividerColor: rgba(0, 0, 0, 0.1); // 分割线
--pageBgColor: #F5F5F5; // 页面背景
--containerBgColor: #FFFFFF; // 内容块背景
--importantColor: #E6521F; // 重要色
--themeColor: #2772F0; // 主题色
--themeColor30: rgba(39, 114, 240, 0.3);//主题色30%
--themeColor10: rgba(39, 114, 240, 0.1);//主题色10%
--navbarBgColor: #FFFFFF; // 导航背景
--defaultUserAvatar: url("/static/img/default-user.png") no-repeat center / 100%;
--emptyData: url("https://jl-td.oss-cn-chengdu.aliyuncs.com/uploads/20241018/fda50c010550e9a93311de89e1e0b0e1.png") no-repeat center / 100%;
--emptyData: url("https://allocatr.oss-cn-hangzhou.aliyuncs.com/uploads/20250421/831dbec0752dd56996789ba5ed4c5e10.png") no-repeat center / 100%;
}
@mixin dark-theme() {
@ -20,16 +23,19 @@
--summaryColor: rgba(255, 255, 255, 0.5);
--descriptionColor: rgba(255, 255, 255, 0.3);
--contentBgColor: rgba(255, 255, 255, 0.1);
--auxiliaryBgColor: rgba(255, 255, 255, 0.05);
--dottedBorderColor: rgba(255, 255, 255, 0.15);
--dividerColor: rgba(255, 255, 255, 0.1);
--pageBgColor: #111111;
--containerBgColor: #1E1E1E;
--importantColor: #E6521F;
--themeColor: #2772F0;
--themeColor30: rgba(39, 114, 240, 0.3);//主题色30%
--themeColor10: rgba(39, 114, 240, 0.1);//主题色10%
--navbarBgColor: #1D1D1D;
--defaultUserAvatar: url("/static/img/default-user-dark.png") no-repeat center / 100%;
--emptyData: url("https://jl-td.oss-cn-chengdu.aliyuncs.com/uploads/20241018/6dbc6a080b19e70d3500e418db24eeb7.png") no-repeat center / 100%;
--emptyData: url("https://allocatr.oss-cn-hangzhou.aliyuncs.com/uploads/20250421/c1f8e22464c78e396aff3688d5970878.png") no-repeat center / 100%;
}
/*亮色模式-自动样式*/

View File

@ -76,7 +76,7 @@
font-size: 14px;
// font-family: Lato-Bold, Lato;
font-weight: bold;
color: var(--contentColor90);
color: var(--titleColor);
}
.uni-calendar-item__weeks-box-item {
@ -102,7 +102,7 @@
width: 8px;
height: 8px;
border-radius: 8px;
background-color: var(--remindColor);
background-color: var(--importantColor);
}
@ -111,21 +111,21 @@
}
.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
color: var(--contentColor30);
color: var(--contentBgColor);
}
.uni-calendar-item--today {
position: absolute;
top: 10px;
right: 17%;
background-color: var(--remindColor);
background-color: var(--importantColor);
width:6px;
height: 6px;
border-radius: 50%;
}
.uni-calendar-item--extra {
color: var(--remindColor);
color: var(--importantColor);
opacity: 0.8;
}
@ -160,7 +160,7 @@
.uni-calendar-item--before-checked .uni-calendar-item--checked-text,
.uni-calendar-item--after-checked .uni-calendar-item--checked-text {
color: var(--contentColor90)
color: var(--titleColor)
}
.uni-calendar-item--before-checked-x {

View File

@ -686,7 +686,7 @@
}
.uni-calendar__content {
background-color: var(--blockBgColor);
background-color: var(--containerBgColor);
}
.uni-calendar__content-mobile {
@ -748,7 +748,7 @@
text-align: center;
width: 100px;
font-size: 15px;
color: var(--contentColor50);
color: var(--summaryColor);
}
.uni-calendar__button-text {
@ -775,10 +775,10 @@
.uni-calendar__header-btn {
width: 9px;
height: 9px;
border-left-color: var(--contentColor50);
border-left-color: var(--summaryColor);
border-left-style: solid;
border-left-width: 1px;
border-top-color: var(--contentColor50);
border-top-color: var(--summaryColor);
border-top-style: solid;
border-top-width: 1px;
}
@ -820,7 +820,7 @@
.uni-calendar__weeks-day-text {
font-size: 12px;
color: var(--contentColor50);
color: var(--summaryColor);
}
.uni-calendar__box {
@ -884,7 +884,7 @@
}
.uni-date-changed--time-date {
color: var(--contentColor50);
color: var(--summaryColor);
line-height: 50px;
/* #ifdef MP-TOUTIAO */
font-size: 16px;

View File

@ -14,12 +14,12 @@
<view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
<view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']"
:style="fixNvueBug">
<view class="uni-title" style="color: var(--contentColor50);">
<view class="uni-title" style="color: var(--summaryColor);">
<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
</view>
<view v-if="dateShow" class="uni-datetime-picker__container-box" style="color: var(--contentColor90)">
<view v-if="dateShow" class="uni-datetime-picker__container-box" style="color: var(--summaryColor)">
<picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
@change="bindDateChange" mask-style="background-color: var(--contentColor10)">
@change="bindDateChange" mask-style="background-color: var(--contentBgColor)">
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
@ -40,7 +40,7 @@
<text class="uni-datetime-picker-sign sign-left">-</text>
<text class="uni-datetime-picker-sign sign-right">-</text>
</view>
<view v-if="timeShow" class="uni-datetime-picker__container-box" style="color: var(--contentColor90);">
<view v-if="timeShow" class="uni-datetime-picker__container-box" style="color: var(--titleColor);">
<picker-view class="uni-datetime-picker-view" mask-style="background-color: rgba(255, 255, 255, 0.1)" :class="[hideSecond ? 'time-hide-second' : '']"
:indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
<picker-view-column>
@ -851,7 +851,7 @@
/* #ifdef APP-NVUE */
width: 330px;
/* #endif */
background-color: var(--blockBgColor);
background-color: var(--containerBgColor);
position: fixed;
top: 50%;
left: 50%;
@ -867,7 +867,7 @@
}
.uni-datetime-picker-time {
color: var(--contentColor50);
color: var(--summaryColor);
}
.uni-datetime-picker-column {
@ -889,7 +889,7 @@
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
color: var(--contentColor90);
color: var(--titleColor);
}

29
utils/enums.js Normal file
View File

@ -0,0 +1,29 @@
const enums = {
//派单状态
ORDER_DISPATCH_STATUS: {
STATUS_TOGET: 0, //待接
STATUS_GOTIT: 10, //已接
STATUS_PLANIT: 20, //已预约
STATUS_OVERTIME: 25, //超时(过了预约时间)
STATUS_CLOCK: 30, //已打卡
STATUS_FINISH: 60, //完成
STATUS_REFUSED: -10, //拒绝
STATUS_MOVE: -20, //中转
STATUS_CANCEL: -30, //取消
},
WORKBENCH_STATUS_TEXT: {
0: '待接单',
10: '待联系客户',
20: '待上门',
30: '服务中',
60: '已完成',
'-10': '已拒接'
},
};
// 冻结对象,防止被修改
Object.freeze(enums);
// 导出枚举对象
export default enums;

View File

@ -15,6 +15,24 @@ class helpers {
let paths = {
//登录页
'login': '/pages/user/login',
//订单详情
'order-info': '/pages/order/order-info',
//首页
'index': '/pages/index/index',
//选择上门时间
'select-time': '/pages/order/select-time',
//完成上门
'arrived-on-site': '/pages/order/arrived-on-site',
//完成服务
'complete-service': '/pages/order/complete-service',
//上报异常
'report-order-exception': '/pages/order/report-order-exception',
//更新师傅备注
'worker-remark': '/pages/order/worker-remark',
//用户协议
'user-agreement': '/pages/user/user-agreement',
//隐私政策
'privacy-policy': '/pages/user/privacy-policy',
}
url = paths[pathName]
@ -32,13 +50,13 @@ class helpers {
}
static showToast(msg) {
let duration = 1500
let duration = 2000
if (msg.length > 7) {
duration = 2000
duration = 3000
}
if (msg.length > 14) {
duration = 4000
duration = 5000
}
uni.showToast({
@ -62,5 +80,119 @@ class helpers {
}
return data;
}
static formatDate(dateString) {
// 兼容 iOS替换 "-" 为 "/"
const compatibleDateString = dateString.replace(/-/g, '/');
const date = new Date(compatibleDateString);
const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const weekDay = weekdays[date.getDay()];
const year = date.getFullYear().toString().slice(2); // 获取两位数年份
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${weekDay} ${year}${month}${day}${hours}:${minutes}`;
}
static rad(d) {
return d * Math.PI / 180.0;
}
static getDistances(lat1, lng1, lat2, lng2) {
var radLat1 = this.rad(lat1);
var radLat2 = this.rad(lat2);
var a = radLat1 - radLat2;
var b = this.rad(lng1) - this.rad(lng2);
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * 6378.137; // EARTH_RADIUS;
// 输出为公里
s = Math.round(s * 10000) / 10000;
var distance = s;
var unit;
if (parseInt(distance) >= 1) {
distance = distance.toFixed(2);
unit = "公里";
} else {
distance = (distance * 1000).toFixed(2);
if (distance >= 1000) {
distance = 999
}
unit = "米";
}
return {
distance: distance,
unit: unit
}
}
static removeCommas(str) {
return str.replace(/,/g, '');
}
static removeSeconds(datetimeStr) {
if (datetimeStr === null) {
return ''
}
return datetimeStr.slice(0, 16);
}
/**
* 打开客户地址
* @param lat
* @param lng
*/
static openLocation (lat, lng) {
uni.openLocation({
latitude: Number(lat),
longitude: Number(lng),
fail: function () {
helpers.showToast('客户经纬度不正确,请联系平台')
}
});
}
/**
* 拨打电话
* @param tel
*/
static makePhoneCall (tel){
uni.makePhoneCall({
phoneNumber: tel,
fail: function () {
}
});
}
static delayHideLoading (timeout = 200) {
setTimeout(() => {
uni.hideLoading()
}, timeout)
}
static previewImage = (url) => {
uni.previewImage({
urls: [url],
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
},
fail: function(err) {
console.log(err.errMsg);
}
}
});
}
}
export default helpers

16
utils/throttle.js Normal file
View File

@ -0,0 +1,16 @@
//节流函数
export function throttle(fn, gapTime = 1500) {
let lastTime = 0;
return function () {
const nowTime = Date.now();
if (nowTime - lastTime >= gapTime) {
lastTime = nowTime;
fn.apply(this, arguments);
}
};
}
module.exports = {
throttle
};