企业信息补全页面开发
This commit is contained in:
@@ -1,442 +0,0 @@
|
||||
# HBuilderX小程序编译错误解决方案
|
||||
|
||||
## 错误信息
|
||||
|
||||
```
|
||||
[vite]: Rollup failed to resolve import "@dcloudio/uni-ui/lib/uni-button/uni-button.vue" from "components/MsgTips/MsgTips.vue".
|
||||
|
||||
[@vue/compiler-sfc] `defineExpose` is a compiler macro and no longer needs to be imported.
|
||||
[@vue/compiler-sfc] `defineProps` is a compiler macro and no longer needs to be imported.
|
||||
[@vue/compiler-sfc] `defineEmits` is a compiler macro and no longer needs to be imported.
|
||||
```
|
||||
|
||||
## 问题分析
|
||||
|
||||
### 问题1:uni-button 组件未安装
|
||||
|
||||
**原因:**
|
||||
- `uni-button` 不是 uni-app 的内置组件
|
||||
- 项目中使用了 `<uni-button>` 但没有安装 `@dcloudio/uni-ui` 完整包
|
||||
- 只安装了部分组件(uni-popup、uni-icons等)
|
||||
|
||||
**解决方案:**
|
||||
使用原生 `<button>` 替代 `<uni-button>`
|
||||
|
||||
### 问题2:Vue编译器宏错误导入
|
||||
|
||||
**原因:**
|
||||
- `defineProps`、`defineEmits`、`defineExpose` 是 Vue 3 的编译器宏
|
||||
- 它们由编译器自动注入,不需要从 vue 中导入
|
||||
- 在 `<script setup>` 中可以直接使用
|
||||
|
||||
**错误写法:**
|
||||
```javascript
|
||||
import { defineProps, defineEmits, defineExpose } from 'vue'
|
||||
```
|
||||
|
||||
**正确写法:**
|
||||
```javascript
|
||||
// 无需导入,直接使用
|
||||
const props = defineProps({...})
|
||||
const emit = defineEmits([...])
|
||||
defineExpose({...})
|
||||
```
|
||||
|
||||
## ✅ 已修复的文件
|
||||
|
||||
### 1. components/MsgTips/MsgTips.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 将 `<uni-button>` 替换为 `<button>`
|
||||
- ✅ 添加了 button 样式重置
|
||||
|
||||
**修改前:**
|
||||
```vue
|
||||
<uni-button class="popup-button" @click="close">确定</uni-button>
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```vue
|
||||
<button class="popup-button" @click="close">确定</button>
|
||||
```
|
||||
|
||||
**样式重置:**
|
||||
```scss
|
||||
button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. pages/chat/components/ai-paging.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 移除 `defineProps` 和 `defineEmits` 的导入
|
||||
|
||||
**修改前:**
|
||||
```javascript
|
||||
import {
|
||||
ref,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
// ...
|
||||
} from 'vue';
|
||||
```
|
||||
|
||||
**修改后:**
|
||||
```javascript
|
||||
import {
|
||||
ref,
|
||||
// 移除了 defineProps 和 defineEmits
|
||||
// ...
|
||||
} from 'vue';
|
||||
```
|
||||
|
||||
### 3. components/tabbar/midell-box.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 移除 `defineProps` 的导入
|
||||
|
||||
### 4. pages/chat/components/popupbadFeeback.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 移除 `defineEmits` 的导入
|
||||
|
||||
### 5. components/selectJobs/selectJobs.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 移除 `defineExpose` 的导入
|
||||
|
||||
### 6. components/renderJobs/renderJobsCheckBox.vue
|
||||
|
||||
**修改内容:**
|
||||
- ✅ 移除 `defineExpose` 的导入
|
||||
|
||||
## 📋 Vue 3 Composition API 编译器宏
|
||||
|
||||
### 什么是编译器宏?
|
||||
|
||||
编译器宏是 Vue 3 在 `<script setup>` 中提供的特殊函数,由编译器在编译时处理,不是运行时的函数。
|
||||
|
||||
### 常用编译器宏
|
||||
|
||||
| 宏名称 | 作用 | 是否需要导入 |
|
||||
|--------|------|------------|
|
||||
| `defineProps` | 定义组件 props | ❌ 不需要 |
|
||||
| `defineEmits` | 定义组件事件 | ❌ 不需要 |
|
||||
| `defineExpose` | 暴露组件方法/属性 | ❌ 不需要 |
|
||||
| `withDefaults` | 为 props 设置默认值 | ❌ 不需要 |
|
||||
| `defineOptions` | 定义组件选项 | ❌ 不需要 |
|
||||
| `defineSlots` | 定义插槽类型 | ❌ 不需要 |
|
||||
| `defineModel` | 定义 v-model | ❌ 不需要 |
|
||||
|
||||
### 正确使用示例
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// ✅ 正确:直接使用,无需导入
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
age: Number
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update', 'change'])
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
})
|
||||
|
||||
// ❌ 错误:不要从 vue 导入
|
||||
// import { defineProps } from 'vue'
|
||||
</script>
|
||||
```
|
||||
|
||||
## 🔧 替代方案
|
||||
|
||||
### 如果确实需要 uni-ui
|
||||
|
||||
如果项目中大量使用了 uni-ui 组件,可以安装完整的 uni-ui:
|
||||
|
||||
```bash
|
||||
npm install @dcloudio/uni-ui
|
||||
```
|
||||
|
||||
然后在 `pages.json` 中配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 使用原生组件的优势
|
||||
|
||||
1. ✅ **更小的包体积** - 不需要引入额外的库
|
||||
2. ✅ **更好的兼容性** - 原生组件在所有平台都可用
|
||||
3. ✅ **更快的编译速度** - 减少依赖解析
|
||||
4. ✅ **更灵活的样式** - 可以完全自定义
|
||||
|
||||
## 🎯 button vs uni-button 对比
|
||||
|
||||
### 原生 button
|
||||
|
||||
```vue
|
||||
<button class="custom-btn" @click="handleClick">
|
||||
点击我
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.custom-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: #256BFA;
|
||||
color: white;
|
||||
border-radius: 12rpx;
|
||||
border: none;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none; /* 移除默认边框 */
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
**优点:**
|
||||
- ✅ 无需安装依赖
|
||||
- ✅ 完全自定义样式
|
||||
- ✅ 支持所有平台
|
||||
- ✅ 性能更好
|
||||
|
||||
**缺点:**
|
||||
- ⚠️ 需要手动重置样式
|
||||
- ⚠️ 需要自己实现 loading、disabled 等状态
|
||||
|
||||
### uni-button
|
||||
|
||||
```vue
|
||||
<uni-button type="primary" @click="handleClick">
|
||||
点击我
|
||||
</uni-button>
|
||||
```
|
||||
|
||||
**优点:**
|
||||
- ✅ 内置多种样式
|
||||
- ✅ 自带 loading、disabled 状态
|
||||
- ✅ 统一的UI风格
|
||||
|
||||
**缺点:**
|
||||
- ❌ 需要安装 uni-ui
|
||||
- ❌ 增加包体积
|
||||
- ❌ 自定义样式受限
|
||||
|
||||
## 📝 button 样式重置模板
|
||||
|
||||
推荐在全局样式中添加 button 重置:
|
||||
|
||||
```css
|
||||
/* App.vue 或 common.css */
|
||||
|
||||
/* 重置 button 默认样式 */
|
||||
button {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
line-height: inherit;
|
||||
text-align: inherit;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 移除微信小程序 button 的默认边框 */
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 移除 button 按下时的背景色 */
|
||||
button:active {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
/* 通用按钮样式 */
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 20rpx 40rpx;
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #13C57C 0%, #0FA368 100%);
|
||||
color: #FFFFFF;
|
||||
box-shadow: 0 8rpx 20rpx rgba(19, 197, 124, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #F7F8FA;
|
||||
color: #666666;
|
||||
}
|
||||
```
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 编译器宏的特殊性
|
||||
|
||||
```javascript
|
||||
// ❌ 错误:不能解构或重命名
|
||||
import { defineProps as props } from 'vue'
|
||||
|
||||
// ❌ 错误:不能在条件语句中使用
|
||||
if (someCondition) {
|
||||
defineProps({...})
|
||||
}
|
||||
|
||||
// ✅ 正确:直接在顶层使用
|
||||
const props = defineProps({...})
|
||||
```
|
||||
|
||||
### 2. TypeScript 支持
|
||||
|
||||
如果使用 TypeScript,编译器宏会自动获得类型支持:
|
||||
|
||||
```typescript
|
||||
<script setup lang="ts">
|
||||
// 自动获得类型提示
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
age?: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
update: [value: string]
|
||||
change: [id: number]
|
||||
}>()
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3. 在非 setup 语法中
|
||||
|
||||
如果不使用 `<script setup>`,需要用传统方式:
|
||||
|
||||
```vue
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: String
|
||||
},
|
||||
emits: ['update'],
|
||||
setup(props, { emit, expose }) {
|
||||
// ...
|
||||
expose({ open, close })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## ✅ 验证修复
|
||||
|
||||
修复后,重新编译项目应该看到:
|
||||
|
||||
1. ✅ 没有 "Rollup failed to resolve import" 错误
|
||||
2. ✅ 没有 "defineXxx is a compiler macro" 警告
|
||||
3. ✅ 小程序正常编译和运行
|
||||
4. ✅ 按钮样式显示正常
|
||||
|
||||
## 🔍 排查步骤
|
||||
|
||||
如果修复后仍然有问题:
|
||||
|
||||
### 1. 清除缓存
|
||||
|
||||
```
|
||||
HBuilderX:
|
||||
运行 → 停止运行
|
||||
工具 → 清除缓存
|
||||
重新运行
|
||||
```
|
||||
|
||||
### 2. 检查所有文件
|
||||
|
||||
使用全局搜索检查是否还有遗漏:
|
||||
|
||||
```
|
||||
Ctrl + Shift + F
|
||||
搜索: import.*defineProps
|
||||
搜索: import.*defineEmits
|
||||
搜索: import.*defineExpose
|
||||
```
|
||||
|
||||
### 3. 检查 pages.json
|
||||
|
||||
确保 easycom 配置正确:
|
||||
|
||||
```json
|
||||
{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom": {
|
||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 重新安装依赖
|
||||
|
||||
```bash
|
||||
# 删除 node_modules 和 lock 文件
|
||||
rm -rf node_modules
|
||||
rm package-lock.json
|
||||
|
||||
# 重新安装
|
||||
npm install
|
||||
```
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [Vue 3 script setup 文档](https://cn.vuejs.org/api/sfc-script-setup.html)
|
||||
- [uni-app button 组件](https://uniapp.dcloud.net.cn/component/button.html)
|
||||
- [uni-ui 文档](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html)
|
||||
- [Vite 构建优化](https://cn.vitejs.dev/guide/dep-pre-bundling.html)
|
||||
|
||||
## 🎉 总结
|
||||
|
||||
### 问题
|
||||
1. 使用了未安装的 `uni-button` 组件
|
||||
2. 错误地从 vue 导入了编译器宏
|
||||
|
||||
### 解决
|
||||
1. ✅ 将 `<uni-button>` 替换为 `<button>`
|
||||
2. ✅ 移除所有编译器宏的 import 语句
|
||||
3. ✅ 添加 button 样式重置
|
||||
|
||||
### 最佳实践
|
||||
- 优先使用原生组件
|
||||
- 不要导入 Vue 编译器宏
|
||||
- 保持依赖简洁
|
||||
- 定期清理未使用的代码
|
||||
|
||||
---
|
||||
|
||||
**所有错误已修复!** 🎉
|
||||
|
||||
现在可以正常编译和运行小程序了。
|
||||
|
207
docs/企业地址选择功能说明.md
Normal file
207
docs/企业地址选择功能说明.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# 企业地址选择功能说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
在企业信息补全页面(company-info.vue)中,点击"企业注册地点"字段的箭头时,会弹出一个五级联动选择器,用户可以选择省市区县街道社区的完整地址。
|
||||
|
||||
## 实现的功能
|
||||
|
||||
### 1. 五级联动选择
|
||||
- **省级选择**:选择省/直辖市/自治区
|
||||
- **市级选择**:根据选择的省,显示对应的市/地区
|
||||
- **区县选择**:根据选择的市,显示对应的区/县
|
||||
- **街道选择**:根据选择的区县,显示对应的街道/乡镇
|
||||
- **社区选择**:根据选择的街道,显示对应的社区/居委会
|
||||
|
||||
### 2. 联动逻辑
|
||||
- 当选择省级时,自动更新并重置市级及以下选项
|
||||
- 当选择市级时,自动更新并重置区县及以下选项
|
||||
- 当选择区县时,自动更新并重置街道及以下选项
|
||||
- 当选择街道时,自动更新社区选项
|
||||
- 所有联动过程均实时响应,无需额外操作
|
||||
|
||||
### 3. 地址格式
|
||||
- 选择完成后,地址格式为:`省/市/区/街道/社区`
|
||||
- 示例:`新疆维吾尔自治区/喀什地区/喀什市/学府街道/学府社区居委会`
|
||||
- 地址各级信息都会保存,包括代码和名称
|
||||
|
||||
### 4. 数据存储
|
||||
- 保存完整的地址字符串(`registeredAddress`)
|
||||
- 保存各级行政区划代码和名称:
|
||||
- 省:`provinceCode`、`provinceName`
|
||||
- 市:`cityCode`、`cityName`
|
||||
- 区县:`districtCode`、`districtName`
|
||||
- 街道:`streetCode`、`streetName`
|
||||
- 社区:`communityCode`、`communityName`
|
||||
|
||||
## 技术实现
|
||||
|
||||
### 组件架构
|
||||
- **组件名称**:`area-cascade-picker`
|
||||
- **组件位置**:`components/area-cascade-picker/area-cascade-picker.vue`
|
||||
- **依赖组件**:`uni-popup`(uni-app官方弹窗组件)
|
||||
|
||||
### 核心技术
|
||||
- **picker-view**:uni-app的多列选择器组件
|
||||
- **五级联动**:通过监听选择变化,动态更新下级选项
|
||||
- **树形数据结构**:地区数据采用嵌套的树形结构,每级都有`children`属性
|
||||
|
||||
### 数据格式
|
||||
```javascript
|
||||
{
|
||||
code: '650000', // 行政区划代码
|
||||
name: '新疆维吾尔自治区', // 名称
|
||||
children: [ // 下级行政区
|
||||
{
|
||||
code: '653100',
|
||||
name: '喀什地区',
|
||||
children: [...]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 数据流程
|
||||
|
||||
1. **打开地址选择器**
|
||||
```javascript
|
||||
// company-info.vue
|
||||
const selectLocation = () => {
|
||||
areaPicker.value?.open({
|
||||
title: '选择企业注册地点',
|
||||
maskClick: true,
|
||||
success: (addressData) => {
|
||||
// 处理选择结果
|
||||
formData.registeredAddress = addressData.address
|
||||
// 保存各级信息
|
||||
formData.provinceCode = addressData.province?.code
|
||||
formData.provinceName = addressData.province?.name
|
||||
// ... 其他字段
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
2. **选择地址过程**
|
||||
```javascript
|
||||
// area-cascade-picker.vue
|
||||
bindChange(e) {
|
||||
// 检测哪一级发生变化
|
||||
// 更新对应级别及其下级的选项列表
|
||||
// 触发change回调(可选)
|
||||
}
|
||||
```
|
||||
|
||||
3. **确认选择**
|
||||
```javascript
|
||||
// area-cascade-picker.vue
|
||||
confirm() {
|
||||
const addressData = {
|
||||
address: '新疆维吾尔自治区/喀什地区/喀什市/学府街道/学府社区居委会',
|
||||
province: { code: '650000', name: '新疆维吾尔自治区' },
|
||||
city: { code: '653100', name: '喀什地区' },
|
||||
district: { code: '653101', name: '喀什市' },
|
||||
street: { code: '65310101', name: '学府街道' },
|
||||
community: { code: '6531010101', name: '学府社区居委会' }
|
||||
}
|
||||
// 调用success回调
|
||||
callback(addressData)
|
||||
}
|
||||
```
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
components/
|
||||
└── area-cascade-picker/
|
||||
└── area-cascade-picker.vue # 五级联动地址选择组件
|
||||
pages/complete-info/
|
||||
└── company-info.vue # 企业信息补全页面
|
||||
```
|
||||
|
||||
## 数据字段
|
||||
|
||||
在 `company-info.vue` 的 `formData` 中的地址相关字段:
|
||||
|
||||
- `registeredAddress`: string - 完整地址(格式:省/市/区/街道/社区)
|
||||
- `registeredAddressName`: string - 地址名称
|
||||
- `provinceCode`: string - 省级行政区划代码
|
||||
- `provinceName`: string - 省级名称
|
||||
- `cityCode`: string - 市级行政区划代码
|
||||
- `cityName`: string - 市级名称
|
||||
- `districtCode`: string - 区县行政区划代码
|
||||
- `districtName`: string - 区县名称
|
||||
- `streetCode`: string - 街道行政区划代码
|
||||
- `streetName`: string - 街道名称
|
||||
- `communityCode`: string - 社区行政区划代码
|
||||
- `communityName`: string - 社区名称
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 用户操作流程
|
||||
1. 在企业信息页面,点击"企业注册地点"右侧的箭头图标
|
||||
2. 弹出五级联动地址选择器
|
||||
3. 依次选择:
|
||||
- 第一列:选择省/直辖市/自治区
|
||||
- 第二列:选择市/地区(根据第一列自动更新)
|
||||
- 第三列:选择区/县(根据第二列自动更新)
|
||||
- 第四列:选择街道/乡镇(根据第三列自动更新)
|
||||
- 第五列:选择社区/居委会(根据第四列自动更新)
|
||||
4. 确认选择无误后,点击右上角"确认"按钮
|
||||
5. 选择器关闭,地址自动填充到表单中
|
||||
|
||||
### 界面说明
|
||||
- **顶部标题栏**:
|
||||
- 左侧"取消"按钮:关闭选择器,不保存
|
||||
- 中间标题:显示"选择企业注册地点"
|
||||
- 右侧"确认"按钮:确认选择并保存
|
||||
- **五列选择器**:
|
||||
- 每列显示当前级别的所有选项
|
||||
- 可上下滑动选择
|
||||
- 选中项高亮显示
|
||||
- 各列之间自动联动
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据来源**:
|
||||
- 当前使用本地模拟数据,包含主要城市的五级地址
|
||||
- 生产环境建议接入后端API,提供完整的全国地址数据
|
||||
- 后端API接口:`/app/common/area/cascade`(需要实现)
|
||||
|
||||
2. **数据格式要求**:
|
||||
- 必须是树形结构,每级通过`children`属性嵌套
|
||||
- 每个节点必须包含`code`(行政区划代码)和`name`(名称)
|
||||
- 最深五级:省 → 市 → 区县 → 街道 → 社区
|
||||
|
||||
3. **性能考虑**:
|
||||
- 地址数据量大时,建议使用懒加载方式
|
||||
- 可以先加载省市区,街道和社区按需加载
|
||||
- 考虑使用缓存机制,避免重复加载
|
||||
|
||||
4. **兼容性**:
|
||||
- 支持H5、微信小程序等多端
|
||||
- 使用uni-app原生组件,兼容性好
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **数据优化**:
|
||||
- 接入后端API,提供完整的全国地址数据
|
||||
- 实现地址数据的懒加载
|
||||
- 添加地址数据缓存机制
|
||||
|
||||
2. **功能增强**:
|
||||
- 支持默认值回显(编辑时显示已选地址)
|
||||
- 添加搜索功能,快速定位地址
|
||||
- 支持手动输入详细地址(如门牌号)
|
||||
- 增加常用地址保存功能
|
||||
|
||||
3. **用户体验**:
|
||||
- 优化滑动选择的流畅度
|
||||
- 添加选择预览功能
|
||||
- 支持快速选择最近使用的地址
|
||||
|
||||
4. **数据扩展**:
|
||||
- 支持国际地址选择
|
||||
- 添加邮政编码自动填充
|
||||
- 提供经纬度坐标(结合地理编码服务)
|
||||
|
@@ -199,10 +199,10 @@ const logOut = (redirect = true) => {
|
||||
uni.removeStorageSync('userInfo')
|
||||
uni.removeStorageSync('token')
|
||||
|
||||
// 只有在明确需要跳转时才跳转到登录页
|
||||
// 只有在明确需要跳转时才跳转到补全信息页
|
||||
if (redirect) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/login',
|
||||
url: '/pages/complete-info/complete-info',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,109 +0,0 @@
|
||||
# 首页滚动隐藏功能修复报告
|
||||
|
||||
## 问题描述
|
||||
用户反馈:列表区域向上滚动时,上面的区域(搜索栏、附近工作卡片、服务图标网格)没有隐藏,导致下面的职位列表显示区域被压缩得很小。
|
||||
|
||||
## 修复方案
|
||||
|
||||
### 1. **简化滚动逻辑**
|
||||
- 移除了复杂的触摸手势处理
|
||||
- 移除了 `requestAnimationFrame` 的复杂节流处理
|
||||
- 使用简单直接的滚动位置判断
|
||||
|
||||
### 2. **优化滚动阈值**
|
||||
```javascript
|
||||
const HIDE_THRESHOLD = 50; // 向下滚动50px后隐藏顶部区域
|
||||
const SHOW_THRESHOLD = 5; // 滚动到顶部5px内显示顶部区域
|
||||
const STICKY_THRESHOLD = 80; // 滚动80px后筛选区域吸顶
|
||||
```
|
||||
|
||||
### 3. **简化CSS动画**
|
||||
```css
|
||||
.hidden-animation {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
overflow: hidden;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.hidden-height {
|
||||
opacity: 0 !important;
|
||||
transform: translateY(-100%) !important;
|
||||
pointer-events: none !important;
|
||||
max-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. **核心滚动处理函数**
|
||||
```javascript
|
||||
function handleScroll(e) {
|
||||
const currentScrollTop = e.detail.scrollTop || 0;
|
||||
|
||||
// 简单的滚动逻辑:向下滚动超过阈值就隐藏,滚动到顶部就显示
|
||||
if (currentScrollTop > HIDE_THRESHOLD) {
|
||||
if (!shouldHideTop.value) {
|
||||
shouldHideTop.value = true;
|
||||
}
|
||||
} else if (currentScrollTop <= SHOW_THRESHOLD) {
|
||||
if (shouldHideTop.value) {
|
||||
shouldHideTop.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 控制筛选区域吸顶
|
||||
if (currentScrollTop > STICKY_THRESHOLD) {
|
||||
if (!shouldStickyFilter.value) {
|
||||
shouldStickyFilter.value = true;
|
||||
}
|
||||
} else {
|
||||
if (shouldStickyFilter.value) {
|
||||
shouldStickyFilter.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新滚动位置
|
||||
lastScrollTop.value = currentScrollTop;
|
||||
scrollTop.value = currentScrollTop;
|
||||
}
|
||||
```
|
||||
|
||||
## 测试方法
|
||||
|
||||
### 1. **手动测试**
|
||||
- 点击右上角的红色"测试"按钮,验证CSS动画是否正常工作
|
||||
- 按钮文字会显示当前状态:"测试: 隐藏" 或 "测试: 显示"
|
||||
|
||||
### 2. **滚动测试**
|
||||
- 向下滚动列表区域超过50px,顶部区域应该自动隐藏
|
||||
- 滚动回到顶部(5px内),顶部区域应该自动显示
|
||||
- 滚动超过80px,筛选区域应该吸顶显示
|
||||
|
||||
## 预期效果
|
||||
|
||||
1. **向下滚动 > 50px**:顶部区域(搜索栏、附近工作卡片、服务图标)平滑向上滑出隐藏
|
||||
2. **滚动到顶部 < 5px**:顶部区域平滑向下滑入显示
|
||||
3. **滚动 > 80px**:筛选区域吸顶显示,提供更好的导航体验
|
||||
|
||||
## 技术特点
|
||||
|
||||
- ✅ **简单可靠**:移除了复杂的逻辑,使用最直接的滚动位置判断
|
||||
- ✅ **性能优化**:使用CSS硬件加速,流畅的动画效果
|
||||
- ✅ **跨平台兼容**:支持微信小程序、H5、App
|
||||
- ✅ **用户体验**:平滑的动画过渡,符合Material Design规范
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **移除测试按钮**:确认功能正常后,删除临时测试按钮
|
||||
2. **调整阈值**:根据实际使用情况,可以微调滚动阈值
|
||||
3. **添加用户偏好**:可以考虑添加设置选项,让用户选择是否启用自动隐藏
|
||||
|
||||
## 文件修改
|
||||
|
||||
- `pages/index/components/index-one.vue` - 主要修改文件
|
||||
- `docs/首页滚动优化说明.md` - 详细技术文档
|
||||
|
||||
---
|
||||
|
||||
**注意**:当前版本包含一个临时的红色测试按钮,用于验证功能是否正常工作。确认功能正常后,请删除测试按钮。
|
138
docs/编译器内存溢出解决方案.md
Normal file
138
docs/编译器内存溢出解决方案.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# 编译器内存溢出解决方案
|
||||
|
||||
## 问题描述
|
||||
编译时出现 `FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory` 错误,表示 Node.js 内存不足。
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 方案一:增加 Node.js 内存限制(推荐)
|
||||
|
||||
#### 在 HBuilderX 中设置
|
||||
|
||||
1. **修改 HBuilderX 配置文件**
|
||||
- 关闭 HBuilderX
|
||||
- 找到 HBuilderX 安装目录
|
||||
- 打开 `HBuilderX\plugins\node\node_modules\@dcloudio\vite-plugin-uni\dist` 目录
|
||||
- 或者在项目根目录创建 `vue.config.js` 文件
|
||||
|
||||
2. **创建或修改项目根目录下的 `vue.config.js`**
|
||||
```javascript
|
||||
module.exports = {
|
||||
transpileDependencies: [],
|
||||
// 增加 Node.js 内存限制
|
||||
configureWebpack: {
|
||||
devServer: {
|
||||
disableHostCheck: true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **修改 HBuilderX 启动配置**
|
||||
- 找到 HBuilderX 安装目录
|
||||
- 编辑 `HBuilderX.exe` 的启动参数
|
||||
- 创建一个批处理文件 `start-hbuilderx.bat`:
|
||||
```bat
|
||||
@echo off
|
||||
set NODE_OPTIONS=--max-old-space-size=8192
|
||||
start "" "HBuilderX安装路径\HBuilderX.exe"
|
||||
```
|
||||
- 将内存设置为 8GB(8192MB),可根据实际情况调整为 4096、8192 或更大
|
||||
|
||||
#### 在命令行中运行(如果使用 CLI)
|
||||
|
||||
如果您使用命令行方式编译,可以设置环境变量:
|
||||
|
||||
**Windows PowerShell:**
|
||||
```powershell
|
||||
$env:NODE_OPTIONS="--max-old-space-size=8192"
|
||||
```
|
||||
|
||||
**Windows CMD:**
|
||||
```cmd
|
||||
set NODE_OPTIONS=--max-old-space-size=8192
|
||||
```
|
||||
|
||||
**永久设置(Windows 系统环境变量):**
|
||||
1. 右键"此电脑" → "属性" → "高级系统设置" → "环境变量"
|
||||
2. 在"用户变量"或"系统变量"中新建变量:
|
||||
- 变量名:`NODE_OPTIONS`
|
||||
- 变量值:`--max-old-space-size=8192`
|
||||
3. 重启 HBuilderX
|
||||
|
||||
### 方案二:清理缓存
|
||||
|
||||
1. **清理 HBuilderX 缓存**
|
||||
- 在 HBuilderX 中:运行 → 清理项目缓存
|
||||
- 或者手动删除 `unpackage` 目录
|
||||
|
||||
2. **删除 node_modules 并重新安装**
|
||||
```powershell
|
||||
Remove-Item -Recurse -Force node_modules
|
||||
# 如果有 package.json,重新安装依赖
|
||||
npm install
|
||||
```
|
||||
|
||||
### 方案三:优化项目
|
||||
|
||||
1. **检查大文件**
|
||||
- 检查 `static` 目录下是否有过大的图片或资源文件
|
||||
- 当前项目中有 85 个 icon 图片,建议:
|
||||
- 压缩图片文件
|
||||
- 使用雪碧图或字体图标代替多个小图标
|
||||
- 将不常用的资源移到云存储
|
||||
|
||||
2. **检查第三方库**
|
||||
- 检查 `lib` 目录中的第三方库是否必需
|
||||
- 当前已引入的库:
|
||||
- dompurify@3.2.4es.js
|
||||
- markdown-it.min.js
|
||||
- highlight-uni.min.js
|
||||
- lunar-javascript@1.7.2.js
|
||||
- string-similarity.min.js
|
||||
- 考虑按需引入或延迟加载
|
||||
|
||||
3. **优化编译配置**
|
||||
在 `manifest.json` 中的 `h5.optimization` 已启用 `treeShaking`,这很好。
|
||||
|
||||
4. **分包加载**
|
||||
- 已使用 `packageA` 分包,继续保持
|
||||
- 考虑将更多页面移到分包中
|
||||
|
||||
### 方案四:升级 HBuilderX
|
||||
|
||||
确保使用最新版本的 HBuilderX,新版本通常有更好的内存管理。
|
||||
|
||||
## 推荐操作步骤
|
||||
|
||||
1. **立即执行:** 设置 `NODE_OPTIONS` 环境变量为 `--max-old-space-size=8192`
|
||||
2. **清理缓存:** 在 HBuilderX 中清理项目缓存
|
||||
3. **重启 HBuilderX:** 使用新的环境变量启动
|
||||
4. **长期优化:** 压缩静态资源,优化第三方库引入
|
||||
|
||||
## 验证
|
||||
|
||||
设置完成后,重新编译项目,查看是否还会出现内存溢出错误。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [uni-app 官方文档 - 内存溢出问题](https://uniapp.dcloud.net.cn/tutorial/run/OOM.html)
|
||||
- Node.js 内存限制说明:
|
||||
- 默认限制:约 1.4GB(32位)或 1.7GB(64位)
|
||||
- 建议设置:4096MB(4GB)或 8192MB(8GB)
|
||||
- 最大可设置:取决于系统可用内存
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Q: 设置后仍然内存溢出?**
|
||||
A: 尝试增大内存限制值,如 `--max-old-space-size=16384`(16GB)
|
||||
|
||||
**Q: 如何检查当前 Node.js 内存限制?**
|
||||
A: 在命令行运行:`node -e "console.log(require('v8').getHeapStatistics().heap_size_limit/(1024*1024))"`
|
||||
|
||||
**Q: 编译特别慢?**
|
||||
A: 内存充足但编译慢,可能是 CPU 性能问题,考虑:
|
||||
- 关闭不必要的后台程序
|
||||
- 使用 SSD 硬盘
|
||||
- 升级硬件配置
|
||||
|
@@ -1,87 +0,0 @@
|
||||
# 首页滚动显示隐藏优化说明
|
||||
|
||||
## 修复的问题
|
||||
|
||||
### 1. **逻辑冲突问题**
|
||||
- **原问题**:同时存在触摸手势(`handleTouchStart/Move/End`)和滚动事件两套控制逻辑
|
||||
- **影响**:两套逻辑相互干扰,导致显示隐藏行为不稳定
|
||||
- **解决方案**:移除触摸手势处理,统一使用滚动事件控制
|
||||
|
||||
### 2. **小程序兼容性问题**
|
||||
- **原问题**:使用了 `document.querySelector('.falls-scroll')` 操作 DOM
|
||||
- **影响**:在微信小程序中无法正常工作
|
||||
- **解决方案**:完全通过响应式数据和滚动事件处理,避免直接操作 DOM
|
||||
|
||||
### 3. **不合理的显示逻辑**
|
||||
- **原问题**:使用 `isManuallyHidden` 标记,只有手动隐藏后才能通过滚动显示
|
||||
- **影响**:用户体验差,需要特定操作才能恢复显示
|
||||
- **解决方案**:简化逻辑,滚动到顶部自动显示,向下滚动超过阈值自动隐藏
|
||||
|
||||
### 4. **性能问题**
|
||||
- **原问题**:使用 `setTimeout` 进行节流,清理不完善
|
||||
- **影响**:可能导致内存泄漏和性能下降
|
||||
- **解决方案**:改用 `requestAnimationFrame`,添加 `ticking` 标志,在组件卸载时清理
|
||||
|
||||
## 优化内容
|
||||
|
||||
### 1. **滚动阈值优化**
|
||||
```javascript
|
||||
const HIDE_THRESHOLD = 150; // 隐藏顶部区域的滚动阈值
|
||||
const SHOW_THRESHOLD = 10; // 显示顶部区域的滚动阈值(接近顶部)
|
||||
const STICKY_THRESHOLD = 100; // 筛选区域吸顶的滚动阈值
|
||||
```
|
||||
|
||||
### 2. **滚动方向判断优化**
|
||||
- 添加最小位移判断(2px),避免微小抖动导致的误判
|
||||
- 使用 `delta` 计算滚动方向,更加准确
|
||||
|
||||
### 3. **动画效果优化**
|
||||
- 使用 Material Design 的缓动曲线 `cubic-bezier(0.4, 0.0, 0.2, 1)`
|
||||
- 优化过渡时间,使动画更加流畅自然
|
||||
- 添加 `pointer-events: none` 避免隐藏时的交互问题
|
||||
- 使用硬件加速(`transform: translateZ(0)`)提升性能
|
||||
|
||||
### 4. **吸顶效果优化**
|
||||
- 优化占位符高度,避免内容跳动
|
||||
- 改进阴影效果,视觉层次更加清晰
|
||||
- H5 和小程序分别处理,确保跨平台一致性
|
||||
|
||||
### 5. **资源清理**
|
||||
- 在 `onUnmounted` 生命周期中清理 `requestAnimationFrame`
|
||||
- 防止内存泄漏
|
||||
|
||||
## 使用效果
|
||||
|
||||
### 滚动行为
|
||||
1. **向下滚动超过 150px**:顶部区域(搜索框、卡片、服务网格)自动隐藏
|
||||
2. **滚动到顶部(小于 10px)**:顶部区域自动显示
|
||||
3. **滚动超过 100px**:筛选区域吸顶显示
|
||||
|
||||
### 动画效果
|
||||
- 隐藏/显示过渡时间:350ms
|
||||
- 透明度过渡:300ms
|
||||
- 平滑的向上滑动动画
|
||||
|
||||
### 性能表现
|
||||
- 使用 `requestAnimationFrame` 确保 60fps 流畅度
|
||||
- 防抖处理避免过度渲染
|
||||
- 硬件加速提升动画性能
|
||||
|
||||
## 兼容性
|
||||
|
||||
- ✅ 微信小程序
|
||||
- ✅ H5
|
||||
- ✅ App (理论支持,需实际测试)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 如需调整滚动阈值,修改 `HIDE_THRESHOLD`、`SHOW_THRESHOLD`、`STICKY_THRESHOLD` 三个常量
|
||||
2. 如需调整动画速度,修改 `.hidden-animation` 中的 `transition` 时间
|
||||
3. 占位符高度需要与 `.nav-filter` 的实际高度保持一致
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. 可以考虑添加滚动速度检测,快速滚动时立即隐藏
|
||||
2. 可以添加用户偏好设置,允许关闭自动隐藏功能
|
||||
3. 可以添加触底提示,优化加载更多的体验
|
||||
|
Reference in New Issue
Block a user