miao33: 从 main 同步 single_uniapp22miao,dart-sass 兼容修复,DEPLOY.md 更新

- 从 main 获取 single_uniapp22miao 子项目
- dart-sass: /deep/ -> ::v-deep,calc 运算符加空格
- DEPLOY.md 采用 shccd159 版本(4 子项目架构说明)

Made-with: Cursor
This commit is contained in:
apple
2026-03-16 11:16:42 +08:00
parent 9c29721dc4
commit 079076a70e
356 changed files with 569762 additions and 129 deletions

View File

@@ -0,0 +1,70 @@
<template>
<view class="error-page">
<view class="error-content">
<text class="error-icon">404</text>
<text class="error-title">页面不存在</text>
<text class="error-desc">抱歉您访问的页面找不到了</text>
<button class="back-btn" @click="goBack">返回首页</button>
</view>
</view>
</template>
<script>
export default {
methods: {
goBack() {
uni.switchTab({
url: '/pages/index/index'
});
}
}
}
</script>
<style lang="scss" scoped>
.error-page {
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
}
.error-content {
display: flex;
flex-direction: column;
align-items: center;
.error-icon {
font-size: 120rpx;
font-weight: bold;
color: #ccc;
margin-bottom: 40rpx;
}
.error-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.error-desc {
font-size: 26rpx;
color: #999;
margin-bottom: 60rpx;
}
.back-btn {
width: 300rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(90deg, #FF6B6B, #FF4757);
color: #fff;
border-radius: 40rpx;
font-size: 28rpx;
border: none;
}
}
</style>

View File

@@ -0,0 +1,160 @@
<template>
<view class="setting-page">
<!-- 基本设置 -->
<view class="setting-section">
<view class="section-title">基本设置</view>
<view class="setting-list">
<view class="setting-item" @click="goToUserInfo">
<text class="label">个人信息</text>
<text class="arrow"></text>
</view>
<view class="setting-item" @click="goToChangePwd">
<text class="label">修改密码</text>
<text class="arrow"></text>
</view>
</view>
</view>
<!-- 其他设置 -->
<view class="setting-section">
<view class="section-title">其他</view>
<view class="setting-list">
<view class="setting-item" @click="goToAgreement">
<text class="label">用户协议</text>
<text class="arrow"></text>
</view>
<view class="setting-item" @click="goToAbout">
<text class="label">关于我们</text>
<text class="arrow"></text>
</view>
<view class="setting-item" @click="contactService">
<text class="label">联系客服</text>
<text class="arrow"></text>
</view>
</view>
</view>
<!-- 退出登录 -->
<view class="logout-btn-container">
<button class="logout-btn" @click="handleLogout">退出登录</button>
</view>
</view>
</template>
<script>
export default {
methods: {
goToUserInfo() {
uni.navigateTo({
url: '/pages/sub-pages/user-info/index'
});
},
goToChangePwd() {
uni.navigateTo({
url: '/pages/sub-pages/login/change-pwd'
});
},
goToAgreement() {
uni.navigateTo({
url: '/pages/sub-pages/agreement/index'
});
},
goToAbout() {
uni.showToast({
title: '功能开发中',
icon: 'none'
});
},
contactService() {
uni.showToast({
title: '请联系客服',
icon: 'none'
});
},
handleLogout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
uni.removeStorageSync('token');
uni.removeStorageSync('userInfo');
uni.reLaunch({
url: '/pages/sub-pages/login/index'
});
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.setting-page {
min-height: 100vh;
background-color: #f5f5f5;
padding: 20rpx 30rpx;
padding-bottom: 200rpx;
}
.setting-section {
margin-bottom: 30rpx;
.section-title {
font-size: 26rpx;
color: #999;
padding: 0 10rpx 20rpx;
}
}
.setting-list {
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
}
.setting-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1px solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.label {
font-size: 28rpx;
color: #333;
}
.arrow {
font-size: 50rpx;
color: #ccc;
}
}
.logout-btn-container {
margin-top: 60rpx;
}
.logout-btn {
width: 100%;
height: 90rpx;
line-height: 90rpx;
background-color: #fff;
color: #FF4757;
border-radius: 45rpx;
font-size: 32rpx;
border: 2rpx solid #FF4757;
}
</style>

View File

@@ -0,0 +1,462 @@
<template>
<view class="route-test-page">
<view class="header">
<text class="title">路由测试工具</text>
<text class="subtitle">测试所有页面路由是否正常访问</text>
</view>
<view class="info-section">
<view class="info-item">
<text class="label">当前路径:</text>
<text class="value">{{ currentPath }}</text>
</view>
<view class="info-item">
<text class="label">路由模式:</text>
<text class="value">{{ routeMode }}</text>
</view>
<view class="info-item">
<text class="label">页面栈深度:</text>
<text class="value">{{ pageStackDepth }}</text>
</view>
</view>
<view class="section">
<view class="section-title">主包路由测试</view>
<view class="route-list">
<view
v-for="route in mainRoutes"
:key="route.path"
class="route-item"
@click="testRoute(route.path)"
>
<view class="route-name">{{ route.name }}</view>
<view class="route-path">{{ route.path }}</view>
<view class="route-status" :class="route.tested ? 'tested' : ''">
{{ route.tested ? '✓ 已测试' : '未测试' }}
</view>
</view>
</view>
</view>
<view class="section">
<view class="section-title">分包路由测试</view>
<view class="route-list">
<view
v-for="route in subRoutes"
:key="route.path"
class="route-item"
@click="testRoute(route.path)"
>
<view class="route-name">{{ route.name }}</view>
<view class="route-path">{{ route.path }}</view>
<view class="route-status" :class="route.tested ? 'tested' : ''">
{{ route.tested ? '✓ 已测试' : '未测试' }}
</view>
</view>
</view>
</view>
<view class="section">
<view class="section-title">路由别名测试</view>
<view class="alias-list">
<view
v-for="(realPath, alias) in routeAlias"
:key="alias"
class="alias-item"
@click="testAlias(alias)"
>
<view class="alias-name">{{ alias }}</view>
<view class="alias-arrow"></view>
<view class="alias-path">{{ realPath }}</view>
</view>
</view>
</view>
<view class="actions">
<button class="btn btn-primary" @click="testAllRoutes">测试所有路由</button>
<button class="btn btn-secondary" @click="clearTestResults">清除测试结果</button>
<button class="btn btn-back" @click="goBack">返回</button>
</view>
</view>
</template>
<script>
import { Navigation, routeAlias } from '@/utils/navigation.js'
export default {
data() {
return {
currentPath: '',
routeMode: 'history',
pageStackDepth: 0,
routeAlias: routeAlias,
mainRoutes: [
{ name: '首页', path: '/pages/index/index', tested: false },
{ name: '我的', path: '/pages/personal/index', tested: false },
{ name: '采购', path: '/pages/rushing/index', tested: false },
{ name: '采购列表', path: '/pages/rushing/detail', tested: false },
],
subRoutes: [
{ name: '登录', path: '/pages/sub-pages/login/index', tested: false },
{ name: '注册', path: '/pages/sub-pages/login/register', tested: false },
{ name: '重置密码', path: '/pages/sub-pages/login/reset-account', tested: false },
{ name: '修改密码', path: '/pages/sub-pages/login/change-pwd', tested: false },
{ name: '签名', path: '/pages/sub-pages/webview/sign', tested: false },
{ name: '签名预览', path: '/pages/sub-pages/webview/sign-preview', tested: false },
{ name: '采购订单', path: '/pages/sub-pages/rushing-order/index', tested: false },
{ name: '订单详情', path: '/pages/sub-pages/rushing-order/detail', tested: false },
{ name: '用户信息', path: '/pages/sub-pages/user-info/index', tested: false },
{ name: '地址管理', path: '/pages/sub-pages/address/index', tested: false },
{ name: '地址详情', path: '/pages/sub-pages/address/detail', tested: false },
{ name: '商品详情', path: '/pages/sub-pages/good/good-detail', tested: false },
{ name: '搜索', path: '/pages/sub-pages/search/index', tested: false },
{ name: '余额', path: '/pages/sub-pages/balance/index', tested: false },
{ name: '优惠券', path: '/pages/sub-pages/coupon/index', tested: false },
{ name: '提现', path: '/pages/sub-pages/withdraw/index', tested: false },
{ name: '提现记录', path: '/pages/sub-pages/withdraw/list', tested: false },
{ name: '我的奖金', path: '/pages/sub-pages/prize/index', tested: false },
{ name: '邀请好友', path: '/pages/sub-pages/invite/index', tested: false },
{ name: '收款方式', path: '/pages/sub-pages/my-payee/index', tested: false },
{ name: '支付宝', path: '/pages/sub-pages/my-payee/zfb-detail', tested: false },
{ name: '银行卡', path: '/pages/sub-pages/my-payee/yl-detail', tested: false },
{ name: '我的粉丝', path: '/pages/sub-pages/my-fans/index', tested: false },
{ name: '推广奖金', path: '/pages/sub-pages/promote-prize/index', tested: false },
{ name: '协议', path: '/pages/sub-pages/agreement/index', tested: false },
{ name: '合同', path: '/pages/sub-pages/agreement/contract', tested: false },
{ name: '合同1', path: '/pages/sub-pages/agreement/contract1', tested: false },
{ name: '我的合同', path: '/pages/sub-pages/agreement/my-contract', tested: false },
{ name: '设置', path: '/pages/sub-pages/setting/index', tested: false },
]
}
},
onLoad() {
this.updateRouteInfo()
},
onShow() {
this.updateRouteInfo()
},
methods: {
updateRouteInfo() {
this.currentPath = Navigation.getCurrentPath()
this.pageStackDepth = Navigation.getPages().length
// #ifdef H5
this.routeMode = 'history'
// #endif
// #ifndef H5
this.routeMode = 'native'
// #endif
},
async testRoute(path) {
try {
await Navigation.push(path)
// 标记为已测试
const route = [...this.mainRoutes, ...this.subRoutes].find(r => r.path === path)
if (route) {
route.tested = true
}
// 保存测试结果到本地存储
this.saveTestResults()
uni.showToast({
title: '路由测试成功',
icon: 'success'
})
} catch (error) {
console.error('路由测试失败:', error)
uni.showToast({
title: '路由测试失败',
icon: 'none'
})
}
},
async testAlias(alias) {
uni.showLoading({
title: '测试中...'
})
try {
await Navigation.push(alias)
uni.hideLoading()
uni.showToast({
title: '别名测试成功',
icon: 'success'
})
} catch (error) {
uni.hideLoading()
console.error('别名测试失败:', error)
uni.showToast({
title: '别名测试失败',
icon: 'none'
})
}
},
async testAllRoutes() {
uni.showModal({
title: '提示',
content: '这将依次测试所有路由,可能需要一些时间',
success: async (res) => {
if (res.confirm) {
uni.showLoading({
title: '测试中...'
})
let successCount = 0
let failCount = 0
const allRoutes = [...this.mainRoutes, ...this.subRoutes]
for (const route of allRoutes) {
try {
// 这里只是标记,不实际跳转
route.tested = true
successCount++
await new Promise(resolve => setTimeout(resolve, 100))
} catch (error) {
failCount++
}
}
uni.hideLoading()
this.saveTestResults()
uni.showModal({
title: '测试完成',
content: `成功: ${successCount}, 失败: ${failCount}`,
showCancel: false
})
}
}
})
},
clearTestResults() {
this.mainRoutes.forEach(route => route.tested = false)
this.subRoutes.forEach(route => route.tested = false)
uni.removeStorageSync('route_test_results')
uni.showToast({
title: '已清除测试结果',
icon: 'success'
})
},
saveTestResults() {
const results = {
mainRoutes: this.mainRoutes,
subRoutes: this.subRoutes,
timestamp: Date.now()
}
uni.setStorageSync('route_test_results', results)
},
loadTestResults() {
try {
const results = uni.getStorageSync('route_test_results')
if (results) {
this.mainRoutes = results.mainRoutes
this.subRoutes = results.subRoutes
}
} catch (error) {
console.error('加载测试结果失败:', error)
}
},
goBack() {
Navigation.back()
}
},
mounted() {
this.loadTestResults()
}
}
</script>
<style lang="scss" scoped>
.route-test-page {
min-height: 100vh;
background-color: #f5f5f5;
padding: 20rpx;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 40rpx 30rpx;
border-radius: 16rpx;
margin-bottom: 20rpx;
.title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #FFFFFF;
margin-bottom: 10rpx;
}
.subtitle {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
}
.info-section {
background-color: #FFFFFF;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #F0F0F0;
&:last-child {
border-bottom: none;
}
.label {
font-size: 28rpx;
color: #666666;
}
.value {
font-size: 28rpx;
color: #333333;
font-weight: 500;
}
}
}
.section {
background-color: #FFFFFF;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
margin-bottom: 20rpx;
}
}
.route-list {
.route-item {
padding: 20rpx;
background-color: #F8F8F8;
border-radius: 12rpx;
margin-bottom: 15rpx;
&:active {
background-color: #E8E8E8;
}
.route-name {
font-size: 30rpx;
color: #333333;
font-weight: 500;
margin-bottom: 8rpx;
}
.route-path {
font-size: 24rpx;
color: #999999;
font-family: monospace;
margin-bottom: 8rpx;
}
.route-status {
font-size: 24rpx;
color: #999999;
&.tested {
color: #52c41a;
font-weight: 500;
}
}
}
}
.alias-list {
.alias-item {
display: flex;
align-items: center;
padding: 20rpx;
background-color: #F8F8F8;
border-radius: 12rpx;
margin-bottom: 15rpx;
&:active {
background-color: #E8E8E8;
}
.alias-name {
font-size: 28rpx;
color: #1890ff;
font-weight: 500;
font-family: monospace;
}
.alias-arrow {
font-size: 28rpx;
color: #999999;
margin: 0 15rpx;
}
.alias-path {
flex: 1;
font-size: 24rpx;
color: #666666;
font-family: monospace;
}
}
}
.actions {
padding: 30rpx;
.btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
border-radius: 12rpx;
font-size: 32rpx;
border: none;
margin-bottom: 20rpx;
&.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #FFFFFF;
}
&.btn-secondary {
background-color: #F0F0F0;
color: #666666;
}
&.btn-back {
background-color: #FFFFFF;
color: #333333;
border: 2rpx solid #E0E0E0;
}
}
}
</style>