gukai 2 years ago
parent e368285be3
commit 2165fd5258

@ -0,0 +1,46 @@
import {
request
} from "@/utils/request";
export default {
content(data) {
return request({
url: "/admin/faceRecon/content",
method: "GET",
data,
type: 'store'
})
},
faceList(data) {
return request({
url: "/admin/OrderInpersonPayment/faceListH5",
method: "GET",
data,
type: 'store'
})
},
tuikuan(data) {
return request({
url: "/admin/faceRecon/tuikuan",
method: "POST",
data,
type: 'store'
})
},
shopList(data) {
return request({
url: "/admin/faceRecon/shopList",
method: "POST",
data,
type: 'store'
})
},
faceOrder(data) {
return request({
url: "/admin/faceRecon/faceOrder",
method: "POST",
data,
type: 'store'
})
},
};

@ -1,6 +1,6 @@
{ {
"name" : "数字化平台", "name" : "数字化平台",
"appid" : "__UNI__D7DC1FF", "appid" : "__UNI__AF1F870",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.0",
"versionCode" : "100", "versionCode" : "100",

1345
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -7,6 +7,7 @@
"weapp-tailwindcss-webpack-plugin": "^1.6.10" "weapp-tailwindcss-webpack-plugin": "^1.6.10"
}, },
"dependencies": { "dependencies": {
"html5-qrcode": "^2.3.8",
"js-md5": "^0.8.3" "js-md5": "^0.8.3"
} }
} }

@ -296,6 +296,20 @@
"navigationBarTitleText": "订单管理", "navigationBarTitleText": "订单管理",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
},
{
"path": "recon/index",
"style": {
"navigationBarTitleText": "对账管理",
"enablePullDownRefresh": false
}
},
{
"path": "recon/list",
"style": {
"navigationBarTitleText": "订单",
"enablePullDownRefresh": false
}
} }
] ]
}, },

@ -30,6 +30,12 @@
</view> </view>
<view v-if="recommend.length" class="grid grid-cols-3 gap-3"> <view v-if="recommend.length" class="grid grid-cols-3 gap-3">
<view @click="utils.toUrl('/store/recon/index')"
class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between"
style="font-size: 0.75rem;">
收款对账
<wd-icon name="lenovo opacity-80" class="opacity-80" size="12px"></wd-icon>
</view>
<view v-for="item of recommend" @click="utils.toUrl(item.url)" <view v-for="item of recommend" @click="utils.toUrl(item.url)"
class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between" class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between"
style="font-size: 0.75rem;"> style="font-size: 0.75rem;">
@ -39,7 +45,14 @@
</view> </view>
<view v-else class="grid grid-cols-3 gap-3"> <view v-else class="grid grid-cols-3 gap-3">
<view @click="utils.toUrl('/store/recon/index')"
class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between"
style="font-size: 0.75rem;">
收款对账
<wd-icon name="lenovo opacity-80" class="opacity-80" size="12px"></wd-icon>
</view>
<view @click="utils.toUrl('/store/user/list')" <view @click="utils.toUrl('/store/user/list')"
class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between" class="items-center border-2 border-solid border-gray-100 rounded bg-slate-50 p-2 flex justify-between"
style="font-size: 0.75rem;"> style="font-size: 0.75rem;">
@ -60,6 +73,8 @@
订单管理 订单管理
<wd-icon name="lenovo opacity-80" class="opacity-80" size="12px"></wd-icon> <wd-icon name="lenovo opacity-80" class="opacity-80" size="12px"></wd-icon>
</view> </view>
</view> </view>

@ -0,0 +1,525 @@
<template>
<view class="content">
<view
style="padding: 120rpx 0 80rpx;background: #19be6b;display: flex;justify-content: space-around;align-items: center;color: #FFF;">
<view @click="saoma">
<view style="text-align: center;">
<wd-icon name="scan1" size="28px"></wd-icon>
</view>
<view style="text-align: center;margin-top: 10rpx;">
收款
</view>
</view>
<view @click="utils.toUrl('/store/recon/list')">
<view style="text-align: center;">
<wd-icon name="view-module" size="28px"></wd-icon>
</view>
<view style="text-align: center;margin-top: 10rpx;">
账单
</view>
</view>
<!-- <view>
<view style="text-align: center;">
<wd-icon name="enter" size="28px"></wd-icon>
</view>
<view style="text-align: center;margin-top: 10rpx;">
退款
</view>
</view> -->
</view>
<!-- <view class="action-box">
<view>
<wd-icon color="#19be6b" name="edit-outline" size="14px"></wd-icon>
<view>
订单退款
</view>
</view>
<view>
<wd-icon color="#ff9900" name="scan" size="14px"></wd-icon>
<view>
订单核销
</view>
</view>
</view> -->
<view
style="padding: 20rpx;display: flex;align-items: center;justify-content: space-between;margin-top: 40rpx;">
<view style="color: #999;">
统计信息
</view>
<view class="pay-type-box">
<view @click="updatePay(0)" :class="pay_type == 0 ? 'time-active' : ''">
总计
</view>
<view @click="updatePay(1)" :class="pay_type == 1 ? 'time-active' : ''">
微信
</view>
<view @click="updatePay(2)" :class="pay_type == 2 ? 'time-active' : ''">
支付宝
</view>
</view>
<view style="color: #f29100;display: flex;align-items: center;" @click="show_shop = true">
{{ shop_info ? shop_info.name : '门店筛选' }}
<wd-icon name="swap" color="#f29100" size="18px"></wd-icon>
</view>
</view>
<!-- 时间 -->
<view class="content-time">
<view @click="updateTime(0)" :class="time_type == 0 ? 'time-active' : ''">
昨天
</view>
<view @click="updateTime(1)" :class="time_type == 1 ? 'time-active' : ''">
今天
</view>
<view :class="time_type == 2 ? 'time-active' : ''">
<wd-calendar type="daterange" v-model="date_list" allow-same-day :formatter="formatter"
@cancel="handleCancel" @confirm="handleConfirm" use-default-slot>
<text @click="updateTime(2)"></text>
</wd-calendar>
</view>
</view>
<view class="content-time-info">
{{ start_time }} - {{ end_time }}
</view>
<template v-if="content_info">
<view class="info-item" style="background: #19be6b;color: #FFF;">
<view>
<view style="font-size: 24rpx;">
订单总金额
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_total_price }}
</view>
</view>
<view style="width: 3rpx;background: #F0F0F0;height: 100rpx;"></view>
<view>
<view>
实收总金额
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_pay_price }}
</view>
</view>
</view>
<view class="info-item">
<view>
<view style="font-size: 24rpx;">
优惠总金额
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_prefer_price }}
</view>
</view>
<view style="width: 3rpx;background: #F0F0F0;height: 100rpx;"></view>
<view>
<view>
交易总笔数
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_count }}
</view>
</view>
</view>
<view class="info-item">
<view>
<view style="font-size: 24rpx;">
退款总金额
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_refund_price }}
</view>
</view>
<view style="width: 3rpx;background: #F0F0F0;height: 100rpx;"></view>
<view>
<view>
退款总笔数
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_refund_num }}
</view>
</view>
</view>
<view class="info-item">
<view>
<view style="font-size: 24rpx;">
余额收款
</view>
<view style="font-weight: bold;margin-top: 10rpx;">
{{ content_info.order_balance_price }}
</view>
</view>
<view style="width: 3rpx;background: #F0F0F0;height: 100rpx;"></view>
<view>
</view>
</view>
</template>
<view class="qrcode" v-if="show_qrcode">
<div id="reader"></div>
</view>
<wd-popup v-model="show_shop" custom-style="padding: 30px 40px;width: 80%;border-radius: 20rpx;" @close="handleClose">
<view class="shop_item_box" style="max-height: 1000rpx;overflow: scroll;">
<view @click="selectShop(null)"></view>
<view v-for="item in shop_list" @click="selectShop(item)">
{{ item.name }}
</view>
</view>
</wd-popup>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue';
import utils from '@/utils/utils.js';
import recon from '@/api/store/recon.js';
import {
Html5Qrcode
} from "html5-qrcode"
const time_type = ref(1);
const pay_type = ref(0);
const start_time = ref(null);
const end_time = ref(null);
const content_info = ref(null);
const shop_list = ref([]);
const shop_info = ref(null);
const html5QrCode = ref(null);
const show_qrcode = ref(0);
const show_shop = ref(0);
const date_list = ref([])
import {
onShow,
} from "@dcloudio/uni-app";
const updateTime = (type) => {
console.log(type, 'type')
time_type.value = type
if (type == 0) {
const now = new Date();
now.setTime(now.getTime() - 24 * 3600 * 1000)
const year = now.getFullYear()
const month = ('0' + (now.getMonth() + 1)).slice(-2)
const day = ('0' + now.getDate()).slice(-2)
start_time.value = year + '-' + month + '-' + day
end_time.value = year + '-' + month + '-' + day
getContent()
} else if (type == 1) {
const now = new Date();
const year = now.getFullYear()
const month = ('0' + (now.getMonth() + 1)).slice(-2)
const day = ('0' + now.getDate()).slice(-2)
start_time.value = year + '-' + month + '-' + day
end_time.value = year + '-' + month + '-' + day
getContent()
} else {
}
}
const updatePay = (type) => {
pay_type.value = type
getContent()
}
function handleConfirm({
value
}) {
const now = new Date();
now.setTime(value[0])
const year = now.getFullYear()
const month = ('0' + (now.getMonth() + 1)).slice(-2)
const day = ('0' + now.getDate()).slice(-2)
start_time.value = year + '-' + month + '-' + day
const now1 = new Date();
now1.setTime(value[1])
const year1 = now1.getFullYear()
const month1 = ('0' + (now1.getMonth() + 1)).slice(-2)
const day1 = ('0' + now1.getDate()).slice(-2)
end_time.value = year1 + '-' + month1 + '-' + day1
getContent()
}
function handleCancel(row) {
console.log('handleCancel', row)
updateTime(1)
}
const formatter = (day) => {
const date = new Date(day.date)
const now = new Date()
const year = date.getFullYear()
const month = date.getMonth()
const da = date.getDate()
const nowYear = now.getFullYear()
const nowMonth = now.getMonth()
const nowDa = now.getDate()
if (year === nowYear && month === nowMonth && da === nowDa) {
day.topInfo = '今天'
}
if (day.type === 'start') {
day.bottomInfo = '开始'
}
if (day.type === 'end') {
day.bottomInfo = '结束'
}
if (day.type === 'same') {
day.bottomInfo = '开始/结束'
}
return day
}
const getContent = (row) => {
recon.content({
start_time: start_time.value,
end_time: end_time.value,
pay_type: pay_type.value,
shop_id: shop_info.value ? shop_info.value.id : 0
}).then(res => {
if (res.code == 0) {
content_info.value = res.data
} else {
showNotify({
type: 'error',
message: '出错了'
})
}
})
}
const getShopList = (row) => {
recon.shopList({
}).then(res => {
if (res.code == 0) {
shop_list.value = res.data
} else {
}
})
}
const selectShop = (row) => {
shop_info.value = row
show_shop.value = 0
getContent()
}
const saoma = (row) => {
Html5Qrcode.getCameras()
.then((devices) => {
if (devices && devices.length) {
html5QrCode.value = new Html5Qrcode("reader");
start();
}
})
.catch((err) => {
// handle err
html5QrCode.value = new Html5Qrcode("reader");
uni.showToast({
icon: 'none',
title: '您需要授予相机访问权限'
})
});
}
const start = () => {
show_qrcode.value = 1
html5QrCode.value
.start({
facingMode: "environment"
}, {
fps: 2,
qrbox: {
width: 250,
height: 250
},
},
(decodedText, decodedResult) => {
recon.faceOrder({
qr_code: decodedText
}).then(res => {
if (res.code == 0) {
show_qrcode.value = 0
uni.showToast({
icon: 'none',
title: res.msg
})
} else {
uni.showToast({
icon: 'none',
title: res.msg
})
}
})
}
)
.catch((err) => {
show_qrcode.value = 0
uni.showToast({
icon: 'none',
title: '扫码出错'
})
});
}
const stop = (row) => {
html5QrCode.value.stop().then((ignore) => {
// QR Code scanning is stopped.
console.log("QR Code scanning stopped.");
})
.catch((err) => {
// Stop failed, handle it.
console.log("Unable to stop scanning.");
});
}
let search_date = computed({
get() {
}
})
//
onShow(() => {
if (time_type.value == 1) {
const now = new Date();
const year = now.getFullYear()
const month = ('0' + (now.getMonth() + 1)).slice(-2)
const day = ('0' + now.getDate()).slice(-2)
start_time.value = year + '-' + month + '-' + day
end_time.value = year + '-' + month + '-' + day
}
getContent()
getShopList()
})
</script>
<style lang="scss" scoped>
.action-box {
margin-top: 30rpx;
display: flex;
justify-content: space-around;
font-size: 24rpx;
}
.action-box>view {
padding: 40rpx;
background: #FFF;
width: 40%;
box-shadow: 0 0 10rpx #aaa;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.action-box>view>view {
margin-left: 10rpx;
}
.content-time {
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1rpx solid #F0F0F0;
padding: 20rpx;
background: #FFF;
// margin-top: 30rpx;
}
.content-time>view {
margin: 10rpx;
}
.content-time>.time-active {
color: #18b566;
}
.content-time-info {
text-align: center;
font-size: 24rpx;
background: #FFF;
padding: 20rpx;
color: #71d5a1;
}
.info-item {
display: flex;
align-items: center;
justify-content: space-between;
background: #FFF;
color: #333;
padding: 20rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
.info-item>view {
text-align: center;
width: 50%;
font-size: 26rpx;
}
.pay-type-box {
display: flex;
justify-content: center;
font-size: 28rpx;
}
.pay-type-box>view {
padding: 4rpx 10rpx;
margin: 0 10rpx;
}
.pay-type-box>.time-active {
color: #fff;
background: #18b566;
border-radius: 10rpx;
}
.qrcode {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba($color: #000000, $alpha: 0.48);
z-index: 5;
}
#reader {
top: 50%;
left: 0;
transform: translateY(-50%);
}
.shop_item_box>view {
padding: 20rpx 0;
border-bottom: 1rpx solid #F0F0F0;
}
</style>

@ -0,0 +1,252 @@
<template>
<view class="content">
<kevyloading v-if="loading" type="bsm-loader" color="#618af8" transparent></kevyloading>
<view class=" bg-white sticky top-0 z-50 flex items-center">
<view class="flex-1">
<wd-search @search="search({ value: params.keywords })" @clear="search({ value: params.keywords = '' })"
v-model="params.keywords" hide-cancel></wd-search>
</view>
</view>
<div class="grid p-2">
<yList height="91vh" ref="yListRef" :apiObj="recon.faceList" :params="{ ...params }">
<template #default="{ list: order_list }">
<div v-for="order of order_list" class="rounded-md overflow-hidden">
<wd-card class="rounded-md overflow-hidden" type="rectangle">
<template #title>
<view class="title">
<view>ID{{ order.id }}</view>
<view @click="utils.copy(order.order_no)" class="title-tip">
{{ order.order_no }}
<wd-icon name="file-copy" size="14px"></wd-icon>
</view>
</view>
</template>
<view style="height: 40px;" class="userBox">
<template v-if="order.detail && order.detail.length > 0">
<view v-for="item of order.detail" style="width: 100%;">
<view style="color: rgba(0,0,0,0.85); font-size: 16px;display: flex;align-items: center;justify-content: space-around;">
<view style="width: 50%;">
{{ item.goods_name }}
</view>
<view style="width: 25%;">
x {{ item.num }}
</view>
<view style="width: 25%;">
<wd-tag class="mx-1" size="small" type="success">
{{ item.price }}
</wd-tag>
</view>
</view>
</view>
</template>
<template v-else>
<view style="color: rgba(0,0,0,0.85);">
支付金额<wd-tag class="mx-1" size="small" type="success">
{{ order.total_price }}
</wd-tag>
</view>
</template>
</view>
<template #footer>
<view class="flex justify-between items-center">
<view style="color: #999;">
{{ order.create_time }}
</view>
<view>
<wd-button @click="tuikuan(order.order_no)" size="small"
style="margin-right: 0px;">退款</wd-button>
</view>
</view>
</template>
</wd-card>
</div>
</template>
</yList>
</div>
<wd-toast />
<wd-message-box></wd-message-box>
</view>
</template>
<script setup>
import {
ref
} from 'vue';
import utils from '@/utils/utils.js';
import recon from '@/api/store/recon.js';
import myTabbar from "../components/myTabbar/index.vue";
import kevyloading from "@/components/kevy-loading/kevy-loading";
import {
useMessage
} from '@/uni_modules/wot-design-uni';
import {
useToast
} from '@/uni_modules/wot-design-uni'
import yList from "/components/yList/index.vue";
import {
onShow,
} from "@dcloudio/uni-app";
const toast = useToast()
const message1 = useMessage();
const originType = ref({
100: 'success',
101: 'success',
200: 'info',
201: 'danger',
300: 'warning',
})
const yListRef = ref(null);
const searchType = ref('订单号');
const popover = ref(false);
const search = ({
value
}) => {
if (searchType.value == '昵称') {
yListRef.value.upData({
type: 'order_no',
keywords: params.value.keywords
});
}
if (searchType.value == '订单号') {
yListRef.value.upData({
type: 'order_no',
keywords: params.value.keywords
});
}
};
const tuikuan = (order_no) => {
uni.showModal({
title: '提示',
content: '是否确认退款?',
success(res) {
if (res.confirm) {
recon.tuikuan({
order_no,
refund_price: ''
}).then(res => {
if (res.code == 0) {
} else {
uni.showToast({
icon: 'none',
title: res.msg
})
}
})
}
}
})
};
const menu = ref([{
content: '昵称'
},
{
content: '订单号'
},
]);
const params = ref({
keywords: "",
type: 'order_no',
status: -2
});
/**
* 切换搜索类型
* @param {Object} item - 切换的项
*/
function changeSearchType({
item,
index
}) {
searchType.value = item.content;
search(params.value.keywords)
}
/**
* @type {Ref<boolean>}
* 控制页面加载状态的 Ref
*/
const loading = ref(false);
const order_list = ref([]);
//
onShow(() => {
})
</script>
<style lang="scss" scoped>
.search-type {
position: relative;
height: 30px;
line-height: 30px;
padding: 0 8px 0 16px;
font-size: 24rpx;
color: rgba(0, 0, 0, .45);
}
.search-type::after {
position: absolute;
content: '';
width: 1px;
right: 0;
top: 5px;
bottom: 5px;
background: rgba(0, 0, 0, 0.25);
}
.search-type {
:deep(.icon-arrow) {
display: inline-block;
font-size: 20px;
vertical-align: middle;
}
}
.userBox,
.title {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.userBox {
justify-content: flex-start;
}
.title {
justify-content: space-between;
}
.title-tip {
color: rgba(0, 0, 0, 0.25);
font-size: 12px;
}
</style>

@ -511,6 +511,11 @@ hasown@^2.0.0:
dependencies: dependencies:
function-bind "^1.1.2" function-bind "^1.1.2"
html5-qrcode@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/html5-qrcode/-/html5-qrcode-2.3.8.tgz#0b0cdf7a9926cfd4be530e13a51db47592adfa0d"
integrity sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==
is-binary-path@~2.1.0: is-binary-path@~2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"

Loading…
Cancel
Save