浏览代码

短信接口

linwu 1 天之前
父节点
当前提交
65fbf203a8

+ 46 - 27
README.md

@@ -1,56 +1,75 @@
-ThinkPHP 6.0
-===============
-
-> 运行环境要求PHP7.2+,兼容PHP8.1
-
-[官方应用服务市场](https://market.topthink.com) | [`ThinkAPI`——官方统一API服务](https://docs.topthink.com/think-api)
+![](https://box.kancloud.cn/5a0aaa69a5ff42657b5c4715f3d49221)
 
-ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
+ThinkPHP 6.1
+===============
 
-## 主要新特性
+### 主要新特性
 
 * 采用`PHP7`强类型(严格模式)
 * 支持更多的`PSR`规范
 * 原生多应用支持
-* 更强大和易用的查询
+* 系统服务注入支持
+* ORM作为独立组件使用
 * 全新的事件系统
-* 模型事件和数据库事件统一纳入事件系统
 * 模板引擎分离出核心
 * 内部功能中间件化
-* SESSION/Cookie机制改进
+* SESSION机制改进
+* 日志多通道支持
+* 规范扩展接口
+* 更强大的控制台
 * 对Swoole以及协程支持改进
 * 对IDE更加友好
 * 统一和精简大量用法
 
-## 安装
+
+> ThinkPHP6.1的运行环境要求PHP7.2.5+,最高兼容PHP8.2
+
+### 安装
 
 ~~~
-composer create-project topthink/think tp 6.0.*
+composer create-project topthink/think tp
 ~~~
 
-如果需要更新框架使用
+启动服务
+
 ~~~
-composer update topthink/framework
+cd tp
+php think run
 ~~~
 
-## 文档
+然后就可以在浏览器中访问
 
-[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
-
-## 参与开发
+~~~
+http://localhost:8000
+~~~
 
-请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
+如果需要更新框架使用
+~~~
+composer update topthink/framework
+~~~
 
-## 版权信息
+### 文档
 
-ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+[TP6完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
 
-本项目包含的第三方源码和二进制文件之版权信息另行标注。
+VUE3.3.4
+===============
 
-版权所有Copyright © 2006-2021 by ThinkPHP (http://thinkphp.cn)
+[VUE官方在线手册](https://cn.vuejs.org/)
 
-All rights reserved。
+VANT4.6
+===============
+[VANT官方在线手册](https://vant-ui.github.io/vant/#/zh-CN/)
 
-ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+LAYUI
+===============
+[官方在线手册](https://www.bejson.com/doc/layui/doc/index.html)
 
-更多细节参阅 [LICENSE.txt](LICENSE.txt)
+其他
+===============
+### 需要写入权限文件
+~~~
+/runtime
+/public/storage
+/public/ueditor
+~~~

+ 1 - 0
app/admin/controller/Setting.php

@@ -15,6 +15,7 @@ class Setting extends AdminBaseController
         $sms = SettingModel::getConfigValue(SettingModel::SMS);
         return view('', [
             'sms' => $sms,
+            'sms_type_list' => SettingModel::SMS_TYPE,
         ]);
     }
 

+ 105 - 0
app/admin/controller/Sms.php

@@ -0,0 +1,105 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\SmsAuthModel;
+use app\common\model\SmsLogModel;
+use app\common\validate\SmsAuthValidate;
+use app\common\validate\SmsTemplateValidate;
+use app\common\model\SmsTemplateModel;
+use think\exception\ValidateException;
+
+class Sms extends AdminBaseController
+{
+    /**
+     * 授权
+     */
+    public function auth()
+    {
+        return view();
+    }
+
+    public function authForm()
+    {
+        $id   = input('id/d, 0');
+        $info = SmsAuthModel::find($id);
+        if (empty($info)) {
+            $info['token'] = rand_str(8) . uniqid();
+        }
+        return view('', [
+            'info' => $info,
+        ]);
+    }
+
+    public function listAuth()
+    {
+        $list  = SmsAuthModel::limit(input('limit'))
+            ->page(input('page'))
+            ->select();
+        $count = SmsAuthModel::count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delAuth()
+    {
+        $id = input('id/d', 0);
+        SmsAuthModel::destroy($id);
+        ajax_return();
+    }
+
+    public function editAuth()
+    {
+        $data = input('post.');
+        try {
+            validate(SmsAuthValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            $check = SmsAuthModel::where('token', $data['token'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该token已存在');
+            }
+            SmsAuthModel::create($data);
+        } else {
+            $check = SmsAuthModel::where('token', $data['token'])->where('id', '<>', $data['id'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该token已存在');
+            }
+            SmsAuthModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+
+    /**
+     * 日志
+     */
+    public function log()
+    {
+        return view('', [
+            'status_list' => SmsLogModel::STATUS,
+        ]);
+    }
+
+    public function listLog()
+    {
+        $map = $this->dealEqualInput(['status']);
+
+        $list  = SmsLogModel::limit(input('limit'))
+            ->where($map)
+            ->page(input('page'))
+            ->append(['status_text'])
+            ->select();
+        $count = SmsLogModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+}

+ 75 - 0
app/admin/controller/SmsTemplate.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\SmsAuthModel;
+use app\common\validate\SmsAuthValidate;
+use app\common\validate\SmsTemplateValidate;
+use app\common\model\SmsTemplateModel;
+use think\exception\ValidateException;
+
+class SmsTemplate extends AdminBaseController
+{
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view();
+    }
+
+    public function templateForm()
+    {
+        $id   = input('id/d, 0');
+        $info = SmsTemplateModel::find($id);
+        return view('', [
+            'info' => $info,
+        ]);
+    }
+
+    public function listTemplate()
+    {
+        $list  = SmsTemplateModel::limit(input('limit'))
+            ->page(input('page'))
+            ->select();
+        $count = SmsTemplateModel::count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delTemplate()
+    {
+        $id = input('id/d', 0);
+        SmsTemplateModel::destroy($id);
+        ajax_return();
+    }
+
+    public function editTemplate()
+    {
+        $data = input('post.');
+        try {
+            validate(SmsTemplateValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            $check = SmsTemplateModel::where('code', $data['code'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该编号已存在');
+            }
+            SmsTemplateModel::create($data);
+        } else {
+            $check = SmsTemplateModel::where('code', $data['code'])->where('id', '<>', $data['id'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该编号已存在');
+            }
+            SmsTemplateModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 2 - 2
app/admin/view/company/info.html

@@ -25,7 +25,7 @@
                             <tbody>
                                 <tr>
                                     <td onclick="copyMobileUrl('https://59.57.98.130:20661/d88b8988');">外网面板地址:https://59.57.98.130:20661/d88b8988</td>
-                                    <td onclick="copyMobileUrl('https://192.168.1.77:20661/d88b8988');"> 内网面板地址:https://192.168.1.77:20661/d88b8988</td>
+                                    <td onclick="copyMobileUrl('http://10.10.10.239:20661/d88b8988');"> 内网面板地址:http://10.10.10.239:20661/d88b8988</td>
                                     <td onclick="copyMobileUrl('vskpybca');">帐号:vskpybca</td>
                                     <td onclick="copyMobileUrl('c9a4dbb5');">密码:c9a4dbb5</td>
                                 </tr>
@@ -253,7 +253,7 @@
                                 <tr>
                                     <td>服务器</td>
                                     <td onclick="copyMobileUrl('zmw');">用户名:zmw</td>
-                                    <td onclick="copyMobileUrl('i6^yVQYil4HnvIc-');">密码:i6^yVQYil4HnvIc-</td>
+                                    <td onclick="copyMobileUrl('LpQ3(p^4)5odnJSy');">密码:LpQ3(p^4)5odnJSy</td>
                                 </tr>
                                 <tr>
                                     <td>数据库</td>

+ 31 - 4
app/admin/view/setting/sms.html

@@ -4,11 +4,38 @@
 
             <div class="layui-card layui-tab  layui-tab-brief" lay-filter="linktab">
                 <ul class="layui-tab-title">
-                    <li class="layui-this">创蓝</li>
-                    <!--<li>阿里</li>-->
+                    <li class="layui-this">基础配置</li>
+                    <li>创蓝</li>
+                    <li>阿里</li>
                 </ul>
                 <div class="layui-tab-content">
                     <div class="layui-tab-item layui-show">
+                        <div class="layui-card">
+                            <div class="layui-card-header">平台选择</div>
+                            <div class="layui-card-body" pad15>
+                                <div class="layui-form layui-form-pane">
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>默认平台</label>
+                                        <div class="layui-input-block">
+                                            <select name="sms_type">
+                                                <option value="">请选择默认平台</option>
+                                                {volist name="sms_type_list" id="type"}
+                                                    <option value="{$key}" {:array_get($sms,'sms_type')==$key ? 'selected' : '' }>{$type}</option>
+                                                {/volist}
+                                            </select>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <div class="layui-input-block">
+                                            <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                                        </div>
+                                    </div>
+                                </div>
+
+                            </div>
+                        </div>
+                    </div>
+                    <div class="layui-tab-item">
                         <div class="layui-card">
                             <div class="layui-card-header">创蓝短信接口参数</div>
                             <div class="layui-card-body" pad15>
@@ -45,7 +72,7 @@
                             </div>
                         </div>
                     </div>
-                    <!--<div class="layui-tab-item">
+                    <div class="layui-tab-item">
                         <div class="layui-card">
                             <div class="layui-card-header">阿里云短信接口参数</div>
                             <div class="layui-card-body" pad15>
@@ -114,7 +141,7 @@
 
                             </div>
                         </div>
-                    </div>-->
+                    </div>
                 </div>
             </div>
 

+ 93 - 0
app/admin/view/sms/auth.html

@@ -0,0 +1,93 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('sms/listAuth')}",
+            cols: [
+                [
+                    {field: 'id', width: 80,title: 'ID'},
+                    {field: 'token', width: 160, title: 'token'},
+                    {field: 'ip', width: 160, title: 'ip'},
+                    {field: 'comment', title: '备注'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加授权',
+                    content: "{:url('sms/authForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此授权吗?', function (index) {
+                    admin.req({
+                        url: "{:url('sms/delAuth')}",
+                        data: {
+                            id: data.id
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑授权',
+                    content: "{:url('sms/authForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 68 - 0
app/admin/view/sms/auth_form.html

@@ -0,0 +1,68 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">短信授权</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>token</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="token" value="{:array_get($info,'token')}" lay-verify="required"
+                                       placeholder="请输入token" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>IP</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="ip" value="{:array_get($info,'ip')}" lay-verify="required"
+                                       placeholder="请输入IP" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>备注</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="comment" value="{:array_get($info,'comment')}" lay-verify="required"
+                                       placeholder="请输入备注" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('sms/editAuth')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-sms-auth-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+    });
+</script>

+ 114 - 0
app/admin/view/sms/log.html

@@ -0,0 +1,114 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-inline">
+                <label class="layui-form-label">状态</label>
+                <div class="layui-input-block">
+                    <select name="status">
+                        <option value="">全部状态</option>
+                        {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                        {/volist}
+                    </select>
+                </div>
+            </div>
+            <div class="layui-inline">
+                <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                    <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                </button>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('sms/listLog')}",
+            cols: [
+                [
+                    {field: 'id', width: 80,title: 'ID'},
+                    {field: 'token', width: 160, title: 'token'},
+                    {field: 'ip', width: 120, title: 'ip'},
+                    {field: 'content', title: '内容'},
+                    {field: 'create_time', width: 160, title: '发送时间'},
+                    {field: 'status_text', width: 120, title: '状态'},
+                    {field: 'error', width: 160,title: '错误提示'},
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //监听搜索
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加授权',
+                    content: "{:url('sms/authForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此授权吗?', function (index) {
+                    admin.req({
+                        url: "{:url('sms/delAuth')}",
+                        data: {
+                            id: data.id
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑授权',
+                    content: "{:url('sms/authForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 92 - 0
app/admin/view/sms_template/index.html

@@ -0,0 +1,92 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('sms_template/listTemplate')}",
+            cols: [
+                [
+                    {field: 'id', width: 80,title: 'ID'},
+                    {field: 'code', width: 160, title: '编号'},
+                    {field: 'comment', title: '备注'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加模板',
+                    content: "{:url('sms_template/templateForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此模板吗?', function (index) {
+                    admin.req({
+                        url: "{:url('sms_template/delTemplate')}",
+                        data: {
+                            id: data.id
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑模板',
+                    content: "{:url('sms_template/templateForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 66 - 0
app/admin/view/sms_template/template_form.html

@@ -0,0 +1,66 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">短信模板</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>编号</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="code" value="{:array_get($info,'code')}" lay-verify="required"
+                                       placeholder="请输入编号" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">短信内容</label>
+                            <div class="layui-input-block">
+                                <textarea name="content" placeholder="请输入..." lay-verify="required" rows="15" class="layui-textarea">{:array_get($info,'content')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>备注</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="comment" value="{:array_get($info,'comment')}" lay-verify="required"
+                                       placeholder="请输入备注" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('sms_template/editTemplate')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-smstemplate-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+    });
+</script>

+ 20 - 0
app/api/ApiBaseController.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace app\api;
+
+use app\BaseController;
+use app\common\model\AdminModel;
+use app\common\model\MenuModel;
+use think\facade\Session;
+use think\facade\View;
+
+/**
+ * 控制器基础类
+ */
+class ApiBaseController extends BaseController
+{
+    // 初始化
+    protected function initialize()
+    {
+    }
+}

+ 12 - 0
app/api/common.php

@@ -0,0 +1,12 @@
+<?php
+// 应用公共文件
+
+function ajax_success($data = [], $msg = '成功')
+{
+    ajax_return(0, $msg, $data);
+}
+
+function ajax_error($msg = '', $data = [])
+{
+    ajax_return(1, $msg, $data);
+}

+ 59 - 0
app/api/controller/Sms.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace app\api\controller;
+
+use app\api\ApiBaseController;
+use app\common\model\SettingModel;
+use app\common\model\SmsAuthModel;
+use app\common\model\SmsLogModel;
+use app\common\service\SmsService;
+use think\facade\Log;
+
+class Sms extends ApiBaseController
+{
+    public function send()
+    {
+        //权限校验
+        $token = $this->request->header('token');
+        $ip    = $this->request->ip();
+        if (empty($token)) {
+            ajax_success();
+        }
+
+        $auth = SmsAuthModel::where('token', $token)->find();
+        if (empty($auth)) {
+            Log::error("无权限token访问,token:{$token},ip:{$ip}");
+            ajax_success();
+        }
+        if ($auth['ip'] != $ip) {
+            Log::error("无权限ip访问,token:{$token},ip:{$ip}");
+            ajax_success();
+        }
+
+        //发送短信
+        $type    = input('post.type', '');
+        $mobile  = input('post.mobile', '');
+        $content = input('post.content', '');
+        if (empty($mobile) || empty($content)) {
+            ajax_error('手机号或内容不能为空!');
+        }
+        $res     = SmsService::apiSend($mobile, $content, $type);
+
+        //记录日志
+        $log = [
+            'ip'      => $ip,
+            'token'   => $token,
+            'mobile'  => $mobile,
+            'content' => $content,
+            'status'  => $res['code'] ? 2 : 1,
+            'error'   => $res['code'] ? $res['msg'] : '',
+        ];
+        SmsLogModel::create($log);
+
+        //返回结果
+        if ($res['code']) {
+            ajax_error($res['msg']);
+        }
+        ajax_success();
+    }
+}

+ 17 - 0
app/api/event.php

@@ -0,0 +1,17 @@
+<?php
+// 事件定义文件
+return [
+    'bind'      => [
+    ],
+
+    'listen'    => [
+        'AppInit'  => [],
+        'HttpRun'  => [],
+        'HttpEnd'  => [],
+        'LogLevel' => [],
+        'LogWrite' => [],
+    ],
+
+    'subscribe' => [
+    ],
+];

+ 10 - 0
app/api/middleware.php

@@ -0,0 +1,10 @@
+<?php
+// 全局中间件定义文件
+return [
+    // 全局请求缓存
+//     \think\middleware\CheckRequestCache::class,
+    // 多语言加载
+    // \think\middleware\LoadLangPack::class,
+    // Session初始化
+//     \think\middleware\SessionInit::class
+];

+ 9 - 0
app/api/provider.php

@@ -0,0 +1,9 @@
+<?php
+use app\ExceptionHandle;
+use app\Request;
+
+// 容器Provider定义文件
+return [
+    'think\Request'          => Request::class,
+    'think\exception\Handle' => ExceptionHandle::class,
+];

+ 4 - 0
app/common/model/SettingModel.php

@@ -9,9 +9,13 @@ class SettingModel extends BaseModel
 
     // 短信配置
     const SMS = [
+        'sms_type',
         'sms_chuanglan_appkey',
         'sms_chuanglan_secret',
     ];
+    const SMS_TYPE = [
+        'chuanglan\\Chuanglan' => '创蓝'
+    ];
     const SYSTEM = [
         'site_name',
     ];

+ 10 - 0
app/common/model/SmsAuthModel.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace app\common\model;
+
+class SmsAuthModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'sms_auth';
+
+}

+ 17 - 0
app/common/model/SmsLogModel.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace app\common\model;
+
+class SmsLogModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'sms_log';
+
+    // 常量
+    const STATUS = [1 => '成功', 2 => '失败'];
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+}

+ 10 - 0
app/common/model/SmsTemplateModel.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace app\common\model;
+
+class SmsTemplateModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'sms_template';
+
+}

+ 47 - 0
app/common/service/SmsService.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace app\common\service;
+
+use app\common\model\SettingModel;
+use app\common\model\SmsTemplateModel;
+use think\facade\Log;
+
+class SmsService
+{
+    public function send($mobile, $code, $content_param = [])
+    {
+        $message = SmsTemplateModel::where('code', $code)->find();
+        if (empty($message)) {
+            Log::error('短信模板不存在:' . $code);
+            return ['code' => 1, 'msg' => '模板不存在'];
+        }
+
+        $msg = $message['content'];
+        if (!empty($content_param)) {
+            foreach ($content_param as $k => $v) {
+                $msg = str_replace('{$' . ($k + 1) . '}', $v, $msg);
+            }
+        }
+
+        $sms_obj = Config('mobile.sms_type');
+        $sms     = new $sms_obj();
+        return $sms->send($mobile, ['message' => $msg]);
+    }
+
+    public static function apiSend($mobile, $content, $sms_obj = '')
+    {
+        if (empty($sms_obj)) {
+            $sms_obj = SettingModel::getConfigValue('sms_type');
+            if (empty($sms_obj)) {
+                return ['code' => 1, 'msg' => '未配置默认模板'];
+            }
+        }
+
+        if (!in_array($sms_obj, array_keys(SettingModel::SMS_TYPE))) {
+            return ['code' => 1, 'msg' => '平台类型不存在'];
+        }
+
+        $sms = new $sms_obj();
+        return $sms->send($mobile, ['message' => $content]);
+    }
+}

+ 19 - 0
app/common/validate/SmsAuthValidate.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace app\common\validate;
+
+use think\Validate;
+
+class SmsAuthValidate extends Validate
+{
+    protected $rule = [
+        'token' => 'require',
+        'ip'    => 'require',
+    ];
+
+    protected $message = [
+        'token' => 'token不能为空',
+        'ip'    => 'ip不能为空',
+    ];
+
+}

+ 19 - 0
app/common/validate/SmsTemplateValidate.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace app\common\validate;
+
+use think\Validate;
+
+class SmsTemplateValidate extends Validate
+{
+    protected $rule = [
+        'code'    => 'require',
+        'content' => 'require',
+    ];
+
+    protected $message = [
+        'code'    => '编号不能为空',
+        'content' => '内容不能为空',
+    ];
+
+}

+ 7 - 18
app/home/controller/Index.php

@@ -2,7 +2,6 @@
 
 namespace app\home\controller;
 
-use app\common\model\OfficerReviewTitleModel;
 use app\common\model\PreviousModel;
 use app\common\model\ReservedModel;
 use app\home\HomeBaseController;
@@ -33,24 +32,14 @@ class Index extends HomeBaseController
 
     public function t1()
     {
-        return '';
-        $str  = '';
-        $arr  = json_decode($str, true);
-        $no   = 292;
-        $rid  = 3;
-        $rsid = 9;
-        foreach ($arr as $v) {
-            OfficerReviewTitleModel::create([
-                'rid'    => $rid,
-                'rsid'   => $rsid,
-                'no'     => $no,
-                'title'  => $v['title'],
-                'option' => json_encode($v['options'], JSON_UNESCAPED_UNICODE),
-            ]);
-            $no++;
-        }
+        $str= file_get_contents('1.json');
+        $arr = json_decode($str,true);
 
-        return '完成';
+        $xlsCell = [
+            ['ID', '编号'],
+            ['Content', '素材内容'],
+        ];
+        export_exl("厂房-整句", $xlsCell, $arr['data'],['ID']);
     }
 
     public function t2()

+ 74 - 0
extend/chuanglan/Chuanglan.php

@@ -0,0 +1,74 @@
+<?php
+/**
+ * 手机短信类
+ */
+
+namespace chuanglan;
+
+use app\common\model\SettingModel;
+use think\facade\Log;
+
+class Chuanglan
+{
+
+    /**
+     * 创蓝短信
+     * @param $mobile
+     * @param $smslog_param
+     * @return array
+     */
+    public function send($mobile, $smslog_param)
+    {
+        $config = SettingModel::getConfigValue(['sms_chuanglan_appkey', 'sms_chuanglan_secret']);
+        if (empty($config['sms_chuanglan_appkey']) || empty($config['sms_chuanglan_secret'])) {
+            return ['code' => 1, 'msg' => '请绑定模板参数'];
+        }
+
+        if (empty($smslog_param['params'])) {
+            $url = 'http://smssh1.253.com/msg/send/json';
+            //创蓝接口参数
+            $postArr = [
+                'account'  => $config['sms_chuanglan_appkey'],
+                'password' => $config['sms_chuanglan_secret'],
+                'msg'      => $smslog_param['message'],
+                'phone'    => $mobile,
+                'report'   => 'true',
+            ];
+        } else {
+            $params_str = $mobile . ',' . implode(',', $smslog_param['params']);
+            $url        = 'http://smssh1.253.com/msg/variable/json';
+            //创蓝接口参数
+            $postArr = [
+                'account'  => $config['sms_chuanglan_appkey'],
+                'password' => $config['sms_chuanglan_secret'],
+                'msg'      => $smslog_param['message'],
+                'params'   => $params_str,
+                'report'   => 'true',
+            ];
+        }
+        $postFields = json_encode($postArr);
+        $ch         = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_HTTPHEADER, [
+                'Content-Type: application/json; charset=utf-8',   //json版本需要填写  Content-Type: application/json;
+            ]
+        );
+        curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); //若果报错 name lookup timed out 报错时添加这一行代码
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
+        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+        $ret = curl_exec($ch);
+        curl_close($ch);
+        $rsp = json_decode($ret, true);
+
+        if ($rsp['code'] != 0) {
+            Log::error('短信发送失败:' . json_encode($rsp) . "。原始参数:" . json_encode($postArr));
+            return ['code' => 1, 'msg' => $rsp['errorMsg']];
+        } else {
+            return ['code' => 0];
+        }
+    }
+}

+ 36 - 0
短信接口文档.md

@@ -0,0 +1,36 @@
+## 发送短信
+
+访问方式和地址
+
+`POST https://lw_test.jinjianghc.com/api/sms/send`
+
+请求头
+
+| 字段名     | 类型   | 是否必填 | 描述         |
+|---------| ------ |------|------------|
+| token   | string | 是    | 平台分配的token |
+
+请求参数(可不传,不传按默认值处理):
+
+| 字段名     | 类型   | 是否必填 | 描述        |
+|---------| ------ |------|-----------|
+| mobile  | string | 是    | 手机号       |
+| content | string | 是    | 短信内容      |
+| type    | string | 否    | 短信平台,目前只有"chuanglan\\Chuanglan" |
+
+数组参数说明:
+
+| 字段名  | 类型      | 描述      |
+|------|---------|---------|
+| code | int     | 0成功,1失败 |
+| msg  | varchar | 提示消息    |
+| data | array   | 返回数据    |
+
+响应示例:
+
+```json
+{
+	"code": 0,
+	"msg": "成功",
+	"data": []
+}