新增团购页面,优化考勤数据日期传参

This commit is contained in:
gyq
2025-12-03 10:43:57 +08:00
parent 3d6d3850b2
commit d49e755506
13 changed files with 2161 additions and 250 deletions

278
src/api/coup/group.js Normal file
View File

@@ -0,0 +1,278 @@
import request from "@/utils/request.js";
import request_php from "@/utils/request-php.js";
/**
* 团购卷订单列表(分页)
* @param {*} data
* @returns
*/
export function searchstorestatus(type) {
return request_php({
method: "post",
headers: {
clint_type: type
},
url: "/meituan/searchstorestatus"
});
}
/**
* 团购卷订单列表(分页)
* @param {*} data
* @returns
*/
export function groupOrderlist(data) {
return request({
method: "post",
url: "/groupOrder/list",
data,
});
}
/**
* 团购卷核销前回显
* @param {*} params
* @returns
*/
export function groupOrderorderInfo(params) {
return request({
method: "get",
url: "/groupOrder/orderInfo",
params,
});
}
/**
* 团购卷核销(仅核销待使用订单)
* @param {*} params
* @returns
*/
export function groupOrdergroupScan(params) {
return request({
method: "get",
url: "/groupOrder/groupScan",
params,
});
}
/**
* 退单
* @param {*} data
* @returns
*/
export function returnGpOrder(data) {
return request({
method: "post",
url: "/pay/returnGpOrder",
data,
});
}
// 注意 抖音核销使用的请求为PHP服务 request_php
/**
* 获取uisdk 绑定 链接
* @param {*} data
* @returns
*/
export function getuisdk(data) {
return request_php({
method: "post",
headers: {
clint_type: 2
},
url: "/douyin/getuisdk",
data,
});
}
/**
* 会员签入
* @param {*} data
* @returns
*/
export function douyincheckIn(data) {
return request_php({
method: "post",
url: "douyin/checkIn",
data,
});
}
/**
* 团购核销准备
* @param {*} data
* @returns
*/
export function douyinfulfilmentcertificateprepare(data) {
return request_php({
method: "post",
url: "douyin/fulfilmentcertificateprepare",
data,
});
}
/**
* 团购核销
* @param {*} data
* @returns
*/
export function douyincertificateprepare(data) {
return request_php({
method: "post",
url: "douyin/certificateprepare",
data,
});
}
/**
* 团购核销记录
* @param {*} data
* @returns
*/
export function douyinorderlist(data) {
return request_php({
method: "post",
url: "douyin/orderlist",
data,
});
}
/**
* 团购核销撤销
* @param {*} data
* @returns
*/
export function douyinfulfilmentcertificatecancel(data) {
return request_php({
method: "post",
url: "douyin/fulfilmentcertificatecancel",
data,
});
}
/**
* 门店列表
* @param {*} data
* @returns
*/
export function douyinstorelist(data) {
return request_php({
method: "post",
url: "douyin/storelist",
data,
});
}
/**
* 绑定门店
* @param {*} data
* @returns
*/
export function douyinbindstore(data) {
return request_php({
method: "post",
url: "douyin/bindstore",
data,
});
}
/**
* 登出团购
* @param {*} data
* @returns
*/
export function tglogout(data) {
return request_php({
method: "post",
url: "user/logout",
data,
});
}
/**
* 美团团购核销
* 绑定-获取绑定状态
* @param {*} data
* @returns
*/
export function thirdPartyCoupon_state(data) {
return request_php({
method: "post",
url: "/meituan/searchstorestatus",
data,
});
}
/**
* 美团团购核销
* 绑定-获取绑定url
* @param {*} data
* @returns
*/
export function thirdPartyCoupon_bindUrl(data) {
return request_php({
method: "post",
headers: {
clint_type: 1
},
url: "/meituan/getuisdkurl",
data,
});
}
/**
* 美团团购核销
* 团购券-获取可用券
* @param {*} data
* @returns
*/
export function thirdPartyCoupon_list(data) {
return request_php({
method: "post",
url: "/meituan/fulfilmentcertificateprepare",
data,
});
}
/**
* 美团团购核销
* 执行核销
* @param {*} data
* @returns
*/
export function certificateprepare(data) {
return request_php({
method: "post",
url: "/meituan/certificateprepare",
data,
});
}
/**
* 美团团购核销
* 团购核销记录
* @param {*} data
* @returns
*/
export function meituan_orderlist(data) {
return request_php({
method: "post",
url: "/meituan/orderlist",
data,
});
}
/**
* 美团团购核销
* 团购撤销
* @param {*} data
* @returns
*/
export function meituan_fulfilmentcertificatecancel(data) {
return request_php({
method: "post",
url: "/meituan/fulfilmentcertificatecancel",
data,
});
}

BIN
src/assets/icon_scan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -51,6 +51,11 @@
import { ref } from 'vue'
import { attendanceDetail } from '@/api/coupon/index'
const props = defineProps({
startTime: '',
endTime: ''
})
const visible = ref(false)
const detail = ref({
@@ -79,7 +84,9 @@ async function attendanceDetailAjax() {
try {
loading.value = true
const res = await attendanceDetail({
userId: row.value.userId
userId: row.value.userId,
startTime: props.startTime,
endTime: props.endTime
})
detail.value = res
} catch (error) {

View File

@@ -42,7 +42,7 @@
</div> -->
</div>
<settingDialog ref="settingDialogRef" @success="searchHandle" />
<detailDialog ref="detailDialogRef" />
<detailDialog :startTime="queryForm.startTime" :endTime="queryForm.endTime" ref="detailDialogRef" />
</div>
</template>

View File

@@ -12,6 +12,229 @@ export const userTypes = [
value: "vip",
},
];
// 新版菜单
export const newMenus = [
{
name: '顾客中心',
intro: '以顾客为核心统一管理',
childrenList: [
{
name: "超级会员",
icon: "cjhy",
pathName: "superVip",
intro: "用户会员管理设置"
},
]
},
{
name: '拉新拓客',
intro: '协助商家拉来新客户,拓展客户群体',
childrenList: [
{
name: "分销",
icon: "zhcz",
pathName: "distribution_page",
intro: "用户成为业务员,可促进消费"
},
{
name: "套餐推广",
icon: "tctg",
pathName: "",
intro: "下单通过用户邀请好友减免金额的方式裂变宣传套餐加购",
},
{
name: "新客立减",
icon: "xklj",
pathName: "newUserDiscount",
intro: "首单下单减免金额"
},
{
name: "商品拼团",
icon: "sppt",
pathName: "",
intro: "拼团"
},
]
},
{
name: '拉高客单价',
intro: '提高每一位顾客单次购买的金额',
childrenList: [
{
name: "满减活动",
icon: "mjhd", pathName: "discount_activity",
intro: "达到指定支付金额享受减价"
},
{
name: "点餐智能推荐",
icon: "dczntj",
pathName: "order_recommendation",
intro: "进入点单页X秒未点自动推荐商品此推荐设置启用即生效",
},
{
name: "限时折扣",
icon: "xszk",
pathName: "discount_limit",
intro: "批量设置商品折扣"
},
{
name: "弹窗广告",
icon: "tcgg",
pathName: "",
intro: "设置弹窗广告"
},
]
},
{
name: '提升复购率',
intro: '提升客户再次购买的概率和频次',
childrenList: [
{
name: "积分锁客",
icon: "jfsk",
pathName: "points",
intro: "设置充值消费的N倍当前订单立即免单",
},
{
name: "消费返现",
icon: "xffx",
pathName: "cashback",
intro: "用户下单后返现一定的金额到余额,可促进复购",
},
{
name: "消费赠券",
icon: "xfzq",
pathName: "consume_ticket",
intro: "达到指定消费金额赠送优惠券",
},
{
name: "私域引流",
icon: "syyl",
pathName: "drainage",
intro: "可设置用户下单成功后的群二维码",
},
{
name: "生日有礼",
icon: "sryl",
pathName: "birthdayGift",
intro: "用户生日管理设置"
},
{
name: "推送活动消息",
icon: "tshdxx",
pathName: "",
intro: "给用户推送服务通知"
}
]
},
{
name: '增加现金流',
intro: '增加商家特定时期内实际可支配的现金流入',
childrenList: [
{
name: "霸王餐",
icon: "bwc",
pathName: "king_dine",
intro: "设置充值消费的N倍当前订单立即免单",
},
{
name: "智慧充值",
icon: "zhcz",
pathName: "wisdom_recharge",
intro: "允许客户充值并使用余额支付",
},
{
name: "充值兑换码",
icon: "czdhm",
pathName: "recharge_exchange",
intro: "兑换码直充余额,可当作礼品赠送",
},
{
name: "券兑换码",
icon: "qdhm",
pathName: "coupon_exchange_code",
intro: "可添加多券组合兑换"
},
]
},
{
name: '优惠券体系',
intro: '完整且系统化的优惠体系',
childrenList: [
{
name: "折扣券",
icon: "zkq",
pathName: "rebate_coupon",
intro: "下单享折扣但折扣的金额将在券中抵扣。",
},
{
name: "满减券",
icon: "mjq",
pathName: "discount_coupon",
intro:
"用户满足指定金额后可使用优惠券立减相应金额设置满100-50券符合要求的订单满100元后立减50元。",
},
{
name: "商品兑换券",
icon: "spdhq",
pathName: "product_redemption",
intro: "设置可兑换成商品的券",
},
{
name: "买一送一券",
icon: "myzy",
pathName: "buy_one",
intro: "针对营销活动买一送一设置券品",
},
{
name: "第二件半价券",
icon: "dejbjq",
pathName: "half_price",
intro: "设置第二件半价券",
},
{
name: "免配送费券",
icon: "mfpsq",
pathName: "",
intro: "可设置一张免除订单配送费的券",
},
{
name: "固定价格券",
icon: "gdjkq",
pathName: "",
intro:
"设置该券后允许用户以固定价格兑换指定商品设置一个固定价格9.9的券商品20元用户使用券后只需要9.9元兑换该商品。",
},
{
name: "超值券包",
icon: "czqb",
pathName: "",
intro: "下单加购"
},
]
},
{
name: '消息推送功能',
intro: '推送商家/平台优惠活动消息的方式',
childrenList: [
{
name: "短信推送",
icon: "dxts",
pathName: "note_push",
intro: "给用户推送服务通知"
},
{
name: "微信公众号",
icon: "wxgzh",
pathName: "official_accounts",
intro:
"授权微信公众号后,让你能够在后台查看和维护公众号的粉丝;同时你的店铺也有出现关注公众号的入口。",
},
]
}
]
export const returnUserType = (type) => {
return userTypes.find((item) => item.value === type)?.label;
};

View File

@@ -15,7 +15,7 @@
</div>
</div>
</div>
<div class="children_wrap" :class="{ active: childrenShow }">
<!-- <div class="children_wrap" :class="{ active: childrenShow }">
<div class="close" @click="childrenShow = false">
<el-icon size="24" color="#333">
<CircleClose />
@@ -37,7 +37,7 @@
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
</template>
@@ -46,6 +46,7 @@
import { ref } from 'vue'
import defaultIcon from "@/assets/logo.png";
import { ElMessage } from "element-plus";
import { newMenus } from './data.js'
const iconSize = ref({
width: '55px',
@@ -53,233 +54,16 @@ const iconSize = ref({
})
function showChildrenHandle(index) {
menusActive.value = index
childrenShow.value = true
// menusActive.value = index
// childrenShow.value = true
router.push({
name: 'marketing_children_page',
query: {
index: index
}
})
}
const childrenShow = ref(false)
const menusActive = ref(0)
const newMenus = ref([
{
name: '顾客中心',
intro: '以顾客为核心统一管理',
childrenList: [
{
name: "超级会员",
icon: "cjhy",
pathName: "superVip",
intro: "用户会员管理设置"
},
]
},
{
name: '拉新拓客',
intro: '协助商家拉来新客户,拓展客户群体',
childrenList: [
{
name: "分销",
icon: "zhcz",
pathName: "distribution_page",
intro: "用户成为业务员,可促进消费"
},
{
name: "套餐推广",
icon: "tctg",
pathName: "",
intro: "下单通过用户邀请好友减免金额的方式裂变宣传套餐加购",
},
{
name: "新客立减",
icon: "xklj",
pathName: "newUserDiscount",
intro: "首单下单减免金额"
},
{
name: "商品拼团",
icon: "sppt",
pathName: "",
intro: "拼团"
},
]
},
{
name: '拉高客单价',
intro: '提高每一位顾客单次购买的金额',
childrenList: [
{
name: "满减活动",
icon: "mjhd", pathName: "discount_activity",
intro: "达到指定支付金额享受减价"
},
{
name: "点餐智能推荐",
icon: "dczntj",
pathName: "order_recommendation",
intro: "进入点单页X秒未点自动推荐商品此推荐设置启用即生效",
},
{
name: "限时折扣",
icon: "xszk",
pathName: "discount_limit",
intro: "批量设置商品折扣"
},
{
name: "弹窗广告",
icon: "tcgg",
pathName: "",
intro: "设置弹窗广告"
},
]
},
{
name: '提升复购率',
intro: '提升客户再次购买的概率和频次',
childrenList: [
{
name: "积分锁客",
icon: "jfsk",
pathName: "points",
intro: "设置充值消费的N倍当前订单立即免单",
},
{
name: "消费返现",
icon: "xffx",
pathName: "cashback",
intro: "用户下单后返现一定的金额到余额,可促进复购",
},
{
name: "消费赠券",
icon: "xfzq",
pathName: "consume_ticket",
intro: "达到指定消费金额赠送优惠券",
},
{
name: "私域引流",
icon: "syyl",
pathName: "drainage",
intro: "可设置用户下单成功后的群二维码",
},
{
name: "生日有礼",
icon: "sryl",
pathName: "birthdayGift",
intro: "用户生日管理设置"
},
{
name: "推送活动消息",
icon: "tshdxx",
pathName: "",
intro: "给用户推送服务通知"
}
]
},
{
name: '增加现金流',
intro: '增加商家特定时期内实际可支配的现金流入',
childrenList: [
{
name: "霸王餐",
icon: "bwc",
pathName: "king_dine",
intro: "设置充值消费的N倍当前订单立即免单",
},
{
name: "智慧充值",
icon: "zhcz",
pathName: "wisdom_recharge",
intro: "允许客户充值并使用余额支付",
},
{
name: "充值兑换码",
icon: "czdhm",
pathName: "recharge_exchange",
intro: "兑换码直充余额,可当作礼品赠送",
},
{
name: "券兑换码",
icon: "qdhm",
pathName: "coupon_exchange_code",
intro: "可添加多券组合兑换"
},
]
},
{
name: '优惠券体系',
intro: '完整且系统化的优惠体系',
childrenList: [
{
name: "折扣券",
icon: "zkq",
pathName: "rebate_coupon",
intro: "下单享折扣但折扣的金额将在券中抵扣。",
},
{
name: "满减券",
icon: "mjq",
pathName: "discount_coupon",
intro:
"用户满足指定金额后可使用优惠券立减相应金额设置满100-50券符合要求的订单满100元后立减50元。",
},
{
name: "商品兑换券",
icon: "spdhq",
pathName: "product_redemption",
intro: "设置可兑换成商品的券",
},
{
name: "买一送一券",
icon: "myzy",
pathName: "buy_one",
intro: "针对营销活动买一送一设置券品",
},
{
name: "第二件半价券",
icon: "dejbjq",
pathName: "half_price",
intro: "设置第二件半价券",
},
{
name: "免配送费券",
icon: "mfpsq",
pathName: "",
intro: "可设置一张免除订单配送费的券",
},
{
name: "固定价格券",
icon: "gdjkq",
pathName: "",
intro:
"设置该券后允许用户以固定价格兑换指定商品设置一个固定价格9.9的券商品20元用户使用券后只需要9.9元兑换该商品。",
},
{
name: "超值券包",
icon: "czqb",
pathName: "",
intro: "下单加购"
},
]
},
{
name: '消息推送功能',
intro: '推送商家/平台优惠活动消息的方式',
childrenList: [
{
name: "短信推送",
icon: "dxts",
pathName: "note_push",
intro: "给用户推送服务通知"
},
{
name: "微信公众号",
icon: "wxgzh",
pathName: "official_accounts",
intro:
"授权微信公众号后,让你能够在后台查看和维护公众号的粉丝;同时你的店铺也有出现关注公众号的入口。",
},
]
}
])
const router = useRouter();
const to = (item) => {
if (!item.pathName) {

View File

@@ -0,0 +1,182 @@
<template>
<div class="app-container">
<div class="card">
<div class="row">
<div class="title">
{{ newMenus[menusActive].name }}
</div>
<div class="menus_wrap">
<div class="item" v-for="(val, index) in newMenus[menusActive].childrenList" :key="index" @click="to(val)">
<img :src="getIconPath(val.icon)" class="icon" @error="handleImageError(val)" />
<div class="info">
<div class="name">{{ val.name }}</div>
<div class="intro">
{{ val.intro }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { newMenus } from './data.js'
const menusActive = ref(0)
const route = useRoute()
const router = useRouter();
const to = (item) => {
if (!item.pathName) {
ElMessage.warning("暂未开放");
return;
}
router.push({
name: item.pathName,
});
};
// 动态获取PNG图标路径
const getIconPath = (iconName) => {
try {
// 直接导入对应PNG文件
return new URL(`/src/assets/applocation/${iconName}.png`, import.meta.url).href;
} catch (error) {
console.warn(`图标 ${iconName}.png 不存在`);
return defaultIcon; // 图标不存在时使用默认图标
}
};
// 动态获取PNG图标路径
const getIconPathNew = (iconName) => {
try {
// 直接导入对应PNG文件
return new URL(`/src/assets/marketing/${iconName}.png`, import.meta.url).href;
} catch (error) {
console.warn(`图标 ${iconName}.png 不存在`);
return defaultIcon; // 图标不存在时使用默认图标
}
};
// 处理图片加载失败
const handleImageError = (item) => {
console.error(`图标 ${item.icon}.png 加载失败`);
};
onMounted(() => {
menusActive.value = +route.query.index
})
</script>
<style scoped lang="scss">
.app-container {
padding: 14px;
.card {
height: 81vh;
overflow-y: auto;
padding: 14px;
background-color: #fff;
border-radius: 10px;
position: relative;
overflow: hidden;
.children_wrap {
width: 100%;
height: 81vh;
position: absolute;
top: 0;
left: 0;
z-index: 99;
background-color: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(20px);
padding: 14px;
border-radius: 10px;
transition: all .3s ease-in-out;
transform: translateY(200%);
&.active {
transform: translateY(0);
}
.close {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 10px;
right: 10px;
&:hover {
cursor: pointer;
}
}
}
.row {
&:not(:first-child) {
padding-bottom: 14px;
}
.title {
font-size: 16px;
}
.menus_wrap {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
margin-top: 14px;
.item {
display: flex;
align-items: center;
padding: 10px;
background-color: #f8f8f8;
border-radius: 4px;
transition: all 0.1s ease-in-out;
&:hover {
cursor: pointer;
background-color: #d5ebff;
}
.icon {
width: 48px;
height: 48px;
margin-right: 10px;
}
.info {
padding-left: 10px;
.name {
font-size: 14px;
}
.intro {
margin-top: 4px;
font-size: 14px;
color: #666;
line-height: 1.4em;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
line-clamp: 1;
-webkit-box-orient: vertical;
word-break: break-all;
white-space: normal;
}
}
}
}
}
}
}
</style>

View File

@@ -112,7 +112,7 @@
</template>
<script>
import { tbGroupOrderInfo, returnGpOrder } from "@/api/order";
// import { tbGroupOrderInfo, returnGpOrder } from "@/api/coup/index";
import dayjs from "dayjs";
export default {
data() {
@@ -203,8 +203,8 @@ export default {
}
},
mounted() {
this.getTableData();
this.resetQuery = { ...this.query };
// this.getTableData();
// this.resetQuery = { ...this.query };
},
methods: {
// 提交退单

View File

@@ -0,0 +1,104 @@
<template>
<el-dialog title="绑定门店" v-model="showDialog" width="80%">
<div class="dialog">
<div class="tips">注意门店绑定后无法更改请谨慎选择</div>
<el-table :data="tableData.list" height="240px" border v-loading="tableData.loading">
<el-table-column label="门店名称" prop="poi_name"></el-table-column>
<el-table-column label="门店地址" prop="address"></el-table-column>
<el-table-column label="操作" width="120px">
<template v-slot="scope">
<el-button type="primary" size="small"
@click="bindShopHandle(scope.row.poi_id)">选择门店</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination @current-change="paginationChange" :current-page="tableData.page"
:page-size="tableData.size" layout="total, prev, pager, next, jumper" :total="tableData.total"
background>
</el-pagination>
</div>
</div>
</el-dialog>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import { onMounted, reactive, ref } from 'vue';
import { douyinstorelist, douyinbindstore } from '@/api/coup/group'
const emits = defineEmits(['success'])
const showDialog = ref(false)
const tableData = reactive({
page: 1,
size: 10,
total: 0,
loading: false,
list: []
})
// 绑定门店
async function bindShopHandle(poi_id) {
try {
await douyinbindstore({
poi_id: poi_id
})
showDialog.value = false
ElMessage.success('绑定成功')
emits('success')
} catch (error) {
console.log(error);
}
}
// 分页变化
function paginationChange(e) {
tableData.page = e
getTableData()
}
// 获取门店列表
async function getTableData() {
try {
tableData.loading = true
const { list, count } = await douyinstorelist({
page: tableData.page,
size: tableData.size
})
tableData.loading = false
tableData.list = list
tableData.total = count
} catch (error) {
console.log(error);
}
}
// 显示
function show() {
showDialog.value = true;
getTableData()
}
defineExpose({
show
})
</script>
<style scoped lang="scss">
.tips {
color: var(--el-color-danger);
padding-bottom: 14px;
}
.pagination {
display: flex;
padding: 0 14px;
margin-top: 14px;
}
.dialog {
padding: 14px;
}
</style>

View File

@@ -0,0 +1,111 @@
<template>
<el-dialog title="退款" v-model="showDialog" width="400px" @close="reset">
<el-form ref="refundFormRef" :model="refundForm" :rules="refundFormRules" label-position="top">
<el-form-item label="退单数" prop="num">
<el-select v-model="refundForm.num" placeholder="请选择退单数" style="width: 100%;" @change="refundNumChange">
<el-option :label="item" :value="item" v-for="item in refundNumList" :key="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="退单金额">
<el-input v-model="refundForm.refundAmount" disabled placeholder="请选择退单数"></el-input>
</el-form-item>
<el-form-item label="退款原因">
<el-input v-model="refundForm.refundReason" type="textarea" placeholder="请输入退款原因"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="showDialog = false" style="width: 100%;">取消</el-button>
<el-button type="primary" :loading="refundLoading" @click="refundConfirm" style="width: 100%;">
</el-button>
</span>
</el-dialog>
</template>
<script setup>
import { returnGpOrder } from '@/api/coup/group'
import { ref, reactive } from 'vue'
import { ElMessage } from "element-plus";
const emits = defineEmits(["success"]);
const newRow = ref('')
const showDialog = ref(false)
const refundLoading = ref(false)
const refundFormRef = ref(null)
const refundForm = reactive({
num: '',
orderId: '',
refundAmount: '',
refundDesc: '',
refundReason: ''
})
const refundFormRules = reactive({
num: [
{
required: true,
message: ' ',
trigger: 'change'
}
]
})
const refundNumList = ref([])
// 提交退单
function refundConfirm() {
refundFormRef.value.validate(async valid => {
if (valid) {
try {
refundLoading.value = true
const res = await returnGpOrder(refundForm)
ElMessage.success('退单成功')
refundLoading.value = false
showDialog.value = false
emits('succcess')
} catch (error) {
console.log(error);
}
refundLoading.value = false
}
})
}
// 计算退单金额
function refundNumChange(e) {
refundForm.refundAmount = Math.floor(newRow.value.orderAmount / newRow.value.number * e * 100) / 100
}
// 显示
function show(row) {
showDialog.value = true;
newRow.value = row
let arr = []
for (let i = 1; i <= row.number - row.refundNumber; i++) {
arr.push(i)
}
refundNumList.value = arr
refundForm.orderId = row.id
}
// 初始化
function reset() {
newRow.value = ''
refundNumList.value = []
refundForm.orderId = ''
for (let key in refundForm) {
refundForm[key] = ''
}
refundFormRef.value.resetFields()
}
defineExpose({
show
});
</script>
<style scoped lang="scss">
.dialog-footer {
display: flex;
}
</style>

View File

@@ -0,0 +1,514 @@
<!-- 扫码弹窗 -->
<template>
<div class="dialog">
<el-dialog :title="`核销${props.title}团购券`" width="600" v-model="dialogVisible" @open="reset" @close="close">
<div class="content">
<div class="left">
<el-image :src="icon" style="width: 60px; height: 60px"></el-image>
</div>
<div class="right" v-if="!userPayWait">
<div class="amount">
<span class="t">扫码核销</span>
<!-- <span class="n">{{ props.amount }}</span> -->
</div>
<div class="input">
<el-input ref="inputRef" v-model="scanCode"
style="height: calc(var(--el-component-size-large) + 30px)" placeholder="请扫描团购券" clearable
@change="inputChange"></el-input>
<div class="tips">注意扫码支付请保证输入框获得焦点输入内容结束后会自动核销请勿重复操作</div>
</div>
<!-- <div class="number_warp">
<div class="item" v-for="item in 9" :key="item" @click="inputHandle(item)">{{ item }}</div>
<div class="item disabled">.</div>
<div class="item" @click="inputHandle(0)">0</div>
<div class="item" @click="delHandle">
<el-icon>
<CloseBold />
</el-icon>
</div>
</div> -->
<div class="btn">
<el-button type="primary" style="width: 100%" v-loading="loading">立即核销</el-button>
</div>
</div>
<div class="pay_wait" v-else>
<div class="loading" v-loading="loading" element-loading-text="用户支付中..."></div>
<div class="btn">
<el-button type="primary" style="width: 100%" v-loading="checkPayStatusLoading"
@click="checkPayStauts">
<span v-if="!checkPayStatusLoading">查询用户支付状态</span>
<span v-else>查询中...</span>
</el-button>
</div>
<div class="btn">
<el-button style="width: 100%" @click="resetScanCode">
重新扫码
</el-button>
</div>
</div>
</div>
</el-dialog>
<el-dialog title="团购券详情" width="600" v-model="detailVisible">
<div class="group_detil">
<div class="shop_info" v-if="props.type == 1">
<el-image :src="groupDetail.images[0]" style="width: 50px;height: 50px;"></el-image>
<div class="info">
<div class="name">{{ groupDetail.productName }}</div>
<div class="price">
<span class="p">{{ groupDetail.salePrice }}</span>
<span class="o">{{ groupDetail.originPrice }}</span>
</div>
</div>
</div>
<div class="table">
<el-table :data="groupDetail.productList" border v-if="props.type == 1">
<el-table-column label="名称" prop="title"></el-table-column>
<el-table-column label="数量" prop="number"></el-table-column>
<el-table-column label="商品信息">
<template v-slot="scope">
<div class="shop_list">
<div class="item" v-for="(item, index) in scope.row.goods" :key="item.id">
<span class="dot"></span>
<div class="name">
<div class="t">{{ item.name }}</div>
<div class="t">x{{ item.groupNum }}</div>
</div>
</div>
</div>
</template>
</el-table-column>
</el-table>
<el-table ref="douyin_table" :data="groupDetail.goods" border v-else>
<el-table-column type="selection" width="55" />
<el-table-column label="名称" prop="title"></el-table-column>
<el-table-column label="价格" prop="amount"></el-table-column>
</el-table>
</div>
</div>
<div class="footer">
<el-button style="width: 100%;" @click="detailVisible = false">取消</el-button>
<el-button type="primary" style="width: 100%;" :loading="groupDetailLoading"
@click="groupOrdergroupScanHandle">确认核销</el-button>
</div>
</el-dialog>
<BindShop ref="BindShopRef" @success="submitHandle()" />
</div>
</template>
<script setup>
import _ from "lodash";
import { ref } from "vue";
import icon from "@/assets/icon_scan.png";
import { groupOrderorderInfo, groupOrdergroupScan, douyinfulfilmentcertificateprepare, douyincertificateprepare, thirdPartyCoupon_list, certificateprepare } from '@/api/coup/group'
import { useUserStore } from "@/store";
import BindShop from './bindShop.vue'
const BindShopRef = ref(null)
const store = useUserStore();
import { ElMessage } from "element-plus";
const emits = defineEmits(["success"]);
const props = defineProps({
title: {
type: String,
default: ''
},
type: {
type: Number,
default: 1
}
});
const dialogVisible = ref(false);
const scanCode = ref("");
const inputRef = ref(null);
const loading = ref(false);
const userPayWait = ref(false);
const checkPayStatusLoading = ref(false);
const fastOrder = ref('')
const groupDetailLoading = ref(false)
const groupDetail = ref({})
const detailVisible = ref(false)
// 团购卷核销(仅核销待使用订单)
async function groupOrdergroupScanHandle() {
try {
switch (props.type) {
case 1:
{
groupDetailLoading.value = true
const res = await groupOrdergroupScan({
id: groupDetail.value.id
})
}
break;
case 2:
{
let encrypted_codes = douyin_table.value.getSelectionRows()
if (encrypted_codes.length) {
groupDetailLoading.value = true
let arr = encrypted_codes.map(item => item.encrypted_code)
console.log(encrypted_codes);
const res = await douyincertificateprepare({
verify_token: groupDetail.value.verify_token,
encrypted_codes: arr.join(','),
id: groupDetail.value.id
})
} else {
ElMessage.error('请选择核销项目')
return
}
}
break;
case 3:
// 美团团购
{
let encrypted_codes = douyin_table.value.getSelectionRows()
if (encrypted_codes.length) {
groupDetailLoading.value = true
let arr = encrypted_codes.map(item => item.encrypted_code)
const res = await certificateprepare({
couponCode: groupDetail.value.couponCode,
num: encrypted_codes.length
})
} else {
ElMessage.error('请选择核销项目')
return
}
}
break
default:
break;
}
groupDetailLoading.value = false
detailVisible.value = false
scanCode.value = ''
inputRef.value.focus();
ElMessage.success('核销成功')
emits('succcess')
} catch (error) {
console.log('groupOrdergroupScanHandle.error', error);
}
groupDetailLoading.value = false
}
const douyin_table = ref(null)
// 核销券码
async function submitHandle() {
try {
loading.value = true
switch (props.type) {
case 1:
{
const res = await groupOrderorderInfo({
coupon: scanCode.value,
});
loading.value = false
groupDetail.value = res
detailVisible.value = true
}
break;
case 2:
{
const res = await douyinfulfilmentcertificateprepare({
object_id: decodeURI(scanCode.value),
});
dialogVisible.value = false
loading.value = false
groupDetail.value = res
detailVisible.value = true
setTimeout(() => {
groupDetail.value.goods.map(item => {
douyin_table.value.toggleRowSelection(item)
})
}, 100)
}
break;
case 3:
{
const res = await thirdPartyCoupon_list({
shopId: store.userInfo.id,
code: scanCode.value
});
dialogVisible.value = false
loading.value = false
groupDetail.value = res
detailVisible.value = true
setTimeout(() => {
groupDetail.value.goods.map(item => {
douyin_table.value.toggleRowSelection(item)
})
}, 100)
}
break;
default:
break;
}
} catch (error) {
console.log('submitHandle.error', error);
if (error.code == 4399) {
BindShopRef.value.show()
}
}
loading.value = false
}
// 重新扫码
function resetScanCode() {
userPayWait.value = false;
loading.value = false;
scanCode.value = "";
inputRef.value.focus();
}
// 输入
function inputHandle(n) {
scanCode.value += n;
inputRef.value.focus();
}
// 删除
function delHandle() {
if (!scanCode.value) return;
scanCode.value = scanCode.value.substring(0, scanCode.value.length - 1);
inputRef.value.focus();
}
// 监听扫码枪回车事件
// function enterHandle() {
// inputRef.value.focus()
// }
const inputChange = _.debounce(function (e) {
// console.log(e);
if (scanCode.value) {
submitHandle();
}
}, 500);
function show() {
dialogVisible.value = true;
setTimeout(() => {
inputRef.value.focus();
}, 500);
}
function close() {
dialogVisible.value = false;
}
function reset() {
loading.value = false;
scanCode.value = "";
}
defineExpose({
show,
close,
loading,
submitHandle
});
</script>
<style scoped lang="scss">
.footer {
display: flex;
padding: 0 14px 14px;
}
.group_detil {
padding: 14px;
.shop_info {
display: flex;
.info {
flex: 1;
padding-left: 10px;
.name {
font-size: 18px;
font-weight: bold;
color: #000;
}
.price {
.p {
font-size: 20px;
font-weight: bold;
color: red;
}
.o {
color: #999;
text-decoration: line-through;
margin-left: 10px;
}
}
}
}
.table {
padding-top: 14px;
}
.shop_list {
.item {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: 6px;
}
.dot {
$size: 6px;
width: $size;
height: $size;
border-radius: 50%;
background-color: #1890FF;
}
.name {
flex: 1;
display: flex;
margin-left: 10px;
align-items: center;
.t {
color: #333;
font-size: 14px;
width: 100px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 10px;
}
}
.del {
font-size: 14px;
color: #999;
&:hover {
cursor: pointer;
color: #555;
}
}
}
}
}
.tips {
padding-top: 10px;
color: #999;
}
.dialog :deep(.el-dialog__body) {
padding: 0 !important;
}
.content {
display: flex;
.left {
width: 200px;
display: flex;
align-items: center;
justify-content: center;
background-color: #efefef;
}
.right {
flex: 1;
padding: var(--el-font-size-base);
.amount {
display: flex;
height: calc(var(--el-component-size-large) + 20px);
display: flex;
align-items: center;
justify-content: space-between;
color: var(--primary-color);
background-color: #555;
border-radius: 6px;
padding: 0 var(--el-font-size-base);
font-size: calc(var(--el-font-size-base) + 10px);
}
.input {
padding: var(--el-font-size-base) 0;
:deep(.el-input__inner) {
font-size: calc(var(--el-font-size-base) + 10px);
}
}
.number_warp {
--h: 50px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: var(--h) var(--h) var(--h) var(--h);
gap: 8px;
.item {
background-color: #dddddd;
display: flex;
align-items: center;
justify-content: center;
font-size: calc(var(--el-font-size-base) + 10px);
border-radius: 4px;
&.disabled {
color: #999;
background-color: #efefef;
&:active {
background-color: #efefef;
}
}
&:active {
background-color: #b9b9b9;
}
}
}
// .btn {
// padding-top: 20px;
// }
}
.pay_wait {
flex: 1;
padding: 0 var(--el-font-size-base);
height: 400px;
padding-bottom: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.loading {
width: 200px;
height: 200px;
--el-loading-spinner-size: 100px;
:deep(.el-loading-text) {
font-size: 20px;
}
}
.btn {
width: 200px;
padding-top: var(--el-font-size-base);
}
}
}
</style>

View File

@@ -1,3 +1,669 @@
<template>
<view>团购设置</view>
<div class="content">
<div class="cart_wrap card">
<div class="top_btns">
<el-button size="large" @click="changeKey(index)" v-for="(item, index) in pays" :key="index">
<img :src="item.icon" alt="" style="width: 30px; height: 30px; margin-right: 10px" />
<span>
{{ item.text }}{{ item.status ? '已绑定' : '未绑定' }}
</span>
</el-button>
</div>
<div class="header">
<div class="left">
<el-select v-model="tableData.type" placeholder="核销类型" @change="typeChange">
<el-option v-for="item in typeList" :key="item.value" :value="item.value" :label="item.label"></el-option>
</el-select>
<el-input placeholder="搜索订单" v-model="tableData.proName"></el-input>
<el-select v-model="tableData.status" placeholder="订单状态">
<el-option v-for="item in statusList" :key="item.value" :value="item.value" :label="item.label"></el-option>
</el-select>
<div class="btn">
<el-button type="primary" :icon="Search" @click="groupOrderlistAjax">搜索</el-button>
<el-button :icon="RefreshRight" :loading="tableData.resetLoading" @click="resetHandle">重置</el-button>
</div>
</div>
<!-- <el-button type="warning" :icon="FullScreen" @click="showScanModalHandle">核销团购券</el-button> -->
</div>
<div class="tab_container">
<el-table :data="tableData.list" height="540px" v-loading="tableData.loading" v-if="tableData.type == 1">
<el-table-column label="订单号" prop="orderNo" width="100px"></el-table-column>
<el-table-column label="优惠卷" prop="proImg" width="200px">
<template v-slot="scope">
<div class="info_wrap">
<el-image :src="scope.row.proImg" style="width: 40px;height: 40px;flex-shrink: 0;" />
<div class="t">{{ scope.row.proName }}</div>
</div>
</template>
</el-table-column>
<!-- <el-table-column label="支付方式" prop="payType">
<template v-slot="scope">
{{ payTypeFilter(scope.row.payType) }}
</template>
</el-table-column> -->
<el-table-column label="订单金额" prop="orderAmount">
<template v-slot="scope">
{{ scope.row.orderAmount }}
</template>
</el-table-column>
<el-table-column label="实付金额" prop="payAmount">
<template v-slot="scope">
{{ scope.row.payAmount }}
</template>
</el-table-column>
<el-table-column label="下单数量" prop="number">
<template v-slot="scope">
{{ scope.row.number }}
</template>
</el-table-column>
<el-table-column label="状态" prop="status">
<template v-slot="scope">
{{ statusFilter(scope.row.status) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right">
<template v-slot="scope">
<el-button type="primary" size="small" v-if="scope.row.refundAble == 1 && scope.row.status == 'unused'"
@click="refundDialogRef.show(scope.row)">退款</el-button>
<el-button type="primary" size="small" disabled v-else>退款</el-button>
</template>
</el-table-column>
</el-table>
<el-table :data="tableData.list" height="540px" v-loading="tableData.loading" v-if="tableData.type == 2">
<el-table-column label="抖音订单号" prop="d_order_id" width="240"></el-table-column>
<el-table-column label="总金额" prop="pay_amount">
<template v-slot="scope">
<span style="color: var(--primary-color);">{{ scope.row.pay_amount }}</span>
</template>
</el-table-column>
<el-table-column label="商品信息" prop="douyinCodeGoods">
<template v-slot="scope">
<div class="goods_list">
<div class="row" v-for="item in scope.row.douyinCodeGoods" :key="item.id">
<div class="item" style="width: 240px;">
{{ item.title }}
</div>
<div class="item" style="width: 100px;color: var(--primary-color);">
{{ item.pay_amount }}
</div>
<div class="item" style="margin-right: 10px;display: flex;justify-content: flex-end;">
<el-tag :type="typeStatus(item.status)" disable-transitions size="default" effect="light" round>
{{ item.status_text }}
</el-tag>
</div>
<div class="item" style="flex: 1;display: flex;justify-content: flex-end;">
<el-button type="danger" size="small" v-if="item.is_show_cacel_banner"
@click="cacelDouyinHandle(item)">撤销</el-button>
</div>
</div>
</div>
</template>
</el-table-column>
</el-table>
<el-table height="540px" :data="tableData.list" v-loading="tableData.loading" v-if="tableData.type == 3">
<el-table-column label="名称" prop="dealTitle"></el-table-column>
<el-table-column label="总金额" prop="couponBuyPrice" width="100">
<template v-slot="scope">
<span style="color: var(--primary-color);">{{ scope.row.couponBuyPrice }}</span>
</template>
</el-table-column>
<el-table-column label="状态" prop="couponStatusDesc" width="150"></el-table-column>
<el-table-column label="使用时间" prop="couponUseTime" width="200"></el-table-column>
<el-table-column label="操作" prop="douyinCodeGoods" width="100">
<template v-slot="scope">
<el-button type="danger" size="small" @click="cacelMeittuanHandle(scope.row)">
撤销
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="pagination">
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.size"
layout="total, prev, pager, next" :total="tableData.total" background @current-change="paginationChange"
@size-change="paginationChange">
</el-pagination>
</div>
</div>
<scanGroup ref="scanGroupRef" :title="typeList.find(item => item.value == tableData.type).label"
:type="tableData.type" @succcess="groupOrderlistAjax" />
<refundDialog ref="refundDialogRef" @success="groupOrderlistAjax" />
<el-dialog v-model="showMeituanUrlModal" title="注意">
<span style="font-size: 18px;">您的店铺还未绑定美团请绑定后操作</span>
<template #footer>
<div class="dialog-footer" style="padding: 0 15px 15px;">
<el-button @click="showMeituanUrlModal = false">取消</el-button>
<el-button type="primary" @click="openMeituan">
去绑定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { groupOrderlist, douyinorderlist, douyinfulfilmentcertificatecancel, thirdPartyCoupon_state, thirdPartyCoupon_bindUrl, meituan_orderlist, meituan_fulfilmentcertificatecancel, searchstorestatus, getuisdk } from '@/api/coup/group'
import { Search, RefreshRight, FullScreen } from '@element-plus/icons-vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import { ref, onMounted, reactive } from 'vue'
import scanGroup from './components/scanGroup.vue'
import refundDialog from './components/refundDialog.vue'
import { useUserStore } from "@/store"
import meituanIcon from "@/assets/icons/meituan.png";
import tiktokIcon from "@/assets/icons/douyin.png";
const paysSel = ref(0)
const pays = ref([
{
text: "美团",
clint_type: 1,
status: 0,
icon: meituanIcon,
},
{
text: "抖音",
clint_type: 2,
status: 0,
icon: tiktokIcon,
},
])
// 查询抖音/美团绑定的状态
async function searchstorestatusAjax() {
try {
const { mt_status, dy_status } = await searchstorestatus(pays.value[paysSel.value].clint_type)
pays.value.forEach(item => {
if (item.clint_type == 1) {
item.status = mt_status
}
if (item.clint_type == 2) {
item.status = dy_status
}
})
} catch (error) {
console.log(error);
}
}
// 切换状态
async function changeKey(index) {
try {
paysSel.value = index
if (pays.value[paysSel.value].clint_type == 1 && pays.value[paysSel.value].status == 0) {
// 如果没有绑定,先提示用户去绑定
const res = await thirdPartyCoupon_bindUrl()
ElMessageBox.confirm('您的店铺还未绑定美团,请绑定后操作!', '注意', {
confirmButtonText: '去绑定'
}).then(() => {
window.open(res)
}).catch(() => { })
}
if (pays.value[paysSel.value].clint_type == 2 && pays.value[paysSel.value].status == 0) {
// 如果没有抖音,先提示用户去绑定
const res = await getuisdk()
ElMessageBox.confirm('您的店铺还未绑定抖音,请绑定后操作!', '注意', {
confirmButtonText: '去绑定'
}).then(() => {
window.open(res)
}).catch(() => { })
}
} catch (error) {
console.log(error);
}
}
const store = useUserStore()
const scanGroupRef = ref(null)
const refundDialogRef = ref(null)
function typeStatus(t) {
const m = {
0: 'warning',
1: 'success',
2: 'danger'
}
return m[t]
}
const tableData = reactive({
resetLoading: false,
proName: '',
type: 3,
status: '',
loading: false,
list: [],
page: 1,
size: 10,
total: 0
})
// 支付方式类型
function payTypeFilter(t) {
const m = {
wechatPay: '微信支付',
aliPay: '支付宝支付'
}
return m[t]
}
// 订单类型
const typeList = reactive([
// {
// value: 1,
// label: '自营'
// },
{
value: 2,
label: '抖音'
},
{
value: 3,
label: '美团'
}
])
// 本店团购订单状态
const originStatus = [
{
value: 'unpaid',
label: '待付款'
},
{
value: 'unused',
label: '待使用'
},
{
value: 'closed',
label: '已完成'
},
{
value: 'refunding',
label: '退款中'
},
{
value: 'refund',
label: '已退款'
},
{
value: 'cancelled',
label: '已取消'
}
]
// 抖音美团
const dmStatus = [
{
value: 0,
label: '等待验券'
},
{
value: 1,
label: '成功'
},
{
value: 2,
label: '失败'
}
]
const statusList = ref([])
// 切换筛选条件
function typeChange(e) {
switch (e) {
case 1:
statusList.value = [...originStatus]
break;
case 2:
statusList.value = [...dmStatus]
break;
case 3:
statusList.value = [...dmStatus]
thirdPartyCoupon_state_ajax()
break;
default:
break;
}
tableData.status = ''
tableData.page = 1
tableData.list = []
groupOrderlistAjax()
}
// 获取美团绑定状态
const meituanStatus = ref(false)
async function thirdPartyCoupon_state_ajax() {
try {
const res = await thirdPartyCoupon_state({
shopId: store.userInfo.id
})
if (res.status == 0) {
meituanStatus.value = false
// showMeituanUrlModal.value = true
// thirdPartyCoupon_bindUrl_ajax()
} else {
meituanStatus.value = true
}
} catch (error) {
console.log(error);
}
}
// 获取美团绑定链接
const meituanURL = ref('')
const showMeituanUrlModal = ref(false)
async function thirdPartyCoupon_bindUrl_ajax() {
try {
const res = await thirdPartyCoupon_bindUrl({
shopId: store.userInfo.id
})
meituanURL.value = res
} catch (error) {
console.log(error);
}
}
// 确认打开绑定美团链接
function openMeituan() {
showMeituanUrlModal.value = false
window.location.href = meituanURL.value
}
function showScanModalHandle() {
// 若果是美团并且没有绑定,则需要先绑定
if (tableData.type == 3 && !meituanStatus.value) {
showMeituanUrlModal.value = true
return
}
scanGroupRef.value.show()
}
// 状态
function statusFilter(t) {
return originStatus.find(item => item.value == t)?.label
}
// 分页变化
function paginationChange(e) {
groupOrderlistAjax()
}
// 重置
function resetHandle() {
tableData.proName = ''
tableData.status = ''
tableData.page = 1
tableData.resetLoading = true
groupOrderlistAjax()
}
// 显示团购核销撤销
function cacelDouyinHandle(item) {
ElMessageBox.confirm(
'是否撤销该团购?',
'注意').then(async () => {
await douyinfulfilmentcertificatecancel({ verify_id: item.verify_id, certificate_id: item.certificate_id })
ElMessage.success('撤销成功')
groupOrderlistAjax()
}).catch(() => { })
}
// 显示美团团购撤销
function cacelMeittuanHandle(item) {
ElMessageBox.confirm(
'是否撤销该团购?',
'注意').then(async () => {
try {
await meituan_fulfilmentcertificatecancel({ couponCode: item.couponCode })
ElMessage.success('撤销成功')
groupOrderlistAjax()
} catch (error) {
console.log(error);
}
}).catch(() => { })
}
// 获取团购订单数据
async function groupOrderlistAjax() {
try {
tableData.loading = true
let res = ''
switch (tableData.type) {
case 1:
// 获取本店团购数据
res = await groupOrderlist({
shopId: store.userInfo.id,
proName: tableData.proName,
status: tableData.status,
page: tableData.page,
size: tableData.size
})
tableData.resetLoading = false
tableData.loading = false
tableData.list = res.list
tableData.total = res.total
break;
case 2:
// 获取抖音团购数据
res = await douyinorderlist({
page: tableData.page,
status: tableData.status,
d_order_id: tableData.proName
})
tableData.resetLoading = false
tableData.loading = false
tableData.list = res.list
tableData.total = res.count
break;
case 3:
// 获取美团购数据
res = await meituan_orderlist({
page: tableData.page,
// status: tableData.status,
// d_order_id: tableData.proName,
date: ''
})
tableData.resetLoading = false
tableData.loading = false
tableData.list = res.list
tableData.total = res.count
break;
default:
break;
}
} catch (error) {
tableData.loading = false
console.log(error);
}
}
onMounted(() => {
typeChange(tableData.type)
searchstorestatusAjax()
})
</script>
<style scoped lang="scss">
.content {
padding: 14px;
}
.card {
background-color: #fff;
}
.top_btns {
padding: 14px;
border-bottom: 1px solid #ececec;
}
.pagination {
display: flex;
padding: 14px;
}
.info_wrap {
display: flex;
align-items: flex-start;
.t {
width: 100px;
margin-left: 10px;
}
}
.cart_wrap {
flex: 2;
}
.right_card {
flex: 1;
height: 100%;
margin-left: var(--el-font-size-base);
}
.header {
display: flex;
padding: 14px;
justify-content: space-between;
border-bottom: 1px solid #ececec;
.left {
display: flex;
gap: 10px;
.btn {
display: flex;
}
}
.menus {
display: flex;
padding: 0 10px;
.item {
padding: 0 10px;
display: flex;
align-items: center;
position: relative;
span {
font-size: var(--el-font-size-base);
}
&.active {
&::after {
content: "";
width: 70%;
height: 4px;
border-radius: 4px;
position: absolute;
bottom: 0;
left: 15%;
background-color: var(--primary-color);
}
span {
color: var(--primary-color);
}
}
}
}
.all {
display: flex;
align-items: center;
}
}
.tab_container {
padding: 0 var(--el-font-size-base) var(--el-font-size-base);
.tab_head {
padding-bottom: var(--el-font-size-base);
}
.overflow_y {
height: calc(100vh - 225px);
overflow-y: auto;
}
.tab_list {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
gap: var(--el-font-size-base);
.item {
background-color: #efefef;
border-radius: 6px;
overflow: hidden;
border: 2px solid #fff;
&.active {
border-color: var(--primary-color);
}
&:hover {
cursor: pointer;
}
.tab_title {
height: var(--el-component-size-large);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
color: #fff;
&.subscribe {
background-color: var(--el-color-success);
}
&.closed {
background-color: #999;
}
&.opening {
background-color: var(--primary-color);
}
&.cleaning {
background-color: var(--el-color-danger);
}
}
.tab_cont {
height: 120px;
display: flex;
align-items: center;
justify-content: center;
.icon {
color: #555;
font-size: 30px;
transform: rotate(45deg);
}
}
}
}
}
.goods_list {
.row {
display: flex;
align-items: center;
&:not(:first-child) {
margin-top: 10px;
}
}
}
</style>

View File

@@ -3,42 +3,31 @@
<el-dialog width="400px" :title="title" v-model="show" @close="reset">
<div class="u-p-15">
<div v-if="openSwitch" class="openSwitch">
<el-button
size="large"
@click="changeKey('paysSel', index)"
v-for="(item, index) in pays"
:key="index"
:type="paysSel == index ? 'primary' : ''"
>
<el-button size="large" @click="changeKey('paysSel', index)" v-for="(item, index) in pays" :key="index"
:type="paysSel == index ? 'primary' : ''">
<img :src="item.icon" alt="" style="width: 30px; height: 30px; margin-right: 10px" />
<span>
{{ item.text }}
</span>
</el-button>
</div>
<div class="u-m-t-20 flex flex-col">
<el-alert :closable="false" v-if="tips" :title="tips" type="warning" show-icon></el-alert>
</div>
<div class="u-m-t-20 flex justify-center">
<el-form label-width="90px" label-position="left">
<el-form-item label="" label-width="0">
<el-input
v-model="form.code"
@change="codeInputChange"
placeholder="请扫码或者输入券码"
ref="refInputCode"
></el-input>
<el-input v-model="form.code" @change="codeInputChange" placeholder="请扫码或者输入券码" ref="refInputCode"
:disabled="!pays[this.paysSel].status"></el-input>
</el-form-item>
<div class="u-flex u-row-center u-m-t-50">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
<el-button type="primary" :disabled="!pays[this.paysSel].status" @click="confirm">确定</el-button>
</div>
</el-form>
</div>
</div>
</el-dialog>
<bind-shop ref="refBindShop"></bind-shop>
<choose-goods ref="refChooseGoods" @hexiaoSuccess="hexiaoSuccess"></choose-goods>
</div>
@@ -51,6 +40,7 @@ import tiktokIcon from "@/assets/icons/douyin.png";
const user = useUserStore();
import * as $Api from "@/api/coup/index.js";
import { searchstorestatus, thirdPartyCoupon_bindUrl, getuisdk } from '@/api/coup/group'
import orderApi from "@/api/order/order";
import bindShop from "./douyin-quan-bind-shop.vue";
import chooseGoods from "./choose-quan-goods.vue";
@@ -94,10 +84,14 @@ export default {
pays: [
{
text: "美团",
clint_type: 1,
status: 0,
icon: meituanIcon,
},
{
text: "抖音",
clint_type: 2,
status: 0,
icon: tiktokIcon,
},
],
@@ -117,6 +111,44 @@ export default {
},
},
methods: {
// 查询抖音/美团绑定的状态
async searchstorestatus() {
try {
const { mt_status, dy_status } = await searchstorestatus(this.pays[this.paysSel].clint_type)
// console.log('查询抖音/美团绑定的状态', mt_status, dy_status);
this.pays.forEach(item => {
if (item.clint_type == 1) {
item.status = mt_status
}
if (item.clint_type == 2) {
item.status = dy_status
}
})
if (this.pays[this.paysSel].clint_type == 1 && this.pays[this.paysSel].status == 0) {
// 如果没有绑定,先提示用户去绑定
const res = await thirdPartyCoupon_bindUrl()
ElMessageBox.confirm('您的店铺还未绑定美团,请绑定后操作!', '注意', {
confirmButtonText: '去绑定'
}).then(() => {
window.open(res)
}).catch(() => { })
}
if (this.pays[this.paysSel].clint_type == 2 && this.pays[this.paysSel].status == 0) {
// 如果没有抖音,先提示用户去绑定
const res = await getuisdk()
ElMessageBox.confirm('您的店铺还未绑定抖音,请绑定后操作!', '注意', {
confirmButtonText: '去绑定'
}).then(() => {
window.open(res)
}).catch(() => { })
}
} catch (error) {
console.log(error);
}
},
refChooseGoodsOpen(data, types) {
this.$refs.refChooseGoods.open(data, types);
},
@@ -152,6 +184,8 @@ export default {
this.$nextTick(() => {
this.$refs.refInputCode.focus(); //获取焦点
});
this.searchstorestatus()
},
async confirm() {
@@ -189,7 +223,7 @@ export default {
window.open(res2);
}
})
.catch(() => {});
.catch(() => { });
return;
}
const res1 = await $Api.$meituan_fulfilmentcertificateprepare({
@@ -215,6 +249,8 @@ export default {
setTimeout(() => {
this.$refs.refInputCode.focus();
}, 100);
this.searchstorestatus()
},
close() {
this.show = false;
@@ -241,22 +277,28 @@ export default {
height: 164px;
overflow: hidden;
}
.openSwitch {
display: flex;
justify-content: center;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
:deep(.el-form) {
width: 200px;
}
:deep(.el-alert) {
width: inherit;
}
.flex-col {
flex-direction: column;
}