# 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 开发团队
