feat(uniapp_v2): 二开功能迁移与小程序主包优化

- 从 uniapp 迁移 HJF 页面、API、组件及用户/订单相关改动
- queue、assets 使用独立分包以降低主包体积
- 修复首页单根节点与支付结果页 v-if 链
- 关闭 HjfDemoPanel 全局注册;uniNoticeBar 注释 $getAppWebview 避免 __webviewId__ 报错
- 配置域名与 manifest 应用名称;cache/store 防御性处理

Made-with: Cursor
This commit is contained in:
apple
2026-03-26 12:16:01 +08:00
parent c84aeda062
commit 8e17762510
742 changed files with 184117 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props: {
visible: {
type: Boolean,
default: false,
},
promotionId:{
type: [String, Number],
default: ''
},
brandList:{
type:Array,
default: () => []
},
promotionList:{
type:Array,
default: () => []
},
labelList:{
type:Array,
default: () => []
},
},
data(){
return {
promotions_id: [],
brand_id: [],
store_label_id: [],
}
},
watch:{
// promotionId:{
// handler(val){
// this.promotions_id = val.split(',');
// },
// immediate:true
// },
},
computed: {
fixedTop() {
// #ifdef MP || APP-PLUS
return uni.getWindowInfo().statusBarHeight
// #endif
// #ifdef H5
return 20
// #endif
}
},
components: {
baseDrawer
},
methods: {
closeDrawer() {
this.$emit('closeDrawer');
},
checkPromotion(item){
if(this.promotions_id.includes(item.id)){
this.promotions_id = this.promotions_id.filter(function (ele){return ele != item.id;});
}else{
this.promotions_id.push(item.id);
}
},
checkLabel(item){
if(this.store_label_id.includes(item.id)){
this.store_label_id = this.store_label_id.filter(function (ele){return ele != item.id;});
}else{
this.store_label_id.push(item.id);
}
},
checkBrand(item){
if(this.brand_id.includes(item.id)){
this.brand_id = this.brand_id.filter(function (ele){return ele != item.id;});
}else{
this.brand_id.push(item.id);
}
},
confirmFilter(){
let data = {
promotions_id: this.promotions_id.join(','),
brand_id: this.brand_id.join(','),
store_label_id: this.store_label_id.join(',')
};
this.$emit('filterChange',data);
},
resetFilter(){
this.promotions_id = [];
this.brand_id = [];
this.store_label_id = [];
}
}
}
</script>
<template>
<view>
<base-drawer mode="right" :visible="visible" background-color="transparent" mask maskClosable
@close="closeDrawer">
<view class="drawer_box bg--w111-fff px-32 h-full">
<scroll-view scroll-y="true" style="height: 100vh;">
<view :style="{height:fixedTop + 'px'}"></view>
<view class="h-80 flex-center fs-34 fw-500 text--w111-333">筛选</view>
<view class="activity_box py-24">
<view v-if="promotionList.length">
<view class="fs-28 text--w111-333 fw-500">商品活动</view>
<view class="grid-column-3 box_gap mt-24">
<view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
v-for="item in promotionList" :key="item.id"
:class="{active: promotions_id.includes(item.id)}"
@tap="checkPromotion(item)">
<text class="inline-block w-full line1 px-12 text-center">{{item.desc}}</text>
</view>
</view>
</view>
<view v-if="brandList.length">
<view class="fs-28 text--w111-333 fw-500 mt-24">品牌</view>
<view class="grid-column-3 box_gap mt-24">
<view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
v-for="item in brandList" :key="item.id"
:class="{active: brand_id.includes(item.id)}"
@tap="checkBrand(item)">
<text class="inline-block w-full line1 px-12 text-center">{{item.brand_name}}</text>
</view>
</view>
</view>
<view v-if="labelList.length">
<view class="fs-28 text--w111-333 fw-500 mt-24">商品标签</view>
<view class="grid-column-3 box_gap mt-24">
<view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
v-for="item in labelList" :key="item.id"
:class="{active: store_label_id.includes(item.id)}"
@tap="checkLabel(item)">
<text class="inline-block w-full line1 px-12 text-center">{{item.label_name}}</text>
</view>
</view>
</view>
</view>
<view class="pb-safe">
<view class="h-112"></view>
</view>
</scroll-view>
<view class="fixed-lb pb-safe w-full">
<view class="px-32 flex-between-center h-112">
<view class="w-296 h-72 rd-40rpx flex-center font-num con_border bg--w111-fff"
@tap="resetFilter()">重置</view>
<view class="w-296 h-72 rd-40rpx flex-center text--w111-fff bg-color" @tap="confirmFilter()">确定</view>
</view>
</view>
</view>
</base-drawer>
</view>
</template>
<style>
.drawer_box {
width: 668rpx;
border-radius: 40rpx 0 0 40rpx;
overflow: auto;
}
.box_gap {
grid-row-gap: 24rpx;
grid-column-gap: 26rpx;
}
.con_border{
border: 1rpx solid var(--view-theme);
}
.active{
border: 1px solid var(--view-theme);
color: var(--view-theme);
background: var(--view-minorColorT);
}
</style>

View File

@@ -0,0 +1,96 @@
<template>
<base-drawer mode="bottom" :maskZIndex="1999" :zIndex="2000" :visible="visible" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="w-full bg--w111-f5f5f5 rd-t-40rpx py-32">
<view class="text-center fs-32 text--w111-333 fw-500">赠品</view>
<view class="px-20">
<scroll-view class="mt-48 w-full scroll-content" scroll-y="true">
<view class="text--w111-333 fs-28 lh-40rpx">本单可获得以下赠品</view>
<view class="gift-card mt-24 bg--w111-fff rd-16rpx p-16 flex-y-center"
v-for="(item,index) in giveCartInfo" :key="item.id" @tap="goPage(1,'/pages/goods_details/index?id=' + item.productInfo.id)">
<image class="w-116 h-116 rd-16rpx" :src="item.productInfo.attrInfo.image" v-if="item.productInfo.attrInfo"></image>
<image class="w-116 h-116 rd-16rpx" :src="item.productInfo.image" v-else></image>
<view class="flex-1 flex-between-center pl-16">
<view class="w-460">
<view class="w-full line1 fs-28 lh-40rpx">{{item.productInfo.store_name}}</view>
<view class="fs-22 text--w111-999 lh-30rpx mt-12">数量x{{item.cart_num}}</view>
</view>
<text class="iconfont icon-ic_rightarrow fs-24 text--w111-999"></text>
</view>
</view>
<view class="gift-card mt-24 bg--w111-fff rd-16rpx p-16 flex-y-center"
v-for="(item,index) in giveData.give_coupon" :key="index" @tap="goPage(1,'/pages/users/user_coupon/index')">
<view class="w-116 h-116 rd-16rpx flex-center bg--w111-f5f5f5">
<text class="fs-48 gold iconfont icon-a-ic_discount1"></text>
</view>
<view class="flex-1 flex-between-center pl-16">
<view class="w-460">
<view class="w-full line1 fs-28 lh-40rpx">{{item.coupon_title}}</view>
<view class="fs-22 text--w111-999 lh-30rpx mt-12">数量x1</view>
</view>
<text class="iconfont icon-ic_rightarrow fs-24 text--w111-999"></text>
</view>
</view>
<view class="gift-card mt-24 bg--w111-fff rd-16rpx p-16 flex-y-center"
v-if="giveData.give_integral>0"
@tap="goPage(1,'/pages/users/user_integral/index')">
<view class="w-116 h-116 rd-16rpx flex-center bg--w111-f5f5f5">
<text class="fs-48 gold iconfont icon-ic_badge11"></text>
</view>
<view class="flex-1 flex-between-center pl-16">
<view class="w-460">
<view class="w-full line1 fs-28 lh-40rpx">{{giveData.give_integral}}积分</view>
<view class="fs-22 text--w111-999 lh-30rpx mt-12">数量x1</view>
</view>
<text class="iconfont icon-ic_rightarrow fs-24 text--w111-999"></text>
</view>
</view>
</scroll-view>
</view>
<view class="mx-20 pb-safe">
<view class="mt-52 h-72 flex-center rd-36px bg-color fs-26 text--w111-fff" @tap="closeDrawer">确定</view>
</view>
</view>
</base-drawer>
</template>
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props:{
visible: {
type: Boolean,
default: false,
},
giveCartInfo:{
type: Array,
default: ()=>[]
},
giveData:{
type: Object,
default: ()=>{}
},
},
components: {
baseDrawer
},
methods:{
closeDrawer() {
this.$emit('closeDrawer');
},
goPage(type,url){
uni.navigateTo({
url
})
}
}
}
</script>
<style>
.gold{
color: #DCA658;
}
.scroll-content{
height: 800rpx;
}
</style>

View File

@@ -0,0 +1,337 @@
<template>
<!-- 选择发票信息下拉列表 -->
<view>
<view :class="{ mask: invShow }" @touchmove.stop.prevent @click="invClose"></view>
<view class="popup" :class="{ on: invShow }" @touchmove.stop.prevent>
<view class="popup-hd">抬头选择<view class="close" @click="invClose"><text class="iconfont icon-ic_close"></text></view>
</view>
<scroll-view class="popup-bd" scroll-y="true">
<radio-group v-if="invList.length" name="inv" @change="invChange">
<template v-for="(item, index) in invList">
<label v-if="item.type === 1 || item.type === 2 && isSpecial" :key="item.id" :class="{ checked: (invChecked || invId) == item.id }" class="acea-row row-middle item">
<text class="iconfont icon-ic_complete"></text>
<radio class="radio" :value="item.id" :checked="item.id === invChecked" />
<view class="text">
<view class="acea-row row-middle type">{{ item.type === 1 ? '普通' : '专用' }}发票抬头-{{ item.header_type === 1 ? '个人' : '企业' }}</view>
<view class="acea-row row-middle text-bottom">
<view class="text-left">
<view class="acea-row row-middle name-wrap">
<view class="name">{{item.name}}</view>
<view v-if="item.is_default" class="default">默认</view>
</view>
<view class="number">{{item.header_type == 1 ? item.drawer_phone : item.duty_number}}</view>
</view>
<navigator v-if="!isOrder" class="navigator acea-row row-center-wrapper" :url="`/pages/users/user_invoice_form/index?from=order_confirm&id=${item.id}&${urlQuery}`"
hover-class="none"><text class="iconfont icon-ic_edit"></text></navigator>
<navigator v-else class="navigator acea-row row-center-wrapper" :url="`/pages/users/user_invoice_form/index?from=order_details&id=${item.id}&order_id=${orderId}`"
hover-class="none"><text class="iconfont icon-ic_edit"></text></navigator>
</view>
</view>
</label>
</template>
</radio-group>
<view v-else class="empty">
<image class="image" :src="imgHost + '/statics/images/noInvoice.png'"></image>
<view>您还没有添加发票信息哟~</view>
</view>
</scroll-view>
<view class="popup-ft">
<button v-if="isOrder && invList.length" class="navigator" plain @click="invSub">确认提交</button>
<navigator v-if="!isOrder" class="button text-center" :url="`/pages/users/user_invoice_form/index?from=order_confirm&${urlQuery}`" hover-class="none">添加新的抬头</navigator>
<navigator v-else class="button text-center" :url="`/pages/users/user_invoice_form/index?order_id=${orderId}&from=order_details`" hover-class="none">添加新的抬头</navigator>
<!-- <button class="button" plain @click="invCancel">不开发票</button> -->
<slot name="buttom"></slot>
</view>
</view>
</view>
</template>
<script>
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
data() {
return {
invId: 0,
imgHost: HTTP_REQUEST_URL
}
},
props: {
invShow: {
type: Boolean,
default: false
},
invList: {
type: Array,
default () {
return [];
}
},
invChecked: {
type: String,
default: ''
},
isSpecial: {
type: Boolean,
default: false
},
urlQuery: {
type: String,
default: ''
},
isOrder: {
type: Number,
default: 0
},
orderId: {
type: String,
default: ''
}
},
methods: {
invClose(state) {
this.$emit('inv-close');
},
invChange(e) {
if (this.isOrder) {
this.invId = e.detail.value
} else {
this.$emit('inv-change', e.detail.value);
}
},
invSub() {
this.$emit('inv-change', this.invId || this.invChecked);
},
invCancel() {
this.$emit('inv-cancel');
}
},
}
</script>
<style lang="scss" scoped>
/deep/uni-radio .uni-radio-input {
margin-right: 0;
}
.popup {
position: fixed;
bottom: 0;
left: 0;
z-index: 2000;
width: 100%;
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
background-color: #F5F5F5;
transform: translateY(100%);
transition: 0.3s;
}
.popup.on {
transform: translateY(0);
}
.popup-hd {
position: relative;
height: 108rpx;
font-size: 32rpx;
line-height: 108rpx;
text-align: center;
color: #333333;
.close {
position: absolute;
top: 50%;
right: 32rpx;
width: 36rpx;
height: 36rpx;
border-radius: 18rpx;
margin-top: -16rpx;
background-color: #EEEEEE;
text-align: center;
line-height: 36rpx;
}
.iconfont {
font-size: 24rpx;
color: #999999;
}
}
.popup-bd {
height: 792rpx;
padding: 24rpx 20rpx 8rpx;
box-sizing: border-box;
.item {
position: relative;
border: 1rpx solid #FFFFFF;
border-radius: 24rpx;
margin-bottom: 20rpx;
background-color: #FFFFFF;
overflow: hidden;
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
border: 36rpx solid #FFFFFF;
}
.icon-ic_complete {
position: absolute;
top: 8rpx;
right: 8rpx;
z-index: 2;
font-size: 32rpx;
color: #FFFFFF;
}
&.checked {
border-color: var(--view-theme);
&::after {
border-color: var(--view-theme);
border-bottom-color: transparent;
border-left-color: transparent;
}
}
}
.radio {
display: none;
}
.text {
flex: 1;
min-width: 0;
}
.text-bottom {
position: relative;
padding: 32rpx 24rpx;
&::before {
content: "";
position: absolute;
top: 0;
right: 24rpx;
left: 24rpx;
border-top: 1rpx solid #eee;
}
}
.name-wrap {
display: inline-flex;
max-width: 100%;
}
.name {
flex: 1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: 500;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
.default {
height: 34rpx;
padding: 0 8rpx;
border-radius: 8rpx;
margin-left: 8rpx;
background-color: #FCEAE9;
font-size: 22rpx;
line-height: 34rpx;
color: var(--view-theme);
}
.email {
margin-top: 16rpx;
font-size: 24rpx;
color: #666666;
}
.number {
margin-top: 12rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #999999;
}
.text-left {
flex: 1;
min-width: 0;
}
.type {
padding: 24rpx;
font-size: 24rpx;
line-height: 34rpx;
color: #333333;
}
.navigator {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
margin-left: 24rpx;
.iconfont {
font-size: 32rpx;
color: #333333;
}
}
}
.popup-ft {
padding: 20rpx 20rpx calc(20rpx + env(safe-area-inset-bottom));
.navigator {
height: 80rpx;
border-radius: 40rpx;
background-color: var(--view-theme);
font-size: 28rpx;
line-height: 80rpx;
text-align: center;
color: #FFFFFF;
border: none;
.iconfont {
margin-right: 14rpx;
font-size: 30rpx;
}
}
.button {
height: 80rpx;
border: 1rpx solid var(--view-theme);
border-radius: 40rpx;
margin-top: 24rpx;
font-size: 28rpx;
line-height: 80rpx;
color: var(--view-theme);
}
}
.empty {
padding-top: 58rpx;
font-size: 26rpx;
text-align: center;
color: #999999;
.image {
width: 400rpx;
height: 260rpx;
margin-bottom: 20rpx;
}
}
.mask {
z-index: 1999;
}
</style>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,250 @@
@charset "UTF-8";
/* 颜色变量 */
/* 行为相关颜色 */
/* 文字基本颜色 */
/* 背景颜色 */
/* 边框颜色 */
/* 尺寸变量 */
/* 文字尺寸 */
/* 图片尺寸 */
/* Border Radius */
/* 水平间距 */
/* 垂直间距 */
/* 透明度 */
/* 文章场景相关 */
li {
list-style: none;
}
ul,
li {
margin: 0;
padding: 0;
}
.lottery_container {
width: 100%;
height: 100%;
}
.grid_wrap {
width: 100%;
height: 100%;
position: relative;
}
.grid_wrap .lottery_wrap_border {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.grid_wrap .lottery_wrap_border ul {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
}
.grid_wrap .lottery_wrap_border ul li {
border-radius: 50%;
width: 17upx;
height: 17upx;
background-color: #bce0e9;
}
.grid_wrap .lottery_wrap_border ul li:nth-child(even) {
width: 24upx;
height: 24upx;
background-color: #f5fbc8;
}
.grid_wrap .lottery_wrap_border ul:nth-child(odd) {
width: 100%;
height: 35upx;
left: 0;
right: 0;
flex-direction: row;
}
.grid_wrap .lottery_wrap_border ul:nth-child(odd) li {
margin: 0 10upx;
}
.grid_wrap .lottery_wrap_border ul:nth-child(even) {
width: 35upx;
height: 100%;
top: 0;
bottom: 0;
flex-direction: column;
}
.grid_wrap .lottery_wrap_border ul:nth-child(even) li {
margin: 10upx 0;
}
.grid_wrap .lottery_wrap_border ul:nth-child(3) {
bottom: 0;
}
.grid_wrap .lottery_wrap_border ul:nth-child(4) {
right: 0;
}
.grid_wrap .lottery_wrap_border ul:nth-child(1) li:nth-child(odd),
.grid_wrap .lottery_wrap_border ul:nth-child(4) li:nth-child(odd) {
animation: blink_large 1s linear infinite;
}
.grid_wrap .lottery_wrap_border ul:nth-child(1) li:nth-child(even),
.grid_wrap .lottery_wrap_border ul:nth-child(4) li:nth-child(even) {
animation: blink_small 1s linear infinite;
}
.grid_wrap .lottery_wrap_border ul:nth-child(3) li:nth-child(even),
.grid_wrap .lottery_wrap_border ul:nth-child(2) li:nth-child(even) {
width: 17upx;
height: 17upx;
background-color: #bce0e9;
animation: blink_large 1s linear infinite;
}
.grid_wrap .lottery_wrap_border ul:nth-child(3) li:nth-child(odd),
.grid_wrap .lottery_wrap_border ul:nth-child(2) li:nth-child(odd) {
width: 24upx;
height: 24upx;
background-color: #f5fbc8;
animation: blink_small 1s linear infinite;
}
.grid_wrap .lottery_wrap {
width: 100%;
height: 100%;
font-size: 14upx;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1;
}
.grid_wrap .lottery_wrap .lottery_grid {
width: 100%;
height: 424rpx;
position: relative;
}
.grid_wrap .lottery_wrap .lottery_grid li {
width: 32%;
height: 130rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
float: left;
position: absolute;
border-radius: 16rpx;
color: #E74435;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 20upx;
/* margin: 4px; */
padding: 4px;
background: #FEF6E7;
}
.grid_wrap .lottery_wrap .lottery_grid li .in_line {
border-radius: 12rpx;
width: 100%;
height: 130rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
padding: 0 4rpx;
}
.grid_wrap .lottery_wrap .lottery_grid li .grid_img {
width: 72rpx;
height: 72rpx;
}
.grid_wrap .lottery_wrap .lottery_grid .active {
background: rgba(255,125,0,0.2) !important;
color: #E93323;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(1) {
left: 1%;
top: 1%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(2) {
left: 34%;
top: 1%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(3) {
left: 67%;
top: 1%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(4) {
left: 67%;
top: 34%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(5) {
left: 67%;
top: 67%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(6) {
left: 34%;
top: 67%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(7) {
left: 1%;
top: 67%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(8) {
left: 1%;
top: 34%;
}
.grid_wrap .lottery_wrap .lottery_grid li:nth-of-type(9) {
left: 34%;
top: 34%;
cursor: pointer;
color: #ffffff;
background: linear-gradient(90deg, var(--view-gradient) 0, var(--view-theme) 100%);
}
@keyframes blink_large {
to {
width: 24upx;
height: 24upx;
background-color: #f5fbc8;
}
}
@keyframes blink_small {
to {
width: 17upx;
height: 17upx;
background-color: #bce0e9;
}
}
/*# sourceMappingURL=SJ-LotteryDraw.css.map */

View File

@@ -0,0 +1,159 @@
<template>
<view class="lottery_container">
<view class="grid_wrap">
<view class="lottery_wrap">
<view class="lottery_grid">
<view v-for="(item, index) in prizeData" :key="index" :class="{ active: current_index == index && index != 8 }" class="item" @click="luck_draw">
<view :class="{in_line:index != 8 }" class="lottery-msg">
<image v-if="index != 8" class="grid_img" mode='aspectFit' :src="item.image" alt="" />
<text v-if="index !=8" class="name line1">
{{ index == 8 ? '抽奖' : item.name }}
</text>
<view v-else class="flex-col flex-center lottery-click">
<!-- <text class="fs-36">立即抽奖</text> -->
<text class="fs-36">{{lotteryNum}}</text>
<text class="fs-20 lh-28rpx">抽奖机会</text>
</view>
</view>
</view>
</view>
</view>
<!-- <view class="lottery_wrap_border">
<ul v-for="(item, index) in 4" :key="index">
<li v-for="(item, index) in 12" :key="index"></li>
</ul>
</view> -->
</view>
</view>
</template>
<script>
import LotteryDraw from './js/grids_lottery.js';
export default {
data() {
return {
current_index: -1,
lotteryBtn: true
};
},
props: {
prizeData: {
type: Array,
default: function() {
return []
}
},
lotteryType: {
type: Number,
default: 0
},
datatime: {
type: Number,
default: 0
},
lotteryNum: {
type: Number,
default: 0
},
isRotating: {
type: Boolean,
default: false
},
winingIndex: {
type: Number,
default: 0
},
},
watch: {
isRotating(newValue, oldValue) {
let that = this;
if (newValue) {
// let lottery_draw_param = res;
let win = new LotteryDraw({
domData: that.prizeData,
// ...lottery_draw_param
startIndex: 3, //开始抽奖位置从0开始
totalCount: 3, //一共要转的圈数
winingIndex: this.winingIndex, //中奖的位置从0开始
speed: 100 //抽奖动画的速度 [数字越大越慢,默认100]
},
function(index, count) {
that.current_index = index;
if (that.winingIndex == index && 3 ==
count) {
that.lotteryBtn = true
that.$emit('luck_draw_finish', that.prizeData[index])
}
}
);
}
}
},
mounted() {},
methods: {
luck_draw(event) {
let timestamp = Date.parse(new Date()) / 1000;
if (this.lotteryType == 1 && parseInt(timestamp) > parseInt(this.datatime)) {
return this.$util.Tips({
title: '您抽奖的有效时间已到期'
}, function() {
uni.switchTab({
url: '/pages/index/index'
})
});
}
let index = event.currentTarget.dataset.index;
if (this.lotteryBtn && index == 8) {
this.lotteryBtn = false
} else {
return
}
let that = this;
if (index == 8) {
// 点击抽奖之后知道获奖位置修改父组件中lottery_draw_param的值
this.$emit('get_winingIndex', function(res) {
let lottery_draw_param = res;
let win = new LotteryDraw({
domData: that.prizeData,
...lottery_draw_param
},
function(index, count) {
that.current_index = index;
if (lottery_draw_param.winingIndex == index && lottery_draw_param.totalCount ==
count) {
that.lotteryBtn = true
that.$emit('luck_draw_finish', that.prizeData[index])
}
}
);
});
}
}
}
};
</script>
<style scoped lang="scss">
@import './css/grids_lottery.css';
.lottery-msg {
width: 100%;
height: 100%;
padding: 0 4rpx;
.name {}
}
.lottery-click {
width: 100%;
height: 100%;
}
.lottery_grid .name {
width: 100%;
text-align: center;
}
</style>

View File

@@ -0,0 +1,47 @@
function LotteryDraw(obj, callback) {
this.timer = null; //计时器
this.startIndex = obj.startIndex-1 || 0; //从第几个位置开始抽奖 [默认为零]
this.count = 0; //计数,跑的圈数
this.winingIndex = obj.winingIndex || 0;//获奖的位置
this.totalCount = obj.totalCount || 6;//抽奖跑的圈数
this.speed = obj.speed || 100;
this.domData=obj.domData;
this.rollFn();
this.callback = callback;
}
LotteryDraw.prototype = {
rollFn: function() {
var that = this;
// console.log(`获奖位置:${this.winingIndex}`)
// 活动index值增加即移动到下一个格子
this.startIndex++;
//startIndex是最后一个时一圈走完重新开始
if (this.startIndex >= this.domData.length - 1) {
this.startIndex = 0;
this.count++;
}
// 当跑的圈数等于设置的圈数且活动的index值是奖品的位置时停止
if (this.count >= this.totalCount && this.startIndex === this.winingIndex) {
if (typeof this.callback === 'function') {
setTimeout(function() {
that.callback(that.startIndex,that.count); //执行回调函数,抽奖完成的相关操作
}, 400);
}
clearInterval(this.timer);
}else { //重新开始一圈
if (this.count >= this.totalCount - 1) {
this.speed += 30;
}
this.timer = setTimeout(function() {
that.callback(that.startIndex,that.count);
that.rollFn();
}, this.speed);
}
}
}
module.exports = LotteryDraw;

View File

@@ -0,0 +1,119 @@
<template>
<view class="lottery_container">
<view class="grid_wrap">
<view class="lottery_wrap">
<ul class="lottery_grid">
<li v-for="(item, index) in prizeData" :class="{ active: current_index == index && index != 8 }"
:key="index" @click="luck_draw" :data-index="index">
<view :class="{in_line:index != 8 }" class="lottery-msg">
<image v-if="index != 8" class="grid_img" mode='aspectFit' :src="item.image" alt="" />
<text v-if="index !=8" class="name">
{{ index == 8 ? '抽奖' : item.name }}
</text>
<view v-else class="flex-col flex-center lottery-click">
<image src="../../static/lottery_text.png" class="w-140 h-32 block"></image>
<text class="fs-20 lh-28rpx pt-6">剩余 {{lotteryNum}} 次机会</text>
</view>
</view>
</li>
</ul>
</view>
</view>
</view>
</template>
<script>
import LotteryDraw from './js/grids_lottery.js';
export default {
data() {
return {
current_index: -1,
lotteryBtn: true
};
},
props: {
prizeData: {
type: Array,
default: function() {
return []
}
},
lotteryType: {
type: Number,
default: 0
},
datatime: {
type: Number,
default: 0
},
lotteryNum:{
type: Number,
default: 0
}
},
onLoad() {
},
methods: {
luck_draw(event) {
console.log(123456);
let timestamp = Date.parse(new Date())/1000;
if(this.lotteryType == 1 && parseInt(timestamp)>parseInt(this.datatime)){
return this.$util.Tips({
title: '您抽奖的有效时间已到期'
},function(){
uni.switchTab({
url: '/pages/index/index'
})
});
}
let index = event.currentTarget.dataset.index;
if (this.lotteryBtn && index == 8) {
this.lotteryBtn = false
} else {
return
}
let that = this;
if (index == 8) {
// 点击抽奖之后知道获奖位置修改父组件中lottery_draw_param的值
this.$emit('get_winingIndex', function(res) {
let lottery_draw_param = res;
let win = new LotteryDraw({
domData: that.prizeData,
...lottery_draw_param
},
function(index, count) {
that.current_index = index;
if (lottery_draw_param.winingIndex == index && lottery_draw_param.totalCount ==
count) {
that.lotteryBtn = true
that.$emit('luck_draw_finish', that.prizeData[index])
}
}
);
});
}
}
}
};
</script>
<style scoped lang="scss">
@import './css/pay_lottery.css';
.lottery-msg {
width: 100%;
height: 100%;
padding: 0 4rpx;
.name {}
}
.lottery-click {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,139 @@
<template>
<!-- 抽奖结果弹窗 -->
<view class="aleart flex-col flex-center" v-if="aleartStatus" @touchmove.stop.prevent>
<image :src="alData.image" class="w-180 h-180"></image>
<view class="fs-34 font-red fw-500 lh-48rpx mt-24"
:class="theme ? 'font-num' : 'font-red'"
>{{alData.type > 1 ? '恭喜你获得' : alData.name}}</view>
<view class="fs-26 text--w111-333 lh-36rpx mt-24">{{aleartData.msg}}</view>
<view class="btn flex-center fs-28 text--w111-fff mt-32" @tap="posterImageClose"
:class="theme ? 'bg-gradient1' : 'bg-red-g'"
>{{alData.type > 1 ? '立即领取' : '我知道了'}}</view>
<text class="close iconfont icon-ic_close1" @click="posterImageClose"></text>
<slot name="bottom"></slot>
</view>
</template>
<script>
import { openReceivedSubscribe } from "@/utils/SubscribeMessage.js"
export default {
data() {
return {
aleartData: {}
}
},
props: {
aleartType: {
type: Number,
default:0
},
alData: {
type: Object,
default:()=>{}
},
aleartStatus: {
type: Boolean,
default: false
},
theme:{
type: Boolean,
default: false
}
},
watch: {
aleartType(type) {
if (type === 1) {
this.aleartData = {
title: '暂无抽奖资格',
msg: `1、您未关注公众号
2、您未获得VIP权限获取VIP途径
1购买过打通版的用户可在会员群联系官方客服开通
2官方小程序商城购买CRMEB打通版、企业版后自动开通`,
btn: '我知道了'
}
} else if (type === 2) {
this.aleartData = {
title: '抽奖结果',
img: this.alData.image,
msg: this.alData.prompt,
btn: '好的',
type: this.alData.type
}
}
},
aleartStatus(status) {
if (!status) {
this.aleartData = {}
}
}
},
methods: {
//隐藏弹窗
posterImageClose(type) {
if(this.alData.type == 4){
// #ifdef MP-WEIXIN
uni.showLoading({
title: '正在加载'
});
openReceivedSubscribe().then(res=>{
uni.hideLoading();
uni.navigateTo({
url: '/pages/goods/lottery/grids/record'
})
}).catch(err=>{
uni.hideLoading();
uni.navigateTo({
url: '/pages/goods/lottery/grids/record'
})
})
// #endif
// #ifdef H5 || APP-PLUS
uni.navigateTo({
url: '/pages/goods/lottery/grids/record'
})
// #endif
}
this.$emit("close", false)
},
}
}
</script>
<style lang="scss" scoped>
.aleart {
width: 480rpx;
height: 544rpx;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 9999;
background-color: #fff;
border-radius: 48rpx;
background-image:url('../../static/alert_modal_bg.png');
background-size:100%;
background-repeat: no-repeat;
}
.aleart .close{
position: absolute;
left:50%;
bottom:-100rpx;
transform: translateX(-50%);
color: #fff;
font-size:50rpx;
}
.font-red{
color: #e93323;
}
.btn{
width: 280rpx;
height: 80rpx;
border-radius: 50rpx;
color: #fff;
}
.bg-red-g{
background: linear-gradient(90deg, #FF7931 0%, #E93323 100%);
}
</style>

View File

@@ -0,0 +1,81 @@
<template>
<view>
<base-drawer mode="bottom" :visible="refundData.show" background-color="transparent" mask maskClosable @close="closeDrawer">
<view class="w-full bg--w111-fff rd-t-40rpx py-32 relative">
<view class="text-center fs-32 text--w111-333 fw-500">选择退款原因</view>
<view class="close flex-center" @tap='closeDrawer'>
<text class="iconfont icon-ic_close fs-24 text--w111-999"></text>
</view>
<view class="mt-48 px-24 scroll-content">
<view class="list">
<view class="cell flex-between-center"
v-for="(item,index) in refundData.RefundArray" :key='index'
@click="tapSelect(index)">
<view class="fs-28">{{item}}</view>
<text v-if="index == current" class="iconfont icon-a-ic_CompleteSelect fs-36 font-num"></text>
<text v-else class="iconfont icon-ic_unselect fs-36 text--w111-ccc"></text>
</view>
</view>
<view class="pb-safe">
<view class="mt-52 w-full h-72 flex-center rd-36px bg-color fs-26 text--w111-fff" @tap="determine">确定</view>
</view>
</view>
</view>
</base-drawer>
</view>
</template>
<script>
import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
export default {
props: {
refundData: {
type: Object,
default: function() {
return {
show: false,
RefundArray: []
};
}
},
},
components: {
baseDrawer
},
data() {
return {
current:0
};
},
methods: {
closeDrawer: function() {
this.$emit('changeClose');
},
tapSelect(index){
this.current = index;
},
determine(){
this.$emit('selectInfo',this.current);
}
}
}
</script>
<style lang="scss" scoped>
.scroll-content{
max-height: 800rpx;
overflow-y: auto;
}
.cell ~ .cell{
margin-top: 64rpx;
}
.close{
position: absolute;
right: 32rpx;
top: 36rpx;
width: 36rpx;
height: 36rpx;
border-radius: 50%;
background-color: #eee;
}
</style>

View File

@@ -0,0 +1,74 @@
<template>
<view class="gift-message-card">
<view class="message-header">
<image class="avatar" :src="avatar" mode="aspectFill"></image>
<text class="gift-text">{{ nickname }} 赠您一份礼物请查收</text>
</view>
<view class="divider"></view>
<view class="message-content">
<text class="message-text">{{
gift_mark || "天天开心,所得皆所愿~"
}}</text>
</view>
</view>
</template>
<script>
export default {
name: "SendGiftMarkCard",
props: {
avatar: {
type: String,
default: "",
},
nickname: {
type: String,
default: "匿名",
},
gift_mark: {
type: String,
default: "",
},
},
};
</script>
<style lang="scss" scoped>
.gift-message-card {
background-color: #ffffff;
border-radius: 24rpx;
padding: 32rpx 24rpx;
.message-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.avatar {
width: 36rpx;
height: 36rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.gift-text {
font-size: 28rpx;
color: #ae5a2a;
font-weight: 400;
}
}
.divider {
height: 1rpx;
background-color: #f5f5f5;
margin: 20rpx 0;
}
.message-content {
.message-text {
font-size: 28rpx;
color: #333;
line-height: 1.5;
}
}
}
</style>

View File

@@ -0,0 +1,429 @@
<template>
<view class="aleart" v-if="aleartStatus" :style="'background-image: url(' + giftbag + ');'">
<template v-if="!posterImageStatus">
<text class="iconfont icon-ic_close1 close" @click="posterImageClose"></text>
<view class="from">赠送给好友一份礼物</view>
<view class="message line2">{{ giftData.message }}</view>
<view class="aleart-body">
<image class="goods-img" :src="giftData.image" mode=""></image>
</view>
<view class="title line1">
{{ giftData.title }}
</view>
<!-- #ifdef H5 -->
<view class="btn" @tap="copyLink">复制礼物链接</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<button class="btn" open-type="share" hover-class="none">送给好友</button>
<!-- #endif -->
<view class="btn-clear" @click="getPoster()">保存海报</view>
</template>
<template v-if="posterImageStatus">
<text class="iconfont icon-ic_close1 close" @click="posterImageClose"></text>
<image class="poster-img" :src="posterImage"></image>
<!-- #ifdef H5 -->
<view class="keep">长按图片可以保存到手机</view>
<!-- #endif -->
</template>
<!-- #ifdef H5 || APP-PLUS -->
<zb-code
ref="qrcode"
:show="codeShow"
:cid="cid"
:val="codeVal"
:size="size"
:unit="unit"
:background="background"
:foreground="foreground"
:pdground="pdground"
:icon="codeIcon"
:iconSize="iconsize"
:onval="onval"
:loadMake="loadMake"
@result="qrR"
/>
<!-- #endif -->
</view>
</template>
<script>
import { HTTP_REQUEST_URL } from '@/config/app';
export default {
data() {
return {
aleartData: {},
bag: HTTP_REQUEST_URL + '/statics/images/canvas-bag.png',
giftBorder: HTTP_REQUEST_URL + '/statics/images/gift-border.png',
giftbag: HTTP_REQUEST_URL + '/statics/images/gift-bag.png',
//二维码参数
codeShow: false,
cid: '1',
codeVal: '', // 要生成的二维码值
size: 200, // 二维码大小
unit: 'upx', // 单位
background: '#FFF', // 背景色
foreground: '#000', // 前景色
pdground: '#000', // 角标色
codeIcon: '', // 二维码图标
iconsize: 40, // 二维码图标大小
lv: 3, // 二维码容错级别 一般不用设置,默认就行
onval: true, // val值变化时自动重新生成二维码
loadMake: true, // 组件加载完成后自动生成二维码
PromotionCode: '',
posterImageStatus: false,
posterImage: ''
};
},
props: {
giftData: {
type: Object
},
aleartStatus: {
type: Boolean,
default: false
}
},
watch: {
aleartStatus(status) {
if (!status) {
this.aleartData = {};
} else {
// #ifdef H5
this.codeVal = window.location.origin + '/pages/goods/receive_gift/index?id=' + this.giftData.id + '&spid=' + this.$store.state.app.uid;
// #endif
// #ifdef APP-PLUS
this.codeVal = HTTP_REQUEST_URL + '/pages/goods/receive_gift/index?id=' + this.giftData.id + '&spid=' + this.$store.state.app.uid;
// #endif
// #ifdef MP
this.PromotionCode = this.giftData.code;
// #endif
}
}
},
methods: {
copyLink() {
uni.setClipboardData({
data: this.codeVal,
success: () => {
this.$util.Tips({
title: '复制成功'
});
}
});
},
qrR(res) {
// #ifdef H5
if (!this.$wechat.isWeixin() || this.shareQrcode != '1') {
this.PromotionCode = res;
}
// #endif
// #ifdef APP-PLUS
this.PromotionCode = res;
// #endif
},
//隐藏弹窗
posterImageClose() {
this.posterImageStatus = false;
this.$emit('close', false);
},
drawPoster(loadedImages, name, store_name) {
// 截断标题函数
function truncateTitle(title, maxLength) {
if (title.length > maxLength) {
return title.substring(0, maxLength) + '...';
}
return title;
}
// 获取canvas上下文
const ctx = uni.createCanvasContext('posterCanvas');
return new Promise(async (resolve, reject) => {
uni.getImageInfo({
src: loadedImages[0],
success: (res) => {
// 海报尺寸
const posterWidth = 375;
const posterHeight = 579;
// const posterWidth = res.width / 2;
// const posterHeight = res.height / 2;
// 绘制背景图
ctx.drawImage(loadedImages[0], 0, 0, posterWidth, posterHeight);
ctx.save();
// 头像和标题的布局
const avatarSize = 22; // 头像尺寸
const nickname = name; // 昵称
const title = '送你一份礼物'; // 标题文字
const titleFontSize = 14; // 标题字号
const nicknameFontSize = 14; // 昵称字号
const padding = 10; // 元素之间的间距
// 计算标题宽度
ctx.setFontSize(titleFontSize);
const titleWidth = ctx.measureText(title).width;
const nicknameWidth = ctx.measureText(nickname).width;
// 计算头像和标题的总宽度
const totalWidth = avatarSize + padding + nicknameWidth + padding + titleWidth;
// 计算起始绘制位置(水平居中)
const startX = (posterWidth - totalWidth) / 2;
const startY = 47; // 距离顶部的距离
// 绘制头像
// ctx.drawImage(loadedImages[3], startX, startY, avatarSize, avatarSize);
const avatarX = startX + avatarSize / 2; // 头像中心点 X
const avatarY = startY + avatarSize / 2; // 头像中心点 Y
ctx.save(); // 保存画布状态
ctx.beginPath();
ctx.arc(avatarX, avatarY, avatarSize / 2, 0, Math.PI * 2); // 绘制圆形路径
ctx.clip(); // 裁剪圆形区域
ctx.drawImage(loadedImages[3], startX, startY, avatarSize, avatarSize); // 绘制头像
ctx.restore(); // 恢复画布状态
// 绘制昵称
ctx.setFontSize(nicknameFontSize);
ctx.setTextAlign('left');
ctx.fillText(nickname, startX + avatarSize + padding, startY + avatarSize - 5); // 调整文字垂直居中
// 绘制标题
ctx.setFontSize(titleFontSize);
ctx.fillText(title, startX + avatarSize + padding + nicknameWidth + padding, startY + avatarSize - 5);
// 商品图尺寸
const productImageSize = 225; // 商品图尺寸为 225px x 225px
// 绘制商品图边框
const productBorderX = (posterWidth - productImageSize) / 2; // 水平居中
const productBorderY = startY + avatarSize + 31; // 距离头像和标题的间距
ctx.drawImage(loadedImages[1], productBorderX, productBorderY, productImageSize, productImageSize);
// 绘制商品图
const productImagePadding = 10; // 商品图与边框的内边距
const productImageX = productBorderX + productImagePadding;
const productImageY = productBorderY + productImagePadding + 11;
const productImageInnerSize = productImageSize - 2 * productImagePadding; // 商品图实际绘制尺寸
ctx.drawImage(loadedImages[2], productImageX, productImageY, productImageInnerSize, productImageInnerSize - 10);
// 绘制商品标题
const productTitle = store_name;
const maxTitleLength = 20; // 标题最大长度
const truncatedTitle = truncateTitle(productTitle, maxTitleLength); // 截断标题
ctx.setFontSize(14);
ctx.setTextAlign('center');
ctx.fillText(truncatedTitle, posterWidth / 2, productBorderY + productImageSize + 26);
// 绘制分享二维码
const qrCodeSize = 100;
const qrCodeX = (posterWidth - qrCodeSize) / 2;
const qrCodeY = productBorderY + productImageSize + 63; // 距离商品标题的间距
ctx.drawImage(loadedImages[4], qrCodeX, qrCodeY, qrCodeSize, qrCodeSize);
// 绘制完成
ctx.draw(false, () => {
// 生成海报图片
uni.canvasToTempFilePath({
canvasId: 'posterCanvas',
width: posterWidth,
height: posterHeight,
success: (res) => {
resolve(res.tempFilePath);
},
fail: (err) => {
reject(err);
}
});
});
}
});
});
},
loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous'; // 允许跨域
img.src = src;
img.onload = () => {
resolve(img);
};
img.onerror = (err) => reject(err);
});
},
share() {
this.$emit('shareH5');
},
getPoster() {
let images = [this.bag, this.giftBorder, this.giftData.image, this.giftData.avatar, this.PromotionCode];
let postImg = ['', '', '', '', ''];
// #ifdef MP
for (let i = 0; i < images.length; i++) {
uni.downloadFile({
url: images[i],
success: (res) => {
if (res.statusCode == 200) {
postImg[i] = res.tempFilePath;
}
const allNotEmpty = postImg.every((item) => item !== '');
if (allNotEmpty) this.goPoster(postImg);
},
fail: function () {
this.$set(this, 'PromotionCode', '');
}
});
}
// #endif
// #ifndef MP
this.goPoster(images);
// #endif
},
goPoster(postImg) {
this.drawPoster(postImg, this.giftData.nickname, this.giftData.title)
.then((posterPath) => {
// #ifdef APP-PLUS || MP
this.savePosterPathMp(posterPath);
// #endif
// #ifdef H5
this.posterImage = posterPath;
this.posterImageStatus = true;
// #endif
})
.catch((err) => {
console.error('海报生成失败:', err);
});
},
// #ifdef APP-PLUS || MP
savePosterPathMp(url) {
let that = this;
uni.saveImageToPhotosAlbum({
filePath: url,
success: function (res) {
that.$util.Tips({
title: '保存成功',
icon: 'success'
});
},
fail: function (res) {
that.$util.Tips({
title: '保存失败'
});
}
});
},
// #endif
savePic(url) {
var a = document.createElement('a'); // 生成一个a元素
a.download = 'Gift'; // 设置图片名称
a.style.display = 'none';
a.href = url; // 将生成的URL设置为a.href属性
document.body.appendChild(a); // 将a标签追加到文档对象中
a.click(); // 触发a的单击事件
a.remove(); // 一次性的用完就删除a标签
}
}
};
</script>
<style lang="scss" scoped>
.aleart {
width: 600rpx;
height: 980rpx;
position: fixed;
left: 50%;
transform: translateX(-50%);
z-index: 200;
top: 50%;
margin-top: -490rpx;
background-color: #fff;
border-radius: 32rpx;
background-size: 100% 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* 动画设置 */
animation: scaleUp 0.3s ease-out;
.poster-img {
width: 100%;
height: 100%;
border-radius: 32rpx;
}
.from {
font-size: 28rpx;
font-weight: 500;
color: #333333;
margin-bottom: 16rpx;
}
.message {
max-width: 70%;
font-weight: 400;
font-size: 26rpx;
color: #999999;
margin-bottom: 42rpx;
}
.aleart-body {
display: flex;
align-items: center;
justify-content: center;
width: 396rpx;
height: 419rpx;
background-image: url('../../static/gift-border.png');
background-size: 100% 100%;
margin-bottom: 32rpx;
.goods-img {
width: 360rpx;
height: 360rpx;
margin-top: 24rpx;
}
}
.title {
max-width: 80%;
font-weight: 400;
font-size: 28rpx;
color: #333333;
margin-bottom: 52rpx;
text-align: center;
}
.btn,
.btn-clear {
width: 396rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 20px;
text-align: center;
font-size: 28rpx;
}
.btn {
color: #fff;
background: linear-gradient(90deg, #ff7931 0%, #e93323 100%);
}
.btn-clear {
margin-top: 20rpx;
color: #e93323;
border: 1px solid #e93323;
}
.keep {
font-size: 24rpx;
font-weight: bold;
color: rgba(255, 255, 255, 0.7);
position: fixed;
right: calc(50% - 130rpx);
bottom: -45rpx;
display: block;
}
.close {
font-size: 50rpx;
color: #fff;
position: fixed;
right: calc(50% - 23rpx);
bottom: -110rpx;
display: block;
}
}
@keyframes scaleUp {
from {
transform: translateX(-50%) scale(0.5);
opacity: 0; /* 可选:淡入效果 */
}
to {
transform: translateX(-50%) scale(1);
opacity: 1;
}
}
</style>

View File

@@ -0,0 +1,101 @@
<template>
<view class="bg--w111-fff rd-16rpx pt-32 pl-24 pr-24 pb-32 flex-between-center">
<view v-for="(item,index) in list" :key="index" class="item">
<view class="h-32 flex-x-center item relative" >
<view class="iconfont fs-32 text--w111-999" :class="index <= indexActive ? 'icon-a-ic_CompleteSelect' : 'icon-ic-complete1'"></view>
<text class="line"
:style="{'width': lineWidth + 'rpx','right': lineRight}"
:class="index < indexActive ? 'bg-color' : ''"
></text>
</view>
<view class="fs-22 text--w111-999 lh-30rpx mt-16" :class="{active:index <= indexActive}">{{item}}</view>
</view>
</view>
</template>
<script>
export default {
props: {
type: {
type: Number,
default: 0
},
applyType: {
type: Number,
default: 0
}
},
data() {
return {}
},
computed: {
list() {
// 步骤条全部选中
if(this.type == -1){
return ['提交申请', '用户已撤销', '退款完成']
}else if(this.type == 3){
return ['提交申请', '商家已拒绝', '退款失败']
} else if(this.type == 6 && this.applyType == 4){
return ['提交申请', '平台强制退款', '退款完成']
}else if([0,6].includes(this.type) && this.applyType == 1){
return ['提交申请', '商家审核', '退款完成']
}else if([0,4,5,6].includes(this.type) && this.applyType == 2){
return ['提交申请', '商家审核','商品寄回', '退款完成']
}else if([0,4,5,6].includes(this.type) && this.applyType == 3){
return ['提交申请', '商家审核','商家收货', '退款完成']
}else {
return ['提交申请', '商家审核', '退款完成']
}
},
indexActive(){
if(this.type == -1){
return 2
}else if(this.type == 3){
return 2
} else if(this.type == 6 && this.applyType == 4){
return 2
}else if(this.applyType == 1){
if([0,1].includes(this.type)){
return 0
}else{
return 2
}
}else if([2,3].includes(this.applyType)){
if(this.type == 0){
return 0
}else if(this.type == 6){
return 3
}else{
return 1
}
}
},
lineWidth(){
if(this.list.length == 4){
return 132
}else{
return 230
}
},
lineRight(){
return '-' + (this.lineWidth - 14) + 'rpx'
}
},
}
</script>
<style lang="scss">
.line{
height:4rpx;
background: #f5f5f5;
position: absolute;
top:16rpx;
}
.item:last-child .line{
display: none;
}
.icon-a-ic_CompleteSelect{
color: var(--view-theme);
}
.active{
color: #333;
}
</style>

View File

@@ -0,0 +1,127 @@
<template>
<view class="modal_container" v-if="visible" @touchmove.stop.prevent>
<view class="modal_box relative">
<view class="h-172 flex-col flex-center">
<view class="fs-32 lh-44rpx fw-500">核销信息</view>
<view class="fs-26 lh-36rpx mt-28" v-if="productType == 4">已核销 {{writeOff}} / 需要核销 {{writeTimes}}</view>
</view>
<view class="mt-52 flex-col flex-center">
<view class="qrcode flex-center">
<view class="qrcode_content">
<!-- #ifdef MP -->
<image :src="qrc" class="image"></image>
<!-- #endif -->
<!-- #ifdef H5 -->
<image v-if="$wechat.isWeixin()" :src="qrc" class="image"></image>
<w-qrcode v-else :options="qrcode"></w-qrcode>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<w-qrcode :options="qrcode"></w-qrcode>
<!-- #endif -->
</view>
</view>
<view class="bg-primary-light qrocode-num rd-16rpx flex-center fs-32 fw-500 font-color mt-48">{{verifyCode}}</view>
<view class="mt-24 text--w111-999 fs-24" v-if="writeDay">核销时间{{writeDay}}</view>
</view>
<text class="iconfont icon-ic_close1 close fs-48 text--w111-fff"></text>
</view>
<view class="mask z-90" @click="closeModal"></view>
</view>
</template>
<script>
export default {
props:{
visible: {
type: Boolean,
default: false,
},
qrcode:{
type:Object,
default: ()=>{}
},
verifyCode:{
type: String,
default:""
},
writeDay:{
type: String,
default:""
},
writeOff:{
type: [String, Number],
default: 0
},
writeTimes:{
type: [String, Number],
default: 0
},
productType:{
type: Number,
default: 0
},
qrc:{
type: String,
default:""
},
},
methods:{
moveHandle(){
return false
},
closeModal(){
this.$emit('closeModal');
}
}
}
</script>
<style>
.modal_box{
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 3000;
width:600rpx;
height:906rpx;
background:#fff;
border-radius:32rpx;
-webkit-mask: radial-gradient(circle at 14rpx 172rpx, transparent 14rpx, red 0) -14rpx;
}
.h-172{
height:172rpx;
border-bottom: 1px dashed #ccc;
}
.z-90{
z-index:2999;
}
.qrcode{
width:440rpx;
height:440rpx;
background-image: url('../../static/qrcode_bg.png');
background-size:100%;
background-repeat: no-repeat;
}
.qrcode_content{
width:360rpx;
height:360rpx;
}
.bg-primary-light{
background: var(--view-minorColorT);
}
.qrocode-num{
width:440rpx;
height:80rpx;
}
.close{
position: absolute;
left:50%;
bottom: -96rpx;
transform: translateX(-50%);
}
.qrcode_content .image {
width: 100%;
height: 100%;
}
</style>