refactor: 移动端升级 Vue3 + uView Plus

将 lilishop-uniapp 从 Vue2/uView 1.6 迁移到 Vue3/uview-plus,优先支持 H5/微商城与微信小程序;移除 vendored uview-ui,改用 npm 依赖、Vuex4 与迁移脚本/补丁,并补充 VUE3_MIGRATION.md 回归清单。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pikachu1995@126.com
2026-06-30 18:50:38 +08:00
parent c290c7a329
commit dc2bef455a
299 changed files with 5507 additions and 43811 deletions

View File

@@ -7,7 +7,7 @@
display: flex;
}
.item-price {
> span {
.price-text {
font-size: 15px;
font-weight: 500;
color: #e1212b;
@@ -26,7 +26,7 @@
position: relative;
}
.item-line-through {
> span {
.price-text {
font-size: 10px;
font-weight: 400;
text-decoration: line-through;
@@ -46,12 +46,12 @@
align-items: center;
background: #fff;
height: 50px;
> div:nth-of-type(1) {
.join-title-name {
font-size: 16px;
font-weight: bold;
}
> div:nth-of-type(2) {
.join-title-more {
font-size: 12px;
color: #999;
}
}
}

View File

@@ -1,6 +1,6 @@
<template>
<div>
<u-popup v-model="enableShowCoupon" mode="center" width="550rpx" height="400px">
<u-popup v-model:show="enableShowCoupon" mode="center" width="550rpx" height="400px">
<view style="height: 130rpx">
<view
style="
@@ -32,14 +32,13 @@
>{{ item.discount }}</view
>
<view v-else
>优惠金额<span style="color: red; font-size: 32rpx">{{
item.price | unitPrice
>优惠金额<span style="color: red; font-size: 32rpx">{{unitPrice(item.price)
}}</span
></view
>
<view
><span style="color: red; font-size: 32rpx"
>{{ item.consumeThreshold | unitPrice }}</span
>{{unitPrice(item.consumeThreshold) }}</span
>可用</view
>
<view v-if="item.scopeType == 'ALL' && item.storeId == '0'"
@@ -100,7 +99,7 @@ export default {
},
methods: {
firstGetAuto() {
if(!this.$options.filters.isLogin('auth')) return false
if(!this.isLogin('auth')) return false
let data = new Date();
let now = data.getDate();
let hours = data.getHours();

View File

@@ -4,8 +4,11 @@
display: block;
padding: 2rpx;
}
// 首页楼层模块统一左右边距(轮播图、宫格等 .layout 容器)
$home-layout-padding: 16rpx;
.layout {
padding: 16rpx;
padding: $home-layout-padding;
margin: 8rpx 0;
background: #fff;
}

View File

@@ -1,11 +1,23 @@
<template>
<div class="layout">
<div class="box">
<u-swiper @click="clickSwiper" interval="5000" duration="500" height="350" v-if="res" name="img" :list="res.list">
<u-loading slot="loading"></u-loading>
<view class="layout">
<view class="banner-box">
<u-swiper
v-if="res && res.list && res.list.length"
class="home-banner-swiper"
:list="res.list"
keyName="img"
height="350rpx"
imgMode="scaleToFill"
interval="5000"
duration="500"
circular
indicator
@click="clickSwiper"
>
<template #loading><u-loading></u-loading></template>
</u-swiper>
</div>
</div>
</view>
</view>
</template>
<script>
@@ -16,7 +28,7 @@ export default {
watch: {
res: {
handler(newValue, oldValue) {
this.$set(this, "res", newValue);
this["res"] = newValue;
},
deep: true,
},
@@ -34,4 +46,25 @@ export default {
</script>
<style lang="scss" scoped>
@import "./tpl.scss";
.banner-box {
width: 100%;
overflow: hidden;
}
:deep(.home-banner-swiper),
:deep(.u-swiper),
:deep(.u-swiper__wrapper) {
width: 100%;
}
:deep(.u-swiper__wrapper__item),
:deep(.u-swiper__wrapper__item__wrapper) {
width: 100%;
}
:deep(.u-swiper__wrapper__item__wrapper__image) {
width: 100% !important;
display: block;
}
</style>

View File

@@ -2,7 +2,7 @@
<template>
<div class="layout">
<u-image width="140rpx" mode="aspectFit" height="140rpx" @click="modelNavigateTo(item)" class="image-mode" v-for="(item,index) in res.list" :key="index" :src="item.img" alt="">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</template>

View File

@@ -2,7 +2,7 @@
<template>
<div class="layout">
<u-image height="175rpx" mode="aspectFit" width="175rpx" @click="modelNavigateTo(item)" class="image-mode" :src="item.img" v-for="(item,index) in res.list" :key="index">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</template>
@@ -29,7 +29,4 @@ export default {
justify-content: center;
background-size: cover;
}
img {
width: 84px;
}
</style>

View File

@@ -29,9 +29,5 @@ export default {
width: 100%;
display: block;
overflow: hidden;
> img {
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -2,7 +2,7 @@
<template>
<div class="layout">
<u-image @click="modelNavigateTo(item)" height="240rpx" width="240rpx" class="image-mode" :src="item.img" v-for="(item, index) in res.list" :key="index">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</template>
@@ -33,7 +33,4 @@ export default {
justify-content: center;
background-size: cover;
}
img {
width: 111px;
}
</style>

View File

@@ -3,23 +3,21 @@
<div class="flex-two">
<div class="flex-item" @click="modelNavigateTo(res.list[0])">
<u-image height="250rpx" width="100%" mode="scaleToFill" :src="res.list[0].img" alt>
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="flex-item" @click="modelNavigateTo(res.list[1])">
<u-image height="250rpx" width="100%" mode="scaleToFill" :src="res.list[1].img" alt>
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>
</div>
</template>
<script>
import uImage from "@/uview-ui/components/u-image/u-image.vue";
import { modelNavigateTo } from "./tpl";
export default {
components: { uImage },
title: "两张横图",
title: "两张横图",
props: ["res"],
mounted() {
@@ -40,10 +38,5 @@ export default {
}
.flex-item {
width: 50%;
> img {
display: block;
max-width: 100%;
height: 100%;
}
}
</style>

View File

@@ -10,76 +10,79 @@
:key="index"
>
<h4 class="h4">{{ title.title }}</h4>
<div>{{ title.desc }}</div>
<div class="title-desc">{{ title.desc }}</div>
</div>
</div>
</u-sticky>
<div class="goods-list">
<div
v-if="
item.___index != undefined
? selected.index == item.___index
: selected.val == item.type
"
@click="handleClick(item)"
class="goods-item"
v-for="(item, item_index) in res.list[0].listWay"
:key="item_index"
>
<div class="goods-img">
<u-image
:src="item.img"
height="350rpx"
mode="aspectFit"
width="100%"
>
<u-loading slot="loading"></u-loading>
</u-image>
</div>
<div class="goods-desc">
<div class="goods-title">
{{ item.title }}
<template v-for="(item, item_index) in res.list[0].listWay" :key="item_index">
<div
v-if="
item.___index != undefined
? selected.index == item.___index
: selected.val == item.type
"
@click="handleClick(item)"
class="goods-item"
>
<div class="goods-img">
<u-image
:src="item.img"
height="350rpx"
mode="aspectFit"
width="100%"
>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="goods-bottom">
<div class="goods-price">
¥<span
>{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
>.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
<div class="goods-desc">
<div class="goods-title">
{{ item.title }}
</div>
<div class="goods-bottom">
<div class="goods-price">
¥<span class="price-int"
>{{ goodsFormatPrice(item.price)[0] }} </span
>.{{ goodsFormatPrice(item.price)[1] }}
</div>
</div>
</div>
</div>
</div>
</template>
<div
<template
v-if="res.list[0].titleWay[selected.index].bindCategory && goodsData.length"
v-for="(item, index) in goodsData"
:key="index"
class="goods-item"
@click="handleClick(item)"
>
<div class="goods-img">
<u-image
:src="item.thumbnail"
height="350rpx"
mode="aspectFit"
width="100%"
>
<u-loading slot="loading"></u-loading>
</u-image>
</div>
<div class="goods-desc">
<div class="goods-title">
{{ item.goodsName }}
<div
v-for="(item, index) in goodsData"
:key="index"
class="goods-item"
@click="handleClick(item)"
>
<div class="goods-img">
<u-image
:src="item.thumbnail"
height="350rpx"
mode="aspectFit"
width="100%"
>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="goods-bottom">
<div class="goods-price">
¥<span
>{{ $options.filters.goodsFormatPrice(item.price)[0] }} </span
>.{{ $options.filters.goodsFormatPrice(item.price)[1] }}
<div class="goods-desc">
<div class="goods-title">
{{ item.goodsName }}
</div>
<div class="goods-bottom">
<div class="goods-price">
¥<span class="price-int"
>{{ goodsFormatPrice(item.price)[0] }} </span
>.{{ goodsFormatPrice(item.price)[1] }}
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</template>
@@ -170,12 +173,12 @@ $w_94: 94%;
}
.selected-title {
> h4 {
.h4 {
font-size: 30rpx;
color: #000 !important;
}
> div {
.title-desc {
font-weight: bold;
color: $main-color !important;
}
@@ -191,11 +194,11 @@ $w_94: 94%;
flex: 1;
text-align: center;
> h4 {
.h4 {
font-size: 32rpx;
}
> div {
.title-desc {
color: #999;
font-size: 24rpx;
}
@@ -223,10 +226,6 @@ $w_94: 94%;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
overflow: hidden;
> img {
width: 100%;
height: 100%;
}
}
.goods-desc {
@@ -252,7 +251,7 @@ $w_94: 94%;
> .goods-price {
line-height: 2;
color: $main-color;
> span {
.price-int {
font-size: 42rpx;
}
}

View File

@@ -2,8 +2,8 @@
<div class="layout">
<div class="join-list">
<div class="join-title">
<div>{{ res.list[0].title }}</div>
<div>更多</div>
<div class="join-title-name">{{ res.list[0].title }}</div>
<div class="join-title-more">更多</div>
</div>
<div class="join-box">
<div class="join-item" @click="modelNavigateTo(item)" v-for="item in 4" :key="item">
@@ -11,10 +11,10 @@
<img class="item-img" src="https://picsum.photos/id/268/200/200" alt />
</div>
<div class="item-price">
<span>120.00</span>
<span class="price-text">120.00</span>
</div>
<div class="item-line-through">
<span>190.00</span>
<span class="price-text">190.00</span>
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
<template>
<div class="layout">
<div class="flex-one hot-image">
<image mode="widthFix" :src="res.list[0].img" alt=""></image>
<image class="hot-image-main" mode="widthFix" :src="res.list[0].img" alt=""></image>
<image
v-for="(area, index) in res.list[0].zoneInfo"
@@ -47,11 +47,9 @@ export default {
width: 100%;
display: block;
overflow: hidden;
image {
width: 100%;
min-height: 200rpx;
// height: 100%;
}
}
.hot-image-main {
width: 100%;
min-height: 200rpx;
}
</style>

View File

@@ -2,8 +2,8 @@
<div class="layout">
<div class="join-list">
<div class="join-title">
<div>{{ res.list[0].title }}</div>
<div>更多</div>
<div class="join-title-name">{{ res.list[0].title }}</div>
<div class="join-title-more">更多</div>
</div>
<div class="join-box">
<div class="join-item" v-for="item in 4" :key="item">
@@ -11,10 +11,10 @@
<img class="item-img" src="https://picsum.photos/id/268/200/200" alt />
</div>
<div class="item-price">
<span>20积分</span>
<span class="price-text">20积分</span>
</div>
<div class="item-line-through">
<span>30积分</span>
<span class="price-text">30积分</span>
</div>
</div>
</div>
@@ -34,7 +34,7 @@ export default {
display: flex;
}
.item-price {
> span {
.price-text {
font-size: 15px;
font-weight: 500;
color: #e1212b;
@@ -53,7 +53,7 @@ export default {
position: relative;
}
.item-line-through {
> span {
.price-text {
font-size: 10px;
font-weight: 400;
text-decoration: line-through;
@@ -73,11 +73,11 @@ export default {
align-items: center;
background: #fff;
height: 50px;
> div:nth-of-type(1) {
.join-title-name {
font-size: 16px;
font-weight: bold;
}
> div:nth-of-type(2) {
.join-title-more {
font-size: 12px;
color: #999;
}

View File

@@ -2,8 +2,8 @@
<div class="layout">
<div class="join-list">
<div class="join-title">
<div>{{ res.list[0].title }}</div>
<div>更多</div>
<div class="join-title-name">{{ res.list[0].title }}</div>
<div class="join-title-more">更多</div>
</div>
<div class="join-box">
<div class="join-item" v-for="item in 4" :key="item">
@@ -16,10 +16,10 @@
<div class="item-position-tips">2人团</div>
</div>
<div class="item-price">
<span>120.00</span>
<span class="price-text">120.00</span>
</div>
<div class="item-line-through">
<span>120.00</span>
<span class="price-text">120.00</span>
</div>
</div>
</div>
@@ -39,7 +39,7 @@ export default {
display: flex;
}
.item-price {
> span {
.price-text {
font-size: 15px;
font-weight: 500;
color: #e1212b;
@@ -58,7 +58,7 @@ export default {
position: relative;
}
.item-line-through {
> span {
.price-text {
font-size: 10px;
font-weight: 400;
text-decoration: line-through;
@@ -78,11 +78,11 @@ export default {
align-items: center;
background: #fff;
height: 50px;
> div:nth-of-type(1) {
.join-title-name {
font-size: 16px;
font-weight: bold;
}
> div:nth-of-type(2) {
.join-title-more {
font-size: 12px;
color: #999;
}

View File

@@ -3,18 +3,18 @@
<div class="layout">
<div class="view-height-150" @click="modelNavigateTo(res.list[0])">
<u-image width="100%" height="340rpx" class="image-mode" :src="res.list[0].img">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-150">
<div class="view-height-75" @click="modelNavigateTo(res.list[1])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[1].img" alt>
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-75" @click="modelNavigateTo(res.list[2])">
<u-image width="100%" height="170rpx" class="image-mode" :src="res.list[2].img" alt>
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>

View File

@@ -1,26 +1,26 @@
<template>
<div class="layout">
<div class="menu-list">
<div
<view class="layout">
<view class="menu-list">
<view
class="menu-item"
@click="modelNavigateTo(item)"
v-for="(item, index) in res.list"
:key="index"
>
<div>
<view class="menu-img-wrap">
<u-image
width="88rpx"
height="88rpx"
class="menu-img"
:src="item.img"
>
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="menu-title">{{ item.title }}</div>
</div>
</div>
</div>
</view>
<view class="menu-title">{{ item.title }}</view>
</view>
</view>
</view>
</template>
<script>
import { modelNavigateTo } from "./tpl";
@@ -38,24 +38,45 @@ export default {
@import "./tpl.scss";
.menu-list {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
align-items: flex-start;
> .menu-item {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
width: 20%;
// flex: 1;
flex: 0 0 20%;
box-sizing: border-box;
margin: 20rpx 0;
padding: 0 4rpx;
}
}
.menu-img {
display: flex;
margin: 0 auto;
.menu-img-wrap {
width: 88rpx;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
}
.menu-img {
flex-shrink: 0;
}
:deep(.menu-img .u-image) {
display: flex;
align-items: center;
justify-content: center;
}
.menu-title {
margin-top: 8rpx;
font-size: 24rpx;
line-height: 1.3;
width: 100%;
text-align: center;
}
</style>

View File

@@ -9,7 +9,7 @@
>
<div>
<div class="join-title">
<div>{{ item.title }}</div>
<div class="join-title-name">{{ item.title }}</div>
<div
class="sub"
v-if="item.type !== 'SECKILL'"
@@ -54,7 +54,7 @@
{{ i.goodsName ? i.goodsName : i.name }}
</div>
<div class="item-price">
<span>{{ i.price ? i.price : i.originalPrice }}</span>
<span class="price-text">{{ i.price ? i.price : i.originalPrice }}</span>
</div>
</div>
</div>
@@ -195,7 +195,7 @@ export default {
width: 316rpx !important;
}
.item-price {
> span {
.price-text {
font-size: 28rpx;
font-weight: 500;
color: #e1212b;
@@ -214,7 +214,7 @@ export default {
position: relative;
}
.item-line-through {
> span {
.price-text {
font-size: 20rpx;
font-weight: 400;
text-decoration: line-through;
@@ -234,11 +234,12 @@ export default {
align-items: center;
background: #fff;
height: 100rpx;
> div:nth-of-type(1) {
.join-title-name {
font-size: 30rpx;
font-weight: bold;
}
> div:nth-of-type(2) {
.sub,
.sub-seckill {
font-size: 20rpx;
line-height: 1.75;
border-radius: 16rpx;

View File

@@ -1,25 +1,16 @@
<template>
<div class="layout">
<div class="search" @click="handleSearch">
<view class="layout">
<view class="search" @click="handleSearch">
<u-icon name="search"></u-icon>
{{ res.list[0].title }}
</div>
<div slot="right" open-type="contact" class="navbar-right message" @click="linkMsgDetail" style="border-style:none;background:rgb(234,234,234);" >
<image style="width:53rpx;height:53rpx;margin-top:6rpx;" src="@/static/img/title.png"></image>
</div>
</div>
<text class="search-text">{{ res.list[0].title }}</text>
</view>
</view>
</template>
<script>
export default {
title:"搜索栏",
props: ["res","storeId"],
methods: {
linkMsgDetail(){
uni.navigateTo({
url:`/pages/tabbar/home/title`
})
},
handleSearch() {
if(this.storeId){
uni.navigateTo({
@@ -39,25 +30,33 @@ export default {
@import "./tpl.scss";
.search {
width: 100%;
height: 64rpx;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-start;
padding: 0 10rpx;
background: #ededed;
color: #999;
overflow: hidden;
box-sizing: border-box;
}
.search-text {
margin-left: 12rpx;
font-size: 26rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.layout {
background: #fff;
padding: 0 16rpx;
position: relative;
}
.navbar-right{
position: absolute;
top: 0;
// right: 0;
}
.message{
right:40rpx;
display: flex;
align-items: center;
width: 100%;
background: transparent;
padding: 0;
box-sizing: border-box;
}
</style>

View File

@@ -2,8 +2,8 @@
<div class="layout">
<div class="join-list">
<div class="join-title">
<div>{{ res.list[0].title }}</div>
<div>更多</div>
<div class="join-title-name">{{ res.list[0].title }}</div>
<div class="join-title-more">更多</div>
</div>
<div class="join-box">
<div class="join-item" v-for="item in 4" :key="item">
@@ -15,10 +15,10 @@
/>
</div>
<div class="item-price">
<span>120.00</span>
<span class="price-text">120.00</span>
</div>
<div class="item-line-through">
<span>190.00</span>
<span class="price-text">190.00</span>
</div>
</div>
</div>

View File

@@ -58,13 +58,8 @@ export default {
background-size: cover;
padding: 0;
}
.-item-image{
padding: 10px ;
>img{
width: 100%;
}
.-item-image {
padding: 10px;
}
.-item-tilte {
background: $aider-light-color;

View File

@@ -3,18 +3,18 @@
<div class="layout">
<div class="view-width-100" @click="modelNavigateTo(res.list[0])">
<u-image class="image-mode" width="100%" height="200rpx" :src="res.list[0].img">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-width-100" @click="modelNavigateTo(res.list[1])">
<div class="view-height-85">
<u-image class="image-mode" width="100%" height="170rpx" :src="res.list[1].img">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-85" @click="modelNavigateTo(res.list[2])">
<u-image class="image-mode" width="100%" height="170rpx" :src="res.list[2].img">
<u-loading slot="loading"></u-loading>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>
@@ -53,18 +53,10 @@ export default {
display: flex;
height: 200rpx;
width: 100%;
> img {
width: 100%;
height: 100%;
}
}
.view-height-85 {
padding: 0 1px;
width: 50%;
> img {
width: 100%;
height: 100%;
}
}
.image-mode{
width: 100%;

View File

@@ -8,8 +8,9 @@
width="100%"
:src="res.list[0].img"
alt
><u-loading slot="loading"></u-loading
></u-image>
>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
<div class="view-height-85" @click="modelNavigateTo(res.list[1])">
<u-image
@@ -18,8 +19,9 @@
width="100%"
:src="res.list[1].img"
alt
><u-loading slot="loading"></u-loading
></u-image>
>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>
<div class="view-width-100" @click="modelNavigateTo(res.list[2])">
@@ -28,8 +30,9 @@
height="200rpx"
width="100%"
:src="res.list[2].img"
><u-loading slot="loading"></u-loading
></u-image>
>
<template #loading><u-loading></u-loading></template>
</u-image>
</div>
</div>
</template>