初始提交

This commit is contained in:
wzgaoyn 2025-03-20 13:47:59 +08:00
commit 68d9870c7c
275 changed files with 14420 additions and 0 deletions

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

17
.env.development Normal file
View File

@ -0,0 +1,17 @@
# 如需添加更多环境变量,请以 VITE_APP_ 开头声明
# 在代码中使用 import.meta.env.VITE_APP_XXX 获取指定变量
# 环境配置标识
VITE_APP_ENV = 'development'
# 微信公众号appid
VITE_APP_MP_APPID = 'wx42bbe857570c5b40'
# 统一接口域名
VITE_APP_BASE_API = 'https://cloud-api-test.mall4j.com'
# 图片域名
VITE_APP_RESOURCES_URL = 'https://mall4j-minio-test.mall4j.com/mall4cloud/'
# 腾讯地图key (WebServiceAPI) 用于IP定位 & 地址位置解析
VITE_APP_MAP_KEY = 'L4DBZ-VSSKJ-GCDFX-KGBVR-KHZ2J-RNF2Q'

16
.env.production Normal file
View File

@ -0,0 +1,16 @@
# 如需添加更多环境变量,请以 VITE_APP_ 开头声明
# 在代码中使用 import.meta.env.VITE_APP_XXX 获取指定变量
# 环境配置标识
VITE_APP_ENV = 'production'
# 微信公众号appid
VITE_APP_MP_APPID = 'wx42bbe857570c5b40'
# 统一接口域名
VITE_APP_BASE_API = 'https://cloud-api.mall4j.com'
# 图片域名
VITE_APP_RESOURCES_URL = 'https://mall4cloud.oss-cn-guangzhou.aliyuncs.com'
# 腾讯地图key (WebServiceAPI) 用于IP定位 & 地址位置解析
VITE_APP_MAP_KEY = ''

18
.env.testing Normal file
View File

@ -0,0 +1,18 @@
# 如需添加更多环境变量,请以 VITE_APP_ 开头声明
# 在代码中使用 import.meta.env.VITE_APP_XXX 获取指定变量
# 环境配置标识
VITE_APP_ENV = 'testing'
# 微信公众号appid
VITE_APP_MP_APPID = 'wx42bbe857570c5b40'
# 统一接口域名
VITE_APP_BASE_API = 'https://cloud-api-vue3.mall4j.com'
# 图片域名
VITE_APP_RESOURCES_URL = 'https://img.mall4j.com/'
# 腾讯地图key (WebServiceAPI) 用于IP定位 & 地址位置解析
# 同时需要配置到 manifest配置文件 h5 -> sdkConfigs -> maps -> qqmap -> key
VITE_APP_MAP_KEY = ''

17
.eslintignore Normal file
View File

@ -0,0 +1,17 @@
# eslint 忽略列表
src/utils/wxqrcode.js
# disk编译目录
dist
build/*.js
src/assets
src/components/tki-barcode
src/uni_modules
src/utils/jwx
src/js_sdk
src/shime.uni.d.ts
public
uni_modules
auto-imports.d.ts

View File

@ -0,0 +1,97 @@
{
"globals": {
"Component": true,
"ComponentPublicInstance": true,
"ComputedRef": true,
"EffectScope": true,
"InjectionKey": true,
"PropType": true,
"Ref": true,
"VNode": true,
"computed": true,
"createApp": true,
"customRef": true,
"defineAsyncComponent": true,
"defineComponent": true,
"effectScope": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"inject": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onUnmounted": true,
"onUpdated": true,
"provide": true,
"reactive": true,
"readonly": true,
"ref": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"toRaw": true,
"toRef": true,
"toRefs": true,
"toValue": true,
"triggerRef": true,
"unref": true,
"useAttrs": true,
"useCssModule": true,
"useCssVars": true,
"useSlots": true,
"watch": true,
"watchEffect": true,
"watchPostEffect": true,
"watchSyncEffect": true,
"onAddToFavorites": true,
"onBackPress": true,
"onError": true,
"onHide": true,
"onLaunch": true,
"onLoad": true,
"onNavigationBarButtonTap": true,
"onNavigationBarSearchInputChanged": true,
"onNavigationBarSearchInputClicked": true,
"onNavigationBarSearchInputConfirmed": true,
"onNavigationBarSearchInputFocusChanged": true,
"onPageNotFound": true,
"onPageScroll": true,
"onPullDownRefresh": true,
"onReachBottom": true,
"onReady": true,
"onResize": true,
"onShareAppMessage": true,
"onShareTimeline": true,
"onShow": true,
"onTabItemTap": true,
"onThemeChange": true,
"onUnhandledRejection": true,
"onUnload": true,
"encrypt": true,
"http": true,
"wechat": true,
"util": true,
"number": true,
"createQrCodeImg": true,
"ExtractDefaultPropTypes": true,
"ExtractPropTypes": true,
"ExtractPublicPropTypes": true,
"WritableComputedRef": true
}
}

86
.eslintrc.js Normal file
View File

@ -0,0 +1,86 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
globals: {
uni: 'readonly',
getApp: 'readonly',
wx: 'readonly',
getCurrentPages: 'readonly',
plus: 'readonly'
},
extends: [
'standard',
'./.eslintrc-auto-import.json',
'plugin:vue/vue3-recommended',
'plugin:vue-scoped-css/vue3-recommended'
],
overrides: [
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: [
'vue'
],
rules: {
// Possible Errors
// 要求使用 let 或 const 而不是 var
'no-var': 'error',
// 强制 "for" 循环中更新子句的计数器朝着正确的方向移动
'for-direction': 'error',
// 强制 getter 函数中出现 return 语句
'getter-return': 'error',
// 禁止在嵌套的块中出现变量声明或 function 声明
'no-inner-declarations': 'error',
// 禁止由于 await 或 yield的使用而可能导致出现竞态条件的赋值
'require-atomic-updates': 'error',
// console 警告
'no-console': 'warn',
// 禁止出现未使用过的变量
'no-unused-vars': [
'warn',
{
args: 'all',
caughtErrors: 'none',
ignoreRestSiblings: true,
vars: 'all'
}
],
// 关闭名称校验
'vue/multi-word-component-names': 'off',
// 非生产环境启用 debugger
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// Best Practices
eqeqeq: 'off',
// Stylistic Issues
// 强制可嵌套的块的最大深度
'max-depth': ['error', 5],
// 强制函数最大代码行数
'max-lines-per-function': [
'error',
{
max: 150,
skipBlankLines: true
}
],
// 强制回调函数最大嵌套深度
'max-nested-callbacks': ['error', { max: 10 }],
// 强制函数定义中最多允许的参数数量
'max-params': ['error', { max: 5 }],
// 强制每一行中所允许的最大语句数量
'max-statements-per-line': ['error', { max: 1 }],
// 三目运算符换行
'multiline-ternary': ['error', 'never'],
// 传值给组件时的使用 kebab-case
'vue/v-on-event-hyphenation': ['warn', 'always', {
autofix: true,
ignore: []
}]
}
}

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
.DS_Store
node_modules/
unpackage/
dist/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-lock.yaml
# Editor directories and files
.project
.idea
.vscode
.hbuilderx
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
src/auto-import

4
.husky/pre-commit Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint:staged

4
.npmrc Normal file
View File

@ -0,0 +1,4 @@
engine-strict = true
shamefully-hoist = true
strict-peer-dependencies = false
registry = https://registry.npmmirror.com

3
Dockerfile Normal file
View File

@ -0,0 +1,3 @@
FROM nginx:1.20
COPY ./dist/build/h5 /usr/share/nginx/html/h5/station
COPY ./nginx.conf /etc/nginx/conf.d

0
README.md Normal file
View File

21
index.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="renderer" content="webkit">
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

26
nginx.conf Normal file
View File

@ -0,0 +1,26 @@
server {
listen 80;
server_name h5.mall4j.com;
location /station {
try_files $uri $uri/ /station/;
root /usr/share/nginx/html/h5;
index index.html;
#### kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
error_page 404 /404.html;
location = /404-light.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

80
package.json Normal file
View File

@ -0,0 +1,80 @@
{
"name": "mall4cloud-station",
"private": true,
"version": "0.0.0",
"scripts": {
"preinstall": "npx only-allow pnpm",
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5-test": "uni --mode testing",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5-test": "uni build --mode testing --outDir ./dist/build/test-h5",
"prepare": "husky install",
"lint:staged": "lint-staged"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-3090920231225001",
"@dcloudio/uni-app-plus": "3.0.0-3090920231225001",
"@dcloudio/uni-components": "3.0.0-3090920231225001",
"@dcloudio/uni-h5": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-alipay": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-baidu": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-jd": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-lark": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-qq": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-toutiao": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-weixin": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-xhs": "3.0.0-3090920231225001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3090920231225001",
"@uni-ui/code-ui": "1.5.3",
"crypto-js": "4.2.0",
"vite-plugin-commonjs": "0.10.1",
"vue": "3.3.8"
},
"devDependencies": {
"@dcloudio/types": "3.4.3",
"@dcloudio/uni-automator": "3.0.0-3090920231225001",
"@dcloudio/uni-cli-shared": "3.0.0-3090920231225001",
"@dcloudio/uni-stacktracey": "3.0.0-3090920231225001",
"@dcloudio/vite-plugin-uni": "3.0.0-3090920231225001",
"@vitejs/plugin-legacy": "4.1.1",
"@vue/runtime-core": "^3.2.45",
"eslint": "8.53.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.29.0",
"eslint-plugin-n": "16.3.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-vue": "9.18.1",
"eslint-plugin-vue-scoped-css": "2.5.1",
"husky": "8.0.3",
"lint-staged": "15.1.0",
"sass": "1.69.5",
"terser": "5.24.0",
"unplugin-auto-import": "0.16.7",
"unplugin-vue-components": "0.25.2",
"vite": "4.5.0",
"vue-eslint-parser": "9.3.2"
},
"lint-staged": {
"*.{js,vue}": [
"eslint --fix"
]
},
"engines": {
"node": ">=18.12.0",
"pnpm": ">=7"
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@babel/core*",
"jest*",
"postcss*",
"regenerator-runtime*",
"url*"
]
}
}
}

32
src/App.vue Normal file
View File

@ -0,0 +1,32 @@
<script setup>
onLaunch(() => {
// eslint-disable-next-line no-console
console.log('mall4j.v240115')
setIOSUrl()
})
//
onPageNotFound(() => {
uni.reLaunch({
url: '/pages/index/index'
})
})
// IOS url
const setIOSUrl = () => {
uni.getSystemInfo({
success: res => {
// iosandroid
if (res.platform === 'ios') {
uni.setStorageSync('cloudIosUrl', window.location.href.split('#')[0])
}
}
})
}
</script>
<!-- eslint-disable-next-line vue-scoped-css/enforce-style-type -->
<style lang="scss">
/*每个页面公共css */
@use "./app.scss";
</style>

37
src/app.scss Normal file
View File

@ -0,0 +1,37 @@
/* 隐藏头部 */
uni-page-head {
display: none;
}
.container {
height: 100%;
box-sizing: border-box;
color: #333;
font-family: helvetica, 'Heiti SC', PingFangSC-Light, sans-serif;
}
/*
*改变radio样式
*自定义样式
*/
/* 未选中的 背景样式 */
uni-radio .uni-radio-input{
height: 36rpx;
width: 36rpx;
border-radius: 50%;
background: transparent;
box-sizing: border-box;
}
/* z-paging 返回顶部按钮的图片样式 */
.zp-back-to-top-img {
width: 40rpx !important;
height: 40rpx !important;
}
/* z-paging 底部加载更多的loading样式 */
.zp-line-loading-image{
width: 24rpx !important;
height: 24rpx !important;
}

View File

@ -0,0 +1,389 @@
<template>
<!-- 打开选择器按钮图标 -->
<image
:class="classList"
:style="imgStyle"
:src="imgIcon"
/>
<template v-if="showPicker">
<view
class="animation-element-wrapper"
:style="'visibility:' + (show ? 'visible':'hidden')"
@tap.stop="cancel"
>
<view
class="animation-element"
@tap.stop="nono"
>
<text
class="right-bt"
@tap.stop="hiddenFloatView"
>
确定
</text>
<view class="line" />
<picker-view
indicator-style="height: 70rpx;"
:value="addressValue"
@change="bindChange"
@tap.stop="nono"
>
<!---->
<picker-view-column>
<view
v-for="(item, i) in provArray"
:key="i"
>
{{ item.areaName }}
</view>
</picker-view-column>
<!--地级市-->
<picker-view-column>
<view
v-for="(item, i) in cityArray"
:key="i"
>
{{ item.areaName }}
</view>
</picker-view-column>
<!--区县-->
<picker-view-column>
<view
v-for="(item, i) in areaArray"
:key="i"
>
{{ item.areaName }}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
</template>
<script setup>
import icon from '@/static/images/icon/more.png'
import http from '@/utils/http'
const props = defineProps({
// [areaId, areaId, areaId]
value: {
type: Array,
default: () => {
return []
}
},
//
classList: {
type: Array,
default: () => {
return []
}
},
//
imgStyle: {
type: Object,
default: () => {
return {}
}
},
//
imgIcon: {
type: String,
default: icon
},
//
showPicker: {
type: Boolean,
default: false
}
})
/**
* 定义所需要操作父组件的数据
* change: 数据发生改变时给父组件返回数据
* showPicker: 改变父组件的值从而可以在子组件进行关闭选择器
* value: 用做与父组件数据同步的值
*/
const emit = defineEmits(['change', 'update:showPicker', 'update:value'])
//
// eslint-disable-next-line no-unused-vars
const change = (arr) => {
emit('change', arr)
}
// showPicker
watch(() => props.showPicker, (newVal) => {
show.value = !!newVal
})
// value
watch(() => props.value, async (newVal) => {
if (newVal.length >= 3) {
if (provArray.value.length > 0) {
await getCityArray(newVal[0], newVal[1], newVal[2])
}
} else {
addressValue.value = [0, 0, 0]
await getCityArray(provArray.value[0].areaId)
}
})
//
const getAreaListInfo = () => {
return new Promise((resolve) => {
http.request({
url: '/mall4cloud_order/area/list',
method: 'GET',
data: {}
}).then(res => {
resolve(res)
})
})
}
const addressValue = ref([])
const provArray = ref([])
onLoad(async () => {
//
const res = await getAreaListInfo()
if (res.data.length > 0) {
provArray.value = res.data
}
if (props.value.length >= 3) {
await getCityArray(props.value[0], props.value[1], props.value[2])
} else {
addressValue.value = [0, 0, 0]
await getCityArray(provArray.value[0].areaId)
}
})
const cityArray = ref([])
const areaArray = ref([])
let addressIndex = []
//
const bindChange = (e) => {
const val = e.detail.value // column
// column
if (addressIndex[0] !== val[0]) {
val[1] = 0
val[2] = 0 //
getCityArray(provArray.value[val[0]].areaId) //
} else {
// column
if (addressIndex[1] !== val[1]) {
val[2] = 0 //
getAreaArray(cityArray.value[val[1]].areaId) //
}
}
if (addressIndex[0] !== val[0] || addressIndex[1] !== val[1] || addressIndex[2] !== val[2]) {
addressValue.value = [val[0], val[1], val[2]]
addressIndex = addressValue.value
}
}
//
const getCurrentAreas = (curList, curId) => {
if (curId) {
for (let index = 0; index < curList.length; index++) {
if (curList[index].areaId === curId) {
return {
curNode: curList[index],
areas: curList[index].areas,
index
}
}
}
} else {
const one = curList[0]
return {
curNode: one,
areas: one.areas,
index: 0
}
}
}
// id
const listAreaByParentId = (pid) => {
let paramData = {}
if (!pid) {
paramData = { level: 1 }
} else {
paramData = { pid }
}
return new Promise((resolve) => {
http.request({
url: '/p/area/listByPid',
method: 'GET',
data: paramData
}).then(res => {
resolve(res)
})
})
}
/**
* 根据省份ID获取 城市数据
*/
const getCityArray = async (provId, cityId, areaId) => {
const { curNode, areas, index } = getCurrentAreas(provArray.value, provId)
let cityArr = areas
if (!areas) {
listAreaByParentId(provId).then(res => {
if (res.data.length > 0) {
cityArr = res.data
}
})
}
if (curNode) {
curNode.areas = cityArr
}
if (index) {
addressValue.value = [index, 0, 0]
}
cityArray.value = cityArr
if (cityId) {
for (let i = 0; i < cityArray.value.length; i++) {
if (cityArray.value[i].areaId === cityId) {
addressValue.value = [addressValue.value[0], i, addressValue.value[2]]
}
}
}
await getAreaArray(cityId || cityArray.value[0].areaId, areaId)
}
/**
* 根据城市ID获取 区数据
*/
const getAreaArray = async (cityOfId, areaOfId) => {
const { curNode, areas, index } = getCurrentAreas(cityArray.value, cityOfId)
let areaArr = areas
if (!areas) {
listAreaByParentId(cityOfId).then(res => {
if (res.data.length > 0) {
areaArr = res.data
}
})
}
if (index) {
addressValue.value = [addressValue.value[0], index, 0]
}
curNode.areas = areaArr
areaArray.value = areaArr
if (areaOfId) {
for (let index = 0; index < areaArray.value.length; index++) {
if (areaArray.value[index].areaId === areaOfId) {
addressValue.value = [addressValue.value[0], addressValue.value[1], Number(index)]
}
}
addressIndex = addressValue.value
}
}
const show = ref(false)
/**
* 隐藏弹窗浮层并重新赋值
*/
const hiddenFloatView = () => {
emit('update:showPicker', false)
initCityData(addressValue.value[0], addressValue.value[1], addressValue.value[2])
}
/**
* 仅取消浮窗不改变值
*/
const cancel = async () => {
await getCityArray(props.value[0], props.value[1], props.value[2])
emit('update:showPicker', false)
}
// id
const initCityData = async (provId, cityId, areaId) => {
const arr = [{
areaId: provArray.value[provId].areaId,
areaName: provArray.value[provId].areaName
}, {
areaId: cityArray.value[cityId].areaId,
areaName: cityArray.value[cityId].areaName
}, {
areaId: areaArray.value[areaId].areaId,
areaName: areaArray.value[areaId].areaName
}]
emit('update:value', [arr[0].areaId, arr[1].areaId, arr[2].areaId])
emit('change', arr)
}
//
const nono = () => {}
</script>
<style scoped lang="scss">
picker-view {
background-color: white;
padding: 0;
width: 100%;
height: 380rpx;
bottom: 0;
position: fixed;
text {
color: #999;
display: inline-flex;
position: fixed;
margin-top: 20rpx;
height: 50rpx;
text-align: center;
line-height: 50rpx;
font-size: 34rpx;
font-family: Arial, Helvetica, sans-serif;
}
}
picker-view-column {
view {
vertical-align: middle;
font-size: 30rpx;
line-height: 30rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
.animation-element-wrapper {
display: flex;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
z-index: 999;
}
.animation-element {
display: flex;
position: fixed;
width: 100%;
height: 530rpx;
bottom: 0;
background-color: rgba(255, 255, 255, 1);
}
.right-bt {
right: 35rpx;
top: 20rpx;
position: absolute;
width: 80rpx !important;
}
.line {
display: block;
position: fixed;
height: 2rpx;
width: 100%;
margin-top: 89rpx;
background-color: #eee;
}
</style>

10
src/main.js Normal file
View File

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

20
src/manifest.json Normal file
View File

@ -0,0 +1,20 @@
{
"name" : "mall4cloud-station",
"appid" : "",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"h5" : {
"title" : "首页",
"domain" : "h5.mall4j.com",
"router" : {
"base" : "/station/",
"mode" : "history"
},
"template" : "index.html",
"devServer" : {
"port" : 80,
"disableHostCheck" : true
}
}
}

70
src/pages.json Normal file
View File

@ -0,0 +1,70 @@
{
"easycom": {
"custom": {
"^w-(.*)": "@uni-ui/code-ui/components/w-$1/index.vue" // componentsvue
}
},
"pages": [
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/account-login/account-login",
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/shop-adminsistration/shop-adminsistration",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "店铺管理"
}
},
{
"path": "pages/order-list/order-list",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "订单列表"
}
},
{
"path": "pages/order-detail/order-detail",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "订单详情"
}
},
{
"path": "pages/scan-pick/scan-pick",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "核销订单"
}
},
{
"path": "pages/pick-code/pick-code",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "核销码核销"
}
},
{
"path": "pages/business-code/business-code",
"style": {
"backgroundTextStyle": "light",
"navigationBarTitleText": "商家码"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "蓝海商城门店端",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}

View File

@ -0,0 +1,122 @@
.page-account-login {
background: #fff;
height: 100%;
padding-top: 100rpx;
.logo { display: flex;
justify-content: center;
height: 150rpx;
margin-bottom: 8%;
}
.logo {
image {
display: block;
width: 100%;
height: 100%;
}
}
.login-form {
width: 90%;
margin: 0 auto;
margin-bottom: 20%;
}
.authorized-btn {
width: 90%;
margin: 0 auto;
text-align: center;
background-color: #0ab906;
border: 1rpx solid #0ab906;
color: #fff;
border-radius: 6rpx;
font-size: 26rpx;
padding: 8rpx;
margin-top: 80rpx;
}
.to-idx-btn {
width: 90%;
margin: 0 auto;
text-align: center;
background-color: #eeeeee;
color: #333;
border-radius: 6rpx;
font-size: 26rpx;
padding: 8rpx;
margin-top: 30rpx;
}
.form-title {
width: 100%;
margin-bottom: 50rpx;
font-size: 32rpx;
text-align: center;
color: #00a0e9;
}
.item {
display: block;
margin-bottom: 30rpx;
}
.account {
display: flex;
background: #f8f8f8;
padding: 15rpx;
box-sizing: border-box;
font-size: 26rpx;
align-items: center;
input {
padding-left: 20rpx;
width: 75%;
}
input.int-yzm {
width: 410rpx;
padding-right: 10rpx;
box-sizing: border-box;
}
}
.inp-palcehoder {
font-size: 26rpx;
}
.input-btn {
width: 152rpx;
font-size: 26rpx;
color: #00a0ea;
text-align: center;
}
button {
&::after {
border: 0 !important;
}
}
.operate {
display: flex;
justify-content: space-between;
align-items: center;
}
.forgot-password {
font-size: 28rpx;
color: #00AAFF;
}
.to-register {
font-size: 28rpx;
color: #00AAFF;
}
.error {
.error-text {
display: block;
width: 100%;
font-size: 28rpx;
color: #e43130;
text-align: left;
margin-top: 10rpx;
.warning-icon {
display: inline-block;
color: #fff;
width: 26rpx;
height: 26rpx;
line-height: 26rpx;
background: #e43130;
border-radius: 50%;
text-align: center;
margin-right: 12rpx;
font-size: 22rpx;
}
}
}
}

View File

@ -0,0 +1,148 @@
<template>
<view class="page-account-login">
<view class="logo">
<image
:src="stationLoginLogoImg"
mode="heightFix"
@error="onError"
/>
</view>
<!-- 登录 -->
<view
v-if="!isForgetPassword"
class="login-form"
>
<view :class="['item',errorTips===1 && !isForgetPassword? 'error':'']">
<view class="account">
<text class="input-item">
账号
</text>
<input
v-model="principal"
type="text"
data-type="account"
placeholder-class="inp-palcehoder"
placeholder="请输入账号"
@blur="principal = principal.replace(/\s/g,'')"
>
</view>
<view
v-if="errorTips===1 && !isForgetPassword"
class="error-text"
>
<text class="warning-icon">
!
</text>账号不能为空
</view>
</view>
<view :class="['item',errorTips===2? 'error':'']">
<view class="account">
<text class="input-item">
密码
</text>
<input
v-model="credentials"
type="password"
data-type="password"
placeholder-class="inp-palcehoder"
placeholder="请输入密码"
@blur="credentials = credentials.replace(/\s/g,'')"
>
</view>
<view
v-if="errorTips===2"
class="error-text"
>
<text class="warning-icon">
!
</text>请输入密码
</view>
</view>
</view>
<view v-if="!isForgetPassword">
<button
class="authorized-btn"
@tap="onLogin"
>
登录
</button>
</view>
</view>
</template>
<script setup>
import { encrypt } from '@/utils/crypto'
import logoImg from '@/static/images/icon/logo.png'
const errorTips = ref(0) //
const stationLoginLogoImg = ref('')
/**
* 生命周期函数--监听页面加载
*/
const isForgetPassword = ref(false) //
onLoad((options) => {
if (options.isForgetPassword) {
isForgetPassword.value = options.isForgetPassword
}
onGetUniWebConfig()
})
const onGetUniWebConfig = () => {
http.request({
url: '/mall4cloud_admin/ua/web_config/get_activity',
method: 'GET',
data: {
webConfigType: 'STATION_WEBSITE_CONFIG'
}
}).then(({ data }) => {
const logo = data.stationLoginLogoImg
stationLoginLogoImg.value = logo ? import.meta.env.VITE_APP_RESOURCES_URL + logo : logoImg
uni.setStorageSync('cloudStationLoginLogoImg', stationLoginLogoImg.value)
})
}
/**
* 登录
*/
const principal = ref('')
const credentials = ref('')
const onLogin = () => {
if (!principal.value) {
errorTips.value = 1
} else if (credentials.value.length === 0) {
errorTips.value = 2
} else {
errorTips.value = 0
http.request({
url: '/mall4cloud_auth/ua/station_login',
method: 'POST',
data: {
userName: principal.value,
passWord: encrypt(credentials.value),
sysType: 4,
tempUid: uni.getStorageSync('cloudSTempUid')
}
}).then(({ data }) => {
uni.removeStorageSync('cloudStationId')
uni.setStorageSync('cloudStationToken', data.accessToken)
uni.showToast({
title: '登录成功!',
icon: 'none',
complete () {
uni.reLaunch({
url: '/pages/index/index'
})
}
})
})
}
}
const onError = () => {
stationLoginLogoImg.value = logoImg
}
</script>
<style lang="scss" scoped>
@use "./account-login.scss";
</style>

View File

@ -0,0 +1,117 @@
.page-business-code {
min-height: 100vh;
background: #f4f4f4;
overflow: auto;
image {
width: 100%;
height: 100%;
}
.delivery-certificate {
margin: 30rpx;
padding: 30rpx;
background: #fff;
font-size: 24rpx;
border-radius: 10rpx;
box-shadow: 0 0 6rpx rgba(0,0,0,0.05);
.item {
position: relative;
border-bottom: 2rpx dashed #ddd;
&::before {
position: absolute;
bottom: -20rpx;
display: block;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: #f4f4f4;
content: " ";
font-size: 0;
left: -56rpx;
}
&::after {
position: absolute;
bottom: -20rpx;
display: block;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: #f4f4f4;
content: " ";
font-size: 0;
right: -56rpx;
}
}
.address-box {
padding-bottom: 30rpx;
.name {
font-size: 28rpx;
display: flex;
align-items: center;
margin-bottom: 20rpx;
font-weight: 600;
.self-icon {
padding: 2rpx 6rpx;
line-height: 1;
color: #e43130;
border: 2rpx solid #e43130;
font-size: 20rpx;
margin-left: 10rpx;
border-radius: 4rpx;
font-weight: 400;
}
}
.a-item {
margin-bottom: 10rpx;
display: flex;
.img {
width: 24rpx;
height: 24rpx;
font-size: 0;
margin-right: 10rpx;
margin-top: 4rpx;
}
.text {
flex: 1;
}
}
}
.code-det {
padding: 40rpx 0;
.bar-code {
font-size: 0;
margin: auto;
width: 610rpx;
display: flex;
justify-content: center;
}
.code-number {
margin-top: 20rpx;
text-align: center;
}
.code {
width: 300rpx;
height: 300rpx;
margin: 40rpx auto 0;
}
}
.btn-box {
margin-top: 30rpx;
display: flex;
justify-content: center;
}
}
.btn {
width: auto;
text-align: center;
font-size: 26rpx;
font-weight: bold;
border-radius: 70rpx;
}
.code {
.qrcode-img {
display: block;
width: 100%;
height: 100%;
}
}
}

View File

@ -0,0 +1,68 @@
<template>
<view class="container page-business-code">
<view class="delivery-certificate">
<view class="address-box item">
<view class="btn">
商家码
</view>
</view>
<view class="code-det item">
<view class="bar-code">
<w-barcode :options="barOpations" />
</view>
<view class="code">
<image :src="stationQrCode" />
</view>
</view>
<view class="btn-box">
扫码一键核销
</view>
</view>
</view>
</template>
<script setup>
import Qr from '@/utils/wxqrcode.js'
import http from '@/utils/http.js'
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
const stationId = ref('') // id
const stationQrCode = ref('')
const barOpations = ref({
height: 150,
width: 350,
code: 'null', //
orient: 'horizontal'
})
/**
* 生命周期函数--监听页面加载
*/
onLoad(() => {
onGetBusCodeInf()
})
/* 请求自提点码信息 */
const onGetBusCodeInf = () => {
uni.showLoading()
http.request({
url: '/mall4cloud_order/station/get_code',
method: 'GET',
data: {}
}).then(({ data }) => {
stationId.value = data.split('#station#')[1]
barOpations.value.code = stationId.value + '' //
//
setTimeout(() => {
onGetQrcode()
}, 50)
uni.hideLoading()
})
}
/* 生成二维码 */
const onGetQrcode = () => {
stationQrCode.value = Qr.createQrCodeImg(stationId.value)
}
</script>
<style lang="scss" scoped>
@use "./business-code.scss";
</style>

161
src/pages/index/index.scss Normal file
View File

@ -0,0 +1,161 @@
.page-index {
height: 100vh;
width: 100%;
background-color: #F5F5F5;
/* 照片默认样式 */
image {
display: block;
width: 100%;
height: 100%;
}
/* 自提点信息or业绩 */
.shop-data {
display: block;
width: 100%;
height: auto;
min-height: 640rpx;
box-sizing: border-box;
color: #fff;
}
.bg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 420rpx;
}
/* 自提点信息 */
.data-top {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 15px;
padding: 10px;
position: relative;
}
.shop-info {
display: flex;
align-items: center;
width: 100%;
.shop-icon {
display: block;
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
margin-right: 20rpx;
overflow: hidden;
}
.shop-name {
width: auto;
max-width: 400rpx;
font-size: 32rpx;
font-weight: bold;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
.switch-num {
display: flex;
align-items: center;
margin-left: auto;
color: #FE3A26;
position: absolute;
right: 0;
font-size: 24rpx;
background-color: #fff;
padding: 15rpx 24rpx;
border-radius: 60rpx 0 0 60rpx;
image {
width: 24rpx;
height: 24rpx;
margin-right: 12rpx;
}
}
.search {
display: flex;
align-items: center;
width: 45%;
height: 35px;
background: rgba(255,255,255,.2);
border-radius: 60px;
box-sizing: border-box;
padding: 8px 10px;
}
.search-icon {
display: block;
width: 20px;
height: 15px;
padding-right: 5px;
}
/* 业绩信息 */
.achievement {
font-size: 24rpx;
padding: 40rpx 0;
background-color: #fff;
width: 702rpx;
margin: 62rpx auto 0;
border-radius: 14rpx;
position: relative;
.data-line {
display: flex;
justify-content: center;
&:first-child {
margin-bottom: 48rpx;
}
.data-block {
width: 33.33%;
&:not(:last-child) {
border-right: 1rpx solid #E1E1E1;
}
.data-cont {
font-size: 40rpx;
color: #FE3A26;
font-weight: bold;
text-align: center;
}
.data-tit {
text-align: center;
line-height: 40rpx;
margin-top: 8rpx;
color: #333;
}
}
}
}
.commom-tit {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 24rpx;
margin-left: 24rpx;
}
.app-list {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 32rpx 0 0 0;
background-color: #fff;
border-radius: 14rpx;
width: 702rpx;
margin: 0 auto;
}
.app-item {
text-align: center;
font-size: 24rpx;
color: #5B5B5B;
line-height: 28rpx;
padding: 0 38rpx;
margin-bottom: 32rpx;
width: 96rpx;
>image {
display: inline-block;
width: 72rpx;
height: 72rpx;
text-align: center;
margin-bottom: 8rpx;
}
}
}

287
src/pages/index/index.vue Normal file
View File

@ -0,0 +1,287 @@
<template>
<view class="my-shop-wrapper page-index">
<view class="shop-data">
<view class="bg">
<image src="/static/images/icon/bg-home.png" />
</view>
<!-- 自提点信息 -->
<view class="data-top">
<view class="shop-info">
<view class="shop-icon">
<image
:src="imgUrl"
@error="onErrorImg"
/>
</view>
<view class="shop-name">
{{ stationName }}
</view>
<view
class="switch-num"
@tap="onSwitchNum"
>
<image src="/static/images/icon/handoff.png" />
<view>切换账号</view>
</view>
</view>
</view>
<!-- /月业绩信息 -->
<view class="achievement">
<!-- <view class="a-title">
<view class="tit">本店业绩</view>
</view> -->
<!-- <view class="data-table"> -->
<view class="data-line">
<view class="data-block">
<view class="data-cont">
{{ dayTurnover.payOrderNumber || 0 }}
</view>
<view class="data-tit">
今日订单
</view>
</view>
<view class="data-block dividing">
<view class="data-cont">
{{ dealNum(dayTurnover.payAmount).res }}<text v-if="dealNum(dayTurnover.payAmount).isW">
w
</text>
</view>
<view class="data-tit">
今日交易额
</view>
</view>
<view class="data-block">
<view class="data-cont">
{{ dealNum(dayTurnover.customerUnitPrice).res }}<text v-if="dealNum(dayTurnover.customerUnitPrice).isW">
w
</text>
</view>
<view class="data-tit">
今日客单价
</view>
</view>
</view>
<view class="data-line">
<view class="data-block">
<view class="data-cont">
{{ monthTurnover.payOrderNumber || 0 }}
</view>
<view class="data-tit">
本月订单
</view>
</view>
<view class="data-block dividing">
<view class="data-cont">
{{ dealNum(monthTurnover.payAmount).res }}<text v-if="dealNum(monthTurnover.payAmount).isW">
w
</text>
</view>
<view class="data-tit">
本月交易额
</view>
</view>
<view class="data-block">
<view class="data-cont">
{{ dealNum(monthTurnover.customerUnitPrice).res }}<text v-if="dealNum(monthTurnover.customerUnitPrice).isW">
w
</text>
</view>
<view class="data-tit">
本月客单价
</view>
</view>
</view>
<!-- </view> -->
</view>
</view>
<!-- 常见应用 -->
<view class="commom-app">
<view class="commom-tit">
常见应用
</view>
<view class="app-list">
<view
class="app-item"
@tap="onToShopAdministration"
>
<image src="/static/images/icon/shop-manage.png" />
<view class="app-name">
店铺管理
</view>
</view>
<view
class="app-item"
@tap="onToOrderAdministration"
>
<image src="/static/images/icon/orders.png" />
<view class="app-name">
订单管理
</view>
</view>
<view
class="app-item"
@tap="scanCode"
>
<image src="/static/images/icon/verification.png" />
<view class="app-name">
验证核销
</view>
</view>
<view
class="app-item"
@tap="onToBusinessCode"
>
<image src="/static/images/icon/merchant-code.png" />
<view class="app-name">
商家码
</view>
</view>
<view
class="app-item"
@tap="onToPinkCode"
>
<image src="/static/images/icon/verification-code.png" />
<view class="app-name">
核销码
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import Wechat from '../../utils/wechat.js'
import util from '@/utils/util.js'
const stationName = ref('') //
const imgUrl = ref('') // logo
const dayTurnover = ref([]) //
const monthTurnover = ref([]) //
/**
* 生命周期函数--监听页面加载
*/
onShow(() => {
onGetIndexData()
})
/* 自提点首页数据 */
const onGetIndexData = () => {
uni.showLoading()
http.request({
url: '/mall4cloud_order/station/get_station_index_info',
method: 'GET',
data: {}
}).then(({ data }) => {
//
stationName.value = data.stationName
imgUrl.value = data.imgUrl ? import.meta.env.VITE_APP_RESOURCES_URL + data.imgUrl : '/static/images/icon/normal-bg.png'
for (let i = 0; i < data.stationSalesDTOList.length; i++) {
const salesType = data.stationSalesDTOList[i].salesType
if (salesType === 1) {
dayTurnover.value = data.stationSalesDTOList[i]
} else if (salesType === 2) {
monthTurnover.value = data.stationSalesDTOList[i]
}
}
if (!uni.getStorageSync('cloudStationId')) {
uni.setStorageSync('cloudStationId', data.stationId)
}
uni.hideLoading()
})
}
/* 切换账号 */
const onSwitchNum = () => {
http.request({
url: '/mall4cloud_auth/ma/login_out',
method: 'post'
}).then(() => {
//
uni.removeStorageSync('cloudStationLoginResult')
uni.removeStorageSync('cloudStationToken')
uni.removeStorageSync('cloudStationHadLogin')
uni.removeStorageSync('cloudStationId')
uni.redirectTo({
url: '/pages/account-login/account-login'
})
})
}
/* 跳转店铺管理页 */
const onToShopAdministration = () => {
uni.navigateTo({
url: '/pages/shop-adminsistration/shop-adminsistration'
})
}
/* 跳转订单管理页 */
const onToOrderAdministration = () => {
uni.navigateTo({
url: '/pages/order-list/order-list'
})
}
/* 跳转商家码页 */
const onToBusinessCode = () => {
uni.navigateTo({
url: '/pages/business-code/business-code'
// url: '/pages/scan-pick/scan-pick'
})
}
/* 跳转提货码取件页 */
const onToPinkCode = () => {
uni.navigateTo({
url: '/pages/pick-code/pick-code'
})
}
/* 唤醒扫码功能 */
let code = ''
const scanCode = util.debounce(function () {
// #ifdef H5
if (!Wechat.isWechat()) {
uni.showToast({
title: '请在微信浏览器打开!',
icon: 'none'
})
return
}
Wechat.scanQRCode((codeStr) => {
//
if (codeStr.indexOf(',') > -1) {
code = codeStr.split(',')[1]
} else {
code = codeStr
}
//
uni.navigateTo({
url: '/pages/scan-pick/scan-pick?pickCode=' + code + '&pageType=1'
})
}, () => {
uni.showToast({
title: '唤起扫码失败,请稍后重试',
icon: 'none'
})
})
// #endif
}, 1000)
//
const dealNum = (val) => {
if (!val) return { res: 0, isW: false }
let res = val / 100
let isW = false
if (res >= 100000) {
isW = true
res = res / 10000
}
res = String(res)
if (res && res.indexOf('.') > -1 && res.indexOf('.') <= res.length - 3) {
res = res.slice(0, res.indexOf('.') + 2)
}
return { res, isW }
}
const onErrorImg = () => {
imgUrl.value = '/static/images/icon/normal-bg.png'
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>

View File

@ -0,0 +1,441 @@
/* pages/order-detail/order-detail.wxss */
.page-order-detail {
background: #f4f4f4;
min-height: 100vh;
image {
width: 100%;
height: 100%;
}
.order-detail {
margin-bottom: 132rpx;
.order-status {
position: relative;
padding: 30rpx 20rpx;
background: #fff;
.status-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 168rpx;
font-size: 0;
}
.status-text {
font-size: 36rpx;
font-weight: 600;
color: #fff;
margin: 26rpx 30rpx 24rpx;
position: relative;
}
.step {
position: relative;
display: flex;
align-items: center;
margin-top: 50rpx;
.item {
flex: 1;
.select {
width: 12rpx;
height: 12rpx;
border: 16rpx solid #fff;
background: #999;
margin: auto;
border-radius: 50%;
position: relative;
}
.des {
font-size: 24rpx;
margin-top: 10rpx;
text-align: center;
}
}
.item.active {
.select {
background: #e43130;
width: 32rpx;
height: 32rpx;
border: 6rpx solid #fff;
color: #fff;
&::after {
content: "";
font: 0.625rem/1 uni;
position: absolute;
left: 20%;
top: 20%;
width: 55%;
height: 30%;
border: 0.125rem solid #FFFFFF;
border-radius: 0.0625rem;
border-top: none;
border-right: none;
background: transparent;
transform: rotate(-45deg);
}
}
.des {
color: #e43130;
}
}
}
}
}
.prod-item {
background: #fff;
margin-top: 20rpx;
font-size: 24rpx;
padding: 0 30rpx;
.shop-box {
padding: 24rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
.refund-sts {
color: #e43130;
}
}
.shop-icon {
width: 24rpx;
height: 24rpx;
margin-right: 10rpx;
}
.shop-name {
flex: 1;
font-weight: 600;
}
.prod-box {
padding: 30rpx 0;
border-top: 2rpx solid #eee;
}
.item-cont {
position: relative;
display: flex;
.prod-pic {
font-size: 0;
width: 180rpx;
height: 180rpx;
}
.prod-info {
flex: 1;
margin-left: 20rpx;
position: relative;
.prodname {
display: flex;
align-items: flex-start;
.a-icon {
margin-right: 10rpx;
font-size: 20rpx;
color: #fff;
background: #e43130;
padding: 4rpx 10rpx;
border-radius: 4rpx;
line-height: 20rpx;
margin-top: 4rpx;
}
.text {
line-height: 36rpx;
max-height: 72rpx;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
}
}
.sku-name {
margin-top: 10rpx;
color: #999;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
}
}
}
.price-nums {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
display: flex;
align-items: baseline;
.prodprice {
color: #e43130;
margin-right: 10rpx;
}
.number {
color: #999;
}
}
.gift-prods {
margin-left: 200rpx;
margin-top: 30rpx;
.gift-item {
display: block;
width: 100%;
color: #333;
&:not(:last-child) {
margin-bottom: 12rpx;
}
.name {
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
width: 90%;
padding-right: 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.num {
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
}
}
}
.sku-name {
.gift-icon {
display: inline-block;
margin-right: 10rpx;
color: #fff;
font-size: 24rpx;
background: #e43130;
padding: 6rpx;
border-radius: 6rpx;
line-height: 1em;
box-sizing: border-box;
}
}
}
.order-msg {
background: #fff;
margin-top: 20rpx;
font-size: 24rpx;
padding: 0 30rpx;
.msg-item {
padding: 20rpx 0;
border-top: 2rpx solid #eee;
&:first-child {
border: 0;
}
.item {
position: relative;
display: flex;
padding: 10rpx 0;
.item-tit {
color: #999;
}
.item-txt {
flex: 1;
}
.remarks-tit {
width: 120rpx;
}
.remarks-txt {
width: 400rpx;
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
line-height: 38rpx;
}
.copy-btn {
display: block;
margin-left: 20rpx;
border: 2rpx solid #bbb;
padding: 6rpx 24rpx;
border-radius: 50rpx;
font-size: 24rpx;
}
}
.item.all-msg {
position: relative;
.item-txt {
word-break: break-word;
display: grid;
line-height: 1.5em;
}
.item-txt.pd {
padding-right: 32rpx;
}
.more-msg {
&::after {
position: absolute;
right: 8rpx;
top: 45%;
display: block;
width: 14rpx;
height: 14rpx;
border: 2rpx solid #666;
border-width: 2rpx 2rpx 0 0;
content: " ";
font-size: 0;
transform: rotate(45deg) translateY(-50%);
}
}
}
}
}
.order-msg.payment {
.msg-item {
.item {
.item-txt {
text-align: right;
}
}
}
}
.popup-hide {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 999;
background-color: rgba(0, 0, 0, 0.3);
.con-tit {
display: flex;
justify-content: space-around;
align-items: center;
font-size: 28rpx;
font-weight: bold;
padding: 30rpx;
.tit-text {
flex: 1;
text-align: center;
}
}
.virtual-goods-msg-pop {
height: auto;
.con-tit {
.tit-text {
text-align: left;
}
}
.msg-pop-con {
.msg-list {
padding: 20rpx 30rpx;
margin-bottom: 140rpx;
}
.msg-item {
display: flex;
margin-bottom: 30rpx;
}
.item-con {
font-size: 24rpx;
word-wrap: break-word;
word-break: break-word;
}
.item-con.weak {
color: #999999;
margin-right: 20rpx;
width: 180rpx;
min-width: 180rpx;
}
.pop-foot {
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
padding: 0 20rpx;
margin-bottom: 30rpx;
margin-top: 20rpx;
box-sizing: border-box;
background: #fff;
.foot-btn {
font-size: 26rpx;
color: #fff;
width: 100%;
background: #E43130;
border-radius: 140rpx;
padding: 20rpx 0;
box-sizing: border-box;
}
}
}
}
}
.popup-box {
position: absolute;
bottom: 0;
width: 100%;
height: 80%;
overflow: hidden;
background-color: #fff;
border-radius: 10rpx 10rpx 0 0;
}
.close {
color: #666;
font-size: 32rpx;
&::before {
content: "\2715";
}
}
.order-msg.voucher-code-con {
.msg-item.voucher-code-list {
max-height: 470rpx;
overflow-y: auto;
box-sizing: border-box;
padding-right: 10rpx;
}
.msg-item {
.item {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0;
&:not(:last-child) {
margin-bottom: 16rpx;
}
.item-left {
.txt.flex-item {
display: flex;
.lf {
white-space: nowrap;
line-height: 1.5em;
}
.rg {
line-height: 1.5em;
}
}
}
.txt {
&:not(:last-child) {
margin-bottom: 10rpx;
}
}
.txt.strong {
font-weight: bold;
}
.txt.weak {
color: #999;
}
.tips {
color: #999;
}
.copy-btn2 {
background: #F7F8FA;
padding: 4rpx 20rpx;
border-radius: 60rpx;
font-size: 24rpx;
}
}
.item.used {
.tips {
margin-right: 8rpx;
height: 40rpx;
line-height: 40rpx;
}
.code-row {
.code {
text-decoration: line-through;
color: #999;
}
}
}
}
}
}

View File

@ -0,0 +1,718 @@
<template>
<!--pages/order-detail/order-detail.wxml-->
<view class="container page-order-detail">
<view class="order-detail">
<!-- 订单状态 -->
<view class="order-status">
<view class="status-bg">
<image src="/static/images/icon/status-bg.png" />
</view>
<view class="status-text">
{{ ['','等待买家支付','等待商家发货','等待买家收货','订单已完成','订单已完成','订单已取消','正在拼团中','待使用'][status] }}
</view>
<view class="step">
<view :class="['item',status===2 || status === 3 || (status === 6 && orderItems[0].refundSn) || status===4 || status===5|| status===8 ? 'active' : '']">
<view class="select" />
<view class="des">
买家付款
</view>
</view>
<view
v-if="dvyType === 2"
:class="['item',status===3 || status===4 || status===5 ? 'active' : '']"
>
<view class="select" />
<view class="des">
买家提货
</view>
</view>
<view :class="['item',status===4||status===5 ? 'active' : '']">
<view class="select" />
<view class="des">
交易完成
</view>
</view>
</view>
</view>
<!-- 商品信息 -->
<view class="prod-item">
<!-- 店铺 -->
<view class="shop-box">
<view class="shop-icon">
<image src="/static/images/icon/shop.png" />
</view>
<view class="shop-name">
{{ shopName }}
</view>
<view
v-if="refundStatus !==0"
class="refund-sts"
>
<!-- refundStatus 订单退款状态 1.申请退款 2.退款完成 3.部分退款完成 4.退款失败 -->
<text>{{ ['','退款中','退款完成','部分退款','退款关闭'][refundStatus] }}</text>
</view>
</view>
<!-- / -->
<view
v-for="(item, spuId) in prodList"
:key="spuId"
class="prod-box"
>
<view
class="item-cont"
:data-prodid="item.spuId"
@tap="onToProdPage"
>
<view class="prod-pic">
<image
v-if="item.pic"
:src="item.pic.indexOf('http') === -1 ? picDomain + item.pic : item.pic"
@error="item.pic = ''"
/>
<image
v-else
src="/static/images/icon/def.png"
/>
</view>
<!-- 拼团商品展示icon -->
<view class="prod-info">
<view class="prodname">
<view
v-if="orderType"
class="a-icon"
>
{{ ['','拼团','秒杀','积分'][orderType] }}
</view>
<view class="text">
{{ item.spuName }}
</view>
</view>
<view class="sku-name">
<text
v-if="orderItems.length === 1 && item.giveawayOrderItemId"
class="gift-icon"
>
赠品
</text>
<text>{{ item.skuName }}</text>
</view>
<view class="price-nums">
<view class="prodprice">
<text
v-if="item.price"
class="symbol"
>
</text>
<text
v-if="item.price"
class="big-num"
>
{{ wxs.parsePrice(item.price)[0] }}
</text>
<text
v-if="item.price"
class="small-num"
>
.{{ wxs.parsePrice(item.price)[1] }}
</text>
<text
v-if="item.price && orderType===3"
class="small-num"
>
+
</text>
<text
v-if="orderType===3"
class="small-num"
>
{{ item.useScore }} 积分
</text>
</view>
<view class="number">
<text>{{ orderMold === 1 ? totalNum : item.count }}</text>
</view>
</view>
</view>
</view>
<!-- 组合 -->
<view
v-if="item.comboItemList && item.comboItemList.length"
class="gift-prods"
>
<view
v-for="comboItem in item.comboItemList"
:key="comboItem.orderItemId"
class="gift-item"
>
<text class="name">
组合{{ comboItem.spuName }}
</text>
<text class="num">
×{{ comboItem.count }}
</text>
</view>
</view>
<!-- 赠品多个商品时展示 -->
<view
v-if="orderItems.length > 1 && item.giveawayList && item.giveawayList.length"
class="gift-prods"
>
<view
v-for="giftItem in item.giveawayList"
:key="giftItem.orderItemId"
class="gift-item"
>
<text class="name">
赠品{{ giftItem.spuName }}
</text>
<text class="num">
×{{ giftItem.count }}
</text>
</view>
</view>
</view>
</view>
<!-- 订单信息 -->
<view class="order-msg">
<view class="msg-item">
<view class="item">
<text class="item-tit">
订单编号
</text>
<text class="item-txt">
{{ orderNumber }}
</text>
<!-- #ifdef APP-PLUS -->
<text
class="copy-btn"
@tap="onCopyBtn"
>
复制
</text>
<!-- #endif -->
</view>
<view class="item">
<text class="item-tit">
下单时间
</text>
<text class="item-txt">
{{ createTime }}
</text>
</view>
</view>
<view class="msg-item">
<view
v-if="payType !== null"
class="item"
>
<text class="item-tit">
支付方式
</text>
<text class="item-txt">
{{ ['积分支付','微信支付','支付宝支付','微信支付','微信支付','微信支付','支付宝支付','支付宝支付','微信支付','余额支付','PayPal支付'][payType] }}
</text>
</view>
<view class="item">
<text class="item-tit">
配送方式
</text>
<text class="item-txt">
{{ ['卖家配送','卖家配送','到店自提','无需快递'][dvyType] }}
</text>
</view>
<!-- 全部留言虚拟商品 -->
<view
v-if="orderMold === 1 && virtualRemarkList.length >= 0"
class="item all-msg"
@tap="onShowViewMsgPopup"
>
<view class="item-tit">
全部留言
</view>
<view
class="item-txt"
:class="{'pd': isExtraLong}"
>
<span
v-for="(item, index) in virtualRemarkList"
:key="index"
>{{ item[0] }}&nbsp;&nbsp;&nbsp;&nbsp;{{ item[1] }}</span>
</view>
<view
v-if="isExtraLong"
class="more-msg"
/>
</view>
</view>
<view
v-if="remarks"
class="msg-item"
>
<view class="item">
<text class="item-tit remarks-tit">
订单备注
</text>
<text class="item-txt remarks-txt">
{{ remarks }}
</text>
</view>
</view>
</view>
<!-- 虚拟商品-券码情况 -->
<view
v-if="orderMold === 1"
class="order-msg voucher-code-con"
>
<view class="msg-item">
<view class="item">
<view class="item-left">
<!-- 待使用/未使用 (unusedCount待使用的核销券) -->
<view
v-if="unusedCount && status !== 6&&orderMold===1"
class="txt strong"
>
{{ (isExpired?'已过期':'待使用') + '' + unusedCount+'张)' }}
</view>
<!-- 确认收货(已完成) & 没有待核销的券码 -->
<view
v-if="status === 5 && !unusedCount&&orderMold===1"
class="txt strong"
>
{{ '已使用(' + orderItems[0].count + '张)' }}
</view>
<!-- 退款成功 -->
<!-- 优惠券待使用 -->
<view
v-if="orderMold===2&& status !== 5"
class="txt strong"
>
{{ (isExpired?'已过期':'待使用') + '' + couponUnusedCount+'张)' }}
</view>
<view
v-if="status === 5 && orderMold === 1 && unusedCount"
class="txt strong"
>
{{ '已使用(' + (virtualInfoList.length - couponUnusedCount) + '张)' }}
</view>
<view class="txt weak flex-item">
<view class="lf">
有效期限
</view>
<view class="rg">
<text v-if="writeOffStart && !writeOffEnd">
购买后长期有效
</text>
<text v-if="writeOffStart && writeOffEnd">
{{ writeOffStart }} {{ writeOffEnd }}
</text>
</view>
</view>
<view
v-if="orderMold === 1"
class="txt weak flex-item"
>
<view class="lf">
核销次数
</view>
<view class="rg">
<text v-if="writeOffNum === -1">
多次核销
</text>
<text v-if="writeOffNum === 1">
单次核销
</text>
<text v-if="writeOffNum === 0">
无需核销
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 券码列表 -->
<view
v-if="virtualInfoList && virtualInfoList.length"
class="msg-item voucher-code-list"
>
<view
v-for="(item, index) in virtualInfoList"
:key="index"
class="item"
:class="{'used': item.isWriteOff === 1 || status === 6||item.status===2}"
>
<view class="code-row">
<text>券码</text>
<text v-if="virtualInfoList.length > 1">
{{ index+1 }}
</text>
<text class="code">
{{ item.writeOffCode }}
</text>
</view>
<view
v-if="item.isWriteOff === 1||item.status===2"
class="tips"
>
已使用
</view>
<view
v-if="(item.isWriteOff === 0 && status !== 6)||item.status===1"
class="copy-btn2"
@tap="copyText(item.writeOffCode)"
>
复制
</view>
</view>
</view>
</view>
<view class="order-msg payment">
<view class="msg-item">
<view class="item">
<view class="item-tit">
商品总额
</view>
<view class="item-txt">
{{ wxs.parsePrice(productTotalAmount)[0] }}.{{ wxs.parsePrice(productTotalAmount)[1] }}
</view>
</view>
<view
v-if="transfee"
class="item"
>
<view class="item-tit">
运费
</view>
<view class="item-txt">
{{ wxs.parsePrice(transfee)[0] }}.{{ wxs.parsePrice(transfee)[1] }}
</view>
</view>
<view
v-if="reduceAmount"
class="item"
>
<view class="item-tit">
<text
v-if="orderType && orderType!==3"
class="item-tit"
>
{{ orderType===1?'团购':'秒杀' }}
</text>优惠
</view>
<view class="item-txt">
-{{ wxs.parsePrice(reduceAmount)[0] }}.{{ wxs.parsePrice(reduceAmount)[1] }}
</view>
</view>
<view class="item price">
<view class="item-tit">
订单总额
</view>
<view class="item-txt">
<text
v-if="actualTotal && actualTotal > 0"
class="symbol"
>
</text>
<text
v-if="actualTotal && actualTotal > 0"
class="big-num"
>
{{ wxs.parsePrice(actualTotal)[0] }}
</text>
<text
v-if="actualTotal && actualTotal > 0 || actualTotal > 0"
class="small-num"
>
.{{ wxs.parsePrice(actualTotal)[1] }}
</text>
<text
v-if="(actualTotal && actualTotal > 0) && (orderType===3 || orderScore > 0)"
class="small-num"
>
+
</text>
<text
v-if="orderType===3 || orderScore > 0"
class="big-num"
>
{{ orderScore }} <text class="small-num">
积分
</text>
</text>
</view>
</view>
</view>
</view>
</view>
<view
class="popup-hide"
:hidden="!showViewMsg"
>
<view class="popup-box virtual-goods-msg-pop">
<view class="con-tit">
<view class="tit-text">
查看留言
</view>
<view
class="close"
@tap="onCloseMsgPopup"
/>
</view>
<view class="msg-pop-con">
<view class="msg-list">
<view
v-for="(item, index) in virtualRemark"
:key="index"
class="msg-item"
>
<view class="item-con weak">
{{ item.name }}
</view>
<view class="item-con">
{{ item.value }}
</view>
</view>
</view>
<view class="pop-foot">
<view
class="foot-btn"
@tap="onCloseMsgPopup"
>
我知道了
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
const wxs = number()
//
const picDomain = import.meta.env.VITE_APP_RESOURCES_URL
/**
* 生命周期函数--监听页面加载
*/
const refundStatus = ref(0) // 退
onLoad((options) => {
onLoadOrderDetail(options.orderNum)
refundStatus.value = options.refundStatus
})
//
const onToProdPage = (e) => {
const prodid = e.currentTarget.dataset.prodid
if (orderType.value === 3) {
uni.navigateTo({
url: '/pages/convertProdDet/convertProdDet?prodid=' + prodid
})
} else {
uni.navigateTo({
url: '/pages/prod/prod?prodid=' + prodid
})
}
}
/**
* 加载订单数据
*/
const orderItems = ref([])
const remarks = ref('')
const actualTotal = ref(0)
const couponUnusedCount = ref(0)
const orderNumber = ref('')
const orderScore = ref(0) // 使
const createTime = ref('')
const status = ref(0) // 0 1 2 3 4 5 6 7
const productTotalAmount = ref('')
const transfee = ref('')
const reduceAmount = ref('')
const orderType = ref(0)
const shopName = ref('') //
const dvyType = ref(1) // 1: 2: 3
const payType = ref('') //
const orderMold = ref('') // 1
const virtualRemark = ref([]) //
const virtualInfoList = ref([]) //
const writeOffNum = ref(0)
const writeOffStart = ref(null)
const writeOffEnd = ref(null)
const totalNum = ref(null) //
const prodList = ref([]) //
const onLoadOrderDetail = (orderNum) => {
uni.showLoading() //
http.request({
url: '/mall4cloud_order/my_order/order_detail',
method: 'GET',
data: {
orderId: orderNum
}
}).then(({ data }) => {
uni.hideLoading()
// const couponUnusedCount = 0
// data.couponUserList?.forEach(el => {
// el.status === 1 ? couponUnusedCount++ : null
// })
orderNumber.value = orderNum
actualTotal.value = data.actualTotal
remarks.value = data.remarks // +)
orderItems.value = data.orderItems
createTime.value = data.createTime
status.value = data.status
productTotalAmount.value = data.total
transfee.value = data.transfee //
reduceAmount.value = data.reduceAmount //
orderType.value = data.orderType
orderScore.value = data.orderScore // 使
shopName.value = data.shopName
dvyType.value = data.deliveryType // 1: 2: 3
payType.value = data.payType //
orderMold.value = data.orderMold // 1
virtualInfoList.value = data.virtualInfoList //
virtualRemark.value = data.orderItems[0].virtualRemark ? JSON.parse(data.orderItems[0].virtualRemark) : [] //
writeOffNum.value = data.writeOffNum // -1 0 1
writeOffStart.value = data.writeOffStart //
writeOffEnd.value = data.writeOffEnd //
totalNum.value = data.totalNum
if (data.deliveryType === 2) {
onLoadStationDetail(orderNum)
}
//
onHandlevirtualRemark()
// -使
onHandleUnusedVirtualCode(data.virtualInfoList)
prodList.value = data.orderItems
//
if (data.orderItems.length === 1 &&
data.orderItems[0].giveawayList &&
data.orderItems[0].giveawayList.length) {
prodList.value = [...data.orderItems, ...data.orderItems[0].giveawayList]
}
}).catch(err => {
uni.hideLoading()
uni.showModal({
title: '提示',
content: err.data,
showCancel: false,
confirmText: '确定',
success: (err) => {
if (err.confirm) {
uni.redirectTo({
url: '/pages/order-list/order-list'
})
}
}
})
})
}
// -使
const unusedCount = ref(0)
const onHandleUnusedVirtualCode = (list) => {
if (list && list.length) {
let isnusedCount = 0
list.forEach(el => {
if (el.isWriteOff === 0) {
isnusedCount = isnusedCount + 1
}
})
unusedCount.value = isnusedCount
}
}
/**
* 加载订单详情自提信息
*/
const onLoadStationDetail = (orderNum) => {
uni.showLoading() //
http.request({
url: '/mall4cloud_order/my_station_order/station_detail',
method: 'GET',
data: {
orderId: orderNum
}
}).then(() => {
uni.hideLoading()
})
}
// -
const virtualRemarkList = ref([])
const isExtraLong = ref() //
let virtualRemarks = []
const onHandlevirtualRemark = () => {
if (virtualRemark.value && virtualRemark.value.length) {
//
console.log(virtualRemark.value)
virtualRemark.value = virtualRemark.value.filter(el => el.value)
const isVirtualRemarkList = []
// 3
if (virtualRemark.value.length > 3) {
const list = JSON.parse(JSON.stringify(virtualRemark.value))
virtualRemarks = list.splice(0, 1)
isExtraLong.value = true
} else {
virtualRemarks = virtualRemark.value
isExtraLong.value = false
}
//
virtualRemarks.forEach((el) => {
isVirtualRemarkList.push([el.name, el.value])
})
if (isExtraLong.value) {
virtualRemarkList.value = isVirtualRemarkList.push('......')
} else {
virtualRemarkList.value = isVirtualRemarkList
}
}
}
//
const showViewMsg = ref() //
const onShowViewMsgPopup = () => {
if (isExtraLong.value) {
showViewMsg.value = true
}
}
const onCloseMsgPopup = () => {
showViewMsg.value = false
}
// #ifdef APP-PLUS
/**
* 一键复制事件
*/
//
const onCopyBtn = () => {
// h5
uni.setClipboardData({
data: orderNumber.value,
success: function () {
uni.showToast({
title: '复制成功',
icon: 'none',
duration: 1000
})
}
})
}
// #endif
</script>
<style lang="scss" scoped>
@import "./order-detail.scss";
</style>

View File

@ -0,0 +1,346 @@
/* pages/order-list/order-list.wxss */
.page-order-list{
background-color: #f4f4f4;
color: #333;
overflow: auto;
min-height: 100vh;
/* 头部菜单 */
.order-tit {
position: fixed;
top: 0;
display: flex;
justify-content: space-around;
z-index: 999;
width: 100%;
height: 88rpx;
line-height: 88rpx;
background-color: #fff;
}
.order-tit text {
display: block;
font-size: 24rpx;
text-align: center;
}
.order-tit text.on {
border-bottom: 4rpx solid #e43130;
color: #e43130;
font-weight: 600;
}
/* end 头部菜单 */
.main {
margin-top: 108rpx;
}
/* 商品列表 */
.prod-item {
background-color: #fff;
margin-bottom: 20rpx;
font-size: 28rpx;
}
/* 店铺 */
.shop-box {
padding: 20rpx;
border-bottom: 2rpx solid #f2f2f2;
display: flex;
align-items: center;
}
.shop-icon {
width: 24rpx;
height: 24rpx;
margin-right: 10rpx;
font-size: 0;
}
.shop-icon > image {
width: 100%;
height: 100%;
}
.shop-name {
font-size: 24rpx;
font-weight: 600;
position: relative;
padding-right: 16rpx;
}
.prod-item .order-num {
padding: 20rpx;
font-size: 24rpx;
display: flex;
align-items: center;
}
.order-num > text {
flex: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.order-state {
color: #999999;
display: flex;
align-items: center;
}
.order-state.red {
color: #e43130;
}
.prod-item .order-num .clear-btn {
width: 28rpx;
height: 28rpx;
font-size: 0;
margin-left: 42rpx;
position: relative;
}
.prod-item .order-num .clear-btn::after {
content: " ";
display: block;
position: absolute;
left: -20rpx;
top: 0rpx;
width: 2rpx;
height: 32rpx;
background: #eee;
}
.prod-item .order-num .clear-btn .clear-list-btn {
width: 100%;
height: 100%;
}
.prod-item .item-cont {
display: flex;
align-items: center;
padding: 20rpx;
display: -webkit-flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
background: #f7f7f7;
position: relative;
}
.prod-item .item-cont .categories {
white-space: nowrap;
}
.prod-item .item-cont .prod-pic {
position: relative;
display: inline-block;
font-size: 0;
width: 160rpx;
height: 160rpx;
background: #fff;
margin-right: 20rpx;
}
.prod-item .item-cont .prod-pic image {
width: 100%;
height: 100%;
}
.spell-group-order {
position: absolute;
display: block;
top: 0;
left: 0;
width: 60rpx;
height: 30rpx;
}
.prod-item .item-cont .prod-info {
font-size: 24rpx;
position: relative;
height: 160rpx;
-webkit-flex: 1;
-ms-flex: 1;
-webkit-box-flex: 1;
-moz-box-flex: 1;
flex: 1;
}
.prod-item .item-cont .prod-info .prodname {
line-height: 34rpx;
max-height: 68rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.prod-item .item-cont .prod-info .tag {
display: inline-block;
font-size: 24rpx;
color: #e43130;
border: 1px solid #e43130;
padding: 4rpx 8rpx;
line-height: 1em;
margin-right: 8rpx;
}
.prod-item .item-cont .prod-info .prod-info-cont {
margin-top: 10rpx;
color: #999;
font-size: 24rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.prod-item .price-nums {
position: absolute;
bottom: 0;
width: 100%;
display: flex;
align-items: baseline;
line-height: 32rpx;
}
.prod-item .price-nums .prodprice {
flex: 1;
}
.prod-item .price-nums .prodcount {
color: #999;
font-family: arial;
margin-right: 10rpx;
}
.prod-item .total-num {
display: flex;
align-items: center;
padding: 20rpx;
position: relative;
}
.prod-item .total-num .spell-group-icon {
margin-right: 10rpx;
padding: 4rpx 18rpx;
color: #fff;
border-radius: 20rpx;
font-size: 20rpx;
color: #e43130;
border: 2rpx solid #e43130;
}
.prod-item .total-num .right {
flex: 1;
display: flex;
justify-content: flex-end;
align-items: baseline;
font-size: 24rpx;
}
.prod-item .total-num .right .prodcount {
margin-right: 20rpx;
}
.prod-item .prod-foot {
padding: 20rpx;
border-top: 2rpx solid #eee;
}
.prod-item .prod-foot .total {
font-size: 24rpx;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #eee;
}
.other-button-hover {
background-color: blue;
}
.button-hover {
background-color: #e43130;
}
/** 添加自定义button点击态样式类**/
.button-hover {
background-color: blue;
}
.btn {
display: flex;
justify-content: flex-end;
align-items: center;
}
.button {
display: inline-block;
margin-left: 10px;
font-size: 24rpx;
background: #fff;
padding: 10rpx 30rpx;
border-radius: 80rpx;
border: 2rpx solid #ddd;
}
.button.warn {
color: #e43130;
border-color: #e43130;
}
/* end 商品列表 */
/* 根据状态显示不同的颜色 */
.order-state .order-sts.red {
color: #e43130;
}
.order-state .order-sts {
color: #333;
}
/* 加载完成 */
.loadall {
margin: 20rpx 0;
line-height: 2em;
font-size: 24rpx;
color: #aaa;
text-align: center;
}
/* 列表为空 */
.empty {
padding-top: 200rpx;
text-align: cneter;
}
.empty-icon {
display: block;
width: 80rpx;
height: 80rpx;
margin: 0 auto;
margin-bottom: 20rpx;
}
.empty-icon > image {
display: block;
width: 100%;
height: 100%;
}
.empty-text {
font-size: 28rpx;
text-align: center;
color: #999;
line-height: 40rpx;
}
}

View File

@ -0,0 +1,370 @@
<template>
<view class="container page-order-list">
<!-- 头部菜单 -->
<view class="order-tit">
<text
data-sts="0"
:class="sts===0 ? 'on' : ''"
@tap="onStsTap"
>
全部
</text>
<text
data-sts="1"
:class="sts===1 ? 'on' : ''"
@tap="onStsTap"
>
待付款
</text>
<text
data-sts="2"
:class="sts===2 ? 'on' : ''"
@tap="onStsTap"
>
待发货
</text>
<text
data-sts="3"
:class="sts===3 ? 'on' : ''"
@tap="onStsTap"
>
待收货
</text>
<text
data-sts="5"
:class="sts===5 ? 'on' : ''"
@tap="onStsTap"
>
已完成
</text>
</view>
<!-- end 头部菜单 -->
<view class="main">
<!-- 订单列表 -->
<block
v-for="(item, orderId) in list"
:key="orderId"
>
<view class="prod-item">
<!-- 店铺 -->
<view class="shop-box">
<view class="shop-icon">
<image src="/static/images/icon/shop.png" />
</view>
<view class="shop-name">
{{ item.shopName }}
</view>
</view>
<!-- 订单编号 -->
<view class="order-num">
<text>订单编号{{ item.orderId }}</text>
<view class="order-state">
<text :class="['order-sts' , {red: (item.status < 5) }]">
{{ ['','待付款','待发货','待收货','待评价','已完成','已取消','拼团中'][item.status] }}
</text>
</view>
<view
v-if="item.refundStatus"
class="order-state red"
>
<!-- refundStatus 订单退款状态 1.申请退款 2.退款完成 3.部分退款完成 4.退款失败 -->
<text>({{ ['','退款中','退款完成','部分退款','退款关闭'][item.refundStatus] }})</text>
</view>
</view>
<!-- 商品列表 -->
<!-- 一个订单单个商品的显示 -->
<block v-if="item.orderItems.length===1">
<block
v-for="(prod, prodId) in item.orderItems"
:key="prodId"
>
<view
class="item-cont"
@tap="onToOrderDetailPage(item.orderId, item.refundStatus)"
>
<view class="prod-pic">
<image
v-if="prod.pic"
:src="util.addDomain(prod.pic)"
@error="prod.pic = ''"
/>
<image
v-else
src="/static/images/icon/def.png"
/>
</view>
<view class="prod-info">
<view class="prodname">
{{ prod.spuName }}
</view>
<view class="prod-info-cont">
{{ prod.skuName }}
</view>
<view class="price-nums">
<text class="prodprice">
<text
v-if="prod.price"
class="symbol"
>
</text>
<text
v-if="prod.price"
class="big-num"
>
{{ wxs.parsePrice(prod.price)[0] }}
</text>
<text
v-if="prod.price"
class="small-num"
>
.{{ wxs.parsePrice(prod.price)[1] }}
</text>
<text
v-if="prod.price && item.orderType===3"
class="small-num"
decode="true"
>
&emsp;+&emsp;
</text>
<text
v-if="prod.useScore && item.orderType===3"
class="small-num"
>
{{ prod.useScore }} 积分
</text>
</text>
<text
v-if="item.orderMold===1&&item.orderVirtualInfoList && item.orderVirtualInfoList.length>0"
class="prodcount"
>
× {{ item.virtualCount }}
</text>
<text
v-else
class="prodcount"
>
× {{ prod.count }}
</text>
</view>
</view>
</view>
</block>
</block>
<!-- 一个订单多个商品时的显示 -->
<block v-else>
<view
class="item-cont"
@tap="onToOrderDetailPage(item.orderId, item.refundStatus)"
>
<scroll-view
scroll-x="true"
scroll-left="0"
scroll-with-animation="false"
class="categories"
>
<block
v-for="(prod, prodId) in item.orderItems"
:key="prodId"
>
<view class="prod-pic">
<image
v-if="prod.pic"
:src="util.addDomain(prod.pic)"
@error="prod.pic = ''"
/>
<image
v-else
src="/static/images/icon/def.png"
/>
</view>
</block>
</scroll-view>
</view>
</block>
<view class="total-num">
<view
v-if="item.orderType"
class="spell-group-icon"
>
<!-- orderType 订单类型(0普通订单 1团购订单 2秒杀订单) -->
{{ ['','拼团','秒杀','积分'][item.orderType] }}
</view>
<view
v-if="item.orderMold !== 0"
class="spell-group-icon"
>
{{ item.orderMold===1?'虚拟':(item.deliveryType===2?'自提':'优惠券') }}
</view>
<!-- <view class="spell-group-icon">自提</view> -->
<view class="right">
<view class="prodcount">
{{ item.allCount }} 件商品
</view>
<view class="prodprice">
合计
<text
v-if="item.actualTotal"
class="symbol"
>
</text>
<text
v-if="item.actualTotal"
class="big-num"
>
{{ wxs.parsePrice(item.actualTotal)[0] }}
</text>
<text
v-if="item.actualTotal"
class="small-num"
>
.{{ wxs.parsePrice(item.actualTotal)[1] }}
</text>
<text
v-if="(item.actualTotal && item.actualTotal > 0) && (item.orderType===3 || item.orderToataluseScore > 0)"
class="small-num"
>
+
</text>
<text
v-if="item.orderType===3 || item.orderToataluseScore > 0"
class="small-num"
>
{{ item.orderToataluseScore }} 积分
</text>
</view>
</view>
</view>
</view>
</block>
</view>
<!-- 到底了~ -->
<view
v-if="list.length > 10 && loadAll"
class="loadall"
>
已加载全部数据
</view>
<!-- -->
<view
v-if="!list.length"
class="empty"
>
<view class="empty-icon">
<image src="/static/images/icon/empty.png" />
</view>
<view class="empty-text">
这里还没有相关订单~
</view>
</view>
</view>
<!-- end 订单列表 -->
</template>
<script setup>
import util from '@/utils/util.js'
const wxs = number()
/**
* 生命周期函数--监听页面加载
*/
const sts = ref(0)
onLoad((options) => {
if (options.sts) {
sts.value = options.sts
}
})
/**
* 生命周期函数--监听页面显示
*/
onShow(() => {
onLoadOrderData(sts.value, 1)
})
/**
* 页面上拉触底事件的处理函数
*/
let current = 1
let pages = 0
const loadAll = ref(false) //
onReachBottom(() => {
if (current < pages) {
current++
onLoadOrderData(sts.value, current)
} else {
loadAll.value = true
}
})
/**
* 加载订单数据
*/
const list = ref([])
let stationId = 0
let newList = []
const onLoadOrderData = (sts, isCurrent) => {
uni.showLoading() //
http.request({
url: '/mall4cloud_order/station/order_list_by_status',
method: 'GET',
data: {
pageNum: isCurrent,
pageSize: 10,
status: sts
}
}).then(({ data }) => {
data.list.forEach(order => {
order.orderToataluseScore = 0
order.orderItems.forEach(orderItem => {
if (orderItem.useScore) {
order.orderToataluseScore += orderItem.useScore
}
})
stationId = uni.getStorageSync('cloudStationId') ? JSON.parse(uni.getStorageSync('cloudStationId')) : ''
if (order.orderMold === 1 && order.orderVirtualInfoList && order.orderVirtualInfoList.length > 0) {
let virtualCount = 0
order.orderVirtualInfoList.forEach((virtualItem) => {
if (virtualItem.stationId === stationId) {
virtualCount++
}
})
order.virtualCount = virtualCount
}
})
if (isCurrent === 1) {
newList = data.list
} else {
newList = list.value.concat(data.list)
}
list.value = newList
pages = data.pages
current = isCurrent
uni.hideLoading()
})
}
/**
* 状态点击事件
*/
const onStsTap = (e) => {
sts.value = Number(e.currentTarget.dataset.sts)
onLoadOrderData(sts.value, 1)
}
/**
* 查看订单详情
*/
const onToOrderDetailPage = (orderNum, refundStatus) => {
const sts = refundStatus || 0
uni.navigateTo({
url: '/pages/order-detail/order-detail?orderNum=' + orderNum + '&refundStatus=' + sts
})
}
</script>
<style lang="scss" scoped>
@import "./order-list.scss";
</style>

View File

@ -0,0 +1,40 @@
page{
overflow: hidden;
}
.page-pick-code {
width: 500rpx;
margin: 0 auto;
margin-top: 45%;
.title {
width: 500rpx;
font-size: 40rpx;
text-align: center;
}
.inp-wrapper {
display: flex;
align-items: center;
width: 100%;
height: 100rpx;
margin-top: 50rpx;
border: 1rpx solid #fd6227;
border-radius: 15rpx;
overflow: hidden;
}
.input {
width: 370rpx;
height: 100rpx;
padding: 0 15rpx;
}
.sub-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
width: 100rpx;
height: 100rpx;
font-size: 30rpx;
color: #fff;
background-color: #fd6227;
}
}

View File

@ -0,0 +1,54 @@
<template>
<view class="page-pick-code">
<view class="title">
输入核销码
</view>
<view class="inp-wrapper">
<input
class="input"
:value="code"
placeholder="请输入核销码"
@input="onGetPinkCodeInp"
>
<view
class="sub-btn"
@tap="onToScanPick"
>
确定
</view>
</view>
</view>
</template>
<script setup>
import util from '@/utils/util'
const code = ref('')
/* 跳转到取件页面 */
const onToScanPick = () => {
if (code.value === '') {
uni.showToast({
title: '请输入核销码',
icon: 'none'
})
} else if (!util.checkIsVerification(code.value)) {
code.value = ''
uni.showToast({
title: '请输入正确的核销码',
icon: 'none'
})
} else {
//
uni.navigateTo({
url: '/pages/scan-pick/scan-pick?pickCode=' + code.value + '&pageType=2'
})
}
}
//
const onGetPinkCodeInp = (e) => {
code.value = e.detail.value
}
</script>
<style lang="scss" scoped>
@import "./pick-code.scss";
</style>

View File

@ -0,0 +1,267 @@
.page-scan-pick {
min-height: 100vh;
background-color: #f8f8f8;
overflow: hidden;
.personal-inf{ display: flex;
align-items: center;
width: 690rpx;
font-size: 28rpx;
background-color: #fff;
border-radius: 10rpx;
margin: 0 auto;
margin-top: 30rpx;
}
.personal-inf-wrapper {
padding: 30rpx 0;
}
.personal-inf {
.line {
display: flex;
align-items: top;
&:not(:last-child) {
margin-bottom: 30rpx;
}
view {
display: inline-block;
}
.title {
white-space: nowrap;
color: #999;
padding-right: 15rpx;
margin-left: 30rpx;
width: 180rpx;
display: flex;
justify-content: space-between;
}
.detail {
width: 460rpx;
word-wrap: break-word;
word-break: normal;
color: 333;
}
}
}
.commodity-inf {
width: 690rpx;
background-color: #fff;
border-radius: 10rpx;
margin: 0 auto;
margin-top: 30rpx;
.title {
display: flex;
align-items: center;
width: 100%;
height: 80rpx;
border-bottom: 3rpx solid #eee;
}
.icon {
display: inline-block;
width: 30rpx;
height: 30rpx;
margin-right: 15rpx;
>image {
width: 100%;
height: 100%;
}
}
.font {
display: inline-block;
font-size: 28rpx;
font-weight: 550;
padding-right: 16rpx;
}
.total {
display: block;
padding: 30rpx 0;
text-align: right;
font-size: 28rpx;
box-sizing: border-box;
}
}
.commodity-inf-wrapper {
padding: 0 30rpx;
}
.prod-box {
display: block;
}
.item-cont {
border-bottom: 3rpx solid #eee;
.gift-prods {
margin-left: 200rpx;
margin-top: 10rpx;
margin-bottom: 30rpx;
font-size: 24rpx;
.gift-item {
display: block;
width: 100%;
color: #333;
margin-bottom: 10rpx;
.name {
display: inline-block;
vertical-align: middle;
padding-right: 10rpx;
box-sizing: border-box;
width: 90%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.num {
display: inline-block;
vertical-align: middle;
padding-right: 10rpx;
box-sizing: border-box;
}
}
}
}
.prod-detail {
display: flex;
align-items: center;
width: 100%;
height: 220rpx;
.prod-img {
display: inline-block;
width: 175rpx;
height: 175rpx;
margin-right: 20rpx;
image {
width: 175rpx;
height: 175rpx;
}
}
.prod-inf {
display: inline-block;
font-size: 25rpx;
width: 100%;
.prod-title {
line-height: 19px;
max-height: 39px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
word-break: break-all;
color: #333;
font-size: 26rpx;
font-weight: 549;
}
.brief {
font-size: 23rpx;
color: #999;
padding: 15rpx 0;
.gift-icon {
display: inline-block;
padding: 8rpx;
border-radius: 6rpx;
background: #e43130;
color: #fff;
margin-right: 8rpx;
line-height: 1em;
}
}
.price {
font-size: 31rpx;
font-weight: 520;
color: #e43130;
}
.num {
float: left;
font-size: 30rpx;
color: #999;
}
.sku-type {
font-size: 22rpx;
float: right;
word-break: break-all;
line-height: 30rpx;
color: #999;
border: 1rpx solid #999;
border-radius: 4rpx;
padding: 1rpx 6rpx;
}
}
}
.red {
color: #e43130;
}
.order-remarks {
display: flex;
width: 690rpx;
padding: 20rpx 0;
font-size: 28rpx;
background-color: #fff;
border-radius: 10rpx;
margin: 0 auto;
margin-top: 20rpx;
.remarks-title {
font-size: 28rpx;
color: #999;
margin-left: 30rpx;
width: 140rpx;
}
.remarks-txt {
width: 500rpx;
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
}
}
.virtual-goods-code {
display: block;
width: 690rpx;
padding: 20rpx 30rpx;
box-sizing: border-box;
font-size: 28rpx;
background-color: #fff;
border-radius: 10rpx;
margin: 0 auto;
margin-top: 20rpx;
.code-tit {
margin-bottom: 20rpx;
}
.code-list.code-box {
max-height: 1000rpx;
overflow-y: auto;
.code-item {
font-size: 26rpx;
}
}
.code-list {
&:not(:last-child) {
border-bottom: 1px solid #eee;
padding-bottom: 10rpx;
margin-bottom: 20rpx;
}
.code-item {
margin-bottom: 16rpx;
font-size: 24rpx;
}
.date {
display: flex;
align-items: flex-start;
.lf {
white-space: nowrap;
}
}
}
.weak {
color: #999;
}
}
.pick-btn {
width: 690rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
color: #fff;
background: #f81a1a;
text-align: center;
border-radius: 10rpx;
margin: 100rpx auto;
}
.no-pick-btn {
background: #e5e5e5;
}
}

View File

@ -0,0 +1,499 @@
<template>
<view class="page-scan-pick">
<!-- 提货人信息 -->
<view
v-if="isSelfPickup === 0 && (stationAddress || stationUserName || stationUserMobile)"
class="personal-inf"
>
<view class="personal-inf-wrapper">
<view class="pick-addr line">
<view class="title">
<text></text>
<text></text>
<text></text>
<text></text>
</view>
<view class="detail">
{{ stationAddress }}
</view>
</view>
<view class="pick-people line">
<view class="title">
<text></text>
<text></text>
<text></text>
</view>
<view class="detail">
{{ stationUserName }}
</view>
</view>
<view class="pick-people line">
<view class="title">
<text></text>
<text></text>
<text></text>
<text></text>
<text></text>
</view>
<view class="detail">
{{ stationUserMobile }}
</view>
</view>
</view>
</view>
<!-- 商品信息 -->
<view
v-if="orderList && orderList.length"
class="commodity-inf"
>
<view class="commodity-inf-wrapper">
<view class="title">
<!-- <view class="icon"><image src=""></image></view> -->
<view class="icon">
<image src="/static/images/icon/shop.png" />
</view>
<view class="font">
{{ shopName }}
</view>
</view>
<view class="prod-box">
<view
v-for="(item, key) in orderList"
:key="key"
class="item-cont"
>
<view class="prod-detail">
<view class="prod-img">
<image
v-if="!item.isPicError && item.pic"
:src="item.pic.indexOf('http') === -1 ? picDomain + item.pic : item.pic"
@error="onHandlePicError(item)"
/>
<image
v-else
src="/static/images/icon/def.png"
/>
</view>
<view class="prod-inf">
<view class="prod-title">
{{ item.spuName }}
</view>
<view class="brief">
<text
v-if="orderItems.length === 1 && item.giveawayOrderItemId"
class="gift-icon"
>
赠品
</text>
<text class="sku-name">
{{ item.skuName }}
</text>
</view>
<view>
<text class="num">
×{{ item.count }}
</text>
<text
v-if="item.stationStatus === 1"
class="sku-type"
>
已核销
</text>
</view>
</view>
</view>
<!-- 组合 -->
<view
v-if="item.comboItemList && item.comboItemList.length"
class="gift-prods"
>
<view
v-for="comboItem in item.comboItemList"
:key="comboItem.orderItemId"
class="gift-item"
>
<text class="name">
组合{{ comboItem.spuName }}
</text>
<text class="num">
×{{ comboItem.count }}
</text>
</view>
</view>
<!-- / -->
<!-- 赠品多个商品时展示 -->
<view
v-if="orderItems.length > 1 && item.giveawayList && item.giveawayList.length"
class="gift-prods"
>
<view
v-for="giftItem in item.giveawayList"
:key="giftItem.orderItemId"
class="gift-item"
>
<text class="name">
赠品{{ giftItem.spuName }}
</text>
<text class="num">
×{{ giftItem.count }}
</text>
</view>
</view>
<!-- / -->
</view>
</view>
<view class="total-box">
<view class="total">
<text>{{ productNums }}件商品合计</text>
<text
v-if="actualTotal"
class="red"
>
{{ actualTotal }}
</text><text v-if="useScore&&actualTotal">
+
</text><text
v-if="useScore"
class="red"
>
{{ useScore }} 积分
</text>
</view>
</view>
</view>
</view>
<!-- 券码列表(虚拟商品核销) -->
<view
v-if="isSelfPickup === 1 && orderVirtualInfoList.length"
class="virtual-goods-code"
>
<view class="code-tit">
即将核销{{ orderVirtualInfoList.length }}
</view>
<view class="code-list">
<view class="code-item date weak">
<view class="lf">
有效期限
</view>
<view class="rg">
<text v-if="writeOffStart && !writeOffEnd">
永久有效
</text>
<text v-if="writeOffStart && writeOffEnd">
{{ writeOffStart }} {{ writeOffEnd }}
</text>
</view>
</view>
<view class="code-item date weak">
<view class="lf">
核销次数
</view>
<view class="rg">
<text v-if="writeOffNum === -1">
多次核销
</text>
<text v-if="writeOffNum === 1">
单次核销
</text>
<text v-if="writeOffNum === 0">
无需核销
</text>
</view>
</view>
</view>
<view class="code-list code-box">
<view
v-for="(item,index) in orderVirtualInfoList"
:key="index"
class="code-item"
>
券码<text v-if="orderVirtualInfoList.length > 1">
{{ index+1 }}
</text>
<text>{{ item.writeOffCode }}</text>
</view>
</view>
</view>
<!-- 全部留言(虚拟商品核销) -->
<view
v-if="!isSelfPickup && virtualRemark && virtualRemark.length"
class="virtual-goods-code"
>
<view class="code-tit">
全部留言
</view>
<view class="code-list">
<view
v-for="(item,index) in virtualRemark"
:key="index"
class="code-item weak"
>
{{ item.name }}&nbsp;&nbsp;&nbsp;&nbsp;{{ item.value }}
</view>
</view>
</view>
<!-- 订单备注 -->
<view
v-if="remarks"
class="order-remarks"
>
<text class="remarks-title">
订单备注
</text>
<text class="remarks-txt">
{{ remarks }}
</text>
</view>
<!-- 提货按钮 -->
<view
v-if="!requestPageError"
:class="['pick-btn']"
@tap="pickGood"
>
{{ isSelfPickup===0 ? '确认取件' : '确认核销' }}
</view>
</view>
</template>
<script setup>
const picDomain = import.meta.env.VITE_APP_RESOURCES_URL //
let pickCode = '' //
const shopName = ref('') //
const status = ref('') // 1: 2: 3: 4: 5: 6:
let orderNumber = '' //
const stationUserName = ref('') //
const stationUserMobile = ref('') //
const stationAddress = ref('') //
const productNums = ref(0)//
const actualTotal = ref(0)//
const useScore = ref(0) //
const orderList = ref([]) //
const remarks = ref('') //
let pageType = 1 // 1 2
const isSelfPickup = ref(0) //
const orderVirtualInfoList = ref([]) //
const couponUsers = [] //
const virtualRemark = ref([]) // -
const writeOffStart = ref(null) //
const writeOffEnd = ref(null)
const writeOffNum = ref(0) // -1 1 0
const requestPageError = ref(true) //
let timer = ''
const orderItems = ref([])
/* 生命周期函数--监听页面加载 */
onLoad((options) => {
//
if (options.pickCode) {
pickCode = options.pickCode
} else {
uni.showModal({
title: '提示',
content: '该提货码,没有对应订单',
showCancel: false,
confirmText: '确定',
success: (res) => {
if (res.confirm) {
uni.redirectTo({
url: '/pages/index/index'
})
}
}
})
return
}
// 1 2
pageType = Number(options.pageType)
})
/* 生命周期函数--监听页面显示 */
onShow(() => {
if (pickCode) {
onGetPickGoodInf()
}
})
/**
* 获取核销码信息
*/
const onGetPickGoodInf = () => {
uni.showLoading()
http.request({
url: '/mall4cloud_order/station/get_station_order_by_code',
method: 'GET',
data: {
code: pickCode
}
}).then(({ data }) => {
if (Object.keys(data).length > 0) {
//
if (data.orderSelfStationVO) {
stationUserName.value = data.orderSelfStationVO.stationUserName
stationUserMobile.value = data.orderSelfStationVO.stationUserMobile
stationAddress.value = data.orderSelfStationVO.stationAddress
isSelfPickup.value = 0
}
//
if (data.orderVirtualInfoList) {
isSelfPickup.value = 1
orderVirtualInfoList.value = data.orderVirtualInfoList
virtualRemark.value = data.virtualRemark ? JSON.parse(data.virtualRemark) : []
writeOffStart.value = data.writeOffStart
writeOffEnd.value = data.writeOffEnd
writeOffNum.value = parseInt(data.writeOffNum)
if (virtualRemark.value && virtualRemark.value.length) {
virtualRemark.value = virtualRemark.value.filter(el => el.value)
}
//
if (!orderVirtualInfoList.value.find(el => el.writeOffCode === pickCode) && pickCode === data.orderNumber && pageType === 2) {
pageType = 1
}
}
data.orderItems.forEach(item => {
useScore.value += item.useScore
})
shopName.value = data.shopName
status.value = data.status
orderNumber = data.orderId
productNums.value = data.allCount
actualTotal.value = data.actualTotal / 100
orderItems.value = data.orderItems
remarks.value = data.remarks
requestPageError.value = false
orderList.value = data.orderItems
//
if (data.orderItems && data.orderItems.length === 1 && data.orderItems[0].giveawayList && data.orderItems[0].giveawayList.length
) {
orderList.value = [...data.orderItems, ...data.orderItems[0].giveawayList]
}
} else {
requestPageError.value = true
uni.showModal({
title: '提示',
content: '没有该货物信息,请确认登录账号是否正确',
showCancel: false,
confirmText: '确定',
success: (data) => {
if (data.confirm) {
uni.redirectTo({
url: '/pages/index/index'
})
}
}
})
}
uni.hideLoading()
}).catch(err => {
uni.hideLoading()
requestPageError.value = true
uni.showModal({
title: '提示',
content: err.msg,
showCancel: false,
confirmText: '确定',
success: (err) => {
if (err.confirm) {
uni.redirectTo({
url: '/pages/index/index'
})
}
}
})
})
}
/**
* 确认核销
*/
const pickGood = () => {
if (requestPageError.value) {
return
}
let title = ''
// 1status==2
// 2status==3(5)
if ((isSelfPickup.value === 0 && status.value === 2) || (isSelfPickup.value === 1 && (status.value === 3 || status.value === 5 || status.value === 8)) || (isSelfPickup.value === 2 && couponUsers[0].status.value === 1)) {
const url = isSelfPickup.value === 0 ? '/mall4cloud_order/station/order_station_by_order_id' : '/mall4cloud_order/station/order_write_off_by_order_id'
const code = isSelfPickup.value === 0 ? orderNumber : { orderId: orderNumber }
// writeOffCodewriteOffCode
if (pageType === 2 && isSelfPickup.value !== 0) {
code.writeOffCode = pickCode
}
uni.showModal({
title: '提示',
content: !isSelfPickup.value ? '是否确认取件' : '是否确认核销',
cancelText: '取消',
confirmText: '确定',
success: (res) => {
if (res.confirm) {
uni.showLoading()
http.request({
url,
method: 'PUT',
data: code
}).then(() => {
uni.showToast({
title: isSelfPickup.value === 0 ? '取件成功' : '核销成功',
icon: 'success'
})
timer = setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index'
})
}, 800)
uni.hideLoading()
}).catch(err => {
uni.showToast({
title: err.data.msg,
icon: 'none'
})
uni.hideLoading()
})
}
}
})
} else {
if (status.value === 1) {
title = !isSelfPickup.value ? '订单待支付,请支付后再来取货' : '订单待支付,请先完成支付'
} else if ((!isSelfPickup.value && (status.value === 3 || status.value === 5)) || status.value === 4 || (isSelfPickup.value === 2 && couponUsers[0].status.value === 2)) {
title = !isSelfPickup.value ? '订单已取货' : '订单已核销'
} else if (status.value === 6) {
title = '订单已取消'
} else if (status.value === 7) {
title = '订单未成团,不支持核销'
}
uni.showModal({
title: '提示',
content: title,
showCancel: false,
confirmText: '确定',
success: (res) => {
if (res.confirm) {
uni.redirectTo({
url: '/pages/index/index'
})
}
}
})
}
}
/**
* 图片加载失败时显示默认图片
*/
const onHandlePicError = (item) => {
item.isPicError = true
}
onUnload(() => {
if (timer) {
clearTimeout(timer)
timer = null
}
})
</script>
<style lang="scss" scoped>
@import "./scan-pick.scss";
</style>

View File

@ -0,0 +1,306 @@
.page-shop-adminsistration {
width: 100%;
height: 100%;
overflow: auto;
.msg-box { display: block;
background: #fff;
margin-bottom: 15rpx;
width: 100%;
height: 100%;
}
.msg-tit {
padding: 20rpx;
border-bottom: 1rpx solid #f2f2f2;
}
.shop-icon {
display: inline-block;
width: 40rpx;
height: 40rpx;
margin-right: 15rpx;
vertical-align: middle;
>image {
display: block;
width: 100%;
height: 100%;
}
}
.shop-msg-tit {
display: inline-block;
font-size: 32rpx;
font-weight: bold;
vertical-align: middle;
}
.msg-cont-box {
font-size: 30rpx;
padding: 25rpx 0;
margin: 0 20rpx;
border-bottom: 1rpx solid #f2f2f2;
display: flex;
}
.cont-txt {
display: inline-block;
width: 150rpx;
text-align: right;
vertical-align: middle;
margin: auto 0;
margin-right: 40rpx;
}
.cont-int {
display: inline-block;
vertical-align: middle;
width: 70%;
}
.cont-left {
display: inline-block;
width: 100rpx;
height: 60rpx;
vertical-align: middle;
padding: 0 15rpx;
border: 1rpx solid #d8dbe2;
}
.cont-right {
display: inline-block;
height: 60rpx;
vertical-align: middle;
padding: 0 15rpx;
border: 1rpx solid #d8dbe2;
}
.num-line {
display: inline-block;
width: 30rpx;
height: 2rpx;
vertical-align: middle;
background-color: #606266;
margin: 30rpx 10rpx;
}
.picker-section {
display: inline-block;
font-size: 25rpx;
vertical-align: middle;
margin-top: 2rpx;
.station-time {
display: inline-block;
width: 150rpx;
color: red;
margin-left: 8rpx;
}
.inter-time {
width: 500rpx;
font-size: 30rpx;
}
}
.cont-day {
display: inline-block;
width: 60rpx;
height: 60rpx;
vertical-align: middle;
text-align: center;
border-bottom: 1rpx solid #d8dbe2;
}
.text-day {
font-size: 18rpx;
}
.station-status {
display: inline-block;
.right-radio {
margin-left: 50rpx;
}
}
.disable {
color: #aaa;
}
.align-top {
vertical-align: top;
}
.cont-textarea {
box-sizing: border-box;
vertical-align: top;
line-height: 1.5em;
border: 1rpx solid #ececec;
border-radius: 8rpx;
padding: 10rpx 15rpx;
}
.addr {
position: relative;
}
.pca {
display: inline-block;
width: 70%;
vertical-align: middle;
}
:deep(.arrow) {
width: 25rpx;
height: 25rpx;
image {
width: 100%;
height: 100%;
}
.areaPicker {
width: 100%;
height: 100%;
}
}
.animation-element-wrapper {
display: flex;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
z-index: 999;
}
.animation-element {
display: flex;
position: fixed;
width: 100%;
height: 470rpx;
bottom: 0;
background-color: rgba(255, 255, 255, 1);
}
.right-bt {
right: 20rpx;
top: 20rpx;
position: absolute;
width: 80rpx !important;
}
.line {
display: block;
position: fixed;
height: 2rpx;
width: 100%;
margin-top: 89rpx;
background-color: #eee;
}
picker-view {
background-color: white;
padding: 0;
width: 100%;
height: 380rpx;
bottom: 0;
position: fixed;
}
picker-view-column {
view {
vertical-align: middle;
font-size: 28rpx;
line-height: 28rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
.show-location {
display: inline-block;
vertical-align: middle;
font-size: 30rpx;
line-height: 1.5em;
width: 45%;
margin-top: 2rpx;
}
.map {
float: right;
color: #ffffff;
background: #e43130;
font-size: 25rpx;
line-height: 40rpx;
height: 40rpx;
padding: 10rpx 20rpx;
border-radius: 8rpx;
margin-top: 16rpx;
vertical-align: middle;
}
.clearfix {
&::after {
display: block;
height: 0;
overflow: hidden;
content: '';
clear: both;
}
}
.upload-files {
display: inline-block;
vertical-align: top;
}
.upload-tips {
font-size: 26rpx;
color: #888888;
line-height: 2em;
margin-bottom: 15rpx;
}
.preview-img-box {
position: relative;
width: 120rpx;
height: 120rpx;
display: inline-block;
margin-bottom: 15rpx;
background: #eee;
}
.preview-logo {
width: 120rpx;
height: 120rpx;
}
image.preview-img {
width: 100%;
height: 100%;
}
.preview-img-del {
position: absolute;
top: -5rpx;
right: -5rpx;
width: 28rpx;
height: 28rpx;
}
.card-upload {
display: inline-block;
margin-right: 50rpx;
}
.card-txt {
font-size: 24rpx;
text-align: center;
color: #777;
}
.upload-icon {
display: inline-block;
width: 120rpx;
height: 120rpx;
line-height: 110rpx;
text-align: center;
border: 1rpx solid #e0e0e0;
vertical-align: top;
font-size: 90rpx;
color: #ddd;
margin-bottom: 15rpx;
}
.apply-btn {
padding: 100rpx 30rpx 150rpx 30rpx;
}
.btn {
font-size: 30rpx;
text-align: center;
background: #e43130;
padding-top: 20rpx;
padding-bottom: 20rpx;
color: #fff;
border-radius: 8rpx;
}
.foot-tips {
font-size: 28rpx;
color: #aaa;
line-height: 1.5em;
margin-top: 20rpx;
}
.audit-remark {
font-size: 26rpx;
background: #ffffcd;
color: #333;
padding: 20rpx;
}
image {
width: 100%;
height: 100%;
}
}

View File

@ -0,0 +1,525 @@
<template>
<view class="page-shop-adminsistration">
<form class="msg-box">
<view class="msg-tit">
<view class="shop-icon">
<image src="/static/images/icon/shop-icon.png" />
</view>
<view class="shop-msg-tit">
店铺管理
</view>
</view>
<!-- 自提点名称 -->
<view class="msg-cont-box">
<label class="cont-txt">门店名称</label>
<input
type="text"
class="cont-int"
:value="stationName"
maxlength="50"
placeholder="输入自提点名称"
@input="onBindStationNameInt"
>
</view>
<!-- 自提点图片 -->
<view class="msg-cont-box">
<label class="cont-txt">门店图片</label>
<!-- 上传文件 -->
<view class="upload-files align-top">
<!-- 预览图片 -->
<view
v-if="logoImg.path"
class="preview-img-box preview-logo"
>
<image
class="preview-img"
:src="logoImg.url"
mode="aspectFill"
/>
<!-- 删除 -->
<image
class="preview-img-del"
data-type="logoImg"
src="/static/images/icon/close2.png"
@tap="onRemoveImage"
/>
</view>
<!-- 上传 -->
<view
v-if="!logoImg.path "
class="upload-icon upload-logo"
data-type="logoImg"
@tap="onGetUploadImg"
>
+
</view>
</view>
<!-- 上传文件end -->
</view>
<!-- / -->
<!-- 状态 -->
<view class="msg-cont-box">
<label class="cont-txt">状态</label>
<radio-group class="station-status">
<label class="radio">
<radio
:checked="stationStatus===1"
color="#e43130"
@tap="onStatusChange(1)"
/>
</label>
<label class="radio right-radio">
<radio
:checked="stationStatus===0"
color="#e43130"
@tap="onStatusChange(0)"
/>
</label>
</radio-group>
</view>
<!-- 电话号码 -->
<view class="msg-cont-box">
<label class="cont-txt">电话号码</label>
<input
type="number"
placeholder="区号"
:value="stationOwnerAreaCode"
class="cont-left"
maxlength="5"
@input="onBindStationOwnerAreaCodeInt"
>
<view class="num-line" />
<input
type="number"
placeholder="电话/手机号码"
:value="stationOwnerPhoneValue"
class="cont-right"
maxlength="11"
@input="onBindStationOwnerPhoneInt"
>
</view>
<!-- 营业时间 -->
<view class="msg-cont-box">
<label class="cont-txt">营业时间</label>
<view class="picker-section">
<picker
mode="time"
:value="stationStartTime"
@change="onBindStartTimeChange"
>
<view class="picker">
开始<text class="station-time">
{{ tsDate(stationStartTime) }}
</text>
</view>
</picker>
</view>
<view class="picker-section">
<picker
mode="time"
:start="stationStartTime"
@change="onBindEndTimeChange"
>
<view class="picker">
结束<text class="station-time">
{{ tsDate(stationEndTime) }}
</text>
</view>
</picker>
</view>
</view>
<!-- 店铺地址 -->
<view
class="msg-cont-box addr"
@tap="translate"
>
<label class="cont-txt">所在地区</label>
<!-- 展示 -->
<view class="pca">
{{ province }} {{ city }} {{ area }}
</view>
<view class="arrow">
<area-picker
v-model:show-picker="showPicker"
v-model:value="addressValue"
:class-list="['areaPicker']"
@change="addressChange"
/>
</view>
</view>
<!-- 详细地址 -->
<view class="msg-cont-box">
<label class="cont-txt">详细地址</label>
<input
type="text"
:value="stationAddrValue"
class="cont-int"
placeholder="填写详细地址"
@input="onBindStationAddrInt"
>
</view>
<!-- 经纬度(调用微信地图获取) -->
<view class="msg-cont-box wx-map clearfix">
<view class="cont-txt">
地理位置
</view>
<view
v-if="latitude"
class="show-location"
>
<view>{{ '纬度:' + latitude }}</view>
<view>{{ '经度:' + longitude }}</view>
</view>
<view
class="map"
@tap="onChooseLocation"
>
点击获取位置
</view>
</view>
</form>
<!-- 提交申请 -->
<view class="apply-btn">
<view
class="btn"
@tap="onSubmitApply"
>
提交修改
</view>
</view>
</view>
</template>
<script setup>
import AreaPicker from '@/components/area-picker/area-picker.vue'
import util from '@/utils/util.js'
const tsDate = (value) => {
if (value) {
try {
value = value.split(':')
value.pop()
return value.join(':')
} catch {
return value
}
}
return value
}
let t = 0
const resourcesUrl = import.meta.env.VITE_APP_RESOURCES_URL
let stationId = 0 // Id
const stationStatus = ref(1) // 0: 1:
const stationName = ref('') //
const logoImg = ref({}) // logo
const stationOwnerAreaCode = ref('') //
const stationOwnerPhoneValue = ref('') // /
const stationStartTime = ref('') //
const stationEndTime = ref('') //
const provinceId = ref(0)
let cityId = 0
let areaId = 0
const province = ref('')
const city = ref('')
const area = ref('')
const stationAddrValue = ref('') //
const latitude = ref('') //
const longitude = ref('') //
const animation = ref('')
let tempFiles = null
let type = ''
const addressChange = (address) => {
province.value = address[0].areaName
city.value = address[1].areaName
area.value = address[2].areaName
provinceId.value = address[0].areaId
cityId = address[1].areaId
areaId = address[2].areaId
}
/**
* 生命周期函数--监听页面加载
*/
onLoad(async (options) => {
await onGetStationInfo(options)//
})
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady(() => {
//
animation.value = uni.createAnimation({
transformOrigin: '50% 50%',
duration: 0,
timingFunction: 'ease',
delay: 0
})
animation.value.translateY(200 + 'vh').step()
animation.value = animation.value.export()
})
/* 自提点信息 */
const onGetStationInfo = (options) => {
uni.showLoading()
http.request({
url: '/mall4cloud_order/station',
method: 'GET',
data: {}
}).then(async ({ data }) => {
const timeDate = JSON.parse(data.timeInfo)
stationId = data.stationId
stationName.value = data.stationName || ''
logoImg.value.url = import.meta.env.VITE_APP_RESOURCES_URL + data.imgUrl
logoImg.value.path = data.imgUrl
stationStatus.value = data.status
stationOwnerAreaCode.value = data.mobilePrefix
stationOwnerPhoneValue.value = data.mobile || ''
stationStartTime.value = util.formatTime(timeDate.shopTime[0]).split(' ')[1]//
stationEndTime.value = util.formatTime(timeDate.shopTime[1]).split(' ')[1]//
provinceId.value = data.provinceId
cityId = data.cityId
areaId = data.areaId
province.value = data.province
city.value = data.city
area.value = data.area
stationAddrValue.value = data.addr || ''
latitude.value = data.lat
longitude.value = data.lng
uni.hideLoading()
addressValue.value = [data.provinceId, data.cityId, data.areaId]
if (options.module && uni.getStorageSync('cloudSetStationLocationFlag')) {
afterLoc(options)
}
})
}
/**
* 获取到定位后的回调
* loc 定位信息
*/
const afterLoc = (loc) => {
if (loc && loc.module === 'locationPicker') { // postmodule'locationPicker'
stationAddrValue.value = loc.addr
latitude.value = loc.latng.split(',')[0]
longitude.value = loc.latng.split(',')[1]
util.area(loc.addr, loc.name).then(res => {
if (!res) return
const addrReplacrstr = res[0].name + res[1].name + res[2].name
stationAddrValue.value = stationAddrValue.value.replace(addrReplacrstr, '') || loc.poiname
province.value = res[0].name
city.value = res[1].name
area.value = res[2].name
provinceId.value = res[0].areaId
cityId = res[1].areaId
areaId = res[2].areaId
})
uni.setStorageSync('cloudSetStationLocationFlag', false)
}
}
/* 改变自提点状态 */
const onStatusChange = (v) => {
stationStatus.value = v
}
/**
* 请求接口传数据
*/
const onSubmitApply = () => {
if (stationName.value.trim().length < 2) {
wx.showToast({
title: '请输入至少两位数字字母汉字组成的自提点名称',
icon: 'none'
})
} else if (stationOwnerPhoneValue.value.trim().length === 0) {
wx.showToast({
title: '请输入电话号码',
icon: 'none'
})
} else if (!stationStartTime.value || !stationEndTime.value) {
wx.showToast({
title: '请选择营业时间',
icon: 'none'
})
} else if (stationStartTime.value === stationEndTime.value) {
uni.showToast({
title: '开始时间不能等于结束时间',
icon: 'none'
})
} else if (!province.value && !city.value && !area.value) {
wx.showToast({
title: '请选择所在地区',
icon: 'none'
})
} else if (stationAddrValue.value.trim().length < 2) {
wx.showToast({
title: '请输入正确的详细地址不得少于2字',
icon: 'none'
})
} else if (latitude.value === '' && longitude.value === '') {
wx.showToast({
title: '请选择地理位置',
icon: 'none'
})
} else {
let timeDate = {}
timeDate.shopTime = []
//
const date = new Date()
const fragTime = util.formatTime(date.getTime()).split(' ')[0]
timeDate.shopTime[0] = util.dateToTimestamp(fragTime + ' ' + stationStartTime.value)
timeDate.shopTime[1] = util.dateToTimestamp(fragTime + ' ' + stationEndTime.value)
timeDate = JSON.stringify(timeDate)
uni.showLoading()
http.request({
url: '/mall4cloud_order/station',
method: 'PUT',
data: {
stationId,
stationName: stationName.value,
imgUrl: logoImg.value.path || '',
status: stationStatus.value,
mobilePrefix: stationOwnerAreaCode.value,
mobile: stationOwnerPhoneValue.value,
timeInfo: timeDate,
provinceId: provinceId.value,
cityId,
areaId,
province: province.value,
city: city.value,
area: area.value,
addr: stationAddrValue.value,
lat: latitude.value,
lng: longitude.value
}
}).then(() => {
uni.hideLoading()
uni.showToast({
title: '修改成功',
icon: 'success'
})
setTimeout(() => {
uni.redirectTo({
url: '/pages/index/index'
})
}, 1500)
})
}
}
/**
* 获取经纬度
*/
const key = import.meta.env.VITE_APP_MAP_KEY
const onChooseLocation = () => {
uni.setStorageSync('cloudSetStationLocationFlag', true)
window.location.replace(`https://apis.map.qq.com/tools/locpicker?search=1&type=0&backurl=${location.href}&key=${key}&referer=myapp`)
}
/**
* 获取input数据
*/
//
const onBindStationNameInt = (e) => {
stationName.value = e.detail.value
}
//
const onBindStationOwnerAreaCodeInt = (e) => {
stationOwnerAreaCode.value = e.detail.value
}
// /
const onBindStationOwnerPhoneInt = (e) => {
stationOwnerPhoneValue.value = e.detail.value
}
//
const onBindStartTimeChange = (e) => {
stationStartTime.value = e.detail.value + ':00'
stationEndTime.value = ''
}
//
const onBindEndTimeChange = (e) => {
stationEndTime.value = e.detail.value + ':00'
}
//
const onBindStationAddrInt = (e) => {
stationAddrValue.value = e.detail.value
}
/**
* 上传图片
*/
let ossList = []
const onGetUploadImg = (e) => {
type = e.target.dataset.type
wx.chooseImage({
count: 1, // 9
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: function (res) {
//
tempFiles = res.tempFiles
uni.showLoading({
mask: true
})
const fileNames = tempFiles?.map(item => item.name).join(',')
http.request({
url: '/mall4cloud_biz/ua/oss/get_batch_pre_sign_url',
method: 'GET',
data: {
fileNames // token
}
}).then(({ data }) => {
uni.hideLoading()
ossList = data
onConfirmUpload()
})
}
})
}
const onUploadSuccess = (filePath) => {
const img = {}
img.path = filePath
img.url = resourcesUrl + filePath
if (type === 'logoImg') {
logoImg.value = img
}
}
/**
* 确认上传
*/
const onConfirmUpload = () => {
if (ossList.length <= 0) {
// message('')
uni.showToast({
title: '数据异常,请刷新后重试',
icon: 'error',
duration: 2000
})
}
//
util.awsUpload(ossList, tempFiles).then(() => {
const filePath = '/' + ossList[0].dir + ossList[0].fileName
onUploadSuccess(filePath)
})
}
/**
* 删除图片
*/
const onRemoveImage = (e) => {
const type = e.target.dataset.type
if (type === 'logoImg') {
logoImg.value = {}
}
}
/**
* 移动按钮点击事件
*/
const translate = () => {
if (t === 0) {
t = 1
} else {
t = 0
}
showPicker.value = true
}
const addressValue = ref([])
const showPicker = ref(false)
onHide(() => {
showPicker.value = false
})
</script>
<style lang="scss" scoped>
@import "./shop-adminsistration.scss";
</style>

6
src/shime-uni.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
export {};
declare module "vue" {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Some files were not shown because too many files have changed in this diff Show More