mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 11:40:05 +08:00
Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
This commit is contained in:
commit
e62495f650
22
pom.xml
22
pom.xml
@ -46,6 +46,7 @@
|
|||||||
<easyexcel.verion>2.2.7</easyexcel.verion>
|
<easyexcel.verion>2.2.7</easyexcel.verion>
|
||||||
<velocity.version>2.2</velocity.version>
|
<velocity.version>2.2</velocity.version>
|
||||||
<screw.version>1.0.5</screw.version>
|
<screw.version>1.0.5</screw.version>
|
||||||
|
<!-- 三方云服务相关 -->
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
@ -271,6 +272,27 @@
|
|||||||
<version>${screw.version}</version>
|
<version>${screw.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 三方云服务相关 -->
|
||||||
|
|
||||||
|
<!-- SMS SDK begin -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.yunpian.sdk</groupId>
|
||||||
|
<artifactId>yunpian-java-sdk</artifactId>
|
||||||
|
<version>1.2.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
|
<version>4.5.18</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||||
|
<version>2.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- SMS SDK end -->
|
||||||
|
|
||||||
</dependencies>
|
</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",
|
"dev": "vue-cli-service serve",
|
||||||
"build:prod": "vue-cli-service build",
|
"build:prod": "vue-cli-service build",
|
||||||
"build:stage": "vue-cli-service build --mode staging",
|
"build:stage": "vue-cli-service build --mode staging",
|
||||||
|
"build:demo1024": "vue-cli-service build --mode demo1024",
|
||||||
"preview": "node build/index.js --preview",
|
"preview": "node build/index.js --preview",
|
||||||
"lint": "eslint --ext .js,.vue src"
|
"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_OPERATE_TYPE: 'sys_operate_type',
|
||||||
SYS_LOGIN_RESULT: 'sys_login_result',
|
SYS_LOGIN_RESULT: 'sys_login_result',
|
||||||
SYS_CONFIG_TYPE: 'sys_config_type',
|
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_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type',
|
||||||
INF_JOB_STATUS: 'inf_job_status',
|
INF_JOB_STATUS: 'inf_job_status',
|
||||||
|
@ -163,7 +163,6 @@ export default {
|
|||||||
businessType: undefined,
|
businessType: undefined,
|
||||||
status: undefined
|
status: undefined
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
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>
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
Navicat Premium Data Transfer
|
Navicat Premium Data Transfer
|
||||||
|
|
||||||
Source Server : 127.0.0.1
|
Source Server : local-mysql001
|
||||||
Source Server Type : MySQL
|
Source Server Type : MySQL
|
||||||
Source Server Version : 50718
|
Source Server Version : 50718
|
||||||
Source Host : localhost:3306
|
Source Host : localhost:3306
|
||||||
@ -11,7 +11,7 @@
|
|||||||
Target Server Version : 50718
|
Target Server Version : 50718
|
||||||
File Encoding : 65001
|
File Encoding : 65001
|
||||||
|
|
||||||
Date: 21/03/2021 18:53:24
|
Date: 05/04/2021 23:51:38
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
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 '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1318 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
|
) ENGINE=InnoDB AUTO_INCREMENT=1909 DEFAULT CHARSET=utf8mb4 COMMENT='API 访问日志表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of inf_api_access_log
|
-- 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 '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='系统异常日志';
|
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COMMENT='系统异常日志';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of inf_api_error_log
|
-- 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 '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=627 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
|
) ENGINE=InnoDB AUTO_INCREMENT=1035 DEFAULT CHARSET=utf8mb4 COMMENT='定时任务日志表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of inf_job_log
|
-- 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 '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='字典数据表';
|
) ENGINE=InnoDB AUTO_INCREMENT=70 DEFAULT CHARSET=utf8mb4 COMMENT='字典数据表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_dict_data
|
-- Records of sys_dict_data
|
||||||
@ -324,6 +324,11 @@ 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 (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 (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 (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, 0, '云片', 'YUN_PIAN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:14', '1', '2021-04-05 01:05:14', b'0');
|
||||||
|
INSERT INTO `sys_dict_data` VALUES (66, 0, '阿里云', 'ALIYUN', 'sys_sms_channel_code', 0, NULL, '1', '2021-04-05 01:05:26', '1', '2021-04-05 01:05:26', 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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -343,7 +348,7 @@ CREATE TABLE `sys_dict_type` (
|
|||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE KEY `dict_type` (`type`)
|
UNIQUE KEY `dict_type` (`type`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=111 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';
|
) ENGINE=InnoDB AUTO_INCREMENT=113 DEFAULT CHARSET=utf8mb4 COMMENT='字典类型表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_dict_type
|
-- Records of sys_dict_type
|
||||||
@ -366,6 +371,8 @@ 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 (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 (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 (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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -386,7 +393,7 @@ CREATE TABLE `sys_login_log` (
|
|||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
|
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COMMENT='系统访问记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_login_log
|
-- Records of sys_login_log
|
||||||
@ -415,7 +422,7 @@ CREATE TABLE `sys_menu` (
|
|||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=1093 DEFAULT CHARSET=utf8mb4 COMMENT='菜单权限表';
|
) ENGINE=InnoDB AUTO_INCREMENT=1100 DEFAULT CHARSET=utf8mb4 COMMENT='菜单权限表';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_menu
|
-- Records of sys_menu
|
||||||
@ -530,6 +537,12 @@ 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 (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 (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 (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', '', 'system/sms/smsChannel', 0, '', '2021-04-01 11:07:15', '1', '2021-04-05 20:32:53', 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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -589,7 +602,7 @@ CREATE TABLE `sys_operate_log` (
|
|||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
|
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COMMENT='操作日志记录';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of sys_operate_log
|
-- Records of sys_operate_log
|
||||||
@ -834,6 +847,118 @@ 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');
|
INSERT INTO `sys_role_menu` VALUES (238, 101, 1065, '', '2021-01-21 03:23:27', '', '2021-01-21 03:23:27', b'0');
|
||||||
COMMIT;
|
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(63) NOT NULL COMMENT '短信 API 的账号',
|
||||||
|
`api_secret` varchar(63) 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=4 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-05 21:02:38', b'0');
|
||||||
|
INSERT INTO `sys_sms_channel` VALUES (2, 'Ballcat', 'ALIYUN', 0, '啦啦啦', 'LTAI5tCnKso2uG3kJ5gRav88', 'fGJ5SNXL7P1NHNRmJ7DJaMJGPyE55C', NULL, '', '2021-03-31 11:53:10', '1', '2021-04-05 21:02:44', 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-05 21:10:34', 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 '0' COMMENT '用户编号',
|
||||||
|
`user_type` tinyint(4) DEFAULT '0' 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=22 DEFAULT CHARSET=utf8mb4 COMMENT='短信moan';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of sys_sms_log
|
||||||
|
-- ----------------------------
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (15, 1, 'YUN_PIAN', 2, 'test_01', 1, '正在进行登录操作登陆,您的验证码是1234', '{\"code\":\"1234\",\"operation\":\"登陆\"}', '4383920', '15601691399', 1, 2, 10, '2021-04-04 23:24:13', 0, '成功', '0', '发送成功', NULL, '62922707786', 10, '2021-04-04 23:24:26', 'DELIVRD', 'DELIVRD', NULL, '2021-04-04 23:23:29', NULL, '2021-04-04 23:25:17', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (16, 2, 'ALIYUN', 3, 'test_02', 1, '您的验证码1234,该验证码5分钟内有效,请勿泄漏于他人!', '{\"code\":\"1234\"}', 'SMS_207945135', '15601691399', 1, 2, 20, '2021-04-05 00:08:39', 999, '未知错误,需要解析', 'SDK.InvalidAccessKeySecret', 'SDK.InvalidAccessKeySecret : Specified Access Key Secret is not valid.\r\nRequestId : 2EA9C6A5-579F-4D21-B7D3-0AD3BA4F7741', '2EA9C6A5-579F-4D21-B7D3-0AD3BA4F7741', NULL, 0, NULL, NULL, NULL, NULL, '2021-04-05 00:08:39', NULL, '2021-04-05 00:08:39', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (17, 2, 'ALIYUN', 3, 'test_02', 1, '您的验证码1234,该验证码5分钟内有效,请勿泄漏于他人!', '{\"code\":\"1234\"}', 'SMS_207945135', '15601691399', 1, 2, 20, '2021-04-05 00:09:43', 999, '未知错误,需要解析', 'SDK.InvalidAccessKeySecret', 'SDK.InvalidAccessKeySecret : Specified Access Key Secret is not valid.\r\nRequestId : BF766164-9C03-44FD-B6D3-ADA74118E432', 'BF766164-9C03-44FD-B6D3-ADA74118E432', NULL, 0, NULL, NULL, NULL, NULL, '2021-04-05 00:09:43', NULL, '2021-04-05 00:09:43', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (18, 2, 'ALIYUN', 3, 'test_02', 1, '您的验证码1234,该验证码5分钟内有效,请勿泄漏于他人!', '{\"code\":\"1234\"}', 'SMS_207945135', '15601691399', 1, 2, 20, '2021-04-05 00:11:13', 999, '未知错误,需要解析', 'SDK.InvalidAccessKeySecret', 'SDK.InvalidAccessKeySecret : Specified Access Key Secret is not valid.\r\nRequestId : 2D7C0ABC-7538-45B4-BFEF-B610D591CE3D', '2D7C0ABC-7538-45B4-BFEF-B610D591CE3D', NULL, 0, NULL, NULL, NULL, NULL, '2021-04-05 00:11:12', NULL, '2021-04-05 00:11:13', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (19, 2, 'ALIYUN', 3, 'test_02', 1, '您的验证码1234,该验证码5分钟内有效,请勿泄漏于他人!', '{\"code\":\"1234\"}', 'SMS_207945135', '15601691399', 1, 2, 20, '2021-04-05 00:12:21', 999, '未知错误,需要解析', 'SDK.InvalidAccessKeySecret', 'SDK.InvalidAccessKeySecret : Specified Access Key Secret is not valid.\r\nRequestId : 0A86DC5C-2985-474F-B076-748C9F2C5D3F', '0A86DC5C-2985-474F-B076-748C9F2C5D3F', NULL, 0, NULL, NULL, NULL, NULL, '2021-04-05 00:12:01', NULL, '2021-04-05 00:12:21', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (20, 1, 'YUN_PIAN', 2, 'test_01', 1, '正在进行登录操作登陆,您的验证码是1234', '{\"code\":\"1234\",\"operation\":\"登陆\"}', '4383920', '15601691399', 1, 2, 10, '2021-04-05 00:14:36', 0, '成功', '0', '发送成功', NULL, '62923244790', 0, NULL, NULL, NULL, NULL, '2021-04-05 00:13:42', NULL, '2021-04-05 00:14:36', b'0');
|
||||||
|
INSERT INTO `sys_sms_log` VALUES (21, 2, 'ALIYUN', 3, 'test_02', 1, '您的验证码1234,该验证码5分钟内有效,请勿泄漏于他人!', '{\"code\":\"1234\"}', 'SMS_207945135', '15601691399', 1, 2, 20, '2021-04-05 00:19:43', 999, '未知错误,需要解析', 'SDK.InvalidAccessKeySecret', 'SDK.InvalidAccessKeySecret : Specified Access Key Secret is not valid.\r\nRequestId : 3837C6D3-B96F-428C-BBB2-86135D4B5B99', '3837C6D3-B96F-428C-BBB2-86135D4B5B99', NULL, 0, NULL, NULL, NULL, NULL, '2021-04-05 00:15:06', NULL, '2021-04-05 00:19:44', b'0');
|
||||||
|
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=4 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', '', '2021-03-31 12:01:38', 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', '', '2021-03-31 11:56:30', b'0');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Table structure for sys_user
|
-- Table structure for sys_user
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -865,8 +990,8 @@ CREATE TABLE `sys_user` (
|
|||||||
-- Records of sys_user
|
-- Records of sys_user
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
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 (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-01-05 17:03:47', 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 (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 (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');
|
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,11 +1049,17 @@ CREATE TABLE `sys_user_session` (
|
|||||||
-- Records of sys_user_session
|
-- Records of sys_user_session
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
BEGIN;
|
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-05 22:23:22', b'0');
|
||||||
|
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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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 ('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');
|
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');
|
||||||
@ -964,7 +1095,7 @@ CREATE TABLE `tool_codegen_column` (
|
|||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=389 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表字段定义';
|
) ENGINE=InnoDB AUTO_INCREMENT=418 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表字段定义';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of tool_codegen_column
|
-- Records of tool_codegen_column
|
||||||
@ -1126,6 +1257,35 @@ 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 (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 (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 (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');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
@ -1151,7 +1311,7 @@ CREATE TABLE `tool_codegen_table` (
|
|||||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
PRIMARY KEY (`id`) USING BTREE
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表定义';
|
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COMMENT='代码生成表定义';
|
||||||
|
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
-- Records of tool_codegen_table
|
-- Records of tool_codegen_table
|
||||||
@ -1169,6 +1329,8 @@ 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 (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 (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 (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');
|
||||||
COMMIT;
|
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;
|
package cn.iocoder.dashboard.common.exception;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
|
import cn.iocoder.dashboard.common.exception.enums.ServiceErrorCodeRange;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 错误码对象
|
* 错误码对象
|
||||||
*
|
*
|
||||||
* 全局错误码,占用 [0, 999],参见 {@link GlobalException}
|
* 全局错误码,占用 [0, 999], 参见 {@link GlobalErrorCodeConstants}
|
||||||
* 业务异常错误码,占用 [1 000 000 000, +∞),参见 {@link ServiceErrorCodeRange}
|
* 业务异常错误码,占用 [1 000 000 000, +∞),参见 {@link ServiceErrorCodeRange}
|
||||||
*
|
*
|
||||||
* TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
|
* TODO 错误码设计成对象的原因,为未来的 i18 国际化做准备
|
||||||
@ -21,11 +22,11 @@ public class ErrorCode {
|
|||||||
/**
|
/**
|
||||||
* 错误提示
|
* 错误提示
|
||||||
*/
|
*/
|
||||||
private final String message;
|
private final String msg;
|
||||||
|
|
||||||
public ErrorCode(Integer code, String message) {
|
public ErrorCode(Integer code, String message) {
|
||||||
this.code = code;
|
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) {
|
public ServiceException(ErrorCode errorCode) {
|
||||||
this.code = errorCode.getCode();
|
this.code = errorCode.getCode();
|
||||||
this.message = errorCode.getMessage();
|
this.message = errorCode.getMsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceException(Integer code, String message) {
|
public ServiceException(Integer code, String message) {
|
||||||
|
@ -47,12 +47,12 @@ public class ServiceExceptionUtil {
|
|||||||
// ========== 和 ServiceException 的集成 ==========
|
// ========== 和 ServiceException 的集成 ==========
|
||||||
|
|
||||||
public static ServiceException exception(ErrorCode errorCode) {
|
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);
|
return exception0(errorCode.getCode(), messagePattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServiceException exception(ErrorCode errorCode, Object... params) {
|
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);
|
return exception0(errorCode.getCode(), messagePattern, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package cn.iocoder.dashboard.common.pojo;
|
package cn.iocoder.dashboard.common.pojo;
|
||||||
|
|
||||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
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.ServiceException;
|
||||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
@ -9,6 +8,7 @@ import lombok.Data;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通用返回
|
* 通用返回
|
||||||
@ -16,7 +16,7 @@ import java.io.Serializable;
|
|||||||
* @param <T> 数据泛型
|
* @param <T> 数据泛型
|
||||||
*/
|
*/
|
||||||
@Data
|
@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;
|
private String msg;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ public final class CommonResult<T> implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <T> CommonResult<T> error(ErrorCode errorCode) {
|
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) {
|
public static <T> CommonResult<T> success(T data) {
|
||||||
@ -68,9 +68,13 @@ public final class CommonResult<T> implements Serializable {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSuccess(Integer code) {
|
||||||
|
return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
@JsonIgnore // 避免 jackson 序列化
|
@JsonIgnore // 避免 jackson 序列化
|
||||||
public boolean isSuccess() {
|
public boolean isSuccess() {
|
||||||
return GlobalErrorCodeConstants.SUCCESS.getCode().equals(code);
|
return isSuccess(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore // 避免 jackson 序列化
|
@JsonIgnore // 避免 jackson 序列化
|
||||||
@ -81,16 +85,12 @@ public final class CommonResult<T> implements Serializable {
|
|||||||
// ========= 和 Exception 异常体系集成 =========
|
// ========= 和 Exception 异常体系集成 =========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断是否有异常。如果有,则抛出 {@link GlobalException} 或 {@link ServiceException} 异常
|
* 判断是否有异常。如果有,则抛出 {@link ServiceException} 异常
|
||||||
*/
|
*/
|
||||||
public void checkError() throws GlobalException, ServiceException {
|
public void checkError() throws ServiceException {
|
||||||
if (isSuccess()) {
|
if (isSuccess()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 全局异常
|
|
||||||
if (GlobalErrorCodeConstants.isMatch(code)) {
|
|
||||||
throw new GlobalException(code, msg);
|
|
||||||
}
|
|
||||||
// 业务异常
|
// 业务异常
|
||||||
throw new ServiceException(code, msg);
|
throw new ServiceException(code, msg);
|
||||||
}
|
}
|
||||||
@ -99,8 +99,4 @@ public final class CommonResult<T> implements Serializable {
|
|||||||
return error(serviceException.getCode(), serviceException.getMessage());
|
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 com.alibaba.excel.metadata.property.ExcelContentProperty;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excel {@link SysDictDataDO} 数据字典转换器
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DictConvert implements Converter<Object> {
|
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 广播消费的容器
|
* 创建 Redis Pub/Sub 广播消费的容器
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory factory,
|
public RedisMessageListenerContainer redisMessageListenerContainer(
|
||||||
List<AbstractChannelMessageListener<?>> listeners) {
|
RedisConnectionFactory factory, List<AbstractChannelMessageListener<?>> listeners) {
|
||||||
// 创建 RedisMessageListenerContainer 对象
|
// 创建 RedisMessageListenerContainer 对象
|
||||||
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||||
// 设置 RedisConnection 工厂。
|
// 设置 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
|
* Redis Stream 的 xreadgroup 命令:https://www.geek-book.com/src/docs/redis/redis/redis.io/commands/xreadgroup.html
|
||||||
*/
|
*/
|
||||||
@Bean(initMethod = "start", destroyMethod = "stop")
|
@Bean(initMethod = "start", destroyMethod = "stop")
|
||||||
public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(RedisTemplate<String, Object> redisTemplate,
|
public StreamMessageListenerContainer<String, ObjectRecord<String, String>> redisStreamMessageListenerContainer(
|
||||||
List<AbstractStreamMessageListener<?>> listeners) {
|
RedisTemplate<String, Object> redisTemplate, List<AbstractStreamMessageListener<?>> listeners) {
|
||||||
// 第一步,创建 StreamMessageListenerContainer 容器
|
// 第一步,创建 StreamMessageListenerContainer 容器
|
||||||
// 创建 options 配置
|
// 创建 options 配置
|
||||||
StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
|
StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, ObjectRecord<String, String>> containerOptions =
|
||||||
|
@ -128,13 +128,13 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||||||
// 设置每个请求的权限
|
// 设置每个请求的权限
|
||||||
.authorizeRequests()
|
.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(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||||
// 文件的获取接口,可匿名访问
|
// 文件的获取接口,可匿名访问
|
||||||
.antMatchers(webProperties.getApiPrefix() + "/infra/file/get/**").anonymous()
|
.antMatchers(api("/infra/file/get/**")).anonymous()
|
||||||
// Swagger 接口文档
|
// Swagger 接口文档
|
||||||
.antMatchers("/swagger-ui.html").anonymous()
|
.antMatchers("/swagger-ui.html").anonymous()
|
||||||
.antMatchers("/swagger-resources/**").anonymous()
|
.antMatchers("/swagger-resources/**").anonymous()
|
||||||
@ -148,13 +148,19 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||||||
.antMatchers("/actuator/**").anonymous()
|
.antMatchers("/actuator/**").anonymous()
|
||||||
// Druid 监控
|
// Druid 监控
|
||||||
.antMatchers("/druid/**").anonymous()
|
.antMatchers("/druid/**").anonymous()
|
||||||
|
// 短信回调 API
|
||||||
|
.antMatchers(api("/system/sms/callback/**")).anonymous()
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
// 除上面外的所有请求全部需要鉴权认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.headers().frameOptions().disable();
|
.headers().frameOptions().disable();
|
||||||
httpSecurity.logout().logoutUrl(webProperties.getApiPrefix() + "/logout").logoutSuccessHandler(logoutSuccessHandler);
|
httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler);
|
||||||
// 添加 JWT Filter
|
// 添加 JWT Filter
|
||||||
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
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;
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,6 @@ package cn.iocoder.dashboard.framework.web.core.handler;
|
|||||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.extra.servlet.ServletUtil;
|
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.exception.ServiceException;
|
||||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||||
import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService;
|
import cn.iocoder.dashboard.framework.logger.apilog.core.service.ApiErrorLogFrameworkService;
|
||||||
@ -96,9 +95,6 @@ public class GlobalExceptionHandler {
|
|||||||
if (ex instanceof AccessDeniedException) {
|
if (ex instanceof AccessDeniedException) {
|
||||||
return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
|
return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
|
||||||
}
|
}
|
||||||
if (ex instanceof GlobalException) {
|
|
||||||
return globalExceptionHandler(request, (GlobalException) ex);
|
|
||||||
}
|
|
||||||
return defaultExceptionHandler(request, ex);
|
return defaultExceptionHandler(request, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,25 +218,6 @@ public class GlobalExceptionHandler {
|
|||||||
return CommonResult.error(ex.getCode(), ex.getMessage());
|
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);
|
this.createExceptionLog(req, ex);
|
||||||
// 返回 ERROR CommonResult
|
// 返回 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) {
|
private void createExceptionLog(HttpServletRequest req, Throwable e) {
|
||||||
|
@ -61,7 +61,7 @@ public class SysDictDataController {
|
|||||||
@GetMapping("/list-all-simple")
|
@GetMapping("/list-all-simple")
|
||||||
@ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
|
@ApiOperation(value = "获得全部字典数据列表", notes = "一般用于管理后台缓存字典数据在本地")
|
||||||
// 无需添加权限认证,因为前端全局都需要
|
// 无需添加权限认证,因为前端全局都需要
|
||||||
public CommonResult<List<SysDictDataSimpleVO>> getSimpleDictDatas() {
|
public CommonResult<List<SysDictDataSimpleRespVO>> getSimpleDictDatas() {
|
||||||
List<SysDictDataDO> list = dictDataService.getDictDatas();
|
List<SysDictDataDO> list = dictDataService.getDictDatas();
|
||||||
return success(SysDictDataConvert.INSTANCE.convertList(list));
|
return success(SysDictDataConvert.INSTANCE.convertList(list));
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public class SysDictTypeController {
|
|||||||
return success(dictTypeId);
|
return success(dictTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("update")
|
@PutMapping("/update")
|
||||||
@ApiOperation("修改字典类型")
|
@ApiOperation("修改字典类型")
|
||||||
@PreAuthorize("@ss.hasPermission('system:dict:update')")
|
@PreAuthorize("@ss.hasPermission('system:dict:update')")
|
||||||
public CommonResult<Boolean> updateDictType(@Valid @RequestBody SysDictTypeUpdateReqVO reqVO) {
|
public CommonResult<Boolean> updateDictType(@Valid @RequestBody SysDictTypeUpdateReqVO reqVO) {
|
||||||
|
@ -4,9 +4,9 @@ import io.swagger.annotations.ApiModel;
|
|||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ApiModel("数据字典精简 VO")
|
@ApiModel("数据字典精简 Response VO")
|
||||||
@Data
|
@Data
|
||||||
public class SysDictDataSimpleVO {
|
public class SysDictDataSimpleRespVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "字典类型", required = true, example = "gender")
|
@ApiModelProperty(value = "字典类型", required = true, example = "gender")
|
||||||
private String dictType;
|
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;
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,7 @@ public interface SysDictDataConvert {
|
|||||||
|
|
||||||
SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
|
SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
|
||||||
|
|
||||||
List<SysDictDataSimpleVO> convertList(List<SysDictDataDO> list);
|
List<SysDictDataSimpleRespVO> convertList(List<SysDictDataDO> list);
|
||||||
|
|
||||||
SysDictDataRespVO convert(SysDictDataDO bean);
|
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);
|
||||||
|
|
||||||
|
}
|
@ -30,8 +30,8 @@ public interface SysErrorCodeConstants {
|
|||||||
|
|
||||||
// ========== 角色模块 1002003000 ==========
|
// ========== 角色模块 1002003000 ==========
|
||||||
ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1002003000, "角色不存在");
|
ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1002003000, "角色不存在");
|
||||||
ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1002003001, "已经存在名为【{}}】的角色");
|
ErrorCode ROLE_NAME_DUPLICATE = new ErrorCode(1002003001, "已经存在名为【{}】的角色");
|
||||||
ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1002003002, "已经存在编码为【{}}】的角色");
|
ErrorCode ROLE_CODE_DUPLICATE = new ErrorCode(1002003002, "已经存在编码为【{}】的角色");
|
||||||
ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1002003004, "不能操作类型为系统内置的角色");
|
ErrorCode ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1002003004, "不能操作类型为系统内置的角色");
|
||||||
|
|
||||||
// ========== 用户模块 1002004000 ==========
|
// ========== 用户模块 1002004000 ==========
|
||||||
@ -78,4 +78,18 @@ public interface SysErrorCodeConstants {
|
|||||||
ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败");
|
ErrorCode FILE_UPLOAD_FAILED = new ErrorCode(1002009002, "文件上传失败");
|
||||||
ErrorCode FILE_IS_EMPTY= new ErrorCode(1002009003, "文件为空");
|
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, "模板参数({})缺失");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,10 @@ public enum SysDictTypeEnum {
|
|||||||
SYS_LOGIN_RESULT("sys_login_result"), // 登陆结果
|
SYS_LOGIN_RESULT("sys_login_result"), // 登陆结果
|
||||||
SYS_CONFIG_TYPE("sys_config_type"), // 参数配置类型
|
SYS_CONFIG_TYPE("sys_config_type"), // 参数配置类型
|
||||||
SYS_BOOLEAN_STRING("sys_boolean_string"), // Boolean 是否类型
|
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_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"), // Redis 超时类型
|
||||||
INF_JOB_STATUS("inf_job_status"), // 定时任务状态的枚举
|
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.framework.redis.core.stream.AbstractStreamMessageListener;
|
||||||
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对 {@link SysSmsSendMessage} 的消费者
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 2021/3/9 16:35
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
|
public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysSmsService smsService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(SysSmsSendMessage message) {
|
public void onMessage(SysSmsSendMessage message) {
|
||||||
log.info("[onMessage][消息内容({})]", 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.mq.message.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信渠道的数据刷新 Message
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SysSmsChannelRefreshMessage implements ChannelMessage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return "system.sms-channel.refresh";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.mq.message.sms;
|
package cn.iocoder.dashboard.modules.system.mq.message.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||||
import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage;
|
import cn.iocoder.dashboard.framework.redis.core.stream.StreamMessage;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 短信发送消息
|
* 短信发送消息
|
||||||
@ -14,29 +15,30 @@ import java.util.Map;
|
|||||||
@Data
|
@Data
|
||||||
public class SysSmsSendMessage implements StreamMessage {
|
public class SysSmsSendMessage implements StreamMessage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志编号
|
||||||
|
*/
|
||||||
|
@NotNull(message = "短信日志编号不能为空")
|
||||||
|
private Long logId;
|
||||||
/**
|
/**
|
||||||
* 手机号
|
* 手机号
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "手机号不能为空")
|
@NotNull(message = "手机号不能为空")
|
||||||
private String mobile;
|
private String mobile;
|
||||||
/**
|
/**
|
||||||
* 短信模板编号
|
* 短信渠道编号
|
||||||
*/
|
*/
|
||||||
@NotNull(message = "短信模板编号不能为空")
|
@NotNull(message = "短信渠道编号不能为空")
|
||||||
private String templateCode;
|
private Long channelId;
|
||||||
|
/**
|
||||||
|
* 短信 API 的模板编号
|
||||||
|
*/
|
||||||
|
@NotNull(message = "短信 API 的模板编号不能为空")
|
||||||
|
private String apiTemplateId;
|
||||||
/**
|
/**
|
||||||
* 短信模板参数
|
* 短信模板参数
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> templateParams;
|
private List<KeyValue<String, Object>> templateParams;
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户编号,允许空
|
|
||||||
*/
|
|
||||||
private Integer userId;
|
|
||||||
/**
|
|
||||||
* 用户类型,允许空
|
|
||||||
*/
|
|
||||||
private Integer userType;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStreamKey() {
|
public String getStreamKey() {
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.mq.message.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信模板的数据刷新 Message
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SysSmsTemplateRefreshMessage implements ChannelMessage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getChannel() {
|
||||||
|
return "system.sms-template.refresh";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,8 @@ import javax.annotation.Resource;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Role 角色相关消息的 Producer
|
* Role 角色相关消息的 Producer
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SysRoleProducer {
|
public class SysRoleProducer {
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.mq.producer.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||||
|
import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils;
|
||||||
|
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
|
||||||
|
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
|
||||||
|
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sms 短信相关消息的 Producer
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 2021/3/9 16:35
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class SysSmsProducer {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 {@link SysSmsSendMessage} 消息
|
||||||
|
*
|
||||||
|
* @param logId 短信日志编号
|
||||||
|
* @param mobile 手机号
|
||||||
|
* @param channelId 渠道编号
|
||||||
|
* @param apiTemplateId 短信模板编号
|
||||||
|
* @param templateParams 短信模板参数
|
||||||
|
*/
|
||||||
|
public void sendSmsSendMessage(Long logId, String mobile,
|
||||||
|
Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
|
||||||
|
SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile);
|
||||||
|
message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
|
||||||
|
RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 {@link SysSmsChannelRefreshMessage} 消息
|
||||||
|
*/
|
||||||
|
public void sendSmsChannelRefreshMessage() {
|
||||||
|
SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage();
|
||||||
|
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送 {@link SysSmsTemplateRefreshMessage} 消息
|
||||||
|
*/
|
||||||
|
public void sendSmsTemplateRefreshMessage() {
|
||||||
|
SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage();
|
||||||
|
RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,7 +18,7 @@ import java.util.Set;
|
|||||||
public interface SysPermissionService extends SecurityPermissionFrameworkService {
|
public interface SysPermissionService extends SecurityPermissionFrameworkService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 初始化权限的本地缓存
|
||||||
*/
|
*/
|
||||||
void initLocalCache();
|
void initLocalCache();
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysMenuProduce
|
|||||||
import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
|
import cn.iocoder.dashboard.modules.system.service.permission.SysMenuService;
|
||||||
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
|
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
|
||||||
import cn.iocoder.dashboard.util.collection.CollectionUtils;
|
import cn.iocoder.dashboard.util.collection.CollectionUtils;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
@ -168,10 +169,6 @@ public class SysMenuServiceImpl implements SysMenuService {
|
|||||||
*/
|
*/
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteMenu(Long menuId) {
|
public void deleteMenu(Long menuId) {
|
||||||
// 校验更新的菜单是否存在
|
|
||||||
if (menuMapper.selectById(menuId) == null) {
|
|
||||||
throw ServiceExceptionUtil.exception(MENU_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
// 校验是否还有子菜单
|
// 校验是否还有子菜单
|
||||||
if (menuMapper.selectCountByParentId(menuId) > 0) {
|
if (menuMapper.selectCountByParentId(menuId) > 0) {
|
||||||
throw ServiceExceptionUtil.exception(MENU_EXISTS_CHILDREN);
|
throw ServiceExceptionUtil.exception(MENU_EXISTS_CHILDREN);
|
||||||
@ -250,7 +247,8 @@ public class SysMenuServiceImpl implements SysMenuService {
|
|||||||
* @param parentId 父菜单编号
|
* @param parentId 父菜单编号
|
||||||
* @param childId 当前菜单编号
|
* @param childId 当前菜单编号
|
||||||
*/
|
*/
|
||||||
private void checkParentResource(Long parentId, Long childId) {
|
@VisibleForTesting
|
||||||
|
public void checkParentResource(Long parentId, Long childId) {
|
||||||
if (parentId == null || MenuIdEnum.ROOT.getId().equals(parentId)) {
|
if (parentId == null || MenuIdEnum.ROOT.getId().equals(parentId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -279,7 +277,8 @@ public class SysMenuServiceImpl implements SysMenuService {
|
|||||||
* @param parentId 父菜单编号
|
* @param parentId 父菜单编号
|
||||||
* @param id 菜单编号
|
* @param id 菜单编号
|
||||||
*/
|
*/
|
||||||
private void checkResource(Long parentId, String name, Long id) {
|
@VisibleForTesting
|
||||||
|
public void checkResource(Long parentId, String name, Long id) {
|
||||||
SysMenuDO menu = menuMapper.selectByParentIdAndName(parentId, name);
|
SysMenuDO menu = menuMapper.selectByParentIdAndName(parentId, name);
|
||||||
if (menu == null) {
|
if (menu == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -3,7 +3,6 @@ package cn.iocoder.dashboard.modules.system.service.permission.impl;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.dashboard.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMenuMapper;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysRoleMenuMapper;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysUserRoleMapper;
|
import cn.iocoder.dashboard.modules.system.dal.mysql.permission.SysUserRoleMapper;
|
||||||
|
@ -18,6 +18,7 @@ import cn.iocoder.dashboard.modules.system.enums.permission.SysRoleTypeEnum;
|
|||||||
import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysRoleProducer;
|
import cn.iocoder.dashboard.modules.system.mq.producer.permission.SysRoleProducer;
|
||||||
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
|
import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
|
||||||
import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
|
import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
@ -58,7 +59,7 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
*/
|
*/
|
||||||
private volatile Map<Long, SysRoleDO> roleCache;
|
private volatile Map<Long, SysRoleDO> roleCache;
|
||||||
/**
|
/**
|
||||||
* 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
|
* 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新
|
||||||
*/
|
*/
|
||||||
private volatile Date maxUpdateTime;
|
private volatile Date maxUpdateTime;
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
@Override
|
@Override
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initLocalCache() {
|
public void initLocalCache() {
|
||||||
// 获取菜单列表,如果有更新
|
// 获取角色列表,如果有更新
|
||||||
List<SysRoleDO> roleList = this.loadRoleIfUpdate(maxUpdateTime);
|
List<SysRoleDO> roleList = this.loadRoleIfUpdate(maxUpdateTime);
|
||||||
if (CollUtil.isEmpty(roleList)) {
|
if (CollUtil.isEmpty(roleList)) {
|
||||||
return;
|
return;
|
||||||
@ -98,23 +99,23 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果菜单发生变化,从数据库中获取最新的全量菜单。
|
* 如果角色发生变化,从数据库中获取最新的全量角色。
|
||||||
* 如果未发生变化,则返回空
|
* 如果未发生变化,则返回空
|
||||||
*
|
*
|
||||||
* @param maxUpdateTime 当前菜单的最大更新时间
|
* @param maxUpdateTime 当前角色的最大更新时间
|
||||||
* @return 菜单列表
|
* @return 角色列表
|
||||||
*/
|
*/
|
||||||
private List<SysRoleDO> loadRoleIfUpdate(Date maxUpdateTime) {
|
private List<SysRoleDO> loadRoleIfUpdate(Date maxUpdateTime) {
|
||||||
// 第一步,判断是否要更新。
|
// 第一步,判断是否要更新。
|
||||||
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
|
||||||
log.info("[loadRoleIfUpdate][首次加载全量菜单]");
|
log.info("[loadRoleIfUpdate][首次加载全量角色]");
|
||||||
} else { // 判断数据库中是否有更新的菜单
|
} else { // 判断数据库中是否有更新的角色
|
||||||
if (!roleMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
|
if (!roleMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
log.info("[loadRoleIfUpdate][增量加载全量菜单]");
|
log.info("[loadRoleIfUpdate][增量加载全量角色]");
|
||||||
}
|
}
|
||||||
// 第二步,如果有更新,则从数据库加载所有菜单
|
// 第二步,如果有更新,则从数据库加载所有角色
|
||||||
return roleMapper.selectList();
|
return roleMapper.selectList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +246,8 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
* @param code 角色额编码
|
* @param code 角色额编码
|
||||||
* @param id 角色编号
|
* @param id 角色编号
|
||||||
*/
|
*/
|
||||||
private void checkDuplicateRole(String name, String code, Long id) {
|
@VisibleForTesting
|
||||||
|
public void checkDuplicateRole(String name, String code, Long id) {
|
||||||
// 1. 该 name 名字被其它角色所使用
|
// 1. 该 name 名字被其它角色所使用
|
||||||
SysRoleDO role = roleMapper.selectByName(name);
|
SysRoleDO role = roleMapper.selectByName(name);
|
||||||
if (role != null && !role.getId().equals(id)) {
|
if (role != null && !role.getId().equals(id)) {
|
||||||
@ -258,7 +260,7 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
// 该 code 编码被其它角色所使用
|
// 该 code 编码被其它角色所使用
|
||||||
role = roleMapper.selectByCode(code);
|
role = roleMapper.selectByCode(code);
|
||||||
if (role != null && !role.getId().equals(id)) {
|
if (role != null && !role.getId().equals(id)) {
|
||||||
throw ServiceExceptionUtil.exception(ROLE_CODE_DUPLICATE, name);
|
throw ServiceExceptionUtil.exception(ROLE_CODE_DUPLICATE, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +269,8 @@ public class SysRoleServiceImpl implements SysRoleService {
|
|||||||
*
|
*
|
||||||
* @param id 角色编号
|
* @param id 角色编号
|
||||||
*/
|
*/
|
||||||
private void checkUpdateRole(Long id) {
|
@VisibleForTesting
|
||||||
|
public void checkUpdateRole(Long id) {
|
||||||
SysRoleDO roleDO = roleMapper.selectById(id);
|
SysRoleDO roleDO = roleMapper.selectById(id);
|
||||||
if (roleDO == null) {
|
if (roleDO == null) {
|
||||||
throw ServiceExceptionUtil.exception(ROLE_NOT_EXISTS);
|
throw ServiceExceptionUtil.exception(ROLE_NOT_EXISTS);
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.service.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelCreateReqVO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelPageReqVO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.controller.sms.vo.channel.SysSmsChannelUpdateReqVO;
|
||||||
|
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信渠道Service接口
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 2021/1/25 9:24
|
||||||
|
*/
|
||||||
|
public interface SysSmsChannelService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化短信客户端
|
||||||
|
*/
|
||||||
|
void initSmsClients();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建短信渠道
|
||||||
|
*
|
||||||
|
* @param createReqVO 创建信息
|
||||||
|
* @return 编号
|
||||||
|
*/
|
||||||
|
Long createSmsChannel(@Valid SysSmsChannelCreateReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新短信渠道
|
||||||
|
*
|
||||||
|
* @param updateReqVO 更新信息
|
||||||
|
*/
|
||||||
|
void updateSmsChannel(@Valid SysSmsChannelUpdateReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除短信渠道
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
*/
|
||||||
|
void deleteSmsChannel(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信渠道
|
||||||
|
*
|
||||||
|
* @param id 编号
|
||||||
|
* @return 短信渠道
|
||||||
|
*/
|
||||||
|
SysSmsChannelDO getSmsChannel(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信渠道列表
|
||||||
|
*
|
||||||
|
* @param ids 编号
|
||||||
|
* @return 短信渠道列表
|
||||||
|
*/
|
||||||
|
List<SysSmsChannelDO> getSmsChannelList(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得所有短信渠道列表
|
||||||
|
*
|
||||||
|
* @return 短信渠道列表
|
||||||
|
*/
|
||||||
|
List<SysSmsChannelDO> getSmsChannelList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信渠道分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 短信渠道分页
|
||||||
|
*/
|
||||||
|
PageResult<SysSmsChannelDO> getSmsChannelPage(SysSmsChannelPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package cn.iocoder.dashboard.modules.system.service.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
|
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 cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信日志 Service 实现类
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 13:48 2021/3/2
|
||||||
|
*/
|
||||||
|
public interface SysSmsLogService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建短信日志
|
||||||
|
*
|
||||||
|
* @param mobile 手机号
|
||||||
|
* @param userId 用户编号
|
||||||
|
* @param userType 用户类型
|
||||||
|
* @param isSend 是否发送
|
||||||
|
* @param template 短信模板
|
||||||
|
* @param templateContent 短信内容
|
||||||
|
* @param templateParams 短信参数
|
||||||
|
* @return 发送日志编号
|
||||||
|
*/
|
||||||
|
Long createSmsLog(String mobile, Long userId, Integer userType, Boolean isSend,
|
||||||
|
SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新日志的发送结果
|
||||||
|
*
|
||||||
|
* @param id 日志编号
|
||||||
|
* @param sendCode 发送结果的编码
|
||||||
|
* @param sendMsg 发送结果的提示
|
||||||
|
* @param apiSendCode 短信 API 发送结果的编码
|
||||||
|
* @param apiSendMsg 短信 API 发送失败的提示
|
||||||
|
* @param apiRequestId 短信 API 发送返回的唯一请求 ID
|
||||||
|
* @param apiSerialNo 短信 API 发送返回的序号
|
||||||
|
*/
|
||||||
|
void updateSmsSendResult(Long id, Integer sendCode, String sendMsg,
|
||||||
|
String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新日志的接收结果
|
||||||
|
*
|
||||||
|
* @param id 日志编号
|
||||||
|
* @param success 是否接收成功
|
||||||
|
* @param receiveTime 用户接收时间
|
||||||
|
* @param apiReceiveCode API 接收结果的编码
|
||||||
|
* @param apiReceiveMsg API 接收结果的说明
|
||||||
|
*/
|
||||||
|
void updateSmsReceiveResult(Long id, Boolean success, Date receiveTime, String apiReceiveCode, String apiReceiveMsg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信日志分页
|
||||||
|
*
|
||||||
|
* @param pageReqVO 分页查询
|
||||||
|
* @return 短信日志分页
|
||||||
|
*/
|
||||||
|
PageResult<SysSmsLogDO> getSmsLogPage(SysSmsLogPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信日志列表, 用于 Excel 导出
|
||||||
|
*
|
||||||
|
* @param exportReqVO 查询条件
|
||||||
|
* @return 短信日志列表
|
||||||
|
*/
|
||||||
|
List<SysSmsLogDO> getSmsLogList(SysSmsLogExportReqVO exportReqVO);
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user