---
author: system
created_at: 2026-06-27
purpose: 短信登录开关与通用系统配置功能设计
---

# 短信登录开关与通用系统配置设计

## 背景

当前系统未接入真实短信服务商，短信验证码使用硬编码 `123456`。小程序登录页同时展示「微信一键登录」和「手机号+验证码登录」两种方式，SMS 相关元素始终可见。

需要在管理后台增加系统配置管理功能，通过「短信登录开关」控制小程序端是否展示手机号短信登录入口。短信未启用时，小程序登录页只显示微信授权登录。

## 方案选择

采用 **方案 A：Key-Value 通用配置表**。

- 新建 `t_system_config` 表，key-value 结构
- 通用性强，后续加新配置只需 INSERT 一行数据，不用改表结构
- 复杂度可控，管理后台根据 `value_type` 动态渲染对应控件

## 详细设计

### 一、数据库设计

#### 新建表 `t_system_config`

```sql
CREATE TABLE t_system_config (
  id            VARCHAR(64)  PRIMARY KEY,
  config_key    VARCHAR(100) NOT NULL UNIQUE COMMENT '配置唯一标识',
  config_value  VARCHAR(500) NOT NULL DEFAULT '' COMMENT '配置值',
  value_type    VARCHAR(20)  NOT NULL DEFAULT 'string' COMMENT '值类型: boolean/string/number/json',
  config_group  VARCHAR(50)  NOT NULL DEFAULT 'system' COMMENT '配置分组: system/login/notification',
  config_name   VARCHAR(100) NOT NULL DEFAULT '' COMMENT '显示名称',
  description   VARCHAR(300) DEFAULT '' COMMENT '配置说明',
  sort_order    INT          NOT NULL DEFAULT 0 COMMENT '排序号',
  is_visible    TINYINT      NOT NULL DEFAULT 1 COMMENT '是否在管理后台可见: 0-隐藏, 1-显示',
  create_by     VARCHAR(64)  DEFAULT NULL,
  create_time   DATETIME     DEFAULT NULL,
  update_by     VARCHAR(64)  DEFAULT NULL,
  update_time   DATETIME     DEFAULT NULL,
  is_deleted    TINYINT      NOT NULL DEFAULT 0
) COMMENT = '系统配置表';
```

#### 初始数据

```sql
INSERT INTO t_system_config (id, config_key, config_value, value_type, config_group, config_name, description, sort_order, is_visible, create_time, update_time, is_deleted)
VALUES (
  REPLACE(UUID(), '-', ''),
  'sms_login_enabled',
  'false',
  'boolean',
  'login',
  '短信登录',
  '是否启用手机号+短信验证码登录方式',
  1,
  1,
  NOW(),
  NOW(),
  0
);
```

### 二、后端设计

#### 新增文件

| 层 | 文件 | 说明 |
|---|---|---|
| Entity | `SystemConfig.java` | 继承 `BaseEntity`，映射 `t_system_config` |
| Mapper | `SystemConfigMapper.java` | MyBatis-Plus 基础 CRUD |
| Service | `SystemConfigService.java` | 接口定义 |
| Service | `SystemConfigServiceImpl.java` | 业务逻辑实现 |
| Controller | `SystemConfigController.java` | 管理端接口，需 admin 登录 |
| DTO | `SystemConfigUpdateRequest.java` | 更新请求体（key + value） |
| DTO | `LoginConfigResponse.java` | 返回给小程序的登录方式配置 |

#### 接口设计

**管理端接口（需要 admin token）：**

| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/admin/systemConfig/list` | 获取所有可见配置列表（`is_visible=1`） |
| PUT | `/admin/systemConfig/update` | 批量更新配置值，传入 `List<SystemConfigUpdateRequest>` |

**公开接口（不需要登录，小程序登录页调用）：**

| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/auth/loginConfig` | 返回当前启用的登录方式 |

`/auth/loginConfig` 返回格式：

```json
{
  "code": 200,
  "data": {
    "wechatLoginEnabled": true,
    "smsLoginEnabled": false
  }
}
```

#### 核心逻辑

1. `SystemConfigService` 提供 `getConfigValue(String key)` 方法
2. 内部做 Redis 缓存，缓存 key 为 `system_config:{config_key}`
3. 更新配置时同步清除对应缓存
4. `/auth/loginConfig` 读取 `sms_login_enabled` 配置值，组装 `LoginConfigResponse` 返回
5. 管理端更新接口接收 `List<SystemConfigUpdateRequest>`，支持一次提交多个配置变更
6. `/auth/loginConfig` 在 `WebMvcConfig` 白名单中放行（与 `/auth/login`、`/auth/wechat/login` 同级）

### 三、管理后台设计

#### 路由配置

在 `web-admin/src/router/index.ts` 中新增：

```ts
{
  path: '/system',
  component: Layout,
  redirect: '/system/settings',
  meta: { title: '系统设置', icon: 'Setting' },
  children: [
    {
      path: 'settings',
      name: 'SystemSettings',
      component: () => import('@/views/system/SystemSettings.vue'),
      meta: { title: '基础设置' }
    }
  ]
}
```

#### 页面设计

**文件**：`web-admin/src/views/system/SystemSettings.vue`

**页面结构**：
- 顶部：页面标题「基础设置」+ 保存按钮
- 内容区：按 `config_group` 分组展示配置项
- 每个配置项根据 `value_type` 渲染不同控件：
  - `boolean` → `el-switch` 开关
  - `string` → `el-input` 输入框
  - `number` → `el-input-number` 数字输入框
- 当前只有一个配置项：「短信登录」开关，下方显示描述文字
- 点击「保存」调用批量更新接口

#### API 封装

新增 `web-admin/src/api/systemConfig.ts`：
- `getSystemConfigList()` → GET `/admin/systemConfig/list`
- `updateSystemConfig(list)` → PUT `/admin/systemConfig/update`

### 四、小程序登录页设计

#### 数据获取

在登录页 `onMounted` 时调用 `/auth/loginConfig` 接口：

```js
const loginConfig = ref({ wechatLoginEnabled: true, smsLoginEnabled: false })

onMounted(async () => {
  try {
    const res = await getLoginConfig()
    loginConfig.value = res.data
  } catch (e) {
    // 接口失败时默认只显示微信登录
    loginConfig.value = { wechatLoginEnabled: true, smsLoginEnabled: false }
  }
})
```

#### 条件渲染

用 `v-if="loginConfig.smsLoginEnabled"` 控制以下元素的显示：
- 分隔线（「或使用手机号登录」）
- 手机号输入框
- 验证码输入框 + 获取验证码按钮
- 「开启旅程」手机号登录按钮

始终显示的元素：
- 品牌标题区域
- 「微信一键登录」按钮
- 底部协议文字

#### 代码处理

- 新增 `services/auth.js` 中的 `getLoginConfig()` 方法
- 短信相关的 `ref`（`phone`、`code`、`countdown` 等）和方法保留不动，只是 `v-if` 不渲染
- 不删除任何现有短信登录代码，后续启用短信时只需将配置改为 `true` 即可

## 验收标准

1. 管理后台出现「系统设置」菜单，可看到「短信登录」开关
2. 开关默认关闭（`false`）
3. 小程序登录页在短信关闭时只显示微信登录按钮，无手机号表单
4. 管理后台将开关打开后，小程序刷新登录页可看到手机号+验证码表单
5. 后端编译通过，部署到服务器后验收正常
6. 浏览器 Console 无报错
