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,86 @@
<template>
<!-- 无缝滚动效果 -->
<view class="marquee-wrap">
<view class="marquee-list" :class="{'animate-up': animateUp}">
<view class="marquee-item" v-for="(item, index) in listData" :key="item.id">
{{ prefix }}<text class="name">{{ item.user ? item.user.nickname : '****' }}</text>获得<text>{{ item.prize.name }}</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: "noticeBar",
data() {
return {
animateUp: false,
listData: JSON.parse(JSON.stringify(this.showMsg)),
timer: null
}
},
props: {
showMsg: {
type: Array
},
prefix: {
type: String
},
},
mounted() {
this.timer = setInterval(this.scrollAnimate, 2500);
},
methods: {
scrollAnimate() {
this.animateUp = true
setTimeout(() => {
this.listData.push(this.listData[0])
this.listData.shift()
this.animateUp = false
}, 500)
}
},
destroyed() {
clearInterval(this.timer)
}
};
</script>
<style lang="scss" scoped>
.marquee-wrap {
width: 100%;
height: 40rpx;
border-radius: 20px;
margin: 0 auto;
overflow: hidden;
.marquee-list {
padding: 0;
.marquee-item {
width: 100%;
height: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding: 0;
list-style: none;
line-height: 40rpx;
// text-align: center;
color: #fff;
font-size: 26rpx;
font-weight: 400;
}
.name {
color: #FFEF6C;
}
}
.animate-up {
transition: all 0.5s ease-in-out;
// transform: translateY(-40rpx);
margin-top: -40rpx;
}
}
</style>

View File

@@ -0,0 +1,258 @@
<template>
<view class="show-box">
<view class="table-title acea-row row-between-wrapper" :style="{
backgroundImage: `url(${imgHost}/statics/images/lottery4.png)`
}">
<view class="text" v-if="showMsg.type === 'user'">
中奖记录
</view>
<view class="text" v-else-if="showMsg.type === 'me'">
我的奖品
</view>
<view class="text" v-else-if="showMsg.type === 'prize'">
活动奖品
</view>
</view>
<view class="table" v-if="['me','user','prize'].includes(showMsg.type)">
<view v-if="showMsg.type=='me'" class="table-head">
<view class="nickname" style="width: 20%;">序号</view>
<view class="table-name time" style="width: 45%;">获奖时间</view>
<view class="table-name" style="width: 35%;">奖品名称</view>
</view>
<view v-if="showMsg.type == 'prize'">
<view class="prize-list acea-row">
<template v-for="(item,index) in showMsg.data">
<view v-if="item.type&&item.type!=1" class="prize-item" :key="item.id">
<view class="prize-item-inner">
<image :src="item.image" class="image"></image>
</view>
<view class="name line1">{{item.name}}</view>
</view>
</template>
</view>
</view>
<view v-else-if="showMsg.type=='user'" class="table-d">
<view class="table-body" v-for="(item,index) in showMsg.data" :key="index">
<view class="table-name time">
{{item.add_time}}
</view>
<view class="nickname">
{{showMsg.type === 'user' ? (item.user?item.user.nickname:'') : index + 1}}
</view>
<view class="table-name">
{{item.prize.name}}
</view>
</view>
</view>
<view v-else class="table-d me">
<view class="table-body acea-row row-middle" v-for="(item,index) in showMsg.data" :key="index">
<view class="nickname" style="width: 20%;">
<view class="inner acea-row row-center-wrapper">{{showMsg.type === 'user' ? (item.user?item.user.nickname:'') : index + 1}}</view>
</view>
<view class="table-name time" style="width: 45%;">
{{item.add_time}}
</view>
<view class="table-name" style="width: 35%;">
{{item.prize.name}}
</view>
</view>
</view>
</view>
<view class="content" v-else v-html="showMsg.data"></view>
</view>
</template>
<script>
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
data() {
return {
imgHost: HTTP_REQUEST_URL,
}
},
props: {
showMsg: {
type: Object
},
},
}
</script>
<style lang="scss" scoped>
.show-box {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
background: linear-gradient(90deg, #FFFEFD 0%, #FFE3E3 100%);
padding: 112rpx 0 48rpx;
border-radius: 24rpx;
+.show-box {
margin-top: 60rpx;
}
}
.table-title {
position: absolute;
top: -24rpx;
height: 108rpx;
padding: 12rpx 104rpx 26rpx;
background-size: 100% 100%;
.text {
color: #FFFFFF;
font-size: 32rpx;
font-weight: 500;
}
image {
width: 50rpx;
height: 16rpx;
}
}
.table-d {
max-height: 200rpx;
overflow-y: scroll;
&.me {
.table-body {
height: 72rpx;
margin: 0 20rpx 32rpx;
background: linear-gradient(90deg, #FEFDFB 0%, #FFD8D8 47%, rgba(255, 228, 228, 0) 100%, rgba(255, 204, 204, 0) 100%, rgba(255, 204, 204, 0) 100%);
.nickname {
width: 30%;
.inner {
width: 40rpx;
height: 40rpx;
border-radius: 20rpx;
margin-left: 12rpx;
background: rgba(255, 71, 71, 0.2);
font-size: 28rpx;
}
}
}
}
}
.table {
width: 100%;
.table-head,
.table-body {
display: flex;
justify-content: space-around;
}
.table-head {
margin: 0 20rpx 32rpx;
font-weight: 500;
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
.nickname {
width: 30%;
padding: 10rpx 20rpx;
}
.table-name {
width: 30%;
text-align: left;
padding: 10rpx 20rpx;
}
.time {
width: 40%;
}
}
.table-body {
color: #333333;
+.table-body {
margin-top: 32rpx;
}
.nickname {
width: 30%;
font-size: 24rpx;
line-height: 34rpx;
padding: 0 20rpx;
}
.table-name {
width: 30%;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 24rpx;
line-height: 34rpx;
padding: 0 20rpx;
}
.time {
width: 40%;
}
}
.prize-list {
padding: 0 24rpx;
margin-right: -23rpx;
}
.prize-item {
position: relative;
padding: 8rpx;
border-radius: 16rpx;
margin: 0 23rpx 32rpx 0;
background: linear-gradient(180deg, #FFB7B7 3%, #FF5E5E 100%);
.name {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50rpx;
padding-top: 14rpx;
border-radius: 0 0 16rpx 16rpx;
background-image: url(data:image/png;base64,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);
background-repeat: no-repeat;
background-size: 100% 100%;
text-align: center;
font-weight: 500;
font-size: 20rpx;
line-height: 28rpx;
color: #FFFFFF;
}
}
.prize-item-inner {
width: 176rpx;
height: 176rpx;
border-radius: 12rpx;
background-color: #FFFFFF;
.image {
display: block;
width: 128rpx;
height: 128rpx;
margin: 0 auto;
object-fit: contain;
}
}
}
.content {
width: 100%;
padding: 0 20rpx;
}
</style>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,180 @@
<template>
<view :style="colorStyle">
<view class="px-20 mt-32">
<view class="bg--w111-fff rd-24rpx p-24 flex-between-center item"
v-for="item in lotteryList" :key="item.id">
<easy-loadimage
:image-src="item.prize.image"
width="136rpx"
height="136rpx"
borderRadius="16rpx"></easy-loadimage>
<view class="flex-1 pl-24 h-136 flex-between-center">
<view class="w-328 h-136 flex-col justify-between">
<view class="w-full h-80 line2">
<text class="label" :class="'label' + item.prize.type">{{item.prize.type | typeName}}</text>
<text class="name">{{item.prize.name}}</text>
</view>
<view class="fs-22 text--w111-999">兑换时间:{{item.receive_time || '--'}}</view>
</view>
<view class="w-120 h-56 rd-30rpx flex-center fs-24 bg-gradient text--w111-fff"
@tap="goDetail(item)" v-if="item.type == 4">{{item.type ==4 && item.wechat_state == 'WAIT_USER_CONFIRM' ? '去领取' : '已领取'}}</view>
<view class="w-120 h-56 rd-30rpx flex-center fs-24 bg-gradient text--w111-fff"
@tap="goDetail(item)" v-else>{{item.is_receive == 0 && item.type == 6 ? '去领取' : '去查看'}}</view>
</view>
</view>
</view>
<view class="px-20 mt-20" v-if="lotteryList.length === 0 && !loading">
<emptyPage title="暂无中奖记录~" src="/statics/images/noOrder.gif"></emptyPage>
</view>
<home></home>
</view>
</template>
<script>
import {getLotteryList} from '@/api/lottery.js';
import { postCartAdd } from '@/api/store.js';
import emptyPage from '@/components/emptyPage.vue'
import colors from '@/mixins/color.js';
export default {
components: {
emptyPage
},
mixins:[colors],
data() {
return {
loading: false,
where: {
page: 1,
limit: 20,
},
lotteryList: [],
loadTitle: ''
}
},
onShow() {
this.lotteryList = [];
this.where.page = 1;
this.loading = false;
this.loadend = false;
this.getLotteryList()
},
filters: {
typeName(type) {
if (type == 2) {
return '积分'
} else if (type == 3) {
return '余额'
} else if (type == 4) {
return '红包'
} else if (type == 5) {
return '优惠券'
} else if (type == 6) {
return '商品'
}
}
},
onPageScroll(object) {
uni.$emit('scroll');
},
methods: {
getLotteryList() {
if (this.loadend) return;
if (this.loading) return;
this.loading = true;
this.loadTitle = '';
getLotteryList(this.where).then(res => {
let list = res.data;
let lotteryList = this.$util.SplitArray(list, this.lotteryList);
let loadend = list.length < this.where.limit;
this.loadend = loadend;
this.loading = false;
this.loadTitle = loadend ? '没有更多内容啦~' : '加载更多';
this.$set(this, 'lotteryList', lotteryList);
this.$set(this.where, 'page', this.where.page + 1);
}).catch(err => {
that.loading = false;
that.loadTitle = '加载更多';
});
},
goDetail(item){
let type = item.type;
if (type == 2) {
uni.navigateTo({
url: '/pages/users/user_integral/index'
})
} else if (type == 3) {
uni.navigateTo({
url: '/pages/users/user_money/index'
})
} else if (type == 4) {
if(item.wechat_state == 'WAIT_USER_CONFIRM'){
uni.navigateTo({
url: '/pages/users/user_spread_money/receiving?type=2&id=' + item.order_id
})
}
} else if (type == 5) {
uni.navigateTo({
url: '/pages/users/user_coupon/index'
})
} else if (type == 6) {
if(item.oid > 0){
uni.navigateTo({
url: `/pages/goods/order_details/index?order_id=${item.oid}`
})
}else{
postCartAdd({
cartNum: 1,
new: 1,
is_new: 1,
productId: item.prize.product_id,
uniqueId: item.prize.unique,
luckRecordId: item.id,
}).then(res => {
uni.navigateTo({
url: `/pages/goods/order_confirm/index?new=1&luckRecordId=${item.id}&cartId=${res.data.cartId}`
});
}).catch(err => {
this.$util.Tips({
title: `${err},请联系客服`
});
});;
}
}
}
},
onReachBottom() {
this.getLotteryList();
}
}
</script>
<style lang="scss" scoped>
.item ~ .item{
margin-top: 20rpx;
}
.item{
.name {
width: 328rpx;
height: 80rpx;
line-height: 40rpx;
color: #333;
font-weight: 500;
font-size: 28rpx;
}
.label {
padding: 0 6rpx;
font-size: 20rpx;
margin-right: 16rpx;
border-radius: 6rpx;
vertical-align: middle;
}
.label2, .label3, .label5{
border: 1rpx solid #FF7D00;
color: #FF7D00;
}
.label4, .label6{
border: 1rpx solid var(--view-theme);
color: var(--view-theme);
}
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long