mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/multi-datasource
Conflicts: pom.xml src/main/resources/application-local.yaml
This commit is contained in:
commit
fb2fbbffb8
@ -102,9 +102,9 @@
|
||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.1.7 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||
| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) |
|
||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 3.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||
| [Resilience4j](https://github.com/quartz-scheduler) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
|
||||
| [Resilience4j](https://github.com/resilience4j/resilience4j) | 服务保障组件 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Resilience4j/?yudao) |
|
||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/skywalking) | Spring Boot 监控平台 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 8.6.0 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.11.4 | |
|
||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.16.14 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||
|
38
pom.xml
38
pom.xml
@ -30,6 +30,7 @@
|
||||
<mysql-connector-java.version>5.1.46</mysql-connector-java.version>
|
||||
<druid.version>1.2.4</druid.version>
|
||||
<mybatis-plus.version>3.4.2</mybatis-plus.version>
|
||||
<dynamic-datasource.version>3.3.2</dynamic-datasource.version>
|
||||
<redisson.version>3.15.1</redisson.version>
|
||||
<!-- Config 配置中心相关 -->
|
||||
<apollo.version>1.7.0</apollo.version>
|
||||
@ -46,7 +47,12 @@
|
||||
<easyexcel.verion>2.2.7</easyexcel.verion>
|
||||
<velocity.version>2.2</velocity.version>
|
||||
<screw.version>1.0.5</screw.version>
|
||||
<dynamic-datasource.version>3.3.2</dynamic-datasource.version>
|
||||
<podam.version>7.2.6.RELEASE</podam.version>
|
||||
<jedis-mock.version>0.1.16</jedis-mock.version>
|
||||
<!-- 三方云服务相关 -->
|
||||
<aliyun-java-sdk-core.version>4.5.18</aliyun-java-sdk-core.version>
|
||||
<aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
|
||||
<yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
@ -134,6 +140,11 @@
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
||||
<version>${dynamic-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
@ -213,14 +224,14 @@
|
||||
<dependency>
|
||||
<groupId>com.github.fppt</groupId> <!-- 单元测试,我们采用内嵌的 Redis 数据库 -->
|
||||
<artifactId>jedis-mock</artifactId>
|
||||
<version>0.1.16</version>
|
||||
<version>${jedis-mock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
|
||||
<artifactId>podam</artifactId>
|
||||
<version>7.2.6.RELEASE</version>
|
||||
<version>${podam.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@ -272,13 +283,26 @@
|
||||
<version>${screw.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 多数据源 -->
|
||||
<!-- 三方云服务相关 -->
|
||||
|
||||
<!-- SMS SDK begin -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>${dynamic-datasource.version}</version>
|
||||
<groupId>com.yunpian.sdk</groupId>
|
||||
<artifactId>yunpian-java-sdk</artifactId>
|
||||
<version>${yunpian-java-sdk.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
<version>${aliyun-java-sdk-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
<version>${aliyun-java-sdk-dysmsapi.version}</version>
|
||||
</dependency>
|
||||
<!-- SMS SDK end -->
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
7
ruoyi-ui/.env.demo1024
Normal file
7
ruoyi-ui/.env.demo1024
Normal file
@ -0,0 +1,7 @@
|
||||
NODE_ENV = production
|
||||
|
||||
# 测试环境配置
|
||||
ENV = 'staging'
|
||||
|
||||
# 芋道管理系统/测试环境
|
||||
VUE_APP_BASE_API = 'http://127.0.0.1:48080'
|
@ -8,6 +8,7 @@
|
||||
"dev": "vue-cli-service serve",
|
||||
"build:prod": "vue-cli-service build",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"build:demo1024": "vue-cli-service build --mode demo1024",
|
||||
"preview": "node build/index.js --preview",
|
||||
"lint": "eslint --ext .js,.vue src"
|
||||
},
|
||||
|
52
ruoyi-ui/src/api/system/sms/smsChannel.js
Normal file
52
ruoyi-ui/src/api/system/sms/smsChannel.js
Normal file
@ -0,0 +1,52 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 创建短信渠道
|
||||
export function createSmsChannel(data) {
|
||||
return request({
|
||||
url: '/system/sms-channel/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新短信渠道
|
||||
export function updateSmsChannel(data) {
|
||||
return request({
|
||||
url: '/system/sms-channel/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除短信渠道
|
||||
export function deleteSmsChannel(id) {
|
||||
return request({
|
||||
url: '/system/sms-channel/delete?id=' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得短信渠道
|
||||
export function getSmsChannel(id) {
|
||||
return request({
|
||||
url: '/system/sms-channel/get?id=' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得短信渠道分页
|
||||
export function getSmsChannelPage(query) {
|
||||
return request({
|
||||
url: '/system/sms-channel/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 获得短信渠道精简列表
|
||||
export function getSimpleSmsChannels() {
|
||||
return request({
|
||||
url: '/system/sms-channel/list-all-simple',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
20
ruoyi-ui/src/api/system/sms/smsLog.js
Normal file
20
ruoyi-ui/src/api/system/sms/smsLog.js
Normal file
@ -0,0 +1,20 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获得短信日志分页
|
||||
export function getSmsLogPage(query) {
|
||||
return request({
|
||||
url: '/system/sms-log/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导出短信日志 Excel
|
||||
export function exportSmsLogExcel(query) {
|
||||
return request({
|
||||
url: '/system/sms-log/export-excel',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
64
ruoyi-ui/src/api/system/sms/smsTemplate.js
Normal file
64
ruoyi-ui/src/api/system/sms/smsTemplate.js
Normal file
@ -0,0 +1,64 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 创建短信模板
|
||||
export function createSmsTemplate(data) {
|
||||
return request({
|
||||
url: '/system/sms-template/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新短信模板
|
||||
export function updateSmsTemplate(data) {
|
||||
return request({
|
||||
url: '/system/sms-template/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除短信模板
|
||||
export function deleteSmsTemplate(id) {
|
||||
return request({
|
||||
url: '/system/sms-template/delete?id=' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得短信模板
|
||||
export function getSmsTemplate(id) {
|
||||
return request({
|
||||
url: '/system/sms-template/get?id=' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得短信模板分页
|
||||
export function getSmsTemplatePage(query) {
|
||||
return request({
|
||||
url: '/system/sms-template/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 创建短信模板
|
||||
export function sendSms(data) {
|
||||
return request({
|
||||
url: '/system/sms-template/send-sms',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 导出短信模板 Excel
|
||||
export function exportSmsTemplateExcel(query) {
|
||||
return request({
|
||||
url: '/system/sms-template/export-excel',
|
||||
method: 'get',
|
||||
params: query,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
@ -17,6 +17,10 @@ export const DICT_TYPE = {
|
||||
SYS_OPERATE_TYPE: 'sys_operate_type',
|
||||
SYS_LOGIN_RESULT: 'sys_login_result',
|
||||
SYS_CONFIG_TYPE: 'sys_config_type',
|
||||
SYS_SMS_CHANNEL_CODE: 'sys_sms_channel_code',
|
||||
SYS_SMS_TEMPLATE_TYPE: 'sys_sms_template_type',
|
||||
SYS_SMS_SEND_STATUS: 'sys_sms_send_status',
|
||||
SYS_SMS_RECEIVE_STATUS: 'sys_sms_receive_status',
|
||||
|
||||
INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type',
|
||||
INF_JOB_STATUS: 'inf_job_status',
|
||||
|
@ -73,6 +73,18 @@ service.interceptors.response.use(res => {
|
||||
type: 'error'
|
||||
})
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code === 901) {
|
||||
Message({
|
||||
type: 'error',
|
||||
duration: 0,
|
||||
dangerouslyUseHTMLString: true,
|
||||
message: '<div>演示模式,不发进行写操作</div>'
|
||||
+ '<div> </div>'
|
||||
+ '<div>参考 https://www.iocoder.cn/Yudao/build-debugger-environment 教程</div>'
|
||||
+ '<div> </div>'
|
||||
+ '<div>5 分钟搭建本地环境</div>',
|
||||
})
|
||||
return Promise.reject(new Error(msg))
|
||||
} else if (code !== 200) {
|
||||
Notification.error({
|
||||
title: msg
|
||||
|
@ -163,7 +163,6 @@ export default {
|
||||
businessType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
542
ruoyi-ui/src/views/system/sms/smsChannel.vue
Normal file
542
ruoyi-ui/src/views/system/sms/smsChannel.vue
Normal file
@ -0,0 +1,542 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="短信签名" prop="signature">
|
||||
<el-input v-model="queryParams.signature" placeholder="请输入短信签名" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['system:sms-channel:create']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['system:sms-channel:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="短信签名" align="center" prop="signature" />
|
||||
<el-table-column label="渠道编码" align="center" prop="code">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, scope.row.code) }}</span>
|
||||
</template>
|
||||
</el-table-column>>
|
||||
<el-table-column label="启用状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
|
||||
</template>
|
||||
</el-table-column>>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="短信 API 的账号" align="center" prop="apiKey" />
|
||||
<el-table-column label="短信 API 的秘钥" align="center" prop="apiSecret" />
|
||||
<el-table-column label="短信发送回调 URL" align="center" prop="callbackUrl" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:sms-channel:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:sms-channel:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="短信签名" prop="signature">
|
||||
<el-input v-model="form.signature" placeholder="请输入短信签名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道编码" prop="code">
|
||||
<el-input v-model="form.code" placeholder="请输入渠道编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="短信 API 的账号" prop="apiKey">
|
||||
<el-input v-model="form.apiKey" placeholder="请输入短信 API 的账号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="短信 API 的秘钥" prop="apiSecret">
|
||||
<el-input v-model="form.apiSecret" placeholder="请输入短信 API 的秘钥" />
|
||||
</el-form-item>
|
||||
<el-form-item label="短信发送回调 URL" prop="callbackUrl">
|
||||
<el-input v-model="form.callbackUrl" placeholder="请输入短信发送回调 URL" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createSmsChannel, updateSmsChannel, deleteSmsChannel, getSmsChannel, getSmsChannelPage,
|
||||
getSimpleSmsChannels } from "@/api/system/sms/smsChannel";
|
||||
|
||||
export default {
|
||||
name: "SmsChannel",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 短信渠道列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: null,
|
||||
status: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
signature: [{ required: true, message: "短信签名不能为空", trigger: "blur" }],
|
||||
code: [{ required: true, message: "渠道编码不能为空", trigger: "blur" }],
|
||||
status: [{ required: true, message: "启用状态不能为空", trigger: "blur" }],
|
||||
apiKey: [{ required: true, message: "短信 API 的账号不能为空", trigger: "blur" }],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getSmsChannelPage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
signature: undefined,
|
||||
code: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
apiKey: undefined,
|
||||
apiSecret: undefined,
|
||||
callbackUrl: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加短信渠道";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getSmsChannel(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改短信渠道";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateSmsChannel(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createSmsChannel(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$confirm('是否确认删除短信渠道编号为"' + id + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return deleteSmsChannel(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行导出
|
||||
this.$confirm('是否确认导出所有短信渠道数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportSmsChannelExcel(params);
|
||||
}).then(response => {
|
||||
this.downloadExcel(response, '短信渠道.xls');
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script><template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="短信签名" prop="signature">
|
||||
<el-input v-model="queryParams.signature" placeholder="请输入短信签名" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择启用状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['system:sms-channel:create']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['system:sms-channel:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="短信签名" align="center" prop="signature" />
|
||||
<el-table-column label="渠道编码" align="center" prop="code">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, scope.row.code) }}</span>
|
||||
</template>
|
||||
</el-table-column>>
|
||||
<el-table-column label="启用状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
|
||||
</template>
|
||||
</el-table-column>>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:sms-channel:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:sms-channel:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="130px">
|
||||
<el-form-item label="短信签名" prop="signature">
|
||||
<el-input v-model="form.signature" placeholder="请输入短信签名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="渠道编码" prop="code">
|
||||
<el-select v-model="form.code" placeholder="请选择渠道编码" :disabled="form.id > 0">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_SMS_CHANNEL_CODE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
<el-form-item label="短信 API 的账号" prop="apiKey">
|
||||
<el-input v-model="form.apiKey" placeholder="请输入短信 API 的账号" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.code !== 'YUN_PIAN'" label="短信 API 的秘钥" prop="apiSecret">
|
||||
<el-input v-model="form.apiSecret" placeholder="请输入短信 API 的秘钥" />
|
||||
</el-form-item>
|
||||
<el-form-item label="短信发送回调 URL" prop="callbackUrl">
|
||||
<el-input v-model="form.callbackUrl" placeholder="请输入短信发送回调 URL" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createSmsChannel, updateSmsChannel, deleteSmsChannel, getSmsChannel, getSmsChannelPage } from "@/api/system/sms/smsChannel";
|
||||
|
||||
export default {
|
||||
name: "SmsChannel",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 短信渠道列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
signature: null,
|
||||
status: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
apiKeyEnableChannelCodes: ['YUN_PIAN'],
|
||||
rules: {
|
||||
signature: [{ required: true, message: "短信签名不能为空", trigger: "blur" }],
|
||||
code: [{ required: true, message: "渠道编码不能为空", trigger: "blur" }],
|
||||
status: [{ required: true, message: "启用状态不能为空", trigger: "blur" }],
|
||||
apiKey: [{ required: true, message: "短信 API 的账号不能为空", trigger: "blur" }],
|
||||
apiSecret: [{ required: true, message: "短信 API 的秘钥不能为空", trigger: "blur" }],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getSmsChannelPage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
signature: undefined,
|
||||
code: undefined,
|
||||
status: undefined,
|
||||
remark: undefined,
|
||||
apiKey: undefined,
|
||||
apiSecret: undefined,
|
||||
callbackUrl: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加短信渠道";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getSmsChannel(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改短信渠道";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateSmsChannel(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createSmsChannel(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$confirm('是否确认删除短信渠道编号为"' + id + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return deleteSmsChannel(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行导出
|
||||
this.$confirm('是否确认导出所有短信渠道数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportSmsChannelExcel(params);
|
||||
}).then(response => {
|
||||
this.downloadExcel(response, '短信渠道.xls');
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
297
ruoyi-ui/src/views/system/sms/smsLog.vue
Normal file
297
ruoyi-ui/src/views/system/sms/smsLog.vue
Normal file
@ -0,0 +1,297 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="手机号" prop="mobile">
|
||||
<el-input v-model="queryParams.mobile" placeholder="请输入手机号" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="短信渠道" prop="channelId">
|
||||
<el-select v-model="queryParams.channelId" placeholder="请选择短信渠道" clearable size="small">
|
||||
<el-option v-for="channel in channelOptions"
|
||||
:key="channel.id" :value="channel.id"
|
||||
:label="channel.signature + '【' + getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, channel.code) + '】'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板编号" prop="templateId">
|
||||
<el-input v-model="queryParams.templateId" placeholder="请输入模板编号" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发送状态" prop="sendStatus">
|
||||
<el-select v-model="queryParams.sendStatus" placeholder="请选择发送状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_SMS_SEND_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="发送时间">
|
||||
<el-date-picker v-model="dateRangeSendTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item label="接收状态" prop="receiveStatus">
|
||||
<el-select v-model="queryParams.receiveStatus" placeholder="请选择接收状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_SMS_RECEIVE_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="接收时间">
|
||||
<el-date-picker v-model="dateRangeReceiveTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['system:sms-log:create']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['system:sms-log:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="编号" align="center" prop="id" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="手机号" align="center" prop="mobile" width="120">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ scope.row.mobile }}</div>
|
||||
<div v-if="scope.row.userType && scope.row.userId">
|
||||
{{ getDictDataLabel(DICT_TYPE.USER_TYPE, scope.row.userType) + '(' + scope.row.userId + ')' }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="短信内容" align="center" prop="templateContent" width="300" />
|
||||
<el-table-column label="发送状态" align="center" width="180">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_SEND_STATUS, scope.row.sendStatus) }}</div>
|
||||
<div>{{ parseTime(scope.row.sendTime) }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="接收状态" align="center" width="180">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_RECEIVE_STATUS, scope.row.receiveStatus) }}</div>
|
||||
<div>{{ parseTime(scope.row.receiveTime) }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="短信渠道" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ formatChannelSignature(scope.row.channelId) }}</div>
|
||||
<div>【{{ getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, scope.row.channelCode) }}】</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="模板编号" align="center" prop="templateId" />
|
||||
<el-table-column label="短信类型" align="center" prop="templateType">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_TEMPLATE_TYPE, scope.row.templateType) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row,scope.index)"
|
||||
v-hasPermi="['system:sms-log:query']">详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 短信日志详细 -->
|
||||
<el-dialog title="短信日志详细" :visible.sync="open" width="700px" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="140px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="日志主键:">{{ form.id }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="短信渠道:">
|
||||
{{ formatChannelSignature(form.channelId) }}【{{ getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, form.channelCode) }}】
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="短信模板:">
|
||||
{{ form.templateId }} | {{ form.templateCode}} | {{ getDictDataLabel(DICT_TYPE.SYS_SMS_TEMPLATE_TYPE, form.templateType) }}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="API 的模板编号:">{{ form.apiTemplateId }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户信息:">{{ form.mobile }}
|
||||
<span v-if="form.userType && form.userId"> | {{ getDictDataLabel(DICT_TYPE.USER_TYPE, form.userType) }} | {{ form.userId }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="短信内容:">{{ form.templateContent }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="短信参数:">{{ form.templateParams }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="创建时间:">{{ parseTime(form.createTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="发送状态:">{{ getDictDataLabel(DICT_TYPE.SYS_SMS_SEND_STATUS, form.sendStatus) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="发送时间:">{{ parseTime(form.sendTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="发送结果:">{{ form.sendCode }} | {{ form.sendMsg }}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="API 发送结果:">{{ form.apiSendCode }} | {{ form.apiSendMsg }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="API 短信编号:">{{ form.apiSerialNo }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="API 请求编号:">{{ form.apiRequestId }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="接收状态:">{{ getDictDataLabel(DICT_TYPE.SYS_SMS_RECEIVE_STATUS, form.receiveStatus) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="接收时间:">{{ parseTime(form.receiveTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="API 接收结果:">{{ form.apiReceiveCode }} | {{ form.apiReceiveMsg }}
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSmsLogPage, exportSmsLogExcel } from "@/api/system/sms/smsLog";
|
||||
import { getSimpleSmsChannels } from "@/api/system/sms/smsChannel";
|
||||
|
||||
export default {
|
||||
name: "SmsLog",
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 短信日志列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dateRangeSendTime: [],
|
||||
dateRangeReceiveTime: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
channelId: null,
|
||||
templateId: null,
|
||||
mobile: null,
|
||||
sendStatus: null,
|
||||
receiveStatus: null,
|
||||
},
|
||||
// 短信渠道
|
||||
channelOptions: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 获得短信渠道
|
||||
getSimpleSmsChannels().then(response => {
|
||||
this.channelOptions = response.data;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeSendTime, 'sendTime');
|
||||
this.addBeginAndEndTime(params, this.dateRangeReceiveTime, 'receiveTime');
|
||||
// 执行查询
|
||||
getSmsLogPage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeSendTime = [];
|
||||
this.dateRangeReceiveTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
this.addBeginAndEndTime(params, this.dateRangeSendTime, 'sendTime');
|
||||
this.addBeginAndEndTime(params, this.dateRangeReceiveTime, 'receiveTime');
|
||||
// 执行导出
|
||||
this.$confirm('是否确认导出所有短信日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportSmsLogExcel(params);
|
||||
}).then(response => {
|
||||
this.downloadExcel(response, '短信日志.xls');
|
||||
})
|
||||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(row) {
|
||||
this.open = true;
|
||||
this.form = row;
|
||||
},
|
||||
/** 格式化短信渠道 */
|
||||
formatChannelSignature(channelId) {
|
||||
for (const channel of this.channelOptions) {
|
||||
if (channel.id === channelId) {
|
||||
return channel.signature;
|
||||
}
|
||||
}
|
||||
return '找不到签名:' + channelId;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
405
ruoyi-ui/src/views/system/sms/smsTemplate.vue
Normal file
405
ruoyi-ui/src/views/system/sms/smsTemplate.vue
Normal file
@ -0,0 +1,405 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="150px">
|
||||
<el-form-item label="短信类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择短信类型" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_SMS_TEMPLATE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable size="small">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="dict.label" :value="dict.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板编码" prop="code">
|
||||
<el-input v-model="queryParams.code" placeholder="请输入模板编码" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="短信 API 的模板编号" prop="apiTemplateId">
|
||||
<el-input v-model="queryParams.apiTemplateId" placeholder="请输入短信 API 的模板编号" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="短信渠道" prop="channelId">
|
||||
<el-select v-model="queryParams.channelId" placeholder="请选择短信渠道" clearable size="small">
|
||||
<el-option v-for="channel in channelOptions"
|
||||
:key="channel.id" :value="channel.id"
|
||||
:label="channel.signature + '【' + getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, channel.code) + '】'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
|
||||
v-hasPermi="['system:sms-template:create']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
|
||||
v-hasPermi="['system:sms-template:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="模板编码" align="center" prop="code" />
|
||||
<el-table-column label="模板名称" align="center" prop="name" />
|
||||
<el-table-column label="模板内容" align="center" prop="content" width="300" />
|
||||
<el-table-column label="短信类型" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_SMS_TEMPLATE_TYPE, scope.row.type) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开启状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="短信 API 的模板编号" align="center" prop="apiTemplateId" width="180" />
|
||||
<el-table-column label="短信渠道" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<div>{{ formatChannelSignature(scope.row.channelId) }}</div>
|
||||
<div>【{{ getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, scope.row.channelCode) }}】</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-share" @click="handleSendSms(scope.row)"
|
||||
v-hasPermi="['system:sms-template:send-sms']">测试</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:sms-template:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:sms-template:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="140px">
|
||||
<el-form-item label="短信渠道编号" prop="channelId">
|
||||
<el-select v-model="form.channelId" placeholder="请选择短信渠道编号">
|
||||
<el-option v-for="channel in channelOptions"
|
||||
:key="channel.id" :value="channel.id"
|
||||
:label="channel.signature + '【' + getDictDataLabel(DICT_TYPE.SYS_SMS_CHANNEL_CODE, channel.code) + '】'" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="短信类型" prop="type">
|
||||
<el-select v-model="form.type" placeholder="请选择短信类型">
|
||||
<el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_SMS_TEMPLATE_TYPE)"
|
||||
:key="dict.value" :label="dict.label" :value="parseInt(dict.value)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板编号" prop="code">
|
||||
<el-input v-model="form.code" placeholder="请输入模板编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入模板名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容" prop="content">
|
||||
<el-input type="textarea" v-model="form.content" placeholder="请输入模板内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开启状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
|
||||
:key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="短信 API 模板编号" prop="apiTemplateId">
|
||||
<el-input v-model="form.apiTemplateId" placeholder="请输入短信 API 的模板编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 对话框(发送短信) -->
|
||||
<el-dialog title="测试发送短信" :visible.sync="sendSmsOpen" width="500px" append-to-body>
|
||||
<el-form ref="sendSmsForm" :model="sendSmsForm" :rules="sendSmsRules" label-width="140px">
|
||||
<el-form-item label="模板内容" prop="content">
|
||||
<el-input v-model="sendSmsForm.content" type="textarea" placeholder="请输入模板内容" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="mobile">
|
||||
<el-input v-model="sendSmsForm.mobile" placeholder="请输入手机号" />
|
||||
</el-form-item>
|
||||
<el-form-item v-for="param in sendSmsForm.params" :label="'参数 {' + param + '}'" :prop="'templateParams.' + param">
|
||||
<el-input v-model="sendSmsForm.templateParams[param]" :placeholder="'请输入 ' + param + ' 参数'" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitSendSmsForm">确 定</el-button>
|
||||
<el-button @click="cancelSendSms">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createSmsTemplate, updateSmsTemplate, deleteSmsTemplate, getSmsTemplate, getSmsTemplatePage,
|
||||
exportSmsTemplateExcel, sendSms } from "@/api/system/sms/smsTemplate";
|
||||
import { getSimpleSmsChannels } from "@/api/system/sms/smsChannel";
|
||||
|
||||
export default {
|
||||
name: "SmsTemplate",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 短信模板列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: null,
|
||||
status: null,
|
||||
code: null,
|
||||
content: null,
|
||||
apiTemplateId: null,
|
||||
channelId: null,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
type: [{ required: true, message: "短信类型不能为空", trigger: "change" }],
|
||||
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
|
||||
code: [{ required: true, message: "模板编码不能为空", trigger: "blur" }],
|
||||
name: [{ required: true, message: "模板名称不能为空", trigger: "blur" }],
|
||||
content: [{ required: true, message: "模板内容不能为空", trigger: "blur" }],
|
||||
apiTemplateId: [{ required: true, message: "短信 API 的模板编号不能为空", trigger: "blur" }],
|
||||
channelId: [{ required: true, message: "短信渠道编号不能为空", trigger: "change" }],
|
||||
},
|
||||
// 短信渠道
|
||||
channelOptions: [],
|
||||
// 发送短信
|
||||
sendSmsOpen: false,
|
||||
sendSmsForm: {
|
||||
params: [], // 模板的参数列表
|
||||
},
|
||||
sendSmsRules: {
|
||||
mobile: [{ required: true, message: "手机不能为空", trigger: "blur" }],
|
||||
templateCode: [{ required: true, message: "手机不能为空", trigger: "blur" }],
|
||||
templateParams: { }
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
// 获得短信渠道
|
||||
getSimpleSmsChannels().then(response => {
|
||||
this.channelOptions = response.data;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getSmsTemplatePage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
type: undefined,
|
||||
status: undefined,
|
||||
code: undefined,
|
||||
name: undefined,
|
||||
content: undefined,
|
||||
remark: undefined,
|
||||
apiTemplateId: undefined,
|
||||
channelId: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加短信模板";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id;
|
||||
getSmsTemplate(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改短信模板";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 修改的提交
|
||||
if (this.form.id != null) {
|
||||
updateSmsTemplate(this.form).then(response => {
|
||||
this.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
createSmsTemplate(this.form).then(response => {
|
||||
this.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$confirm('是否确认删除短信模板编号为"' + id + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return deleteSmsTemplate(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
params.pageNo = undefined;
|
||||
params.pageSize = undefined;
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行导出
|
||||
this.$confirm('是否确认导出所有短信模板数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportSmsTemplateExcel(params);
|
||||
}).then(response => {
|
||||
this.downloadExcel(response, '短信模板.xls');
|
||||
})
|
||||
},
|
||||
/** 发送短息按钮 */
|
||||
handleSendSms(row) {
|
||||
this.resetSendSms(row);
|
||||
// 设置参数
|
||||
this.sendSmsForm.content = row.content;
|
||||
this.sendSmsForm.params = row.params;
|
||||
this.sendSmsForm.templateCode = row.code;
|
||||
this.sendSmsForm.templateParams = row.params.reduce(function(obj, item) {
|
||||
obj[item] = undefined;
|
||||
return obj;
|
||||
}, {});
|
||||
// 根据 row 重置 rules
|
||||
this.sendSmsRules.templateParams = row.params.reduce(function(obj, item) {
|
||||
obj[item] = { required: true, message: '参数 ' + item + " 不能为空", trigger: "change" };
|
||||
return obj;
|
||||
}, {});
|
||||
// 设置打开
|
||||
this.sendSmsOpen = true;
|
||||
},
|
||||
/** 重置发送短信的表单 */
|
||||
resetSendSms() {
|
||||
// 根据 row 重置表单
|
||||
this.sendSmsForm = {
|
||||
content: undefined,
|
||||
params: undefined,
|
||||
mobile: undefined,
|
||||
templateCode: undefined,
|
||||
templateParams: {}
|
||||
};
|
||||
this.resetForm("sendSmsForm");
|
||||
},
|
||||
/** 取消发送短信 */
|
||||
cancelSendSms() {
|
||||
this.sendSmsOpen = false;
|
||||
this.resetSendSms();
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitSendSmsForm() {
|
||||
this.$refs["sendSmsForm"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
sendSms(this.sendSmsForm).then(response => {
|
||||
this.msgSuccess("提交发送成功!发送结果,见发送日志编号:" + response.data);
|
||||
this.sendSmsOpen = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
/** 格式化短信渠道 */
|
||||
formatChannelSignature(channelId) {
|
||||
for (const channel of this.channelOptions) {
|
||||
if (channel.id === channelId) {
|
||||
return channel.signature;
|
||||
}
|
||||
}
|
||||
return '找不到签名:' + channelId;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -362,7 +362,7 @@ export default {
|
||||
created() {
|
||||
this.getList();
|
||||
this.getTreeselect();
|
||||
this.getConfigKey("sys.user.initPassword").then(response => {
|
||||
this.getConfigKey("sys.user.init-password").then(response => {
|
||||
this.initPassword = response.msg;
|
||||
});
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : 127.0.0.1
|
||||
Source Server : local-mysql001
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 50718
|
||||
Source Host : localhost:3306
|
||||
@ -11,7 +11,7 @@
|
||||
Target Server Version : 50718
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 21/03/2021 18:53:24
|
||||
Date: 18/04/2021 00:36:06
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
@ -43,7 +43,7 @@ CREATE TABLE `inf_api_access_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1318 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3750 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of inf_api_access_log
|
||||
@ -84,7 +84,7 @@ CREATE TABLE `inf_api_error_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='系统异常日志';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='系统异常日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of inf_api_error_log
|
||||
@ -201,7 +201,7 @@ CREATE TABLE `inf_job_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=627 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2322 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of inf_job_log
|
||||
@ -264,7 +264,7 @@ CREATE TABLE `sys_dict_data` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='字典数据表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=78 DEFAULT CHARSET=utf8mb4 COMMENT='字典数据表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_dict_data
|
||||
@ -324,6 +324,19 @@ INSERT INTO `sys_dict_data` VALUES (61, 2, '管理员', '2', 'user_type', 0, NUL
|
||||
INSERT INTO `sys_dict_data` VALUES (62, 0, '未处理', '0', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:19', '', '2021-02-26 08:11:23', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (63, 1, '已处理', '1', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:26', '', '2021-02-26 08:11:29', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (64, 2, '已忽略', '2', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:34', '', '2021-02-26 08:11:34', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (65, 1, '云片', 'YUN_PIAN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:14', '1', '2021-04-13 00:20:13', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (66, 2, '阿里云', 'ALIYUN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:26', '1', '2021-04-13 00:20:16', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (67, 1, '验证码', '1', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:57', '1', '2021-04-05 21:50:57', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (68, 2, '通知', '2', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:08', '1', '2021-04-05 21:51:08', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (69, 0, '营销', '3', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:51:15', '1', '2021-04-05 21:51:15', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (70, 0, '初始化', '0', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:33', '1', '2021-04-11 09:30:18', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (71, 1, '发送成功', '10', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:43', '1', '2021-04-11 09:30:20', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (72, 2, '发送失败', '20', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:49', '1', '2021-04-11 09:30:22', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (73, 3, '不发送', '30', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:19:44', '1', '2021-04-11 09:30:23', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (74, 0, '等待结果', '0', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:43', '1', '2021-04-17 23:05:19', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (75, 1, '接收成功', '10', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:25', '1', '2021-04-11 20:29:35', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (76, 2, '接收失败', '20', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:29:31', '1', '2021-04-11 20:29:39', b'0');
|
||||
INSERT INTO `sys_dict_data` VALUES (77, 0, '调试(钉钉)', 'DEBUG_DING_TALK', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-13 00:20:37', '1', '2021-04-13 00:20:37', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -343,7 +356,7 @@ CREATE TABLE `sys_dict_type` (
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `dict_type` (`type`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=111 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=115 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_dict_type
|
||||
@ -366,6 +379,10 @@ INSERT INTO `sys_dict_type` VALUES (107, '定时任务状态', 'inf_job_status',
|
||||
INSERT INTO `sys_dict_type` VALUES (108, '定时任务日志状态', 'inf_job_log_status', 0, NULL, '', '2021-02-08 10:03:51', '', '2021-02-08 10:03:51', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (109, '用户类型', 'user_type', 0, NULL, '', '2021-02-26 00:15:51', '', '2021-02-26 00:15:51', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (110, 'API 异常数据的处理状态', 'inf_api_error_log_process_status', 0, NULL, '', '2021-02-26 07:07:01', '', '2021-02-26 07:07:01', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (111, '短信渠道编码', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:04:50', '1', '2021-04-05 01:04:50', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (112, '短信模板的类型', 'sys_sms_template_type', 0, NULL, '1', '2021-04-05 21:50:43', '1', '2021-04-05 21:50:43', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (113, '短信发送状态', 'sys_sms_send_status', 0, NULL, '1', '2021-04-11 20:18:03', '1', '2021-04-11 09:30:02', b'0');
|
||||
INSERT INTO `sys_dict_type` VALUES (114, '短信接收状态', 'sys_sms_receive_status', 0, NULL, '1', '2021-04-11 20:27:14', '1', '2021-04-11 20:27:14', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -386,7 +403,7 @@ CREATE TABLE `sys_login_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_login_log
|
||||
@ -415,7 +432,7 @@ CREATE TABLE `sys_menu` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1093 DEFAULT CHARSET=utf8mb4 COMMENT='菜单权限表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1110 DEFAULT CHARSET=utf8mb4 COMMENT='菜单权限表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_menu
|
||||
@ -530,6 +547,22 @@ INSERT INTO `sys_menu` VALUES (1089, '日志查询', 'infra:api-error-log:query'
|
||||
INSERT INTO `sys_menu` VALUES (1090, '文件管理', '', 2, 0, 2, 'file', 'upload', 'infra/file/index', 0, '', '2021-03-12 20:16:20', '1', '2021-03-13 11:07:05', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1091, '文件查询', 'infra:file:query', 3, 1, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1092, '文件删除', 'infra:file:delete', 3, 4, 1090, '', '', '', 0, '', '2021-03-12 20:16:20', '', '2021-03-12 20:16:20', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1093, '短信管理', '', 1, 11, 1, 'sms', 'validCode', NULL, 0, '1', '2021-04-05 01:10:16', '1', '2021-04-05 01:11:38', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1094, '短信渠道', '', 2, 0, 1093, 'sms-channel', 'phone', 'system/sms/smsChannel', 0, '', '2021-04-01 11:07:15', '1', '2021-04-09 23:44:07', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1095, '短信渠道查询', 'system:sms-channel:query', 3, 1, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1096, '短信渠道创建', 'system:sms-channel:create', 3, 2, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1097, '短信渠道更新', 'system:sms-channel:update', 3, 3, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1098, '短信渠道删除', 'system:sms-channel:delete', 3, 4, 1094, '', '', '', 0, '', '2021-04-01 11:07:15', '', '2021-04-01 11:07:15', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1100, '短信模板', '', 2, 1, 1093, 'sms-template', 'phone', 'system/sms/smsTemplate', 0, '', '2021-04-01 17:35:17', '1', '2021-04-11 19:34:21', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1101, '短信模板查询', 'system:sms-template:query', 3, 1, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1102, '短信模板创建', 'system:sms-template:create', 3, 2, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1103, '短信模板更新', 'system:sms-template:update', 3, 3, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1104, '短信模板删除', 'system:sms-template:delete', 3, 4, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1105, '短信模板导出', 'system:sms-template:export', 3, 5, 1100, '', '', '', 0, '', '2021-04-01 17:35:17', '', '2021-04-01 17:35:17', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1106, '发送测试短信', 'system:sms-template:send-sms', 3, 6, 1100, '', '', '', 0, '1', '2021-04-11 00:26:40', '1', '2021-04-11 00:26:40', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1107, '短信日志', '', 2, 2, 1093, 'sms-log', 'phone', 'system/sms/smsLog', 0, '', '2021-04-11 08:37:05', '1', '2021-04-11 19:34:25', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1108, '短信日志查询', 'system:sms-log:query', 3, 1, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0');
|
||||
INSERT INTO `sys_menu` VALUES (1109, '短信日志导出', 'system:sms-log:export', 3, 5, 1107, '', '', '', 0, '', '2021-04-11 08:37:05', '', '2021-04-11 08:37:05', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -589,7 +622,7 @@ CREATE TABLE `sys_operate_log` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=177 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_operate_log
|
||||
@ -834,6 +867,116 @@ INSERT INTO `sys_role_menu` VALUES (237, 101, 1064, '', '2021-01-21 03:23:27', '
|
||||
INSERT INTO `sys_role_menu` VALUES (238, 101, 1065, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_sms_channel
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_sms_channel`;
|
||||
CREATE TABLE `sys_sms_channel` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`signature` varchar(10) NOT NULL COMMENT '短信签名',
|
||||
`code` varchar(63) NOT NULL COMMENT '渠道编码',
|
||||
`status` tinyint(4) NOT NULL COMMENT '开启状态',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`api_key` varchar(128) NOT NULL COMMENT '短信 API 的账号',
|
||||
`api_secret` varchar(128) DEFAULT NULL COMMENT '短信 API 的秘钥',
|
||||
`callback_url` varchar(255) DEFAULT NULL COMMENT '短信发送回调 URL',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='短信渠道';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_sms_channel
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `sys_sms_channel` VALUES (1, '芋道', 'YUN_PIAN', 0, '呵呵呵哒', '1555a14277cb8a608cf45a9e6a80d510', NULL, 'http://java.nat300.top/api/system/sms/callback/sms/yunpian', '', '2021-03-31 06:12:20', '1', '2021-04-13 01:03:19', b'0');
|
||||
INSERT INTO `sys_sms_channel` VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-14 00:08:37', b'0');
|
||||
INSERT INTO `sys_sms_channel` VALUES (3, '测试', 'YUN_PIAN', 0, '哈哈哈', '23132', NULL, 'http://www.baidu.com', '1', '2021-04-05 21:10:34', '1', '2021-04-11 16:21:58', b'1');
|
||||
INSERT INTO `sys_sms_channel` VALUES (4, '测试渠道', 'DEBUG_DING_TALK', 0, '123', '696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859', 'SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67', NULL, '1', '2021-04-13 00:23:14', '1', '2021-04-14 00:07:10', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_sms_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_sms_log`;
|
||||
CREATE TABLE `sys_sms_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`channel_id` bigint(20) NOT NULL COMMENT '短信渠道编号',
|
||||
`channel_code` varchar(63) NOT NULL COMMENT '短信渠道编码',
|
||||
`template_id` bigint(20) NOT NULL COMMENT '模板编号',
|
||||
`template_code` varchar(63) NOT NULL COMMENT '模板编码',
|
||||
`template_type` tinyint(4) NOT NULL COMMENT '短信类型',
|
||||
`template_content` varchar(255) NOT NULL COMMENT '短信内容',
|
||||
`template_params` varchar(255) NOT NULL COMMENT '短信参数',
|
||||
`api_template_id` varchar(63) NOT NULL COMMENT '短信 API 的模板编号',
|
||||
`mobile` varchar(11) NOT NULL COMMENT '手机号',
|
||||
`user_id` bigint(20) DEFAULT NULL COMMENT '用户编号',
|
||||
`user_type` tinyint(4) DEFAULT NULL COMMENT '用户类型',
|
||||
`send_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '发送状态',
|
||||
`send_time` datetime DEFAULT NULL COMMENT '发送时间',
|
||||
`send_code` int(11) DEFAULT NULL COMMENT '发送结果的编码',
|
||||
`send_msg` varchar(255) DEFAULT NULL COMMENT '发送结果的提示',
|
||||
`api_send_code` varchar(63) DEFAULT NULL COMMENT '短信 API 发送结果的编码',
|
||||
`api_send_msg` varchar(255) DEFAULT NULL COMMENT '短信 API 发送失败的提示',
|
||||
`api_request_id` varchar(255) DEFAULT NULL COMMENT '短信 API 发送返回的唯一请求 ID',
|
||||
`api_serial_no` varchar(255) DEFAULT NULL COMMENT '短信 API 发送返回的序号',
|
||||
`receive_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '接收状态',
|
||||
`receive_time` datetime DEFAULT NULL COMMENT '接收时间',
|
||||
`api_receive_code` varchar(63) DEFAULT NULL COMMENT 'API 接收结果的编码',
|
||||
`api_receive_msg` varchar(255) DEFAULT NULL COMMENT 'API 接收结果的说明',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 COMMENT='短信日志';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_sms_log
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_sms_template
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `sys_sms_template`;
|
||||
CREATE TABLE `sys_sms_template` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
|
||||
`type` tinyint(4) NOT NULL COMMENT '短信签名',
|
||||
`status` tinyint(4) NOT NULL COMMENT '开启状态',
|
||||
`code` varchar(63) NOT NULL COMMENT '模板编码',
|
||||
`name` varchar(63) NOT NULL COMMENT '模板名称',
|
||||
`content` varchar(255) NOT NULL COMMENT '模板内容',
|
||||
`params` varchar(255) NOT NULL COMMENT '参数数组',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`api_template_id` varchar(63) NOT NULL COMMENT '短信 API 的模板编号',
|
||||
`channel_id` bigint(20) NOT NULL COMMENT '短信渠道编号',
|
||||
`channel_code` varchar(63) NOT NULL COMMENT '短信渠道编码',
|
||||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='短信模板';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of sys_sms_template
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `sys_sms_template` VALUES (2, 1, 0, 'test_01', '测试验证码短信', '正在进行登录操作{operation},您的验证码是{code}', '[\"operation\",\"code\"]', NULL, '4383920', 1, 'YUN_PIAN', '', '2021-03-31 10:49:38', '1', '2021-04-10 01:22:00', b'0');
|
||||
INSERT INTO `sys_sms_template` VALUES (3, 1, 0, 'test_02', '公告通知', '您的验证码{code},该验证码5分钟内有效,请勿泄漏于他人!', '[\"code\"]', NULL, 'SMS_207945135', 2, 'ALIYUN', '', '2021-03-31 11:56:30', '1', '2021-04-10 01:22:02', b'0');
|
||||
INSERT INTO `sys_sms_template` VALUES (4, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 07:47:12', b'1');
|
||||
INSERT INTO `sys_sms_template` VALUES (5, 3, 0, 'test-ooxx', '测试模板', 'biubiubiu', '[]', '1111', '110', 1, 'YUN_PIAN', '1', '2021-04-09 23:58:42', '1', '2021-04-02 08:32:22', b'1');
|
||||
INSERT INTO `sys_sms_template` VALUES (6, 3, 0, 'test-01', '测试模板', '哈哈哈 {name}', '[\"name\"]', 'f哈哈哈', '4383920', 1, 'YUN_PIAN', '1', '2021-04-10 01:07:21', '1', '2021-04-10 01:22:05', b'0');
|
||||
INSERT INTO `sys_sms_template` VALUES (7, 3, 0, 'test-04', '测试下', '老鸡{name},牛逼{code}', '[\"name\",\"code\"]', NULL, 'suibian', 4, 'DEBUG_DING_TALK', '1', '2021-04-13 00:29:53', '1', '2021-04-14 00:30:38', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for sys_user
|
||||
-- ----------------------------
|
||||
@ -865,8 +1008,8 @@ CREATE TABLE `sys_user` (
|
||||
-- Records of sys_user
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:8080/api/system/file/get/add5ec1891a7d97d2cc1d60847e16294.jpg', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '1', '2021-03-21 18:16:16', b'0');
|
||||
INSERT INTO `sys_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '测试员', 105, '[2]', 'ry@qq.com', '15666666666', 1, '', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-01-05 17:03:47', b'0');
|
||||
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$0acJOIk2D25/oC87nyclE..0lzeu9DtQ/n3geP4fkun/zIVRhHJIO', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://api-dashboard.yudao.iocoder.cn/api/infra/file/get/5e8609290e915c4fa8b08e67.jpg', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '1', '2021-04-05 02:16:10', b'0');
|
||||
INSERT INTO `sys_user` VALUES (2, 'ry', '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', '若依', '测试员', 105, '[2]', 'ry@qq.com', '15666666666', 1, '', 0, '127.0.0.1', '2021-01-05 17:03:47', 'admin', '2021-01-05 17:03:47', '', '2021-04-01 04:50:36', b'1');
|
||||
INSERT INTO `sys_user` VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 100, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '', NULL, '', '2021-01-07 09:07:17', '1', '2021-03-14 22:35:17', b'0');
|
||||
INSERT INTO `sys_user` VALUES (103, 'yuanma', '', '源码', NULL, 100, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '', NULL, '', '2021-01-13 23:50:35', '', '2021-01-13 23:50:35', b'0');
|
||||
INSERT INTO `sys_user` VALUES (104, 'test', '$2a$10$.TOFpaIiI3PzEwkGrNq0Eu6Cc3rOqJMxTb1DqeSEM8StxaGPBRKoi', '测试号', NULL, 100, '[]', '', '15601691200', 1, '', 0, '', NULL, '', '2021-01-21 02:13:53', '1', '2021-03-14 22:36:38', b'0');
|
||||
@ -924,13 +1067,40 @@ CREATE TABLE `sys_user_session` (
|
||||
-- Records of sys_user_session
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `sys_user_session` VALUES ('04c6624c7bf14b1ba1a01cb976a9d876', 1, '2021-04-05 21:40:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-05 20:21:09', NULL, '2021-04-01 12:25:35', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('0e235ce5ae7342a09b372a00bd7d1b41', 1, '2021-04-05 01:43:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-05 00:51:03', NULL, '2021-04-01 04:18:06', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('0e6943f8ca9b4215a014843eb489ccc7', 1, '2021-04-05 22:53:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-05 21:43:59', NULL, '2021-04-01 17:25:41', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('12166cd28b4f448ea468d13c471dfc6e', 1, '2021-04-09 19:48:58', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-09 19:18:58', NULL, '2021-04-02 04:33:15', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('134d908ae33146bd9b5291471c04f604', 1, '2021-04-10 00:29:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-09 23:10:26', NULL, '2021-04-02 08:08:17', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('1407ce21e47947b9b8d93bff1b55c7d6', 1, '2021-04-07 01:09:11', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-07 00:07:43', NULL, '2021-04-01 18:10:44', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('1477c38290ff4cee8887ebfe593faa02', 1, '2021-04-17 23:34:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-17 23:04:57', NULL, '2021-04-12 21:36:29', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('3c75ea73e13b4857a18eb57ca2eea80f', 1, '2021-04-11 20:06:52', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 19:36:52', NULL, '2021-04-11 09:10:53', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('40d532d8900c43b791266429a7911751', 1, '2021-04-05 22:11:34', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-05 21:41:34', NULL, '2021-04-01 12:28:20', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('43676e85d0e04980b2a67181f8d9933b', 1, '2021-04-11 10:41:09', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 09:56:31', NULL, '2021-04-02 17:32:07', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('505b4e7d8b0d4b40aa23bf540da81234', 1, '2021-03-14 01:25:13', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 00:31:43', NULL, '2021-03-13 07:35:26', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('56a92b99f7b642ccbb7508042a25cb0c', 1, '2021-04-11 21:16:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 20:14:54', NULL, '2021-04-11 10:08:20', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('5a7248bf87d14e7e9f0578b05969986c', 1, '2021-03-13 10:42:50', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-13 09:37:36', NULL, '2021-03-12 19:53:07', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('5c30d80eb72048daa1a24d3d4f01317b', 1, '2021-04-12 00:31:10', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 23:08:14', NULL, '2021-04-11 15:47:45', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('5dca80a5c61541479a4dbb6e004c2e28', 1, '2021-04-14 00:57:25', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-13 23:38:30', NULL, '2021-04-12 17:33:48', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('7324a76b029a49ee95bf54ceb4164ba9', 1, '2021-04-13 01:29:14', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-13 00:18:40', NULL, '2021-04-11 23:15:00', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('749619894bc441bb9773902515f81e6a', 1, '2021-04-11 00:39:51', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 00:09:51', NULL, '2021-04-02 16:50:56', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('7768ae62ad974fd989f5159649a4be82', 1, '2021-04-11 00:53:39', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-10 23:23:27', NULL, '2021-04-02 17:04:58', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('79efcb8f64aa42af9f4b327fb383532f', 1, '2021-04-11 22:44:07', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 21:34:53', NULL, '2021-04-11 14:10:45', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('87d5b95fdad9447189a95abf8a5152df', 1, '2021-04-17 23:01:18', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-17 22:31:18', NULL, '2021-04-12 21:03:27', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('8b3eac5e4a104a4191c8070e03d553ea', 1, '2021-04-05 02:45:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-05 02:15:12', NULL, '2021-04-01 11:05:25', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('9ae27346d8b7491aad1385f51e8aa196', 1, '2021-03-13 14:02:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-13 10:43:06', NULL, '2021-03-13 06:40:35', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('a2fb443b31c049008975ff8ee5499db1', 1, '2021-04-11 09:42:09', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 09:12:09', NULL, '2021-04-02 17:16:00', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('a71a74adf9d141e2849d2a411d558205', 1, '2021-04-17 18:24:44', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-17 17:54:44', NULL, '2021-04-12 17:54:50', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('ae9ee7452ee54e4b983d658188c15c4d', 1, '2021-03-14 21:32:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 20:25:00', NULL, '2021-03-13 15:19:10', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('d0adf48f82914212b947e5ab04d9fb65', 1, '2021-03-21 19:16:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 18:13:37', NULL, '2021-03-21 18:46:28', b'0');
|
||||
INSERT INTO `sys_user_session` VALUES ('b727853eccea4c8589e006ffea985146', 1, '2021-04-12 01:36:00', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-12 01:06:00', NULL, '2021-04-11 19:40:07', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('c095616db95044c5bed66a3f84519b8b', 1, '2021-04-11 19:59:33', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 19:29:33', NULL, '2021-04-11 09:04:19', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('d0adf48f82914212b947e5ab04d9fb65', 1, '2021-03-21 19:16:28', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 18:13:37', NULL, '2021-03-15 05:53:20', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('dfbce0af867547f4bb01ac6f2e583337', 1, '2021-04-11 17:06:15', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 16:36:15', NULL, '2021-04-11 08:24:03', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('e5ecf10e40a5463b8f9b5b453cb1649b', 1, '2021-04-11 17:06:22', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-11 16:36:22', NULL, '2021-04-11 08:24:03', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('e80c2400724042a2ab73732166cde8fc', 1, '2021-03-21 21:17:12', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 20:47:12', NULL, '2021-03-15 08:18:56', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('e8872f5192584440a548641b83c877ef', 1, '2021-03-21 18:36:01', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-03-21 17:51:48', NULL, '2021-03-15 03:54:20', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('f1ab99b09b5a475795579ff99d60ac78', 1, '2021-03-14 23:04:31', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-14 21:12:44', NULL, '2021-03-15 03:32:38', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('f2a4182f62ea4559b9946a523928fac4', 1, '2021-04-10 01:45:57', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36', NULL, '2021-04-10 00:55:38', NULL, '2021-04-02 14:52:48', b'1');
|
||||
INSERT INTO `sys_user_session` VALUES ('f853b50d064340a581e9a49bba9411fc', 1, '2021-03-10 01:55:41', 'admin', '127.0.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36', NULL, '2021-03-10 01:11:53', NULL, '2021-03-12 18:37:05', b'1');
|
||||
COMMIT;
|
||||
|
||||
@ -964,7 +1134,7 @@ CREATE TABLE `tool_codegen_column` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=389 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表字段定义';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=447 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表字段定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tool_codegen_column
|
||||
@ -1126,6 +1296,64 @@ INSERT INTO `tool_codegen_column` VALUES (385, 33, 'create_time', 'datetime', '
|
||||
INSERT INTO `tool_codegen_column` VALUES (386, 33, 'updater', 'varchar(64)', '更新者', b'1', b'0', '0', 6, 'String', 'updater', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-03-13 09:43:20', '1', '2021-03-13 11:27:12', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (387, 33, 'update_time', 'datetime', '更新时间', b'0', b'0', '0', 7, 'Date', 'updateTime', '', NULL, b'0', b'0', b'0', 'BETWEEN', b'0', 'datetime', '1', '2021-03-13 09:43:20', '1', '2021-03-13 11:27:12', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (388, 33, 'deleted', 'bit(1)', '是否删除', b'0', b'0', '0', 8, 'Boolean', 'deleted', '', NULL, b'0', b'0', b'0', '=', b'0', 'radio', '1', '2021-03-13 09:43:20', '1', '2021-03-13 11:27:12', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (389, 34, 'id', 'bigint(20)', '编号', b'0', b'1', '1', 1, 'Long', 'id', '', '1024', b'0', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (390, 34, 'signature', 'varchar(8)', '短信签名', b'0', b'0', '0', 2, 'String', 'signature', '', '芋道源码', b'1', b'1', b'1', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (391, 34, 'code', 'varchar(63)', '渠道编码', b'0', b'0', '0', 3, 'String', 'code', 'sys_sms_channel_code', 'YUN_PIAN', b'1', b'0', b'0', '=', b'1', 'select', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (392, 34, 'status', 'tinyint(4)', '启用状态', b'0', b'0', '0', 4, 'Integer', 'status', 'sys_common_status', '1', b'1', b'1', b'1', '=', b'1', 'radio', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (393, 34, 'remark', 'varchar(255)', '备注', b'1', b'0', '0', 5, 'String', 'remark', '', '好吃!', b'1', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (394, 34, 'api_key', 'varchar(63)', '短信 API 的账号', b'0', b'0', '0', 6, 'String', 'apiKey', '', 'yudao', b'1', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (395, 34, 'api_secret', 'varchar(63)', '短信 API 的秘钥', b'1', b'0', '0', 7, 'String', 'apiSecret', '', 'yuanma', b'1', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (396, 34, 'callback_url', 'varchar(255)', '短信发送回调 URL', b'1', b'0', '0', 8, 'String', 'callbackUrl', '', 'http://www.iocoder.cn', b'1', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (397, 34, 'creator', 'varchar(64)', '创建者', b'1', b'0', '0', 9, 'String', 'creator', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (398, 34, 'create_time', 'datetime', '创建时间', b'0', b'0', '0', 10, 'Date', 'createTime', '', NULL, b'0', b'0', b'1', 'BETWEEN', b'1', 'datetime', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (399, 34, 'updater', 'varchar(64)', '更新者', b'1', b'0', '0', 11, 'String', 'updater', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (400, 34, 'update_time', 'datetime', '更新时间', b'0', b'0', '0', 12, 'Date', 'updateTime', '', NULL, b'0', b'0', b'0', 'BETWEEN', b'0', 'datetime', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (401, 34, 'deleted', 'bit(1)', '是否删除', b'0', b'0', '0', 13, 'Boolean', 'deleted', '', NULL, b'0', b'0', b'0', '=', b'0', 'radio', '1', '2021-04-05 00:51:34', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (402, 35, 'id', 'bigint(20)', '编号', b'0', b'1', '1', 1, 'Long', 'id', '', '1024', b'0', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (403, 35, 'type', 'tinyint(4)', '短信签名', b'0', b'0', '0', 2, 'Integer', 'type', 'sys_sms_template_type', '1', b'1', b'1', b'1', '=', b'1', 'select', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (404, 35, 'status', 'tinyint(4)', '开启状态', b'0', b'0', '0', 3, 'Integer', 'status', 'sys_common_status', '1', b'1', b'1', b'1', '=', b'1', 'radio', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (405, 35, 'code', 'varchar(63)', '模板编码', b'0', b'0', '0', 4, 'String', 'code', '', 'test_01', b'1', b'1', b'1', 'LIKE', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (406, 35, 'name', 'varchar(63)', '模板名称', b'0', b'0', '0', 5, 'String', 'name', '', 'yudao', b'1', b'1', b'0', 'LIKE', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (407, 35, 'content', 'varchar(255)', '模板内容', b'0', b'0', '0', 6, 'String', 'content', '', '你好,{name}。你长的太{like}啦!', b'1', b'1', b'1', 'LIKE', b'1', 'editor', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (408, 35, 'params', 'varchar(255)', '参数数组', b'0', b'0', '0', 7, 'String', 'params', '', 'name,code', b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (409, 35, 'remark', 'varchar(255)', '备注', b'1', b'0', '0', 8, 'String', 'remark', '', '哈哈哈', b'1', b'1', b'0', '=', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (410, 35, 'api_template_id', 'varchar(63)', '短信 API 的模板编号', b'0', b'0', '0', 9, 'String', 'apiTemplateId', '', '4383920', b'1', b'1', b'1', 'LIKE', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (411, 35, 'channel_id', 'bigint(20)', '短信渠道编号', b'0', b'0', '0', 10, 'Long', 'channelId', '', '10', b'1', b'1', b'1', '=', b'1', 'select', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (412, 35, 'channel_code', 'varchar(63)', '短信渠道编码', b'0', b'0', '0', 11, 'String', 'channelCode', 'sys_sms_channel_code', 'ALIYUN', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (413, 35, 'creator', 'varchar(64)', '创建者', b'1', b'0', '0', 12, 'String', 'creator', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (414, 35, 'create_time', 'datetime', '创建时间', b'0', b'0', '0', 13, 'Date', 'createTime', '', NULL, b'0', b'0', b'1', 'BETWEEN', b'1', 'datetime', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (415, 35, 'updater', 'varchar(64)', '更新者', b'1', b'0', '0', 14, 'String', 'updater', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (416, 35, 'update_time', 'datetime', '更新时间', b'0', b'0', '0', 15, 'Date', 'updateTime', '', NULL, b'0', b'0', b'0', 'BETWEEN', b'0', 'datetime', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (417, 35, 'deleted', 'bit(1)', '是否删除', b'0', b'0', '0', 16, 'Boolean', 'deleted', '', NULL, b'0', b'0', b'0', '=', b'0', 'radio', '1', '2021-04-05 21:42:22', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (418, 36, 'id', 'bigint(20)', '编号', b'0', b'1', '1', 1, 'Long', 'id', '', '1024', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (419, 36, 'channel_id', 'bigint(20)', '短信渠道编号', b'0', b'0', '0', 2, 'Long', 'channelId', '', '10', b'0', b'0', b'1', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (420, 36, 'channel_code', 'varchar(63)', '短信渠道编码', b'0', b'0', '0', 3, 'String', 'channelCode', '', 'ALIYUN', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (421, 36, 'template_id', 'bigint(20)', '模板编号', b'0', b'0', '0', 4, 'Long', 'templateId', '', '20', b'0', b'0', b'1', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (422, 36, 'template_code', 'varchar(63)', '模板编码', b'0', b'0', '0', 5, 'String', 'templateCode', '', 'test-01', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (423, 36, 'template_type', 'tinyint(4)', '短信类型', b'0', b'0', '0', 6, 'Integer', 'templateType', 'sys_sms_template_type', '1', b'0', b'0', b'0', '=', b'1', 'select', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (424, 36, 'template_content', 'varchar(255)', '短信内容', b'0', b'0', '0', 7, 'String', 'templateContent', '', '你好,你的验证码是 1024', b'0', b'0', b'0', '=', b'1', 'editor', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (425, 36, 'template_params', 'varchar(255)', '短信参数', b'0', b'0', '0', 8, 'String', 'templateParams', '', 'name,code', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (426, 36, 'api_template_id', 'varchar(63)', '短信 API 的模板编号', b'0', b'0', '0', 9, 'String', 'apiTemplateId', '', 'SMS_207945135', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (427, 36, 'mobile', 'varchar(11)', '手机号', b'0', b'0', '0', 10, 'String', 'mobile', '', '15601691300', b'0', b'0', b'1', 'LIKE', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (428, 36, 'user_id', 'bigint(20)', '用户编号', b'1', b'0', '0', 11, 'Long', 'userId', '', '10', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (429, 36, 'user_type', 'tinyint(4)', '用户类型', b'1', b'0', '0', 12, 'Integer', 'userType', 'user_type', '1', b'0', b'0', b'0', '=', b'1', 'select', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (430, 36, 'send_status', 'tinyint(4)', '发送状态', b'0', b'0', '0', 13, 'Integer', 'sendStatus', 'sys_sms_send_status', '1', b'0', b'0', b'1', '=', b'1', 'radio', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (431, 36, 'send_time', 'datetime', '发送时间', b'1', b'0', '0', 14, 'Date', 'sendTime', '', NULL, b'0', b'0', b'1', 'BETWEEN', b'1', 'datetime', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (432, 36, 'send_code', 'int(11)', '发送结果的编码', b'1', b'0', '0', 15, 'Integer', 'sendCode', '', '0', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (433, 36, 'send_msg', 'varchar(255)', '发送结果的提示', b'1', b'0', '0', 16, 'String', 'sendMsg', '', '成功', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (434, 36, 'api_send_code', 'varchar(63)', '短信 API 发送结果的编码', b'1', b'0', '0', 17, 'String', 'apiSendCode', '', 'SUCCESS', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (435, 36, 'api_send_msg', 'varchar(255)', '短信 API 发送失败的提示', b'1', b'0', '0', 18, 'String', 'apiSendMsg', '', '成功', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (436, 36, 'api_request_id', 'varchar(255)', '短信 API 发送返回的唯一请求 ID', b'1', b'0', '0', 19, 'String', 'apiRequestId', '', '3837C6D3-B96F-428C-BBB2-86135D4B5B99', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (437, 36, 'api_serial_no', 'varchar(255)', '短信 API 发送返回的序号', b'1', b'0', '0', 20, 'String', 'apiSerialNo', '', '62923244790', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (438, 36, 'receive_status', 'tinyint(4)', '接收状态', b'0', b'0', '0', 21, 'Integer', 'receiveStatus', 'sys_sms_receive_status', '0', b'0', b'0', b'1', '=', b'1', 'radio', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (439, 36, 'receive_time', 'datetime', '接收时间', b'1', b'0', '0', 22, 'Date', 'receiveTime', '', NULL, b'0', b'0', b'1', 'BETWEEN', b'1', 'datetime', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (440, 36, 'api_receive_code', 'varchar(63)', 'API 接收结果的编码', b'1', b'0', '0', 23, 'String', 'apiReceiveCode', '', 'DELIVRD', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (441, 36, 'api_receive_msg', 'varchar(255)', 'API 接收结果的说明', b'1', b'0', '0', 24, 'String', 'apiReceiveMsg', '', 'DELIVRD', b'0', b'0', b'0', '=', b'1', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (442, 36, 'creator', 'varchar(64)', '创建者', b'1', b'0', '0', 25, 'String', 'creator', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (443, 36, 'create_time', 'datetime', '创建时间', b'0', b'0', '0', 26, 'Date', 'createTime', '', NULL, b'0', b'0', b'0', 'BETWEEN', b'1', 'datetime', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (444, 36, 'updater', 'varchar(64)', '更新者', b'1', b'0', '0', 27, 'String', 'updater', '', NULL, b'0', b'0', b'0', '=', b'0', 'input', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (445, 36, 'update_time', 'datetime', '更新时间', b'0', b'0', '0', 28, 'Date', 'updateTime', '', NULL, b'0', b'0', b'0', 'BETWEEN', b'0', 'datetime', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
INSERT INTO `tool_codegen_column` VALUES (446, 36, 'deleted', 'bit(1)', '是否删除', b'0', b'0', '0', 29, 'Boolean', 'deleted', '', NULL, b'0', b'0', b'0', '=', b'0', 'radio', '1', '2021-04-11 09:13:48', '1', '2021-04-11 20:33:54', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
@ -1151,7 +1379,7 @@ CREATE TABLE `tool_codegen_table` (
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表定义';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表定义';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of tool_codegen_table
|
||||
@ -1169,6 +1397,9 @@ INSERT INTO `tool_codegen_table` VALUES (28, 1, 'sys_dict_type', '字典类型
|
||||
INSERT INTO `tool_codegen_table` VALUES (29, 1, 'sys_dict_type', '字典类型表', NULL, 'system', 'dict', 'SysDictType', '字典类型', '芋艿', 1, NULL, '', '2021-03-06 03:52:57', '', '2021-03-06 04:03:52', b'0');
|
||||
INSERT INTO `tool_codegen_table` VALUES (30, 1, 'sys_dict_data', '字典数据表', NULL, 'system', 'type', 'SysDictData', '字典数据', '芋道源码', 1, NULL, '', '2021-03-06 06:48:28', '', '2021-03-06 06:50:47', b'0');
|
||||
INSERT INTO `tool_codegen_table` VALUES (33, 1, 'inf_file', '文件表', NULL, 'infra', 'file', 'InfFile', '文件', '芋艿', 1, 2, '1', '2021-03-13 09:43:20', '1', '2021-03-13 11:27:12', b'0');
|
||||
INSERT INTO `tool_codegen_table` VALUES (34, 1, 'sys_sms_channel', '短信渠道', NULL, 'system', 'sms', 'SysSmsChannel', '短信渠道', '芋道源码', 1, 1093, '1', '2021-04-03 13:39:06', '1', '2021-04-05 20:52:09', b'0');
|
||||
INSERT INTO `tool_codegen_table` VALUES (35, 1, 'sys_sms_template', '短信模板', NULL, 'system', 'sms', 'SysSmsTemplate', '短信模板', '芋道源码', 1, 1093, '1', '2021-04-03 13:58:55', '1', '2021-04-05 22:23:38', b'0');
|
||||
INSERT INTO `tool_codegen_table` VALUES (36, 1, 'sys_sms_log', '短信日志', NULL, 'system', 'sms', 'SysSmsLog', '短信日志', '芋道源码', 1, 1093, '1', '2021-04-11 01:12:57', '1', '2021-04-11 20:33:54', b'0');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
20
src/main/java/cn/iocoder/dashboard/common/core/KeyValue.java
Normal file
20
src/main/java/cn/iocoder/dashboard/common/core/KeyValue.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.dashboard.common.core;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Key Value 的键值对
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class KeyValue<K, V> {
|
||||
|
||||
private K key;
|
||||
private V value;
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.dashboard.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 通用状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DefaultBitFieldEnum {
|
||||
|
||||
NO(0, "否"),
|
||||
YES(1, "是");
|
||||
|
||||
/**
|
||||
* 状态值
|
||||
*/
|
||||
private final Integer val;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
package cn.iocoder.dashboard.common.exception;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 错误码对象
|
||||
*
|
||||
* 全局错误码,占用 [0, 999],参见 {@link GlobalException}
|
||||
* 全局错误码,占用 [0, 999], 参见 {@link GlobalErrorCodeConstants}
|
||||
* 业务异常错误码,占用 [1 000 000 000, +∞),参见 {@link ServiceErrorCodeRange}
|
||||
*
|
||||
* TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
|
||||
@ -21,11 +22,11 @@ public class ErrorCode {
|
||||
/**
|
||||
* 错误提示
|
||||
*/
|
||||
private final String message;
|
||||
private final String msg;
|
||||
|
||||
public ErrorCode(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.msg = message;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
package cn.iocoder.dashboard.common.exception;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 全局异常 Exception
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class GlobalException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* 全局错误码
|
||||
*
|
||||
* @see GlobalErrorCodeConstants
|
||||
*/
|
||||
private Integer code;
|
||||
/**
|
||||
* 错误提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 空构造方法,避免反序列化问题
|
||||
*/
|
||||
public GlobalException() {
|
||||
}
|
||||
|
||||
public GlobalException(ErrorCode errorCode) {
|
||||
this.code = errorCode.getCode();
|
||||
this.message = errorCode.getMessage();
|
||||
}
|
||||
|
||||
public GlobalException(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ public final class ServiceException extends RuntimeException {
|
||||
|
||||
public ServiceException(ErrorCode errorCode) {
|
||||
this.code = errorCode.getCode();
|
||||
this.message = errorCode.getMessage();
|
||||
this.message = errorCode.getMsg();
|
||||
}
|
||||
|
||||
public ServiceException(Integer code, String message) {
|
||||
|
@ -32,6 +32,7 @@ public interface GlobalErrorCodeConstants {
|
||||
|
||||
// ========== 自定义错误段 ==========
|
||||
ErrorCode REPEATED_REQUESTS = new ErrorCode(900, "重复请求,请稍后重试"); // 重复请求
|
||||
ErrorCode DEMO_DENY = new ErrorCode(901, "演示模式,禁止写操作");
|
||||
|
||||
ErrorCode UNKNOWN = new ErrorCode(999, "未知错误");
|
||||
|
||||
|
@ -47,12 +47,12 @@ public class ServiceExceptionUtil {
|
||||
// ========== 和 ServiceException 的集成 ==========
|
||||
|
||||
public static ServiceException exception(ErrorCode errorCode) {
|
||||
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
|
||||
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
|
||||
return exception0(errorCode.getCode(), messagePattern);
|
||||
}
|
||||
|
||||
public static ServiceException exception(ErrorCode errorCode, Object... params) {
|
||||
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMessage());
|
||||
String messagePattern = MESSAGES.getOrDefault(errorCode.getCode(), errorCode.getMsg());
|
||||
return exception0(errorCode.getCode(), messagePattern, params);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package cn.iocoder.dashboard.common.pojo;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.common.exception.GlobalException;
|
||||
import cn.iocoder.dashboard.common.exception.ServiceException;
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@ -9,6 +8,7 @@ import lombok.Data;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 通用返回
|
||||
@ -16,7 +16,7 @@ import java.io.Serializable;
|
||||
* @param <T> 数据泛型
|
||||
*/
|
||||
@Data
|
||||
public final class CommonResult<T> implements Serializable {
|
||||
public class CommonResult<T> implements Serializable {
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
@ -31,7 +31,7 @@ public final class CommonResult<T> implements Serializable {
|
||||
/**
|
||||
* 错误提示,用户可阅读
|
||||
*
|
||||
* @see ErrorCode#getMessage() ()
|
||||
* @see ErrorCode#getMsg() ()
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
@ -57,7 +57,7 @@ public final class CommonResult<T> implements Serializable {
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(ErrorCode errorCode) {
|
||||
return error(errorCode.getCode(), errorCode.getMessage());
|
||||
return error(errorCode.getCode(), errorCode.getMsg());
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
@ -68,9 +68,13 @@ public final class CommonResult<T> implements Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isSuccess(Integer code) {
|
||||
return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
}
|
||||
|
||||
@JsonIgnore // 避免 jackson 序列化
|
||||
public boolean isSuccess() {
|
||||
return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code);
|
||||
return isSuccess(code);
|
||||
}
|
||||
|
||||
@JsonIgnore // 避免 jackson 序列化
|
||||
@ -81,16 +85,12 @@ public final class CommonResult<T> implements Serializable {
|
||||
// ========= 和 Exception 异常体系集成 =========
|
||||
|
||||
/**
|
||||
* 判断是否有异常。如果有,则抛出 {@link GlobalException} 或 {@link ServiceException} 异常
|
||||
* 判断是否有异常。如果有,则抛出 {@link ServiceException} 异常
|
||||
*/
|
||||
public void checkError() throws GlobalException, ServiceException {
|
||||
public void checkError() throws ServiceException {
|
||||
if (isSuccess()) {
|
||||
return;
|
||||
}
|
||||
// 全局异常
|
||||
if (GlobalErrorCodeConstants.isMatch(code)) {
|
||||
throw new GlobalException(code, msg);
|
||||
}
|
||||
// 业务异常
|
||||
throw new ServiceException(code, msg);
|
||||
}
|
||||
@ -99,8 +99,4 @@ public final class CommonResult<T> implements Serializable {
|
||||
return error(serviceException.getCode(), serviceException.getMessage());
|
||||
}
|
||||
|
||||
public static <T> CommonResult<T> error(GlobalException globalException) {
|
||||
return error(globalException.getCode(), globalException.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,6 +13,11 @@ import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Excel {@link SysDictDataDO} 数据字典转换器
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class DictConvert implements Converter<Object> {
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.dashboard.framework.excel.core.convert;
|
||||
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import com.alibaba.excel.converters.Converter;
|
||||
import com.alibaba.excel.enums.CellDataTypeEnum;
|
||||
import com.alibaba.excel.metadata.CellData;
|
||||
import com.alibaba.excel.metadata.GlobalConfiguration;
|
||||
import com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||
|
||||
/**
|
||||
* Excel Json 转换器
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class JsonConvert implements Converter<Object> {
|
||||
|
||||
@Override
|
||||
public Class<?> supportJavaTypeKey() {
|
||||
throw new UnsupportedOperationException("暂不支持,也不需要");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellDataTypeEnum supportExcelTypeKey() {
|
||||
throw new UnsupportedOperationException("暂不支持,也不需要");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
|
||||
throw new UnsupportedOperationException("暂不支持,也不需要");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CellData<String> convertToExcelData(Object value, ExcelContentProperty contentProperty,
|
||||
GlobalConfiguration globalConfiguration) {
|
||||
// 生成 Excel 小表格
|
||||
return new CellData<>(JsonUtils.toJsonString(value));
|
||||
}
|
||||
|
||||
}
|
@ -48,8 +48,8 @@ public class RedisConfig {
|
||||
* 创建 Redis Pub/Sub 广播消费的容器
|
||||
*/
|
||||
@Bean
|
||||
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory factory,
|
||||
List<AbstractChannelMessageListener<?>> listeners) {
|
||||
public RedisMessageListenerContainer redisMessageListenerContainer(
|
||||
RedisConnectionFactory factory, List<AbstractChannelMessageListener<?>> listeners) {
|
||||
// 创建 RedisMessageListenerContainer 对象
|
||||
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
// 设置 RedisConnection 工厂。
|
||||
@ -69,8 +69,8 @@ public class RedisConfig {
|
||||
* Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html
|
||||
*/
|
||||
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||
public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(RedisTemplate<String, Object> redisTemplate,
|
||||
List<AbstractStreamMessageListener<?>> listeners) {
|
||||
public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
|
||||
RedisTemplate<String, Object> redisTemplate, List<AbstractStreamMessageListener<?>> listeners) {
|
||||
// 第一步,创建 StreamMessageListenerContainer 容器
|
||||
// 创建 options 配置
|
||||
StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
|
||||
|
@ -128,13 +128,13 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
// 设置每个请求的权限
|
||||
.authorizeRequests()
|
||||
// 登陆的接口,可匿名访问
|
||||
.antMatchers(webProperties.getApiPrefix() + "/login").anonymous()
|
||||
.antMatchers(api("/login")).anonymous()
|
||||
// 通用的接口,可匿名访问
|
||||
.antMatchers( webProperties.getApiPrefix() + "/system/captcha/**").anonymous()
|
||||
.antMatchers(api("/system/captcha/**")).anonymous()
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
// 文件的获取接口,可匿名访问
|
||||
.antMatchers(webProperties.getApiPrefix() + "/infra/file/get/**").anonymous()
|
||||
.antMatchers(api("/infra/file/get/**")).anonymous()
|
||||
// Swagger 接口文档
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
.antMatchers("/swagger-resources/**").anonymous()
|
||||
@ -148,13 +148,19 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
.antMatchers("/actuator/**").anonymous()
|
||||
// Druid 监控
|
||||
.antMatchers("/druid/**").anonymous()
|
||||
// 短信回调 API
|
||||
.antMatchers(api("/system/sms/callback/**")).anonymous()
|
||||
// 除上面外的所有请求全部需要鉴权认证
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.headers().frameOptions().disable();
|
||||
httpSecurity.logout().logoutUrl(webProperties.getApiPrefix() + "/logout").logoutSuccessHandler(logoutSuccessHandler);
|
||||
httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler);
|
||||
// 添加 JWT Filter
|
||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
private String api(String url) {
|
||||
return webProperties.getApiPrefix() + url;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.framework.sms.config;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.SmsClientFactoryImpl;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 短信配置类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Configuration
|
||||
public class SmsConfiguration {
|
||||
|
||||
@Bean
|
||||
public SmsClientFactory smsClientFactory() {
|
||||
return new SmsClientFactoryImpl();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信客户端接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 14:14
|
||||
*/
|
||||
public interface SmsClient {
|
||||
|
||||
/**
|
||||
* 获得渠道编号
|
||||
*
|
||||
* @return 渠道编号
|
||||
*/
|
||||
Long getId();
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param logId 日志编号
|
||||
* @param mobile 手机号
|
||||
* @param apiTemplateId 短信 API 的模板编号
|
||||
* @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序
|
||||
* @return 短信发送结果
|
||||
*/
|
||||
SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile, String apiTemplateId,
|
||||
List<KeyValue<String, Object>> templateParams);
|
||||
|
||||
/**
|
||||
* 解析接收短信的接收结果
|
||||
*
|
||||
* @param text 结果
|
||||
* @return 结果内容
|
||||
* @throws Throwable 当解析 text 发生异常时,则会抛出异常
|
||||
*/
|
||||
List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable;
|
||||
|
||||
/**
|
||||
* 查询指定的短信模板
|
||||
*
|
||||
* @param apiTemplateId 短信 API 的模板编号
|
||||
* @return 短信模板
|
||||
*/
|
||||
SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId);
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
|
||||
/**
|
||||
* 短信客户端工厂接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/28 14:01
|
||||
*/
|
||||
public interface SmsClientFactory {
|
||||
|
||||
/**
|
||||
* 获得短信 Client
|
||||
*
|
||||
* @param channelId 渠道编号
|
||||
* @return 短信 Client
|
||||
*/
|
||||
SmsClient getSmsClient(Long channelId);
|
||||
|
||||
/**
|
||||
* 获得短信 Client
|
||||
*
|
||||
* @param channelCode 渠道编码
|
||||
* @return 短信 Client
|
||||
*/
|
||||
SmsClient getSmsClient(String channelCode);
|
||||
|
||||
/**
|
||||
* 创建短信 Client
|
||||
*
|
||||
* @param properties 配置对象
|
||||
*/
|
||||
void createOrUpdateSmsClient(SmsChannelProperties properties);
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 将 API 的错误码,转换为通用的错误码
|
||||
*
|
||||
* @see SmsCommonResult
|
||||
* @see SmsFrameworkErrorCodeConstants
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SmsCodeMapping extends Function<String, ErrorCode> {
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 短信的 CommonResult 拓展类
|
||||
*
|
||||
* 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段
|
||||
*
|
||||
* 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SmsCommonResult<T> extends CommonResult<T> {
|
||||
|
||||
/**
|
||||
* API 返回错误码
|
||||
*
|
||||
* 由于第三方的错误码可能是字符串,所以使用 String 类型
|
||||
*/
|
||||
private String apiCode;
|
||||
/**
|
||||
* API 返回提示
|
||||
*/
|
||||
private String apiMsg;
|
||||
|
||||
/**
|
||||
* API 请求编号
|
||||
*/
|
||||
private String apiRequestId;
|
||||
|
||||
private SmsCommonResult() {
|
||||
}
|
||||
|
||||
public static <T> SmsCommonResult<T> build(String apiCode, String apiMsg, String apiRequestId,
|
||||
T data, SmsCodeMapping codeMapping) {
|
||||
Assert.notNull(codeMapping, "参数 codeMapping 不能为空");
|
||||
SmsCommonResult<T> result = new SmsCommonResult<T>().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId);
|
||||
result.setData(data);
|
||||
// 翻译错误码
|
||||
if (codeMapping != null) {
|
||||
ErrorCode errorCode = codeMapping.apply(apiCode);
|
||||
if (errorCode == null) {
|
||||
errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
|
||||
}
|
||||
result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> SmsCommonResult<T> error(Throwable ex) {
|
||||
SmsCommonResult<T> result = new SmsCommonResult<>();
|
||||
result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode());
|
||||
result.setMsg(ExceptionUtil.getRootCauseMessage(ex));
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 消息接收 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SmsReceiveRespDTO {
|
||||
|
||||
/**
|
||||
* 是否接收成功
|
||||
*/
|
||||
private Boolean success;
|
||||
/**
|
||||
* API 接收结果的编码
|
||||
*/
|
||||
private String errorCode;
|
||||
/**
|
||||
* API 接收结果的说明
|
||||
*/
|
||||
private String errorMsg;
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 用户接收时间
|
||||
*/
|
||||
private Date receiveTime;
|
||||
|
||||
/**
|
||||
* 短信 API 发送返回的序号
|
||||
*/
|
||||
private String serialNo;
|
||||
/**
|
||||
* 短信日志编号
|
||||
*
|
||||
* 对应 SysSmsLogDO 的编号
|
||||
*/
|
||||
private Long logId;
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 短信发送 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SmsSendRespDTO {
|
||||
|
||||
/**
|
||||
* 短信 API 发送返回的序号
|
||||
*/
|
||||
private String serialNo;
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.dto;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 短信模板 Response DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SmsTemplateRespDTO {
|
||||
|
||||
/**
|
||||
* 模板编号
|
||||
*/
|
||||
private String id;
|
||||
/**
|
||||
* 短信内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 审核状态
|
||||
*
|
||||
* 枚举 {@link SmsTemplateAuditStatusEnum}
|
||||
*/
|
||||
private Integer auditStatus;
|
||||
/**
|
||||
* 审核未通过的理由
|
||||
*/
|
||||
private String auditReason;
|
||||
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl;
|
||||
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信客户端抽象类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/2/1 9:28
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractSmsClient implements SmsClient {
|
||||
|
||||
/**
|
||||
* 短信渠道配置
|
||||
*/
|
||||
protected volatile SmsChannelProperties properties;
|
||||
/**
|
||||
* 错误码枚举类
|
||||
*/
|
||||
protected final SmsCodeMapping codeMapping;
|
||||
|
||||
/**
|
||||
* 短信客户端有参构造函数
|
||||
*
|
||||
* @param properties 短信配置
|
||||
*/
|
||||
public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) {
|
||||
this.properties = properties;
|
||||
this.codeMapping = codeMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
public final void init() {
|
||||
doInit();
|
||||
log.info("[init][配置({}) 初始化完成]", properties);
|
||||
}
|
||||
|
||||
public final void refresh(SmsChannelProperties properties) {
|
||||
// 判断是否更新
|
||||
if (properties.equals(this.properties)) {
|
||||
return;
|
||||
}
|
||||
log.info("[refresh][配置({})发生变化,重新初始化]", properties);
|
||||
this.properties = properties;
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义初始化
|
||||
*/
|
||||
protected abstract void doInit();
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return properties.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final SmsCommonResult<SmsSendRespDTO> sendSms(Long logId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
// 执行短信发送
|
||||
SmsCommonResult<SmsSendRespDTO> result;
|
||||
try {
|
||||
result = doSendSms(logId, mobile, apiTemplateId, templateParams);
|
||||
} catch (Throwable ex) {
|
||||
// 打印异常日志
|
||||
log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]",
|
||||
logId, mobile, apiTemplateId, templateParams, ex);
|
||||
// 封装返回
|
||||
return SmsCommonResult.error(ex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams)
|
||||
throws Throwable;
|
||||
|
||||
@Override
|
||||
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) throws Throwable {
|
||||
try {
|
||||
return doParseSmsReceiveStatus(text);
|
||||
} catch (Throwable ex) {
|
||||
log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable;
|
||||
|
||||
@Override
|
||||
public SmsCommonResult<SmsTemplateRespDTO> getSmsTemplate(String apiTemplateId) {
|
||||
// 执行短信发送
|
||||
SmsCommonResult<SmsTemplateRespDTO> result;
|
||||
try {
|
||||
result = doGetSmsTemplate(apiTemplateId);
|
||||
} catch (Throwable ex) {
|
||||
// 打印异常日志
|
||||
log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex);
|
||||
// 封装返回
|
||||
return SmsCommonResult.error(ex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable;
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun.AliyunSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* 短信客户端工厂接口
|
||||
*
|
||||
* @author zzf
|
||||
*/
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class SmsClientFactoryImpl implements SmsClientFactory {
|
||||
|
||||
/**
|
||||
* 短信客户端 Map
|
||||
* key:渠道编号,使用 {@link SmsChannelProperties#getId()}
|
||||
*/
|
||||
private final ConcurrentMap<Long, AbstractSmsClient> channelIdClients = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 短信客户端 Map
|
||||
* key:渠道编码,使用 {@link SmsChannelProperties#getCode()} ()}
|
||||
*
|
||||
* 注意,一些场景下,需要获得某个渠道类型的客户端,所以需要使用它。
|
||||
* 例如说,解析短信接收结果,是相对通用的,不需要使用某个渠道编号的 {@link #channelIdClients}
|
||||
*/
|
||||
private final ConcurrentMap<String, AbstractSmsClient> channelCodeClients = new ConcurrentHashMap<>();
|
||||
|
||||
public SmsClientFactoryImpl() {
|
||||
// 初始化 channelCodeClients 集合
|
||||
Arrays.stream(SmsChannelEnum.values()).forEach(channel -> {
|
||||
// 创建一个空的 SmsChannelProperties 对象
|
||||
SmsChannelProperties properties = new SmsChannelProperties().setCode(channel.getCode())
|
||||
.setApiKey("default").setApiSecret("default");
|
||||
// 创建 Sms 客户端
|
||||
AbstractSmsClient smsClient = createSmsClient(properties);
|
||||
channelCodeClients.put(channel.getCode(), smsClient);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsClient getSmsClient(Long channelId) {
|
||||
return channelIdClients.get(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmsClient getSmsClient(String channelCode) {
|
||||
return channelCodeClients.get(channelCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createOrUpdateSmsClient(SmsChannelProperties properties) {
|
||||
AbstractSmsClient client = channelIdClients.get(properties.getId());
|
||||
if (client == null) {
|
||||
client = this.createSmsClient(properties);
|
||||
client.init();
|
||||
channelIdClients.put(client.getId(), client);
|
||||
} else {
|
||||
client.refresh(properties);
|
||||
}
|
||||
}
|
||||
|
||||
private AbstractSmsClient createSmsClient(SmsChannelProperties properties) {
|
||||
SmsChannelEnum channelEnum = SmsChannelEnum.getByCode(properties.getCode());
|
||||
Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum));
|
||||
// 创建客户端
|
||||
switch (channelEnum) {
|
||||
case ALIYUN: return new AliyunSmsClient(properties);
|
||||
case YUN_PIAN: return new YunpianSmsClient(properties);
|
||||
case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties);
|
||||
}
|
||||
// 创建失败,错误日志 + 抛出异常
|
||||
log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties);
|
||||
throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.util.collection.MapUtils;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import com.aliyuncs.AcsRequest;
|
||||
import com.aliyuncs.AcsResponse;
|
||||
import com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.aliyuncs.profile.IClientProfile;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||
|
||||
/**
|
||||
* 阿里短信客户端的实现类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 14:17
|
||||
*/
|
||||
@Slf4j
|
||||
public class AliyunSmsClient extends AbstractSmsClient {
|
||||
|
||||
/**
|
||||
* REGION, 使用杭州
|
||||
*/
|
||||
private static final String ENDPOINT = "cn-hangzhou";
|
||||
|
||||
/**
|
||||
* 阿里云客户端
|
||||
*/
|
||||
private volatile IAcsClient client;
|
||||
|
||||
public AliyunSmsClient(SmsChannelProperties properties) {
|
||||
super(properties, new AliyunSmsCodeMapping());
|
||||
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
|
||||
Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret());
|
||||
client = new DefaultAcsClient(profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||
// 构建参数
|
||||
SendSmsRequest request = new SendSmsRequest();
|
||||
request.setPhoneNumbers(mobile);
|
||||
request.setSignName(properties.getSignature());
|
||||
request.setTemplateCode(apiTemplateId);
|
||||
request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams)));
|
||||
request.setOutId(String.valueOf(sendLogId));
|
||||
// 执行请求
|
||||
return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
|
||||
return statuses.stream().map(status -> {
|
||||
SmsReceiveRespDTO resp = new SmsReceiveRespDTO();
|
||||
resp.setSuccess(status.getSuccess());
|
||||
resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg());
|
||||
resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime());
|
||||
resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()));
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
|
||||
// 构建参数
|
||||
QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
|
||||
request.setTemplateCode(apiTemplateId);
|
||||
// 执行请求
|
||||
return invoke(request, response -> {
|
||||
SmsTemplateRespDTO data = new SmsTemplateRespDTO();
|
||||
data.setId(response.getTemplateCode()).setContent(response.getTemplateContent());
|
||||
data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason());
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
|
||||
switch (templateStatus) {
|
||||
case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
|
||||
case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
|
||||
case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
|
||||
default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
<T extends AcsResponse, R> SmsCommonResult<R> invoke(AcsRequest<T> request, Function<T, R> responseConsumer) {
|
||||
try {
|
||||
// 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射
|
||||
T sendResult = client.getAcsResponse(request);
|
||||
String code = (String) ReflectUtil.getFieldValue(sendResult, "code");
|
||||
String message = (String) ReflectUtil.getFieldValue(sendResult, "message");
|
||||
String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId");
|
||||
// 解析结果
|
||||
R data = null;
|
||||
if (Objects.equals(code, "OK")) { // 请求成功的情况下
|
||||
data = responseConsumer.apply(sendResult);
|
||||
}
|
||||
// 拼接结果
|
||||
return SmsCommonResult.build(code, message, requestId, data, codeMapping);
|
||||
} catch (ClientException ex) {
|
||||
return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping);
|
||||
}
|
||||
}
|
||||
|
||||
private static String formatResultMsg(ClientException ex) {
|
||||
if (StrUtil.isEmpty(ex.getErrorDescription())) {
|
||||
return ex.getErrMsg();
|
||||
}
|
||||
return ex.getErrMsg() + " => " + ex.getErrorDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信接收状态
|
||||
*
|
||||
* 参见 https://help.aliyun.com/document_detail/101867.html 文档
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public static class SmsReceiveStatus {
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@JsonProperty("phone_number")
|
||||
private String phoneNumber;
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@JsonProperty("send_time")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private Date sendTime;
|
||||
/**
|
||||
* 状态报告时间
|
||||
*/
|
||||
@JsonProperty("report_time")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private Date reportTime;
|
||||
/**
|
||||
* 是否接收成功
|
||||
*/
|
||||
private Boolean success;
|
||||
/**
|
||||
* 状态报告说明
|
||||
*/
|
||||
@JsonProperty("err_msg")
|
||||
private String errMsg;
|
||||
/**
|
||||
* 状态报告编码
|
||||
*/
|
||||
@JsonProperty("err_code")
|
||||
private String errCode;
|
||||
/**
|
||||
* 发送序列号
|
||||
*/
|
||||
@JsonProperty("biz_id")
|
||||
private String bizId;
|
||||
/**
|
||||
* 用户序列号
|
||||
*
|
||||
* 这里我们传递的是 SysSmsLogDO 的日志编号
|
||||
*/
|
||||
@JsonProperty("out_id")
|
||||
private String outId;
|
||||
/**
|
||||
* 短信长度,例如说 1、2、3
|
||||
*
|
||||
* 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送
|
||||
*/
|
||||
@JsonProperty("sms_size")
|
||||
private Integer smsSize;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
|
||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 阿里云的 SmsCodeMapping 实现类
|
||||
*
|
||||
* 参见 https://help.aliyun.com/document_detail/101346.htm 文档
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class AliyunSmsCodeMapping implements SmsCodeMapping {
|
||||
|
||||
@Override
|
||||
public ErrorCode apply(String apiCode) {
|
||||
switch (apiCode) {
|
||||
case "OK": return GlobalErrorCodeConstants.SUCCESS;
|
||||
case "isv.ACCOUNT_NOT_EXISTS":
|
||||
case "isv.ACCOUNT_ABNORMAL":
|
||||
case "MissingAccessKeyId": return SMS_ACCOUNT_INVALID;
|
||||
case "isp.RAM_PERMISSION_DENY": return SMS_PERMISSION_DENY;
|
||||
case "isv.INVALID_JSON_PARAM":
|
||||
case "isv.INVALID_PARAMETERS": return SMS_API_PARAM_ERROR;
|
||||
case "isv.BUSINESS_LIMIT_CONTROL": return SMS_SEND_BUSINESS_LIMIT_CONTROL;
|
||||
case "isv.DAY_LIMIT_CONTROL": return SMS_SEND_DAY_LIMIT_CONTROL;
|
||||
case "isv.SMS_CONTENT_ILLEGAL": return SMS_SEND_CONTENT_INVALID;
|
||||
case "isv.SMS_TEMPLATE_ILLEGAL": return SMS_TEMPLATE_INVALID;
|
||||
case "isv.SMS_SIGNATURE_ILLEGAL":
|
||||
case "isv.SIGN_NAME_ILLEGAL":
|
||||
case "isv.SMS_SIGN_ILLEGAL": return SMS_SIGN_INVALID;
|
||||
case "isv.AMOUNT_NOT_ENOUGH":
|
||||
case "isv.OUT_OF_SERVICE": return SMS_ACCOUNT_MONEY_NOT_ENOUGH;
|
||||
case "isv.MOBILE_NUMBER_ILLEGAL": return SMS_MOBILE_INVALID;
|
||||
case "isv.TEMPLATE_MISSING_PARAMETERS": return SMS_TEMPLATE_PARAM_ERROR;
|
||||
}
|
||||
return SMS_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.debug;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
|
||||
|
||||
/**
|
||||
* 钉钉的 SmsCodeMapping 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DebugDingTalkCodeMapping implements SmsCodeMapping {
|
||||
|
||||
@Override
|
||||
public ErrorCode apply(String apiCode) {
|
||||
return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SMS_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.debug;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.util.collection.MapUtils;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 基于钉钉 WebHook 实现的调试的短信客户端实现类
|
||||
*
|
||||
* 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DebugDingTalkSmsClient extends AbstractSmsClient {
|
||||
|
||||
public DebugDingTalkSmsClient(SmsChannelProperties properties) {
|
||||
super(properties, new DebugDingTalkCodeMapping());
|
||||
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
|
||||
Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
// 构建请求
|
||||
String url = buildUrl("robot/send");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("msgtype", "text");
|
||||
String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s",
|
||||
mobile, sendLogId, MapUtils.convertMap(templateParams));
|
||||
params.put("text", MapUtil.builder().put("content", content).build());
|
||||
// 执行请求
|
||||
String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params));
|
||||
// 解析结果
|
||||
Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class);
|
||||
return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"),
|
||||
null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求地址
|
||||
*
|
||||
* 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档
|
||||
*
|
||||
* @param path 请求路径
|
||||
* @return 请求地址
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private String buildUrl(String path) {
|
||||
// 生成 timestamp
|
||||
long timestamp = System.currentTimeMillis();
|
||||
// 生成 sign
|
||||
String secret = properties.getApiSecret();
|
||||
String stringToSign = timestamp + "\n" + secret;
|
||||
byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign);
|
||||
String sign = Base64.encode(signData);
|
||||
// 构建最终 URL
|
||||
return String.format("https://oapi.dingtalk.com/%s?access_token=%s×tamp=%d&sign=%s",
|
||||
path, properties.getApiKey(), timestamp, sign);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
|
||||
SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("")
|
||||
.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason("");
|
||||
return SmsCommonResult.build("0", "success", null, data, codeMapping);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.yunpian.sdk.YunpianClient;
|
||||
import com.yunpian.sdk.constant.YunpianConstant;
|
||||
import com.yunpian.sdk.model.Result;
|
||||
import com.yunpian.sdk.model.Template;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.TIME_ZONE_DEFAULT;
|
||||
|
||||
/**
|
||||
* 云片短信客户端的实现类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 9:48 2021/3/5
|
||||
*/
|
||||
@Slf4j
|
||||
public class YunpianSmsClient extends AbstractSmsClient {
|
||||
|
||||
/**
|
||||
* 云信短信客户端
|
||||
*/
|
||||
private volatile YunpianClient client;
|
||||
|
||||
public YunpianSmsClient(SmsChannelProperties properties) {
|
||||
super(properties, new YunpianSmsCodeMapping());
|
||||
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doInit() {
|
||||
YunpianClient oldClient = client;
|
||||
// 初始化新的客户端
|
||||
YunpianClient newClient = new YunpianClient(properties.getApiKey());
|
||||
newClient.init();
|
||||
this.client = newClient;
|
||||
// 销毁老的客户端
|
||||
if (oldClient != null) {
|
||||
oldClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
return invoke(() -> {
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put(YunpianConstant.MOBILE, mobile);
|
||||
request.put(YunpianConstant.TPL_ID, apiTemplateId);
|
||||
request.put(YunpianConstant.TPL_VALUE, formatTplValue(templateParams));
|
||||
request.put(YunpianConstant.UID, String.valueOf(sendLogId));
|
||||
request.put(YunpianConstant.CALLBACK_URL, properties.getCallbackUrl());
|
||||
return client.sms().tpl_single_send(request);
|
||||
}, response -> new SmsSendRespDTO().setSerialNo(String.valueOf(response.getSid())));
|
||||
}
|
||||
|
||||
private static String formatTplValue(List<KeyValue<String, Object>> templateParams) {
|
||||
if (CollUtil.isEmpty(templateParams)) {
|
||||
return "";
|
||||
}
|
||||
// 参考 https://www.yunpian.com/official/document/sms/zh_cn/introduction_demos_encode_sample 格式化
|
||||
StringJoiner joiner = new StringJoiner("&");
|
||||
templateParams.forEach(param -> joiner.add(String.format("#%s#=%s", param.getKey(), URLUtil.encode(String.valueOf(param.getValue())))));
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class);
|
||||
return statuses.stream().map(status -> {
|
||||
SmsReceiveRespDTO resp = new SmsReceiveRespDTO();
|
||||
resp.setSuccess(Objects.equals(status.getReportStatus(), "SUCCESS"));
|
||||
resp.setErrorCode(status.getErrorMsg()).setErrorMsg(status.getErrorDetail());
|
||||
resp.setMobile(status.getMobile()).setReceiveTime(status.getUserReceiveTime());
|
||||
resp.setSerialNo(String.valueOf(status.getSid())).setLogId(status.getUid());
|
||||
return resp;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) throws Throwable {
|
||||
return invoke(() -> {
|
||||
Map<String, String> request = new HashMap<>();
|
||||
request.put(YunpianConstant.APIKEY, properties.getApiKey());
|
||||
request.put(YunpianConstant.TPL_ID, apiTemplateId);
|
||||
return client.tpl().get(request);
|
||||
}, response -> {
|
||||
Template template = response.get(0);
|
||||
return new SmsTemplateRespDTO().setId(String.valueOf(template.getTpl_id())).setContent(template.getTpl_content())
|
||||
.setAuditStatus(convertSmsTemplateAuditStatus(template.getCheck_status())).setAuditReason(template.getReason());
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Integer convertSmsTemplateAuditStatus(String checkStatus) {
|
||||
switch (checkStatus) {
|
||||
case "CHECKING": return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
|
||||
case "SUCCESS": return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
|
||||
case "FAIL": return SmsTemplateAuditStatusEnum.FAIL.getStatus();
|
||||
default: throw new IllegalArgumentException(String.format("未知审核状态(%s)", checkStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
<T, R> SmsCommonResult<R> invoke(Supplier<Result<T>> requestConsumer, Function<T, R> responseConsumer) throws Throwable {
|
||||
// 执行请求
|
||||
Result<T> result = requestConsumer.get();
|
||||
if (result.getThrowable() != null) {
|
||||
throw result.getThrowable();
|
||||
}
|
||||
// 解析结果
|
||||
R data = null;
|
||||
if (result.getData() != null) {
|
||||
data = responseConsumer.apply(result.getData());
|
||||
}
|
||||
// 拼接结果
|
||||
return SmsCommonResult.build(String.valueOf(result.getCode()), formatResultMsg(result), null, data, codeMapping);
|
||||
}
|
||||
|
||||
private static String formatResultMsg(Result<?> sendResult) {
|
||||
if (StrUtil.isEmpty(sendResult.getDetail())) {
|
||||
return sendResult.getMsg();
|
||||
}
|
||||
return sendResult.getMsg() + " => " + sendResult.getDetail();
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信接收状态
|
||||
*
|
||||
* 参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public static class SmsReceiveStatus {
|
||||
|
||||
/**
|
||||
* 接收状态
|
||||
*
|
||||
* 目前仅有 SUCCESS / FAIL,所以使用 Boolean 接收
|
||||
*/
|
||||
@JsonProperty("report_status")
|
||||
private String reportStatus;
|
||||
/**
|
||||
* 接收手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 运营商返回的代码,如:"DB:0103"
|
||||
*
|
||||
* 由于不同运营商信息不同,此字段仅供参考;
|
||||
*/
|
||||
@JsonProperty("error_msg")
|
||||
private String errorMsg;
|
||||
/**
|
||||
* 运营商反馈代码的中文解释
|
||||
*
|
||||
* 默认不推送此字段,如需推送,请联系客服
|
||||
*/
|
||||
@JsonProperty("error_detail")
|
||||
private String errorDetail;
|
||||
/**
|
||||
* 短信编号
|
||||
*/
|
||||
private Long sid;
|
||||
/**
|
||||
* 用户自定义 id
|
||||
*
|
||||
* 这里我们传递的是 SysSmsLogDO 的日志编号
|
||||
*/
|
||||
private Long uid;
|
||||
/**
|
||||
* 用户接收时间
|
||||
*/
|
||||
@JsonProperty("user_receive_time")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
||||
private Date userReceiveTime;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
|
||||
import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.SUCCESS;
|
||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*;
|
||||
import static com.yunpian.sdk.constant.Code.*;
|
||||
|
||||
/**
|
||||
* 云片的 SmsCodeMapping 实现类
|
||||
*
|
||||
* 参见 https://www.yunpian.com/official/document/sms/zh_CN/returnvalue_common 文档
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class YunpianSmsCodeMapping implements SmsCodeMapping {
|
||||
|
||||
@Override
|
||||
public ErrorCode apply(String apiCode) {
|
||||
int code = Integer.parseInt(apiCode);
|
||||
switch (code) {
|
||||
case OK: return SUCCESS;
|
||||
case ARGUMENT_MISSING: return SMS_API_PARAM_ERROR;
|
||||
case BAD_ARGUMENT_FORMAT: return SMS_TEMPLATE_PARAM_ERROR;
|
||||
case TPL_NOT_FOUND:
|
||||
case TPL_NOT_VALID: return SMS_TEMPLATE_INVALID;
|
||||
case MONEY_NOT_ENOUGH: return SMS_ACCOUNT_MONEY_NOT_ENOUGH;
|
||||
case BLACK_WORD: return SMS_SEND_CONTENT_INVALID;
|
||||
case DUP_IN_SHORT_TIME:
|
||||
case TOO_MANY_TIME_IN_5:
|
||||
case DAY_LIMIT_PER_MOBILE:
|
||||
case HOUR_LIMIT_PER_MOBILE: return SMS_SEND_BUSINESS_LIMIT_CONTROL;
|
||||
case BLACK_PHONE_FILTER: return SMS_MOBILE_BLACK;
|
||||
case SIGN_NOT_MATCH:
|
||||
case BAD_SIGN_FORMAT:
|
||||
case SIGN_NOT_VALID: return SMS_SIGN_INVALID;
|
||||
case BAD_API_KEY: return SMS_ACCOUNT_INVALID;
|
||||
case API_NOT_ALLOWED: return SMS_PERMISSION_DENY;
|
||||
case IP_NOT_ALLOWED: return SMS_IP_DENY;
|
||||
}
|
||||
return SMS_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.enums;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信渠道枚举
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 10:56
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SmsChannelEnum {
|
||||
|
||||
DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
|
||||
YUN_PIAN("YUN_PIAN", "云片"),
|
||||
ALIYUN("ALIYUN", "阿里云"),
|
||||
// TENCENT("TENCENT", "腾讯云"),
|
||||
// HUA_WEI("HUA_WEI", "华为云"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*/
|
||||
private final String code;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
public static SmsChannelEnum getByCode(String code) {
|
||||
return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.enums;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* 短信框架的错误码枚举
|
||||
*
|
||||
* 短信框架,使用 2-001-000-000 段
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SmsFrameworkErrorCodeConstants {
|
||||
|
||||
ErrorCode SMS_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析");
|
||||
|
||||
// ========== 权限 / 限流等相关 2001000100 ==========
|
||||
|
||||
ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限");
|
||||
// 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信
|
||||
ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信");
|
||||
|
||||
// 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。
|
||||
ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流");
|
||||
// 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。
|
||||
ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流");
|
||||
|
||||
ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词");
|
||||
|
||||
// ========== 模板相关 2001000200 ==========
|
||||
ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在
|
||||
ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确");
|
||||
|
||||
// ========== 签名相关 2001000300 ==========
|
||||
ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用");
|
||||
|
||||
// ========== 账户相关 2001000400 ==========
|
||||
ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足");
|
||||
ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在");
|
||||
|
||||
// ========== 其它相关 2001000900 开头 ==========
|
||||
ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失");
|
||||
ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确");
|
||||
ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中");
|
||||
|
||||
ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常");
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信模板的审核状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum SmsTemplateAuditStatusEnum {
|
||||
|
||||
CHECKING(1),
|
||||
SUCCESS(2),
|
||||
FAIL(3);
|
||||
|
||||
private final Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.property;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import lombok.Data;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 短信渠道配置类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 17:01
|
||||
*/
|
||||
@Data
|
||||
@Validated
|
||||
public class SmsChannelProperties {
|
||||
|
||||
/**
|
||||
* 渠道编号
|
||||
*/
|
||||
@NotNull(message = "短信渠道 ID 不能为空")
|
||||
private Long id;
|
||||
/**
|
||||
* 短信签名
|
||||
*/
|
||||
@NotEmpty(message = "短信签名不能为空")
|
||||
private String signature;
|
||||
/**
|
||||
* 渠道编码
|
||||
*
|
||||
* 枚举 {@link SmsChannelEnum}
|
||||
*/
|
||||
@NotEmpty(message = "渠道编码不能为空")
|
||||
private String code;
|
||||
/**
|
||||
* 短信 API 的账号
|
||||
*/
|
||||
@NotEmpty(message = "短信 API 的账号不能为空")
|
||||
private String apiKey;
|
||||
/**
|
||||
* 短信 API 的秘钥
|
||||
*/
|
||||
@NotEmpty(message = "短信 API 的秘钥不能为空")
|
||||
private String apiSecret;
|
||||
/**
|
||||
* 短信发送回调 URL
|
||||
*/
|
||||
private String callbackUrl;
|
||||
|
||||
}
|
@ -2,7 +2,9 @@ package cn.iocoder.dashboard.framework.web.config;
|
||||
|
||||
import cn.iocoder.dashboard.framework.web.core.enums.FilterOrderEnum;
|
||||
import cn.iocoder.dashboard.framework.web.core.filter.CacheRequestBodyFilter;
|
||||
import cn.iocoder.dashboard.framework.web.core.filter.DemoFilter;
|
||||
import cn.iocoder.dashboard.framework.web.core.filter.XssFilter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -68,6 +70,15 @@ public class WebConfiguration implements WebMvcConfigurer {
|
||||
return createFilterBean(new XssFilter(properties, pathMatcher), FilterOrderEnum.XSS_FILTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 DemoFilter Bean,演示模式
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "yudao.demo", havingValue = "true")
|
||||
public FilterRegistrationBean<DemoFilter> demoFilter() {
|
||||
return createFilterBean(new DemoFilter(), FilterOrderEnum.DEMO_FILTER);
|
||||
}
|
||||
|
||||
private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
|
||||
FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
|
||||
bean.setOrder(order);
|
||||
|
@ -9,6 +9,7 @@ public interface FilterOrderEnum {
|
||||
|
||||
int CORS_FILTER = Integer.MIN_VALUE;
|
||||
|
||||
|
||||
int REQUEST_BODY_CACHE_FILTER = Integer.MIN_VALUE + 500;
|
||||
|
||||
// OrderedRequestContextFilter 默认为 -105,用于国际化上下文等等
|
||||
@ -19,4 +20,6 @@ public interface FilterOrderEnum {
|
||||
|
||||
// Spring Security Filter 默认为 -100,可见 SecurityProperties 配置属性类
|
||||
|
||||
int DEMO_FILTER = Integer.MAX_VALUE;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.dashboard.framework.web.core.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.dashboard.util.servlet.ServletUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import static cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY;
|
||||
|
||||
/**
|
||||
* 演示 Filter,禁止用户发起写操作,避免影响测试数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DemoFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
String method = request.getMethod();
|
||||
return !StrUtil.equalsAnyIgnoreCase(method, "POST", "PUT", "DELETE") // 写操作时,不进行过滤率
|
||||
|| SecurityFrameworkUtils.getLoginUser() == null; // 非登陆用户时,不进行过滤
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
|
||||
// 直接返回 DEMO_DENY 的结果。即,请求不继续
|
||||
ServletUtils.writeJSON(response, CommonResult.error(DEMO_DENY));
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,6 @@ package cn.iocoder.dashboard.framework.web.core.handler;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.iocoder.dashboard.common.exception.GlobalException;
|
||||
import cn.iocoder.dashboard.common.exception.ServiceException;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService;
|
||||
@ -96,9 +95,6 @@ public class GlobalExceptionHandler {
|
||||
if (ex instanceof AccessDeniedException) {
|
||||
return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
|
||||
}
|
||||
if (ex instanceof GlobalException) {
|
||||
return globalExceptionHandler(request, (GlobalException) ex);
|
||||
}
|
||||
return defaultExceptionHandler(request, ex);
|
||||
}
|
||||
|
||||
@ -222,25 +218,6 @@ public class GlobalExceptionHandler {
|
||||
return CommonResult.error(ex.getCode(), ex.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理全局异常 ServiceException
|
||||
*
|
||||
* 例如说,Dubbo 请求超时,调用的 Dubbo 服务系统异常
|
||||
*/
|
||||
@ExceptionHandler(value = GlobalException.class)
|
||||
public CommonResult<?> globalExceptionHandler(HttpServletRequest req, GlobalException ex) {
|
||||
// 系统异常时,才打印异常日志
|
||||
if (INTERNAL_SERVER_ERROR.getCode().equals(ex.getCode())) {
|
||||
// 插入异常日志
|
||||
this.createExceptionLog(req, ex);
|
||||
// 普通全局异常,打印 info 日志即可
|
||||
} else {
|
||||
log.info("[globalExceptionHandler]", ex);
|
||||
}
|
||||
// 返回 ERROR CommonResult
|
||||
return CommonResult.error(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理系统异常,兜底处理所有的一切
|
||||
*/
|
||||
@ -250,7 +227,7 @@ public class GlobalExceptionHandler {
|
||||
// 插入异常日志
|
||||
this.createExceptionLog(req, ex);
|
||||
// 返回 ERROR CommonResult
|
||||
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMessage());
|
||||
return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
|
||||
}
|
||||
|
||||
private void createExceptionLog(HttpServletRequest req, Throwable e) {
|
||||
|
@ -61,7 +61,7 @@ public class SysDictDataController {
|
||||
@GetMapping("/list-all-simple")
|
||||
@ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
|
||||
// 无需添加权限认证,因为前端全局都需要
|
||||
public CommonResult<List<SysDictDataSimpleVO>> getSimpleDictDatas() {
|
||||
public CommonResult<List<SysDictDataSimpleRespVO>> getSimpleDictDatas() {
|
||||
List<SysDictDataDO> list = dictDataService.getDictDatas();
|
||||
return success(SysDictDataConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class SysDictTypeController {
|
||||
return success(dictTypeId);
|
||||
}
|
||||
|
||||
@PostMapping("update")
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("修改字典类型")
|
||||
@PreAuthorize("@ss.hasPermission('system:dict:update')")
|
||||
public CommonResult<Boolean> updateDictType(@Valid @RequestBody SysDictTypeUpdateReqVO reqVO) {
|
||||
|
@ -4,9 +4,9 @@ import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("数据字典精简 VO")
|
||||
@ApiModel("数据字典精简 Response VO")
|
||||
@Data
|
||||
public class SysDictDataSimpleVO {
|
||||
public class SysDictDataSimpleRespVO {
|
||||
|
||||
@ApiModelProperty(value = "字典类型", required = true, example = "gender")
|
||||
private String dictType;
|
@ -0,0 +1,49 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "短信回调")
|
||||
@RestController
|
||||
@RequestMapping("/system/sms/callback")
|
||||
public class SmsCallbackController {
|
||||
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
@PostMapping("/sms/yunpian")
|
||||
@ApiOperation(value = "云片短信的回调", notes = "参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档")
|
||||
@ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = Long.class)
|
||||
@OperateLog(enable = false)
|
||||
public String receiveYunpianSmsStatus(@RequestParam("sms_status") String smsStatus) throws Throwable {
|
||||
String text = URLUtil.decode(smsStatus); // decode 解码参数,因为它被 encode
|
||||
smsService.receiveSmsStatus(SmsChannelEnum.YUN_PIAN.getCode(), text);
|
||||
return "SUCCESS"; // 约定返回 SUCCESS 为成功
|
||||
}
|
||||
|
||||
@PostMapping("/sms/aliyun")
|
||||
@ApiOperation(value = "阿里云短信的回调", notes = "参见 https://help.aliyun.com/document_detail/120998.html 文档")
|
||||
@OperateLog(enable = false)
|
||||
public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable {
|
||||
String text = ServletUtil.getBody(request);
|
||||
smsService.receiveSmsStatus(SmsChannelEnum.ALIYUN.getCode(), text);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.*;
|
||||
import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsChannelConvert;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "短信渠道")
|
||||
@RestController
|
||||
@RequestMapping("system/sms-channel")
|
||||
public class SysSmsChannelController {
|
||||
|
||||
@Resource
|
||||
private SysSmsChannelService smsChannelService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建短信渠道")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:create')")
|
||||
public CommonResult<Long> createSmsChannel(@Valid @RequestBody SysSmsChannelCreateReqVO createReqVO) {
|
||||
return success(smsChannelService.createSmsChannel(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新短信渠道")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:update')")
|
||||
public CommonResult<Boolean> updateSmsChannel(@Valid @RequestBody SysSmsChannelUpdateReqVO updateReqVO) {
|
||||
smsChannelService.updateSmsChannel(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除短信渠道")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:delete')")
|
||||
public CommonResult<Boolean> deleteSmsChannel(@RequestParam("id") Long id) {
|
||||
smsChannelService.deleteSmsChannel(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得短信渠道")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
|
||||
public CommonResult<SysSmsChannelRespVO> getSmsChannel(@RequestParam("id") Long id) {
|
||||
SysSmsChannelDO smsChannel = smsChannelService.getSmsChannel(id);
|
||||
return success(SysSmsChannelConvert.INSTANCE.convert(smsChannel));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得短信渠道分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-channel:query')")
|
||||
public CommonResult<PageResult<SysSmsChannelRespVO>> getSmsChannelPage(@Valid SysSmsChannelPageReqVO pageVO) {
|
||||
PageResult<SysSmsChannelDO> pageResult = smsChannelService.getSmsChannelPage(pageVO);
|
||||
return success(SysSmsChannelConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/list-all-simple")
|
||||
@ApiOperation(value = "获得短信渠道精简列表", notes = "包含被禁用的短信渠道")
|
||||
public CommonResult<List<SysSmsChannelSimpleRespVO>> getSimpleSmsChannels() {
|
||||
List<SysSmsChannelDO> list = smsChannelService.getSmsChannelList();
|
||||
// 排序后,返回给前端
|
||||
list.sort(Comparator.comparing(SysSmsChannelDO::getId));
|
||||
return success(SysSmsChannelConvert.INSTANCE.convertList03(list));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsLogConvert;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsLogService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Api(tags = "短信日志")
|
||||
@RestController
|
||||
@RequestMapping("/system/sms-log")
|
||||
@Validated
|
||||
public class SysSmsLogController {
|
||||
|
||||
@Resource
|
||||
private SysSmsLogService smsLogService;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得短信日志分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-log:query')")
|
||||
public CommonResult<PageResult<SysSmsLogRespVO>> getSmsLogPage(@Valid SysSmsLogPageReqVO pageVO) {
|
||||
PageResult<SysSmsLogDO> pageResult = smsLogService.getSmsLogPage(pageVO);
|
||||
return success(SysSmsLogConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ApiOperation("导出短信日志 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-log:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportSmsLogExcel(@Valid SysSmsLogExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<SysSmsLogDO> list = smsLogService.getSmsLogList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<SysSmsLogExcelVO> datas = SysSmsLogConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "短信日志.xls", "数据", SysSmsLogExcelVO.class, datas);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
### 请求 /menu/list 接口 => 成功
|
||||
POST {{baseUrl}}/system/sms-template/send-sms
|
||||
Authorization: Bearer {{token}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"code": "test_01",
|
||||
"params": {
|
||||
"key01": "value01",
|
||||
"key02": "value02"
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.*;
|
||||
import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsTemplateConvert;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsTemplateService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Api("短信模板")
|
||||
@RestController
|
||||
@RequestMapping("/system/sms-template")
|
||||
public class SysSmsTemplateController {
|
||||
|
||||
@Resource
|
||||
private SysSmsTemplateService smsTemplateService;
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("创建短信模板")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:create')")
|
||||
public CommonResult<Long> createSmsTemplate(@Valid @RequestBody SysSmsTemplateCreateReqVO createReqVO) {
|
||||
return success(smsTemplateService.createSmsTemplate(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("更新短信模板")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:update')")
|
||||
public CommonResult<Boolean> updateSmsTemplate(@Valid @RequestBody SysSmsTemplateUpdateReqVO updateReqVO) {
|
||||
smsTemplateService.updateSmsTemplate(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除短信模板")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:delete')")
|
||||
public CommonResult<Boolean> deleteSmsTemplate(@RequestParam("id") Long id) {
|
||||
smsTemplateService.deleteSmsTemplate(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得短信模板")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:query')")
|
||||
public CommonResult<SysSmsTemplateRespVO> getSmsTemplate(@RequestParam("id") Long id) {
|
||||
SysSmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id);
|
||||
return success(SysSmsTemplateConvert.INSTANCE.convert(smsTemplate));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得短信模板分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:query')")
|
||||
public CommonResult<PageResult<SysSmsTemplateRespVO>> getSmsTemplatePage(@Valid SysSmsTemplatePageReqVO pageVO) {
|
||||
PageResult<SysSmsTemplateDO> pageResult = smsTemplateService.getSmsTemplatePage(pageVO);
|
||||
return success(SysSmsTemplateConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ApiOperation("导出短信模板 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportSmsTemplateExcel(@Valid SysSmsTemplateExportReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
List<SysSmsTemplateDO> list = smsTemplateService.getSmsTemplateList(exportReqVO);
|
||||
// 导出 Excel
|
||||
List<SysSmsTemplateExcelVO> datas = SysSmsTemplateConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "短信模板.xls", "数据", SysSmsTemplateExcelVO.class, datas);
|
||||
}
|
||||
|
||||
@PostMapping("/send-sms")
|
||||
@ApiOperation("发送短信")
|
||||
@PreAuthorize("@ss.hasPermission('system:sms-template:send-sms')")
|
||||
public CommonResult<Long> sendSms(@Valid @RequestBody SysSmsTemplateSendReqVO sendReqVO) {
|
||||
return success(smsService.sendSingleSms(sendReqVO.getMobile(), null, null,
|
||||
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 短信渠道 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class SysSmsChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "短信签名", required = true, example = "芋道源码")
|
||||
@NotNull(message = "短信签名不能为空")
|
||||
private String signature;
|
||||
|
||||
@ApiModelProperty(value = "启用状态", required = true, example = "1")
|
||||
@NotNull(message = "启用状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "备注", example = "好吃!")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的账号", required = true, example = "yudao")
|
||||
@NotNull(message = "短信 API 的账号不能为空")
|
||||
private String apiKey;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的秘钥", example = "yuanma")
|
||||
private String apiSecret;
|
||||
|
||||
@ApiModelProperty(value = "短信发送回调 URL", example = "http://www.iocoder.cn")
|
||||
@URL(message = "回调 URL 格式不正确")
|
||||
private String callbackUrl;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("短信渠道创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsChannelCreateReqVO extends SysSmsChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "渠道编码", required = true, example = "YUN_PIAN", notes = "参见 SmsChannelEnum 枚举类")
|
||||
@NotNull(message = "渠道编码不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("短信渠道分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsChannelPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "任务状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "短信签名", example = "芋道源码", notes = "模糊匹配")
|
||||
private String signature;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("短信渠道 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsChannelRespVO extends SysSmsChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "渠道编码", required = true, example = "YUN_PIAN", notes = "参见 SmsChannelEnum 枚举类")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("短信渠道精简 Response VO")
|
||||
@Data
|
||||
public class SysSmsChannelSimpleRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "短信签名", required = true, example = "芋道源码")
|
||||
@NotNull(message = "短信签名不能为空")
|
||||
private String signature;
|
||||
|
||||
@ApiModelProperty(value = "渠道编码", required = true, example = "YUN_PIAN", notes = "参见 SmsChannelEnum 枚举类")
|
||||
private String code;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.channel;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("短信渠道更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsChannelUpdateReqVO extends SysSmsChannelBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.log;
|
||||
|
||||
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
|
||||
import cn.iocoder.dashboard.framework.excel.core.convert.JsonConvert;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.*;
|
||||
|
||||
/**
|
||||
* 短信日志 Excel VO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SysSmsLogExcelVO {
|
||||
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@ExcelProperty("短信渠道编号")
|
||||
private Long channelId;
|
||||
|
||||
@ExcelProperty("短信渠道编码")
|
||||
private String channelCode;
|
||||
|
||||
@ExcelProperty("模板编号")
|
||||
private Long templateId;
|
||||
|
||||
@ExcelProperty("模板编码")
|
||||
private String templateCode;
|
||||
|
||||
@ExcelProperty(value = "短信类型", converter = DictConvert.class)
|
||||
@DictFormat(SYS_SMS_TEMPLATE_TYPE)
|
||||
private Integer templateType;
|
||||
|
||||
@ExcelProperty("短信内容")
|
||||
private String templateContent;
|
||||
|
||||
@ExcelProperty(value = "短信参数", converter = JsonConvert.class)
|
||||
private Map<String, Object> templateParams;
|
||||
|
||||
@ExcelProperty("短信 API 的模板编号")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ExcelProperty("手机号")
|
||||
private String mobile;
|
||||
|
||||
@ExcelProperty("用户编号")
|
||||
private Long userId;
|
||||
|
||||
@ExcelProperty(value = "用户类型", converter = DictConvert.class)
|
||||
@DictFormat(USER_TYPE)
|
||||
private Integer userType;
|
||||
|
||||
@ExcelProperty(value = "发送状态", converter = DictConvert.class)
|
||||
@DictFormat(SYS_SMS_SEND_STATUS)
|
||||
private Integer sendStatus;
|
||||
|
||||
@ExcelProperty("发送时间")
|
||||
private Date sendTime;
|
||||
|
||||
@ExcelProperty("发送结果的编码")
|
||||
private Integer sendCode;
|
||||
|
||||
@ExcelProperty("发送结果的提示")
|
||||
private String sendMsg;
|
||||
|
||||
@ExcelProperty("短信 API 发送结果的编码")
|
||||
private String apiSendCode;
|
||||
|
||||
@ExcelProperty("短信 API 发送失败的提示")
|
||||
private String apiSendMsg;
|
||||
|
||||
@ExcelProperty("短信 API 发送返回的唯一请求 ID")
|
||||
private String apiRequestId;
|
||||
|
||||
@ExcelProperty("短信 API 发送返回的序号")
|
||||
private String apiSerialNo;
|
||||
|
||||
@ExcelProperty(value = "接收状态", converter = DictConvert.class)
|
||||
@DictFormat(SYS_SMS_RECEIVE_STATUS)
|
||||
private Integer receiveStatus;
|
||||
|
||||
@ExcelProperty("接收时间")
|
||||
private Date receiveTime;
|
||||
|
||||
@ExcelProperty("API 接收结果的编码")
|
||||
private String apiReceiveCode;
|
||||
|
||||
@ExcelProperty("API 接收结果的说明")
|
||||
private String apiReceiveMsg;
|
||||
|
||||
@ExcelProperty("创建时间")
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.log;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel(value = "短信日志 Excel 导出 Request VO", description = "参数和 SysSmsLogPageReqVO 是一致的")
|
||||
@Data
|
||||
public class SysSmsLogExportReqVO {
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", example = "10")
|
||||
private Long channelId;
|
||||
|
||||
@ApiModelProperty(value = "模板编号", example = "20")
|
||||
private Long templateId;
|
||||
|
||||
@ApiModelProperty(value = "手机号", example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "发送状态", example = "1")
|
||||
private Integer sendStatus;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始发送时间")
|
||||
private Date beginSendTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束发送时间")
|
||||
private Date endSendTime;
|
||||
|
||||
@ApiModelProperty(value = "接收状态", example = "0")
|
||||
private Integer receiveStatus;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始接收时间")
|
||||
private Date beginReceiveTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束接收时间")
|
||||
private Date endReceiveTime;
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.log;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("短信日志分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsLogPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", example = "10")
|
||||
private Long channelId;
|
||||
|
||||
@ApiModelProperty(value = "模板编号", example = "20")
|
||||
private Long templateId;
|
||||
|
||||
@ApiModelProperty(value = "手机号", example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "发送状态", example = "1", notes = "参见 SysSmsSendStatusEnum 枚举类")
|
||||
private Integer sendStatus;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始发送时间")
|
||||
private Date beginSendTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束发送时间")
|
||||
private Date endSendTime;
|
||||
|
||||
@ApiModelProperty(value = "接收状态", example = "0", notes = "参见 SysSmsReceiveStatusEnum 枚举类")
|
||||
private Integer receiveStatus;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始接收时间")
|
||||
private Date beginReceiveTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束接收时间")
|
||||
private Date endReceiveTime;
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.log;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiModel("短信日志 Response VO")
|
||||
@Data
|
||||
public class SysSmsLogRespVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", required = true, example = "10")
|
||||
private Long channelId;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编码", required = true, example = "ALIYUN")
|
||||
private String channelCode;
|
||||
|
||||
@ApiModelProperty(value = "模板编号", required = true, example = "20")
|
||||
private Long templateId;
|
||||
|
||||
@ApiModelProperty(value = "模板编码", required = true, example = "test-01")
|
||||
private String templateCode;
|
||||
|
||||
@ApiModelProperty(value = "短信类型", required = true, example = "1")
|
||||
private Integer templateType;
|
||||
|
||||
@ApiModelProperty(value = "短信内容", required = true, example = "你好,你的验证码是 1024")
|
||||
private String templateContent;
|
||||
|
||||
@ApiModelProperty(value = "短信参数", required = true, example = "name,code")
|
||||
private Map<String, Object> templateParams;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的模板编号", required = true, example = "SMS_207945135")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "用户编号", example = "10")
|
||||
private Long userId;
|
||||
|
||||
@ApiModelProperty(value = "用户类型", example = "1")
|
||||
private Integer userType;
|
||||
|
||||
@ApiModelProperty(value = "发送状态", required = true, example = "1")
|
||||
private Integer sendStatus;
|
||||
|
||||
@ApiModelProperty(value = "发送时间")
|
||||
private Date sendTime;
|
||||
|
||||
@ApiModelProperty(value = "发送结果的编码", example = "0")
|
||||
private Integer sendCode;
|
||||
|
||||
@ApiModelProperty(value = "发送结果的提示", example = "成功")
|
||||
private String sendMsg;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 发送结果的编码", example = "SUCCESS")
|
||||
private String apiSendCode;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 发送失败的提示", example = "成功")
|
||||
private String apiSendMsg;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 发送返回的唯一请求 ID", example = "3837C6D3-B96F-428C-BBB2-86135D4B5B99")
|
||||
private String apiRequestId;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 发送返回的序号", example = "62923244790")
|
||||
private String apiSerialNo;
|
||||
|
||||
@ApiModelProperty(value = "接收状态", required = true, example = "0")
|
||||
private Integer receiveStatus;
|
||||
|
||||
@ApiModelProperty(value = "接收时间")
|
||||
private Date receiveTime;
|
||||
|
||||
@ApiModelProperty(value = "API 接收结果的编码", example = "DELIVRD")
|
||||
private String apiReceiveCode;
|
||||
|
||||
@ApiModelProperty(value = "API 接收结果的说明", example = "用户接收成功")
|
||||
private String apiReceiveMsg;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 短信模板 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class SysSmsTemplateBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "短信类型", required = true, example = "1", notes = "参见 SysSmsTemplateTypeEnum 枚举类")
|
||||
@NotNull(message = "短信类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "开启状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举类")
|
||||
@NotNull(message = "开启状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "模板编码", required = true, example = "test_01")
|
||||
@NotNull(message = "模板编码不能为空")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "模板名称", required = true, example = "yudao")
|
||||
@NotNull(message = "模板名称不能为空")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "模板内容", required = true, example = "你好,{name}。你长的太{like}啦!")
|
||||
@NotNull(message = "模板内容不能为空")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "备注", example = "哈哈哈")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的模板编号", required = true, example = "4383920")
|
||||
@NotNull(message = "短信 API 的模板编号不能为空")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", required = true, example = "10")
|
||||
@NotNull(message = "短信渠道编号不能为空")
|
||||
private Long channelId;
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@ApiModel("短信模板创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsTemplateCreateReqVO extends SysSmsTemplateBaseVO {
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
|
||||
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum.*;
|
||||
|
||||
/**
|
||||
* 短信模板 Excel VO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class SysSmsTemplateExcelVO {
|
||||
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@ExcelProperty(value = "短信签名", converter = DictConvert.class)
|
||||
@DictFormat(SYS_SMS_TEMPLATE_TYPE)
|
||||
private Integer type;
|
||||
|
||||
@ExcelProperty(value = "开启状态", converter = DictConvert.class)
|
||||
@DictFormat(SYS_COMMON_STATUS)
|
||||
private Integer status;
|
||||
|
||||
@ExcelProperty("模板编码")
|
||||
private String code;
|
||||
|
||||
@ExcelProperty("模板名称")
|
||||
private String name;
|
||||
|
||||
@ExcelProperty("模板内容")
|
||||
private String content;
|
||||
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@ExcelProperty("短信 API 的模板编号")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ExcelProperty("短信渠道编号")
|
||||
private Long channelId;
|
||||
|
||||
@ExcelProperty(value = "短信渠道编码", converter = DictConvert.class)
|
||||
@DictFormat(SYS_SMS_CHANNEL_CODE)
|
||||
private String channelCode;
|
||||
|
||||
@ExcelProperty("创建时间")
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel(value = "短信模板 Excel 导出 Request VO", description = "参数和 SysSmsTemplatePageReqVO 是一致的")
|
||||
@Data
|
||||
public class SysSmsTemplateExportReqVO {
|
||||
|
||||
@ApiModelProperty(value = "短信签名", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "开启状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "模板编码", example = "test_01", notes = "模糊匹配")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "模板内容", example = "你好,{name}。你长的太{like}啦!", notes = "模糊匹配")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的模板编号", example = "4383920", notes = "模糊匹配")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", example = "10")
|
||||
private Long channelId;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("短信模板分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsTemplatePageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "短信签名", example = "1")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "开启状态", example = "1")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "模板编码", example = "test_01", notes = "模糊匹配")
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty(value = "模板内容", example = "你好,{name}。你长的太{like}啦!", notes = "模糊匹配")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "短信 API 的模板编号", example = "4383920", notes = "模糊匹配")
|
||||
private String apiTemplateId;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编号", example = "10")
|
||||
private Long channelId;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("短信模板 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsTemplateRespVO extends SysSmsTemplateBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "短信渠道编码", required = true, example = "ALIYUN")
|
||||
private String channelCode;
|
||||
|
||||
@ApiModelProperty(value = "参数数组", example = "name,code")
|
||||
private List<String> params;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiModel("短信模板的发送 Request VO")
|
||||
@Data
|
||||
public class SysSmsTemplateSendReqVO {
|
||||
|
||||
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
|
||||
@NotNull(message = "手机号不能为空")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "模板编码", required = true, example = "test_01")
|
||||
@NotNull(message = "模板编码不能为空")
|
||||
private String templateCode;
|
||||
|
||||
@ApiModelProperty(value = "模板参数")
|
||||
private Map<String, Object> templateParams;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms.vo.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("短信模板更新 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsTemplateUpdateReqVO extends SysSmsTemplateBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
@ -149,9 +149,9 @@ public class SysUserController {
|
||||
// 手动创建导出 demo
|
||||
List<SysUserImportExcelVO> list = Arrays.asList(
|
||||
SysUserImportExcelVO.builder().username("yudao").deptId(1L).email("yudao@iocoder.cn").mobile("15601691300")
|
||||
.nickname("芋道").status(CommonStatusEnum.ENABLE.getStatus()).sex(SysSexEnum.MALE.getSEX()).build(),
|
||||
.nickname("芋道").status(CommonStatusEnum.ENABLE.getStatus()).sex(SysSexEnum.MALE.getSex()).build(),
|
||||
SysUserImportExcelVO.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300")
|
||||
.nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SysSexEnum.FEMALE.getSEX()).build()
|
||||
.nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SysSexEnum.FEMALE.getSex()).build()
|
||||
);
|
||||
|
||||
// 输出
|
||||
|
@ -3,9 +3,9 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.profile;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@ApiModel("用户个人信息更新 Request VO")
|
||||
@ -22,7 +22,7 @@ public class SysUserProfileUpdateReqVO {
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty(value = "手机号码", example = "15601691300")
|
||||
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
|
||||
@Length(min = 11, max = 11, message = "手机号长度必须 11 位")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类")
|
||||
|
@ -2,10 +2,10 @@ package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Set;
|
||||
|
||||
@ -40,7 +40,7 @@ public class SysUserBaseVO {
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty(value = "手机号码", example = "15601691300")
|
||||
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
|
||||
@Length(min = 11, max = 11, message = "手机号长度必须 11 位")
|
||||
private String mobile;
|
||||
|
||||
@ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SysSexEnum 枚举类")
|
||||
|
@ -13,7 +13,7 @@ public interface SysDictDataConvert {
|
||||
|
||||
SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
|
||||
|
||||
List<SysDictDataSimpleVO> convertList(List<SysDictDataDO> list);
|
||||
List<SysDictDataSimpleRespVO> convertList(List<SysDictDataDO> list);
|
||||
|
||||
SysDictDataRespVO convert(SysDictDataDO bean);
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.dashboard.modules.system.convert.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelSimpleRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信渠道 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysSmsChannelConvert {
|
||||
|
||||
SysSmsChannelConvert INSTANCE = Mappers.getMapper(SysSmsChannelConvert.class);
|
||||
|
||||
SysSmsChannelDO convert(SysSmsChannelCreateReqVO bean);
|
||||
|
||||
SysSmsChannelDO convert(SysSmsChannelUpdateReqVO bean);
|
||||
|
||||
SysSmsChannelRespVO convert(SysSmsChannelDO bean);
|
||||
|
||||
List<SysSmsChannelRespVO> convertList(List<SysSmsChannelDO> list);
|
||||
|
||||
PageResult<SysSmsChannelRespVO> convertPage(PageResult<SysSmsChannelDO> page);
|
||||
|
||||
List<SmsChannelProperties> convertList02(List<SysSmsChannelDO> list);
|
||||
|
||||
List<SysSmsChannelSimpleRespVO> convertList03(List<SysSmsChannelDO> list);
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package cn.iocoder.dashboard.modules.system.convert.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExcelVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信日志 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface SysSmsLogConvert {
|
||||
|
||||
SysSmsLogConvert INSTANCE = Mappers.getMapper(SysSmsLogConvert.class);
|
||||
|
||||
SysSmsLogRespVO convert(SysSmsLogDO bean);
|
||||
|
||||
List<SysSmsLogRespVO> convertList(List<SysSmsLogDO> list);
|
||||
|
||||
PageResult<SysSmsLogRespVO> convertPage(PageResult<SysSmsLogDO> page);
|
||||
|
||||
List<SysSmsLogExcelVO> convertList02(List<SysSmsLogDO> list);
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.dashboard.modules.system.convert.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateExcelVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsTemplateConvert {
|
||||
|
||||
SysSmsTemplateConvert INSTANCE = Mappers.getMapper(SysSmsTemplateConvert.class);
|
||||
|
||||
SysSmsTemplateDO convert(SysSmsTemplateCreateReqVO bean);
|
||||
|
||||
SysSmsTemplateDO convert(SysSmsTemplateUpdateReqVO bean);
|
||||
|
||||
SysSmsTemplateRespVO convert(SysSmsTemplateDO bean);
|
||||
|
||||
List<SysSmsTemplateRespVO> convertList(List<SysSmsTemplateDO> list);
|
||||
|
||||
PageResult<SysSmsTemplateRespVO> convertPage(PageResult<SysSmsTemplateDO> page);
|
||||
|
||||
List<SysSmsTemplateExcelVO> convertList02(List<SysSmsTemplateDO> list);
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 短信渠道 DO
|
||||
*
|
||||
* @author zzf
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "sys_sms_channel", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsChannelDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 渠道编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 短信签名
|
||||
*/
|
||||
private String signature;
|
||||
/**
|
||||
* 渠道编码
|
||||
*
|
||||
* 枚举 {@link SmsChannelEnum}
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 启用状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 短信 API 的账号
|
||||
*/
|
||||
private String apiKey;
|
||||
/**
|
||||
* 短信 API 的秘钥
|
||||
*/
|
||||
private String apiSecret;
|
||||
/**
|
||||
* 短信发送回调 URL
|
||||
*/
|
||||
private String callbackUrl;
|
||||
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsReceiveStatusEnum;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 短信日志 DO
|
||||
*
|
||||
* @author zzf
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "sys_sms_log", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SysSmsLogDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 自增编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
// ========= 渠道相关字段 =========
|
||||
|
||||
/**
|
||||
* 短信渠道编号
|
||||
*
|
||||
* 关联 {@link SysSmsChannelDO#getId()}
|
||||
*/
|
||||
private Long channelId;
|
||||
/**
|
||||
* 短信渠道编码
|
||||
*
|
||||
* 冗余 {@link SysSmsChannelDO#getCode()}
|
||||
*/
|
||||
private String channelCode;
|
||||
|
||||
// ========= 模板相关字段 =========
|
||||
|
||||
/**
|
||||
* 模板编号
|
||||
*
|
||||
* 关联 {@link SysSmsTemplateDO#getId()}
|
||||
*/
|
||||
private Long templateId;
|
||||
/**
|
||||
* 模板编码
|
||||
*
|
||||
* 冗余 {@link SysSmsTemplateDO#getCode()}
|
||||
*/
|
||||
private String templateCode;
|
||||
/**
|
||||
* 短信类型
|
||||
*
|
||||
* 冗余 {@link SysSmsTemplateDO#getType()}
|
||||
*/
|
||||
private Integer templateType;
|
||||
/**
|
||||
* 基于 {@link SysSmsTemplateDO#getContent()} 格式化后的内容
|
||||
*/
|
||||
private String templateContent;
|
||||
/**
|
||||
* 基于 {@link SysSmsTemplateDO#getParams()} 输入后的参数
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private Map<String, Object> templateParams;
|
||||
/**
|
||||
* 短信 API 的模板编号
|
||||
*
|
||||
* 冗余 {@link SysSmsTemplateDO#getApiTemplateId()}
|
||||
*/
|
||||
private String apiTemplateId;
|
||||
|
||||
// ========= 手机相关字段 =========
|
||||
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
private String mobile;
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 枚举 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
|
||||
// ========= 发送相关字段 =========
|
||||
|
||||
/**
|
||||
* 发送状态
|
||||
*
|
||||
* 枚举 {@link SysSmsSendStatusEnum}
|
||||
*/
|
||||
private Integer sendStatus;
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
private Date sendTime;
|
||||
/**
|
||||
* 发送结果的编码
|
||||
*
|
||||
* 枚举 {@link SmsFrameworkErrorCodeConstants}
|
||||
*/
|
||||
private Integer sendCode;
|
||||
/**
|
||||
* 发送结果的提示
|
||||
*
|
||||
* 一般情况下,使用 {@link SmsFrameworkErrorCodeConstants}
|
||||
* 异常情况下,通过格式化 Exception 的提示存储
|
||||
*/
|
||||
private String sendMsg;
|
||||
/**
|
||||
* 短信 API 发送结果的编码
|
||||
*
|
||||
* 由于第三方的错误码可能是字符串,所以使用 String 类型
|
||||
*/
|
||||
private String apiSendCode;
|
||||
/**
|
||||
* 短信 API 发送失败的提示
|
||||
*/
|
||||
private String apiSendMsg;
|
||||
/**
|
||||
* 短信 API 发送返回的唯一请求 ID
|
||||
*
|
||||
* 用于和短信 API 进行定位于排错
|
||||
*/
|
||||
private String apiRequestId;
|
||||
/**
|
||||
* 短信 API 发送返回的序号
|
||||
*
|
||||
* 用于和短信 API 平台的发送记录关联
|
||||
*/
|
||||
private String apiSerialNo;
|
||||
|
||||
// ========= 接收相关字段 =========
|
||||
|
||||
/**
|
||||
* 接收状态
|
||||
*
|
||||
* 枚举 {@link SysSmsReceiveStatusEnum}
|
||||
*/
|
||||
private Integer receiveStatus;
|
||||
/**
|
||||
* 接收时间
|
||||
*/
|
||||
private Date receiveTime;
|
||||
/**
|
||||
* 短信 API 接收结果的编码
|
||||
*/
|
||||
private String apiReceiveCode;
|
||||
/**
|
||||
* 短信 API 接收结果的提示
|
||||
*/
|
||||
private String apiReceiveMsg;
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsTemplateTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信模板 DO
|
||||
*
|
||||
* @author zzf
|
||||
* @since 2021-01-25
|
||||
*/
|
||||
@TableName(value = "sys_sms_template", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysSmsTemplateDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 自增编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
// ========= 模板相关字段 =========
|
||||
|
||||
/**
|
||||
* 短信类型
|
||||
*
|
||||
* 枚举 {@link SysSmsTemplateTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 启用状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 模板编码,保证唯一
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 模板名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 模板内容
|
||||
*
|
||||
* 内容的参数,使用 {} 包括,例如说 {name}
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 参数数组(自动根据内容生成)
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<String> params;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 短信 API 的模板编号
|
||||
*/
|
||||
private String apiTemplateId;
|
||||
|
||||
// ========= 渠道相关字段 =========
|
||||
|
||||
/**
|
||||
* 短信渠道编号
|
||||
*
|
||||
* 关联 {@link SysSmsChannelDO#getId()}
|
||||
*/
|
||||
private Long channelId;
|
||||
/**
|
||||
* 短信渠道编码
|
||||
*
|
||||
* 冗余 {@link SysSmsChannelDO#getCode()}
|
||||
*/
|
||||
private String channelCode;
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsChannelMapper extends BaseMapperX<SysSmsChannelDO> {
|
||||
|
||||
default PageResult<SysSmsChannelDO> selectPage(SysSmsChannelPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<SysSmsChannelDO>()
|
||||
.likeIfPresent("signature", reqVO.getSignature())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM sys_sms_channel WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogExportReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.log.SysSmsLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsLogMapper extends BaseMapperX<SysSmsLogDO> {
|
||||
|
||||
default PageResult<SysSmsLogDO> selectPage(SysSmsLogPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<SysSmsLogDO>()
|
||||
.eqIfPresent("channel_id", reqVO.getChannelId())
|
||||
.eqIfPresent("template_id", reqVO.getTemplateId())
|
||||
.likeIfPresent("mobile", reqVO.getMobile())
|
||||
.eqIfPresent("send_status", reqVO.getSendStatus())
|
||||
.betweenIfPresent("send_time", reqVO.getBeginSendTime(), reqVO.getEndSendTime())
|
||||
.eqIfPresent("receive_status", reqVO.getReceiveStatus())
|
||||
.betweenIfPresent("receive_time", reqVO.getBeginReceiveTime(), reqVO.getEndReceiveTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
default List<SysSmsLogDO> selectList(SysSmsLogExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<SysSmsLogDO>()
|
||||
.eqIfPresent("channel_id", reqVO.getChannelId())
|
||||
.eqIfPresent("template_id", reqVO.getTemplateId())
|
||||
.likeIfPresent("mobile", reqVO.getMobile())
|
||||
.eqIfPresent("send_status", reqVO.getSendStatus())
|
||||
.betweenIfPresent("send_time", reqVO.getBeginSendTime(), reqVO.getEndSendTime())
|
||||
.eqIfPresent("receive_status", reqVO.getReceiveStatus())
|
||||
.betweenIfPresent("receive_time", reqVO.getBeginReceiveTime(), reqVO.getEndReceiveTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsTemplateMapper extends BaseMapperX<SysSmsTemplateDO> {
|
||||
|
||||
default SysSmsTemplateDO selectByCode(String code) {
|
||||
return selectOne("code", code);
|
||||
}
|
||||
|
||||
default PageResult<SysSmsTemplateDO> selectPage(SysSmsTemplatePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<SysSmsTemplateDO>()
|
||||
.eqIfPresent("type", reqVO.getType())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.likeIfPresent("code", reqVO.getCode())
|
||||
.likeIfPresent("content", reqVO.getContent())
|
||||
.likeIfPresent("api_template_id", reqVO.getApiTemplateId())
|
||||
.eqIfPresent("channel_id", reqVO.getChannelId())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
default List<SysSmsTemplateDO> selectList(SysSmsTemplateExportReqVO reqVO) {
|
||||
return selectList(new QueryWrapperX<SysSmsTemplateDO>()
|
||||
.eqIfPresent("type", reqVO.getType())
|
||||
.eqIfPresent("status", reqVO.getStatus())
|
||||
.likeIfPresent("code", reqVO.getCode())
|
||||
.likeIfPresent("content", reqVO.getContent())
|
||||
.likeIfPresent("api_template_id", reqVO.getApiTemplateId())
|
||||
.eqIfPresent("channel_id", reqVO.getChannelId())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("id"));
|
||||
}
|
||||
|
||||
default Integer selectCountByChannelId(Long channelId) {
|
||||
return selectCount("channel_id", channelId);
|
||||
}
|
||||
|
||||
@Select("SELECT id FROM sys_sms_template WHERE update_time > #{maxUpdateTime} LIMIT 1")
|
||||
Long selectExistsByUpdateTimeAfter(Date maxUpdateTime);
|
||||
|
||||
}
|
@ -78,4 +78,18 @@ public interface SysErrorCodeConstants {
|
||||
ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败");
|
||||
ErrorCode FILE_IS_EMPTY= new ErrorCode(1002009003, "文件为空");
|
||||
|
||||
// ========== 短信渠道 1002011000 ==========
|
||||
ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1002011000, "短信渠道不存在");
|
||||
ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1002011001, "短信渠道不处于开启状态,不允许选择");
|
||||
ErrorCode SMS_CHANNEL_HAS_CHILDREN = new ErrorCode(1002011002, "无法删除,该短信渠道还有短信模板");
|
||||
|
||||
// ========== 短信模板 1002011000 ==========
|
||||
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
|
||||
ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
|
||||
|
||||
// ========== 短信发送 1002012000 ==========
|
||||
ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002012000, "手机号不存在");
|
||||
ErrorCode SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS = new ErrorCode(1002012001, "模板参数({})缺失");
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,11 @@ package cn.iocoder.dashboard.modules.system.enums.common;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 性别的枚举值
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SysSexEnum {
|
||||
@ -10,6 +15,9 @@ public enum SysSexEnum {
|
||||
MALE(1), // 男
|
||||
FEMALE(2); // 女
|
||||
|
||||
private final Integer SEX;
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
private final Integer sex;
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ public enum SysDictTypeEnum {
|
||||
SYS_LOGIN_RESULT("sys_login_result"), // 登陆结果
|
||||
SYS_CONFIG_TYPE("sys_config_type"), // 参数配置类型
|
||||
SYS_BOOLEAN_STRING("sys_boolean_string"), // Boolean 是否类型
|
||||
SYS_SMS_CHANNEL_CODE("sys_sms_channel_code"), // 短信渠道编码
|
||||
SYS_SMS_TEMPLATE_TYPE("sys_sms_template_type"), // 短信模板类型
|
||||
SYS_SMS_SEND_STATUS("sys_sms_send_status"), // 短信发送状态
|
||||
SYS_SMS_RECEIVE_STATUS("sys_sms_receive_status"), // 短信接收状态
|
||||
|
||||
INF_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"), // Redis 超时类型
|
||||
INF_JOB_STATUS("inf_job_status"), // 定时任务状态的枚举
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.dashboard.modules.system.enums.sms;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信的接收状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
* @date 2021/2/1 13:39
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SysSmsReceiveStatusEnum {
|
||||
|
||||
INIT(0), // 初始化
|
||||
SUCCESS(10), // 接收成功
|
||||
FAILURE(20), // 接收失败
|
||||
;
|
||||
|
||||
private final int status;
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.dashboard.modules.system.enums.sms;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信的发送状态枚举
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/2/1 13:39
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SysSmsSendStatusEnum {
|
||||
|
||||
INIT(0), // 初始化
|
||||
SUCCESS(10), // 发送成功
|
||||
FAILURE(20), // 发送失败
|
||||
IGNORE(30), // 忽略,即不发送
|
||||
;
|
||||
|
||||
private final int status;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.dashboard.modules.system.enums.sms;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信的模板类型枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SysSmsTemplateTypeEnum {
|
||||
|
||||
VERIFICATION_CODE(1), // 验证码
|
||||
NOTICE(2), // 通知
|
||||
PROMOTION(3), // 营销
|
||||
;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
|
||||
|
||||
import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener;
|
||||
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 针对 {@link SysSmsChannelRefreshMessage} 的消费者
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SysSmsChannelRefreshConsumer extends AbstractChannelMessageListener<SysSmsChannelRefreshMessage> {
|
||||
|
||||
@Resource
|
||||
private SysSmsChannelService smsChannelService;
|
||||
|
||||
@Override
|
||||
public void onMessage(SysSmsChannelRefreshMessage message) {
|
||||
log.info("[onMessage][收到 SmsChannel 刷新消息]");
|
||||
smsChannelService.initSmsClients();
|
||||
}
|
||||
|
||||
}
|
@ -2,16 +2,29 @@ package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
|
||||
|
||||
import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
|
||||
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 针对 {@link SysSmsSendMessage} 的消费者
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/9 16:35
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
|
||||
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
@Override
|
||||
public void onMessage(SysSmsSendMessage message) {
|
||||
log.info("[onMessage][消息内容({})]", message);
|
||||
smsService.doSendSms(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
|
||||
|
||||
import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener;
|
||||
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsTemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 针对 {@link SysSmsTemplateRefreshMessage} 的消费者
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SysSmsTemplateRefreshConsumer extends AbstractChannelMessageListener<SysSmsTemplateRefreshMessage> {
|
||||
|
||||
@Resource
|
||||
private SysSmsTemplateService smsTemplateService;
|
||||
|
||||
@Override
|
||||
public void onMessage(SysSmsTemplateRefreshMessage message) {
|
||||
log.info("[onMessage][收到 SmsTemplate 刷新消息]");
|
||||
smsTemplateService.initLocalCache();
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user