805 lines
15 KiB
Markdown
805 lines
15 KiB
Markdown
# Lyzsys 常见问题 (FAQ)
|
||
|
||
## 📖 目录
|
||
|
||
- [快速导航](#快速导航)
|
||
- [后端开发问题](#后端开发问题)
|
||
- [前端开发问题](#前端开发问题)
|
||
- [部署运维问题](#部署运维问题)
|
||
- [性能优化问题](#性能优化问题)
|
||
- [功能定制问题](#功能定制问题)
|
||
- [故障排查问题](#故障排查问题)
|
||
|
||
---
|
||
|
||
## 快速导航
|
||
|
||
### 新手入门
|
||
|
||
- [如何快速开始?](#如何快速开始)
|
||
- [项目运行需要什么环境?](#项目运行需要什么环境)
|
||
- [如何获取项目源码?](#如何获取项目源码)
|
||
|
||
### 开发相关
|
||
|
||
- [如何添加新的业务模块?](#如何添加新的业务模块)
|
||
- [如何修改前端页面?](#如何修改前端页面)
|
||
- [如何自定义接口?](#如何自定义接口)
|
||
- [如何实现权限控制?](#如何实现权限控制)
|
||
|
||
### 部署相关
|
||
|
||
- [如何部署到生产环境?](#如何部署到生产环境)
|
||
- [如何配置数据库连接?](#如何配置数据库连接)
|
||
- [如何配置 SSL 证书?](#如何配置-ssl-证书)
|
||
- [如何进行性能优化?](#如何进行性能优化)
|
||
|
||
---
|
||
|
||
## 后端开发问题
|
||
|
||
### Q1: 如何快速开始?
|
||
|
||
**A**: 按照以下步骤操作:
|
||
|
||
1. **克隆项目**
|
||
```bash
|
||
git clone https://github.com/your-org/lyzsys.git
|
||
cd lyzsys/lyzsys_backend
|
||
```
|
||
|
||
2. **导入数据库**
|
||
```bash
|
||
mysql -u root -p < sql/lyzsys.sql
|
||
```
|
||
|
||
3. **修改配置**
|
||
```yaml
|
||
# application.yaml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://localhost:3306/lyzsys
|
||
username: root
|
||
password: your_password
|
||
```
|
||
|
||
4. **启动项目**
|
||
```bash
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
5. **访问系统**
|
||
- 后端地址: http://localhost:48080
|
||
- API 文档: http://localhost:48080/doc.html
|
||
|
||
### Q2: 如何添加新的业务模块?
|
||
|
||
**A**: 按照以下步骤创建新模块:
|
||
|
||
1. **创建模块目录**
|
||
```
|
||
lyzsys-module-xxx/
|
||
├── src/
|
||
│ └── main/
|
||
│ ├── java/
|
||
│ └── resources/
|
||
└── pom.xml
|
||
```
|
||
|
||
2. **创建模块 pom.xml**
|
||
```xml
|
||
<parent>
|
||
<groupId>cn.iocoder</groupId>
|
||
<artifactId>lyzsys-backend</artifactId>
|
||
<version>1.0.0</version>
|
||
</parent>
|
||
|
||
<artifactId>lyzsys-module-xxx</artifactId>
|
||
<packaging>jar</packaging>
|
||
|
||
<dependencies>
|
||
<!-- 依赖其他模块 -->
|
||
</dependencies>
|
||
```
|
||
|
||
3. **创建标准包结构**
|
||
```
|
||
cn.iocoder.lyzsys.module.xxx/
|
||
├── api/
|
||
├── controller/
|
||
│ ├── admin/
|
||
│ └── app/
|
||
├── service/
|
||
├── dal/
|
||
│ ├── dataobject/
|
||
│ ├── mysql/
|
||
│ └── redis/
|
||
├── convert/
|
||
└── enums/
|
||
```
|
||
|
||
4. **在主 pom.xml 中添加模块**
|
||
```xml
|
||
<modules>
|
||
<module>lyzsys-module-xxx</module>
|
||
</modules>
|
||
```
|
||
|
||
5. **在 lyzsys-server 中引入**
|
||
```xml
|
||
<dependency>
|
||
<groupId>cn.iocoder</groupId>
|
||
<artifactId>lyzsys-module-xxx</artifactId>
|
||
</dependency>
|
||
```
|
||
|
||
### Q3: 如何实现权限控制?
|
||
|
||
**A**: Lyzsys 提供了多层次的权限控制:
|
||
|
||
#### 1. 接口权限
|
||
|
||
使用 `@PreAuthorize` 注解:
|
||
|
||
```java
|
||
@PostMapping("/create")
|
||
@PreAuthorize("@ss.hasPermission('system:user:create')")
|
||
public CommonResult<Long> createUser(@Valid @RequestBody UserCreateReqVO reqVO) {
|
||
return success(userService.createUser(reqVO));
|
||
}
|
||
```
|
||
|
||
#### 2. 数据权限
|
||
|
||
使用 `@DataScope` 注解:
|
||
|
||
```java
|
||
@DataScope(deptAlias = "d", userAlias = "u")
|
||
public List<UserDO> getUserList() {
|
||
return userMapper.selectList();
|
||
}
|
||
```
|
||
|
||
#### 3. 前端权限
|
||
|
||
使用权限指令:
|
||
|
||
```vue
|
||
<!-- 有权限时显示 -->
|
||
<el-button v-hasPermi="['system:user:create']">创建</el-button>
|
||
|
||
<!-- 有角色时显示 -->
|
||
<el-button v-hasRole="['admin']">管理员操作</el-button>
|
||
```
|
||
|
||
### Q4: 如何使用代码生成器?
|
||
|
||
**A**: 代码生成器使用步骤:
|
||
|
||
1. **访问代码生成**
|
||
- 登录系统后,进入「基础设施」→「代码生成」
|
||
|
||
2. **导入数据库表**
|
||
- 点击「导入」按钮
|
||
- 选择要生成的表
|
||
|
||
3. **配置生成信息**
|
||
- 基本信息:模块名、业务名、功能名
|
||
- 生成信息:包路径、模块名、业务名
|
||
- 字段信息:字段显示、查询条件、必填项
|
||
|
||
4. **生成代码**
|
||
- 点击「生成代码」按钮
|
||
- 下载代码压缩包
|
||
|
||
5. **导入项目**
|
||
- 解压代码到对应模块
|
||
- 创建菜单和权限
|
||
|
||
### Q5: 如何实现文件上传?
|
||
|
||
**A**: 文件上传实现步骤:
|
||
|
||
#### 1. 配置文件存储
|
||
|
||
```yaml
|
||
lyzsys:
|
||
upload:
|
||
base-url: http://your-domain.com
|
||
storage:
|
||
minio:
|
||
endpoint: http://localhost:9000
|
||
access-key: your_access_key
|
||
secret-key: your_secret_key
|
||
bucket-name: lyzsys
|
||
```
|
||
|
||
#### 2. 后端上传
|
||
|
||
```java
|
||
@PostMapping("/upload")
|
||
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file) {
|
||
String url = fileService.uploadFile(file);
|
||
return success(url);
|
||
}
|
||
```
|
||
|
||
#### 3. 前端上传
|
||
|
||
```vue
|
||
<el-upload
|
||
:action="uploadUrl"
|
||
:headers="uploadHeaders"
|
||
:on-success="handleSuccess"
|
||
>
|
||
<el-button type="primary">上传文件</el-button>
|
||
</el-upload>
|
||
```
|
||
|
||
### Q6: 如何使用 Redis 缓存?
|
||
|
||
**A**: Redis 缓存使用方法:
|
||
|
||
#### 1. 使用 Spring Cache
|
||
|
||
```java
|
||
@Cacheable(value = "user", key = "#id")
|
||
public UserDO getUser(Long id) {
|
||
return userMapper.selectById(id);
|
||
}
|
||
|
||
@CachePut(value = "user", key = "#user.id")
|
||
public UserDO updateUser(UserDO user) {
|
||
userMapper.updateById(user);
|
||
return user;
|
||
}
|
||
|
||
@CacheEvict(value = "user", key = "#id")
|
||
public void deleteUser(Long id) {
|
||
userMapper.deleteById(id);
|
||
}
|
||
```
|
||
|
||
#### 2. 使用 RedisTemplate
|
||
|
||
```java
|
||
@Autowired
|
||
private RedisTemplate<String, UserDO> redisTemplate;
|
||
|
||
public UserDO getUser(Long id) {
|
||
String key = "user:" + id;
|
||
UserDO user = redisTemplate.opsForValue().get(key);
|
||
|
||
if (user == null) {
|
||
user = userMapper.selectById(id);
|
||
redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS);
|
||
}
|
||
|
||
return user;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 前端开发问题
|
||
|
||
### Q7: 如何修改前端页面?
|
||
|
||
**A**: 前端页面修改步骤:
|
||
|
||
1. **找到页面文件**
|
||
- 页面文件位于 `src/views/` 目录
|
||
- 按照模块分类,如 `src/views/system/user/`
|
||
|
||
2. **修改页面内容**
|
||
```vue
|
||
<template>
|
||
<div class="user-list">
|
||
<!-- 页面内容 -->
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
// 脚本逻辑
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
// 样式
|
||
</style>
|
||
```
|
||
|
||
3. **热更新**
|
||
- 修改后自动热更新,无需重启
|
||
|
||
4. **构建测试**
|
||
```bash
|
||
pnpm build:prod
|
||
```
|
||
|
||
### Q8: 如何调用后端 API?
|
||
|
||
**A**: API 调用方法:
|
||
|
||
#### 1. 定义 API
|
||
|
||
```typescript
|
||
// src/api/system/user/index.ts
|
||
import request from '@/utils/request'
|
||
|
||
export function getUserPage(params: UserPageReqVO) {
|
||
return request.get({ url: '/system/user/page', params })
|
||
}
|
||
|
||
export function createUser(data: UserCreateReqVO) {
|
||
return request.post({ url: '/system/user/create', data })
|
||
}
|
||
```
|
||
|
||
#### 2. 调用 API
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { getUserPage } from '@/api/system/user'
|
||
|
||
const loading = ref(false)
|
||
const tableData = ref([])
|
||
|
||
async function fetchUsers() {
|
||
loading.value = true
|
||
try {
|
||
const { data } = await getUserPage({
|
||
pageNo: 1,
|
||
pageSize: 10
|
||
})
|
||
tableData.value = data.list
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
</script>
|
||
```
|
||
|
||
### Q9: 如何实现国际化?
|
||
|
||
**A**: 国际化实现步骤:
|
||
|
||
#### 1. 添加语言文件
|
||
|
||
```typescript
|
||
// src/locales/zh-CN/common.ts
|
||
export default {
|
||
title: 'Lyzsys 管理系统',
|
||
logout: '退出登录'
|
||
}
|
||
```
|
||
|
||
```typescript
|
||
// src/locales/en/common.ts
|
||
export default {
|
||
title: 'Lyzsys Admin',
|
||
logout: 'Logout'
|
||
}
|
||
```
|
||
|
||
#### 2. 使用翻译
|
||
|
||
```vue
|
||
<template>
|
||
<h1>{{ $t('common.title') }}</h1>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { useI18n } from '@/hooks/web/useI18n'
|
||
|
||
const { t } = useI18n()
|
||
const title = t('common.title')
|
||
</script>
|
||
```
|
||
|
||
### Q10: 如何自定义主题?
|
||
|
||
**A**: 主题定制方法:
|
||
|
||
#### 1. 修改主题色
|
||
|
||
```scss
|
||
// styles/variables.scss
|
||
$primary-color: #409eff;
|
||
$success-color: #67c23a;
|
||
$warning-color: #e6a23c;
|
||
$danger-color: #f56c6c;
|
||
```
|
||
|
||
#### 2. 动态切换主题
|
||
|
||
```typescript
|
||
import { useAppStore } from '@/store/modules/app'
|
||
|
||
const appStore = useAppStore()
|
||
|
||
// 切换暗黑模式
|
||
function toggleDarkMode() {
|
||
appStore.setDarkMode(!appStore.getDarkMode)
|
||
}
|
||
```
|
||
|
||
### Q11: 如何使用 Element Plus 组件?
|
||
|
||
**A**: Element Plus 组件使用:
|
||
|
||
#### 1. 表格组件
|
||
|
||
```vue
|
||
<el-table :data="tableData" border>
|
||
<el-table-column prop="name" label="姓名" />
|
||
<el-table-column prop="email" label="邮箱" />
|
||
<el-table-column label="操作">
|
||
<template #default="{ row }">
|
||
<el-button link @click="handleEdit(row)">编辑</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
```
|
||
|
||
#### 2. 表单组件
|
||
|
||
```vue
|
||
<el-form :model="form" :rules="rules" ref="formRef">
|
||
<el-form-item label="用户名" prop="username">
|
||
<el-input v-model="form.username" />
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleSubmit">提交</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
```
|
||
|
||
#### 3. 对话框组件
|
||
|
||
```vue
|
||
<el-dialog v-model="visible" title="提示">
|
||
<span>这是一段内容</span>
|
||
<template #footer>
|
||
<el-button @click="visible = false">取消</el-button>
|
||
<el-button type="primary" @click="visible = false">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
```
|
||
|
||
---
|
||
|
||
## 部署运维问题
|
||
|
||
### Q12: 如何部署到生产环境?
|
||
|
||
**A**: 生产部署步骤:
|
||
|
||
#### 后端部署
|
||
|
||
1. **打包项目**
|
||
```bash
|
||
mvn clean package -DskipTests
|
||
```
|
||
|
||
2. **上传到服务器**
|
||
```bash
|
||
scp lyzsys-server.jar user@server:/opt/lyzsys/
|
||
```
|
||
|
||
3. **启动服务**
|
||
```bash
|
||
java -jar lyzsys-server.jar --spring.profiles.active=prod
|
||
```
|
||
|
||
#### 前端部署
|
||
|
||
1. **构建项目**
|
||
```bash
|
||
pnpm build:prod
|
||
```
|
||
|
||
2. **部署到 Nginx**
|
||
```bash
|
||
scp -r dist/* user@server:/var/www/lyzsys/
|
||
```
|
||
|
||
3. **配置 Nginx**
|
||
```nginx
|
||
server {
|
||
listen 80;
|
||
server_name your-domain.com;
|
||
root /var/www/lyzsys;
|
||
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
location /admin-api/ {
|
||
proxy_pass http://localhost:48080/admin-api/;
|
||
}
|
||
}
|
||
```
|
||
|
||
### Q13: 如何配置数据库连接?
|
||
|
||
**A**: 数据库连接配置:
|
||
|
||
```yaml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://localhost:3306/lyzsys?useSSL=false&serverTimezone=Asia/Shanghai
|
||
username: root
|
||
password: your_password
|
||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||
|
||
# 连接池配置
|
||
hikari:
|
||
minimum-idle: 5
|
||
maximum-pool-size: 20
|
||
idle-timeout: 30000
|
||
connection-timeout: 30000
|
||
```
|
||
|
||
### Q14: 如何配置 SSL 证书?
|
||
|
||
**A**: SSL 证书配置步骤:
|
||
|
||
1. **获取证书**
|
||
```bash
|
||
certbot certonly --standalone -d your-domain.com
|
||
```
|
||
|
||
2. **配置 Nginx**
|
||
```nginx
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name your-domain.com;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name your-domain.com;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
```
|
||
|
||
### Q15: 如何进行备份和恢复?
|
||
|
||
**A**: 备份恢复方法:
|
||
|
||
#### 数据库备份
|
||
|
||
```bash
|
||
# 备份
|
||
mysqldump -u root -p lyzsys > lyzsys_backup.sql
|
||
|
||
# 恢复
|
||
mysql -u root -p lyzsys < lyzsys_backup.sql
|
||
```
|
||
|
||
#### 文件备份
|
||
|
||
```bash
|
||
# 备份
|
||
tar -czf lyzsys_backup.tar.gz /var/www/lyzsys
|
||
|
||
# 恢复
|
||
tar -xzf lyzsys_backup.tar.gz -C /
|
||
```
|
||
|
||
---
|
||
|
||
## 性能优化问题
|
||
|
||
### Q16: 如何进行性能优化?
|
||
|
||
**A**: 性能优化建议:
|
||
|
||
#### 后端优化
|
||
|
||
1. **数据库优化**
|
||
- 添加索引
|
||
- 优化 SQL
|
||
- 使用缓存
|
||
|
||
2. **代码优化**
|
||
- 批量操作
|
||
- 异步处理
|
||
- 减少数据库查询
|
||
|
||
3. **JVM 优化**
|
||
```bash
|
||
java -Xms2g -Xmx2g \
|
||
-XX:+UseG1GC \
|
||
-XX:MaxGCPauseMillis=200 \
|
||
-jar lyzsys-server.jar
|
||
```
|
||
|
||
#### 前端优化
|
||
|
||
1. **代码分割**
|
||
```typescript
|
||
const UserList = defineAsyncComponent(() => import('./views/system/user/index.vue'))
|
||
```
|
||
|
||
2. **资源优化**
|
||
- 压缩代码
|
||
- 使用 CDN
|
||
- 图片优化
|
||
|
||
3. **缓存优化**
|
||
- 浏览器缓存
|
||
- 本地存储
|
||
- Service Worker
|
||
|
||
### Q17: 如何处理高并发?
|
||
|
||
**A**: 高并发处理方案:
|
||
|
||
1. **水平扩展**
|
||
- 应用集群
|
||
- 负载均衡
|
||
- 数据库主从
|
||
|
||
2. **缓存策略**
|
||
- Redis 缓存
|
||
- 本地缓存
|
||
- 缓存预热
|
||
|
||
3. **异步处理**
|
||
- 消息队列
|
||
- 异步任务
|
||
- 线程池
|
||
|
||
4. **限流降级**
|
||
- 接口限流
|
||
- 服务降级
|
||
- 熔断保护
|
||
|
||
---
|
||
|
||
## 功能定制问题
|
||
|
||
### Q18: 如何修改 Logo 和标题?
|
||
|
||
**A**: 品牌定制方法:
|
||
|
||
#### 1. 修改前端
|
||
|
||
```typescript
|
||
// src/config/index.ts
|
||
export default {
|
||
title: '你的系统名称',
|
||
logo: '/logo.png'
|
||
}
|
||
```
|
||
|
||
#### 2. 修改后端
|
||
|
||
```yaml
|
||
lyzsys:
|
||
info:
|
||
name: '你的系统名称'
|
||
version: '1.0.0'
|
||
```
|
||
|
||
### Q19: 如何集成第三方服务?
|
||
|
||
**A**: 第三方集成方法:
|
||
|
||
#### 1. 短信集成
|
||
|
||
```java
|
||
@Service
|
||
public class SmsServiceImpl implements SmsService {
|
||
|
||
@Autowired
|
||
private SmsClient smsClient;
|
||
|
||
public void sendSms(String mobile, String content) {
|
||
SmsSendReqDTO req = new SmsSendReqDTO();
|
||
req.setMobile(mobile);
|
||
req.setContent(content);
|
||
smsClient.send(req);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2. 支付集成
|
||
|
||
```java
|
||
@Service
|
||
public class PayServiceImpl implements PayService {
|
||
|
||
@Autowired
|
||
private PayClient payClient;
|
||
|
||
public String createOrder(PayOrderCreateReqDTO req) {
|
||
return payClient.createOrder(req);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 故障排查问题
|
||
|
||
### Q20: 如何查看错误日志?
|
||
|
||
**A**: 日志查看方法:
|
||
|
||
#### 后端日志
|
||
|
||
```bash
|
||
# 查看应用日志
|
||
tail -f logs/lyzsys.log
|
||
|
||
# 查看错误日志
|
||
grep ERROR logs/lyzsys.log
|
||
|
||
# 查看 Nginx 日志
|
||
tail -f /var/log/nginx/error.log
|
||
```
|
||
|
||
#### 前端日志
|
||
|
||
```javascript
|
||
// 浏览器控制台
|
||
console.log('日志信息')
|
||
console.error('错误信息')
|
||
|
||
// 网络请求
|
||
// Network 标签查看请求详情
|
||
```
|
||
|
||
### Q21: 常见错误及解决方案
|
||
|
||
#### 1. 数据库连接失败
|
||
|
||
**错误**: `Could not get JDBC Connection`
|
||
|
||
**解决方案**:
|
||
- 检查数据库是否启动
|
||
- 检查连接信息是否正确
|
||
- 检查防火墙是否开放端口
|
||
|
||
#### 2. Redis 连接失败
|
||
|
||
**错误**: `Unable to connect to Redis`
|
||
|
||
**解决方案**:
|
||
- 检查 Redis 是否启动
|
||
- 检查 Redis 密码是否正确
|
||
- 检查 Redis 地址是否正确
|
||
|
||
#### 3. 前端页面空白
|
||
|
||
**错误**: 页面无法显示
|
||
|
||
**解决方案**:
|
||
- 检查 Nginx 配置
|
||
- 检查前端路由配置
|
||
- 检查浏览器控制台错误
|
||
|
||
#### 4. API 请求失败
|
||
|
||
**错误**: `Network Error`
|
||
|
||
**解决方案**:
|
||
- 检查后端服务是否启动
|
||
- 检查 API 地址是否正确
|
||
- 检查跨域配置
|
||
|
||
---
|
||
|
||
**文档版本**: v1.0.0
|
||
**最后更新**: 2025-01-19
|
||
**维护团队**: Lyzsys 开发团队
|