Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23e4407459 | |||
| 53a1442cf7 |
245
App.vue
245
App.vue
@@ -3,57 +3,61 @@
|
||||
App.vue本身不是页面,这里不能编写视图元素,也就是没有<template>
|
||||
-->
|
||||
<script setup>
|
||||
import { onLaunch } from '@dcloudio/uni-app';
|
||||
import { getVersion } from '@/http/api/index.js';
|
||||
import appConfig from '@/config/appConfig.js';
|
||||
import { provide, onMounted } from 'vue';
|
||||
import WebsocketUtil from '@/commons/utils/websocket.js';
|
||||
import { onLaunch } from '@dcloudio/uni-app';
|
||||
import { getVersion } from '@/http/api/index.js'
|
||||
import appConfig from '@/config/appConfig.js';
|
||||
import { provide,onMounted } from 'vue';
|
||||
import WebsocketUtil from '@/commons/utils/websocket.js'
|
||||
|
||||
const websocketUtil = new WebsocketUtil(appConfig.wss, 5000); // 创建 WebSocket 工具类实例
|
||||
provide('websocketUtil', websocketUtil); // 提供给所有子组件
|
||||
onMounted(() => {
|
||||
|
||||
|
||||
});
|
||||
onLaunch(() => {
|
||||
// 非开发工具移除 console.log console.info
|
||||
if (uni.getSystemInfoSync().platform !== "devtools") {
|
||||
console.log = () => {};
|
||||
console.info = () => {};
|
||||
}
|
||||
let that = this
|
||||
uni.hideTabBar()
|
||||
// #ifdef MP-WEIXIN
|
||||
const updateManager = wx.getUpdateManager() // 小程序版本更新管理器
|
||||
updateManager.onCheckForUpdate(function(res) {
|
||||
// 请求完新版本信息的回调
|
||||
})
|
||||
updateManager.onUpdateReady(function() {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate()
|
||||
|
||||
const websocketUtil = new WebsocketUtil(appConfig.wss, 5000); // 创建 WebSocket 工具类实例
|
||||
provide('websocketUtil', websocketUtil); // 提供给所有子组件
|
||||
onMounted(() => {});
|
||||
onLaunch(() => {
|
||||
// 非开发工具移除 console.log console.info
|
||||
// if (uni.getSystemInfoSync().platform !== "devtools") {
|
||||
// console.log = () => {};
|
||||
// console.info = () => {};
|
||||
// }
|
||||
let that = this;
|
||||
uni.hideTabBar();
|
||||
// #ifdef MP-WEIXIN
|
||||
const updateManager = wx.getUpdateManager(); // 小程序版本更新管理器
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
// 请求完新版本信息的回调
|
||||
});
|
||||
updateManager.onUpdateReady(function () {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
});
|
||||
updateManager.onUpdateFailed(function () {
|
||||
// 新版本下载失败
|
||||
});
|
||||
// #endif
|
||||
// console.log("getSystemSetting==",uni.getSystemInfoSync())
|
||||
// console.log("getSystemSetting==",uni.getSystemSetting())
|
||||
|
||||
//#ifdef APP-PLUS
|
||||
//获取当前系统版本信息
|
||||
plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => {
|
||||
//请求后台接口 解析数据 对比版本
|
||||
console.log('widgetInfo==', widgetInfo);
|
||||
let type = uni.getSystemInfoSync().platform == 'ios' ? 2 : 1;
|
||||
getVersion({ source: 'manager_app', type: type })
|
||||
.then((res) => {
|
||||
console.log('selectNewApp==', res);
|
||||
console.log('version===', res.url && widgetInfo.version < res.version);
|
||||
})
|
||||
updateManager.onUpdateFailed(function() {
|
||||
// 新版本下载失败
|
||||
})
|
||||
// #endif
|
||||
// console.log("getSystemSetting==",uni.getSystemInfoSync())
|
||||
// console.log("getSystemSetting==",uni.getSystemSetting())
|
||||
|
||||
|
||||
//#ifdef APP-PLUS
|
||||
//获取当前系统版本信息
|
||||
plus.runtime.getProperty(plus.runtime.appid, widgetInfo => {
|
||||
//请求后台接口 解析数据 对比版本
|
||||
console.log("widgetInfo==",widgetInfo)
|
||||
let type = uni.getSystemInfoSync().platform == 'ios' ? 2 : 1
|
||||
getVersion({source:'manager_app',type: type}).then(res => {
|
||||
console.log("selectNewApp==",res)
|
||||
console.log("version===",res.url && widgetInfo.version < res.version)
|
||||
if (res.url && widgetInfo.version < res.version) {
|
||||
console.log('version===222');
|
||||
console.log("version===222")
|
||||
let downloadLink = res.url;
|
||||
// let downloadLink = "https://short-video.hnsiyao.cn/app/sy-duanju.apk";
|
||||
console.log(downloadLink);
|
||||
console.log(downloadLink)
|
||||
// let androidLink = res.androidWgtUrl;
|
||||
// let iosLink = res.iosWgtUrl;
|
||||
let ready = false;
|
||||
let ready = false;
|
||||
// 校验是否强制升级
|
||||
if (res.isUp == 1) {
|
||||
uni.showModal({
|
||||
@@ -61,84 +65,81 @@ onLaunch(() => {
|
||||
title: '发现新版本',
|
||||
confirmText: '立即更新',
|
||||
content: res.message,
|
||||
success: (res) => {
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading('下载中...');
|
||||
if (uni.getSystemInfoSync().platform == 'android') {
|
||||
uni.downloadFile({
|
||||
url: downloadLink,
|
||||
success: (downloadResult) => {
|
||||
if (downloadResult.statusCode === 200) {
|
||||
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, (entry) => {
|
||||
entry.getParent((_oldFile) => {
|
||||
entry.moveTo(_oldFile, '.apk', (newFilePath) => {
|
||||
console.log('newFilePath', newFilePath.fullPath);
|
||||
plus.runtime.install(
|
||||
newFilePath.fullPath,
|
||||
{ force: false },
|
||||
(d) => {
|
||||
console.log('install success...');
|
||||
plus.runtime.restart();
|
||||
success: downloadResult => {
|
||||
if (downloadResult.statusCode === 200) {
|
||||
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, entry => {
|
||||
entry.getParent(_oldFile=>{
|
||||
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
||||
console.log('newFilePath',newFilePath.fullPath)
|
||||
plus.runtime.install(newFilePath.fullPath, { force: false },
|
||||
d => {
|
||||
console .log( 'install success...' );
|
||||
plus.runtime .restart();
|
||||
},
|
||||
(e) => {
|
||||
console.log(e);
|
||||
console.error('install fail...');
|
||||
e => {
|
||||
console.log(e)
|
||||
console .error( 'install fail...' );
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (uni.getSystemInfoSync().platform == 'ios') {
|
||||
plus.runtime.openURL(downloadLink, function (res) {});
|
||||
plus.runtime.openURL(downloadLink, function( res) {});
|
||||
}
|
||||
} else if (res.cancel) {
|
||||
console.log('取消');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
} else {
|
||||
uni.showModal({
|
||||
title: '发现新版本',
|
||||
confirmText: '立即更新',
|
||||
cancelText: '下次更新',
|
||||
content: res.message,
|
||||
success: (res) => {
|
||||
content: res.message,
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading('下载中...');
|
||||
if (uni.getSystemInfoSync().platform == 'android') {
|
||||
uni.downloadFile({
|
||||
url: downloadLink,
|
||||
success: (downloadResult) => {
|
||||
success: downloadResult => {
|
||||
if (downloadResult.statusCode == 200) {
|
||||
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, (entry) => {
|
||||
entry.getParent((_oldFile) => {
|
||||
entry.moveTo(_oldFile, '.apk', (newFilePath) => {
|
||||
console.log('newFilePath', newFilePath.fullPath);
|
||||
plus.runtime.install(
|
||||
newFilePath.fullPath,
|
||||
{ force: false },
|
||||
(d) => {
|
||||
console.log('install success...');
|
||||
plus.runtime.restart();
|
||||
},
|
||||
(e) => {
|
||||
console.log(e);
|
||||
console.error('install fail...');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
plus.io.resolveLocalFileSystemURL(downloadResult.tempFilePath, entry => {
|
||||
entry.getParent(_oldFile=>{
|
||||
entry.moveTo(_oldFile,'.apk',newFilePath=>{
|
||||
console.log('newFilePath',newFilePath.fullPath)
|
||||
plus.runtime.install(newFilePath.fullPath, { force: false },
|
||||
d => {
|
||||
console.log('install success...');
|
||||
plus.runtime.restart();
|
||||
},
|
||||
e => {
|
||||
console.log(e)
|
||||
console.error('install fail...');
|
||||
}
|
||||
);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (uni.getSystemInfoSync().platform == 'ios') {
|
||||
plus.runtime.openURL(downloadLink, function (res) {});
|
||||
plus.runtime.openURL(downloadLink, function( res) {});
|
||||
}
|
||||
} else if (res.cancel) {
|
||||
console.log('取消');
|
||||
@@ -147,63 +148,23 @@ onLaunch(() => {
|
||||
});
|
||||
}
|
||||
}
|
||||
}).catch((res)=>{
|
||||
console.log(res)
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
});
|
||||
|
||||
// #endif
|
||||
|
||||
});
|
||||
|
||||
// #endif
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'uview-plus/index.scss';
|
||||
/** 每个页面公共css */
|
||||
@import '@/commons/style/global.scss';
|
||||
@import '@/commons/style/common.scss';
|
||||
|
||||
/** 每个页面公共css */
|
||||
@import '@/commons/style/global.scss';
|
||||
@import '@/commons/style/common.scss';
|
||||
/** uni 组件样式覆盖 */
|
||||
@import '@/commons/style/uni-overwrite.scss';
|
||||
|
||||
/** uni 组件样式覆盖 */
|
||||
@import '@/commons/style/uni-overwrite.scss';
|
||||
|
||||
// 优惠券插槽公用样式
|
||||
.my-coupon-item-list {
|
||||
padding-bottom: 28upx;
|
||||
.my-coupon-item-item {
|
||||
&:not(:first-child) {
|
||||
margin-top: 28upx;
|
||||
}
|
||||
.my-coupon-item-row-wrap {
|
||||
.row {
|
||||
display: flex;
|
||||
&:not(:first-child) {
|
||||
margin-top: 12upx;
|
||||
}
|
||||
.title {
|
||||
width: 180upx;
|
||||
font-size: 28upx;
|
||||
color: #666;
|
||||
}
|
||||
.info {
|
||||
flex: 1;
|
||||
font-size: 28upx;
|
||||
color: #333;
|
||||
padding-left: 28upx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// u-form card专用样式
|
||||
.u-form-card {
|
||||
background-color: #fff;
|
||||
border-radius: 20upx;
|
||||
padding: 0 28upx 14upx;
|
||||
margin-bottom: 28upx;
|
||||
:deep(.u-form-item__body__left__content__label.data-v-b4fd400b) {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@import "uview-plus/index.scss";
|
||||
</style>
|
||||
@@ -308,9 +308,6 @@ text {
|
||||
.border-r-12{
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.border-r-16{
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.border-r-18{
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
@@ -358,18 +355,6 @@ text {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.fixed-bottom{
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 30rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
z-index: 999;
|
||||
/* #ifdef H5 */
|
||||
padding-bottom: 28rpx;
|
||||
/* #endif */
|
||||
}
|
||||
.lh30 {
|
||||
line-height: 30px;
|
||||
}
|
||||
@@ -418,60 +403,4 @@ text {
|
||||
|
||||
::v-deep .u-m-t-16 .u-textarea{
|
||||
border-width: 1px!important;
|
||||
}
|
||||
.font-700{
|
||||
font-weight: 700;
|
||||
}
|
||||
.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
.bg-f7{
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
.default-box-padding{
|
||||
padding: 32rpx 28rpx;
|
||||
}
|
||||
.default-box-radius{
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.default-box-x-padding{
|
||||
padding-left: 28rpx;
|
||||
padding-right: 28rpx;
|
||||
}
|
||||
.default-box-y-padding{
|
||||
padding-top: 32rpx;
|
||||
padding-bottom: 32rpx;
|
||||
}
|
||||
$height: 70rpx;
|
||||
|
||||
.number-box {
|
||||
font-size: 28rpx;
|
||||
padding: 0 26rpx;
|
||||
border-radius: 6rpx 0 0 6rpx;
|
||||
border-top: 2rpx solid #d9d9d9;
|
||||
border-bottom: 2rpx solid #d9d9d9;
|
||||
border-left: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
height: $height;
|
||||
flex: 1;
|
||||
line-height: $height;
|
||||
}
|
||||
.unit {
|
||||
display: flex;
|
||||
padding: 0 38rpx;
|
||||
height: $height;
|
||||
line-height: $height;
|
||||
align-items: center;
|
||||
border-radius: 0 6rpx 6rpx 0;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #f7f7fa;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.u-col-baseline{
|
||||
align-items: baseline;
|
||||
}
|
||||
.text-right{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ $v-b-color-ed: #ededed;
|
||||
|
||||
//common.scss 分包页面以及组件里所用的颜色
|
||||
$my-main-color:#318AFE;
|
||||
$my-red-color:#FE4F1E;
|
||||
$my-red-color:#F02C45;
|
||||
|
||||
//my-components
|
||||
$u-main-color: #303133;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @site https://www.jeepay.vip
|
||||
* @date 2021/5/16 17:35
|
||||
*/
|
||||
// import { SM4 } from 'gm-crypto'
|
||||
import { SM4 } from 'gm-crypto'
|
||||
import appConfig from '@/config/appConfig.js'
|
||||
|
||||
let HEX_KEY = null
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
export function encrypt(txt) {
|
||||
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
|
||||
|
||||
return txt
|
||||
// 密钥对生成 http://web.chacuo.net/netrsakeypair
|
||||
|
||||
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' +
|
||||
'2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ=='
|
||||
|
||||
// 加密
|
||||
export function encrypt(txt) {
|
||||
const encryptor = new JSEncrypt()
|
||||
encryptor.setPublicKey(publicKey) // 设置公钥
|
||||
return encryptor.encrypt(txt) // 对需要加密的数据进行加密
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ const model = {
|
||||
|
||||
setLogin(res){
|
||||
uni.setStorageSync('shopInfo',res.shopInfo)
|
||||
uni.setStorageSync('shopStaff',res.shopStaff)
|
||||
uni.setStorageSync('loginType',res.loginType)
|
||||
if(res.loginType=='1'){
|
||||
// uni.setStorageSync('merchantName',user.createBy||user.updateBy)
|
||||
|
||||
@@ -5,191 +5,161 @@
|
||||
@date 2022/11/16 11:45
|
||||
-->
|
||||
<template>
|
||||
<!-- 宫格类型 -->
|
||||
<template v-if="props.type == 'grid'">
|
||||
<view class="grid-card-wrapper" :style="{ margin: calcPadding(), '--space-w': space + 'rpx' }">
|
||||
<block v-for="(v, i) in navListComputed" :key="i">
|
||||
<view class="card-main" :style="{ margin: calcMargin(), '--radius-size': radiusSize + 'rpx' }"
|
||||
hover-class="touch-hover" hover-stay-time="150"
|
||||
:class="{ 'card-big-main': navListComputed.length == 4 || navListComputed.length <= 2 }"
|
||||
@tap="clickFunc(v)">
|
||||
<image :src="v.icon" mode="scaleToFill" />
|
||||
<view class="card-title">{{ v.title }}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 宫格类型 -->
|
||||
<template v-if="props.type == 'grid'">
|
||||
<view class="grid-card-wrapper" :style="{ margin: calcPadding(), '--space-w': space + 'rpx' }">
|
||||
<block v-for="(v, i) in navListComputed" :key="i">
|
||||
<view
|
||||
class="card-main"
|
||||
:style="{ margin: calcMargin(), '--radius-size': radiusSize + 'rpx' }"
|
||||
hover-class="touch-hover"
|
||||
hover-stay-time="150"
|
||||
:class="{ 'card-big-main': navListComputed.length == 4 || navListComputed.length <= 2 }"
|
||||
@tap="clickFunc(v)"
|
||||
>
|
||||
<image :src="v.icon" mode="scaleToFill" />
|
||||
<view class="card-title">{{ v.title }}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 列表类型 -->
|
||||
<template v-if="props.type == 'list'">
|
||||
<view class="list-nav-wrapper" :style="{ '--radius-size': radiusSize + 'rpx' }">
|
||||
<block v-for="(v, i) in navListComputed" :key="i">
|
||||
<view class="nav-main" hover-class="touch-hover" hover-stay-time="150" @tap="clickFunc(v)">
|
||||
<image :src="v.icon" mode="scaleToFill" />
|
||||
<view class="nav-text">{{ v.title }}</view>
|
||||
<image class="nav-right" src="/static/iconImg/icon-arrow-right.svg" mode="scaleToFill" />
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 列表类型 -->
|
||||
<template v-if="props.type == 'list'">
|
||||
<view class="list-nav-wrapper" :style="{ '--radius-size': radiusSize + 'rpx' }">
|
||||
<block v-for="(v, i) in navListComputed" :key="i">
|
||||
<view class="nav-main" hover-class="touch-hover" hover-stay-time="150" @tap="clickFunc(v)">
|
||||
<image :src="v.icon" mode="scaleToFill" />
|
||||
<view class="nav-text">{{ v.title }}</view>
|
||||
<image class="nav-right" src="/static/iconImg/icon-arrow-right.svg" mode="scaleToFill" />
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useMenusStore
|
||||
} from '@/store/menus.js'
|
||||
const menusStore = useMenusStore()
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
computed
|
||||
} from "vue"
|
||||
import go from "@/commons/utils/go.js"
|
||||
import ent from '@/commons/utils/ent.js'
|
||||
import { reactive, ref, computed } from "vue"
|
||||
import go from "@/commons/utils/go.js"
|
||||
import ent from '@/commons/utils/ent.js'
|
||||
import {
|
||||
hasPermission
|
||||
} from '@/commons/utils/hasPermission.js';
|
||||
// 定义组件参数
|
||||
const props = defineProps({
|
||||
//显示类型: 支持 grid-宫格 list-列表
|
||||
type: {
|
||||
type: String,
|
||||
default: "list"
|
||||
},
|
||||
// 定义组件参数
|
||||
const props = defineProps({
|
||||
//显示类型: 支持 grid-宫格 list-列表
|
||||
type: { type: String, default: "list" },
|
||||
|
||||
// 圆角矩形大小 为0 则 无圆角
|
||||
radiusSize: {
|
||||
type: Number,
|
||||
default: 32
|
||||
},
|
||||
// 圆角矩形大小 为0 则 无圆角
|
||||
radiusSize: { type: Number, default: 32 },
|
||||
|
||||
//间隙类型: 仅grid-宫格时生效, 支持 0 和 25
|
||||
space: {
|
||||
type: Number,
|
||||
default: 25
|
||||
},
|
||||
//间隙类型: 仅grid-宫格时生效, 支持 0 和 25
|
||||
space: { type: Number, default: 25 },
|
||||
|
||||
// 导航列表, 格式:{ icon, title, pageUrl, clickFunc, entId }
|
||||
navList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
})
|
||||
// 导航列表, 格式:{ icon, title, pageUrl, clickFunc, entId }
|
||||
navList: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
// 点击事件
|
||||
async function clickFunc(nav) {
|
||||
if (nav.pageUrl == "PAGES_DATA_SUMMARY") {
|
||||
let res = await hasPermission('允许查看经营数据')
|
||||
if (!res) return
|
||||
}
|
||||
// 包含回调事件
|
||||
if (nav.clickFunc) {
|
||||
return nav.clickFunc(nav)
|
||||
}
|
||||
|
||||
// 包含URL
|
||||
if (nav.pageUrl) {
|
||||
return go.to(nav.pageUrl)
|
||||
}
|
||||
// 点击事件
|
||||
async function clickFunc(nav) {
|
||||
if(nav.pageUrl=="PAGES_SALES_SUMMARY"){
|
||||
let res =await hasPermission('允许查看经营数据')
|
||||
if(!res) return
|
||||
}
|
||||
const calcPadding = () => `${50 - props.space}rpx 35rpx 50rpx ${35 - props.space}rpx`
|
||||
const calcMargin = () => `${props.space}rpx 0 0 ${props.space}rpx`
|
||||
// 包含回调事件
|
||||
if (nav.clickFunc) {
|
||||
return nav.clickFunc(nav)
|
||||
}
|
||||
|
||||
// 包含URL
|
||||
if (nav.pageUrl) {
|
||||
return go.to(nav.pageUrl)
|
||||
}
|
||||
}
|
||||
const calcPadding = () => `${50 - props.space}rpx 35rpx 50rpx ${35 - props.space}rpx`
|
||||
const calcMargin = () => `${props.space}rpx 0 0 ${props.space}rpx`
|
||||
|
||||
|
||||
// 计算属性
|
||||
let navListComputed = computed(() => {
|
||||
// return props.navList.filter(r => hasEnt(r.entId))
|
||||
// return props.navList.filter(r => {
|
||||
// if (r.hasOwnProperty('visiable')) {
|
||||
// return r.visiable
|
||||
// } else {
|
||||
// return true
|
||||
// }
|
||||
// })
|
||||
return props.navList.filter(r => {
|
||||
return menusStore.menuList.find(menu=>menu.pageId==r.pageUrl)
|
||||
})
|
||||
})
|
||||
// 计算属性
|
||||
let navListComputed = computed(() => {
|
||||
return props.navList.filter(r => hasEnt(r.entId))
|
||||
})
|
||||
|
||||
function hasEnt(entId) {
|
||||
|
||||
// 不包含: 说明无需隐藏
|
||||
if (!entId) {
|
||||
return true
|
||||
}
|
||||
return ent.has(entId)
|
||||
function hasEnt(entId){
|
||||
|
||||
// 不包含: 说明无需隐藏
|
||||
if(!entId){
|
||||
return true
|
||||
}
|
||||
return ent.has(entId)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid-card-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.card-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 25rpx 0 0 25rpx;
|
||||
width: calc(33.3% - var(--space-w));
|
||||
height: 210rpx;
|
||||
border-radius: var(--radius-size);
|
||||
background-color: $J-bg-ff;
|
||||
.grid-card-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background-color: $v-color-bgrey;
|
||||
padding-top: 25rpx;
|
||||
.card-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 25rpx 0 0 25rpx;
|
||||
width: calc(33.3% - var(--space-w));
|
||||
height: 210rpx;
|
||||
border-radius: var(--radius-size);
|
||||
background-color: $J-bg-ff;
|
||||
image {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
.card-title {
|
||||
margin-top: 22rpx;
|
||||
color: $J-color-t80;
|
||||
font-size: $J-f-size30;
|
||||
}
|
||||
}
|
||||
.card-big-main {
|
||||
width: calc(50% - var(--space-w));
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
.list-nav-wrapper {
|
||||
margin: 0 auto;
|
||||
width: 680rpx;
|
||||
border-radius: var(--radius-size);
|
||||
overflow: hidden;
|
||||
|
||||
.card-title {
|
||||
margin-top: 22rpx;
|
||||
color: $J-color-t80;
|
||||
font-size: $J-f-size30;
|
||||
}
|
||||
}
|
||||
|
||||
.card-big-main {
|
||||
width: calc(50% - var(--space-w));
|
||||
}
|
||||
}
|
||||
|
||||
.list-nav-wrapper {
|
||||
margin: 0 auto;
|
||||
width: 680rpx;
|
||||
border-radius: var(--radius-size);
|
||||
overflow: hidden;
|
||||
|
||||
.nav-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 30rpx;
|
||||
height: 120rpx;
|
||||
background-color: $J-bg-ff;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
vertical-align: text-bottom;
|
||||
margin: 0 20rpx 0 10rpx;
|
||||
}
|
||||
|
||||
.nav-text {
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
margin: 0;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-setup {
|
||||
margin: 30rpx auto;
|
||||
width: 680rpx;
|
||||
border-radius: $J-b-r32;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.nav-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 30rpx;
|
||||
height: 120rpx;
|
||||
background-color: $J-bg-ff;
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
vertical-align: text-bottom;
|
||||
margin: 0 20rpx 0 10rpx;
|
||||
}
|
||||
.nav-text {
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.nav-right {
|
||||
margin: 0;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
}
|
||||
.nav-setup {
|
||||
margin: 30rpx auto;
|
||||
width: 680rpx;
|
||||
border-radius: $J-b-r32;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#时间范围选择器
|
||||
#### 参数文档
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 其他 |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| show | 显示选择器 | Boolean | false | - |
|
||||
| defaultDate | 默认日期 | String | - | 不传则默认今天 |
|
||||
| minYear | 最小年份 | Number | 1990 | - |
|
||||
| themeColor | 主题色 | String | #43b983 | - |
|
||||
| startText | 开始时间文字 | String | 开始时间 | - |
|
||||
| endText | 结束时间文字 | String | 结束时间 | - |
|
||||
|
||||
#### case
|
||||
```vue
|
||||
<template>
|
||||
<view style="padding: 30rpx;">
|
||||
<view style="margin-top: 30rpx" @click="show=true">
|
||||
显示日期选择器
|
||||
</view>
|
||||
<view style="margin-top: 30rpx">
|
||||
所选日期 {{ date.join(',') }}
|
||||
</view>
|
||||
<dateRangePicker
|
||||
:show="show"
|
||||
:minYear="2022"
|
||||
@close="show=false"
|
||||
@confirm="confirm"
|
||||
>
|
||||
</dateRangePicker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dateRangePicker from '@/components/date-range-picker/date-range-picker.vue'
|
||||
export default {
|
||||
components: {dateRangePicker},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
date: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confirm(v) {
|
||||
console.log(v);
|
||||
this.date = v
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
```
|
||||
@@ -1,342 +0,0 @@
|
||||
<template>
|
||||
<view :class="{'remark':show}" :style="{'--theme-color': themeColor}" @click="close" @touchmove.stop.prevent="returnHandle">
|
||||
<view class="picker-box" :class="{show: show}">
|
||||
<view class="operate-box" @touchmove.stop.prevent="returnHandle" @tap.stop="returnHandle">
|
||||
<view @click="touchSelect(0)" class="time-item" :style="{color:touchIndex?'#303030':themeColor}">
|
||||
<view class="label">{{ startText }}</view>
|
||||
<view class="date">{{ resultDate[0] }}</view>
|
||||
</view>
|
||||
<view>至</view>
|
||||
<view @click="touchSelect(1)" class="time-item" :style="{color:touchIndex?themeColor:'#303030'}">
|
||||
<view class="label">{{ endText }}</view>
|
||||
<view class="date">{{ resultDate[1] }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<picker-view
|
||||
:value="pickerValue"
|
||||
@change="pickerChange"
|
||||
class="picker-view"
|
||||
:immediate-change="true"
|
||||
indicator-class="select-line"
|
||||
:indicator-style="indicatorStyle"
|
||||
mask-style="background: transparent"
|
||||
@tap.stop="returnHandle"
|
||||
>
|
||||
<picker-view-column class="column-left">
|
||||
<view class="picker-item" :class="index == pickerValue[0] ? 'picker-select' : ''" v-for="(item, index) in years" :key="index">
|
||||
{{ item }}年
|
||||
</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="column-center">
|
||||
<view class="picker-item" :class="index == pickerValue[1] ? 'picker-select' : ''" v-for="(item, index) in months" :key="index">
|
||||
{{ item }}月
|
||||
</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="column-right" v-if="days.length > 0">
|
||||
<view class="picker-item" :class="index == pickerValue[2] ? 'picker-select' : ''" v-for="(item, index) in days" :key="index">
|
||||
{{ item }}日
|
||||
</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<view class="button-group">
|
||||
<view class="item cancel" @click.stop="close">取消</view>
|
||||
<view class="item confirm" @click.stop="pickerConfirm">确认</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
const date = new Date();
|
||||
const years = [];
|
||||
const currentYear = date.getFullYear();
|
||||
const months = [];
|
||||
const currentMonth = date.getMonth() + 1;
|
||||
const currentDay = date.getDate();
|
||||
|
||||
export default {
|
||||
name: 'dateRangePicker',
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultDate: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
minYear: {
|
||||
type: Number,
|
||||
default: 1990,
|
||||
},
|
||||
themeColor: {
|
||||
type: String,
|
||||
default: '#43b983'
|
||||
},
|
||||
startText: {
|
||||
type: String,
|
||||
default: '开始时间'
|
||||
},
|
||||
endText: {
|
||||
type: String,
|
||||
default: '结束时间'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
for (let i = this.minYear; i <= currentYear; i++) {
|
||||
years.push(i);
|
||||
}
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
months.push(this.padStart(i));
|
||||
}
|
||||
return {
|
||||
indicatorStyle: `height: ${uni.upx2px(84)}px`,
|
||||
touchIndex: 0,
|
||||
year: currentYear,
|
||||
month: currentMonth,
|
||||
day: currentDay,
|
||||
years,
|
||||
months,
|
||||
days: [],
|
||||
pickerValue: [],
|
||||
resultDate: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setDate()
|
||||
},
|
||||
methods: {
|
||||
returnHandle() {},
|
||||
setDate() {
|
||||
if (this.defaultDate.length > 0) {
|
||||
const date = this.defaultDate[0]
|
||||
this.resultDate = this.defaultDate
|
||||
this.setPicker(date)
|
||||
} else {
|
||||
const month = this.month.toString().padStart(2, 0)
|
||||
const day = this.day.toString().padStart(2, 0)
|
||||
const nowTime = `${this.year}-${month}-${day}`
|
||||
this.resultDate = [nowTime, nowTime]
|
||||
this.setPicker(nowTime)
|
||||
}
|
||||
},
|
||||
setPicker(date) {
|
||||
const splitVal = date.split('-')
|
||||
const year = this.years.indexOf(Number(splitVal[0]))
|
||||
const month = Number(splitVal[1]) - 1
|
||||
const day = Number(splitVal[2]) - 1
|
||||
this.pickerChange({
|
||||
detail: {
|
||||
value: [year, month, day]
|
||||
}
|
||||
})
|
||||
},
|
||||
touchSelect(val) {
|
||||
const date = this.resultDate[val]
|
||||
this.touchIndex = val
|
||||
this.setPicker(date)
|
||||
},
|
||||
getDateTime(date) {
|
||||
const year = this.years[date[0]]
|
||||
const month = this.months[Number(date[1])] || this.padStart(currentMonth)
|
||||
const day = this.days[Number(date[2])] || this.padStart(currentDay)
|
||||
|
||||
this.resultDate[this.touchIndex] = `${year}-${month}-${day}`
|
||||
},
|
||||
pickerChange(e) {
|
||||
const currents = e.detail.value
|
||||
|
||||
// 月份处理,限制到当前月份
|
||||
if (this.years[currents[0]] === currentYear) {
|
||||
const allmonths = JSON.parse(JSON.stringify(months))
|
||||
const m = allmonths.splice(0, currentMonth)
|
||||
this.months = m
|
||||
if(currents[1] > currentMonth - 1) {
|
||||
currents[1] = currentMonth - 1
|
||||
}
|
||||
} else {
|
||||
this.months = months
|
||||
}
|
||||
|
||||
// 日期天数处理
|
||||
let days = []
|
||||
if (currents[1] + 1 === 2) {
|
||||
if (
|
||||
((currents[0] + this.minYear) % 4 === 0 &&
|
||||
(currents[0] + this.minYear) % 100 !== 0) ||
|
||||
(currents[0] + this.minYear) % 400 === 0
|
||||
) {
|
||||
for (let i = 1; i < 30; i++) {
|
||||
days.push(this.padStart(i))
|
||||
}
|
||||
} else {
|
||||
for (let i = 1; i < 29; i++) {
|
||||
days.push(this.padStart(i))
|
||||
}
|
||||
}
|
||||
} else if ([4, 6, 9, 11].some((item) => currents[1] + 1 === item)) {
|
||||
for (let i = 1; i < 31; i++) {
|
||||
days.push(this.padStart(i))
|
||||
}
|
||||
} else if ([1, 3, 5, 7, 8, 10, 12].some((item) => currents[1] + 1 === item)) {
|
||||
for (let i = 1; i < 32; i++) {
|
||||
days.push(this.padStart(i))
|
||||
}
|
||||
}
|
||||
// 限制到当前日期
|
||||
if (this.years[currents[0]] === currentYear && this.months[currents[1]]*1 === currentMonth) {
|
||||
days = days.splice(0, currentDay)
|
||||
if(currents[2] > currentDay - 1) {
|
||||
currents[2] = currentDay - 1
|
||||
}
|
||||
}
|
||||
this.days = days
|
||||
this.pickerValue = currents
|
||||
this.getDateTime(currents)
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', false)
|
||||
},
|
||||
pickerConfirm() {
|
||||
const { resultDate } = this
|
||||
let startTime = new Date(resultDate[0]).getTime()
|
||||
let endTime = new Date(resultDate[1]).getTime()
|
||||
let nowTime = endTime
|
||||
if (startTime <= endTime && endTime <= nowTime) {
|
||||
this.$emit('confirm', resultDate)
|
||||
this.close()
|
||||
return
|
||||
}
|
||||
if (startTime > endTime) {
|
||||
uni.showToast({
|
||||
title: '开始时间应小于结束时间',
|
||||
icon: 'none',
|
||||
duration: 3500
|
||||
})
|
||||
}
|
||||
if (endTime > nowTime) {
|
||||
uni.showToast({
|
||||
title: '请正确选择时间范围',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
padStart(val) {
|
||||
return val.toString().padStart(2, 0)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep.column-left,
|
||||
::v-deep.column-center,
|
||||
::v-deep.column-right {
|
||||
.select-line {
|
||||
background: #F9FAFC;
|
||||
z-index: -1;
|
||||
&::before, &::after {
|
||||
border: none ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.column-left .select-line {
|
||||
border-radius: 42rpx 0 0 42rpx;
|
||||
}
|
||||
|
||||
::v-deep.column-right .select-line {
|
||||
border-radius: 0 42rpx 42rpx 0;
|
||||
}
|
||||
|
||||
.remark {
|
||||
position: fixed;
|
||||
z-index: 998;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.picker-box {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: all 0.3s ease;
|
||||
transform: translateY(100%);
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #FFFFFF;
|
||||
z-index: 998;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
overflow: hidden;
|
||||
padding-bottom: calc(40rpx + constant(safe-area-inset-bottom)/2) !important;
|
||||
padding-bottom: calc(40rpx + env(safe-area-inset-bottom)/2) !important;
|
||||
&.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.operate-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
padding: 34rpx 30rpx 20rpx;
|
||||
background-color: #FFFFFF;
|
||||
text-align: center;
|
||||
border-bottom: 2rpx solid #f6f6f6;
|
||||
.label {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.date {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
width: 100%;
|
||||
height: 420rpx;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.picker-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
transition: all 0.2s ease;
|
||||
height: 84rpx;
|
||||
line-height: 84rpx;
|
||||
font-size: 32rpx;
|
||||
color: rgba(94, 104, 128, 0.6);
|
||||
&.picker-select {
|
||||
color: var(--theme-color);
|
||||
font-size: 38rpx;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 30rpx;
|
||||
.item {
|
||||
width: 280rpx;
|
||||
height: 84rpx;
|
||||
text-align: center;
|
||||
line-height: 84rpx;
|
||||
border-radius: 42rpx;
|
||||
&.cancel {
|
||||
background: #f8f8f8;
|
||||
color: #333;
|
||||
}
|
||||
&.confirm {
|
||||
background: var(--theme-color);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,223 +1,201 @@
|
||||
<template>
|
||||
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
|
||||
<template #desc>
|
||||
<view class="u-text-left u-p-30 color-666">
|
||||
<view class="u-m-t-32 u-flex">
|
||||
<view>应付金额</view>
|
||||
<view class="u-m-l-32">
|
||||
{{ form.price }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-40 u-flex">
|
||||
<view>实收金额</view>
|
||||
<view class="u-m-l-32 border u-p-l-10 u-p-r-10 u-flex-1">
|
||||
<uni-easyinput
|
||||
type="number"
|
||||
@input="currentPriceInput"
|
||||
@change="currentPriceChange"
|
||||
paddingNone
|
||||
:inputBorder="false"
|
||||
v-model="form.currentPrice"
|
||||
placeholder="输入实际金额"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-54 u-flex">
|
||||
<view>优惠折扣</view>
|
||||
<view class="u-m-l-32 u-flex-1 u-flex border u-p-l-10 u-p-r-10">
|
||||
<view class="u-flex-1">
|
||||
<uni-easyinput
|
||||
type="number"
|
||||
@input="discountInput"
|
||||
@change="discountChange"
|
||||
paddingNone
|
||||
:inputBorder="false"
|
||||
v-model="form.discount"
|
||||
placeholder="输入折扣"
|
||||
></uni-easyinput>
|
||||
</view>
|
||||
<view class="u-font-32 color-333">%</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #btn>
|
||||
<view class="u-p-30">
|
||||
<view class="u-m-t-10">
|
||||
<my-button @tap="confirm" shape="circle" fontWeight="700"
|
||||
>修改</my-button
|
||||
>
|
||||
<view class="">
|
||||
<my-button @tap="close" type="cancel" bgColor="#fff"
|
||||
>取消</my-button
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</my-model>
|
||||
<my-model ref="model" :title="title" iconColor="#000" @close="resetForm">
|
||||
<template #desc>
|
||||
<view class="u-text-left u-p-30 color-666">
|
||||
<view class="u-m-t-32 u-flex ">
|
||||
<view>应付金额</view>
|
||||
<view class="u-m-l-32">
|
||||
{{form.price}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-40 u-flex ">
|
||||
<view>实收金额</view>
|
||||
<view class="u-m-l-32 border u-p-l-10 u-p-r-10 u-flex-1">
|
||||
<uni-easyinput type="number" @input="currentPriceInput" @change="currentPriceChange" paddingNone :inputBorder="false"
|
||||
v-model="form.currentPrice"
|
||||
placeholder="输入实际金额"></uni-easyinput>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-54 u-flex ">
|
||||
<view>优惠折扣</view>
|
||||
<view class="u-m-l-32 u-flex-1 u-flex border u-p-l-10 u-p-r-10">
|
||||
<view class="u-flex-1">
|
||||
<uni-easyinput type="number" @input="discountInput" @change="discountChange" paddingNone :inputBorder="false"
|
||||
v-model="form.discount"
|
||||
placeholder="输入折扣"></uni-easyinput>
|
||||
</view>
|
||||
<view class="u-font-32 color-333">%</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template #btn>
|
||||
<view class="u-p-30">
|
||||
<view class="u-m-t-10">
|
||||
<my-button @tap="confirm" shape="circle" fontWeight="700" >修改</my-button>
|
||||
<view class="">
|
||||
<my-button @tap="close" type="cancel" bgColor="#fff" >取消</my-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</my-model>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, nextTick, ref, watch } from "vue";
|
||||
import myModel from "@/components/my-components/my-model.vue";
|
||||
import myButton from "@/components/my-components/my-button.vue";
|
||||
import infoBox from "@/commons/utils/infoBox.js";
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
discount: {
|
||||
type: [Number, String],
|
||||
default: 100,
|
||||
},
|
||||
price: {
|
||||
type: [Number, String],
|
||||
default: 0,
|
||||
},
|
||||
});
|
||||
function currentPriceInput(newval) {
|
||||
form.discount = ((newval * 100) / form.price).toFixed(2);
|
||||
}
|
||||
function discountInput(newval) {
|
||||
const currentPrice = uni.$utils.isMoney((form.price * newval) / 100) * 1;
|
||||
form.currentPrice = currentPrice.toFixed(2);
|
||||
}
|
||||
function currentPriceChange(newval) {
|
||||
if (newval < 0) {
|
||||
form.currentPrice = "0.00";
|
||||
form.discount = 100;
|
||||
return infoBox.showToast("实收金额不能小于0");
|
||||
}
|
||||
console.log(props.price);
|
||||
console.log(newval);
|
||||
if (newval > props.price) {
|
||||
const currentPrice = uni.$utils.isMoney(props.price * 1);
|
||||
form.currentPrice = currentPrice.toFixed(2);
|
||||
form.discount = 0;
|
||||
return infoBox.showToast("实收金额不能大于应付金额");
|
||||
}
|
||||
}
|
||||
function discountChange(newval) {
|
||||
if (newval < 0) {
|
||||
form.currentPrice = props.price;
|
||||
form.discount = 0;
|
||||
return infoBox.showToast("优惠折扣不能小于0");
|
||||
}
|
||||
if (newval > 100) {
|
||||
form.discount = 100;
|
||||
form.currentPrice = 0;
|
||||
return infoBox.showToast("优惠折扣不能大于100");
|
||||
}
|
||||
}
|
||||
import { reactive, nextTick, ref,watch } from 'vue';
|
||||
import myModel from '@/components/my-components/my-model.vue'
|
||||
import myButton from '@/components/my-components/my-button.vue'
|
||||
import infoBox from '@/commons/utils/infoBox.js'
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
discount:{
|
||||
type: [Number,String],
|
||||
default:100
|
||||
},
|
||||
price: {
|
||||
type: [Number,String],
|
||||
default: 0
|
||||
},
|
||||
|
||||
})
|
||||
function currentPriceInput(newval){
|
||||
form.discount = (newval*100/form.price).toFixed(2)
|
||||
}
|
||||
function discountInput(newval){
|
||||
form.currentPrice= uni.$utils.isMoney(form.price*newval/100).toFixed(2)
|
||||
}
|
||||
function currentPriceChange(newval){
|
||||
if(newval<0){
|
||||
form.currentPrice = '0.00'
|
||||
form.discount=100
|
||||
return infoBox.showToast('实收金额不能小于0')
|
||||
}
|
||||
console.log(props.price)
|
||||
console.log(newval)
|
||||
if(newval > props.price){
|
||||
form.currentPrice = (uni.$utils.isMoney(props.price)*1).toFixed(2)
|
||||
form.discount=0
|
||||
return infoBox.showToast('实收金额不能大于应付金额')
|
||||
}
|
||||
}
|
||||
function discountChange(newval){
|
||||
if(newval<0){
|
||||
form.currentPrice=props.price
|
||||
form.discount=0
|
||||
return infoBox.showToast('优惠折扣不能小于0')
|
||||
}
|
||||
if(newval>100){
|
||||
form.discount=100
|
||||
form.currentPrice=0
|
||||
return infoBox.showToast('优惠折扣不能大于100')
|
||||
}
|
||||
}
|
||||
|
||||
const $form = {
|
||||
price: props.price,
|
||||
currentPrice: props.price,
|
||||
discount: 100
|
||||
}
|
||||
const form = reactive({
|
||||
...$form
|
||||
})
|
||||
watch(()=>props.price,(newval)=>{
|
||||
form.price = (newval*1).toFixed(2)
|
||||
form.currentPrice=newval
|
||||
})
|
||||
function resetForm() {
|
||||
Object.assign(form, {
|
||||
...$form
|
||||
})
|
||||
}
|
||||
|
||||
const $form = {
|
||||
price: props.price,
|
||||
currentPrice: props.price,
|
||||
discount: 100,
|
||||
};
|
||||
const form = reactive({
|
||||
...$form,
|
||||
});
|
||||
watch(
|
||||
() => props.price,
|
||||
(newval) => {
|
||||
form.price = (newval * 1).toFixed(2);
|
||||
form.currentPrice = newval;
|
||||
}
|
||||
);
|
||||
function resetForm() {
|
||||
Object.assign(form, {
|
||||
...$form,
|
||||
});
|
||||
}
|
||||
const model = ref(null)
|
||||
|
||||
const model = ref(null);
|
||||
function open() {
|
||||
model.value.open()
|
||||
form.price= (props.price*1).toFixed(2)
|
||||
form.discount=props.discount
|
||||
form.currentPrice=(props.discount*props.price/100).toFixed(2)
|
||||
console.log(form)
|
||||
}
|
||||
|
||||
function open() {
|
||||
model.value.open();
|
||||
form.price = (props.price * 1).toFixed(2);
|
||||
form.discount = props.discount;
|
||||
form.currentPrice = ((props.discount * props.price) / 100).toFixed(2);
|
||||
console.log(form);
|
||||
}
|
||||
function close() {
|
||||
model.value.close()
|
||||
}
|
||||
const emits = defineEmits(['confirm'])
|
||||
|
||||
function close() {
|
||||
model.value.close();
|
||||
}
|
||||
const emits = defineEmits(["confirm"]);
|
||||
|
||||
function confirm() {
|
||||
emits("confirm", {
|
||||
...form,
|
||||
currentPrice: Number(form.currentPrice).toFixed(2),
|
||||
});
|
||||
close();
|
||||
}
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
});
|
||||
function confirm() {
|
||||
emits('confirm',{...form,currentPrice:Number(form.currentPrice).toFixed(2)})
|
||||
close()
|
||||
}
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.border {
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
border-color: #999;
|
||||
}
|
||||
.lh34 {
|
||||
line-height: 34rpx;
|
||||
}
|
||||
.border{
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
border-color: #999;
|
||||
}
|
||||
.lh34 {
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
line-height: inherit;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
.tag {
|
||||
background-color: #fff;
|
||||
border: 1px solid #E5E5E5;
|
||||
line-height: inherit;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
|
||||
&.active {
|
||||
border-color: #e6f0ff;
|
||||
color: $my-main-color;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
border-color: #E6F0FF;
|
||||
color: $my-main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.hover-class {
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
.hover-class {
|
||||
background-color: #E5E5E5;
|
||||
}
|
||||
|
||||
.discount {
|
||||
.u-absolute {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
.discount {
|
||||
.u-absolute {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.bg1 {
|
||||
background: #f7f7fa;
|
||||
}
|
||||
.bg1 {
|
||||
background: #F7F7FA;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 0 80rpx;
|
||||
}
|
||||
.tab {
|
||||
padding: 0 80rpx;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
.border {
|
||||
border: 1px solid #E5E5E5;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
padding: 22rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
.input-box {
|
||||
padding: 22rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.placeholder-class {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
.placeholder-class {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,68 +0,0 @@
|
||||
<template>
|
||||
<view v-if="isShow">
|
||||
<view class="zhanwei" :class="[direction == 'column' ? 'zhanwei1' : '']"></view>
|
||||
|
||||
<view
|
||||
class="fixed-bottom u-flex gap-20"
|
||||
:class="[direction == 'column' ? 'u-flex-column' : '']"
|
||||
>
|
||||
<view class="u-flex-1">
|
||||
<my-button type="primary" @click="save" shape="circle">
|
||||
保存
|
||||
</my-button>
|
||||
</view>
|
||||
<view class="u-flex-1">
|
||||
<my-button bgColor="#fff" type="default" @click="cancel" shape="circle">
|
||||
取消
|
||||
</my-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
const emit = defineEmits(["save", "cancel"]);
|
||||
import { isMainShop } from "@/store/account.js";
|
||||
|
||||
const props = defineProps({
|
||||
isOpenPermission: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//方向 row横向布局 column 纵向布局
|
||||
direction: {
|
||||
type: String,
|
||||
default: "row",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const isShow = computed(() => {
|
||||
if (props.isOpenPermission) {
|
||||
return isMainShop();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
function save() {
|
||||
emit("save");
|
||||
}
|
||||
function cancel() {
|
||||
emit("cancel");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.zhanwei {
|
||||
height: 180rpx;
|
||||
}
|
||||
.zhanwei1{
|
||||
height: 240rpx;
|
||||
}
|
||||
.fixed-bottom {
|
||||
&.u-flex-column{
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,142 +0,0 @@
|
||||
<!-- 优惠券item -->
|
||||
<template>
|
||||
<view class="item">
|
||||
<view class="header">
|
||||
<text class="title" v-if="item.couponType == 5">消费赠券</text>
|
||||
<text v-else>{{ item.title }}</text>
|
||||
<text class="id">ID:{{ item.id }}</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view class="total-info">
|
||||
<view class="item">
|
||||
<text class="info">
|
||||
<template v-if="item.giveNum == -10086">无限</template>
|
||||
<template v-else>{{ item.giveNum }}</template>
|
||||
</text>
|
||||
<text class="title">总发放</text>
|
||||
</view>
|
||||
<view class="item" v-if="item.couponType == 5">
|
||||
<text class="info">{{ item.giftNum }}</text>
|
||||
<view class="title">
|
||||
<text class="t">已赠送</text>
|
||||
<text class="l" @click="toDetail(item)">详情</text>
|
||||
</view>
|
||||
</view>
|
||||
<template v-else>
|
||||
<view class="item">
|
||||
<text class="info">{{ item.giftNum }}</text>
|
||||
<text class="title">已领取</text>
|
||||
</view>
|
||||
<view class="item">
|
||||
<text class="info">{{ item.useNum }}</text>
|
||||
<text class="title">已使用</text>
|
||||
</view>
|
||||
</template>
|
||||
<view class="item">
|
||||
<text class="info">
|
||||
<template v-if="item.giveNum == -10086">无限</template>
|
||||
<template v-else>{{ item.leftNum }}</template>
|
||||
</text>
|
||||
<text class="title">剩余</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer-wrap">
|
||||
<view class="btn">
|
||||
<u-button shape="circle" @click="emits('delete', item)">删除</u-button>
|
||||
</view>
|
||||
<view class="btn">
|
||||
<u-button shape="circle" type="primary" @click="emits('editor', item)">编辑</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import go from '@/commons/utils/go.js';
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: {}
|
||||
}
|
||||
});
|
||||
|
||||
const emits = defineEmits(['delete', 'editor']);
|
||||
|
||||
// 去领取详情
|
||||
function toDetail(item) {
|
||||
go.to('PAGES_COUPON_GET_DETAIL', { couponId: item.couponGiftList[0].couponId });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item {
|
||||
background-color: #fff;
|
||||
border-radius: 20upx;
|
||||
padding: 28upx;
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.title {
|
||||
font-size: 32upx;
|
||||
color: #333;
|
||||
}
|
||||
.id {
|
||||
font-size: 24upx;
|
||||
color: #999;
|
||||
background-color: #f8f8f8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 8upx;
|
||||
border-radius: 4upx;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
margin-top: 28upx;
|
||||
padding: 20upx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 12upx;
|
||||
}
|
||||
.total-info {
|
||||
display: flex;
|
||||
.item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 12upx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
.info {
|
||||
font-weight: bold;
|
||||
font-size: 28upx;
|
||||
color: #333;
|
||||
}
|
||||
.title {
|
||||
font-size: 24upx;
|
||||
color: #999;
|
||||
display: flex;
|
||||
gap: 28upx;
|
||||
.t {
|
||||
font-size: 24upx;
|
||||
color: #999;
|
||||
}
|
||||
.l {
|
||||
font-size: 24upx;
|
||||
color: #318afe;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-wrap {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 28upx;
|
||||
.btn {
|
||||
width: 200upx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,597 +0,0 @@
|
||||
<template>
|
||||
<view class="mask" v-if="show" @tap="close">
|
||||
<view class="box" @tap.stop="nullFunction">
|
||||
<view
|
||||
class="u-flex u-relative u-row-center u-p-30 top"
|
||||
v-if="props.isArea"
|
||||
>
|
||||
<view class="font-bold u-font-32">{{ props.title }}</view>
|
||||
<view class="close" @tap="close">
|
||||
<uni-icons type="closeempty" size="24"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="u-p-30 u-flex u-flex-wrap gap-20 fastTime"
|
||||
v-if="props.isArea"
|
||||
>
|
||||
<view
|
||||
class="item"
|
||||
v-for="(item, index) in fastTime"
|
||||
:key="index"
|
||||
@tap="changeTime(item)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
<picker-view
|
||||
:immediate-change="true"
|
||||
@pickend="pickend"
|
||||
:value="value"
|
||||
@change="bindChange"
|
||||
class="picker-view"
|
||||
>
|
||||
<template v-if="props.mode === 'all' || props.mode === 'date'">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in years" :key="index"
|
||||
>{{ item }}年</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in months" :key="index"
|
||||
>{{ item }}月</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in days" :key="index"
|
||||
>{{ item }}日</view
|
||||
>
|
||||
</picker-view-column>
|
||||
</template>
|
||||
<template v-if="props.mode === 'all' || props.mode === 'time'">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in hours" :key="index"
|
||||
>{{ item }}时</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in minutes" :key="index"
|
||||
>{{ item }}分</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in seconds" :key="index"
|
||||
>{{ item }}秒</view
|
||||
>
|
||||
</picker-view-column>
|
||||
</template>
|
||||
</picker-view>
|
||||
<template v-if="props.isArea">
|
||||
<view class="u-text-center color-999">至</view>
|
||||
<picker-view
|
||||
:immediate-change="true"
|
||||
:value="value1"
|
||||
@pickend="pickend1"
|
||||
@change="bindChange1"
|
||||
class="picker-view"
|
||||
>
|
||||
<template v-if="props.mode === 'all' || props.mode === 'date'">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in years" :key="index"
|
||||
>{{ item }}年</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in months" :key="index"
|
||||
>{{ item }}月</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in days1" :key="index"
|
||||
>{{ item }}日</view
|
||||
>
|
||||
</picker-view-column>
|
||||
</template>
|
||||
<template v-if="props.mode === 'all' || props.mode === 'time'">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in hours" :key="index"
|
||||
>{{ item }}时</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in minutes" :key="index"
|
||||
>{{ item }}分</view
|
||||
>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(item, index) in seconds" :key="index"
|
||||
>{{ item }}秒</view
|
||||
>
|
||||
</picker-view-column>
|
||||
</template>
|
||||
</picker-view>
|
||||
</template>
|
||||
|
||||
<!-- 占位 -->
|
||||
<view style="height: 80px"></view>
|
||||
<template v-if="props.isArea">
|
||||
<view class="fixed_b">
|
||||
<my-button shape="circle" @tap="confirm">确定</my-button>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="fixed_b u-flex u-row-center">
|
||||
<view class="u-m-r-16">
|
||||
<my-button type="cancel" @tap="close" width="240">
|
||||
<view class="color-999">取消</view>
|
||||
</my-button>
|
||||
</view>
|
||||
<view class="u-m-l-16">
|
||||
<button @tap="confirm">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, nextTick, ref } from "vue";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
const $time = {
|
||||
// 获取今天的开始和结束时间
|
||||
getTodayTimestamps() {
|
||||
const start = dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss");
|
||||
const end = dayjs().endOf("day").format("YYYY-MM-DD HH:mm:ss");
|
||||
return { start, end, label: "今日" };
|
||||
},
|
||||
|
||||
// 获取昨天的开始和结束时间
|
||||
getYesterdayTimestamps() {
|
||||
const start = dayjs()
|
||||
.subtract(1, "day")
|
||||
.startOf("day")
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
const end = dayjs()
|
||||
.subtract(1, "day")
|
||||
.endOf("day")
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
return { start, end, label: "昨日" };
|
||||
},
|
||||
|
||||
// 获取本周的开始和结束时间
|
||||
getThisWeekTimestamps() {
|
||||
const start = dayjs().startOf("week").format("YYYY-MM-DD HH:mm:ss");
|
||||
const end = dayjs().endOf("week").format("YYYY-MM-DD HH:mm:ss");
|
||||
return { start, end, label: "本周" };
|
||||
},
|
||||
|
||||
// 获取本月的开始和结束时间
|
||||
getThisMonthTimestamps() {
|
||||
const start = dayjs().startOf("month").format("YYYY-MM-DD HH:mm:ss");
|
||||
const end = dayjs().endOf("month").format("YYYY-MM-DD HH:mm:ss");
|
||||
return { start, end, label: "本月" };
|
||||
},
|
||||
|
||||
// 获取上个月的开始和结束时间
|
||||
getThisLastMonthTimestamps() {
|
||||
const start = dayjs()
|
||||
.subtract(1, "month")
|
||||
.startOf("month")
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
const end = dayjs()
|
||||
.subtract(1, "month")
|
||||
.endOf("month")
|
||||
.format("YYYY-MM-DD HH:mm:ss");
|
||||
return { start, end, label: "上月" };
|
||||
},
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
selTime: {
|
||||
type: [String, Number],
|
||||
},
|
||||
defaultIndex: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
defaultTime: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "筛选日期时间",
|
||||
},
|
||||
isArea: {
|
||||
//是否选中范围时间
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
mode: {
|
||||
//all date time
|
||||
type: String,
|
||||
default: "time",
|
||||
},
|
||||
yearsLen: {
|
||||
type: Number,
|
||||
default: 30,
|
||||
},
|
||||
});
|
||||
const $nowDate = new Date();
|
||||
const nowDate = {
|
||||
year: $nowDate.getFullYear(),
|
||||
month: $nowDate.getMonth() + 1,
|
||||
day: $nowDate.getDate(),
|
||||
hours: $nowDate.getHours(),
|
||||
minutes: $nowDate.getMinutes(),
|
||||
seconds: $nowDate.getSeconds(),
|
||||
};
|
||||
const yearsLen = props.yearsLen;
|
||||
|
||||
function returnYears() {
|
||||
if (props.isArea) {
|
||||
return new Array(yearsLen)
|
||||
.fill(1)
|
||||
.map((v, index) => {
|
||||
return nowDate.year - index;
|
||||
})
|
||||
.reverse();
|
||||
} else {
|
||||
return new Array(yearsLen).fill(1).map((v, index) => {
|
||||
return nowDate.year - Math.floor(yearsLen / 2) + index;
|
||||
});
|
||||
}
|
||||
}
|
||||
const years = returnYears();
|
||||
|
||||
const months = new Array(12).fill(1).map((v, index) => {
|
||||
return index + 1;
|
||||
});
|
||||
const days = ref(
|
||||
new Array(getMonthArea($nowDate, "end").getDate()).fill(1).map((v, index) => {
|
||||
return index + 1;
|
||||
})
|
||||
);
|
||||
const days1 = ref(
|
||||
new Array(getMonthArea($nowDate, "end").getDate()).fill(1).map((v, index) => {
|
||||
return index + 1;
|
||||
})
|
||||
);
|
||||
const hours = new Array(24).fill(1).map((v, index) => {
|
||||
return index;
|
||||
});
|
||||
const minutes = new Array(60).fill(1).map((v, index) => {
|
||||
return index;
|
||||
});
|
||||
const seconds = new Array(60).fill(1).map((v, index) => {
|
||||
return index;
|
||||
});
|
||||
// const fastTime = reactive([{
|
||||
// title: '今日',
|
||||
// key: 'now'
|
||||
// },
|
||||
// {
|
||||
// title: '昨日',
|
||||
// key: 'prve'
|
||||
// },
|
||||
// {
|
||||
// title: '本月',
|
||||
// key: 'nowMonth'
|
||||
// },
|
||||
// {
|
||||
// title: '上月',
|
||||
// key: 'prveMonth'
|
||||
// }
|
||||
// ])
|
||||
const today = $time.getTodayTimestamps();
|
||||
const yesterday = $time.getYesterdayTimestamps();
|
||||
const thisMonth = $time.getThisMonthTimestamps();
|
||||
const thisLastMonth = $time.getThisLastMonthTimestamps();
|
||||
const fastTime = reactive([today, yesterday, thisMonth, thisLastMonth]);
|
||||
|
||||
function setPrveDay() {}
|
||||
|
||||
function setNowMoneth() {}
|
||||
|
||||
function setprveMoneth() {}
|
||||
|
||||
function setDay(start, end) {
|
||||
value.value = [start.year, start.month, start.day, 0, 0, 0];
|
||||
value1.value = [end.year, end.month, end.day, 23, 59, 59];
|
||||
}
|
||||
|
||||
function changeTime(e) {
|
||||
console.log(e);
|
||||
const start = e.start;
|
||||
const end = e.end;
|
||||
emits("confirm", {
|
||||
text: `${start}——${end}`,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
close();
|
||||
}
|
||||
let value = ref([]);
|
||||
let value1 = ref([]);
|
||||
initValue();
|
||||
|
||||
function returnFindIndex(arr) {
|
||||
const yearIndex = years.findIndex((v) => v == arr[0]);
|
||||
const monthIndex = arr[1];
|
||||
const dayIndex = arr[2] - 1;
|
||||
const hIndex = arr[3];
|
||||
const mIndex = arr[4];
|
||||
const sIndex = arr[5];
|
||||
return [yearIndex, monthIndex, dayIndex, hIndex, mIndex, sIndex];
|
||||
}
|
||||
|
||||
function initValue() {
|
||||
if (props.defaultTime.length && !props.isArea) {
|
||||
value.value = returnFindIndex(props.defaultTime);
|
||||
} else {
|
||||
const yearIndex = years.findIndex((v) => v == nowDate.year);
|
||||
value.value = [yearIndex, nowDate.month - 1, nowDate.day - 1, 0, 0, 0];
|
||||
value1.value = [yearIndex, nowDate.month - 1, nowDate.day - 1, 23, 59, 59];
|
||||
}
|
||||
}
|
||||
|
||||
let show = ref(false);
|
||||
const emits = defineEmits("close", "open", "confirm");
|
||||
|
||||
function toggle() {
|
||||
show.value = !show.value;
|
||||
if (show.value) {
|
||||
open();
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
// emits('close', false)
|
||||
}
|
||||
|
||||
function open() {
|
||||
if (typeof props.selTime === "number") {
|
||||
const d = new Date(props.selTime);
|
||||
value.value[0] = years.findIndex((v) => v === d.getFullYear());
|
||||
value.value[1] = months.findIndex((v) => v === d.getMonth()) + 1;
|
||||
value.value[2] = days.value.findIndex((v) => v === d.getDate());
|
||||
}
|
||||
show.value = true;
|
||||
// emits('open', true)
|
||||
}
|
||||
|
||||
function returnDateString(arr, isObj) {
|
||||
const year = years[arr[0]];
|
||||
const month = arr[1] + 1;
|
||||
const day = arr[2] + 1;
|
||||
const hour = ("0" + (arr[3] || 0)).slice(-2);
|
||||
const min = ("0" + (arr[4] || 0)).slice(-2);
|
||||
const sen = ("0" + (arr[5] || 0)).slice(-2);
|
||||
if (isObj) {
|
||||
return new Date(year, month, day, hour, min, sen);
|
||||
}
|
||||
return `${year}-${month}-${day} ${hour}:${min}:${sen}`;
|
||||
}
|
||||
|
||||
function confirm(e) {
|
||||
const start = returnDateString(value.value);
|
||||
const end = returnDateString(value1.value);
|
||||
if (!props.isArea) {
|
||||
emits("confirm", start);
|
||||
} else {
|
||||
emits("confirm", {
|
||||
text: `${start}——${end}`,
|
||||
start,
|
||||
end,
|
||||
});
|
||||
}
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
function returnMonthStart(arr) {
|
||||
return new Date(years[arr[0]], months[arr[1]] - 1, 1).getDate();
|
||||
}
|
||||
|
||||
function returnMonthEnd(arr) {
|
||||
return new Date(years[arr[0]], months[arr[1]], 0).getDate();
|
||||
}
|
||||
|
||||
//防抖
|
||||
function debounce(fn, wait) {
|
||||
let timeout = null;
|
||||
return function () {
|
||||
let context = this;
|
||||
let args = arguments;
|
||||
if (timeout) clearTimeout(timeout);
|
||||
let callNow = !timeout;
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null;
|
||||
}, wait);
|
||||
if (callNow) fn.apply(context, args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} isDays1 //是否是结束时间选择
|
||||
* @param {Object} arr
|
||||
*/
|
||||
function changeDays(isDays1, arr) {
|
||||
const end = returnMonthEnd(arr);
|
||||
if (end) {
|
||||
if (isDays1) {
|
||||
days1.value = new Array(end).fill(1).map((v, index) => {
|
||||
return index + 1;
|
||||
});
|
||||
} else {
|
||||
days.value = new Array(end).fill(1).map((v, index) => {
|
||||
return index + 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bindChange(e) {
|
||||
const startTotal = returnDateString(e.detail.value, true).getTime();
|
||||
const endTotal = returnDateString(value1.value, true).getTime();
|
||||
value.value = e.detail.value;
|
||||
setTimeout(() => {
|
||||
if (props.isArea) {
|
||||
value.value = startTotal > endTotal ? value1.value : e.detail.value;
|
||||
}
|
||||
debounce(changeDays(false, value.value), 100);
|
||||
}, 10);
|
||||
// nextTick(() => {
|
||||
// if (props.isArea) {
|
||||
// value.value = startTotal > endTotal ? value1.value : e.detail.value
|
||||
// }
|
||||
// console.log(value.value);
|
||||
// debounce(changeDays(false, value.value), 100)
|
||||
// })
|
||||
}
|
||||
|
||||
function bindChange1(e) {
|
||||
const startTotal = returnDateString(value.value, true).getTime();
|
||||
const endTotal = returnDateString(e.detail.value, true).getTime();
|
||||
value1.value = e.detail.value;
|
||||
nextTick(() => {
|
||||
if (props.isArea) {
|
||||
value1.value = endTotal < startTotal ? value.value : e.detail.value;
|
||||
}
|
||||
debounce(changeDays(true, value1.value), 100);
|
||||
});
|
||||
}
|
||||
|
||||
function getDayDate(date = new Date(), type) {
|
||||
const now = date;
|
||||
if (type === "start") {
|
||||
const startOfDay = new Date(
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDate()
|
||||
);
|
||||
return startOfDay;
|
||||
}
|
||||
if (type === "end") {
|
||||
const endOfDay = new Date(
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDate(),
|
||||
23,
|
||||
59,
|
||||
59,
|
||||
999
|
||||
);
|
||||
return endOfDay;
|
||||
}
|
||||
}
|
||||
|
||||
function getMonthArea(date = new Date(), type) {
|
||||
let now = date;
|
||||
let currentMonthStart = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
let currentMonthEnd = new Date(
|
||||
now.getFullYear(),
|
||||
now.getMonth() + 1,
|
||||
0,
|
||||
23,
|
||||
59,
|
||||
59,
|
||||
999
|
||||
);
|
||||
if (type === "start") {
|
||||
return currentMonthStart;
|
||||
}
|
||||
if (type === "end") {
|
||||
return currentMonthEnd;
|
||||
}
|
||||
return {
|
||||
start: currentMonthStart,
|
||||
end: currentMonthEnd,
|
||||
};
|
||||
}
|
||||
|
||||
function nullFunction() {}
|
||||
|
||||
function pickend(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
function pickend1(e) {
|
||||
console.log(e);
|
||||
}
|
||||
defineExpose({
|
||||
close,
|
||||
open,
|
||||
confirm,
|
||||
toggle,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fastTime {
|
||||
.item {
|
||||
background-color: rgb(247, 247, 247);
|
||||
padding: 6rpx 40rpx;
|
||||
border-radius: 6rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: 30rpx;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
z-index: 9999;
|
||||
background-color: rgba(51, 51, 51, 0.5);
|
||||
|
||||
.item {
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.box {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fixed_b {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 30rpx;
|
||||
z-index: 100;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
width: 750rpx;
|
||||
height: 300rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -495,7 +495,7 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
z-index: 9999;
|
||||
z-index: 999;
|
||||
background-color: rgba(51, 51, 51, .5);
|
||||
|
||||
.item {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-checkbox-group
|
||||
v-model="useType"
|
||||
placement="row"
|
||||
shape="square"
|
||||
size="28rpx"
|
||||
>
|
||||
<up-checkbox
|
||||
v-for="item in dinetyps"
|
||||
:key="item.value"
|
||||
:name="item.value"
|
||||
:label="item.label"
|
||||
:customStyle="radioCustomStyle"
|
||||
></up-checkbox>
|
||||
</up-checkbox-group>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
|
||||
|
||||
|
||||
// 可使用类型:dine堂食/pickup自取/deliv配送/express快递
|
||||
const dinetyps = [
|
||||
{
|
||||
value: "dine-in",
|
||||
label: "堂食",
|
||||
},
|
||||
{
|
||||
value: "take-out",
|
||||
label: "自取",
|
||||
},
|
||||
{
|
||||
value: "post",
|
||||
label: "配送",
|
||||
},
|
||||
{
|
||||
value: "take-away",
|
||||
label: "快递",
|
||||
},
|
||||
];
|
||||
|
||||
const props = defineProps({
|
||||
radioCustomStyle: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return { marginRight: "15px" };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const useType = defineModel({
|
||||
default: () => [],
|
||||
type: Array,
|
||||
});
|
||||
</script>
|
||||
@@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<view class="fixed-wrap" :style="{ '--num': `${numValue}px` }">
|
||||
<view class="fixed-btn" :class="[type]" id="targetRef">
|
||||
<div class="btn">
|
||||
<u-button type="primary" :color="confirmColor" :shape="shape" size="large" @click="emits('confirm')">{{ confirmText }}</u-button>
|
||||
</div>
|
||||
<div class="btn" v-if="showCancel">
|
||||
<u-button :shape="shape" size="large" @click="emits('cancel')">取消</u-button>
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, nextTick, getCurrentInstance, computed } from 'vue';
|
||||
// import { isMainShop } from '@/store/account.js';
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'vertical' // horizontal横向 vertical竖向
|
||||
},
|
||||
isOpenPermission: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '保存'
|
||||
},
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#3C9CFF'
|
||||
},
|
||||
showCancel: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'circle' // squre circle
|
||||
}
|
||||
});
|
||||
|
||||
// const isShow = computed(() => {
|
||||
// if (props.isOpenPermission) {
|
||||
// return isMainShop();
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
const numValue = computed(() => {
|
||||
let num = 0;
|
||||
if (props.type == 'vertical' && props.showCancel) {
|
||||
num = 63;
|
||||
return num;
|
||||
}
|
||||
if (props.type == 'horizontal') {
|
||||
num = 0;
|
||||
return num;
|
||||
}
|
||||
return num;
|
||||
});
|
||||
|
||||
const emits = defineEmits(['confirm', 'cancel']);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fixed-wrap {
|
||||
--height: calc(83px + var(--num) + env(safe-area-inset-bottom) / 2);
|
||||
width: 100%;
|
||||
height: var(--height);
|
||||
.fixed-btn {
|
||||
width: 100%;
|
||||
height: var(--height);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
padding: 10px 14px calc(20px + env(safe-area-inset-bottom) / 2) 10px;
|
||||
background-color: #fff;
|
||||
&.horizontal {
|
||||
display: flex;
|
||||
gap: 28upx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
&:first-child {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,52 +0,0 @@
|
||||
<template>
|
||||
<view class="conetnt">
|
||||
<div class="row">
|
||||
<u-radio-group v-model="getType">
|
||||
<u-radio :label="item.label" :name="item.value" v-for="item in emunList.getType" :key="item.value" :customStyle="style"></u-radio>
|
||||
</u-radio-group>
|
||||
</div>
|
||||
<template v-if="getType == 'yes'">
|
||||
<view class="row mt">
|
||||
<text class="title">用户领取方式</text>
|
||||
</view>
|
||||
<div class="row">
|
||||
<u-checkbox-group v-model="getMode">
|
||||
<u-checkbox :label="item.label" :name="item.value" v-for="item in emunList.getMode" :key="item.value" :customStyle="style"></u-checkbox>
|
||||
</u-checkbox-group>
|
||||
</div>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { emunList } from '@/utils/couponUtils.js';
|
||||
|
||||
const style = {
|
||||
marginRight: '20px'
|
||||
};
|
||||
|
||||
const getType = defineModel('getType', {
|
||||
type: String,
|
||||
default: 'no'
|
||||
});
|
||||
|
||||
const getMode = defineModel('getMode', {
|
||||
type: Array,
|
||||
default: ['eat']
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.conetnt {
|
||||
.row {
|
||||
&.mt {
|
||||
margin-top: 28upx;
|
||||
padding-bottom: 10upx;
|
||||
}
|
||||
.title {
|
||||
color: #303133;
|
||||
font-size: 30upx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,105 +0,0 @@
|
||||
<template>
|
||||
<view class="item-doc" :style="{ height: headHeight + 'px' }">
|
||||
<view class="item" :style="{ height: headHeight + 'px' }">
|
||||
<view class="left">
|
||||
<image v-if="options.icon.indexOf('http') != -1" :src="options.icon" mode="aspectFit" class="icon"></image>
|
||||
<image v-else :src="`/static/applocation/${options.icon}.png`" mode="aspectFit" class="icon"></image>
|
||||
|
||||
<view class="info">
|
||||
<view class="title">
|
||||
<text class="t">{{ options.name }}</text>
|
||||
</view>
|
||||
<view class="intro">
|
||||
<text class="t">{{ options.intro }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right" v-if="showSwitch">
|
||||
<!-- 关键修复:删掉错误的 @change 绑定,defineModel 已自动处理双向绑定 -->
|
||||
<u-switch :active-value="1" :inactive-value="0" v-model="isOpen"></u-switch>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, nextTick } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
// 注意:对象/数组默认值推荐用函数,避免引用共享
|
||||
name: '标题',
|
||||
intro: '说明',
|
||||
icon: 'xszk'
|
||||
})
|
||||
},
|
||||
showSwitch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const headHeight = ref(70);
|
||||
|
||||
// defineModel 是 Vue3.4+ 语法糖,自动实现 v-model:isOpen 的双向绑定
|
||||
const isOpen = defineModel('isOpen', {
|
||||
type: [Boolean, String, Number],
|
||||
default: 0
|
||||
});
|
||||
|
||||
// 声明自定义 emit 事件(仅在 script setup 内使用)
|
||||
const emits = defineEmits(['load']);
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
emits('load', { height: headHeight.value });
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.item-doc {
|
||||
width: 100%;
|
||||
}
|
||||
.item {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
padding: 20upx 28upx;
|
||||
.left {
|
||||
display: flex;
|
||||
.icon {
|
||||
$size: 80upx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.info {
|
||||
display: flex;
|
||||
padding-left: 20upx;
|
||||
flex-direction: column;
|
||||
.title {
|
||||
margin-top: -4upx;
|
||||
.t {
|
||||
font-size: 28upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.intro {
|
||||
.t {
|
||||
font-size: 28upx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,110 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-radio-group v-model="useTimeType" placement="row" v-if="showType">
|
||||
<up-radio v-for="item in useTimeTypeList" :key="item.value" :value="item.value" :name="item.value" :label="item.label" :customStyle="customStyle"></up-radio>
|
||||
</up-radio-group>
|
||||
<view class="container" v-if="useTimeType == 'custom' || !showType">
|
||||
<view class="u-flex u-m-t-30 box">
|
||||
<view class="u-flex u-flex-1">
|
||||
<view class="item" @click="pirckerShow(startValue, 'startValue')">
|
||||
<text class="u-m-r-12" v-if="!startValue">开始时间</text>
|
||||
<text class="u-m-r-12" v-else>{{ startValue }}</text>
|
||||
</view>
|
||||
<view class="u-m-l-8 u-m-r-8" style="padding: 0 30rpx">—</view>
|
||||
<view class="item" @click="pirckerShow(endValue, 'endValue')">
|
||||
<text class="u-m-r-12" v-if="!endValue">结束时间</text>
|
||||
<text class="u-m-r-12" v-else>{{ endValue }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<up-icon name="clock"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-datetime-picker :show="show" v-model="value1" closeOnClickOverlay @close="close" @cancel="close" @confirm="confirm" mode="time"></up-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
showType: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
function cancel() {
|
||||
union.navigateBack();
|
||||
}
|
||||
const customStyle = ref({
|
||||
marginRight: '15px'
|
||||
});
|
||||
|
||||
const useTimeType = defineModel('useTimeType', {
|
||||
type: String,
|
||||
default: 'all'
|
||||
});
|
||||
const useTimeTypeList = [
|
||||
{
|
||||
value: 'all',
|
||||
label: '全时段可用'
|
||||
},
|
||||
{
|
||||
value: 'custom',
|
||||
label: '指定时间段可用'
|
||||
}
|
||||
];
|
||||
import dayjs from 'dayjs';
|
||||
const startValue = defineModel('startValue', {
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
const endValue = defineModel('endValue', {
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
const value1 = ref('');
|
||||
const show = ref(false);
|
||||
const nowKey = ref('');
|
||||
|
||||
function pirckerShow(date, key) {
|
||||
nowKey.value = key;
|
||||
show.value = true;
|
||||
value1.value = date || '';
|
||||
}
|
||||
|
||||
function confirm(e) {
|
||||
console.log(e);
|
||||
|
||||
if (nowKey.value == 'startValue') {
|
||||
startValue.value = e.value;
|
||||
} else if (nowKey.value == 'endValue') {
|
||||
endValue.value = e.value;
|
||||
}
|
||||
value1.value = e.value;
|
||||
show.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 48rpx;
|
||||
padding: 0 12rpx;
|
||||
display: flex;
|
||||
}
|
||||
.box {
|
||||
border: 2rpx solid #dddfe6;
|
||||
padding: 16rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
width: 564rpx;
|
||||
border-radius: 4rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
@@ -1,41 +0,0 @@
|
||||
<template>
|
||||
<view class="mask-conetnt">
|
||||
<text class="t">门店未参与{{ name }}活动或主店未开启活动,如需开启参与请联系主店</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
default: '活动'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mask-conetnt {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-bottom: 5vh;
|
||||
.t {
|
||||
width: 80vw;
|
||||
font-size: 28upx;
|
||||
color: #333;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,190 +0,0 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<view @click="show = true">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<view v-else class="choose-goods u-flex u-row-between">
|
||||
<text class="color-999" v-if="!modelValue">请选择优惠券</text>
|
||||
<text class="color-333 u-m-r-32 u-line-1" v-else>{{ goodsName }}</text>
|
||||
<up-icon size="14" name="arrow-down"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<up-popup :show="show" :round="20" mode="bottom">
|
||||
<view class="">
|
||||
<view class="top u-flex u-row-between">
|
||||
<text class="font-bold u-font-32 color-333">{{ title }}</text>
|
||||
<up-icon size="18" name="close" @click="show = false"></up-icon>
|
||||
</view>
|
||||
<scroll-view :scroll-y="true" style="max-height: 50vh" @scroll="scroll" :scroll-top="scrollTop">
|
||||
<view v-for="(item, index) in list" :key="index" class="item" @click="itemClick(item)" :class="[selGoods && selGoods.id == item.id ? 'selected' : '']">
|
||||
<view class="u-flex u-row-between">
|
||||
<view class="u-flex gap-20">
|
||||
<!-- <view class="u-flex" @click.stop="preview(item)">
|
||||
<up-image :src="item.coverImg" width="80rpx" height="80rpx"></up-image>
|
||||
</view> -->
|
||||
<text class="u-font-32 color-333">{{ item.title }}</text>
|
||||
</view>
|
||||
<!-- <text class="u-font-32 color-red u-p-l-30">¥{{ item.lowPrice }}</text> -->
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="bottom">
|
||||
<view class="btn cancel" @click="close">{{ cancelText }}</view>
|
||||
<view class="btn success" @click="confirm">{{ confirmText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { couponPage } from '@/http/api/market/index.js';
|
||||
const show = ref(false);
|
||||
const modelValue = defineModel({
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
|
||||
const goodsName = defineModel('goodsName', {
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: '选择优惠券'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
}
|
||||
});
|
||||
|
||||
const selGoods = ref('');
|
||||
function itemClick(item) {
|
||||
if (selGoods.value && selGoods.value.id == item.id) {
|
||||
selGoods.value = '';
|
||||
return;
|
||||
}
|
||||
selGoods.value = item;
|
||||
}
|
||||
const list = ref([]);
|
||||
|
||||
const scrollTop = ref(0);
|
||||
function scroll(e) {
|
||||
scrollTop.value = e.detail.scrollTop;
|
||||
}
|
||||
function preview(item) {
|
||||
uni.previewImage({
|
||||
urls: item.images || [item.coverImg]
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => modelValue.value,
|
||||
(newVal, oldVal) => {
|
||||
console.log(newVal, oldVal);
|
||||
selGoods.value = list.value.find((item) => item.id == newVal);
|
||||
console.log(selGoods.value);
|
||||
if (selGoods.value) {
|
||||
goodsName.value = selGoods.value.title;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => list.value.length,
|
||||
(newVal, oldVal) => {
|
||||
selGoods.value = list.value.find((item) => item.id == modelValue.value);
|
||||
console.log(selGoods.value);
|
||||
if (selGoods.value) {
|
||||
modelValue.value = selGoods.value.id;
|
||||
goodsName.value = selGoods.value.title;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
function confirm() {
|
||||
if (!selGoods.value) {
|
||||
uni.showToast({
|
||||
title: '请选择优惠券',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
modelValue.value = selGoods.value.id;
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
const emits = defineEmits(['load']);
|
||||
|
||||
onMounted(() => {
|
||||
couponPage({ page: 1, size: 500 }).then((res) => {
|
||||
list.value = res.records;
|
||||
emits('load', list.value);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.popup-content {
|
||||
background: #fff;
|
||||
width: 640rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.top {
|
||||
padding: 40rpx 48rpx;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
.bottom {
|
||||
padding: 48rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
gap: 50rpx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 32rpx;
|
||||
border: 2rpx solid transparent;
|
||||
&.success {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.cancel {
|
||||
border-color: #d9d9d9;
|
||||
box-shadow: 0 4rpx 0 0 #00000005;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
padding: 10rpx 30rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
margin: 10rpx;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s ease-in-out;
|
||||
box-shadow: 0 0 10px transparent;
|
||||
&.selected {
|
||||
border-color: $my-main-color;
|
||||
box-shadow: 0 0 10px $my-main-color;
|
||||
}
|
||||
}
|
||||
.choose-goods {
|
||||
display: flex;
|
||||
padding: 24rpx;
|
||||
align-items: center;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
@@ -1,325 +0,0 @@
|
||||
<template>
|
||||
<view class="my-select-goods">
|
||||
<view class="radio-wrap">
|
||||
<u-radio-group v-model="foodType" @change="foodTypeChange">
|
||||
<u-radio v-for="item in radioList" :key="item.value" :label="item.label" :name="item.value" :customStyle="customStyle"></u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
<view class="selec-goods-card" @click="popupShow = true" v-if="foodType == 2">
|
||||
<view class="title">
|
||||
<text class="t">选择商品</text>
|
||||
</view>
|
||||
<view class="placeholder">
|
||||
<view class="left">
|
||||
<text class="placeholder-t" v-if="selectGoodsCount.length <= 0">请选择商品</text>
|
||||
<text class="t" v-else>{{ selectGoodsCount.map((item) => item.name).join('、') }}</text>
|
||||
</view>
|
||||
<u-icon name="arrow-right" size="14px" color="#999"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<u-popup :show="popupShow" :round="20" closeable @close="popupClosed">
|
||||
<view class="popup-container">
|
||||
<view class="title">
|
||||
<text class="t">请选择</text>
|
||||
</view>
|
||||
<view class="goods-scroll-wrap">
|
||||
<view class="left">
|
||||
<scroll-view scroll-y class="scroll-view">
|
||||
<view
|
||||
class="category-item"
|
||||
v-for="(item, index) in categorys"
|
||||
:key="item.id"
|
||||
:class="{ active: categorysIndex == index }"
|
||||
@click="changeCategorys(item, index)"
|
||||
>
|
||||
<text class="t">{{ item.name }}</text>
|
||||
<text class="t" v-if="item.selectedNum > 0">({{ item.selectedNum }})</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="right">
|
||||
<scroll-view scroll-y class="scroll-view">
|
||||
<view class="goods-item" v-for="(item, index) in categorys[categorysIndex].goods" :key="item.id" @click="selectGoods(item, index)">
|
||||
<view class="name">
|
||||
<text class="t">{{ item.name }}</text>
|
||||
</view>
|
||||
<view class="selec-btn">
|
||||
<u-icon name="checkmark-circle-fill" color="#318afe" size="18" v-if="item.selected"></u-icon>
|
||||
<view class="circle" v-else></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<view class="btn">
|
||||
<u-button type="primary" size="large" @click="confirmHandle">
|
||||
确定
|
||||
<template v-if="countNum > 0">({{ countNum }})</template>
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getCategoryList, getProductList } from '@/http/api/product.js';
|
||||
|
||||
const popupShow = ref(false);
|
||||
|
||||
const modelValue = defineModel({
|
||||
type: [String, Array],
|
||||
default: []
|
||||
});
|
||||
|
||||
const customStyle = ref({
|
||||
marginRight: '20px'
|
||||
});
|
||||
|
||||
const radioList = ref([
|
||||
{
|
||||
value: 1,
|
||||
label: '全部商品参与'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '部分商品参与'
|
||||
}
|
||||
]);
|
||||
|
||||
const emits = defineEmits('foodTypeChange');
|
||||
function foodTypeChange(e) {
|
||||
console.log('foodTypeChange', e);
|
||||
emits('foodTypeChange', e);
|
||||
}
|
||||
|
||||
const foodType = defineModel('foodType', {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
});
|
||||
|
||||
const categorys = ref([]);
|
||||
const categorysIndex = ref(0);
|
||||
|
||||
// 切换分类
|
||||
function changeCategorys(item, index) {
|
||||
categorysIndex.value = index;
|
||||
}
|
||||
|
||||
// 获取商品分类
|
||||
async function getCategoryListAjax() {
|
||||
try {
|
||||
categorys.value = await getCategoryList();
|
||||
categorys.value.forEach((item) => {
|
||||
item.goods = [];
|
||||
item.selectedNum = 0;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
const goods = ref([]);
|
||||
|
||||
function selectGoods(item, index) {
|
||||
item.selected = !item.selected;
|
||||
updateSelectGoods();
|
||||
}
|
||||
|
||||
// 在这个方法里更新已选择的数量和商品
|
||||
const countNum = ref(0);
|
||||
function updateSelectGoods() {
|
||||
countNum.value = 0;
|
||||
categorys.value.forEach((item) => {
|
||||
let num = 0;
|
||||
item.goods.forEach((val) => {
|
||||
if (val.selected) {
|
||||
num++;
|
||||
countNum.value++;
|
||||
}
|
||||
});
|
||||
item.selectedNum = num;
|
||||
});
|
||||
confirmSelectGoods;
|
||||
}
|
||||
|
||||
// 确定
|
||||
function confirmHandle() {
|
||||
confirmSelectGoods();
|
||||
popupShow.value = false;
|
||||
}
|
||||
|
||||
// 点击确定更新已选择的商品
|
||||
const selectGoodsCount = ref([]);
|
||||
function confirmSelectGoods() {
|
||||
selectGoodsCount.value = [];
|
||||
categorys.value.forEach((item) => {
|
||||
item.goods.forEach((val) => {
|
||||
if (val.selected) {
|
||||
selectGoodsCount.value.push(val);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
modelValue.value = selectGoodsCount.value.map((item) => item.id);
|
||||
}
|
||||
|
||||
// 获取商品列表
|
||||
async function getProductListAjax() {
|
||||
try {
|
||||
const res = await getProductList();
|
||||
res.forEach((item, index) => {
|
||||
// console.log('modelValue.value===', modelValue.value);
|
||||
// console.log('index===', item.id.includes(modelValue.value));
|
||||
if (modelValue.value.includes(item.id)) {
|
||||
item.selected = true;
|
||||
} else {
|
||||
item.selected = false;
|
||||
}
|
||||
categorys.value.forEach((val, i) => {
|
||||
if (val.id == item.categoryId) {
|
||||
val.goods.push(item);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
updateSelectGoods();
|
||||
confirmSelectGoods();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// popup关闭
|
||||
function popupClosed() {
|
||||
popupShow.value = false;
|
||||
// countNum.value = 0;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getCategoryListAjax();
|
||||
await getProductListAjax();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-select-goods {
|
||||
.selec-goods-card {
|
||||
margin-top: 20upx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 10upx;
|
||||
padding: 20upx;
|
||||
.ttile {
|
||||
.t {
|
||||
font-size: 28upx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
.placeholder {
|
||||
display: flex;
|
||||
padding-top: 12upx;
|
||||
.left {
|
||||
flex: 1;
|
||||
.placeholder-t {
|
||||
font-size: 28upx;
|
||||
color: #999;
|
||||
}
|
||||
.t {
|
||||
display: block;
|
||||
max-width: 400upx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.popup-container {
|
||||
$color: #318afe;
|
||||
.title {
|
||||
padding: 28upx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.goods-scroll-wrap {
|
||||
width: 100%;
|
||||
height: 50vh;
|
||||
display: flex;
|
||||
.left {
|
||||
width: 240upx;
|
||||
height: 100%;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.right {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
.scroll-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.category-item {
|
||||
width: 100%;
|
||||
height: 84upx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 38upx;
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
&::after {
|
||||
content: '';
|
||||
width: 8upx;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
background-color: $color;
|
||||
}
|
||||
}
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
}
|
||||
}
|
||||
.goods-item {
|
||||
height: 84upx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 28upx;
|
||||
.name {
|
||||
.t {
|
||||
font-size: 32upx;
|
||||
}
|
||||
}
|
||||
.selec-btn {
|
||||
$size: 32upx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.circle {
|
||||
width: $size;
|
||||
height: $size;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
padding: 28upx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,134 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-radio-group v-model="useType" placement="row">
|
||||
<up-radio v-for="item in useTypeList" :key="item.value" :name="item.value" :label="item.label" :customStyle="customStyle"></up-radio>
|
||||
</up-radio-group>
|
||||
<view class="box" v-if="useType == 'custom'" @click.stop="openPopup">
|
||||
<text class="u-font-28 color-999 u-p-r-16" v-if="selShops.length == 0">请选择</text>
|
||||
<view class="u-font-24 shop-item u-flex u-p-r-20 u-col-center u-p-r-16" v-for="(item, index) in selShops" :key="item.shopId">
|
||||
<text>{{ returnShopName(item) }}</text>
|
||||
<view @click.stop="delShop(index)">
|
||||
<up-icon name="close" size="14" @click="delShop(index)" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon">
|
||||
<up-icon name="arrow-down" size="14" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<up-popup :show="show" placement="bottom" round="18rpx" closeOnClickOverlay @close="close">
|
||||
<view class="u-p-30">
|
||||
<view class="font-bold color-333 u-font-32">选择门店</view>
|
||||
<scroll-view class="scroll-view u-m-t-30" scroll-y="true" max-height="40vh">
|
||||
<view class="u-m-b-10" v-for="item in list" :key="item.shopId">
|
||||
<up-checkbox usedAlone :name="item.shopId" :label="item.shopName" v-model:checked="item.checked"></up-checkbox>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="u-flex gap-20 u-m-t-30">
|
||||
<view class="u-flex-1">
|
||||
<my-button type="default" @click="close">取消</my-button>
|
||||
</view>
|
||||
<view class="u-flex-1">
|
||||
<my-button type="primary" @click="submit">确定</my-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { getShopList } from '@/http/api/shop.js';
|
||||
|
||||
const customStyle = ref({
|
||||
marginRight: '15px'
|
||||
});
|
||||
|
||||
const show = ref(false);
|
||||
const selShops = defineModel('selShops', {
|
||||
default: () => [],
|
||||
type: [Array, String]
|
||||
});
|
||||
const useType = defineModel('useType', {
|
||||
default: () => 'only',
|
||||
type: String
|
||||
});
|
||||
const useTypeList = [
|
||||
{
|
||||
value: 'only',
|
||||
label: '仅本店'
|
||||
},
|
||||
{
|
||||
value: 'all',
|
||||
label: '全部门店'
|
||||
},
|
||||
{
|
||||
value: 'custom',
|
||||
label: '指定门店可用'
|
||||
}
|
||||
];
|
||||
|
||||
function returnShopName(shopId) {
|
||||
const item = list.value.find((v) => v.shopId == shopId);
|
||||
return item?.shopName || '';
|
||||
}
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
function submit() {
|
||||
selShops.value = list.value.filter((item) => item.checked).map((v) => v.shopId);
|
||||
show.value = false;
|
||||
}
|
||||
function delShop(index) {
|
||||
selShops.value.splice(index, 1);
|
||||
}
|
||||
const list = ref([]);
|
||||
|
||||
function openPopup() {
|
||||
show.value = true;
|
||||
list.value = list.value.map((item) => ({
|
||||
shopId: item.shopId,
|
||||
shopName: item.shopName,
|
||||
checked: selShops.value.includes(item.shopId)
|
||||
}));
|
||||
}
|
||||
async function init() {
|
||||
const res = await getShopList();
|
||||
console.log('selShops.value', selShops.value);
|
||||
|
||||
if (res) {
|
||||
list.value = res.map((item) => ({
|
||||
shopId: item.shopId,
|
||||
shopName: item.shopName,
|
||||
checked: selShops.value.includes(item.shopId)
|
||||
}));
|
||||
}
|
||||
}
|
||||
onMounted(init);
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.box {
|
||||
border-radius: 8upx;
|
||||
margin-top: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: top;
|
||||
flex-wrap: wrap;
|
||||
padding: 10rpx 24rpx;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
position: relative;
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 24rpx;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
.shop-item {
|
||||
padding: 4rpx 8rpx 4rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
border: 2rpx solid #f0f0f0;
|
||||
background-color: #f5f5f5;
|
||||
margin-bottom: 16rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,135 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-radio-group v-model="useType" placement="row" @change="useTypeChange">
|
||||
<up-radio v-for="item in useTypeList" :key="item.value" :name="item.value" :label="item.label" :customStyle="customStyle"></up-radio>
|
||||
</up-radio-group>
|
||||
<view class="box" v-if="useType == 'part'" @click.stop="openPopup">
|
||||
<text class="u-font-28 color-999 u-p-r-16" v-if="selShops.length == 0">请选择</text>
|
||||
<view class="u-font-24 shop-item u-flex u-p-r-20 u-col-center u-p-r-16" v-for="(item, index) in selShops" :key="item.shopId">
|
||||
<text>{{ returnShopName(item) }}</text>
|
||||
<view @click.stop="delShop(index)">
|
||||
<up-icon name="close" size="14" @click="delShop(index)" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon">
|
||||
<up-icon name="arrow-down" size="14" color="#999"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<up-popup :show="show" placement="bottom" round="18rpx" closeOnClickOverlay @close="close">
|
||||
<view class="u-p-30">
|
||||
<view class="font-bold color-333 u-font-32">选择门店</view>
|
||||
<scroll-view class="scroll-view u-m-t-30" scroll-y="true" max-height="40vh">
|
||||
<view class="u-m-b-10" v-for="item in list" :key="item.shopId">
|
||||
<up-checkbox usedAlone :name="item.shopId" :label="item.shopName" v-model:checked="item.checked"></up-checkbox>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="u-flex gap-20 u-m-t-30">
|
||||
<view class="u-flex-1">
|
||||
<my-button type="default" @click="close">取消</my-button>
|
||||
</view>
|
||||
<view class="u-flex-1">
|
||||
<my-button type="primary" @click="submit">确定</my-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
import { getShopList } from '@/http/api/shop.js';
|
||||
|
||||
const customStyle = ref({
|
||||
marginRight: '20px'
|
||||
});
|
||||
|
||||
const show = ref(false);
|
||||
let selShops = defineModel('selShops', {
|
||||
default: () => [],
|
||||
type: Array
|
||||
});
|
||||
const useType = defineModel('useType', {
|
||||
default: () => 'all',
|
||||
type: String
|
||||
});
|
||||
const useTypeList = [
|
||||
{
|
||||
value: 'all',
|
||||
label: '全部门店'
|
||||
},
|
||||
{
|
||||
value: 'part',
|
||||
label: '指定门店可用'
|
||||
}
|
||||
];
|
||||
|
||||
const emits = defineEmits(['useTypeChange']);
|
||||
function useTypeChange(e) {
|
||||
emits('useTypeChange', e);
|
||||
}
|
||||
|
||||
function returnShopName(shopId) {
|
||||
const item = list.value.find((v) => v.shopId == shopId);
|
||||
return item?.shopName || '';
|
||||
}
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
function submit() {
|
||||
selShops.value = list.value.filter((item) => item.checked).map((v) => v.shopId);
|
||||
show.value = false;
|
||||
}
|
||||
function delShop(index) {
|
||||
selShops.value.splice(index, 1);
|
||||
}
|
||||
const list = ref([]);
|
||||
|
||||
function openPopup() {
|
||||
show.value = true;
|
||||
list.value = list.value.map((item) => ({
|
||||
shopId: item.shopId,
|
||||
shopName: item.shopName,
|
||||
checked: selShops.value.includes(item.shopId)
|
||||
}));
|
||||
}
|
||||
async function init() {
|
||||
const res = await getShopList();
|
||||
console.log('selShops.value', selShops.value);
|
||||
|
||||
if (res) {
|
||||
list.value = res.map((item) => ({
|
||||
shopId: item.shopId,
|
||||
shopName: item.shopName,
|
||||
checked: selShops.value.includes(item.shopId)
|
||||
}));
|
||||
}
|
||||
}
|
||||
onMounted(init);
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.box {
|
||||
border-radius: 8upx;
|
||||
margin-top: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: top;
|
||||
flex-wrap: wrap;
|
||||
padding: 10rpx 24rpx;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
position: relative;
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 24rpx;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
.shop-item {
|
||||
padding: 4rpx 8rpx 4rpx 16rpx;
|
||||
border-radius: 4rpx;
|
||||
border: 2rpx solid #f0f0f0;
|
||||
background-color: #f5f5f5;
|
||||
margin-bottom: 16rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<u-radio-group v-model="modelValue" @change="defineEmits(['update:modelValue'])">
|
||||
<u-radio label="仅本店" name="only" :customStyle="customStyle"></u-radio>
|
||||
<u-radio label="全部" name="all" :customStyle="customStyle"></u-radio>
|
||||
<u-radio label="指定" name="custom" :customStyle="customStyle"></u-radio>
|
||||
</u-radio-group>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const customStyle = ref({
|
||||
marginRight: '20px'
|
||||
});
|
||||
|
||||
const modelValue = defineModel('modelValue', {
|
||||
type: String,
|
||||
default: 'only'
|
||||
});
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
@@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="u-flex">
|
||||
<view class="item" @click="pirckerShow(startDate, 'startDate')">
|
||||
<text class="u-m-r-12" v-if="!startDate">{{ startText }}</text>
|
||||
<text class="u-m-r-12" v-else>{{ startDate }}</text>
|
||||
<up-icon name="arrow-down" size="14"></up-icon>
|
||||
</view>
|
||||
<view class="u-m-l-8 u-m-r-8">—</view>
|
||||
<view class="item" @click="pirckerShow(endDate, 'endDate')">
|
||||
<text class="u-m-r-12" v-if="!endDate">{{ endText }}</text>
|
||||
<text class="u-m-r-12" v-else>{{ endDate }}</text>
|
||||
<up-icon name="arrow-down" size="14"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-datetime-picker
|
||||
:show="show"
|
||||
v-model="value1"
|
||||
closeOnClickOverlay
|
||||
@close="close"
|
||||
@cancel="close"
|
||||
@confirm="confirm"
|
||||
mode="date"
|
||||
></up-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import dayjs from "dayjs";
|
||||
const props=defineProps({
|
||||
startText: {
|
||||
type: String,
|
||||
default: "请选择开始时间",
|
||||
},
|
||||
endText: {
|
||||
type: String,
|
||||
default: "请选择结束时间",
|
||||
},
|
||||
});
|
||||
const startDate = defineModel("startDate", {
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
const endDate = defineModel("endDate", {
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
|
||||
const minDate = ref(0);
|
||||
const maxDate = ref(dayjs().add(80, "year").valueOf());
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
const value1 = ref(Date.now());
|
||||
const show = ref(false);
|
||||
const nowKey = ref("");
|
||||
|
||||
function pirckerShow(date, key) {
|
||||
nowKey.value = key;
|
||||
console.log(date);
|
||||
show.value = true;
|
||||
}
|
||||
|
||||
function confirm(e) {
|
||||
console.log(e);
|
||||
|
||||
if (nowKey.value == "startDate") {
|
||||
startDate.value = dayjs(e.value).format("YYYY-MM-DD");
|
||||
} else if (nowKey.value == "endDate") {
|
||||
endDate.value = dayjs(e.value).format("YYYY-MM-DD");
|
||||
}
|
||||
value1.value = e.value
|
||||
show.value = false;
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.item {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 64rpx;
|
||||
border: 2rpx solid #dddfe6;
|
||||
padding: 0 12rpx;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
@@ -1,125 +1,113 @@
|
||||
<template>
|
||||
<up-upload
|
||||
:fileList="images"
|
||||
@afterRead="afterRead"
|
||||
@delete="deletePic"
|
||||
:multiple="multiple"
|
||||
:width="width"
|
||||
:height="height"
|
||||
:maxCount="maxCount"
|
||||
>
|
||||
<template #default v-if="$slots.default">
|
||||
<slot></slot>
|
||||
</template>
|
||||
</up-upload>
|
||||
<up-upload :fileList="images" @afterRead="afterRead" @delete="deletePic" :multiple="multiple" :width="width"
|
||||
:height="height" :maxCount="maxCount"></up-upload>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { uploadFile } from "@/http/api/index.js";
|
||||
import { ref, watch } from 'vue';
|
||||
import { uploadFile } from '@/http/api/index.js'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 60,
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 60,
|
||||
},
|
||||
maxCount: {
|
||||
type: [Number],
|
||||
default: 10,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 60
|
||||
},
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 60
|
||||
},
|
||||
maxCount: {
|
||||
type: [Number],
|
||||
default: 10
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(["update:modelValue"]);
|
||||
const images = ref(props.modelValue);
|
||||
|
||||
function uploadfile(par) {
|
||||
let file = null;
|
||||
// #ifdef H5
|
||||
file = par.file;
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
file = par;
|
||||
// #endif
|
||||
return uploadFile(file);
|
||||
}
|
||||
const emits = defineEmits(['update:modelValue'])
|
||||
const images = ref(props.modelValue)
|
||||
|
||||
|
||||
|
||||
function uploadfile(par){
|
||||
let file=null;
|
||||
// #ifdef H5
|
||||
file= par.file
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
file= par
|
||||
// #endif
|
||||
return uploadFile(file)
|
||||
}
|
||||
|
||||
function afterRead(e) {
|
||||
console.log(e);
|
||||
if (Array.isArray(e.file)) {
|
||||
for (let i in e.file) {
|
||||
const file = e.file[i]
|
||||
console.log(file);
|
||||
uploadfile(file).then(res => {
|
||||
console.log(res);
|
||||
images.value.push({
|
||||
url: e.file[i].url,
|
||||
serveUrl: res
|
||||
})
|
||||
}).catch(res => {
|
||||
console.log(res);
|
||||
if (res.errMsg) {
|
||||
images.value.splice(i, 1)
|
||||
uni.showToast({
|
||||
title: '图片大小超出限制',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
|
||||
function afterRead(e) {
|
||||
console.log(e);
|
||||
if (Array.isArray(e.file)) {
|
||||
for (let i in e.file) {
|
||||
const file = e.file[i];
|
||||
console.log(file);
|
||||
uploadfile(file)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
images.value.push({
|
||||
url: e.file[i].url,
|
||||
serveUrl: res,
|
||||
});
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log(res);
|
||||
if (res.errMsg) {
|
||||
images.value.splice(i, 1);
|
||||
uni.showToast({
|
||||
title: "图片大小超出限制",
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const i = 0;
|
||||
uploadfile(e.file)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
images.value.push({
|
||||
url: e.file.url,
|
||||
serveUrl: res,
|
||||
});
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log(res);
|
||||
if (res.errMsg) {
|
||||
images.value.splice(i, 1);
|
||||
uni.showToast({
|
||||
title: "图片大小超出限制",
|
||||
icon: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}else{
|
||||
const i=0
|
||||
uploadfile(e.file).then(res => {
|
||||
console.log(res);
|
||||
images.value.push({
|
||||
url: e.file.url,
|
||||
serveUrl: res
|
||||
})
|
||||
}).catch(res => {
|
||||
console.log(res);
|
||||
if (res.errMsg) {
|
||||
images.value.splice(i, 1)
|
||||
uni.showToast({
|
||||
title: '图片大小超出限制',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function deletePic(e) {
|
||||
const { index } = e;
|
||||
images.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => images.value,
|
||||
(newval) => {
|
||||
emits("update:modelValue", newval);
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newval) => {
|
||||
images.value = newval;
|
||||
}
|
||||
);
|
||||
function deletePic(e) {
|
||||
const {
|
||||
index
|
||||
} = e
|
||||
images.value.splice(index, 1)
|
||||
}
|
||||
|
||||
watch(() => images.value, (newval) => {
|
||||
emits('update:modelValue', newval)
|
||||
})
|
||||
watch(() => props.modelValue, (newval) => {
|
||||
images.value = newval
|
||||
})
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
<style>
|
||||
</style>
|
||||
@@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<view class="upload-file" @click="chooseImage">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<view class="icon" v-if="!modelValue">+</view>
|
||||
<image class="img" v-else :src="modelValue"></image>
|
||||
|
||||
<view class="close" @click.stop="() => {}" v-if="modelValue">
|
||||
<up-icon name="close-circle" color="#333" size="14" @click="clearImg"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { uploadFile } from '@/http/api/index.js';
|
||||
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
|
||||
const modelValue = defineModel({
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
|
||||
function chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 1, //默认9
|
||||
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album', 'camera'],
|
||||
success: async function (res) {
|
||||
uni.showLoading({
|
||||
title: '上传中'
|
||||
});
|
||||
console.log(res);
|
||||
const fileRes = await uploadFile(res.tempFiles[0]);
|
||||
uni.hideLoading();
|
||||
if (fileRes) {
|
||||
modelValue.value = fileRes;
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '上传失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function clearImg() {
|
||||
modelValue.value = '';
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-file {
|
||||
$size: 128rpx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 8rpx;
|
||||
position: relative;
|
||||
.close {
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
}
|
||||
.img {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
.icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 4rpx solid #999;
|
||||
border-radius: 8rpx;
|
||||
font-weight: 700;
|
||||
color: #999;
|
||||
font-size: 32rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,181 +0,0 @@
|
||||
<template>
|
||||
<view class="upload-file-wrap">
|
||||
<!-- 多图展示区域 -->
|
||||
<view class="upload-file-item" v-for="(img, index) in modelValue" :key="index">
|
||||
<image class="img" :src="img" mode="aspectFill" @click="previewImage(index)"></image>
|
||||
<view class="close" @click.stop="removeImg(index)">
|
||||
<up-icon name="close-circle" color="#333" size="14"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 上传按钮(未达上限时显示) -->
|
||||
<view class="upload-file-btn" @click="chooseImage" v-if="modelValue.length < props.maxCount">
|
||||
<slot v-if="$slots.default"></slot>
|
||||
<view class="icon" v-else>+</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { uploadFile } from '@/http/api/index.js';
|
||||
import { ref, watch, defineProps, defineEmits } from 'vue';
|
||||
|
||||
// 1. 定义Props(扩展配置项)
|
||||
const props = defineProps({
|
||||
// 最大上传数量(默认9,可外部传参)
|
||||
maxCount: {
|
||||
type: Number,
|
||||
default: 9
|
||||
},
|
||||
// 是否压缩(默认开启)
|
||||
isCompressed: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 图片来源(相册/相机,默认都支持)
|
||||
sourceType: {
|
||||
type: Array,
|
||||
default: () => ['album', 'camera']
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 双向绑定多图列表(Array类型)
|
||||
const modelValue = defineModel({
|
||||
type: Array,
|
||||
default: () => []
|
||||
});
|
||||
|
||||
// 3. 选择图片(支持多图)
|
||||
async function chooseImage() {
|
||||
// 计算剩余可上传数量
|
||||
const remainCount = props.maxCount - modelValue.value.length;
|
||||
if (remainCount <= 0) {
|
||||
uni.showToast({ title: `最多只能上传${props.maxCount}张图片`, icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
uni.chooseImage({
|
||||
count: remainCount, // 仅能选择剩余数量的图片
|
||||
sizeType: props.isCompressed ? ['compressed'] : ['original', 'compressed'],
|
||||
sourceType: props.sourceType,
|
||||
success: async function (res) {
|
||||
uni.showLoading({ title: '上传中' });
|
||||
try {
|
||||
// 批量上传选中的图片
|
||||
const uploadPromises = res.tempFiles.map((file) => uploadFile(file));
|
||||
const fileResList = await Promise.all(uploadPromises);
|
||||
|
||||
// 过滤上传失败的图片,仅保留成功的URL
|
||||
const successUrls = fileResList.filter((url) => !!url);
|
||||
if (successUrls.length > 0) {
|
||||
modelValue.value = [...modelValue.value, ...successUrls]; // 追加到列表
|
||||
uni.showToast({ title: `成功上传${successUrls.length}张图片`, icon: 'success' });
|
||||
}
|
||||
} catch (error) {
|
||||
uni.showToast({ title: '部分图片上传失败', icon: 'none' });
|
||||
console.error('图片上传失败:', error);
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '取消选择图片', icon: 'none' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 4. 删除单张图片
|
||||
function removeImg(index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除这张图片吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
modelValue.value.splice(index, 1); // 删除对应索引的图片
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 5. 预览图片(支持左右滑动)
|
||||
function previewImage(currentIndex) {
|
||||
uni.previewImage({
|
||||
urls: modelValue.value, // 所有已上传的图片列表
|
||||
current: modelValue.value[currentIndex], // 当前预览的图片
|
||||
loop: true // 支持循环预览
|
||||
});
|
||||
}
|
||||
|
||||
// 6. 扩展:批量清空图片(可暴露给父组件调用)
|
||||
const clearAllImg = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要清空所有图片吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
modelValue.value = [];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({ clearAllImg });
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-file-wrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx; // 图片之间的间距
|
||||
}
|
||||
|
||||
.upload-file-item {
|
||||
$size: 128rpx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 8rpx;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
padding: 2rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-file-btn {
|
||||
$size: 128rpx;
|
||||
width: $size;
|
||||
height: $size;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border: 4rpx solid #999;
|
||||
border-radius: 8rpx;
|
||||
font-weight: 700;
|
||||
color: #999;
|
||||
font-size: 32rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-checkbox-group v-model="selectedWeek" :options="week">
|
||||
<up-checkbox :customStyle="customStyle" :shape="shape" v-for="item in week" :key="item.value" :value="item.value" :name="item.value" :label="item.value">
|
||||
{{ item.name }}
|
||||
</up-checkbox>
|
||||
</up-checkbox-group>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const customStyle = {
|
||||
marginRight: '40rpx',
|
||||
marginBottom: '16rpx'
|
||||
};
|
||||
const props = defineProps({
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'square' // circle
|
||||
}
|
||||
});
|
||||
const selectedWeek = defineModel({
|
||||
type: Array,
|
||||
default: () => []
|
||||
});
|
||||
const week = ref([
|
||||
{
|
||||
name: '周一',
|
||||
value: '周一'
|
||||
},
|
||||
{
|
||||
name: '周二',
|
||||
value: '周二'
|
||||
},
|
||||
{
|
||||
name: '周三',
|
||||
value: '周三'
|
||||
},
|
||||
{
|
||||
name: '周四',
|
||||
value: '周四'
|
||||
},
|
||||
{
|
||||
name: '周五',
|
||||
value: '周五'
|
||||
},
|
||||
{
|
||||
name: '周六',
|
||||
value: '周六'
|
||||
},
|
||||
{
|
||||
name: '周日',
|
||||
value: '周日'
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
@@ -1,33 +0,0 @@
|
||||
import dayjs from "dayjs";
|
||||
export const timeList = [
|
||||
{
|
||||
label: "今天",
|
||||
value: "today",
|
||||
beginDate: dayjs().format("YYYY-MM-DD"),
|
||||
endDate: dayjs().format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
label: "昨天",
|
||||
value: "yesterday",
|
||||
beginDate: dayjs().subtract(1, "day").format("YYYY-MM-DD"),
|
||||
endDate: dayjs().subtract(1, "day").format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
label: "本周",
|
||||
value: "this_week",
|
||||
beginDate: dayjs().startOf("week").format("YYYY-MM-DD"),
|
||||
endDate: dayjs().endOf("week").format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
label: "本月",
|
||||
value: "this_month",
|
||||
beginDate: dayjs().startOf("month").format("YYYY-MM-DD"),
|
||||
endDate: dayjs().endOf("month").format("YYYY-MM-DD"),
|
||||
},
|
||||
{
|
||||
label: "自定义",
|
||||
value: "custom",
|
||||
beginDate: "",
|
||||
endDate: "",
|
||||
},
|
||||
];
|
||||
6
env/env.development.js
vendored
6
env/env.development.js
vendored
@@ -1,7 +1,7 @@
|
||||
export default {
|
||||
'JEEPAY_BASE_URL': 'http://192.168.1.42/', // 请求URL(生产环境)
|
||||
'JEEPAY_BASE_URL_H5': 'http://192.168.1.42/',
|
||||
'JEEPAY_BASE_URL_WSS': 'ws://192.168.1.42:2348' ,// sockets
|
||||
'JEEPAY_BASE_URL': 'http://192.168.1.31/', // 请求URL(生产环境)
|
||||
'JEEPAY_BASE_URL_H5': 'http://192.168.1.31/',
|
||||
'JEEPAY_BASE_URL_WSS': 'ws://192.168.1.31:2348' ,// sockets
|
||||
// 'JEEPAY_BASE_URL': 'https://cashier.sxczgkj.com/', // 请求URL(生产环境)
|
||||
// 'JEEPAY_BASE_URL_H5': 'https://cashier.sxczgkj.com/',
|
||||
// 'JEEPAY_BASE_URL_WSS': 'wss://czgeatws.sxczgkj.com/wss' // sockets
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "account";
|
||||
|
||||
export function tableOrderStatistic(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/tableOrderStatistic`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function chatCouponCreate(data) {
|
||||
return request({
|
||||
url: urlType + `/admin/chat/coupon/create`,
|
||||
method: "post",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function chatCouponPage(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/chat/coupon/page`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function chatCouponExpired(id) {
|
||||
return request({
|
||||
url: urlType + `/admin/chat/coupon/expired/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
|
||||
export function chatCouponGrant(data) {
|
||||
return request({
|
||||
url: urlType + `/admin/chat/coupon/grant`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function chatCouponRecord(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/chat/coupon/record`,
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteRecord(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/coupon/deleteRecord?id=`+params.id,
|
||||
method: "delete",
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function chatCoupon(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/coupon/chatCoupon`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumeCashback/record`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function getConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumeCashback`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function update(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumeCashback`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const marketUrl = "market";
|
||||
|
||||
/**
|
||||
* 新客立减
|
||||
* @returns
|
||||
*/
|
||||
export function getDiscountByUserId(params) {
|
||||
return request({
|
||||
url: marketUrl + `/admin/consumeDiscount/getDiscountByUserId`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function getConfig(params) {
|
||||
return request({
|
||||
url: marketUrl + `/admin/consumeDiscount`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function editConfig(params) {
|
||||
return request({
|
||||
url: marketUrl + `/admin/consumeDiscount`,
|
||||
method: "POST",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function enable(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption/enable`,
|
||||
method: "PUT",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function status(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption/enable/status`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function couponRedemption(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function couponRedemptionList(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption/list`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function add(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption`,
|
||||
method: "POST",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function edit(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption`,
|
||||
method: "PUT",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function codeList(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/couponRedemption/code/list`,
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function codeExport(params) {
|
||||
return http.download({
|
||||
url: urlType + `/admin/couponRedemption/code/export`,
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const urlType='market'
|
||||
|
||||
export function getList(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/discountActivity/page`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function add(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/discountActivity`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function update(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/discountActivity`,
|
||||
method: "PUT",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function del(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/discountActivity?id=`+id,
|
||||
method: "DELETE",
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 满减活动
|
||||
* @returns
|
||||
*/
|
||||
export function discountActivity(params) {
|
||||
return request({
|
||||
url: urlType+`/admin/discountActivity`,
|
||||
method: 'get',
|
||||
params: {
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const urlType='market'
|
||||
|
||||
export function getConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function editConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution`,
|
||||
method: "PUT",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function moneyRecoders(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/flow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function cashPay(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/cashPay`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function openFlow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/openFlow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function distributionFlow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/distributionFlow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function rechargeQrCode(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/rechargeQrCode`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function withdrawFlow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/withdrawFlow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function distributionUser(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function addDistributionUser(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function editDistributionUser(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user`,
|
||||
method: "PUT",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteDistributionUser(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user`,
|
||||
method: "DELETE",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function inviteUser(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user/inviteUser`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function resetLevel(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/user/resetLevel`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const urlType='market'
|
||||
|
||||
export function distributionFlow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/distributionFlow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function openFlow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/openFlow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function flow(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/distribution/flow`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const urlType='market'
|
||||
|
||||
export function getConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/drainageConfig`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function update(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/drainageConfig`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
/**
|
||||
* 限时折扣-分页
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function limitTimeDiscountPage(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/limitTimeDiscount/page`,
|
||||
method: "GET",
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除限时折扣
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function limitTimeDiscountDel(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/limitTimeDiscount?id=${id}`,
|
||||
method: "DELETE"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 限时折扣-新增/编辑
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function limitTimeDiscount(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/limitTimeDiscount`,
|
||||
method: data.id ? 'put' : 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券-分页
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function couponPage(params) {
|
||||
return request({
|
||||
url: `${urlType}/admin/coupon/page`,
|
||||
method: "GET",
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券-添加/编辑
|
||||
* @param {Object} params
|
||||
*/
|
||||
export function couponAdd(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/coupon`,
|
||||
method: data.id ? 'put' : 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券-删除
|
||||
* @param id
|
||||
*/
|
||||
export function couponDel(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/coupon?id=${id}&type=0`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券-详情
|
||||
* @param id
|
||||
*/
|
||||
export function couponDetail(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/coupon/${id}`,
|
||||
method: "GET"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠券-添加
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function couponPost(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumerCoupon/addConsumerCoupon`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠券-更新
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function updateConsumerCouponById(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumerCoupon/updateConsumerCouponById`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠券-分页
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function getConsumerCouponPage(params) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumerCoupon/getConsumerCouponPage`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠券-删除
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function deleteConsumerCoupon(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumerCoupon/deleteConsumerCoupon?id=${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费赠券-详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function getConsumerCouponById(params) {
|
||||
return request({
|
||||
url: `${urlType}/admin/consumerCoupon/getConsumerCouponById`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 优惠券列表/已领取详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function couponGetRecord(params) {
|
||||
return request({
|
||||
url: `${urlType}/admin/coupon/record`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 智慧充值规/配置信息修改
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function shopRechargePost(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/shopRecharge`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 智慧充值规/配置信息获取
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function shopRechargeGet(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/shopRecharge`,
|
||||
method: 'get',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺用户充值记录
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function shopUserFlow(data) {
|
||||
return request({
|
||||
url: `/account/admin/shopUser/flow`,
|
||||
method: 'get',
|
||||
data
|
||||
});
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
/**
|
||||
* 限时折扣
|
||||
* @returns
|
||||
*/
|
||||
export function limitTimeDiscount(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/limitTimeDiscount`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const urlType='market'
|
||||
|
||||
export function getConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function editConfig(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function levelList(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member/level/list`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function orderList(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member/order`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function levelAdd(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member/level`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function levelEdit(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member/level`,
|
||||
method: "PUT",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
export function levelDel(id) {
|
||||
return request({
|
||||
url: `${urlType}/admin/member/level/${id}`,
|
||||
method: "DELETE",
|
||||
})
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const MARKET_URL = 'market'
|
||||
const ORDER_URL = 'order'
|
||||
|
||||
/**
|
||||
* 积分:配置:新增/更新
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsConfigPost(data) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/points/config`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:配置:详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsConfigGet() {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/points/config`,
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:商品:列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsGoodsPage(data) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/pointsGoods/page`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:商品:新增/修改
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsGoodsPost(data) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/pointsGoods`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分-商品-删除
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsGoodsDel(id) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/pointsGoods/${id}`,
|
||||
method: "DELETE"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:商品:详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointsGoodsDetail(id) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/pointsGoods/${id}`,
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:积分商品:兑换记录
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function goodsRecordPage(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/points/goodsRecord/page`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:积分商品:商家核销
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function goodsRecordCkecout(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/points/goodsRecord/checkout`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:积分商品:同意退单
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function goodsRecordAgreeRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/points/goodsRecord/agreeRefund`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:积分商品:驳回退单
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function goodsRecordRejectRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/points/goodsRecord/rejectRefund`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:获取用户所有门店下积分列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointUserPage(data) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/points/userPage`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 积分:积分详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function pointUserRecord(data) {
|
||||
return request({
|
||||
url: `${MARKET_URL}/admin/points/userRecord`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function enable(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption/enable`,
|
||||
method: "PUT",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function status(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption/enable/status`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function couponRedemption(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function couponRedemptionList(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption/list`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function add(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption`,
|
||||
method: "POST",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function edit(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption`,
|
||||
method: "PUT",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function codeList(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/rechargeRedemption/code/list`,
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function codeExport(params) {
|
||||
return http.download({
|
||||
url: urlType + `/admin/rechargeRedemption/code/export`,
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "market";
|
||||
|
||||
export function suggestPage(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/suggest/page`,
|
||||
method: "get",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function addSuggest(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/suggest`,
|
||||
method: "POST",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function editSuggest(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/suggest`,
|
||||
method: "PUT",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
export function deleteSuggest(params) {
|
||||
return request({
|
||||
url: urlType + `/admin/suggest?id=${params.id}`,
|
||||
method: "DELETE",
|
||||
params: {
|
||||
...params,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const prveUrl='account'
|
||||
export function getMenus() {
|
||||
return request({
|
||||
url: `${prveUrl}/admin/menus`,
|
||||
method: "GET",
|
||||
})
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "order";
|
||||
|
||||
export function tableSummaryList(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/table/summary/list`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function saleSummaryPage(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/sale/summary/page`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function saleSummaryCount(data) {
|
||||
return request({
|
||||
url: `${urlType}/admin/sale/summary/count`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -8,7 +8,7 @@ const request = http.request
|
||||
export function getOrderPayUrl(data, urlType = 'order') {
|
||||
return request({
|
||||
url: `${urlType}/pay/shopPayApi/orderPayUrl`,
|
||||
method: "POST",
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
@@ -98,13 +98,3 @@ export function queryOrderStatus(data, urlType = 'order') {
|
||||
}
|
||||
})
|
||||
}
|
||||
// 分销员开通支付
|
||||
export function mchRecharge(data, urlType = 'order') {
|
||||
return request({
|
||||
url: `${urlType}/pay/distribution/mchRecharge`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -5,7 +5,7 @@ const request = http.request
|
||||
* 获取商品分页
|
||||
* @returns
|
||||
*/
|
||||
export function getProductPage(data, urlType = 'product', showLoading) {
|
||||
export function getProductPage(data, urlType = 'product' ,showLoading) {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/page`,
|
||||
method: "GET",
|
||||
@@ -20,7 +20,7 @@ export function getProductPage(data, urlType = 'product', showLoading) {
|
||||
* 获取商品列表
|
||||
* @returns
|
||||
*/
|
||||
export function getProductList(data, urlType = 'product', showLoading) {
|
||||
export function getProductList(data, urlType = 'product' ,showLoading) {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/list`,
|
||||
method: "GET",
|
||||
@@ -36,11 +36,11 @@ export function getProductList(data, urlType = 'product', showLoading) {
|
||||
* 获取商品详情
|
||||
* @returns
|
||||
*/
|
||||
export function getProductDetail(id, urlType = 'product') {
|
||||
export function getProductDetail (id, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/${id}`,
|
||||
method: "GET",
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export function delProduct(id, urlType = 'product') {
|
||||
* 商品上下架
|
||||
* @returns
|
||||
*/
|
||||
export function productOnOff(data, urlType = 'product') {
|
||||
export function productOnOff (data, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/onOff`,
|
||||
method: "POST",
|
||||
@@ -87,7 +87,7 @@ export function productOnOff(data, urlType = 'product') {
|
||||
* 商品售罄
|
||||
* @returns
|
||||
*/
|
||||
export function productMarkIsSoldOut(data, urlType = 'product') {
|
||||
export function productMarkIsSoldOut (data, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/markIsSoldOut`,
|
||||
method: "POST",
|
||||
@@ -262,7 +262,7 @@ export function delSpec(id, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/prod/spec/${id}`,
|
||||
method: "DELETE",
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -343,28 +343,4 @@ export function delProdGroup(id, urlType = 'product') {
|
||||
url: `${urlType}/admin/prod/group/${id}`,
|
||||
method: "DELETE",
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库单识别
|
||||
* @returns
|
||||
*/
|
||||
export function stockOcr(data, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/stock/ocr`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* ocr识别结果
|
||||
* @returns
|
||||
*/
|
||||
export function ocrResult(data, urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/stock/ocrResult`,
|
||||
method: "get",
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import http from "@/http/http.js";
|
||||
const request = http.request;
|
||||
const urlType = "product";
|
||||
|
||||
export function stickCount(file, data) {
|
||||
return http.upload(`${urlType}/admin/stick/count`,data,file)
|
||||
}
|
||||
@@ -56,17 +56,3 @@ export function editShopExtend(data, urlType = 'account') {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门店列表
|
||||
* @returns
|
||||
*/
|
||||
export function getShopList(data, urlType = 'account') {
|
||||
return request({
|
||||
url: `${urlType}/admin/shopInfo/branchList`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export function getShopTable(data, urlType = 'account') {
|
||||
*/
|
||||
export function getShopTableDetail(data, urlType = 'account') {
|
||||
return request({
|
||||
url: `/account/admin/shopTable/detail`,
|
||||
url: `${urlType}/admin/shopTable/detail`,
|
||||
method: "GET",
|
||||
data: {
|
||||
...data
|
||||
|
||||
@@ -15,18 +15,6 @@ export function getVendorPage(data, urlType = 'product') {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取供应商列表/无分页
|
||||
* @returns
|
||||
*/
|
||||
export function getVendorList(urlType = 'product') {
|
||||
return request({
|
||||
url: `${urlType}/admin/product/vendor/list`,
|
||||
method: "GET"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加供应商
|
||||
* @returns
|
||||
@@ -64,4 +52,5 @@ export function delVendor(id, urlType = 'product') {
|
||||
url: `${urlType}/admin/product/vendor/${id}`,
|
||||
method: "DELETE",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
303
http/api/ware.js
303
http/api/ware.js
@@ -1,303 +0,0 @@
|
||||
import http from '@/http/http.js'
|
||||
const request = http.request
|
||||
const ORDER_URL = 'order'
|
||||
const Market_BaseUrl = 'market'
|
||||
|
||||
/**
|
||||
* 拼团商品-列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function getGbWarePage(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/getGbWarePage`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品-新增
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function addGbWare(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/addGbWare`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品-列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function updateGbWareById(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/updateGbWareById`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品-修改状态
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function editOnlineStatus(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/editOnlineStatus`,
|
||||
method: "post",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品-删除
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function deleteGbWare(id) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/deleteGbWare/${id}`,
|
||||
method: "DELETE"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品:订单列表
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function gbOrderPage(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/gbOrder/page`,
|
||||
method: "GET",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品-活动开关
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function upShopConfig(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/upShopConfig`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团订单-退单/同意退单
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function agreeRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/gbOrder/agreeRefund`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团订单-驳回退单
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function rejectRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/gbOrder/rejectRefund`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品:核销
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function checkout(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/gbOrder/checkout`,
|
||||
method: "POST",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼团商品:拼团商品详情
|
||||
* @param {Object} data
|
||||
*/
|
||||
export function wareDetail(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ware/ware/detail`,
|
||||
method: "get",
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:添加套餐
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageAddEdit(data) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package`,
|
||||
method: data.id ? 'put' : 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:获取套餐列表
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageGet(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package`,
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:获取套餐推广开关
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageSwitchGet() {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/switch`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:修改套餐推广开关
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageSwitchPut(data) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/switch`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:删除套餐
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageDel(id) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/${id}`,
|
||||
method: 'DELETE'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:确认删除套餐
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageSureDel(id) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/sure/${id}`,
|
||||
method: 'DELETE'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:修改套餐推广开关
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageOnline(data) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/online`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:获取套餐推广订单列表
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageOrder(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/order`,
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:订单统计
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageOrderStat(params) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/order/stat`,
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:确认退单
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageConfirmRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ppOrder/confirmRefund`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:驳回退单
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageRejectRefund(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ppOrder/rejectRefund`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:核销
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageCheckout(data) {
|
||||
return request({
|
||||
url: `${ORDER_URL}/admin/ppOrder/checkout`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 套餐推广:获取套餐详情
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function packageDetail(data) {
|
||||
return request({
|
||||
url: `${Market_BaseUrl}/admin/package/detail/${data.id}`,
|
||||
method: 'GET',
|
||||
data: {
|
||||
shopId: data.shopId
|
||||
}
|
||||
});
|
||||
}
|
||||
416
http/http.js
416
http/http.js
@@ -1,26 +1,26 @@
|
||||
/**
|
||||
* HTTP的封装, 基于uni.request
|
||||
* 包括: 通用响应结果的处理 和 业务的增删改查函数
|
||||
*
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021/12/16 18:35
|
||||
*/
|
||||
// 设置env配置文件
|
||||
import envConfig from "@/env/config.js";
|
||||
import envConfig from '@/env/config.js'
|
||||
// 导入全局属性
|
||||
import appConfig from "@/config/appConfig.js";
|
||||
import storageManage from "@/commons/utils/storageManage.js";
|
||||
import infoBox from "@/commons/utils/infoBox.js";
|
||||
import go from "@/commons/utils/go.js";
|
||||
import { reject } from "lodash";
|
||||
import appConfig from '@/config/appConfig.js'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import { sm4DecryptByResData } from '@/commons/utils/encryptUtil.js'
|
||||
import infoBox from "@/commons/utils/infoBox.js"
|
||||
import go from '@/commons/utils/go.js';
|
||||
import { reject } from 'lodash';
|
||||
// 设置node环境
|
||||
envConfig.changeEnv(storageManage.env('production')) //正式
|
||||
// envConfig.changeEnv(storageManage.env("development")); //测试
|
||||
envConfig.changeEnv(storageManage.env())
|
||||
|
||||
// 测试服
|
||||
// #ifdef H5
|
||||
let baseUrl = "/javaapi/";
|
||||
let baseUrl = '/api/'
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// let baseUrl = 'https://tapi.cashier.sxczgkj.cn/'
|
||||
@@ -29,247 +29,215 @@ let baseUrl = "/javaapi/";
|
||||
|
||||
//正式
|
||||
// let baseUrl = 'https://cashier.sxczgkj.com/'
|
||||
let baseUrl = appConfig.env.JEEPAY_BASE_URL;
|
||||
let baseUrl = appConfig.env.JEEPAY_BASE_URL
|
||||
// #endif
|
||||
|
||||
const loadingShowTime = 200;
|
||||
const loadingShowTime = 200
|
||||
|
||||
function getHeader() {
|
||||
const headerObject = {};
|
||||
headerObject["token"] = storageManage.token();
|
||||
headerObject["shopId"] = uni.getStorageSync("shopInfo").id;
|
||||
headerObject["platformType"] = "APP";
|
||||
|
||||
return headerObject;
|
||||
function getHeader(){
|
||||
const headerObject={}
|
||||
headerObject["token"] = storageManage.token()
|
||||
headerObject["shopId"] = uni.getStorageSync("shopInfo").id
|
||||
headerObject["platformType"] = 'APP'
|
||||
|
||||
return headerObject
|
||||
}
|
||||
|
||||
// 通用处理逻辑
|
||||
// 通用处理逻辑
|
||||
function commonsProcess(showLoading, httpReqCallback) {
|
||||
// 判断是否请求完成(用作 是否loading )
|
||||
// 包括: 'ing', 'ingLoading', 'finish'
|
||||
let reqState = "ing";
|
||||
|
||||
// 是否已经提示的错误信息
|
||||
let isShowErrorToast = false;
|
||||
// 判断是否请求完成(用作 是否loading )
|
||||
// 包括: 'ing', 'ingLoading', 'finish'
|
||||
let reqState = 'ing'
|
||||
|
||||
// 请求完成, 需要处理的动作
|
||||
let reqFinishFunc = () => {
|
||||
if (reqState == "ingLoading") {
|
||||
// 关闭loading弹层
|
||||
infoBox.hideLoading();
|
||||
}
|
||||
reqState = "finish"; // 请求完毕
|
||||
};
|
||||
// 是否已经提示的错误信息
|
||||
let isShowErrorToast = false
|
||||
|
||||
// 明确显示loading
|
||||
if (showLoading) {
|
||||
// xx ms内响应完成,不提示loading
|
||||
setTimeout(() => {
|
||||
if (reqState == "ing") {
|
||||
reqState = "ingLoading";
|
||||
infoBox.showLoading();
|
||||
}
|
||||
}, loadingShowTime);
|
||||
}
|
||||
|
||||
return httpReqCallback()
|
||||
.then((httpData) => {
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
// 从http响应数据中解构响应数据 [ 响应码、 bodyData ]
|
||||
let { statusCode, data } = httpData;
|
||||
// 避免混淆重新命名
|
||||
let bodyData = data;
|
||||
if (statusCode == 500) {
|
||||
isShowErrorToast = true;
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
if (statusCode == 501) {
|
||||
// storageManage.token(null, true)
|
||||
// 提示信息
|
||||
isShowErrorToast = true;
|
||||
// infoBox.showErrorToast('请登录').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
// http响应码不正确
|
||||
if (statusCode != 200 && statusCode != 204 && statusCode != 201) {
|
||||
isShowErrorToast = true;
|
||||
bodyData.msg =
|
||||
bodyData.msg == "Bad credentials" ? "用户名或密码错误" : bodyData.msg;
|
||||
infoBox.showToast(bodyData.msg || "服务器异常");
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
// 请求完成, 需要处理的动作
|
||||
let reqFinishFunc = () => {
|
||||
|
||||
// // 业务响应异常
|
||||
if (bodyData.hasOwnProperty("code") && bodyData.code != 200) {
|
||||
isShowErrorToast = true;
|
||||
infoBox.showToast(bodyData.msg);
|
||||
// if (bodyData.code == 5005) { // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.reLaunch({
|
||||
// url: '/pageUser/setting/updatePwd'
|
||||
// })
|
||||
// }
|
||||
// if(bodyData.code == 500){ // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.redirectTo({url: '/pages/login/index'})
|
||||
// }
|
||||
return Promise.reject(bodyData); // 跳转到catch函数
|
||||
}
|
||||
if (reqState == 'ingLoading') { // 关闭loading弹层
|
||||
infoBox.hideLoading()
|
||||
}
|
||||
reqState = 'finish' // 请求完毕
|
||||
}
|
||||
|
||||
// 构造请求成功的响应数据
|
||||
return Promise.resolve(bodyData.data);
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log(res);
|
||||
if (res.code == 501) {
|
||||
storageManage.token(null, true);
|
||||
infoBox.showToast("登录过期,请重新登录").then(() => {
|
||||
uni.redirectTo({ url: "/pages/login/index" });
|
||||
reject();
|
||||
});
|
||||
}
|
||||
// if(res.status==400){
|
||||
// storageManage.token(null, true)
|
||||
// infoBox.showErrorToast('').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
// }
|
||||
if (res.code == 500) {
|
||||
infoBox.showToast(res.msg || "服务器异常").then(() => {});
|
||||
}
|
||||
// if(res&&res.msg){
|
||||
// infoBox.showErrorToast(res.msg)
|
||||
// }
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
// 明确显示loading
|
||||
if (showLoading) {
|
||||
// xx ms内响应完成,不提示loading
|
||||
setTimeout(() => {
|
||||
if (reqState == 'ing') {
|
||||
reqState = 'ingLoading'
|
||||
infoBox.showLoading()
|
||||
}
|
||||
}, loadingShowTime)
|
||||
}
|
||||
|
||||
// 如果没有提示错误, 那么此处提示 异常。
|
||||
if (!isShowErrorToast) {
|
||||
infoBox.showToast(`请求网络异常`);
|
||||
}
|
||||
return httpReqCallback().then((httpData) => {
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
// 从http响应数据中解构响应数据 [ 响应码、 bodyData ]
|
||||
let {
|
||||
statusCode,
|
||||
data
|
||||
} = httpData
|
||||
// 避免混淆重新命名
|
||||
let bodyData = data
|
||||
if (statusCode == 500) {
|
||||
isShowErrorToast = true
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
if (statusCode == 501) {
|
||||
// storageManage.token(null, true)
|
||||
// 提示信息
|
||||
isShowErrorToast = true
|
||||
// infoBox.showErrorToast('请登录').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
// http响应码不正确
|
||||
if (statusCode != 200 && statusCode != 204 && statusCode != 201) {
|
||||
isShowErrorToast = true
|
||||
bodyData.msg=bodyData.msg=='Bad credentials'?'用户名或密码错误':bodyData.msg
|
||||
infoBox.showToast(bodyData.msg || '服务器异常')
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
|
||||
// // 业务响应异常
|
||||
if (bodyData.hasOwnProperty('code') && bodyData.code != 200) {
|
||||
isShowErrorToast = true
|
||||
infoBox.showToast(bodyData.msg)
|
||||
// if (bodyData.code == 5005) { // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.reLaunch({
|
||||
// url: '/pageUser/setting/updatePwd'
|
||||
// })
|
||||
// }
|
||||
// if(bodyData.code == 500){ // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.redirectTo({url: '/pages/login/index'})
|
||||
// }
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
|
||||
// 加密数据
|
||||
if (!bodyData.data && bodyData.encryptData) {
|
||||
return Promise.resolve({
|
||||
bizData: sm4DecryptByResData(bodyData.encryptData),
|
||||
code: bodyData.code
|
||||
})
|
||||
}
|
||||
|
||||
// 构造请求成功的响应数据
|
||||
return Promise.resolve(bodyData.data)
|
||||
|
||||
}).catch(res => {
|
||||
console.log(res)
|
||||
if(res.code==501){
|
||||
storageManage.token(null, true)
|
||||
infoBox.showToast('登录过期,请重新登录').then(() => {
|
||||
uni.redirectTo({url: '/pages/login/index'})
|
||||
reject()
|
||||
})
|
||||
}
|
||||
// if(res.status==400){
|
||||
// storageManage.token(null, true)
|
||||
// infoBox.showErrorToast('').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
// }
|
||||
if(res.code==500){
|
||||
infoBox.showToast(res.msg||'服务器异常').then(() => {})
|
||||
}
|
||||
// if(res&&res.msg){
|
||||
// infoBox.showErrorToast(res.msg)
|
||||
// }
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
|
||||
// 如果没有提示错误, 那么此处提示 异常。
|
||||
if (!isShowErrorToast) {
|
||||
infoBox.showToast(`请求网络异常`)
|
||||
}
|
||||
|
||||
return Promise.reject(res)
|
||||
|
||||
}).finally(() => { // finally 是 then结束后再执行, 此处不适用。 需要在请求完成后立马调用: reqFinishFunc()
|
||||
|
||||
});
|
||||
|
||||
return Promise.reject(res);
|
||||
})
|
||||
.finally(() => {
|
||||
// finally 是 then结束后再执行, 此处不适用。 需要在请求完成后立马调用: reqFinishFunc()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 默认 显示loading(控制 xxs 内 不提示loading )
|
||||
function req(uri, data, method = "GET", showLoading = true, extParams = {}) {
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign(
|
||||
{
|
||||
url: baseUrl + uri,
|
||||
data: data,
|
||||
method: method,
|
||||
header: getHeader(),
|
||||
},
|
||||
extParams
|
||||
)
|
||||
);
|
||||
});
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign({
|
||||
url: baseUrl + uri,
|
||||
data: data,
|
||||
method: method,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 默认 显示loading(控制 xxs 内 不提示loading )
|
||||
function request(args) {
|
||||
const {
|
||||
url,
|
||||
data,
|
||||
params,
|
||||
method = "GET",
|
||||
showLoading = true,
|
||||
extParams = {},
|
||||
} = args;
|
||||
let headerObject = {};
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign(
|
||||
{
|
||||
url: baseUrl + url,
|
||||
data: params || data,
|
||||
method: method,
|
||||
header: getHeader(),
|
||||
},
|
||||
extParams
|
||||
)
|
||||
);
|
||||
});
|
||||
const {
|
||||
url,
|
||||
data,
|
||||
params,
|
||||
method = "GET",
|
||||
showLoading = true,
|
||||
extParams = {}
|
||||
} = args
|
||||
let headerObject = {}
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign({
|
||||
url: baseUrl + url,
|
||||
data: params||data,
|
||||
method: method,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 上传
|
||||
function upload(uri, data, file, showLoading = true, extParams = {}) {
|
||||
// 放置token
|
||||
let headerObject = {};
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni
|
||||
.uploadFile(
|
||||
Object.assign(
|
||||
{
|
||||
url: baseUrl + uri,
|
||||
formData: data,
|
||||
name: "file",
|
||||
filePath: file.path || file.url ||file,
|
||||
header: getHeader(),
|
||||
},
|
||||
extParams
|
||||
)
|
||||
)
|
||||
.then((httpData) => {
|
||||
// uni.upload 返回bodyData 的是 string类型。 需要解析。
|
||||
httpData.data = JSON.parse(httpData.data);
|
||||
return Promise.resolve(httpData);
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading();
|
||||
infoBox.showErrorToast(`上传失败`);
|
||||
});
|
||||
});
|
||||
}
|
||||
// 放置token
|
||||
let headerObject = {}
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
|
||||
function returnParams(params) {
|
||||
let returnStr = "";
|
||||
if (params) {
|
||||
returnStr = "?";
|
||||
for (let key in params) {
|
||||
returnStr += `${key}=${params[key]}&`;
|
||||
}
|
||||
returnStr = returnStr.substring(0, returnStr.length - 1);
|
||||
}
|
||||
return returnStr;
|
||||
}
|
||||
// 下载文件
|
||||
function download(args) {
|
||||
const {
|
||||
url,
|
||||
data,
|
||||
params,
|
||||
method = "GET",
|
||||
showLoading = true,
|
||||
extParams = {},
|
||||
} = args;
|
||||
let headerObject = {};
|
||||
return uni
|
||||
.downloadFile({
|
||||
url: baseUrl + url + returnParams(params),
|
||||
|
||||
header: getHeader(),
|
||||
})
|
||||
.then((httpData) => {
|
||||
return Promise.resolve(httpData);
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading();
|
||||
infoBox.showErrorToast(`下载失败`);
|
||||
});
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.uploadFile(
|
||||
Object.assign({
|
||||
url: baseUrl + uri,
|
||||
formData: data,
|
||||
name: "file",
|
||||
filePath: file.path||file.url,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
).then((httpData) => {
|
||||
// uni.upload 返回bodyData 的是 string类型。 需要解析。
|
||||
httpData.data = JSON.parse(httpData.data)
|
||||
return Promise.resolve(httpData)
|
||||
}).catch(err=>{
|
||||
uni.hideLoading()
|
||||
infoBox.showErrorToast(`上传失败`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
req: req,
|
||||
request,
|
||||
upload: upload,
|
||||
download,
|
||||
};
|
||||
req: req,
|
||||
request,
|
||||
upload: upload
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import { request } from "./request";
|
||||
const prveUrl = "chat/";
|
||||
|
||||
/**
|
||||
* 群消息
|
||||
* @param {Object} data
|
||||
* @returns
|
||||
*/
|
||||
export const groupInfo = (data) => {
|
||||
return request(prveUrl + "group/info", "POST", data, true);
|
||||
};
|
||||
|
||||
export const commonPhrase = (data) => {
|
||||
return request(prveUrl + "common-phrase/index", "POST", data, true);
|
||||
};
|
||||
export const commonPhraseAdd = (data) => {
|
||||
return request(prveUrl + "common-phrase/add", "POST", data, true);
|
||||
};
|
||||
|
||||
|
||||
export const commonPhraseDel = (data) => {
|
||||
return request(prveUrl + "common-phrase/del", "POST", data, true);
|
||||
};
|
||||
|
||||
|
||||
export const groupCreate = (data) => {
|
||||
return request(prveUrl + "group/create", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupJoin = (data) => {
|
||||
return request(prveUrl + "group/join", "POST", data, true);
|
||||
};
|
||||
export const groupGetGroupUrl = (data) => {
|
||||
return request(prveUrl + "group/getgrepurl", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupQuit = (data) => {
|
||||
return request(prveUrl + "group/quit", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupTarsGroup = (data) => {
|
||||
return request(prveUrl + "group/tarsgroup", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupAnnouncement = (data) => {
|
||||
return request(prveUrl + "group/announcement", "POST", data, true);
|
||||
};
|
||||
export const groupMute = (data) => {
|
||||
return request(prveUrl + "group/mute", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupMunute = (data) => {
|
||||
return request(prveUrl + "group/unmute", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupKick = (data) => {
|
||||
return request(prveUrl + "group/kick", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupMembers = (data) => {
|
||||
return request(prveUrl + "group/members", "POST", data, true);
|
||||
};
|
||||
|
||||
|
||||
export const messageHistory = (data) => {
|
||||
return request(prveUrl + "message/history", "POST", data, true);
|
||||
};
|
||||
|
||||
export const messageMarkRead = (data) => {
|
||||
return request(prveUrl + "message/mark-read", "POST", data, true);
|
||||
};
|
||||
|
||||
export const messageMarkReadAll = (data) => {
|
||||
return request(prveUrl + "message/mark-read-all", "POST", data, true);
|
||||
};
|
||||
|
||||
export const messageUnreadCount = (data) => {
|
||||
return request(prveUrl + "message/unread-count", "POST", data, true);
|
||||
};
|
||||
|
||||
export const messageSessionList = (data) => {
|
||||
return request(prveUrl + "message/sessionlist", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupDoNotDisturb = (data) => {
|
||||
return request(prveUrl + "group/do-not-disturb", "POST", data, true);
|
||||
};
|
||||
|
||||
export const groupEditTitle = (data) => {
|
||||
return request(prveUrl + "group/editTitle", "POST", data, true);
|
||||
};
|
||||
|
||||
@@ -1,100 +1,80 @@
|
||||
//服务器接口地址
|
||||
// const baseURL : string = 'https://newblockwlx.sxczgkj.cn/index.php/api/'
|
||||
let baseURL: string = "http://192.168.1.42:8787/api/";
|
||||
// #ifdef H5
|
||||
baseURL = "/phpapi/api/";
|
||||
// #endif
|
||||
|
||||
import go from "@/commons/utils/go.js";
|
||||
|
||||
const baseURL : string = 'https://newblockwlx.sxczgkj.cn/index.php/api/'
|
||||
// 封装公共请求方法
|
||||
function request(
|
||||
url: string,
|
||||
method: "GET" | "POST" | undefined,
|
||||
data: object | any,
|
||||
toast: boolean
|
||||
) {
|
||||
let networkType = "";
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
networkType = res.networkType;
|
||||
},
|
||||
});
|
||||
if (networkType == "none") {
|
||||
uni.showToast({
|
||||
title: "网络异常,请检查网络",
|
||||
icon: "none",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (toast) {
|
||||
uni.showLoading({
|
||||
title: "加载中",
|
||||
mask: true,
|
||||
});
|
||||
}
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let header: any;
|
||||
header = {
|
||||
"content-type": "application/json",
|
||||
clinttype: uni.getStorageSync("clint_type"),
|
||||
bausertoken: uni.getStorageSync("phpuserinfo").token || "",
|
||||
token: uni.getStorageSync("iToken").tokenValue || "",
|
||||
};
|
||||
uni.request({
|
||||
url: baseURL + url,
|
||||
method: method,
|
||||
data: data,
|
||||
header: header,
|
||||
success(res: any) {
|
||||
if (res.data.code != 1) {
|
||||
if (res.data.code === 3000) {
|
||||
uni.hideLoading();
|
||||
go.to("PAGES_LOGIN", {}, "redirect");
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
//是否提示错误
|
||||
if (toast) {
|
||||
uni.showToast({
|
||||
title: res.data.msg || res.data.message,
|
||||
icon: "none",
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.hideLoading();
|
||||
}, 1000);
|
||||
}
|
||||
if (res.data.code == 401) {
|
||||
uni.showToast({
|
||||
title: res.message || res.msg,
|
||||
icon: "none",
|
||||
success: () => {
|
||||
// uni.removeStorageSync('logintoken');
|
||||
// uni.removeStorageSync('token');
|
||||
uni.reLaunch({
|
||||
url: "/pages/index/index",
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
uni.hideLoading();
|
||||
reject(res.message | res.msg);
|
||||
} else {
|
||||
uni.hideLoading();
|
||||
console.log(res);
|
||||
resolve(res.data.data);
|
||||
}
|
||||
},
|
||||
fail(err) {
|
||||
uni.hideLoading();
|
||||
//请求失败
|
||||
uni.showToast({
|
||||
title: "无法连接到服务器",
|
||||
icon: "none",
|
||||
});
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
function request(url : string, method : "GET" | "POST" | undefined, data : object | any, toast : boolean) {
|
||||
let networkType = ''
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
networkType = res.networkType
|
||||
}
|
||||
});
|
||||
if (networkType == 'none') {
|
||||
uni.showToast({
|
||||
title: '网络异常,请检查网络',
|
||||
icon: 'none'
|
||||
})
|
||||
return false;
|
||||
}
|
||||
if (toast) {
|
||||
uni.showLoading({
|
||||
title: '加载中',
|
||||
mask: true
|
||||
})
|
||||
}
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let header : any
|
||||
header = {
|
||||
'content-type': 'application/json',
|
||||
'clinttype':uni.getStorageSync('clint_type'),
|
||||
'bausertoken': uni.getStorageSync('phpuserinfo').token
|
||||
};
|
||||
uni.request({
|
||||
url: baseURL + url,
|
||||
method: method,
|
||||
data: data,
|
||||
header: header,
|
||||
success(res : any) {
|
||||
if (res.data.code != 1) {
|
||||
//是否提示错误
|
||||
if (toast) {
|
||||
uni.showToast({
|
||||
title: res.data.msg || res.data.message,
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.hideLoading()
|
||||
}, 1000)
|
||||
}
|
||||
if (res.data.code == 401) {
|
||||
uni.showToast({
|
||||
title: res.message || res.msg,
|
||||
icon: "none",
|
||||
success: () => {
|
||||
// uni.removeStorageSync('logintoken');
|
||||
// uni.removeStorageSync('token');
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
uni.hideLoading()
|
||||
reject(res.message | res.msg);
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
resolve(res.data.data);
|
||||
}
|
||||
},
|
||||
fail(err) {
|
||||
uni.hideLoading()
|
||||
//请求失败
|
||||
uni.showToast({
|
||||
title: '无法连接到服务器',
|
||||
icon: 'none'
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
export { request, baseURL };
|
||||
export { request, baseURL }
|
||||
@@ -1,415 +0,0 @@
|
||||
// 代课下单
|
||||
import http from '@/http/yskApi/http.js'
|
||||
|
||||
import { accountUrl, marketUrl } from './prveUrl.js'
|
||||
|
||||
const request = http.request
|
||||
|
||||
|
||||
//就餐形式,默认堂食后付费
|
||||
const useType = 'dine-in-after'
|
||||
|
||||
function getUseType() {
|
||||
const type = uni.getStorageSync("useType")
|
||||
return type ? type : useType
|
||||
}
|
||||
// import {
|
||||
// webscoketUtill
|
||||
// } from '../websock.js'
|
||||
// let wxObj = null
|
||||
// wx初始化购物车
|
||||
// export function getWXCart(params) {
|
||||
// let wxUrl = 'ws://192.168.1.31:2348/?' + objectToString(params)
|
||||
// wxObj = new webscoketUtill(wxUrl,3000,9,(e)=>{
|
||||
// console.log('收到消息');
|
||||
// console.log(e);
|
||||
// })
|
||||
// return uni.getStorageSync('wxList')
|
||||
// }
|
||||
// 新增\删除\修改到购物车
|
||||
// export function addWXCart(params) {
|
||||
// wxObj.ws.send(params)
|
||||
// }
|
||||
|
||||
|
||||
function objectToString(obj) {
|
||||
let result = '';
|
||||
for (const key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
result += `${key}=${obj[key]}&`;
|
||||
}
|
||||
}
|
||||
// 去掉最后一个多余的 &
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
/**
|
||||
* 获取当前台桌订单信息
|
||||
* @returns
|
||||
*/
|
||||
export function getCart(params) {
|
||||
return request({
|
||||
url: `/api/place/cart`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...params
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 已上架商品列表
|
||||
* @returns
|
||||
*/
|
||||
export function getGoodsLists(params, showLoading = true) {
|
||||
return request({
|
||||
url: `/product/admin/product/list`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...params
|
||||
},
|
||||
showLoading
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点单
|
||||
* @returns
|
||||
*/
|
||||
export function addCart(data) {
|
||||
return request({
|
||||
url: `/api/place/addCart`,
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空购物车/支付订单
|
||||
* @returns
|
||||
*/
|
||||
export function $clearCart(data) {
|
||||
return request({
|
||||
url: `/api/place/clearCart`,
|
||||
method: "delete",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除购物车某个商品
|
||||
* @returns
|
||||
*/
|
||||
export function $removeCart(data) {
|
||||
return request({
|
||||
url: `/api/place/removeCart`,
|
||||
method: "delete",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 更新规格
|
||||
* @returns
|
||||
*/
|
||||
export function $updateCart(data) {
|
||||
return request({
|
||||
url: `/api/place/updateCart`,
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 批量打包
|
||||
* @returns
|
||||
*/
|
||||
export function $allPack(data) {
|
||||
return request({
|
||||
url: `/api/place/pack`,
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取取餐号
|
||||
* @returns
|
||||
*/
|
||||
export function $getMasterId(data) {
|
||||
return request({
|
||||
url: `/api/place/masterId`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 支付方式获取
|
||||
* @returns
|
||||
*/
|
||||
export function $getPayType(data) {
|
||||
return request({
|
||||
url: `/account/admin/payType`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 创建订单
|
||||
* @returns
|
||||
*/
|
||||
export function $createOrder(data) {
|
||||
return request({
|
||||
url: `/api/place/order`,
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 挂起订单
|
||||
* @returns
|
||||
*/
|
||||
export function $cacheOrder(data) {
|
||||
return request({
|
||||
url: `/api/place/pending`,
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已挂起订单
|
||||
* @returns
|
||||
*/
|
||||
export function $getCacheOrder(data) {
|
||||
return request({
|
||||
url: `/api/place/pending/cart`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 会员点单/取消会员点单
|
||||
export function $setUser(data) {
|
||||
return request({
|
||||
url: `/api/place/updateVip`,
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
// 删除订单
|
||||
export function $delOrder(data) {
|
||||
return request({
|
||||
url: `/api/place/order`,
|
||||
method: "delete",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
// 支付订单
|
||||
export function $payOrder(data) {
|
||||
return request({
|
||||
url: '/api/place/pay',
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
//退单
|
||||
|
||||
export function $returnCart(data) {
|
||||
return request({
|
||||
url: '/api/place/returnCart',
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
// 选择台桌
|
||||
export function $choseTable(data) {
|
||||
return request({
|
||||
url: '/api/place/choseTable',
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
// 用餐人数
|
||||
|
||||
export function $choseCount(data) {
|
||||
return request({
|
||||
url: '/api/place/choseCount',
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
useType: getUseType(),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 批量生成台桌
|
||||
export function $fastCreateTable(data) {
|
||||
return request({
|
||||
url: '/api/tbShopTable/generate',
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//打印当前台桌订单
|
||||
export function $printOrder(data) {
|
||||
return request({
|
||||
url: '/api/place/printOrder',
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
//打印当前台桌菜品
|
||||
|
||||
export function $printDishes(data) {
|
||||
return request({
|
||||
url: '/api/place/printDishes',
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 就餐模式切换
|
||||
export function $changeUseType(data) {
|
||||
return request({
|
||||
url: '/api/place/choseModel',
|
||||
method: "put",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 退款
|
||||
export function $returnOrder(data) {
|
||||
return request({
|
||||
url: '/api/place/returnOrder',
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//获取用户可用优惠券
|
||||
export function $findCoupon(data) {
|
||||
return request({
|
||||
url: marketUrl+'/admin/coupon/findCoupon',
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//会员积分列表
|
||||
export function $returnMemberPointsList(data) {
|
||||
return request({
|
||||
url: '/api/points/member-points/page',
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 会员积分账户信息
|
||||
export function $returnMemberPoints(memberId) {
|
||||
return request({
|
||||
url: '/api/points/member-points/' + memberId,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
//002-获取订单可用积分及抵扣金额(支付页面使用)
|
||||
export function $calcUsablePoints(data) {
|
||||
return request({
|
||||
url: '/api/points/member-points/calc-usable-points',
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
// 003-根据积分计算可抵扣金额
|
||||
export function $calcDeDuctionPoints(data) {
|
||||
return request({
|
||||
url: '/api/points/member-points/calc-deduction-amount',
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync("shopId"),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/**
|
||||
* HTTP的封装, 基于uni.request
|
||||
* 包括: 通用响应结果的处理 和 业务的增删改查函数
|
||||
*
|
||||
* @author terrfly
|
||||
* @site https://www.jeequan.com
|
||||
* @date 2021/12/16 18:35
|
||||
*/
|
||||
// 设置env配置文件
|
||||
import envConfig from '@/env/config.js'
|
||||
// 导入全局属性
|
||||
import appConfig from '@/config/appConfig.js'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import infoBox from "@/commons/utils/infoBox.js"
|
||||
import go from '@/commons/utils/go.js';
|
||||
import { reject } from 'lodash';
|
||||
// 设置node环境
|
||||
// envConfig.changeEnv(storageManage.env('production'))
|
||||
|
||||
// 测试服
|
||||
// #ifdef H5
|
||||
let baseUrl = '/api/'
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// let baseUrl = 'https://tapi.cashier.sxczgkj.cn/'
|
||||
//预发布
|
||||
// let baseUrl = 'https://pre-cashieradmin.sxczgkj.cn'
|
||||
|
||||
//正式
|
||||
// let baseUrl = 'https://cashier.sxczgkj.com/'
|
||||
let baseUrl = appConfig.env.JEEPAY_BASE_URL
|
||||
// #endif
|
||||
|
||||
const loadingShowTime = 200
|
||||
|
||||
function getHeader(){
|
||||
const headerObject={}
|
||||
headerObject["token"] = storageManage.token()
|
||||
headerObject["shopId"] = uni.getStorageSync("shopInfo").id
|
||||
headerObject["platformType"] = 'APP'
|
||||
|
||||
return headerObject
|
||||
}
|
||||
|
||||
// 通用处理逻辑
|
||||
function commonsProcess(showLoading, httpReqCallback) {
|
||||
|
||||
// 判断是否请求完成(用作 是否loading )
|
||||
// 包括: 'ing', 'ingLoading', 'finish'
|
||||
let reqState = 'ing'
|
||||
|
||||
// 是否已经提示的错误信息
|
||||
let isShowErrorToast = false
|
||||
|
||||
|
||||
// 请求完成, 需要处理的动作
|
||||
let reqFinishFunc = () => {
|
||||
|
||||
if (reqState == 'ingLoading') { // 关闭loading弹层
|
||||
infoBox.hideLoading()
|
||||
}
|
||||
reqState = 'finish' // 请求完毕
|
||||
}
|
||||
|
||||
// 明确显示loading
|
||||
if (showLoading) {
|
||||
// xx ms内响应完成,不提示loading
|
||||
setTimeout(() => {
|
||||
if (reqState == 'ing') {
|
||||
reqState = 'ingLoading'
|
||||
infoBox.showLoading()
|
||||
}
|
||||
}, loadingShowTime)
|
||||
}
|
||||
|
||||
return httpReqCallback().then((httpData) => {
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
// 从http响应数据中解构响应数据 [ 响应码、 bodyData ]
|
||||
let {
|
||||
statusCode,
|
||||
data
|
||||
} = httpData
|
||||
// 避免混淆重新命名
|
||||
let bodyData = data
|
||||
if (statusCode == 500) {
|
||||
isShowErrorToast = true
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
if (statusCode == 501) {
|
||||
// storageManage.token(null, true)
|
||||
// 提示信息
|
||||
isShowErrorToast = true
|
||||
// infoBox.showErrorToast('请登录').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
// http响应码不正确
|
||||
if (statusCode != 200 && statusCode != 204 && statusCode != 201) {
|
||||
isShowErrorToast = true
|
||||
bodyData.msg=bodyData.msg=='Bad credentials'?'用户名或密码错误':bodyData.msg
|
||||
infoBox.showToast(bodyData.msg || '服务器异常')
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
|
||||
// // 业务响应异常
|
||||
if (bodyData.hasOwnProperty('code') && bodyData.code != 200) {
|
||||
isShowErrorToast = true
|
||||
infoBox.showToast(bodyData.msg)
|
||||
// if (bodyData.code == 5005) { // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.reLaunch({
|
||||
// url: '/pageUser/setting/updatePwd'
|
||||
// })
|
||||
// }
|
||||
// if(bodyData.code == 500){ // 密码已过期, 直接跳转到更改密码页面
|
||||
// uni.redirectTo({url: '/pages/login/index'})
|
||||
// }
|
||||
return Promise.reject(bodyData) // 跳转到catch函数
|
||||
}
|
||||
|
||||
// 构造请求成功的响应数据
|
||||
return Promise.resolve(bodyData.data)
|
||||
|
||||
}).catch(res => {
|
||||
console.log(res)
|
||||
if(res.code==501){
|
||||
storageManage.token(null, true)
|
||||
infoBox.showToast('登录过期,请重新登录').then(() => {
|
||||
uni.redirectTo({url: '/pages/login/index'})
|
||||
reject()
|
||||
})
|
||||
}
|
||||
// if(res.status==400){
|
||||
// storageManage.token(null, true)
|
||||
// infoBox.showErrorToast('').then(() => {
|
||||
// go.to("PAGES_LOGIN", {}, go.GO_TYPE_RELAUNCH)
|
||||
// })
|
||||
// }
|
||||
if(res.code==500){
|
||||
infoBox.showToast(res.msg||'服务器异常').then(() => {})
|
||||
}
|
||||
// if(res&&res.msg){
|
||||
// infoBox.showErrorToast(res.msg)
|
||||
// }
|
||||
reqFinishFunc(); // 请求完毕的动作
|
||||
|
||||
// 如果没有提示错误, 那么此处提示 异常。
|
||||
if (!isShowErrorToast) {
|
||||
infoBox.showToast(`请求网络异常`)
|
||||
}
|
||||
|
||||
return Promise.reject(res)
|
||||
|
||||
}).finally(() => { // finally 是 then结束后再执行, 此处不适用。 需要在请求完成后立马调用: reqFinishFunc()
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 默认 显示loading(控制 xxs 内 不提示loading )
|
||||
function req(uri, data, method = "GET", showLoading = true, extParams = {}) {
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign({
|
||||
url: baseUrl + uri,
|
||||
data: data,
|
||||
method: method,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 默认 显示loading(控制 xxs 内 不提示loading )
|
||||
function request(args) {
|
||||
const {
|
||||
url,
|
||||
data,
|
||||
params,
|
||||
method = "GET",
|
||||
showLoading = true,
|
||||
extParams = {}
|
||||
} = args
|
||||
let headerObject = {}
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.request(
|
||||
Object.assign({
|
||||
url: baseUrl + url,
|
||||
data: params||data,
|
||||
method: method,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 上传
|
||||
function upload(uri, data, file, showLoading = true, extParams = {}) {
|
||||
// 放置token
|
||||
let headerObject = {}
|
||||
// headerObject[appConfig.tokenKey] = storageManage.token()
|
||||
|
||||
return commonsProcess(showLoading, () => {
|
||||
return uni.uploadFile(
|
||||
Object.assign({
|
||||
url: baseUrl + uri,
|
||||
formData: data,
|
||||
name: "file",
|
||||
filePath: file.path||file.url,
|
||||
header: getHeader()
|
||||
}, extParams)
|
||||
).then((httpData) => {
|
||||
// uni.upload 返回bodyData 的是 string类型。 需要解析。
|
||||
httpData.data = JSON.parse(httpData.data)
|
||||
return Promise.resolve(httpData)
|
||||
}).catch(err=>{
|
||||
uni.hideLoading()
|
||||
infoBox.showErrorToast(`上传失败`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
req: req,
|
||||
request,
|
||||
upload: upload
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import http from '@/http/yskApi/http.js'
|
||||
const request = http.request
|
||||
import {marketUrl} from './prveUrl.js'
|
||||
|
||||
/**
|
||||
* 限时折扣
|
||||
* @returns
|
||||
*/
|
||||
export function limitTimeDiscount(params) {
|
||||
return request({
|
||||
url: marketUrl+`/admin/limitTimeDiscount`,
|
||||
method: 'get',
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopInfo').id,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import http from '@/http/yskApi/http.js'
|
||||
|
||||
const request = http.request
|
||||
import {marketUrl} from '../prveUrl.js'
|
||||
|
||||
/**
|
||||
* 新客立减
|
||||
* @returns
|
||||
*/
|
||||
export function getDiscountByUserId(params) {
|
||||
return request({
|
||||
url: marketUrl+`/admin/consumeDiscount/getDiscountByUserId`,
|
||||
method: 'get',
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopInfo').id,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import http from '@/http/yskApi/http.js'
|
||||
|
||||
const request = http.request
|
||||
import {marketUrl} from '../prveUrl.js'
|
||||
|
||||
/**
|
||||
* 满减活动
|
||||
* @returns
|
||||
*/
|
||||
export function discountActivity(params) {
|
||||
console.log(uni.getStorageSync('shopInfo').id)
|
||||
return request({
|
||||
url: marketUrl+`/admin/discountActivity`,
|
||||
method: 'get',
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopInfo').id,
|
||||
...params
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
import http from '@/http/yskApi/http.js'
|
||||
|
||||
const request = http.request
|
||||
import {orderUrl} from './prveUrl.js'
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function tbOrderInfoData(data) {
|
||||
return request({
|
||||
url: "/order/admin/order",
|
||||
method: "get",
|
||||
data: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function tbOrderInfoDownload(data) {
|
||||
return request({
|
||||
url: "/api/tbOrderInfo/download",
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...data
|
||||
},
|
||||
responseType: "blob"
|
||||
});
|
||||
}
|
||||
export function createOrder(data, urlType = 'order') {
|
||||
return request({
|
||||
url: `/${urlType}/admin/order/createOrder`,
|
||||
method: "POST",
|
||||
data: {
|
||||
...data
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 通过Id查询订单
|
||||
* @param {*} id
|
||||
* @returns
|
||||
*/
|
||||
export function tbOrderInfoDetail(id) {
|
||||
return request({
|
||||
url: orderUrl+ `/admin/order/historyOrder?orderId=${id}`,
|
||||
method: "get"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过Id查询订单
|
||||
* @param {*} createdAt
|
||||
* @returns
|
||||
*/
|
||||
export function payCount(createdAt) {
|
||||
console.log(createdAt);
|
||||
return request({
|
||||
url: `/api/tbOrderInfo/payCount`,
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
createdAt: createdAt
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单列表
|
||||
* @param {*} createdAt
|
||||
* @returns
|
||||
*/
|
||||
export function tbGroupOrderInfo(params) {
|
||||
return request({
|
||||
url: `/api/tbGroupOrderInfo`,
|
||||
method: "post",
|
||||
data: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...params
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 退单
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
export function returnGpOrder(data) {
|
||||
return request({
|
||||
url: `/api/tbGroupOrderInfo/returnGpOrder`,
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 店铺订单支付获取链接
|
||||
*/
|
||||
export function $getOrderPayUrl(data) {
|
||||
return request({
|
||||
url: `/api/shopPayApi/getOrderPayUrl`,
|
||||
method: "get",
|
||||
data: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...data
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export const marketUrl = '/market'
|
||||
export const accountUrl = '/account'
|
||||
export const orderUrl = '/order'
|
||||
@@ -1,59 +0,0 @@
|
||||
// 用户管理
|
||||
import http from './http.js'
|
||||
import {accountUrl} from './prveUrl.js'
|
||||
|
||||
|
||||
const request=http.request
|
||||
|
||||
// 获取店铺会员二维码
|
||||
export function getwxacode(data) {
|
||||
return request({
|
||||
url: `/shop/storage/getwxacode`,
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 商家用户列表
|
||||
* @returns
|
||||
*/
|
||||
export function queryAllShopUser(params) {
|
||||
return request({
|
||||
url: accountUrl+`/admin/shopUser`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...params
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 查询商家用户概述信息
|
||||
* @returns
|
||||
*/
|
||||
export function queryAllShopInfo(params) {
|
||||
return request({
|
||||
url: `/api/tbShopUser/summary`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
isVip:1,
|
||||
...params
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取店铺用户详情
|
||||
* @returns
|
||||
*/
|
||||
export function shopUserDetail(params) {
|
||||
return request({
|
||||
url: accountUrl+`/admin/shopUser/detail`,
|
||||
method: "get",
|
||||
params: {
|
||||
shopId: uni.getStorageSync('shopId'),
|
||||
...params
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES6",
|
||||
"module": "ESNext",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"] // 适配 uni-app 的 @ 路径别名(关键,避免导入路径报错)
|
||||
},
|
||||
"jsx": "preserve",
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"pages.json",
|
||||
"uni.pages.json" // 包含 uni-app 配置文件,让 Vetur 识别页面结构
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"unpackage" // 排除编译产物和依赖目录
|
||||
]
|
||||
}
|
||||
852
lib/coupon.ts
852
lib/coupon.ts
@@ -1,852 +0,0 @@
|
||||
import { BigNumber } from "bignumber.js";
|
||||
import _ from "lodash";
|
||||
|
||||
import {
|
||||
ShopInfo,
|
||||
couponCalcParams,
|
||||
BaseCartItem,
|
||||
TimeLimitDiscountConfig,
|
||||
CanDikouGoodsArrArgs,
|
||||
Coupon,
|
||||
ShopUserInfo,
|
||||
GoodsType,
|
||||
BackendCoupon,
|
||||
ExchangeCalculationResult,
|
||||
PointDeductionRule,
|
||||
OrderCostSummary,
|
||||
} from "./types";
|
||||
|
||||
import { getCompatibleFieldValue } from "./utils";
|
||||
|
||||
/**
|
||||
* 返回商品单价
|
||||
* @param goods 商品
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo
|
||||
*/
|
||||
export function returnGoodsPrice(
|
||||
goods: BaseCartItem,
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
if (!goods) {
|
||||
return 0;
|
||||
}
|
||||
//是否可以使用会员价
|
||||
const canUseVipPrice =
|
||||
user &&
|
||||
user.isVip &&
|
||||
user.isMemberPrice &&
|
||||
goods.memberPrice * 1 > 0 &&
|
||||
shopInfo &&
|
||||
shopInfo.isMemberPrice;
|
||||
// 商家改价
|
||||
if (goods.discount_sale_amount && goods.discount_sale_amount * 1 > 0) {
|
||||
return goods.salePrice;
|
||||
}
|
||||
// 限时折扣
|
||||
if (limitTimeDiscount && limitTimeDiscount.id) {
|
||||
//优先使用
|
||||
// 兼容 isTimeDiscount/is_time_discount(这里顺便处理该字段的命名兼容)
|
||||
const isTimeDiscount = getCompatibleFieldValue(
|
||||
goods,
|
||||
"isTimeDiscount",
|
||||
"is_time_discount"
|
||||
);
|
||||
if (isTimeDiscount) {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
const canUseFoods = limitTimeDiscount.foods.split(",");
|
||||
const canUseLimit =
|
||||
limitTimeDiscount.foodType == 1 ||
|
||||
canUseFoods.includes(`${goods.productId}`);
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "limit-time") {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
if (canUseLimit && limitTimeDiscount.discountPriority == "vip-price") {
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
} else {
|
||||
return new BigNumber(goods.salePrice)
|
||||
.times(limitTimeDiscount.discountRate / 100)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canUseVipPrice) {
|
||||
return goods.memberPrice;
|
||||
}
|
||||
return goods.salePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品分组
|
||||
* @param arr 商品列表
|
||||
*/
|
||||
export function returnGoodsGroupMap(arr: BaseCartItem[]) {
|
||||
let map: { [key: string]: BaseCartItem[] } = {};
|
||||
arr.forEach((v) => {
|
||||
const key = v.productId + "_" + v.skuId;
|
||||
if (!map[key]) {
|
||||
map[key] = [];
|
||||
}
|
||||
map[key].push(v);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
interface CouponTypes {
|
||||
1: "满减券";
|
||||
2: "商品券";
|
||||
3: "折扣券";
|
||||
4: "第二件半价券";
|
||||
5: "消费送券";
|
||||
6: "买一送一券";
|
||||
7: "固定价格券";
|
||||
8: "免配送费券";
|
||||
}
|
||||
/**
|
||||
* 优惠券类型:1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券,5-消费送券,6-买一送一券,7-固定价格券,8-免配送费券
|
||||
* @param coupon
|
||||
*/
|
||||
export function returnCoupType(coupon: Coupon) {
|
||||
const couponTypes: CouponTypes = {
|
||||
1: "满减券",
|
||||
2: "商品券",
|
||||
3: "折扣券",
|
||||
4: "第二件半价券",
|
||||
5: "消费送券",
|
||||
6: "买一送一券",
|
||||
7: "固定价格券",
|
||||
8: "免配送费券",
|
||||
};
|
||||
return couponTypes[coupon.type as keyof CouponTypes] || "未知类型";
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品券抵扣后的商品列表
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param user 用户信息
|
||||
*/
|
||||
export function returnCanDikouGoodsArr(args: CanDikouGoodsArrArgs) {
|
||||
const { canDikouGoodsArr, selCoupon, user, shopInfo, limitTimeDiscount } =
|
||||
args;
|
||||
const types = [2, 4, 6];
|
||||
// 收集已抵扣商品并关联对应的优惠券类型
|
||||
const goodsCouponGoods = selCoupon
|
||||
.filter((v) => types.includes(v.type))
|
||||
.reduce((prev: BaseCartItem[], cur) => {
|
||||
// 给每个抵扣商品添加所属优惠券类型
|
||||
if (cur && cur.discount) {
|
||||
const goodsWithType = cur.discount.hasDiscountGoodsArr.map((goods) => ({
|
||||
...goods,
|
||||
couponType: cur.type, // 记录该商品是被哪种类型的优惠券抵扣的
|
||||
}));
|
||||
prev.push(...goodsWithType);
|
||||
}
|
||||
return prev;
|
||||
}, []);
|
||||
const arr = _.cloneDeep(canDikouGoodsArr)
|
||||
.map((v) => {
|
||||
const findCart = goodsCouponGoods.find((carts) => carts.id == v.id);
|
||||
if (findCart) {
|
||||
// 根据优惠券类型判断扣减数量
|
||||
if ([4, 6].includes(findCart.couponType ?? 0)) {
|
||||
// 类型4(第二件半价)或6(买一送一),数量减2
|
||||
if (v.num) {
|
||||
v.num -= 2;
|
||||
}
|
||||
} else {
|
||||
// 其他类型(如类型2商品券),按原逻辑扣减对应数量
|
||||
if (v.num) {
|
||||
v.num -= findCart.num ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return v;
|
||||
})
|
||||
.filter((v) => {
|
||||
const canUseNum = (v.num ?? 0) - (v.returnNum || 0);
|
||||
// 兼容 is_temporary/isTemporary 和 is_gift/isGift
|
||||
const isTemporary = getCompatibleFieldValue(
|
||||
v,
|
||||
"isTemporary",
|
||||
"is_temporary"
|
||||
);
|
||||
const isGift = getCompatibleFieldValue(v, "isGift", "is_gift");
|
||||
|
||||
if (canUseNum <= 0 || isTemporary || isGift) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}); // 过滤掉数量<=0的商品,赠菜,临时菜
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品是否享用了会员价/会员折扣
|
||||
* @param {*} goods
|
||||
*/
|
||||
function returnGoodsIsUseVipPrice(
|
||||
shopInfo: ShopInfo,
|
||||
user: ShopUserInfo,
|
||||
goods: BaseCartItem
|
||||
) {
|
||||
// 兼容 isTimeDiscount/is_time_discount
|
||||
const isTimeDiscount = getCompatibleFieldValue(
|
||||
goods,
|
||||
"isTimeDiscount",
|
||||
"is_time_discount"
|
||||
);
|
||||
if (isTimeDiscount) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice != 1 || user.isVip != 1) {
|
||||
return false;
|
||||
}
|
||||
if (shopInfo.isMemberPrice == 1 && user.isVip == 1) {
|
||||
if (goods.memberPrice <= 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回可以计算抵扣金额的商品列表
|
||||
*/
|
||||
function returnCanCalcGoodsList(
|
||||
canCalcGoodsArr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
shopInfo: ShopInfo,
|
||||
user: ShopUserInfo
|
||||
) {
|
||||
return canCalcGoodsArr.filter((goods) => {
|
||||
// 兼容 isTimeDiscount/is_time_discount
|
||||
const isTimeDiscount = getCompatibleFieldValue(
|
||||
goods,
|
||||
"isTimeDiscount",
|
||||
"is_time_discount"
|
||||
);
|
||||
if (!coupon.discountShare && isTimeDiscount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!coupon.vipPriceShare &&
|
||||
returnGoodsIsUseVipPrice(shopInfo, user, goods)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断优惠券是否可使用,并返回不可用原因
|
||||
*
|
||||
* @param {Object} args - 函数参数集合
|
||||
* @param {Array} args.canDikouGoodsArr - 可参与抵扣的商品列表
|
||||
* @param {Object} args.coupon - 优惠券信息对象
|
||||
* @param {boolean} args.coupon.use - 优惠券是否启用
|
||||
* @param {Array} args.coupon.useFoods - 优惠券适用的商品ID列表
|
||||
* @param {number} args.coupon.fullAmount - 优惠券使用门槛金额
|
||||
* @param {number} args.coupon.type - 优惠券类型
|
||||
* @param {number} args.goodsOrderPrice - 订单中所有商品的总金额
|
||||
* @param {Object} args.user - 用户信息对象
|
||||
* @param {Object} args.selCoupon - 已经选择的优惠券信息对象
|
||||
* @param {Object} args.shopInfo
|
||||
* @param {boolean} args.limitTimeDiscount - 限时折扣
|
||||
* @returns {Object} - { canUse: boolean, reason: string } 可用状态及不可用原因
|
||||
*/
|
||||
export function returnCouponCanUse(args: couponCalcParams) {
|
||||
let {
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
goodsOrderPrice,
|
||||
user,
|
||||
selCoupon,
|
||||
shopInfo,
|
||||
isMemberPrice,
|
||||
limitTimeDiscount,
|
||||
} = args;
|
||||
// 优惠券未启用
|
||||
if (!coupon.use) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不在可用时间段内",
|
||||
};
|
||||
}
|
||||
if (
|
||||
limitTimeDiscount &&
|
||||
limitTimeDiscount.id &&
|
||||
limitTimeDiscount.foodType == 1 &&
|
||||
!coupon.discountShare
|
||||
) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: coupon.noUseRestrictions || "不可与限时折扣同享",
|
||||
};
|
||||
}
|
||||
|
||||
// 计算门槛金额
|
||||
let fullAmount = goodsOrderPrice;
|
||||
canDikouGoodsArr = returnCanDikouGoodsArr(args);
|
||||
//优惠券指定门槛商品列表
|
||||
let canCalcGoodsArr = [...canDikouGoodsArr];
|
||||
//部分商品参与门槛计算
|
||||
if (coupon.thresholdFoods.length) {
|
||||
canCalcGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.thresholdFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
}
|
||||
|
||||
canCalcGoodsArr = returnCanCalcGoodsList(
|
||||
canCalcGoodsArr,
|
||||
coupon,
|
||||
shopInfo,
|
||||
user
|
||||
);
|
||||
|
||||
fullAmount = canCalcGoodsArr.reduce((pre, cur) => {
|
||||
return (
|
||||
pre +
|
||||
returnGoodsPrice(cur, user, shopInfo, limitTimeDiscount) * (cur.num || 0)
|
||||
);
|
||||
}, 0);
|
||||
|
||||
// 是否全部商品可用
|
||||
const isDikouAll = coupon.useFoods.length === 0;
|
||||
// 订单可用商品列表
|
||||
let canUseGoodsArr: BaseCartItem[] = [];
|
||||
if (!isDikouAll) {
|
||||
canUseGoodsArr = canDikouGoodsArr.filter((v) => {
|
||||
return coupon.useFoods.find((food) => food.id == v.productId);
|
||||
});
|
||||
}
|
||||
// if (user.isVip && !coupon.vipPriceShare) {
|
||||
// return {
|
||||
// canUse: false,
|
||||
// reason: "非会员可用",
|
||||
// };
|
||||
// }
|
||||
if (selCoupon.length > 0 && !selCoupon[0].otherCouponShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "当前选中的券不可与其他券同享",
|
||||
};
|
||||
}
|
||||
if (selCoupon.length > 0 && !coupon.otherCouponShare) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "当前选中的券不可与其他券同享",
|
||||
};
|
||||
}
|
||||
|
||||
// 满减券和折扣券计算门槛金额是否满足
|
||||
if ([1, 3].includes(coupon.type)) {
|
||||
if (canCalcGoodsArr.length <= 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有可参与计算门槛的商品",
|
||||
};
|
||||
}
|
||||
// 不满足门槛金额
|
||||
if (fullAmount < (coupon.fullAmount || 0)) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
}
|
||||
// 商品兑换券,第二件半价和买一送一判断是否有可用商品
|
||||
if ([2, 4, 5].includes(coupon.type)) {
|
||||
// 没有符合条件的商品
|
||||
if (isDikouAll && canDikouGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (!isDikouAll && canUseGoodsArr.length === 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合条件的商品",
|
||||
};
|
||||
}
|
||||
if (coupon.type == 2) {
|
||||
if (canCalcGoodsArr.length <= 0) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "没有符合计算门槛条件的商品",
|
||||
};
|
||||
}
|
||||
if (fullAmount < (coupon.fullAmount || 0)) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
//商品兑换券是否达到门槛金额
|
||||
if (coupon.type == 2 && goodsOrderPrice < (coupon.fullAmount || 0)) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: `满${coupon.fullAmount}元可用,当前可参与金额${fullAmount}元`,
|
||||
};
|
||||
}
|
||||
|
||||
// 买一送一券特殊验证
|
||||
if (coupon.type === 6) {
|
||||
let canUse = false;
|
||||
if (isDikouAll) {
|
||||
canUse = canDikouGoodsArr.some((v) => (v.num || 0) >= 2);
|
||||
} else if (canUseGoodsArr.length > 0) {
|
||||
canUse = canUseGoodsArr.some((v) => (v.num || 0) >= 2);
|
||||
}
|
||||
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 第二件半价券特殊验证
|
||||
if (coupon.type === 4) {
|
||||
let canUse = false;
|
||||
if (isDikouAll) {
|
||||
canUse = canDikouGoodsArr.some((v) => (v.num || 0) >= 2);
|
||||
} else if (canUseGoodsArr.length > 0) {
|
||||
canUse = canUseGoodsArr.some((v) => (v.num || 0) >= 2);
|
||||
}
|
||||
if (!canUse) {
|
||||
return {
|
||||
canUse: false,
|
||||
reason: "需要购买至少2件相同的商品才能使用",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 所有条件都满足
|
||||
return {
|
||||
canUse: true,
|
||||
reason: "",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算抵扣商品金额
|
||||
* @param discountGoodsArr 可抵扣商品列表
|
||||
* @param discountNum 抵扣数量
|
||||
* @param user 用户信息
|
||||
* @param {Object} shopInfo 店铺信息
|
||||
*/
|
||||
export function calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr: BaseCartItem[],
|
||||
discountNum: number,
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
let hasCountNum = 0;
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr:BaseCartItem[] = [];
|
||||
|
||||
for (let i = 0; i < discountGoodsArr.length; i++) {
|
||||
if (hasCountNum >= discountNum) {
|
||||
break;
|
||||
}
|
||||
const goods = discountGoodsArr[i];
|
||||
const shengyuNum = discountNum - hasCountNum;
|
||||
const num = Math.min(goods.num || 0, shengyuNum);
|
||||
const realPrice = returnGoodsPrice(
|
||||
goods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
|
||||
discountPrice += realPrice * num;
|
||||
|
||||
hasCountNum += num;
|
||||
if(goods){
|
||||
hasDiscountGoodsArr.push({
|
||||
...goods,
|
||||
num,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
discountPrice,
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算优惠券抵扣金额
|
||||
* @param arr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponDiscount(
|
||||
arr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
user: ShopUserInfo,
|
||||
goodsOrderPrice: number,
|
||||
selCoupon: Coupon[],
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
arr = returnCanDikouGoods(arr, user, shopInfo, limitTimeDiscount);
|
||||
const canDikouGoodsArr = returnCanDikouGoodsArr({
|
||||
canDikouGoodsArr: arr,
|
||||
selCoupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount,
|
||||
});
|
||||
if (coupon.type == 2) {
|
||||
return returnCouponProductDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 6) {
|
||||
const result = returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
if (coupon.type == 4) {
|
||||
return returnSecoendDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
if (coupon.type == 3) {
|
||||
return returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr,
|
||||
coupon,
|
||||
user,
|
||||
goodsOrderPrice,
|
||||
selCoupon,
|
||||
limitTimeDiscount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 折扣券抵扣金额
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param goodsOrderPrice 商品订单金额
|
||||
* @param selCoupon 已选择的优惠券列表
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCouponZhekouDiscount(
|
||||
canDikouGoodsArr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
user: ShopUserInfo,
|
||||
goodsOrderPrice: number,
|
||||
selCoupon: Coupon[],
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
let { discountRate, maxDiscountAmount } = coupon;
|
||||
maxDiscountAmount = maxDiscountAmount || 0;
|
||||
// 计算商品优惠券折扣总和,使用BigNumber避免精度问题
|
||||
const goodsCouponDiscount = selCoupon
|
||||
.filter((v) => v.type == 2)
|
||||
.reduce((prve, cur) => {
|
||||
return new BigNumber(prve).plus(
|
||||
new BigNumber(cur?.discount?.discountPrice || 0)
|
||||
);
|
||||
}, new BigNumber(0));
|
||||
|
||||
// 将商品订单价格转换为BigNumber并减去优惠券折扣
|
||||
const adjustedGoodsOrderPrice = new BigNumber(goodsOrderPrice).minus(
|
||||
goodsCouponDiscount
|
||||
);
|
||||
|
||||
// 计算优惠比例:(100 - 折扣率) / 100
|
||||
const discountAmountRatio = new BigNumber(100)
|
||||
.minus(discountRate || 0)
|
||||
.dividedBy(100);
|
||||
|
||||
// 计算折扣金额:调整后的商品订单金额 × 优惠比例
|
||||
let discountPrice = adjustedGoodsOrderPrice
|
||||
.times(discountAmountRatio)
|
||||
.decimalPlaces(2, BigNumber.ROUND_FLOOR)
|
||||
.toNumber();
|
||||
|
||||
// 应用最大折扣金额限制
|
||||
if (maxDiscountAmount !== 0) {
|
||||
discountPrice =
|
||||
discountPrice >= maxDiscountAmount ? maxDiscountAmount : discountPrice;
|
||||
}
|
||||
|
||||
return {
|
||||
discountPrice, // 折扣抵扣金额(即优惠的金额)
|
||||
hasDiscountGoodsArr: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品券抵扣金额
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
*/
|
||||
export function returnCouponProductDiscount(
|
||||
canDikouGoodsArr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
let { useFoods, discountNum, useRule } = coupon;
|
||||
discountNum = discountNum || 0;
|
||||
//抵扣商品数组
|
||||
let discountGoodsArr:BaseCartItem[] = [];
|
||||
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoodsArr = canDikouGoodsArr.slice(discountNum * -1).reverse();
|
||||
} else {
|
||||
discountGoodsArr = canDikouGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
} else {
|
||||
//抵扣选中商品
|
||||
const discountSelGoodsArr = canDikouGoodsArr.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoodsArr = discountSelGoodsArr.slice(discountNum * -1).reverse();
|
||||
} else {
|
||||
discountGoodsArr = discountSelGoodsArr.slice(0, discountNum);
|
||||
}
|
||||
}
|
||||
|
||||
const result = calcDiscountGoodsArrPrice(
|
||||
discountGoodsArr,
|
||||
discountNum,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回买一送一券抵扣详情
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
*/
|
||||
function returnCouponBuyOneGiveOneDiscount(
|
||||
canDikouGoodsArr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods:BaseCartItem | undefined = undefined;
|
||||
//符合买一送一条件的商品(数量>=2 + 非临时/非赠品)
|
||||
const canUseGoods = canDikouGoodsArr.filter((v) => {
|
||||
const isTemporary = getCompatibleFieldValue(
|
||||
v,
|
||||
"isTemporary",
|
||||
"is_temporary"
|
||||
);
|
||||
const isGift = getCompatibleFieldValue(v, "isGift", "is_gift");
|
||||
return (v.num || 0) >= 2 && !isTemporary && !isGift;
|
||||
});
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods[canUseGoods.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods[0];
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods1[0];
|
||||
}
|
||||
}
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr: BaseCartItem[] = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
return {
|
||||
discountPrice: discountPrice <= 0 ? 0 : discountPrice,
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回第二件半价券抵扣详情
|
||||
* @param canDikouGoodsArr 可抵扣商品列表
|
||||
* @param coupon 优惠券
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
*/
|
||||
function returnSecoendDiscount(
|
||||
canDikouGoodsArr: BaseCartItem[],
|
||||
coupon: Coupon,
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
const { useFoods, useRule } = coupon;
|
||||
//抵扣商品
|
||||
let discountGoods:BaseCartItem | undefined = undefined;
|
||||
//符合条件的商品(数量>=2 + 非临时/非赠品)
|
||||
const canUseGoods = canDikouGoodsArr.filter((v) => {
|
||||
const isTemporary = getCompatibleFieldValue(
|
||||
v,
|
||||
"isTemporary",
|
||||
"is_temporary"
|
||||
);
|
||||
const isGift = getCompatibleFieldValue(v, "isGift", "is_gift");
|
||||
return (v.num || 0) >= 2 && !isTemporary && !isGift;
|
||||
});
|
||||
//抵扣全部商品
|
||||
if (useFoods.length === 0) {
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods[canUseGoods.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods[0];
|
||||
}
|
||||
} else {
|
||||
//符合抵扣条件的商品
|
||||
const canUseGoods1 = canUseGoods.filter((v) =>
|
||||
useFoods.find((food) => food.id == v.productId)
|
||||
);
|
||||
if (useRule == "price_asc") {
|
||||
discountGoods = canUseGoods1[canUseGoods1.length - 1];
|
||||
} else {
|
||||
discountGoods = canUseGoods1[0];
|
||||
}
|
||||
}
|
||||
let discountPrice = 0;
|
||||
let hasDiscountGoodsArr: BaseCartItem[] = [];
|
||||
if (discountGoods) {
|
||||
discountPrice = returnGoodsPrice(
|
||||
discountGoods,
|
||||
user,
|
||||
shopInfo,
|
||||
limitTimeDiscount
|
||||
);
|
||||
hasDiscountGoodsArr = [discountGoods];
|
||||
}
|
||||
//返回半价价格
|
||||
return {
|
||||
discountPrice:
|
||||
discountPrice <= 0
|
||||
? 0
|
||||
: new BigNumber(discountPrice).dividedBy(2).toNumber(),
|
||||
hasDiscountGoodsArr,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回可以抵扣优惠券的商品列表,过滤掉赠品、临时商品,价格从高到低排序
|
||||
* @param arr 商品列表
|
||||
* @param user 用户信息
|
||||
* @param shopInfo 店铺信息
|
||||
* @param limitTimeDiscount 限时折扣
|
||||
*/
|
||||
export function returnCanDikouGoods(
|
||||
arr: BaseCartItem[],
|
||||
user: ShopUserInfo,
|
||||
shopInfo: ShopInfo,
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined
|
||||
) {
|
||||
const result = arr
|
||||
.filter((v) => {
|
||||
// 兼容 is_temporary/isTemporary 和 is_gift/isGift
|
||||
const isTemporary = getCompatibleFieldValue(
|
||||
v,
|
||||
"isTemporary",
|
||||
"is_temporary"
|
||||
);
|
||||
const isGift = getCompatibleFieldValue(v, "isGift", "is_gift");
|
||||
return !isTemporary && !isGift;
|
||||
})
|
||||
.filter((v) => {
|
||||
return (v.num || 0) > 0;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return (
|
||||
returnGoodsPrice(b, user, shopInfo, limitTimeDiscount) -
|
||||
returnGoodsPrice(a, user, shopInfo, limitTimeDiscount)
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export const utils = {
|
||||
returnGoodsPrice,
|
||||
returnGoodsGroupMap,
|
||||
returnCoupType,
|
||||
returnCanDikouGoods,
|
||||
returnCanDikouGoodsArr,
|
||||
returnCouponCanUse,
|
||||
calcDiscountGoodsArrPrice,
|
||||
returnCouponDiscount,
|
||||
returnCouponProductDiscount,
|
||||
returnCouponZhekouDiscount,
|
||||
};
|
||||
|
||||
export default utils;
|
||||
File diff suppressed because it is too large
Load Diff
1382
lib/goods.ts
1382
lib/goods.ts
File diff suppressed because it is too large
Load Diff
11
lib/index.ts
11
lib/index.ts
@@ -1,11 +0,0 @@
|
||||
export * from "./types";
|
||||
import OrderPriceCalculator from "./goods";
|
||||
import couponUtils from "./coupon";
|
||||
import limitUtils from "./limit";
|
||||
|
||||
export { OrderPriceCalculator, couponUtils, limitUtils };
|
||||
export default {
|
||||
OrderPriceCalculator,
|
||||
couponUtils,
|
||||
limitUtils,
|
||||
};
|
||||
216
lib/limit.ts
216
lib/limit.ts
@@ -1,216 +0,0 @@
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
import _ from "lodash";
|
||||
|
||||
import {
|
||||
BaseCartItem,
|
||||
ShopUserInfo,
|
||||
ShopInfo,
|
||||
TimeLimitDiscountConfig,
|
||||
CanReturnMemberPriceArgs,
|
||||
returnPriceArgs,
|
||||
} from "./types";
|
||||
|
||||
/**
|
||||
* 判断商品是否可以使用限时折扣
|
||||
* @param goods 商品对象
|
||||
* @param limitTimeDiscountRes 限时折扣配置
|
||||
* @param shopInfo 店铺信息
|
||||
* @param shopUserInfo 店铺用户信息
|
||||
* @param idKey 商品ID键名,默认"id"
|
||||
* @returns
|
||||
*/
|
||||
export function canUseLimitTimeDiscount(
|
||||
goods: BaseCartItem,
|
||||
limitTimeDiscountRes: TimeLimitDiscountConfig | null | undefined,
|
||||
shopInfo: ShopInfo,
|
||||
shopUserInfo: ShopUserInfo,
|
||||
idKey = "id" as keyof BaseCartItem
|
||||
) {
|
||||
shopInfo = shopInfo || {};
|
||||
shopUserInfo = shopUserInfo || {};
|
||||
if(shopInfo.isMemberPrice){
|
||||
shopUserInfo.isMemberPrice=1
|
||||
}
|
||||
if (!limitTimeDiscountRes || !limitTimeDiscountRes.id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
|
||||
|
||||
const goodsCanUse =
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes(`${goods[idKey]}`);
|
||||
if (!goodsCanUse) {
|
||||
return false;
|
||||
}
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
return true;
|
||||
}
|
||||
if (limitTimeDiscountRes.discountPriority == "vip-price") {
|
||||
if (
|
||||
shopUserInfo.isVip == 1 &&
|
||||
shopUserInfo.isMemberPrice == 1 &&
|
||||
goods.memberPrice * 1 > 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回商品显示价格
|
||||
* @params {*} args 参数对象
|
||||
* @params {*} args.goods 商品对象
|
||||
* @params {*} args.shopInfo 店铺信息
|
||||
* @params {*} args.limitTimeDiscountRes 限时折扣信息
|
||||
* @params {*} args.shopUserInfo 店铺用户信息
|
||||
* @returns
|
||||
*/
|
||||
export function returnPrice(args: returnPriceArgs) {
|
||||
let {
|
||||
goods,
|
||||
shopInfo,
|
||||
limitTimeDiscountRes,
|
||||
shopUserInfo,
|
||||
idKey = "product_id",
|
||||
} = args;
|
||||
limitTimeDiscountRes = limitTimeDiscountRes || {
|
||||
foods: "",
|
||||
foodType: 2,
|
||||
discountPriority: "",
|
||||
discountRate: 0,
|
||||
id: 0,
|
||||
shopId: 0,
|
||||
useType: "",
|
||||
};
|
||||
const canUseFoods = (limitTimeDiscountRes.foods || "").split(",");
|
||||
const includesGoods =
|
||||
limitTimeDiscountRes.foodType == 1 ||
|
||||
canUseFoods.includes("" + goods[idKey]);
|
||||
shopInfo = shopInfo || {};
|
||||
shopUserInfo = shopUserInfo || {};
|
||||
if (
|
||||
shopUserInfo.isMemberPrice == 1 &&
|
||||
shopUserInfo.isVip == 1 &&
|
||||
shopInfo.isMemberPrice == 1
|
||||
) {
|
||||
const memberPrice = goods.memberPrice || goods.salePrice;
|
||||
|
||||
//是会员而且启用会员价
|
||||
if (limitTimeDiscountRes) {
|
||||
//使用限时折扣
|
||||
//限时折扣优先
|
||||
if (limitTimeDiscountRes.discountPriority == "limit-time") {
|
||||
if (includesGoods) {
|
||||
return returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
});
|
||||
} else {
|
||||
return memberPrice;
|
||||
}
|
||||
}
|
||||
if (
|
||||
limitTimeDiscountRes.discountPriority == "vip-price" &&
|
||||
includesGoods
|
||||
) {
|
||||
if (goods.memberPrice * 1 > 0) {
|
||||
//会员优先
|
||||
return memberPrice;
|
||||
} else {
|
||||
const price = returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
goods: goods,
|
||||
});
|
||||
|
||||
return price;
|
||||
}
|
||||
} else {
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
//是会员没有限时折扣
|
||||
return memberPrice;
|
||||
}
|
||||
} else {
|
||||
//不是会员或者没有启用会员价
|
||||
if (limitTimeDiscountRes && limitTimeDiscountRes.id && includesGoods) {
|
||||
const price = returnLimitPrice({
|
||||
price: goods.salePrice,
|
||||
limitTimeDiscountRes,
|
||||
goods: goods,
|
||||
});
|
||||
|
||||
return price;
|
||||
} else {
|
||||
return goods.salePrice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface returnLimitPriceArgs {
|
||||
limitTimeDiscountRes: TimeLimitDiscountConfig | null | undefined;
|
||||
price: number;
|
||||
goods?: BaseCartItem;
|
||||
}
|
||||
/**
|
||||
* 返回限时折扣价格
|
||||
* @params {*} args 参数对象
|
||||
* @params {*} args.limitTimeDiscountRes 限时折扣信息
|
||||
* @params {*} args.price 商品价格
|
||||
* @param {*} args.goods 商品对象
|
||||
* @returns
|
||||
*/
|
||||
export function returnLimitPrice(args: returnLimitPriceArgs) {
|
||||
const { limitTimeDiscountRes, price, goods } = args;
|
||||
const discountRate = new BigNumber(
|
||||
limitTimeDiscountRes ? limitTimeDiscountRes.discountRate : 100
|
||||
).dividedBy(100);
|
||||
|
||||
const result = BigNumber(price)
|
||||
.times(discountRate)
|
||||
.decimalPlaces(2, BigNumber.ROUND_UP)
|
||||
.toNumber();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否返回会员价
|
||||
* @param {*} args 参数对象
|
||||
* @param {*} args.shopInfo 店铺信息
|
||||
* @param {*} args.shopUserInfo 店铺用户信息
|
||||
* @returns
|
||||
*/
|
||||
export function canReturnMemberPrice(args: CanReturnMemberPriceArgs) {
|
||||
const { shopInfo, shopUserInfo } = args;
|
||||
if (shopUserInfo.isMemberPrice == 1 && shopUserInfo.isVip == 1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回会员价格
|
||||
* @param {*} goods
|
||||
* @returns
|
||||
*/
|
||||
export function returnMemberPrice(goods: BaseCartItem) {
|
||||
return goods.memberPrice || goods.salePrice;
|
||||
}
|
||||
|
||||
export const utils = {
|
||||
returnPrice,
|
||||
canUseLimitTimeDiscount,
|
||||
returnLimitPrice,
|
||||
canReturnMemberPrice,
|
||||
returnMemberPrice,
|
||||
};
|
||||
|
||||
export default utils;
|
||||
430
lib/types.ts
430
lib/types.ts
@@ -1,430 +0,0 @@
|
||||
/** 商品类型枚举 */
|
||||
export enum GoodsType {
|
||||
NORMAL = "normal", // 普通商品
|
||||
WEIGHT = "weight", // 称重商品
|
||||
GIFT = "gift", // 赠菜(继承普通商品逻辑,标记用)
|
||||
EMPTY = "", // 空字符串类型(后端未返回时默认归类为普通商品)
|
||||
PACKAGE = "package", // 打包商品(如套餐/预打包商品,按普通商品逻辑处理,可扩展特殊规则)
|
||||
}
|
||||
|
||||
/** 优惠券计算结果类型(新增细分字段) */
|
||||
export interface CouponResult {
|
||||
deductionAmount: number; // 抵扣金额
|
||||
excludedProductIds: string[]; // 不适用商品ID列表(注意:是商品ID,非购物车ID)
|
||||
usedCoupon: Coupon | undefined; // 实际使用的优惠券
|
||||
productCouponDeduction: number; // 新增:商品优惠券抵扣(兑换券等)
|
||||
fullCouponDeduction: number; // 新增:满减优惠券抵扣
|
||||
}
|
||||
|
||||
/** 兑换券计算结果类型(新增细分字段) */
|
||||
export interface ExchangeCalculationResult {
|
||||
deductionAmount: number;
|
||||
excludedProductIds: string[]; // 不适用商品ID列表(商品ID)
|
||||
productCouponDeduction: number; // 新增:兑换券属于商品券,同步记录
|
||||
}
|
||||
|
||||
export interface CouponTypes {
|
||||
1: "满减券";
|
||||
2: "商品券";
|
||||
3: "折扣券";
|
||||
4: "第二件半价券";
|
||||
5: "消费送券";
|
||||
6: "买一送一券";
|
||||
7: "固定价格券";
|
||||
8: "免配送费券";
|
||||
}
|
||||
|
||||
/** 优惠券类型枚举 */
|
||||
export enum CouponType {
|
||||
FULL_REDUCTION = "full_reduction", // 满减券
|
||||
DISCOUNT = "discount", // 折扣券
|
||||
SECOND_HALF = "second_half", // 第二件半价券
|
||||
BUY_ONE_GET_ONE = "buy_one_get_one", // 买一送一券
|
||||
EXCHANGE = "exchange", // 商品兑换券
|
||||
}
|
||||
|
||||
/** 后端返回的优惠券原始字段类型 */
|
||||
export interface BackendCoupon {
|
||||
id?: number; // 自增主键(int64)
|
||||
shopId?: number; // 店铺ID(int64)
|
||||
syncId?: number; // 同步Id(int64)
|
||||
type?: number; // 优惠券类型:1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券,5-消费送券,6-买一送一券,7-固定价格券,8-免配送费券
|
||||
name?: string; // 券名称
|
||||
useShopType?: string; // 可用门店类型:only-仅本店;all-所有门店,custom-指定门店
|
||||
useShops?: string; // 可用门店(逗号分隔字符串,如"1,2,3")
|
||||
useType?: string; // 可使用类型:dine堂食/pickup自取/deliv配送/express快递
|
||||
validType?: string; // 有效期类型:fixed(固定时间),custom(自定义时间)
|
||||
validDays?: number; // 有效期(天)
|
||||
validStartTime?: string; // 有效期开始时间(如"2024-01-01 00:00:00")
|
||||
validEndTime?: string; // 有效期结束时间
|
||||
daysToTakeEffect?: number; // 隔天生效
|
||||
useDays?: string; // 可用周期(如"周一,周二")
|
||||
useTimeType?: string; // 可用时间段类型:all-全时段,custom-指定时段
|
||||
useStartTime?: string; // 可用开始时间(每日)
|
||||
useEndTime?: string; // 可用结束时间(每日)
|
||||
getType?: string; // 发放设置:不可自行领取/no,可领取/yes
|
||||
getMode?: string; // 用户领取方式
|
||||
giveNum?: number; // 总发放数量,-10086为不限量
|
||||
getUserType?: string; // 可领取用户:全部/all,新用户一次/new,仅会员/vip
|
||||
getLimit?: number; // 每人领取限量,-10086为不限量
|
||||
useLimit?: number; // 每人每日使用限量,-10086为不限量
|
||||
discountShare?: number; // 与限时折扣同享:0-否,1-是
|
||||
vipPriceShare?: number; // 与会员价同享:0-否,1-是
|
||||
ruleDetails?: string; // 附加规则说明
|
||||
status?: number; // 状态:0-禁用,1-启用
|
||||
useNum?: number; // 已使用数量
|
||||
leftNum?: number; // 剩余数量
|
||||
foods?: string; // 指定门槛商品(逗号分隔字符串,如"101,102",此处为商品ID)
|
||||
fullAmount?: number; // 使用门槛:满多少金额(元)
|
||||
discountAmount?: number; // 使用门槛:减多少金额(元)
|
||||
discountRate?: number; // 折扣%(如90=9折)
|
||||
maxDiscountAmount?: number; // 可抵扣最大金额(元)
|
||||
useRule?: string; // 使用规则:price_asc-价格低到高,price_desc-高到低
|
||||
discountNum?: number; // 抵扣数量
|
||||
otherCouponShare?: number; // 与其它优惠共享:0-否,1-是
|
||||
createTime?: string; // 创建时间
|
||||
updateTime?: string; // 更新时间
|
||||
}
|
||||
|
||||
/** 营销活动类型枚举 */
|
||||
export enum ActivityType {
|
||||
TIME_LIMIT_DISCOUNT = "time_limit_discount", // 限时折扣
|
||||
}
|
||||
|
||||
/** 基础购物车商品项(核心修正:新增product_id,明确各ID含义) */
|
||||
export interface BaseCartItem {
|
||||
id: string | number; // 购物车ID(唯一标识购物车中的条目,如购物车项主键)
|
||||
product_id: string | number; // 商品ID(唯一标识商品,用于优惠券/活动匹配,必选)
|
||||
productId?: string | number; // 商品ID
|
||||
salePrice: number; // 商品原价(元)
|
||||
number: number; // 商品数量
|
||||
num?: number; // 商品数量
|
||||
isTimeDiscount?: boolean; // 是否限时折扣商品(默认false)
|
||||
is_time_discount?: boolean; // 是否限时折扣商品(默认false)
|
||||
product_type: GoodsType; // 商品类型
|
||||
is_temporary?: boolean; // 是否临时菜(默认false)
|
||||
isTemporary?: boolean; // 是否临时菜(默认false)
|
||||
is_gift?: boolean; // 是否赠菜(默认false)
|
||||
isGift?: boolean; // 是否赠菜(默认false)
|
||||
returnNum?: number; // 退货数量(历史订单用,默认0)
|
||||
memberPrice: number; // 商品会员价(元,优先级:商品会员价 > 会员折扣)
|
||||
discountSaleAmount?: number; // 商家改价后单价(元,优先级最高)
|
||||
discount_sale_amount?: number; // 商家改价后单价(元,优先级最高)
|
||||
packFee?: number; // 单份打包费(元,默认0)
|
||||
packNumber?: number; // 堂食打包数量(默认0)
|
||||
activityInfo?: {
|
||||
// 商品参与的营销活动(如限时折扣)
|
||||
type: ActivityType;
|
||||
discountRate: number; // 折扣率(如0.8=8折)
|
||||
vipPriceShare: boolean; // 是否与会员优惠同享(默认false)
|
||||
};
|
||||
skuData?: {
|
||||
// SKU扩展数据(可选)
|
||||
id: string | number; // SKU ID(唯一标识商品规格,如颜色/尺寸)
|
||||
memberPrice: number; // SKU会员价
|
||||
salePrice?: number; // SKU原价
|
||||
};
|
||||
skuId?: string | number; // SKU ID(唯一标识商品规格,如颜色/尺寸)
|
||||
couponType?: number; // 优惠券类型:1-满减券,2-商品兑换券,3-折扣券,4-第二件半价券,5-消费送券,6-买一送一券,7-固定价格券,8-免配送费券
|
||||
}
|
||||
|
||||
export interface CouponFoods {
|
||||
id: string;
|
||||
name: string;
|
||||
images: string;
|
||||
}
|
||||
|
||||
/** 基础优惠券接口(所有券类型继承,包含统一门槛商品字段) */
|
||||
export interface BaseCoupon {
|
||||
otherCouponShare?: number; // 与其它优惠共享:0-否,1-是
|
||||
id: string | number; // 优惠券ID
|
||||
type: number; // 工具库字符串枚举(由后端couponType转换)
|
||||
name: string; // 对应后端title
|
||||
available: boolean; // 基于BackendCoupon字段计算的可用性
|
||||
useShopType?: string; // only-仅本店;all-所有门店,custom-指定门店
|
||||
useShops: string[]; // 可用门店ID列表
|
||||
discountShare: boolean; // 与限时折扣同享:0-否,1-是(后端字段转换为布尔值)
|
||||
vipPriceShare: boolean; // 与会员价同享:0-否,1-是(后端字段转换为布尔值)
|
||||
useType?: string[]; // 可使用类型:dine堂食/pickup自取/deliv配送/express快递
|
||||
isValid: boolean; // 是否在有效期内
|
||||
discountAmount?: number; // 减免金额 (满减券有)
|
||||
fullAmount?: number; // 使用门槛:满多少金额
|
||||
maxDiscountAmount?: number; // 可抵扣最大金额 元
|
||||
use: boolean;
|
||||
discountNum?: number; // 抵扣数量
|
||||
useRule?: string; // 使用规则:price_asc-价格低到高,price_desc-高到低
|
||||
discountRate?: number; // 折扣%(如90=9折)
|
||||
noUseRestrictions?: boolean; // 是不可用原因
|
||||
thresholdFoods: CouponFoods[]; // 门槛商品ID列表(空数组=全部商品,非空=指定商品ID)
|
||||
useFoods: CouponFoods[]; // 可用商品ID列表(空数组=全部商品,非空=指定商品ID)
|
||||
}
|
||||
export interface couponDiscount {
|
||||
discountPrice: number;
|
||||
hasDiscountGoodsArr: BaseCartItem[];
|
||||
}
|
||||
/** 满减券(适配后端字段) */
|
||||
export interface FullReductionCoupon extends BaseCoupon {
|
||||
fullAmount: number; // 对应后端fullAmount(满减门槛)
|
||||
discountAmount: number; // 对应后端discountAmount(减免金额)
|
||||
maxDiscountAmount?: number; // 对应后端maxDiscountAmount(最大减免)
|
||||
discount?: couponDiscount;
|
||||
}
|
||||
|
||||
/** 折扣券(适配后端字段) */
|
||||
export interface DiscountCoupon extends BaseCoupon {
|
||||
discountRate: number; // 后端discountRate(%)转小数(如90→0.9)
|
||||
maxDiscountAmount: number; // 对应后端maxDiscountAmount(最大减免)
|
||||
discount?: couponDiscount;
|
||||
}
|
||||
|
||||
/** 第二件半价券(适配后端字段) */
|
||||
export interface SecondHalfPriceCoupon extends BaseCoupon {
|
||||
maxUseCountPerOrder?: number; // 对应后端useLimit(-10086=不限)
|
||||
discount?: couponDiscount;
|
||||
}
|
||||
|
||||
/** 买一送一券(适配后端字段) */
|
||||
export interface BuyOneGetOneCoupon extends BaseCoupon {
|
||||
maxUseCountPerOrder?: number; // 对应后端useLimit(-10086=不限)
|
||||
discount?: couponDiscount;
|
||||
}
|
||||
|
||||
/** 商品兑换券(适配后端字段) */
|
||||
export interface ExchangeCoupon extends BaseCoupon {
|
||||
deductCount: number; // 对应后端discountNum(抵扣数量)
|
||||
sortRule: "low_price_first" | "high_price_first"; // 后端useRule转换
|
||||
discount?: couponDiscount;
|
||||
}
|
||||
|
||||
/** 所有优惠券类型联合 */
|
||||
export type Coupon =
|
||||
| FullReductionCoupon
|
||||
| DiscountCoupon
|
||||
| SecondHalfPriceCoupon
|
||||
| BuyOneGetOneCoupon
|
||||
| ExchangeCoupon;
|
||||
|
||||
/** 营销活动配置(如限时折扣,applicableProductIds为商品ID列表) */
|
||||
export interface ActivityConfig {
|
||||
type: ActivityType;
|
||||
applicableProductIds?: string[]; // 适用商品ID列表(与BaseCartItem.product_id匹配)
|
||||
discountRate: number; // 折扣率(如0.8=8折)
|
||||
vipPriceShare: boolean; // 是否与会员优惠同享
|
||||
}
|
||||
|
||||
/** 积分抵扣规则 */
|
||||
export interface PointDeductionRule {
|
||||
pointsPerYuan: number; // X积分=1元(如100=100积分抵1元)
|
||||
maxDeductionAmount?: number; // 最大抵扣金额(元,默认不限)
|
||||
}
|
||||
|
||||
/** 餐位费配置 */
|
||||
export interface SeatFeeConfig {
|
||||
pricePerPerson: number; // 每人餐位费(元)
|
||||
personCount: number; // 用餐人数(默认1)
|
||||
isEnabled: boolean; // 是否启用餐位费(默认false)
|
||||
}
|
||||
/** 商家减免类型枚举 */
|
||||
export enum MerchantReductionType {
|
||||
FIXED_AMOUNT = "fixed_amount", // 固定金额减免(如直接减 10 元)
|
||||
DISCOUNT_RATE = "discount_rate", // 比例折扣减免(如打 9 折,即减免 10%)
|
||||
}
|
||||
|
||||
/** 商家减免配置(新增,替代原单一金额字段) */
|
||||
export interface MerchantReductionConfig {
|
||||
type: MerchantReductionType; // 减免类型(二选一)
|
||||
fixedAmount?: number; // 固定减免金额(元,仅 FIXED_AMOUNT 生效,≥0)
|
||||
discountRate?: number; // 折扣率(%,仅 DISCOUNT_RATE 生效,0-100,如 90 代表 9 折)
|
||||
}
|
||||
/**商家霸王餐配置 */
|
||||
export interface FreeDineConfig {
|
||||
enable: boolean; //是否开启
|
||||
rechargeThreshold: number; //订单满多少元可以使用
|
||||
rechargeTimes: number; //充值多少倍免单
|
||||
withCoupon: boolean; //与优惠券同享
|
||||
withPoints: boolean; //与积分同享
|
||||
useType?: string[]; //使用类型 dine-in店内 takeout 自取 post快递,takeaway外卖
|
||||
useShopType?: string; //all 全部 part部分
|
||||
shopIdList?: number[]; //可用门店id
|
||||
}
|
||||
|
||||
//限时折扣配置
|
||||
export interface TimeLimitDiscountConfig {
|
||||
/**
|
||||
* 折扣优先级 limit-time/vip-price
|
||||
*/
|
||||
discountPriority: string;
|
||||
/**
|
||||
* 折扣% 范围1-99
|
||||
*/
|
||||
discountRate: number;
|
||||
/**
|
||||
* 参与商品
|
||||
*/
|
||||
foods: string;
|
||||
/**
|
||||
* 参与商品 1全部 2部分
|
||||
*/
|
||||
foodType: number;
|
||||
/**
|
||||
* 自增主键
|
||||
*/
|
||||
id: number;
|
||||
/**
|
||||
* 店铺ID
|
||||
*/
|
||||
shopId: number;
|
||||
/**
|
||||
* 可使用类型:堂食 dine-in 外带 take-out 外卖 take-away 配送 post
|
||||
*/
|
||||
useType: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
//用户信息
|
||||
export interface ShopUserInfo {
|
||||
isVip: number | null; //是否会员
|
||||
discount: number | null; //用户折扣
|
||||
isMemberPrice: number | null; //会员折扣与会员价是否同时使用
|
||||
id?: number; //用户ID
|
||||
}
|
||||
/** 订单额外费用配置 */
|
||||
export interface OrderExtraConfig {
|
||||
// merchantReduction: number; // 商家减免金额(元,默认0)
|
||||
// 替换原单一金额字段,支持两种减免形式
|
||||
merchantReduction: MerchantReductionConfig;
|
||||
additionalFee: number; // 附加费(元,如余额充值、券包,默认0)
|
||||
pointDeductionRule: PointDeductionRule; // 积分抵扣规则
|
||||
seatFeeConfig: SeatFeeConfig; // 餐位费配置
|
||||
currentStoreId: string; // 当前门店ID(用于验证优惠券适用门店)
|
||||
userPoints: number; // 用户当前积分(用于积分抵扣)
|
||||
isMember: boolean; // 用户是否会员(用于会员优惠)
|
||||
memberDiscountRate?: number; // 会员折扣率(如0.95=95折,无会员价时用)
|
||||
newUserDiscount?: number; // 新用户减免金额(元,默认0)
|
||||
fullReductionActivities: FullReductionActivity[]; // 当前店铺的满减活动列表(后端返回结构)
|
||||
currentDinnerType: "dine-in" | "take-out" | "take-away" | "post"; // 当前就餐类型(匹配useType)
|
||||
isFreeDine?: boolean; //是否霸王餐
|
||||
freeDineConfig?: FreeDineConfig;
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig; //限时折扣
|
||||
shopUserInfo: ShopUserInfo; // 用户信息
|
||||
}
|
||||
|
||||
/** 订单费用汇总(修改:补充商家减免类型和明细) */
|
||||
export interface OrderCostSummary {
|
||||
goodsList: BaseCartItem[];
|
||||
// 商品总件数
|
||||
goodsTotal: number;
|
||||
totalDiscountAmount: number;
|
||||
goodsRealAmount: number; // 商品真实原价总和
|
||||
goodsOriginalAmount: number; // 商品原价总和
|
||||
goodsDiscountAmount: number; // 商品折扣金额
|
||||
couponDeductionAmount: number; // 优惠券总抵扣
|
||||
productCouponDeduction: number; // 商品优惠券抵扣
|
||||
fullCouponDeduction: number; // 满减优惠券抵扣
|
||||
pointDeductionAmount: number; // 积分抵扣金额
|
||||
seatFee: number; // 餐位费
|
||||
packFee: number; // 打包费
|
||||
scoreMaxMoney: number; // 积分最大可抵扣金额
|
||||
// 新增:商家减免明细
|
||||
merchantReduction: {
|
||||
type: MerchantReductionType; // 实际使用的减免类型
|
||||
originalConfig: MerchantReductionConfig; // 原始配置(便于前端展示)
|
||||
actualAmount: number; // 实际减免金额(计算后的值,≥0)
|
||||
};
|
||||
additionalFee: number; // 附加费
|
||||
finalPayAmount: number; // 最终实付金额
|
||||
couponUsed?: Coupon; // 实际使用的优惠券
|
||||
pointUsed: number; // 实际使用的积分
|
||||
newUserDiscount: number; // 新用户减免金额(元,默认0)
|
||||
dinnerType?: "dine-in" | "take-out"; // 就餐类型(堂食/自取/配送/快递)
|
||||
config: OrderExtraConfig; // 订单额外费用配置
|
||||
//满减活动
|
||||
fullReduction: {
|
||||
usedFullReductionActivityFullAmount: number; // 计算出的满减活动的门槛金额
|
||||
usedActivity?: FullReductionActivity; // 实际使用的满减活动
|
||||
usedThreshold?: FullReductionThreshold; // 实际使用的满减阈值(多门槛中选最优)
|
||||
actualAmount: number; // 满减实际减免金额(元)
|
||||
};
|
||||
vipDiscountAmount: number; //会员折扣减免金额
|
||||
// 订单原支付金额
|
||||
orderOriginFinalPayAmount: number; //订单原金额(包含打包费+餐位费)
|
||||
}
|
||||
|
||||
/** 满减活动阈值(单条满减规则:满X减Y)- 对应 MkDiscountThresholdInsertGroupDefaultGroup */
|
||||
export interface FullReductionThreshold {
|
||||
activityId?: number; // 关联满减活动ID
|
||||
fullAmount?: number; // 满多少金额(元,必填)
|
||||
discountAmount?: number; // 减多少金额(元,必填)
|
||||
}
|
||||
|
||||
/** 满减活动主表 - 对应 Request 接口(后端真实字段) */
|
||||
export interface FullReductionActivity {
|
||||
id?: number; // 自增主键(后端字段:id)
|
||||
shopId?: number; // 店铺ID(后端字段:shopId)
|
||||
status?: number; // 活动状态:1=未开始,2=进行中,3=已结束(后端字段:status)
|
||||
sort?: number; // 排序值(越大优先级越高,后端字段:sort)
|
||||
createTime?: string; // 创建时间(后端字段:createTime,格式如"2025-10-14 13:56:07")
|
||||
updateTime?: string; // 最新修改时间(后端字段:updateTime,用于优先级排序)
|
||||
validStartTime?: string; // 有效期开始时间(后端字段:validStartTime,格式如"2025-10-14")
|
||||
validEndTime?: string; // 有效期结束时间(后端字段:validEndTime,格式如"2025-12-14")
|
||||
useType?: string; // 可使用类型(后端字段:useType,如"dine,pickup,deliv,express")
|
||||
useDays?: string; // 可用周期(后端字段:useDays,如"周一,周二,周三,周四,周五,周六,周日")
|
||||
useTimeType?: string; // 可用时间段类型(后端字段:useTimeType,all=全时段,custom=指定时段)
|
||||
useStartTime?: string; // 每日可用开始时间(后端字段:useStartTime,如"09:00:00",仅custom时有效)
|
||||
useEndTime?: string; // 每日可用结束时间(后端字段:useEndTime,如"22:00:00",仅custom时有效)
|
||||
couponShare?: number; // 与优惠券同享:0=否,1=是(后端字段:couponShare)
|
||||
discountShare?: number; // 与限时折扣同享:0=否,1=是(后端字段:discountShare)
|
||||
vipPriceShare?: number; // 与会员价同享:0=否,1=是(后端字段:vipPriceShare)
|
||||
pointsShare?: number; // 与积分抵扣同享:0=否,1=是(后端字段:pointsShare)
|
||||
thresholds?: FullReductionThreshold[]; // 满减阈值列表(多门槛,后端字段:thresholds)
|
||||
isDel?: boolean; // 是否删除:0=否,1=是(后端字段:isDel,默认false)
|
||||
}
|
||||
|
||||
// 辅助枚举:星期映射(用于useDays校验)
|
||||
export const WEEKDAY_MAP = {
|
||||
周一: 1,
|
||||
周二: 2,
|
||||
周三: 3,
|
||||
周四: 4,
|
||||
周五: 5,
|
||||
周六: 6,
|
||||
周日: 0, // JS中getDay()返回0=周日
|
||||
};
|
||||
|
||||
export interface ShopInfo {
|
||||
isMemberPrice: number; // 是否开启会员价 1是开启
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface couponCalcParams {
|
||||
canDikouGoodsArr: BaseCartItem[];
|
||||
coupon: Coupon;
|
||||
user: ShopUserInfo;
|
||||
shopInfo: ShopInfo;
|
||||
selCoupon: Coupon[];
|
||||
goodsOrderPrice: number; //商品订单总价
|
||||
isMemberPrice: number; // 是否开启会员价 1是开启
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
|
||||
}
|
||||
export interface CanDikouGoodsArrArgs {
|
||||
canDikouGoodsArr: BaseCartItem[];
|
||||
selCoupon: Coupon[];
|
||||
user: ShopUserInfo;
|
||||
shopInfo: ShopInfo;
|
||||
limitTimeDiscount?: TimeLimitDiscountConfig | null | undefined;
|
||||
}
|
||||
export interface returnPriceArgs {
|
||||
goods: BaseCartItem;
|
||||
selCoupon: Coupon[];
|
||||
user: ShopUserInfo;
|
||||
shopInfo: ShopInfo;
|
||||
shopUserInfo: ShopUserInfo;
|
||||
limitTimeDiscountRes?: TimeLimitDiscountConfig | null | undefined;
|
||||
idKey?: keyof BaseCartItem;
|
||||
}
|
||||
|
||||
|
||||
export interface CanReturnMemberPriceArgs {
|
||||
shopInfo?: ShopInfo;
|
||||
shopUserInfo: ShopUserInfo;
|
||||
}
|
||||
33
lib/utils.ts
33
lib/utils.ts
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* 通用字段兼容工具函数:处理驼峰/下划线命名的字段取值
|
||||
* @param obj 目标对象(如商品信息 BaseCartItem)
|
||||
* @param camelCaseKey 驼峰命名字段(如 'isTemporary')
|
||||
* @param snakeCaseKey 下划线命名字段(如 'is_temporary')
|
||||
* @param defaultValue 默认值(默认 false,适配布尔类型字段)
|
||||
* @returns 字段值(优先取存在的字段,无则返回默认值)
|
||||
*/
|
||||
export function getCompatibleFieldValue(
|
||||
obj: Record<string, any>,
|
||||
camelCaseKey: string,
|
||||
snakeCaseKey: string,
|
||||
defaultValue: boolean = false
|
||||
): boolean {
|
||||
// 优先判断驼峰字段(如果存在且不是 undefined/null)
|
||||
if (
|
||||
obj.hasOwnProperty(camelCaseKey) &&
|
||||
obj[camelCaseKey] !== undefined &&
|
||||
obj[camelCaseKey] !== null
|
||||
) {
|
||||
return Boolean(obj[camelCaseKey]);
|
||||
}
|
||||
// 再判断下划线字段
|
||||
if (
|
||||
obj.hasOwnProperty(snakeCaseKey) &&
|
||||
obj[snakeCaseKey] !== undefined &&
|
||||
obj[snakeCaseKey] !== null
|
||||
) {
|
||||
return Boolean(obj[snakeCaseKey]);
|
||||
}
|
||||
// 都不存在时返回默认值(布尔类型字段默认 false)
|
||||
return defaultValue;
|
||||
}
|
||||
16
main.js
16
main.js
@@ -6,12 +6,6 @@ import storageManage from '@/commons/utils/storageManage.js'
|
||||
import dict from '@/commons/utils/dict.js'
|
||||
import {utils} from '@/commons/utils/index.js'
|
||||
import uviewPlus from 'uview-plus'
|
||||
import * as Pinia from 'pinia';
|
||||
import {
|
||||
createUnistorage
|
||||
} from "pinia-plugin-unistorage";
|
||||
|
||||
uni.$utils=utils
|
||||
|
||||
// 设置node环境
|
||||
envConfig.changeEnv(storageManage.env())
|
||||
@@ -30,11 +24,6 @@ const app = new Vue({
|
||||
})
|
||||
|
||||
app.$mount()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
@@ -45,9 +34,6 @@ export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
|
||||
app.use(uviewPlus)
|
||||
const store = Pinia.createPinia();
|
||||
store.use(createUnistorage());
|
||||
app.use(store)
|
||||
app.config.globalProperties.$appName = appConfig.appName
|
||||
uni.$appName = appConfig.appName
|
||||
app.config.globalProperties.$utils = utils
|
||||
@@ -56,7 +42,7 @@ export function createApp() {
|
||||
uni.$dict = dict
|
||||
|
||||
return {
|
||||
app,Pinia
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
36
package-lock.json
generated
36
package-lock.json
generated
@@ -5,19 +5,14 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.3.1",
|
||||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.13",
|
||||
"gm-crypto": "^0.1.8",
|
||||
"immutable": "^4.3.7",
|
||||
"js-base64": "^3.7.2",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"pinia-plugin-unistorage": "^0.1.2",
|
||||
"to-arraybuffer": "^1.0.1",
|
||||
"uview-plus": "^3.3.32",
|
||||
"ysk-utils": "^1.0.78"
|
||||
"uview-plus": "^3.3.32"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
@@ -455,14 +450,6 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
||||
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||
@@ -1084,12 +1071,6 @@
|
||||
"node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/loadsh": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/loadsh/-/loadsh-0.0.4.tgz",
|
||||
"integrity": "sha512-U+wLL8InpfRalWrr+0SuhWgGt10M4OyAk6G8xCYo2rwpiHtxZkWiFpjei0vO463ghW8LPCdhqQxXlMy2qicAEw==",
|
||||
"deprecated": "This is a typosquat on the popular Lodash package. This is not maintained nor is the original Lodash package."
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||
@@ -1200,11 +1181,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pinia-plugin-unistorage": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/pinia-plugin-unistorage/-/pinia-plugin-unistorage-0.1.2.tgz",
|
||||
"integrity": "sha512-WXit2cGnm5rG6CDTcLSLehNWhyJS/Yq7WEeeXAapZbCnqoPJxlszqg7rT8S+OP47az0h5nlajGo+LuyMxUQ2uw=="
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
|
||||
@@ -1750,16 +1726,6 @@
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ysk-utils": {
|
||||
"version": "1.0.78",
|
||||
"resolved": "https://registry.npmmirror.com/ysk-utils/-/ysk-utils-1.0.78.tgz",
|
||||
"integrity": "sha512-Bgr5B3WWiy0nbgL91QVKoVPYm4wt13Rlav757zEjMVRHbmTjwFEhi3wJlYus0JGd52mbknSxXHMazAPHXwA7uQ==",
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.3.1",
|
||||
"loadsh": "^0.0.4",
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.3.1",
|
||||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.13",
|
||||
"gm-crypto": "^0.1.8",
|
||||
"immutable": "^4.3.7",
|
||||
"js-base64": "^3.7.2",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "4.x",
|
||||
"pinia-plugin-unistorage": "^0.1.2",
|
||||
"to-arraybuffer": "^1.0.1",
|
||||
"uview-plus": "^3.3.32",
|
||||
"ysk-utils": "^1.0.82"
|
||||
"uview-plus": "^3.3.32"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
|
||||
@@ -1,39 +1,36 @@
|
||||
<template>
|
||||
<view class="boxconstant min-page">
|
||||
<view class="bg-fff u-flex u-m-b-32 top">
|
||||
<image style="width: 60rpx; height: 60rpx" src="/pageBwc/static/images/bwc.png"></image>
|
||||
<view class="u-flex-1 u-flex u-p-l-24">
|
||||
<view class="u-font-28 u-flex-1 u-p-r-4">
|
||||
<view class="color-333 font-bold">霸王餐</view>
|
||||
<view class="color-666 u-m-t-4 u-font-24">设置充值消费的N倍,当前订单立即免单</view>
|
||||
</view>
|
||||
<up-switch v-model="form.enable" size="18" :active-value="1" :inactive-value="0" :disabled="isMainShop() ? false : true"></up-switch>
|
||||
<view class="boxconstant">
|
||||
<view class="boxconstantbox"
|
||||
style="border-radius: 18px 18px 0 0;padding:32rpx 24rpx;border-bottom: 2rpx solid #E5E5E5;">
|
||||
<view class="boxconstantbox_one">
|
||||
充值设置
|
||||
</view>
|
||||
<view class="boxconstantbox_tow">
|
||||
<text>用户消费结账时,成功充值</text>
|
||||
<input class="text" type="number" :min='2' v-model="form.rechargeTimes" @change="rechargeTimesInput"/>
|
||||
<text>倍的金额本单即可享受免单</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="boxconstantbox">
|
||||
<view class="boxconstantbox_one">充值设置</view>
|
||||
<view class="u-flex u-m-t-32">
|
||||
<input class="number-box" type="number" :min="2" v-model="form.rechargeTimes" @blur="rechargeTimesInput" />
|
||||
<view class="bei">倍</view>
|
||||
<view class="boxconstantbox" style="border-radius: 0 0 18px 18px;">
|
||||
<view class="boxconstantbox_one">
|
||||
充值门槛
|
||||
</view>
|
||||
<view class="color-666 u-font-28 u-m-t-16">用户消费结账时,成功充值订单金额的X倍即可享受免单</view>
|
||||
<view class="u-m-t-20 u-m-b-20">
|
||||
<up-line class=""></up-line>
|
||||
</view>
|
||||
<view class="boxconstantbox_one">充值门槛</view>
|
||||
<view class="u-flex u-m-t-32">
|
||||
<input class="number-box" type="number" v-model="form.rechargeThreshold" @blur="rechargeThresholdInput" />
|
||||
<view class="bei">元</view>
|
||||
</view>
|
||||
<view class="color-666 u-font-28 u-m-t-16">订单的支付金额满足X元,才能使用</view>
|
||||
</view>
|
||||
<view class="boxconstantbox">
|
||||
<view class="boxconstantbox_one">可用门店</view>
|
||||
<view class="u-m-t-16">
|
||||
<my-shop-select @shop-select="shopSelect" v-model:selShops="form.shopIdList" v-model:useType="form.useShopType"></my-shop-select>
|
||||
<view class="boxconstantbox_tow">
|
||||
<text>订单支付金额需满</text>
|
||||
<input class="text" type="digit" v-model="form.rechargeThreshold" @change="form.rechargeThreshold = $utils.isMoney(form.rechargeThreshold)"></input>
|
||||
<!-- <input class="text" type="digit" v-model="form.rechargeThreshold" @input="form.rechargeThreshold = 2"></input> -->
|
||||
<!-- <input class="text" type="digit" v-model.lazy="form.rechargeThreshold" @input="form.rechargeThreshold = $utils.debounce($utils.isMoney(form.rechargeThreshold))"></input> -->
|
||||
<!-- <input class="text" type="digit" v-model="form.rechargeThreshold" @input="form.rechargeThreshold = $utils.isMoney(form.rechargeThreshold)"></input> -->
|
||||
<text> 元,才能使用</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="boxconstantbox"
|
||||
<view class="oneboxconstant">
|
||||
<view class="oneboxconstant_one">
|
||||
功能启用
|
||||
</view>
|
||||
<up-switch v-model="form.enable" size="18"></up-switch>
|
||||
</view>
|
||||
<view class="boxconstantbox"
|
||||
style="margin-top:24rpx; padding:32rpx 24rpx; border-radius: 0 0 18px 18px;">
|
||||
<view class="boxconstantbox_one" style="margin-bottom: 15rpx;">
|
||||
充值说明
|
||||
@@ -41,239 +38,139 @@
|
||||
<view>
|
||||
<up-textarea v-model="form.rechargeDesc" placeholder="请输入内容"></up-textarea>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="boxconstantbox">
|
||||
<view class="boxconstantbox_one">可使用类型</view>
|
||||
<view class="u-m-t-16">
|
||||
<my-dine-types v-model="form.useType"></my-dine-types>
|
||||
</view>
|
||||
</view>
|
||||
<view class="boxconstantbox">
|
||||
<view class="u-flex u-col-center u-row-between">
|
||||
<view>
|
||||
<view class="color-333 u-font-32 font-bold">与优惠券同享</view>
|
||||
<view class="color-666 u-font-24 u-m-t-4">开启后,可与优惠券同时使用</view>
|
||||
</view>
|
||||
<up-switch v-model="form.withCoupon" size="18"></up-switch>
|
||||
</view>
|
||||
<view class="u-flex u-col-center u-row-between u-m-t-24">
|
||||
<view>
|
||||
<view class="color-333 u-font-32 font-bold">与积分抵扣同享</view>
|
||||
<view class="color-666 u-font-24 u-m-t-4">开启后,可与积分抵扣同时使用</view>
|
||||
</view>
|
||||
<up-switch v-model="form.withPoints" size="18"></up-switch>
|
||||
</view>
|
||||
<view class="save" @click="editFreeDing">
|
||||
保存
|
||||
</view>
|
||||
<my-bottom-btn-group @cancel="cancel" @save="editFreeDing" isOpenPermission></my-bottom-btn-group>
|
||||
<my-marketing-mask name="霸王餐" v-if="isMarketShow(configInfo, 'shopIdList', 'enable')"></my-marketing-mask>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onShow, onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { isMainShop, isMarketShow } from '@/store/account';
|
||||
import { getFreeDing, updateFreeDing } from '@/http/api/freeDing.js';
|
||||
|
||||
const configInfo = ref({});
|
||||
|
||||
const form = reactive({
|
||||
rechargeTimes: 2,
|
||||
rechargeThreshold: '',
|
||||
enable: false,
|
||||
rechargeDesc: '',
|
||||
useShopType: 'all',
|
||||
useType: [],
|
||||
shopIdList: [],
|
||||
withCoupon: false,
|
||||
withPoints: false
|
||||
});
|
||||
onLoad(() => {
|
||||
// uni.$utils.inputReg.bind()()
|
||||
});
|
||||
onShow(() => {
|
||||
getlist();
|
||||
});
|
||||
/**
|
||||
* 获取配置信息
|
||||
*/
|
||||
const getlist = async () => {
|
||||
let res = await getFreeDing();
|
||||
configInfo.value = res;
|
||||
res.shopIdList = res.shopIdList || [];
|
||||
Object.assign(form, res);
|
||||
};
|
||||
|
||||
let rechargeTimesInput = (e) => {
|
||||
console.log(e);
|
||||
if (e.detail.value == '' || e.detail.value < 2) {
|
||||
form.rechargeTimes = 2;
|
||||
uni.showToast({
|
||||
title: '请输入大于等于2的整数',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
function rechargeThresholdInput(e) {
|
||||
if (e.detail.value == '' || e.detail.value <= 0.01) {
|
||||
form.rechargeThreshold = 0.01;
|
||||
uni.showToast({
|
||||
title: '请输入大于0的数字',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 修改配置信息
|
||||
*/
|
||||
const editFreeDing = async () => {
|
||||
if (!form.rechargeTimes) {
|
||||
uni.showToast({
|
||||
title: '请输入充值设置',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!form.rechargeThreshold) {
|
||||
uni.showToast({
|
||||
title: '请输入充值门槛',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (form.useShopType != 'all' && !form.shopIdList.length) {
|
||||
uni.showToast({
|
||||
title: '请选择可用门店',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (form.useType.length == 0) {
|
||||
uni.showToast({
|
||||
title: '请选择可使用类型',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
let res = await updateFreeDing(form);
|
||||
uni.showToast({
|
||||
title: '保存成功'
|
||||
import { onShow ,onLoad} from '@dcloudio/uni-app';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
|
||||
import { getFreeDing, updateFreeDing } from '@/http/api/freeDing.js'
|
||||
const form = reactive({
|
||||
rechargeTimes: 2,
|
||||
rechargeThreshold: '',
|
||||
enable: false,
|
||||
rechargeDesc: '',
|
||||
});
|
||||
Object.assign(form, res);
|
||||
setTimeout(() => {
|
||||
// uni.navigateBack();
|
||||
}, 1500);
|
||||
};
|
||||
onLoad(()=>{
|
||||
// uni.$utils.inputReg.bind()()
|
||||
})
|
||||
onShow(() => {
|
||||
getlist()
|
||||
})
|
||||
/**
|
||||
* 获取配置信息
|
||||
*/
|
||||
const getlist = async () => {
|
||||
let res = await getFreeDing()
|
||||
Object.assign(form, res)
|
||||
}
|
||||
|
||||
let rechargeTimesInput = (e) => {
|
||||
if( uni.$utils.isNumber(e.detail.value) == '' || uni.$utils.isNumber(e.detail.value) < 2 ){
|
||||
form.rechargeTimes = 2;
|
||||
return;
|
||||
}
|
||||
form.rechargeTimes = uni.$utils.isNumber(e.detail.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改配置信息
|
||||
*/
|
||||
const editFreeDing = async () => {
|
||||
let res = await updateFreeDing(form)
|
||||
uni.showToast({
|
||||
title: '保存成功'
|
||||
})
|
||||
Object.assign(form, res)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.boxconstant {
|
||||
background: #f7f7f7;
|
||||
padding: 32rpx 28rpx;
|
||||
page {
|
||||
background: #F9F9F9;
|
||||
}
|
||||
|
||||
.boxconstantbox {
|
||||
padding: 32rpx 24rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-top: 32rpx;
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
.boxconstant {
|
||||
padding: 32rpx 28rpx;
|
||||
|
||||
.boxconstantbox_one {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.boxconstantbox {
|
||||
padding: 32rpx 24rpx;
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
|
||||
.boxconstantbox_tow {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
// display: flex;
|
||||
// justify-content: flex-start;
|
||||
// align-items: center;
|
||||
// flex-wrap: wrap;
|
||||
// align-content: flex-start;
|
||||
.text {
|
||||
display: inline-flex;
|
||||
text-align: center;
|
||||
margin: 0 12rpx;
|
||||
width: 118rpx;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
.boxconstantbox_one {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.boxconstantbox_tow {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
// display: flex;
|
||||
// justify-content: flex-start;
|
||||
// align-items: center;
|
||||
// flex-wrap: wrap;
|
||||
// align-content: flex-start;
|
||||
.text {
|
||||
display:inline-flex;
|
||||
text-align: center;
|
||||
margin: 0 12rpx;
|
||||
width: 118rpx;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||||
border: 2rpx solid #E5E5E5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.oneboxconstant {
|
||||
margin-top: 32rpx;
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 32rpx 24rpx;
|
||||
.oneboxconstant {
|
||||
margin-top: 32rpx;
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 32rpx 24rpx;
|
||||
|
||||
.oneboxconstant_one {
|
||||
.oneboxconstant_one {
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.save {
|
||||
margin: 100rpx auto 50rpx auto;
|
||||
width: 530rpx;
|
||||
height: 80rpx;
|
||||
background: #318AFE;
|
||||
border-radius: 56rpx 56rpx 56rpx 56rpx;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.save {
|
||||
margin: 100rpx auto 50rpx auto;
|
||||
width: 530rpx;
|
||||
height: 80rpx;
|
||||
background: #318afe;
|
||||
border-radius: 56rpx 56rpx 56rpx 56rpx;
|
||||
font-family: Source Han Sans CN, Source Han Sans CN;
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.top {
|
||||
padding: 24rpx 20rpx 28rpx 28rpx;
|
||||
}
|
||||
.number-box {
|
||||
width: 260rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 0 26rpx;
|
||||
border-radius: 6rpx 0 0 6rpx;
|
||||
border-top: 2rpx solid #d9d9d9;
|
||||
border-bottom: 2rpx solid #d9d9d9;
|
||||
border-left: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
}
|
||||
.bei {
|
||||
display: flex;
|
||||
padding: 0 38rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
align-items: center;
|
||||
border-radius: 0 6rpx 6rpx 0;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #f7f7fa;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,694 +0,0 @@
|
||||
<template>
|
||||
<view class="min-page bg-f7 u-font-28 color-333" :style="pageHeight">
|
||||
<view class="top u-flex u-row-between">
|
||||
<view>
|
||||
<text style="max-width: 286rpx" class="u-line-1 u-font-32">
|
||||
{{ groupInfo.name }}
|
||||
</text>
|
||||
<text class="u-m-l-22">({{ membersRes.user_list.length }}人)</text>
|
||||
</view>
|
||||
<view class="" @click="toMore()">
|
||||
<view class="u-flex u-row-center">
|
||||
<up-icon name="more-dot-fill" color="#333" size="14"></up-icon>
|
||||
</view>
|
||||
<view class="color-666">更多</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-1">
|
||||
<!-- @refresherrefresh="refresherrefresh" -->
|
||||
|
||||
<scroll-view
|
||||
scroll-y
|
||||
refresher-background="transparent"
|
||||
style="height: 100%"
|
||||
@scrolltoupper="refresherrefresh"
|
||||
:refresher-enabled="false"
|
||||
:scroll-with-animation="false"
|
||||
:refresher-triggered="scrollView.refresherTriggered"
|
||||
:scroll-into-view="scrollView.intoView"
|
||||
>
|
||||
<view class="scroll-view-box">
|
||||
<view class="talk-list">
|
||||
<view :id="'msg-' + index" v-for="(item, index) in chatStore.chatList" :key="index">
|
||||
<!-- 发消息 -->
|
||||
<template v-if="item.operate_type == 'sendMsg' || item.is_user_send == 1 || item.from_id == shopInfo.id">
|
||||
<view class="shop u-flex u-row-right">
|
||||
<view class="u-p-r-18">
|
||||
<view class="u-flex u-row-right name-wrap">
|
||||
<view class="tag">商家</view>
|
||||
<view class="name">{{ shopInfo.shopName }}</view>
|
||||
</view>
|
||||
<view class="u-m-t-14 msg" :class="['type' + item.msg_type]">
|
||||
<chatItem :item="item"></chatItem>
|
||||
</view>
|
||||
<view class="text-center u-m-t-20" v-if="item.msg_type == 4 && item.hasGet">
|
||||
<text>{{ item.hasGet || 0 }}人已领取</text>
|
||||
<text class="color-main">优惠券</text>
|
||||
</view>
|
||||
</view>
|
||||
<up-avatar size="70rpx" shape="square" bg-color="#fff" :src="shopInfo.logo"></up-avatar>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 收消息 -->
|
||||
<template v-else>
|
||||
<view class="user u-flex">
|
||||
<up-avatar size="70rpx" :src="item.avatar" shape="square" bg-color="#fff"></up-avatar>
|
||||
<view class="u-p-l-18">
|
||||
<view class="name u-line-1">{{ item.nick }}</view>
|
||||
<view class="u-m-t-14 msg u-p-l-30" :class="['type' + item.msg_type]">
|
||||
<chatItem :item="item"></chatItem>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<up-loadmore v-if="isEnd" :status="isEnd ? 'nomore' : 'loading'"></up-loadmore>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- <view :style="bottomSlotHeight"></view> -->
|
||||
|
||||
<view class="bottom" :class="[showMoreBtn ? '' : 'safe-bottom']">
|
||||
<view class="u-flex" style="padding: 14rpx 28rpx">
|
||||
<!-- <input
|
||||
type="text"
|
||||
class="u-flex-1 u-m-r-52 iput"
|
||||
placeholder="请输入内容"
|
||||
v-model="msg"
|
||||
/> -->
|
||||
<view class="u-flex-1 u-m-r-52 iput">
|
||||
<up-input v-model="msg" border="none" placeholder="请输入内容"></up-input>
|
||||
</view>
|
||||
<button class="send-btn" v-if="msg.trim().length > 0" @click="sendText">发送</button>
|
||||
<up-icon name="plus-circle" color="#666" size="60rpx" @click="showMoreBtnToggle" v-else></up-icon>
|
||||
</view>
|
||||
<view class="more-btn" v-if="showMoreBtn">
|
||||
<view v-for="(item, index) in moreBtns" @click="moreBtnsClick(item, index)" class="u-flex-col u-row-center u-col-center">
|
||||
<view class="u-flex icon">
|
||||
<image :src="item.icon" class="img" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="u-m-t-8">{{ item.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 发送优惠券 -->
|
||||
<Modal title="发送优惠券" v-model="modalData.show" confirmText="确认发送" @close="closeModal" @confirm="confirmCoupon">
|
||||
<view class="u-p-30">
|
||||
<view class="font-bold u-m-b-16">自定义文案</view>
|
||||
<up-input v-model="modalData.form.title" placeholder="请输入自定义文案" :placeholderStyle="placeholderStyle" maxlength="12"></up-input>
|
||||
<view class="font-bold u-m-b-16 u-m-t-32">发放数量(张)</view>
|
||||
|
||||
<up-number-box v-model="modalData.form.giveNum" inputWidth="240rpx" @change="valChange"></up-number-box>
|
||||
|
||||
<view class="font-bold u-m-b-16 u-m-t-32">每人限领量(张)</view>
|
||||
<up-number-box v-model="modalData.form.getLimit" :max="modalData.form.giveNum" inputWidth="240rpx" @change="valChange"></up-number-box>
|
||||
<view class="font-bold u-m-b-16 u-m-t-32">选择优惠券</view>
|
||||
<chooseCoupon v-model="modalData.form.couponId"></chooseCoupon>
|
||||
</view>
|
||||
</Modal>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onReady, onReachBottom, onLoad, onShow, onPageScroll } from '@dcloudio/uni-app';
|
||||
import { ref, inject, onMounted, onUnmounted, nextTick, reactive, watch, computed } from 'vue';
|
||||
import { useChatStore } from '@/store/chat';
|
||||
import * as chatApi from '@/http/php/chat';
|
||||
import * as chatCouponApi from '@/http/api/market/chat';
|
||||
import { uploadFile } from '@/http/api/index.js';
|
||||
import go from '@/commons/utils/go.js';
|
||||
import Modal from './components/modal.vue';
|
||||
import chooseCoupon from './components/coupon.vue';
|
||||
import chatItem from './components/chat-item.vue';
|
||||
const placeholderStyle = {
|
||||
color: '#999',
|
||||
fontSize: '28rpx'
|
||||
};
|
||||
|
||||
function refresherrefresh() {
|
||||
console.log('refresherrefresh');
|
||||
// 关键:同时判断「正在加载」和「无更多数据」,只要一个为真就关闭刷新
|
||||
if (isLoading.value || isEnd.value) {
|
||||
scrollView.refresherTriggered = false; // 立即关闭刷新状态
|
||||
if (isEnd.value) {
|
||||
}
|
||||
return; // 终止后续逻辑
|
||||
}
|
||||
|
||||
query.page++;
|
||||
getMsgList();
|
||||
}
|
||||
|
||||
const scrollView = reactive({
|
||||
refresherTriggered: false,
|
||||
intoView: '',
|
||||
safeAreaHeight: 0
|
||||
});
|
||||
|
||||
const showMoreBtn = ref(false);
|
||||
function showMoreBtnToggle() {
|
||||
showMoreBtn.value = !showMoreBtn.value;
|
||||
if (showMoreBtn.value) {
|
||||
}
|
||||
}
|
||||
const modalData = reactive({
|
||||
show: false,
|
||||
form: {
|
||||
title: '',
|
||||
getLimit: 1,
|
||||
giveNum: 1,
|
||||
couponId: ''
|
||||
}
|
||||
});
|
||||
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const handleReceiveMsg = (msg) => {
|
||||
nextTick(() => {
|
||||
scrollView.intoView = 'msg-0';
|
||||
});
|
||||
};
|
||||
|
||||
// 注册消息回调
|
||||
chatStore.registerReceiveMsgCallback(handleReceiveMsg);
|
||||
const msg = ref('');
|
||||
|
||||
const shopInfo = uni.getStorageSync('shopInfo');
|
||||
|
||||
const moreBtns = ref([
|
||||
{
|
||||
icon: '/pageChat/static/pic.png',
|
||||
title: '发送照片',
|
||||
value: 'pic'
|
||||
},
|
||||
{
|
||||
icon: '/pageChat/static/video.png',
|
||||
title: '发送视频',
|
||||
value: 'video'
|
||||
},
|
||||
{
|
||||
icon: '/pageChat/static/coupon.png',
|
||||
title: '发送优惠券',
|
||||
value: 'coupon'
|
||||
}
|
||||
]);
|
||||
|
||||
function moreBtnsClick(item, index) {
|
||||
if (item.value == 'coupon') {
|
||||
modalData.show = true;
|
||||
return;
|
||||
}
|
||||
if (item.value == 'pic') {
|
||||
sendImg();
|
||||
}
|
||||
if (item.value == 'video') {
|
||||
sendVideo();
|
||||
}
|
||||
}
|
||||
function videoErrorCallback(e) {
|
||||
console.error('视频播放失败', e);
|
||||
}
|
||||
async function sendImg() {
|
||||
try {
|
||||
// 1. 调用图片选择API,添加fail回调
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
uni.chooseImage({
|
||||
count: 3,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: resolve,
|
||||
fail: reject // 捕获选择失败(含权限拒绝)
|
||||
});
|
||||
});
|
||||
|
||||
uni.showLoading({ title: '发送中' });
|
||||
console.log('选择图片成功', res);
|
||||
|
||||
// 2. 批量上传图片(保持原有逻辑)
|
||||
for (let i = 0; i < res.tempFiles.length; i++) {
|
||||
const fileRes = await uploadFile(res.tempFiles[i]);
|
||||
if (fileRes) {
|
||||
sendMsg({
|
||||
image_url: fileRes,
|
||||
msg_type: 2
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('图片选择/发送失败', err);
|
||||
// 3. 处理权限拒绝场景
|
||||
handlePermissionError(err, '图片');
|
||||
} finally {
|
||||
// 4. 确保加载弹窗关闭(无论成功/失败)
|
||||
uni.hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
// 视频选择与发送优化
|
||||
async function sendVideo() {
|
||||
try {
|
||||
// 1. 调用视频选择API,添加fail回调
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
uni.chooseVideo({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: resolve,
|
||||
fail: reject // 捕获选择失败(含权限拒绝)
|
||||
});
|
||||
});
|
||||
|
||||
uni.showLoading({ title: '发送中' });
|
||||
console.log('选择视频成功', res);
|
||||
|
||||
// 2. 上传视频(保持原有逻辑)
|
||||
const fileRes = await uploadFile({ path: res.tempFilePath });
|
||||
if (fileRes) {
|
||||
sendMsg({
|
||||
image_url: fileRes,
|
||||
msg_type: 5
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '视频发送失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('视频选择/发送失败', err);
|
||||
// 3. 处理权限拒绝场景
|
||||
handlePermissionError(err, '视频');
|
||||
} finally {
|
||||
// 4. 确保加载弹窗关闭(无论成功/失败)
|
||||
uni.hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
// 通用权限错误处理函数
|
||||
function handlePermissionError(err, mediaType) {
|
||||
const errMsg = err.errMsg || '';
|
||||
// 识别权限拒绝关键词(兼容不同平台)
|
||||
const isAuthDenied = ['auth deny', 'permission denied', 'auth denied', '用户拒绝'].some((keyword) => errMsg.includes(keyword));
|
||||
|
||||
if (isAuthDenied) {
|
||||
// 弹窗提示用户,并引导至设置页
|
||||
uni.showModal({
|
||||
title: '权限提示',
|
||||
content: `需要${mediaType}权限才能使用该功能,请前往设置开启`,
|
||||
confirmText: '去设置',
|
||||
cancelText: '取消',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
// 跳转到小程序设置页
|
||||
uni.openSetting({
|
||||
success: (settingRes) => {
|
||||
console.log('设置页返回结果', settingRes);
|
||||
// 可根据需要添加权限开启后的回调逻辑
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 其他错误(如取消选择),仅轻提示
|
||||
if (!errMsg.includes('cancel')) {
|
||||
uni.showToast({
|
||||
title: `${mediaType}选择失败`,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const groupInfo = ref({});
|
||||
async function init() {
|
||||
const res = await chatApi.groupInfo({
|
||||
group_id: options.group_id
|
||||
});
|
||||
console.log(res);
|
||||
groupInfo.value = res || {};
|
||||
if (res) {
|
||||
chatStore.connectSocket();
|
||||
// 确保状态监听已初始化
|
||||
if (!chatStore._listenersInitialized) {
|
||||
chatStore.initStateListeners();
|
||||
chatStore._listenersInitialized = true;
|
||||
}
|
||||
}
|
||||
getMsgList();
|
||||
}
|
||||
const query = reactive({
|
||||
page: 1,
|
||||
size: 10
|
||||
});
|
||||
async function getMsgList() {
|
||||
// 提前拦截:已无更多数据,直接关闭状态
|
||||
if (isEnd.value) {
|
||||
scrollView.refresherTriggered = false;
|
||||
isLoading.value = false;
|
||||
uni.showToast({ title: '没有更多了', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const msgRes = await chatApi.messageHistory({
|
||||
...query,
|
||||
chat_type: '2',
|
||||
session_id: options.session_id,
|
||||
to_id: options.group_id,
|
||||
shop_id: options.group_id,
|
||||
group_id: options.group_id
|
||||
});
|
||||
const data = msgRes.list || [];
|
||||
const selector = `msg-${query.page == 1 ? 0 : chatStore.chatList.length}`;
|
||||
|
||||
if (query.page == 1) {
|
||||
chatStore.chatList = data;
|
||||
} else {
|
||||
chatStore.chatList.push(...data);
|
||||
}
|
||||
|
||||
isEnd.value = chatStore.chatList.length >= msgRes.total;
|
||||
nextTick(() => {
|
||||
scrollView.intoView = selector;
|
||||
console.log(selector);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('加载历史消息异常', err);
|
||||
// 加载失败回退页码,避免页码错乱
|
||||
if (query.page > 1) query.page--;
|
||||
} finally {
|
||||
console.log('scrollView', scrollView);
|
||||
setTimeout(() => {
|
||||
scrollView.refresherTriggered = false;
|
||||
isLoading.value = false;
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
const options = reactive({});
|
||||
const membersRes = reactive({
|
||||
user_list: []
|
||||
});
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt);
|
||||
init();
|
||||
chatApi.messageMarkReadAll({
|
||||
session_ids: options.group_id
|
||||
});
|
||||
chatStore.group_id = options.group_id;
|
||||
chatApi.groupMembers({ group_id: options.group_id }).then((res) => {
|
||||
console.log(res);
|
||||
membersRes.user_list = res.user_list || [];
|
||||
});
|
||||
// #ifdef H5
|
||||
scrollView.safeAreaHeight = uni.getSystemInfoSync().safeArea.height;
|
||||
// #endif
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
// 页面显示时,检查连接状态
|
||||
if (!chatStore.isConnect || !chatStore.socketTask) {
|
||||
console.log('聊天页显示,检查Socket连接');
|
||||
chatStore.forceReconnect();
|
||||
}
|
||||
});
|
||||
|
||||
function toMore() {
|
||||
go.to('PAGES_CHAT_GROUP_INFO', {
|
||||
group_id: groupInfo.value.id,
|
||||
session_id: options.session_id
|
||||
});
|
||||
}
|
||||
function sendText() {
|
||||
if (!msg.value.trim().length) return;
|
||||
sendMsg({ content: msg.value, msg_type: 1 });
|
||||
msg.value = '';
|
||||
}
|
||||
|
||||
function sendMsg(msg) {
|
||||
chatStore.sendMessage({
|
||||
to_id: groupInfo.value.id,
|
||||
to_user_type: groupInfo.value.id,
|
||||
chat_type: 2,
|
||||
content: msg.value,
|
||||
image_url: '',
|
||||
order_id: '',
|
||||
session_id: groupInfo.value.session_id || options.session_id,
|
||||
...msg
|
||||
});
|
||||
}
|
||||
function closeModal() {
|
||||
modalData.form = {
|
||||
title: '',
|
||||
getLimit: 1,
|
||||
giveNum: 1,
|
||||
couponId: ''
|
||||
};
|
||||
}
|
||||
function confirmCoupon() {
|
||||
console.log(modalData.form);
|
||||
// if (!modalData.form.title) {
|
||||
// uni.showToast({
|
||||
// title: "请输入自定义文案",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
if (!modalData.form.couponId) {
|
||||
uni.showToast({
|
||||
title: '请选择优惠券',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!modalData.form.giveNum) {
|
||||
uni.showToast({
|
||||
title: '请输入发放数量',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!modalData.form.getLimit) {
|
||||
uni.showToast({
|
||||
title: '请输入每人限领量',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
chatCouponApi.chatCouponCreate(modalData.form).then((res) => {
|
||||
if (res) {
|
||||
modalData.show = false;
|
||||
const couponJson = JSON.parse(res.couponJson);
|
||||
sendMsg({
|
||||
coupon: {
|
||||
...couponJson,
|
||||
title: modalData.form.title,
|
||||
activity_id: res.id
|
||||
},
|
||||
chat_coupon_id: res.id,
|
||||
msg_type: 4
|
||||
});
|
||||
closeModal();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '发送失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function previewImage(url) {
|
||||
uni.previewImage({
|
||||
urls: [url]
|
||||
});
|
||||
}
|
||||
|
||||
//是否到底了
|
||||
const isBottom = ref(false);
|
||||
|
||||
const isLoading = ref(false);
|
||||
|
||||
//消息是否完了
|
||||
const isEnd = ref(false);
|
||||
|
||||
watch(
|
||||
() => chatStore.chatList.length,
|
||||
(newVal, oldVal) => {}
|
||||
);
|
||||
|
||||
const bottomSlotHeight = computed(() => {
|
||||
if (showMoreBtn.value) {
|
||||
return {
|
||||
height: '180px'
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
height: '88px'
|
||||
};
|
||||
}
|
||||
});
|
||||
onReady(() => {});
|
||||
const pageHeight = computed(() => {
|
||||
const safeAreaHeight = scrollView.safeAreaHeight;
|
||||
if (safeAreaHeight > 0) {
|
||||
return `height: calc(${safeAreaHeight}px - var(--window-top));`;
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 组件卸载时,移除消息回调
|
||||
chatStore.removeReceiveMsgCallback(handleReceiveMsg);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$grayColor: #9e9e9e;
|
||||
$grayBorderColor: #bebebe;
|
||||
.top {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 32rpx;
|
||||
}
|
||||
.min-page {
|
||||
height: calc(100vh - var(--window-top));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
align-content: center;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
.talk-list {
|
||||
padding: 30rpx 28rpx 30rpx 26rpx;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
flex-wrap: nowrap;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-end;
|
||||
align-items: stretch;
|
||||
// 添加弹性容器,让内容自动在顶部
|
||||
&::before {
|
||||
content: '.';
|
||||
display: inline;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
font-size: 0;
|
||||
flex: 1 0 auto;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
.box-1 {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
flex: 1 0 auto;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.user {
|
||||
margin-bottom: 88rpx;
|
||||
align-items: flex-start;
|
||||
.name {
|
||||
margin-top: -4upx;
|
||||
color: $grayColor;
|
||||
font-size: 24upx;
|
||||
}
|
||||
.msg {
|
||||
padding: 16rpx 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
.shop {
|
||||
margin-bottom: 88rpx;
|
||||
align-items: flex-start;
|
||||
.tag {
|
||||
margin-right: 32rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border: 1px solid $grayBorderColor;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
color: $grayColor;
|
||||
}
|
||||
.name-wrap {
|
||||
margin-top: -8upx;
|
||||
}
|
||||
.name {
|
||||
color: $grayColor;
|
||||
font-size: 24upx;
|
||||
}
|
||||
.msg {
|
||||
padding: 16rpx 20rpx;
|
||||
border-radius: 20rpx;
|
||||
&.type1 {
|
||||
background-color: #fff;
|
||||
}
|
||||
&.type4 {
|
||||
background-color: #fff;
|
||||
}
|
||||
.img {
|
||||
width: 50vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom {
|
||||
height: auto;
|
||||
z-index: 2;
|
||||
border-top: #e5e5e5 solid 1px;
|
||||
box-sizing: content-box;
|
||||
background-color: #f3f3f3;
|
||||
|
||||
/* 兼容iPhoneX */
|
||||
padding-bottom: 0;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
&.safe-bottom {
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 4rpx);
|
||||
}
|
||||
.iput {
|
||||
background-color: #f8f8f8;
|
||||
padding: 16rpx 20rpx;
|
||||
}
|
||||
}
|
||||
.send-btn {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
padding: 16rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.more-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
background-color: #f0f0f0;
|
||||
gap: 74rpx;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 4rpx);
|
||||
|
||||
.icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.img {
|
||||
height: 70rpx;
|
||||
width: 70rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-view-box {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
</style>
|
||||
@@ -1,147 +0,0 @@
|
||||
<template>
|
||||
<text class="" v-if="item.msg_type == 1">{{ item.content }}</text>
|
||||
<image
|
||||
v-if="item.msg_type == 2"
|
||||
:src="item.image_url"
|
||||
class="img"
|
||||
mode="widthFix"
|
||||
@click="previewImage(item.image_url)"
|
||||
></image>
|
||||
<video
|
||||
@error="videoErrorCallback"
|
||||
v-if="item.msg_type == 5"
|
||||
:src="item.image_url"
|
||||
class="img"
|
||||
mode="widthFix"
|
||||
></video>
|
||||
<view class="" v-if="item.msg_type == 4">
|
||||
<view>{{ item.coupon.title }}</view>
|
||||
<view class="u-m-t-16 bg-f7 coupon u-flex u-col-stretch" style="min-width: 500rpx;">
|
||||
<template v-if="item.coupon.type == 1">
|
||||
<view class="left">
|
||||
<view class="price">
|
||||
<text class="u-font-32">¥</text>
|
||||
<text style="font-size: 72rpx">{{
|
||||
item.coupon.discountAmount
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="u-font-24 color-999 no-wrap"
|
||||
>满{{ item.coupon.fullAmount }}可用</view
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.coupon.type == 2">
|
||||
<view class="left">
|
||||
<view class="price">
|
||||
<text class="u-font-32"
|
||||
>商品兑换券</text
|
||||
>
|
||||
</view>
|
||||
<view class="u-font-24 color-999 no-wrap"
|
||||
>满{{ item.coupon.fullAmount }}可用</view
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template v-if="item.coupon.type == 3">
|
||||
<view class="left">
|
||||
<view class="price">
|
||||
<text class="u-font-32"
|
||||
>{{ item.coupon.discountRate / 100 }}折</text
|
||||
>
|
||||
</view>
|
||||
<view class="u-font-24 color-999 no-wrap"
|
||||
>满{{ item.coupon.fullAmount }}可用</view
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.coupon.type == 4">
|
||||
<view class="left">
|
||||
<view class="price">
|
||||
<text class="u-font-32"
|
||||
>第二件半价券</text
|
||||
>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.coupon.type == 6">
|
||||
<view class="left">
|
||||
<view class="price">
|
||||
<text class="u-font-32"
|
||||
>买一送一券</text
|
||||
>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
<view class="right u-p-l-28 u-flex u-col-center">
|
||||
<view class="u-font-32">{{ item.coupon.couponName }}</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import dayjs from 'dayjs'
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
function previewImage(url) {
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
});
|
||||
}
|
||||
function returnTime(coupon){
|
||||
// if(coupon.validType=="fixed"){
|
||||
// return dayjs().add(coupon.daysToTakeEffect,'day').format('YYYY-MM-DD')
|
||||
// }
|
||||
let startTime = coupon.useStartTime;
|
||||
let endTime = coupon.useEndTime;
|
||||
if(startTime && endTime){
|
||||
return startTime.split(' ')[0] + '-' + endTime.split(' ')[0]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.img {
|
||||
width: 50vw;
|
||||
}
|
||||
.coupon {
|
||||
padding: 16rpx 10rpx;
|
||||
border-radius: 16rpx;
|
||||
.price {
|
||||
color: #ff1c1c;
|
||||
font-weight: 700;
|
||||
}
|
||||
.left {
|
||||
width: 112rpx;
|
||||
margin-right: 26rpx;
|
||||
}
|
||||
.right {
|
||||
border-left: 1rpx solid #ededed;
|
||||
|
||||
}
|
||||
}
|
||||
.lingqu {
|
||||
background-color: #e8ad7b;
|
||||
line-height: 48rpx;
|
||||
font-size: 28rpx;
|
||||
padding: 6rpx 70rpx;
|
||||
color: #fff;
|
||||
border-radius: 140rpx;
|
||||
&.hasGet {
|
||||
background-color: #eee;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.u-col-stretch{
|
||||
align-items: stretch;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<up-popup :show="show" mode="bottom">
|
||||
<view class="">
|
||||
<view class="top u-flex u-row-between">
|
||||
<text class="font-bold u-font-32 color-333">{{ title }}</text>
|
||||
<up-icon size="18" name="close" @click="show = false"></up-icon>
|
||||
</view>
|
||||
<scroll-view
|
||||
ref="couponScroll"
|
||||
:scroll-y="true"
|
||||
style="max-height: 50vh"
|
||||
@scroll="scroll"
|
||||
:scroll-top="scrollTop"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
class="item"
|
||||
@click="itemClick(item)"
|
||||
:class="[selGoods && selGoods.id == item.id ? 'selected' : '']"
|
||||
>
|
||||
<view class="u-flex u-row-between">
|
||||
<view class="u-flex gap-20">
|
||||
<!-- <view class="u-flex" @click.stop="preview(item)">
|
||||
<up-image
|
||||
:src="item.coverImg"
|
||||
width="80rpx"
|
||||
height="80rpx"
|
||||
></up-image>
|
||||
</view> -->
|
||||
|
||||
<text class="u-font-32 color-333">{{ item.title }}</text>
|
||||
</view>
|
||||
<text class="u-font-32 color-red u-p-l-30"
|
||||
></text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<up-empty v-if="list.length == 0" class="u-p-30" text="暂无数据"></up-empty>
|
||||
</scroll-view>
|
||||
<view class="bottom">
|
||||
<view class="btn cancel" @click="close">{{ cancelText }}</view>
|
||||
<view class="btn success" @click="confirm">{{ confirmText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
const modelValue = defineModel({
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
const show = defineModel("show", {
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
const couponName = defineModel("couponName", {
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "选择优惠券",
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: "确认",
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: "取消",
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const selGoods = ref("");
|
||||
function itemClick(item) {
|
||||
if (selGoods.value && selGoods.value.id == item.id) {
|
||||
selGoods.value = "";
|
||||
return;
|
||||
}
|
||||
selGoods.value = item;
|
||||
}
|
||||
|
||||
const scrollTop = ref(0);
|
||||
function scroll(e) {
|
||||
scrollTop.value = e.detail.scrollTop;
|
||||
}
|
||||
function preview(item) {
|
||||
uni.previewImage({
|
||||
urls: item.images || [item.coverImg],
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => modelValue.value,
|
||||
(newVal, oldVal) => {
|
||||
console.log(newVal, oldVal);
|
||||
selGoods.value = props.list.find((item) => item.id == newVal);
|
||||
console.log(selGoods.value);
|
||||
if (selGoods.value) {
|
||||
couponName.value = selGoods.value.title;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.list.length,
|
||||
(newVal, oldVal) => {
|
||||
selGoods.value = props.list.find((item) => item.id == modelValue.value);
|
||||
console.log(selGoods.value);
|
||||
if (selGoods.value) {
|
||||
modelValue.value = selGoods.value.id;
|
||||
couponName.value = selGoods.value.title;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
const emit = defineEmits(["confirm"]);
|
||||
function confirm() {
|
||||
if (!selGoods.value) {
|
||||
uni.showToast({
|
||||
title: "请选择优惠券",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
modelValue.value = selGoods.value.id;
|
||||
show.value = false;
|
||||
emit("confirm", selGoods.value);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.popup-content {
|
||||
background: #fff;
|
||||
width: 640rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.top {
|
||||
padding: 40rpx 48rpx;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
.bottom {
|
||||
padding: 48rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
gap: 50rpx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 32rpx;
|
||||
border: 2rpx solid transparent;
|
||||
&.success {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.cancel {
|
||||
border-color: #d9d9d9;
|
||||
box-shadow: 0 4rpx 0 0 #00000005;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
padding: 10rpx 30rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
margin: 10rpx;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s ease-in-out;
|
||||
box-shadow: 0 0 10px transparent;
|
||||
&.selected {
|
||||
border-color: $my-main-color;
|
||||
box-shadow: 0 0 10px $my-main-color;
|
||||
}
|
||||
}
|
||||
.choose-goods {
|
||||
display: flex;
|
||||
padding: 24rpx;
|
||||
align-items: center;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<view @click="show = true">
|
||||
<slot v-if="$slots.default"> </slot>
|
||||
<view v-else class="choose-goods u-flex u-row-between">
|
||||
<text class="color-999" v-if="!modelValue">请选择商品</text>
|
||||
<text class="color-333 u-m-r-32 u-line-1" v-else>{{ goodsName }}</text>
|
||||
<up-icon size="14" name="arrow-down"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-popup :show="show" mode="bottom">
|
||||
<view class="">
|
||||
<view class="top u-flex u-row-between">
|
||||
<text class="font-bold u-font-32 color-333">{{ title }}</text>
|
||||
<up-icon size="18" name="close" @click="show = false"></up-icon>
|
||||
</view>
|
||||
<scroll-view :scroll-y="true" style="max-height: 50vh" @scroll="scroll" :scroll-top="scrollTop">
|
||||
<view
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
class="item"
|
||||
@click="itemClick(item)"
|
||||
:class="[selGoods&&selGoods.id == item.id ? 'selected' : '']"
|
||||
>
|
||||
<view class="u-flex u-row-between">
|
||||
<view class="u-flex gap-20">
|
||||
<view class="u-flex" @click.stop="preview(item)">
|
||||
<up-image
|
||||
:src="item.coverImg"
|
||||
width="80rpx"
|
||||
height="80rpx"
|
||||
></up-image>
|
||||
</view>
|
||||
|
||||
<text class="u-font-32 color-333">{{ item.name }}</text>
|
||||
</view>
|
||||
<text class="u-font-32 color-red u-p-l-30"
|
||||
>¥{{ item.lowPrice }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="bottom">
|
||||
<view class="btn cancel" @click="close">{{ cancelText }}</view>
|
||||
<view class="btn success" @click="confirm">{{ confirmText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from "vue";
|
||||
import { getProductList } from "@/http/api/product.js";
|
||||
const show = ref(false);
|
||||
const modelValue = defineModel({
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
|
||||
const goodsName = defineModel("goodsName", {
|
||||
type: String,
|
||||
default: "",
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "选择商品",
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: "确认",
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: "取消",
|
||||
},
|
||||
});
|
||||
|
||||
const selGoods = ref("");
|
||||
function itemClick(item) {
|
||||
if (selGoods.value&& selGoods.value.id == item.id) {
|
||||
selGoods.value = "";
|
||||
return;
|
||||
}
|
||||
selGoods.value = item;
|
||||
}
|
||||
const list = ref([]);
|
||||
|
||||
const scrollTop = ref(0);
|
||||
function scroll(e) {
|
||||
scrollTop.value = e.detail.scrollTop;
|
||||
}
|
||||
function preview(item) {
|
||||
uni.previewImage({
|
||||
urls: item.images || [item.coverImg],
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => modelValue.value,
|
||||
(newVal, oldVal) => {
|
||||
console.log(newVal, oldVal);
|
||||
selGoods.value = list.value.find((item) => item.id == newVal);
|
||||
console.log(selGoods.value);
|
||||
if(selGoods.value){
|
||||
goodsName.value = selGoods.value.name;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(()=>list.value.length,(newVal,oldVal)=>{
|
||||
selGoods.value = list.value.find((item) => item.id == modelValue.value);
|
||||
console.log(selGoods.value);
|
||||
if(selGoods.value){
|
||||
modelValue.value = selGoods.value.id;
|
||||
goodsName.value = selGoods.value.name;
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
function confirm() {
|
||||
if (!selGoods.value) {
|
||||
uni.showToast({
|
||||
title: "请选择商品",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
modelValue.value = selGoods.value.id;
|
||||
show.value = false;
|
||||
}
|
||||
onMounted(() => {
|
||||
getProductList().then((res) => {
|
||||
list.value = res;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.popup-content {
|
||||
background: #fff;
|
||||
width: 640rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.top {
|
||||
padding: 40rpx 48rpx;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
.bottom {
|
||||
padding: 48rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
gap: 50rpx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 32rpx;
|
||||
border: 2rpx solid transparent;
|
||||
&.success {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.cancel {
|
||||
border-color: #d9d9d9;
|
||||
box-shadow: 0 4rpx 0 0 #00000005;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
padding: 10rpx 30rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
margin: 10rpx;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s ease-in-out;
|
||||
box-shadow: 0 0 10px transparent;
|
||||
&.selected {
|
||||
border-color: $my-main-color;
|
||||
box-shadow: 0 0 10px $my-main-color;
|
||||
}
|
||||
}
|
||||
.choose-goods {
|
||||
display: flex;
|
||||
padding: 24rpx;
|
||||
align-items: center;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
@@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view
|
||||
class="u-flex u-row-between u-m-b-24"
|
||||
style="gap: 40rpx"
|
||||
v-for="(item, index) in modelValue"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
class="choose-coupon u-flex-1 u-flex u-row-between"
|
||||
@click="showCoupon(item, index)"
|
||||
>
|
||||
<template v-if="item.title">
|
||||
<text>{{ item.title }}</text>
|
||||
<view class="u-flex" @click.stop="item.title = ''">
|
||||
<up-icon name="close" size="14"></up-icon>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<text class="color-999">选择赠送券</text>
|
||||
<up-icon name="arrow-down" size="14"></up-icon>
|
||||
</template>
|
||||
</view>
|
||||
<view class="u-flex-1 u-flex">
|
||||
<view class="u-flex-1 choose-coupon u-flex">
|
||||
<input
|
||||
class="u-flex-1"
|
||||
placeholder=""
|
||||
type="number"
|
||||
v-model="item.num"
|
||||
placeholder-class="color-999 u-font-28"
|
||||
/>
|
||||
<text class="no-wrap color-999">张/1个码</text>
|
||||
</view>
|
||||
<view class="u-m-l-20">
|
||||
<up-icon name="minus-circle-fill" color="#EB4F4F" size="18" @click="removeCoupon(index)"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<chooseCoupon
|
||||
v-model="chooseCouponData.couponId"
|
||||
v-model:show="chooseCouponData.show"
|
||||
@confirm="confirmCoupon"
|
||||
:list="couponList"
|
||||
></chooseCoupon>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted } from "vue";
|
||||
import chooseCoupon from "./choose-coupon.vue";
|
||||
import { couponPage } from "@/http/api/market/index.js";
|
||||
|
||||
const chooseCouponData = reactive({
|
||||
couponId: "",
|
||||
show: false,
|
||||
index: -1,
|
||||
item: null,
|
||||
});
|
||||
const modelValue = defineModel({
|
||||
type: Array,
|
||||
default: () => [],
|
||||
});
|
||||
const couponList = ref([]);
|
||||
function showCoupon(item, index) {
|
||||
chooseCouponData.couponId = item ? item.id : "";
|
||||
chooseCouponData.show = true;
|
||||
chooseCouponData.index = index;
|
||||
chooseCouponData.item = item;
|
||||
}
|
||||
function confirmCoupon(e) {
|
||||
modelValue.value[chooseCouponData.index].id = e.id;
|
||||
modelValue.value[chooseCouponData.index].title = e.title;
|
||||
}
|
||||
function removeCoupon(index) {
|
||||
modelValue.value.splice(index, 1);
|
||||
}
|
||||
onMounted(() => {
|
||||
couponPage({ size: 999 }).then((res) => {
|
||||
couponList.value = res.records;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.choose-coupon {
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
}
|
||||
</style>
|
||||
@@ -1,75 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="u-flex u-row-between u-m-b-24" style="gap: 40rpx">
|
||||
<view
|
||||
class="choose-coupon u-flex-1 u-flex u-row-between"
|
||||
@click="showCoupon(item, index)"
|
||||
>
|
||||
<template v-if="couponName">
|
||||
<text>{{ couponName }}</text>
|
||||
<view class="u-flex" @click.stop="modelValue = ''">
|
||||
<up-icon name="close" size="14"></up-icon>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<text class="color-999">选择赠送券</text>
|
||||
<up-icon name="arrow-down" size="14"></up-icon>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<chooseCoupon
|
||||
v-model="chooseCouponData.couponId"
|
||||
v-model:show="chooseCouponData.show"
|
||||
@confirm="confirmCoupon"
|
||||
:list="couponList"
|
||||
></chooseCoupon>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, ref, onMounted, computed } from "vue";
|
||||
import chooseCoupon from "./choose-coupon.vue";
|
||||
import { chatCoupon } from "@/http/api/market/chatCoupon.js";
|
||||
|
||||
const chooseCouponData = reactive({
|
||||
couponId: "",
|
||||
show: false,
|
||||
index: -1,
|
||||
item: null,
|
||||
});
|
||||
const modelValue = defineModel({
|
||||
default: "",
|
||||
});
|
||||
|
||||
const couponName = computed(() => {
|
||||
if (modelValue.value) {
|
||||
const item = couponList.value.find((item) => item.id === modelValue.value);
|
||||
return item?.title || "";
|
||||
}
|
||||
return "";
|
||||
});
|
||||
const couponList = ref([]);
|
||||
function showCoupon(item, index) {
|
||||
chooseCouponData.couponId = modelValue.value;
|
||||
chooseCouponData.show = true;
|
||||
}
|
||||
function confirmCoupon(e) {
|
||||
modelValue.value=e.id
|
||||
}
|
||||
function removeCoupon(index) {
|
||||
modelValue.value.splice(index, 1);
|
||||
}
|
||||
onMounted(() => {
|
||||
chatCoupon({ size: 999 }).then((res) => {
|
||||
couponList.value = res.records;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.choose-coupon {
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
}
|
||||
</style>
|
||||
@@ -1,108 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view @click="open">
|
||||
<slot v-if="$slots.default"> </slot>
|
||||
<view v-else class="choose-goods u-flex u-row-between">
|
||||
<text class="color-999" v-if="!startTime && !endTime"
|
||||
>请选择日期范围</text
|
||||
>
|
||||
<text class="color-333 u-font-24 u-m-r-32 " v-else
|
||||
>{{ startTime }} - {{ endTime }}</text
|
||||
>
|
||||
<view class="u-flex" v-if="startTime&&endTime" @click.stop="clear">
|
||||
<up-icon name="close" size="14"></up-icon>
|
||||
</view>
|
||||
<up-icon size="14" name="arrow-right" v-else ></up-icon>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<my-date-pickerview
|
||||
@confirm="datePickerConfirm"
|
||||
mode="all"
|
||||
ref="datePicker"
|
||||
></my-date-pickerview>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const datePicker = ref(null);
|
||||
const startTime = defineModel("startTime", {
|
||||
default: () => "",
|
||||
type: String,
|
||||
});
|
||||
const endTime = defineModel("endTime", {
|
||||
default: () => "",
|
||||
type: String,
|
||||
});
|
||||
|
||||
function clear(){
|
||||
startTime.value = "";
|
||||
endTime.value = "";
|
||||
}
|
||||
function open() {
|
||||
datePicker.value.toggle();
|
||||
}
|
||||
function datePickerConfirm(e) {
|
||||
startTime.value = e.start;
|
||||
endTime.value = e.end;
|
||||
console.log(e);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.popup-content {
|
||||
background: #fff;
|
||||
width: 640rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.top {
|
||||
padding: 40rpx 48rpx;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
.bottom {
|
||||
padding: 48rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
gap: 50rpx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 32rpx;
|
||||
border: 2rpx solid transparent;
|
||||
&.success {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.cancel {
|
||||
border-color: #d9d9d9;
|
||||
box-shadow: 0 4rpx 0 0 #00000005;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
padding: 10rpx 30rpx;
|
||||
border: 1px solid #d9d9d9;
|
||||
margin: 10rpx;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s ease-in-out;
|
||||
box-shadow: 0 0 10px transparent;
|
||||
&.selected {
|
||||
border-color: $my-main-color;
|
||||
box-shadow: 0 0 10px $my-main-color;
|
||||
}
|
||||
}
|
||||
.choose-goods {
|
||||
display: flex;
|
||||
padding: 24rpx;
|
||||
align-items: center;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
background: #fff;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
min-height: 90rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-popup :show="show" mode="center">
|
||||
<view class="popup-content">
|
||||
<view class="top u-flex u-row-between">
|
||||
<text class="font-bold u-font-32 color-333">{{ title }}</text>
|
||||
<up-icon size="18" name="close" @click="close"></up-icon>
|
||||
</view>
|
||||
<up-line></up-line>
|
||||
<scroll-view style="max-height: 50vh" :scroll-y="true">
|
||||
<slot></slot>
|
||||
</scroll-view>
|
||||
<up-line></up-line>
|
||||
|
||||
<view class="bottom">
|
||||
<view class="btn cancel" @click="close">{{ cancelText }}</view>
|
||||
<view class="btn success" @click="confirm">{{ confirmText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "标题",
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: "保存",
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: "取消",
|
||||
},
|
||||
});
|
||||
const show = defineModel({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
});
|
||||
const emits = defineEmits(["close", "confirm"]);
|
||||
function close() {
|
||||
show.value = false;
|
||||
emits("close");
|
||||
}
|
||||
function confirm() {
|
||||
emits("confirm");
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.popup-content {
|
||||
background: #fff;
|
||||
width: 640rpx;
|
||||
border-radius: 18rpx;
|
||||
}
|
||||
.top {
|
||||
padding: 40rpx 48rpx;
|
||||
}
|
||||
.bottom {
|
||||
padding: 48rpx 52rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 50rpx;
|
||||
.btn {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 32rpx;
|
||||
border: 2rpx solid transparent;
|
||||
white-space: nowrap;
|
||||
&.success {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.cancel {
|
||||
border-color: #d9d9d9;
|
||||
box-shadow: 0 4rpx 0 0 #00000005;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,49 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<up-action-sheet
|
||||
:round="14"
|
||||
:actions="list"
|
||||
:title="title"
|
||||
:show="show"
|
||||
closeOnClickAction
|
||||
cancelText="取消"
|
||||
@close="close"
|
||||
@select="sheetSelect"
|
||||
></up-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup >
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { getShopList } from "@/http/api/shop.js";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: "请选择",
|
||||
},
|
||||
});
|
||||
const list = ref([]);
|
||||
const show=defineModel({
|
||||
name: "show",
|
||||
default: false,
|
||||
})
|
||||
function close() {
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
const emit=defineEmits(["choose"]);
|
||||
function sheetSelect(e) {
|
||||
console.log(e);
|
||||
emit("choose", e);
|
||||
}
|
||||
onMounted(() => {
|
||||
getShopList().then((res) => {
|
||||
list.value = res.map((v) => ({
|
||||
...v,
|
||||
value: v.shopId,
|
||||
name: v.shopName,
|
||||
}));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,230 +0,0 @@
|
||||
<template>
|
||||
<view class="min-page bg-f7 u-font-28 color-333 u-p-t-32">
|
||||
<view class="bg-fff">
|
||||
<view class="default-box u-flex u-row-between border-bottom">
|
||||
<text class="font-bold">优惠券名称</text>
|
||||
<text>{{ couponActivity.couponJson.couponName }}</text>
|
||||
</view>
|
||||
<view class="default-box u-flex u-row-between border-bottom">
|
||||
<text class="font-bold">发放数量</text>
|
||||
<text>{{ couponActivity.giveNum }}</text>
|
||||
</view>
|
||||
<view class="default-box u-flex u-row-between border-bottom">
|
||||
<text class="font-bold">已领取数量</text>
|
||||
<text>{{ couponActivity.giveNum - couponActivity.leftNum }}</text>
|
||||
</view>
|
||||
<view class="default-box u-flex u-row-between border-bottom">
|
||||
<text class="font-bold">剩余数量</text>
|
||||
<text>{{ couponActivity.leftNum }}</text>
|
||||
</view>
|
||||
<view class="default-box u-flex u-row-between border-bottom">
|
||||
<text class="font-bold">已使用数量</text>
|
||||
<text>{{ couponActivity.useNum }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="u-flex u-row-right default-box u-p-r-32 bg-fff">
|
||||
<up-select
|
||||
:options="statusOptions"
|
||||
@select="selectItem"
|
||||
labelName="label"
|
||||
>
|
||||
<template #text>
|
||||
<view class="select">
|
||||
<text v-if="selStatus">{{ selStatus.label }}</text>
|
||||
<text v-else class="color-999">请选择状态</text>
|
||||
<up-icon name="arrow-down"></up-icon>
|
||||
</view>
|
||||
</template>
|
||||
<template #icon> <view></view></template>
|
||||
</up-select>
|
||||
</view>
|
||||
|
||||
<view class="u-m-t-32 table bg-fff">
|
||||
<view class="header">
|
||||
<view class="user">用户</view>
|
||||
<view class="gettime">领取时间</view>
|
||||
<view class="usetime">使用时间</view>
|
||||
<view class="status">状态</view>
|
||||
<view class="operation">操作</view>
|
||||
</view>
|
||||
<view class="body">
|
||||
<view class="item" v-for="(item, index) in list" :key="index">
|
||||
<view class="user">
|
||||
<view>
|
||||
{{ item.nickName }}
|
||||
</view>
|
||||
<view> ({{ item.shopUserId }}) </view>
|
||||
</view>
|
||||
<view class="gettime">{{ item.createTime }}</view>
|
||||
<view class="usetime">{{ item.useTime }}</view>
|
||||
<view class="status">{{ returnStatus(item.status) }}</view>
|
||||
<view class="operation status3">
|
||||
<text v-if="item.status == 0" @click="deleteRecord(item)"
|
||||
>失效</text
|
||||
></view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-loadmore :status="isEnd ? 'nomore' : 'loading'"></up-loadmore>
|
||||
<view style="height: 40px"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onReachBottom, onLoad } from "@dcloudio/uni-app";
|
||||
import { reactive, ref, watch } from "vue";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import go from "@/commons/utils/go.js";
|
||||
import * as chatCouponApi from "@/http/api/market/chat";
|
||||
|
||||
function deleteRecord(item) {
|
||||
uni
|
||||
.showModal({
|
||||
title: "提示",
|
||||
content: "确定要让该记录失效吗?",
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.confirm) {
|
||||
chatCouponApi
|
||||
.deleteRecord({
|
||||
id: item.id,
|
||||
})
|
||||
.then((res) => {
|
||||
uni.showToast({
|
||||
title: "操作成功",
|
||||
icon: "none",
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
refresh();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const statusOptions = ref([
|
||||
{ label: "全部", value: "" },
|
||||
{ label: "未使用", value: 0 },
|
||||
{ label: "已使用", value: 1 },
|
||||
{ label: "已过期", value: 2 },
|
||||
]);
|
||||
function returnStatus(status) {
|
||||
if (status == 0) {
|
||||
return "未使用";
|
||||
}
|
||||
if (status == 1) {
|
||||
return "已使用";
|
||||
}
|
||||
if (status == 2) {
|
||||
return "已过期";
|
||||
}
|
||||
}
|
||||
const selStatus = ref("");
|
||||
const query = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
status: "",
|
||||
});
|
||||
const options = reactive({
|
||||
id: "",
|
||||
});
|
||||
|
||||
function selectItem(item) {
|
||||
selStatus.value = item;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => selStatus.value,
|
||||
(newVal, oldVal) => {
|
||||
query.status = newVal.value;
|
||||
refresh();
|
||||
}
|
||||
);
|
||||
|
||||
function refresh() {
|
||||
query.page = 1;
|
||||
isEnd.value = false;
|
||||
getList();
|
||||
}
|
||||
|
||||
const couponActivity = ref({});
|
||||
|
||||
const list = ref([]);
|
||||
const isEnd = ref(false);
|
||||
function getList() {
|
||||
chatCouponApi.chatCouponRecord({ ...query, id: options.id }).then((res) => {
|
||||
if (query.page == 1) {
|
||||
list.value = res.records;
|
||||
} else {
|
||||
list.value.push(...res.records);
|
||||
}
|
||||
isEnd.value = query.page >= res.totalPage * 1;
|
||||
});
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
if (!isEnd.value) {
|
||||
query.page++;
|
||||
getList();
|
||||
}
|
||||
});
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt);
|
||||
const item = uni.getStorageSync("cach_couponActivity");
|
||||
couponActivity.value = item || {};
|
||||
console.log(item);
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.default-box {
|
||||
padding: 24rpx 28rpx;
|
||||
}
|
||||
.select {
|
||||
padding: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
min-width: 322rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.table {
|
||||
.user {
|
||||
width: 142rpx;
|
||||
}
|
||||
.gettime {
|
||||
width: 172rpx;
|
||||
}
|
||||
.usetime {
|
||||
width: 158rpx;
|
||||
}
|
||||
.status {
|
||||
width: 84rpx;
|
||||
}
|
||||
.operation {
|
||||
width: 56rpx;
|
||||
&.status3 {
|
||||
color: #ff383c;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx 16rpx;
|
||||
color: #666;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
.body {
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 16rpx;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,312 +0,0 @@
|
||||
<template>
|
||||
<view class="min-page bg-f7">
|
||||
<up-sticky>
|
||||
<view class="top">
|
||||
<my-tabs
|
||||
:list="tabs.list"
|
||||
v-model="tabs.selIndex"
|
||||
@change="tabsChange"
|
||||
textKey="label"
|
||||
></my-tabs>
|
||||
</view>
|
||||
</up-sticky>
|
||||
|
||||
<view class="list">
|
||||
<view class="item" v-for="(item, index) in list" :key="index">
|
||||
<view class="u-flex u-row-between">
|
||||
<view>{{ item.couponJson.couponName }}</view>
|
||||
|
||||
<view class="u-flex">
|
||||
<view class="status" :class="['status' + item.status]">{{
|
||||
returnStateText(item)
|
||||
}}</view>
|
||||
<view class="Id">ID:{{ item.id }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-28 desc">
|
||||
<view class="u-flex">
|
||||
<text class="color-666 text-right u-m-r-48" style="min-width: 96rpx"
|
||||
>使用门槛</text
|
||||
>
|
||||
<text class="color-333"
|
||||
>满{{ item.couponJson.fullAmount }}元可用</text
|
||||
>
|
||||
</view>
|
||||
<view class="u-flex u-m-t-16">
|
||||
<text class="color-666 text-right u-m-r-48" style="min-width: 96rpx"
|
||||
>有效期</text
|
||||
>
|
||||
<text class="color-333"
|
||||
>领券后{{ item.couponJson.validDays }}天过期</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex u-row-between u-m-t-24">
|
||||
<view
|
||||
class="u-flex u-flex-col u-row-center u-font-24 u-col-center text-center"
|
||||
>
|
||||
<view class="color-333 font-bold">{{ item.giveNum }}</view>
|
||||
<view class="color-666 u-m-t-16">发放数量</view>
|
||||
</view>
|
||||
<view
|
||||
class="u-flex u-flex-col u-row-center u-font-24 u-col-center text-center"
|
||||
>
|
||||
<view class="color-333 font-bold">{{
|
||||
item.giveNum - item.leftNum
|
||||
}}</view>
|
||||
<view class="color-666 u-m-t-16">已领取</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="u-flex u-flex-col u-row-center u-font-24 u-col-center text-center"
|
||||
>
|
||||
<view class="color-333 font-bold">{{ item.leftNum }}</view>
|
||||
<view class="color-666 u-m-t-16">剩余</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="u-flex u-flex-col u-row-center u-font-24 u-col-center text-center"
|
||||
>
|
||||
<view class="color-333 font-bold">{{ item.useNum }}</view>
|
||||
<view class="color-666 u-m-t-16">已使用</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-t-16 u-flex u-row-right" style="gap: 16rpx">
|
||||
<view
|
||||
class="btn share"
|
||||
@click="toShare(item)"
|
||||
v-if="item.status == 1"
|
||||
>
|
||||
分享</view
|
||||
>
|
||||
<view class="btn cancel" @click="cancel(item)">失效</view>
|
||||
<view class="btn primary" @click="toDetail(item)"> 查看</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<up-loadmore :status="isEnd ? 'nomore' : 'loading'"></up-loadmore>
|
||||
<view style="height: 40px"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as chatApi from "@/http/php/chat";
|
||||
|
||||
import { onReachBottom, onLoad } from "@dcloudio/uni-app";
|
||||
import { reactive, ref, watch } from "vue";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import go from "@/commons/utils/go.js";
|
||||
import * as chatCouponApi from "@/http/api/market/chat";
|
||||
|
||||
import { useChatStore } from "@/store/chat";
|
||||
|
||||
const chatStore = useChatStore();
|
||||
chatStore.onReceiveMsg = (msg) => {};
|
||||
chatStore.connectSocket();
|
||||
|
||||
function toDetail(item) {
|
||||
uni.setStorageSync("cach_couponActivity", item);
|
||||
go.to("PAGES_CHAT_COUPON_ACTIVITY_DETAIL", {
|
||||
id: item.id,
|
||||
});
|
||||
}
|
||||
const tabs = reactive({
|
||||
list: [
|
||||
{
|
||||
label: "全部",
|
||||
value: "",
|
||||
},
|
||||
{
|
||||
label: "发放中",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
label: "已失效",
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
selIndex: 0,
|
||||
});
|
||||
|
||||
const query = reactive({
|
||||
page: 1,
|
||||
size: 10,
|
||||
});
|
||||
function cancelChatCoupon(item) {
|
||||
chatCouponApi.chatCouponExpired(item.id).then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "操作成功",
|
||||
icon: "none",
|
||||
});
|
||||
refresh();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "取消失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sendMsg(msg) {
|
||||
chatStore.sendMessage({
|
||||
to_id: groupInfo.value.id,
|
||||
to_user_type: groupInfo.value.id,
|
||||
chat_type: 2,
|
||||
content: msg.value,
|
||||
image_url: "",
|
||||
order_id: "",
|
||||
session_id: options.session_id,
|
||||
...msg,
|
||||
});
|
||||
}
|
||||
function toShare(item) {
|
||||
const hasGet=item.couponJson.giveNum-item.couponJson.leftNum
|
||||
sendMsg({
|
||||
coupon: { ...item.couponJson, title: item.title,activity_id:item.id, hasGet:hasGet<=0?0:hasGet} ,
|
||||
chat_coupon_id:item.id,
|
||||
msg_type: 4,
|
||||
});
|
||||
|
||||
uni.navigateBack({
|
||||
delta: 2,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const options = reactive({});
|
||||
const groupInfo = ref({});
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt);
|
||||
chatApi
|
||||
.groupInfo({
|
||||
group_id: options.group_id,
|
||||
})
|
||||
.then((res) => {
|
||||
groupInfo.value = res || {};
|
||||
});
|
||||
});
|
||||
function cancel(item) {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定取消该优惠券吗?",
|
||||
confirmText: "确定",
|
||||
cancelText: "取消",
|
||||
success: function (res) {
|
||||
if (res.confirm) {
|
||||
cancelChatCoupon(item);
|
||||
} else if (res.cancel) {
|
||||
console.log("用户点击取消");
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
function returnStateText(item) {
|
||||
if (item.status == 1) {
|
||||
return "发放中";
|
||||
} else if (item.status == 3) {
|
||||
return "已失效";
|
||||
}
|
||||
}
|
||||
function tabsChange(e) {
|
||||
tabs.selIndex = e;
|
||||
refresh();
|
||||
}
|
||||
function refresh() {
|
||||
query.page = 1;
|
||||
isEnd.value = false;
|
||||
init();
|
||||
}
|
||||
const list = ref([]);
|
||||
|
||||
const isEnd = ref(false);
|
||||
function init() {
|
||||
chatCouponApi
|
||||
.chatCouponPage({ ...query, status: tabs.list[tabs.selIndex].value })
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
const arr = (res.records || []).map((v) => {
|
||||
return {
|
||||
...v,
|
||||
couponJson: JSON.parse(v.couponJson),
|
||||
};
|
||||
});
|
||||
if (query.page == 1) {
|
||||
list.value = arr;
|
||||
} else {
|
||||
list.value.push(...arr);
|
||||
}
|
||||
console.log(list.value);
|
||||
isEnd.value = query.page >= res.totalPage * 1;
|
||||
});
|
||||
}
|
||||
onReachBottom(() => {
|
||||
if (!isEnd.value) {
|
||||
query.page++;
|
||||
init();
|
||||
}
|
||||
});
|
||||
onShow(init);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.top {
|
||||
padding: 20rpx 62rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.list {
|
||||
padding: 32rpx 28rpx;
|
||||
.item {
|
||||
padding: 32rpx;
|
||||
background-color: #fff;
|
||||
margin-bottom: 28rpx;
|
||||
.desc {
|
||||
padding: 32rpx 28rpx;
|
||||
background: #f8f8f8;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.status {
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
&.status1 {
|
||||
color: rgba(52, 199, 89, 1);
|
||||
background-color: rgba(52, 199, 89, 0.15);
|
||||
}
|
||||
&.status3 {
|
||||
color: #999999;
|
||||
background-color: rgba(153, 153, 153, 0.15);
|
||||
}
|
||||
}
|
||||
.Id {
|
||||
padding: 8rpx 6rpx;
|
||||
margin-left: 36rpx;
|
||||
font-size: 18rpx;
|
||||
color: #999;
|
||||
border-radius: 4rpx;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
padding: 8rpx 42rpx;
|
||||
border-radius: 100rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
&.cancel {
|
||||
background-color: #f8f8f8;
|
||||
color: #999999;
|
||||
}
|
||||
&.primary {
|
||||
background-color: $my-main-color;
|
||||
color: #fff;
|
||||
}
|
||||
&.share {
|
||||
background-color: #ecf5ff;
|
||||
color: $my-main-color;
|
||||
border: 1px solid $my-main-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,250 +0,0 @@
|
||||
<template>
|
||||
<view class="min-page bg-f7 u-font-28">
|
||||
<view class="user-list bg-fff">
|
||||
<view class="u-flex u-row-between u-col-center">
|
||||
<text class="color-000">群成员({{ allUser.length }}人)</text>
|
||||
<text class="color-red" @click="showRemove = !showRemove">移除</text>
|
||||
</view>
|
||||
<view class="list u-m-t-26">
|
||||
<view
|
||||
class="u-flex u-flex-col u-row-center u-col-center relative"
|
||||
v-for="(item, index) in userLists"
|
||||
:key="index"
|
||||
>
|
||||
<up-avatar
|
||||
size="104rpx"
|
||||
shape="square"
|
||||
:src="item.avatar"
|
||||
round="8rpx"
|
||||
></up-avatar>
|
||||
<view class="u-m-t-8 color-000 u-line-1" style="max-width: 104rpx">{{
|
||||
item.nick_name
|
||||
}}</view>
|
||||
<view
|
||||
class="remove u-absolute"
|
||||
v-if="showRemove && item.role != 1"
|
||||
@click="removeMember(item)"
|
||||
>
|
||||
<up-icon
|
||||
name="minus-circle-fill"
|
||||
size="24rpx"
|
||||
color="#FF2424"
|
||||
></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex u-row-center color-666 u-m-t-30" v-if="hasMore">
|
||||
<view class="u-flex" @click="loadMore">
|
||||
<text class="u-m-r-20">查看更多</text>
|
||||
<up-icon name="arrow-down" size="24rpx" color="#666"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom">
|
||||
<view
|
||||
class="u-flex u-row-between default-padding bg-fff border-bottom"
|
||||
@click="toEditTitle"
|
||||
>
|
||||
<text>群聊名称</text>
|
||||
<view class="u-flex color-666">
|
||||
<text>{{ groupInfo.name }}</text>
|
||||
<up-icon name="arrow-right" size="24rpx" color="#666"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex u-row-between default-padding bg-fff border-bottom">
|
||||
<view>
|
||||
<view>禁言</view>
|
||||
<view class="color-999 u-font-24">
|
||||
开启后,顾客将不能在群内发消息</view
|
||||
>
|
||||
</view>
|
||||
<up-switch
|
||||
v-model="groupInfo.is_mute"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="groupMuteChange"
|
||||
></up-switch>
|
||||
</view>
|
||||
<view
|
||||
class="u-flex u-row-between default-padding bg-fff"
|
||||
@click="
|
||||
go.to('PAGES_CHAT_COUPON_ACTIVITY', {
|
||||
group_id: options.group_id,
|
||||
session_id: options.session_id,
|
||||
})
|
||||
"
|
||||
>
|
||||
<text>优惠券领取记录</text>
|
||||
<view class="u-flex color-666">
|
||||
<text class="color-main">去查看</text>
|
||||
<up-icon name="arrow-right" size="24rpx" color="#318AFE"></up-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<Modal v-model="modalData.show" title="修改群名称" @confirm="modalConfirm">
|
||||
<view class="u-p-40">
|
||||
<view class="font-bold u-m-b-16">群名称</view>
|
||||
<up-input
|
||||
v-model="modalData.form.title"
|
||||
placeholder="请输入群名称"
|
||||
maxlength="20"
|
||||
></up-input>
|
||||
</view>
|
||||
</Modal>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import go from "@/commons/utils/go.js";
|
||||
import * as chatApi from "@/http/php/chat";
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import { reactive, toRefs, computed, watch, onMounted, ref } from "vue";
|
||||
import Modal from "@/pageChat/components/modal.vue";
|
||||
const options = reactive({});
|
||||
const groupInfo = ref({});
|
||||
const modalData = reactive({
|
||||
show: false,
|
||||
form: {
|
||||
title: "",
|
||||
},
|
||||
key: "editTitle",
|
||||
});
|
||||
|
||||
function toEditTitle() {
|
||||
modalData.show = true;
|
||||
modalData.form.title = groupInfo.value.name || "";
|
||||
}
|
||||
|
||||
function modalConfirm(e) {
|
||||
if (modalData.key == "editTitle") {
|
||||
if (!modalData.form.title.trim().length) {
|
||||
uni.showToast({
|
||||
title: "请输入群名称",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
chatApi
|
||||
.groupEditTitle({
|
||||
group_id: options.group_id,
|
||||
title: modalData.form.title,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
groupInfo.value.name = modalData.form.title;
|
||||
modalData.show = false;
|
||||
uni.showToast({
|
||||
title: "修改成功",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getGroupInfo() {
|
||||
chatApi
|
||||
.groupInfo({
|
||||
group_id: options.group_id,
|
||||
})
|
||||
.then((res) => {
|
||||
groupInfo.value = res || {};
|
||||
});
|
||||
}
|
||||
onLoad((opt) => {
|
||||
Object.assign(options, opt);
|
||||
getGroupInfo();
|
||||
});
|
||||
function groupMuteChange(e) {
|
||||
if (e) {
|
||||
chatApi
|
||||
.groupMute({
|
||||
group_id: options.group_id,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "已禁言",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
chatApi
|
||||
.groupMunute({
|
||||
group_id: options.group_id,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "禁言已取消",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const showRemove = ref(false);
|
||||
let allUser = ref([]);
|
||||
const userLists = ref([]);
|
||||
const hasMore = ref(false);
|
||||
function getMembers() {
|
||||
chatApi.groupMembers({ group_id: options.group_id }).then((res) => {
|
||||
allUser.value = res.user_list || [];
|
||||
hasMore.value = allUser.value.length > 20;
|
||||
userLists.value = allUser.value.slice(0, 20);
|
||||
});
|
||||
}
|
||||
|
||||
function loadMore() {
|
||||
userLists.value = allUser.value;
|
||||
}
|
||||
onShow(() => {
|
||||
getMembers();
|
||||
});
|
||||
|
||||
function removeMember(item) {
|
||||
chatApi
|
||||
.groupKick({ group_id: options.group_id, target_uid: item.user_id })
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "移除成功",
|
||||
icon: "none",
|
||||
});
|
||||
setTimeout(() => {
|
||||
getMembers();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.user-list {
|
||||
padding: 32rpx 28rpx;
|
||||
.list {
|
||||
gap: 20rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
}
|
||||
}
|
||||
.color-red {
|
||||
color: #ff2424;
|
||||
}
|
||||
.bottom {
|
||||
margin: 28rpx;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.default-padding {
|
||||
padding: 32rpx 28rpx;
|
||||
}
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
.remove {
|
||||
top: -6rpx;
|
||||
right: -6rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,303 +0,0 @@
|
||||
<template>
|
||||
<view class="min-page bg-f7 color-333 u-font-28">
|
||||
<up-sticky>
|
||||
<view class="top u-flex u-row-between u-col-center">
|
||||
<view style="width: 420rpx">
|
||||
<up-search
|
||||
v-model="query.key"
|
||||
placeholder="搜索群名称"
|
||||
:showAction="false"
|
||||
@clear="throttleSearch"
|
||||
@change="throttleSearch"
|
||||
></up-search>
|
||||
</view>
|
||||
<view class="u-flex u-col-center" @click="clearAllmsg">
|
||||
<text class="color-666 u-m-r-12">清空未读</text>
|
||||
<image src="/pageChat/static/clear.png" class="clear"></image>
|
||||
</view>
|
||||
</view>
|
||||
</up-sticky>
|
||||
<view class="list">
|
||||
<up-swipe-action>
|
||||
<template v-for="(item, index) in list" :key="item.id">
|
||||
<up-swipe-action-item
|
||||
:options="options1"
|
||||
v-model:show="item.showOptions"
|
||||
@click="optionsClick($event, item, index)"
|
||||
>
|
||||
<view class="item u-flex" @click="toDetail(item)">
|
||||
<view class="u-flex avatar">
|
||||
<up-avatar
|
||||
size="118rpx"
|
||||
:src="item.avatar"
|
||||
shape="square"
|
||||
round="8rpx"
|
||||
></up-avatar>
|
||||
<view class="bandage" v-if="item.unread_count > 0">{{
|
||||
item.unread_count >= 99 ? "99" : item.unread_count
|
||||
}}</view>
|
||||
</view>
|
||||
<view class="u-flex-1 u-flex u-row-between u-p-l-14">
|
||||
<view style="max-width: 364rpx">
|
||||
<view class="color-000 u-line-1">{{ item.name }}</view>
|
||||
<view class="u-m-t-28 u-line-1 u-font-24 color-999">{{
|
||||
item.msg
|
||||
}}</view>
|
||||
</view>
|
||||
<view class="color-333 u-font-24">{{ item.send_time }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</up-swipe-action-item>
|
||||
<view style="height: 16rpx" class="bg-f7"></view>
|
||||
</template>
|
||||
</up-swipe-action>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import * as chatApi from "@/http/php/chat";
|
||||
import { ref, reactive, onMounted, onUnmounted } from "vue";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import { useChatStore } from "@/store/chat";
|
||||
import dayjs from "dayjs";
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const originalOnReceiveMsg = chatStore.onReceiveMsg;
|
||||
|
||||
// 定义消息回调函数
|
||||
const handleReceiveMsg = (msg) => {
|
||||
// 先执行原始回调(如果有)
|
||||
if (typeof originalOnReceiveMsg === "function") {
|
||||
originalOnReceiveMsg(msg);
|
||||
}
|
||||
|
||||
if (msg.operate_type == "receive_msg" && msg.chat_type == 2) {
|
||||
const index = allList.value.findIndex((v) => v.group_id == msg.group_id);
|
||||
if (index != -1) {
|
||||
allList.value[index].unread_count += 1;
|
||||
allList.value[index].msg = returnMsg(msg);
|
||||
allList.value[index].send_time = msg.send_time;
|
||||
allList.value[index].send_time_origin = msg.send_time_origin;
|
||||
allList.value = listSort(allList.value);
|
||||
}
|
||||
const index1 = list.value.findIndex((v) => v.group_id == msg.group_id);
|
||||
if (index1 != -1) {
|
||||
list.value[index1].unread_count += 1;
|
||||
list.value[index1].msg = returnMsg(msg);
|
||||
list.value[index1].send_time = msg.send_time;
|
||||
list.value[index1].send_time_origin = msg.send_time_origin;
|
||||
list.value = listSort(list.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
chatStore.registerReceiveMsgCallback(handleReceiveMsg);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 移除消息回调,避免内存泄漏
|
||||
chatStore.removeReceiveMsgCallback(handleReceiveMsg);
|
||||
});
|
||||
|
||||
function returnMsg(msg) {
|
||||
if (msg.msg_type == 1) {
|
||||
return msg.nick + ":" + msg.content;
|
||||
}
|
||||
if (msg.msg_type == 2) {
|
||||
return msg.nick + ":" + "[图片]";
|
||||
}
|
||||
if (msg.msg_type == 5) {
|
||||
return msg.nick + ":" + "[视频]";
|
||||
}
|
||||
if (msg.msg_type == 4) {
|
||||
return msg.nick + ":" + "[优惠券]";
|
||||
}
|
||||
}
|
||||
chatStore.connectSocket();
|
||||
|
||||
// 使用 reactive 创建响应式对象
|
||||
const options1 = reactive([
|
||||
{
|
||||
text: "删除",
|
||||
style: {
|
||||
backgroundColor: "#f56c6c",
|
||||
color: "#fff",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
function optionsClick(e, item, index) {
|
||||
if (e.index == 0) {
|
||||
//删除
|
||||
|
||||
chatApi
|
||||
.sessionlistdel({
|
||||
session_id: item.session_id,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "删除成功",
|
||||
icon: "none",
|
||||
duration: 1000,
|
||||
});
|
||||
list.value.splice(index, 1);
|
||||
setTimeout(() => {
|
||||
getList();
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const list = ref([]);
|
||||
let allList = ref([]);
|
||||
|
||||
const query = reactive({
|
||||
key: "",
|
||||
});
|
||||
|
||||
function throttle(fn, delay) {
|
||||
let timer = null;
|
||||
return function (...args) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(this, args);
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
//使用节流函数
|
||||
const throttleSearch = throttle(search, 500);
|
||||
function search() {
|
||||
const arr = allList.value
|
||||
.filter((v) => v.name.includes(query.key.trim()))
|
||||
.map((v) => {
|
||||
return {
|
||||
...v,
|
||||
showOptions: false,
|
||||
};
|
||||
});
|
||||
list.value = listSort(arr);
|
||||
}
|
||||
|
||||
function listSort(arr) {
|
||||
return arr.sort((a, b) => {
|
||||
return dayjs(b.send_time_origin).unix() - dayjs(a.send_time_origin).unix();
|
||||
});
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
const res = await chatApi.messageSessionList({});
|
||||
const arr = (res.list || []).filter((v) => !v.is_del);
|
||||
allList.value = listSort(arr);
|
||||
|
||||
search();
|
||||
}
|
||||
|
||||
async function clearAllmsg() {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "确定要清空所有未读消息吗?",
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
const res = await chatApi.messageMarkReadAll({
|
||||
session_ids: list.value.map((v) => v.group_id).join(","),
|
||||
});
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: "清空成功",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
getList();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function toDetail(item) {
|
||||
if (!item.is_th) {
|
||||
return uni.showToast({
|
||||
title: "你已不在该群内",
|
||||
icon: "none",
|
||||
duration: 1500,
|
||||
});
|
||||
}
|
||||
uni.navigateTo({
|
||||
url:
|
||||
"/pageChat/chat" +
|
||||
`?group_id=${item.group_id}&session_id=${item.session_id}`,
|
||||
});
|
||||
}
|
||||
|
||||
const messageUnreadCount = ref(0);
|
||||
onShow(() => {
|
||||
getList();
|
||||
// 检查连接状态,确保连接活跃
|
||||
if (!chatStore.isConnect || !chatStore.socketTask) {
|
||||
console.log("列表页显示,检查Socket连接");
|
||||
chatStore.forceReconnect();
|
||||
} else {
|
||||
chatStore.shop_id = "";
|
||||
chatStore.init();
|
||||
}
|
||||
|
||||
// 获取未读消息总数
|
||||
chatApi.messageUnreadCount({}).then((res) => {
|
||||
console.log(res);
|
||||
messageUnreadCount.value = res.total;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.top {
|
||||
padding: 32rpx 28rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.clear {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
.list {
|
||||
padding: 36rpx 28rpx;
|
||||
|
||||
.item {
|
||||
padding: 32rpx 28rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
.avatar {
|
||||
position: relative;
|
||||
.bandage {
|
||||
position: absolute;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
background: #ff1c1c;
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
text-align: center;
|
||||
line-height: 38rpx;
|
||||
right: -10rpx;
|
||||
top: -10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.u-swipe-action-item__content) {
|
||||
background-color: transparent;
|
||||
}
|
||||
:deep(.u-swipe-action-item) {
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.6 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user