├── .gitignore ├── README.md ├── api ├── admin │ └── controller │ │ └── PublicController.php ├── command.php ├── common │ ├── exception │ │ └── Http.php │ └── model │ │ └── CommonModel.php ├── config.php ├── database.php ├── debug.php ├── home │ ├── controller │ │ ├── IndexController.php │ │ ├── RestController.php │ │ ├── SlidesController.php │ │ └── ThemeController.php │ ├── model │ │ ├── SlideItemModel.php │ │ ├── SlideModel.php │ │ └── ThemeFileModel.php │ └── route.php ├── portal │ ├── controller │ │ ├── ArticlesController.php │ │ ├── CategoriesController.php │ │ ├── ListsController.php │ │ ├── PagesController.php │ │ ├── TagsController.php │ │ ├── UserArticlesController.php │ │ └── UserController.php │ ├── logic │ │ └── PortalPostModel.php │ ├── model │ │ ├── PortalCategoryModel.php │ │ ├── PortalCategoryPostModel.php │ │ ├── PortalPostModel.php │ │ ├── PortalTagModel.php │ │ ├── PortalTagPostModel.php │ │ ├── RecycleBinModel.php │ │ └── UserModel.php │ ├── route.php │ ├── service │ │ └── PortalPostModel.php │ └── validate │ │ └── ArticlesValidate.php ├── release.php ├── route.php ├── tags.php ├── user │ ├── controller │ │ ├── CommentsController.php │ │ ├── FavoritesController.php │ │ ├── ProfileController.php │ │ ├── PublicController.php │ │ ├── UploadController.php │ │ └── VerificationCodeController.php │ ├── model │ │ ├── CommentModel.php │ │ ├── RecycleBinModel.php │ │ ├── UserFavoriteModel.php │ │ ├── UserLikeModel.php │ │ └── UserModel.php │ └── route.php └── wxapp │ └── controller │ ├── PublicController.php │ └── UserController.php └── public └── api ├── .htaccess └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .DS_Store 3 | .project 4 | .settings 5 | .idea 6 | composer.lock 7 | /app 8 | /simplewind 9 | /data 10 | /public/plugins/ 11 | /public/static/ 12 | /public/themes/ 13 | /public/upload/ 14 | /public/.htaccess 15 | /public/index.php 16 | /public/robots.txt 17 | /public/router.php 18 | /think -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ThinkCMF 5.0 API 1.1.0 2 | =============== 3 | ### 环境推荐 4 | > php5.5+ 5 | 6 | > mysql 5.6+ 7 | 8 | > 打开rewrite 9 | 10 | ### 安装步骤 11 | 12 | 1. 请先安装ThinkCMF5 https://github.com/thinkcmf/thinkcmf 13 | 2. 再把本项目代码覆盖到 thinkcmf5根目录(最终目录参考http://www.kancloud.cn/thinkcmf/doc/266477) 14 | ``` 15 | thinkcmf 根目录 16 | ├─api api目录 17 | ├─app 应用目录 18 | │ ├─portal 门户应用目录 19 | │ │ ├─config.php 应用配置文件 20 | │ │ ├─common.php 模块函数文件 21 | │ │ ├─controller 控制器目录 22 | │ │ ├─model 模型目录 23 | │ │ └─ ... 更多类库目录 24 | │ ├─ ... 更多应用 25 | │ ├─command.php 命令行工具配置文件 26 | │ ├─common.php 应用公共(函数)文件 27 | │ ├─config.php 应用(公共)配置文件 28 | │ ├─database.php 数据库配置文件 29 | │ ├─tags.php 应用行为扩展定义文件 30 | │ └─route.php 路由配置文件 31 | ├─data 数据目录 32 | │ ├─conf 动态配置目录 33 | │ ├─runtime 应用的运行时目录(可写) 34 | │ └─ ... 更多 35 | ├─public WEB 部署目录(对外访问目录) 36 | │ ├─api api入口目录 37 | │ ├─plugins 插件目录 38 | │ ├─static 静态资源存放目录(css,js,image) 39 | │ ├─themes 前后台主题目录 40 | │ │ ├─admin_simpleboot3 后台默认主题 41 | │ │ └─simpleboot3 前台默认主题 42 | │ ├─upload 文件上传目录 43 | │ ├─index.php 入口文件 44 | │ ├─robots.txt 爬虫协议文件 45 | │ ├─router.php 快速测试文件 46 | │ └─.htaccess apache重写文件 47 | ├─simplewind 48 | │ ├─cmf CMF核心库目录 49 | │ ├─extend 扩展类库目录 50 | │ ├─thinkphp thinkphp目录 51 | │ └─vendor 第三方类库目录(Composer) 52 | ├─composer.json composer 定义文件 53 | ├─LICENSE.txt 授权说明文件 54 | ├─README.md README 文件 55 | ├─think 命令行入口文件 56 | ``` 57 | 58 | ### API手册 59 | http://www.kancloud.cn/thinkcmf/cmf5api 60 | 61 | QQ群:100828313 (付费) 62 | 63 | ### ThinkCMF小程序 ThinkCMFlite发布 64 | https://www.kancloud.cn/thinkcmf/cmf5api/451391 65 | 66 | ### 更新日志 67 | #### 1.1.0 68 | [核心] 69 | * 增加是否收藏判断 70 | * 增加登录API,返回用户信息 71 | * 优化登录时设备类型判断 72 | * 优化手机号验证,支持国际手机号 73 | * 优化评论列表,无须用户登录 74 | * 优化rest api基类设备类型获取 75 | * 优化rest api用户token生成逻辑 76 | * 修复幻灯片列表,后台排序无效 #8 77 | * 修复UserModel.php被写死了cmf_前缀 #9 78 | * 修复文章附件url转化问题 79 | * 修复评论成功后,评论对象评论数字段没有加1 80 | * 修复添加收藏报错 81 | * 修复收藏判断错误 82 | * 修复文章列表发布时间格式问题,统一为时间戳 83 | * 修复评论用户头像链接错误 84 | * 修复不加载动态路由 85 | 86 | [门户应用] 87 | * 增加指定分类的子分类列表 88 | * 增加文章点击数更新 89 | * 增加相关文章接口 90 | * 增加文章收藏接口 91 | * 增加取消文章收藏接口 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /api/admin/controller/PublicController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\admin\controller; 10 | 11 | use cmf\controller\RestBaseController; 12 | use think\Db; 13 | use think\Validate; 14 | 15 | class PublicController extends RestBaseController 16 | { 17 | 18 | // 用户登录 TODO 增加最后登录信息记录,如 ip 19 | public function login() 20 | { 21 | $validate = new Validate([ 22 | 'username' => 'require', 23 | 'password' => 'require' 24 | ]); 25 | $validate->message([ 26 | 'username.require' => '请输入手机号,邮箱或用户名!', 27 | 'password.require' => '请输入您的密码!' 28 | ]); 29 | 30 | $data = $this->request->param(); 31 | if (!$validate->check($data)) { 32 | $this->error($validate->getError()); 33 | } 34 | 35 | $userQuery = Db::name("user"); 36 | if (Validate::is($data['username'], 'email')) { 37 | $userQuery = $userQuery->where('user_email', $data['username']); 38 | } else if (cmf_check_mobile($data['username'])) { 39 | $userQuery = $userQuery->where('mobile', $data['username']); 40 | } else { 41 | $userQuery = $userQuery->where('user_login', $data['username']); 42 | } 43 | 44 | $findUser = $userQuery->find(); 45 | 46 | if (empty($findUser)) { 47 | $this->error("用户不存在!"); 48 | } else { 49 | 50 | switch ($findUser['user_status']) { 51 | case 0: 52 | $this->error('您已被拉黑!'); 53 | case 2: 54 | $this->error('账户还没有验证成功!'); 55 | } 56 | 57 | if (!cmf_compare_password($data['password'], $findUser['user_pass'])) { 58 | $this->error("密码不正确!"); 59 | } 60 | } 61 | 62 | $allowedDeviceTypes = ['mobile', 'android', 'iphone', 'ipad', 'web', 'pc', 'mac']; 63 | 64 | if (empty($data['device_type']) || !in_array($data['device_type'], $allowedDeviceTypes)) { 65 | $this->error("请求错误,未知设备!"); 66 | } 67 | 68 | $userTokenQuery = Db::name("user_token") 69 | ->where('user_id', $findUser['id']) 70 | ->where('device_type', $data['device_type']); 71 | $findUserToken = $userTokenQuery->find(); 72 | $currentTime = time(); 73 | $expireTime = $currentTime + 24 * 3600 * 180; 74 | $token = md5(uniqid()) . md5(uniqid()); 75 | if (empty($findUserToken)) { 76 | $result = $userTokenQuery->insert([ 77 | 'token' => $token, 78 | 'user_id' => $findUser['id'], 79 | 'expire_time' => $expireTime, 80 | 'create_time' => $currentTime, 81 | 'device_type' => $data['device_type'] 82 | ]); 83 | } else { 84 | $result = $userTokenQuery 85 | ->where('user_id', $findUser['id']) 86 | ->where('device_type', $data['device_type']) 87 | ->update([ 88 | 'token' => $token, 89 | 'expire_time' => $expireTime, 90 | 'create_time' => $currentTime 91 | ]); 92 | } 93 | 94 | 95 | if (empty($result)) { 96 | $this->error("登录失败!"); 97 | } 98 | 99 | $this->success("登录成功!", ['token' => $token]); 100 | } 101 | 102 | // 管理员退出 103 | public function logout() 104 | { 105 | $userId = $this->getUserId(); 106 | Db::name('user_token')->where([ 107 | 'token' => $this->token, 108 | 'user_id' => $userId, 109 | 'device_type' => $this->deviceType 110 | ])->update(['token' => '']); 111 | 112 | $this->success("退出成功!"); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /api/command.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | $apps = cmf_scan_dir(APP_PATH . '*', GLOB_ONLYDIR); 11 | 12 | $returnCommands = []; 13 | 14 | foreach ($apps as $app) { 15 | $commandFile = APP_PATH . $app . '/command.php'; 16 | 17 | if (file_exists($commandFile)) { 18 | $commands = include $commandFile; 19 | 20 | $returnCommands = array_merge($returnCommands, $commands); 21 | } 22 | 23 | } 24 | 25 | return $returnCommands; -------------------------------------------------------------------------------- /api/common/exception/Http.php: -------------------------------------------------------------------------------- 1 | getMessage(); 22 | } else { 23 | $msg= '系统错误!'; 24 | } 25 | $code=0; 26 | $httpCode=500; 27 | $result = [ 28 | 'code' => $code, 29 | 'msg' => $msg, 30 | 'data' => [], 31 | ]; 32 | return json($result, $httpCode); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /api/common/model/CommonModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\common\model; 10 | 11 | use think\Model; 12 | use think\Loader; 13 | 14 | class CommonModel extends Model 15 | { 16 | // 关联模型过滤 17 | protected $relationFilter = []; 18 | 19 | /** 20 | * 内容查询 21 | * @access public 22 | * @param array $params 过滤参数 23 | * @return array|false|\PDOStatement|string|\think\Collection|Model 查询结果 24 | * @throws \think\db\exception\DataNotFoundException 25 | * @throws \think\db\exception\ModelNotFoundException 26 | * @throws \think\exception\DbException 27 | */ 28 | public function getDatas($params = []) 29 | { 30 | if (empty($params)) { 31 | return $this->select(); 32 | } 33 | 34 | $this->setCondition($params); 35 | if (!empty($params['id'])) { 36 | $datas = $this->find(); 37 | } else { 38 | $datas = $this->select(); 39 | } 40 | 41 | if (!empty($params['relation'])) { 42 | $allowedRelations = $this->allowedRelations($params['relation']); 43 | if (!empty($allowedRelations)) { 44 | if (!empty($params['id'])) { 45 | if (!empty($datas)) { 46 | $datas->append($allowedRelations); 47 | } 48 | } else { 49 | if (count($datas) > 0) { 50 | $datas->load($allowedRelations); 51 | $datas->append($allowedRelations); 52 | } 53 | } 54 | } 55 | } 56 | 57 | return $datas; 58 | } 59 | 60 | /** 61 | * @access public 62 | * @param array $params 过滤参数 63 | * @return $this 64 | */ 65 | public function setCondition($params) 66 | { 67 | if (empty($params)) { 68 | return $this; 69 | } 70 | if (!empty($params['relation'])) { 71 | $allowedRelations = $this->allowedRelations($params['relation']); 72 | if (!empty($allowedRelations)) { 73 | if (!empty($params['id']) && count($allowedRelations) == 1) { 74 | $this->paramsFilter($params); 75 | } else { 76 | $this->paramsFilter($params);//->with($allowedRelations); 77 | } 78 | } 79 | } else { 80 | $this->paramsFilter($params); 81 | } 82 | return $this; 83 | } 84 | 85 | /** 86 | * @access public 87 | * @param array $params 过滤参数 88 | * @param model $model 关联模型 89 | * @return model|array $this|链式查询条件数组 90 | */ 91 | public function paramsFilter($params, $model = null) 92 | { 93 | if (!empty($model)) { 94 | $_this = $model; 95 | } else { 96 | $_this = $this; 97 | } 98 | 99 | if (isset($_this->visible)) { 100 | $whiteParams = $_this->visible; 101 | } 102 | 103 | // 设置field字段过滤 104 | if (!empty($params['field'])) { 105 | $filterParams = $this->strToArr($params['field']); 106 | if (!empty($whiteParams)) { 107 | $mixedField = array_intersect($filterParams, $whiteParams); 108 | } else { 109 | $mixedField = $filterParams; 110 | } 111 | 112 | if (!empty($mixedField)) { 113 | $_this->field($mixedField); 114 | } 115 | } 116 | 117 | // 设置id,ids 118 | if (!empty($params['ids'])) { 119 | $ids = $this->strToArr($params['ids']); 120 | foreach ($ids as $key => $value) { 121 | $ids[$key] = intval($value); 122 | } 123 | } 124 | 125 | if (!empty($params['where']) && !is_string($params['where'])) { 126 | if (empty($model)) { 127 | $_this->where($params['where']); 128 | } 129 | } 130 | 131 | if (!empty($params['id'])) { 132 | $id = intval($params['id']); 133 | if (!empty($id)) { 134 | return $_this->where('id', $id); 135 | } 136 | } elseif (!empty($ids)) { 137 | $_this->where('id', 'in', $ids); 138 | } 139 | 140 | // 设置分页 141 | if (!empty($params['page'])) { 142 | $pageArr = $this->strToArr($params['page']); 143 | $page = []; 144 | foreach ($pageArr as $value) { 145 | $page[] = intval($value); 146 | } 147 | if (count($page) == 1) { 148 | $_this->page($page[0]); 149 | } elseif (count($page) == 2) { 150 | $_this->page($page[0], $page[1]); 151 | } 152 | } elseif (!empty($params['limit'])) { // 设置limit查询 153 | $limitArr = $this->strToArr($params['limit']); 154 | $limit = []; 155 | foreach ($limitArr as $value) { 156 | $limit[] = intval($value); 157 | } 158 | if (count($limit) == 1) { 159 | $_this->limit($limit[0]); 160 | } elseif (count($limit) == 2) { 161 | $_this->limit($limit[0], $limit[1]); 162 | } 163 | } else { 164 | $_this->limit(10); 165 | } 166 | 167 | //设置排序 168 | if (!empty($params['order'])) { 169 | $order = $this->strToArr($params['order']); 170 | foreach ($order as $key => $value) { 171 | $upDwn = substr($value, 0, 1); 172 | $orderType = $upDwn == '-' ? 'desc' : 'asc'; 173 | $orderField = substr($value, 1); 174 | if (!empty($whiteParams)) { 175 | if (in_array($orderField, $whiteParams)) { 176 | $orderWhere[$orderField] = $orderType; 177 | } 178 | } else { 179 | $orderWhere[$orderField] = $orderType; 180 | } 181 | } 182 | 183 | if (!empty($orderWhere)) { 184 | $_this->order($orderWhere); 185 | } 186 | } 187 | 188 | return $_this; 189 | } 190 | 191 | /** 192 | * 设置链式查询 193 | * @access public 194 | * @param array $params 链式查询条件 195 | * @param model $model 模型 196 | * @return $this 197 | */ 198 | public function setParamsQuery($params, $model = null) 199 | { 200 | if (!empty($model)) { 201 | $_this = $model; 202 | } else { 203 | $_this = $this; 204 | } 205 | $_this->alias('articles'); 206 | if (!empty($params['field'])) { 207 | $_this->field($params['field']); 208 | } 209 | if (!empty($params['ids'])) { 210 | $_this->where('articles.id', $params['ids'][1], $params['ids'][2]); 211 | } 212 | if (!empty($params['limit'])) { 213 | $_this->limit($params['limit']); 214 | } 215 | if (!empty($params['page'])) { 216 | $_this->page($params['page']); 217 | } 218 | if (!empty($params['order'])) { 219 | $_this->order($params['order']); 220 | } 221 | return $_this; 222 | } 223 | 224 | public function allowedRelations($relations) 225 | { 226 | if (is_string($relations)) { 227 | $relations = explode(',', $relations); 228 | } 229 | 230 | if (!is_array($relations)) { 231 | return false; 232 | } 233 | 234 | return array_intersect($this->relationFilter, $relations); 235 | } 236 | 237 | /** 238 | * 是否允许关联 239 | * @access public 240 | * @param string $relationName 模型关联方法名 241 | * @return boolean 242 | */ 243 | public function isWhite($relationName) 244 | { 245 | if (!is_string($relationName)) { 246 | return false; 247 | } 248 | $name = Loader::parseName($relationName, 1, false); 249 | if (in_array($name, $this->relationFilter)) { 250 | return true; 251 | } else { 252 | return false; 253 | } 254 | } 255 | 256 | /** 257 | * 懒人函数 258 | * @access public 259 | * @param string $value 字符串 260 | * @return array 261 | */ 262 | public function strToArr($string) 263 | { 264 | return is_string($string) ? explode(',', $string) : $string; 265 | } 266 | } -------------------------------------------------------------------------------- /api/config.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | return [ 11 | // +---------------------------------------------------------------------- 12 | // | 应用设置 13 | // +---------------------------------------------------------------------- 14 | 15 | // 应用命名空间 16 | 'app_namespace' => 'api', 17 | // 应用模式状态 18 | 'app_status' => APP_DEBUG ? 'debug' : 'release', 19 | // 是否支持多模块 20 | 'app_multi_module' => true, 21 | // 入口自动绑定模块 22 | 'auto_bind_module' => false, 23 | // 注册的根命名空间 24 | 'root_namespace' => ['cmf' => CMF_PATH, 'plugins' => PLUGINS_PATH, 'app' => CMF_ROOT . 'app/'], 25 | // 扩展函数文件 26 | 'extra_file_list' => [THINK_PATH . 'helper' . EXT, CMF_PATH . 'common' . EXT], 27 | // 默认输出类型 28 | 'default_return_type' => 'json', 29 | // 默认AJAX 数据返回格式,可选json xml ... 30 | 'default_ajax_return' => 'json', 31 | // 默认JSONP格式返回的处理方法 32 | 'default_jsonp_handler' => 'jsonpReturn', 33 | // 默认JSONP处理方法 34 | 'var_jsonp_handler' => 'callback', 35 | // 默认时区 36 | 'default_timezone' => 'PRC', 37 | // 是否开启多语言 38 | 'lang_switch_on' => false, 39 | // 默认全局过滤方法 用逗号分隔多个 40 | 'default_filter' => 'htmlspecialchars', 41 | // 默认语言 42 | 'default_lang' => 'zh-cn', 43 | // 应用类库后缀 44 | 'class_suffix' => true, 45 | // 控制器类后缀 46 | 'controller_suffix' => true, 47 | 48 | // +---------------------------------------------------------------------- 49 | // | 模块设置 50 | // +---------------------------------------------------------------------- 51 | 52 | // 默认模块名 53 | 'default_module' => 'home', 54 | // 禁止访问模块 55 | 'deny_module_list' => ['common'], 56 | // 默认控制器名 57 | 'default_controller' => 'Index', 58 | // 默认操作名 59 | 'default_action' => 'index', 60 | // 默认验证器 61 | 'default_validate' => '', 62 | // 默认的空控制器名 63 | 'empty_controller' => 'Error', 64 | // 自动搜索控制器 65 | 'controller_auto_search' => false, 66 | 67 | // +---------------------------------------------------------------------- 68 | // | URL设置 69 | // +---------------------------------------------------------------------- 70 | 71 | 'pathinfo_depr' => '/', 72 | // URL伪静态后缀 73 | 'url_html_suffix' => 'html', 74 | // URL普通方式参数 用于自动生成 75 | 'url_common_param' => false, 76 | // URL参数方式 0 按名称成对解析 1 按顺序解析 77 | 'url_param_type' => 0, 78 | // 是否开启路由 79 | 'url_route_on' => true, 80 | // 路由配置文件(支持配置多个) 81 | 'route_config_file' => ['route'], 82 | // 是否强制使用路由 83 | 'url_route_must' => false, 84 | // 域名部署 85 | 'url_domain_deploy' => false, 86 | // 域名根,如thinkphp.cn 87 | 'url_domain_root' => '', 88 | // 是否自动转换URL中的控制器和操作名 89 | 'url_convert' => true, 90 | // 默认的访问控制器层 91 | 'url_controller_layer' => 'controller', 92 | // 表单请求类型伪装变量 93 | 'var_method' => '_method', 94 | 95 | // +---------------------------------------------------------------------- 96 | // | 模板设置 97 | // +---------------------------------------------------------------------- 98 | 99 | 'template' => [ 100 | // 模板引擎类型 支持 php think 支持扩展 101 | 'type' => 'Think', 102 | // 视图根目录 103 | 'view_base' => '', 104 | // 模板路径 105 | 'view_path' => '', 106 | // 模板后缀 107 | 'view_suffix' => 'html', 108 | // 模板文件名分隔符 109 | 'view_depr' => DS, 110 | // 模板引擎普通标签开始标记 111 | 'tpl_begin' => '{', 112 | // 模板引擎普通标签结束标记 113 | 'tpl_end' => '}', 114 | // 标签库标签开始标记 115 | 'taglib_begin' => '<', 116 | // 标签库标签结束标记 117 | 'taglib_end' => '>', 118 | ], 119 | 120 | // 视图输出字符串内容替换 121 | 'view_replace_str' => [], 122 | // 默认跳转页面对应的模板文件 123 | 'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 124 | 'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl', 125 | 126 | // +---------------------------------------------------------------------- 127 | // | 异常及错误设置 128 | // +---------------------------------------------------------------------- 129 | 130 | // 异常页面的模板文件 131 | 'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl', 132 | 133 | // 错误显示信息,非调试模式有效 134 | 'error_message' => '页面错误!请稍后再试~', 135 | // 显示错误信息 136 | 'show_error_msg' => false, 137 | // 异常处理handle类 留空使用 \think\exception\Handle 138 | 'exception_handle' => '\\api\\common\\exception\\Http', 139 | 140 | // +---------------------------------------------------------------------- 141 | // | 日志设置 142 | // +---------------------------------------------------------------------- 143 | 144 | 'log' => [ 145 | // 日志记录方式,内置 file socket 支持扩展 146 | 'type' => 'File', 147 | // 日志保存目录 148 | 'path' => LOG_PATH, 149 | // 日志记录级别 150 | 'level' => [], 151 | ], 152 | 153 | // +---------------------------------------------------------------------- 154 | // | Trace设置 开启 app_trace 后 有效 155 | // +---------------------------------------------------------------------- 156 | 'trace' => [ 157 | // 内置Html Console 支持扩展 158 | 'type' => 'Html', 159 | ], 160 | 161 | // +---------------------------------------------------------------------- 162 | // | 缓存设置 163 | // +---------------------------------------------------------------------- 164 | 165 | 'cache' => [ 166 | // 驱动方式 167 | 'type' => 'File', 168 | // 缓存保存目录 169 | 'path' => CACHE_PATH, 170 | // 缓存前缀 171 | 'prefix' => '', 172 | // 缓存有效期 0表示永久缓存 173 | 'expire' => 0, 174 | ], 175 | 176 | // +---------------------------------------------------------------------- 177 | // | 会话设置 178 | // +---------------------------------------------------------------------- 179 | 180 | 'session' => [ 181 | 'id' => '', 182 | // SESSION_ID的提交变量,解决flash上传跨域 183 | 'var_session_id' => '', 184 | // SESSION 前缀 185 | 'prefix' => 'think', 186 | // 驱动方式 支持redis memcache memcached 187 | 'type' => '', 188 | // 是否自动开启 SESSION 189 | 'auto_start' => true, 190 | ], 191 | 192 | // +---------------------------------------------------------------------- 193 | // | Cookie设置 194 | // +---------------------------------------------------------------------- 195 | 'cookie' => [ 196 | // cookie 名称前缀 197 | 'prefix' => '', 198 | // cookie 保存时间 199 | 'expire' => 0, 200 | // cookie 保存路径 201 | 'path' => '/', 202 | // cookie 有效域名 203 | 'domain' => '', 204 | // cookie 启用安全传输 205 | 'secure' => false, 206 | // httponly设置 207 | 'httponly' => '', 208 | // 是否使用 setcookie 209 | 'setcookie' => true, 210 | ], 211 | 212 | // +---------------------------------------------------------------------- 213 | // | 数据库设置 214 | // +---------------------------------------------------------------------- 215 | 216 | 'database' => [ 217 | // 数据库调试模式 218 | 'debug' => true, 219 | // 数据集返回类型 220 | 'resultset_type' => 'collection', 221 | // 自动写入时间戳字段 222 | 'auto_timestamp' => false, 223 | // 时间字段取出后的默认时间格式 224 | 'datetime_format' => false, 225 | // 是否需要进行SQL性能分析 226 | 'sql_explain' => false, 227 | ], 228 | 229 | //分页配置 230 | 'paginate' => [ 231 | 'type' => 'bootstrap', 232 | 'var_page' => 'page', 233 | 'list_rows' => 15, 234 | ], 235 | //图片验证码 236 | 'captcha' => [ 237 | // 验证码字符集合 238 | 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY', 239 | // 验证码字体大小(px) 240 | 'fontSize' => 25, 241 | // 是否画混淆曲线 242 | 'useCurve' => true, 243 | // 验证码图片高度 244 | 'imageH' => 30, 245 | // 验证码图片宽度 246 | 'imageW' => 100, 247 | // 验证码位数 248 | 'length' => 5, 249 | // 验证成功后是否重置 250 | 'reset' => true 251 | ], 252 | 253 | // +---------------------------------------------------------------------- 254 | // | CMF 设置 255 | // +---------------------------------------------------------------------- 256 | 'cmf_theme_path' => 'themes/home/', 257 | 'cmf_default_theme' => 'simpleboot3', 258 | 'cmf_admin_theme_path' => 'themes/admin/', 259 | 'cmf_admin_default_theme' => 'simpleboot3', 260 | ]; 261 | -------------------------------------------------------------------------------- /api/database.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | if(file_exists(ROOT_PATH."data/conf/database.php")){ 11 | $database=include ROOT_PATH."data/conf/database.php"; 12 | }else{ 13 | $database=[]; 14 | } 15 | 16 | return $database; 17 | -------------------------------------------------------------------------------- /api/debug.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // 应用调试模式 14 | 'app_debug' => true, 15 | // 应用Trace 16 | 'app_trace' => true, 17 | 18 | ]; -------------------------------------------------------------------------------- /api/home/controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\home\controller; 10 | 11 | use think\Db; 12 | use think\Validate; 13 | use cmf\controller\RestBaseController; 14 | 15 | class IndexController extends RestBaseController 16 | { 17 | // api 首页 18 | public function index() 19 | { 20 | $this->success("恭喜您,API访问成功!", [ 21 | 'version' => '1.1.0', 22 | 'doc' => 'http://www.thinkcmf.com/cmf5api.html' 23 | ]); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /api/home/controller/RestController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // API 模板文件,可以复制 10 | namespace api\home\controller; 11 | 12 | use cmf\controller\RestBaseController; 13 | 14 | class RestController extends RestBaseController 15 | { 16 | /** 17 | * 显示资源列表 18 | */ 19 | public function index() 20 | { 21 | } 22 | 23 | /** 24 | * 保存新建的资源 25 | */ 26 | public function save() 27 | { 28 | } 29 | 30 | /** 31 | * 显示指定的资源 32 | * 33 | * @param int $id 34 | */ 35 | public function read($id) 36 | { 37 | } 38 | 39 | /** 40 | * 保存更新的资源 41 | * 42 | * @param int $id 43 | */ 44 | public function update($id) 45 | { 46 | } 47 | 48 | /** 49 | * 删除指定资源 50 | * 51 | * @param int $id 52 | */ 53 | public function delete($id) 54 | { 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /api/home/controller/SlidesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-5-25 12 | // +---------------------------------------------------------------------- 13 | namespace api\home\controller; 14 | 15 | use api\home\model\SlideModel; 16 | use cmf\controller\RestBaseController; 17 | 18 | class SlidesController extends RestBaseController 19 | { 20 | /** 21 | * [获取幻灯片] 22 | * @Author: wuwu<15093565100@163.com> 23 | * @DateTime: 2017-05-25T20:48:53+0800 24 | * @since: 1.0 25 | */ 26 | public function read() 27 | { 28 | //slide为空或不存在抛出异常 29 | $id = $this->request->param('id', 0, 'intval'); 30 | if (empty($id)) { 31 | $this->error('缺少ID参数'); 32 | } 33 | 34 | $map['id'] = $id; 35 | $obj = new SlideModel(); 36 | $data = $obj->SlideList($map); 37 | 38 | 39 | //剔除分类状态隐藏 剔除分类下显示数据为空 40 | if (empty($data) || $data['items']->isEmpty()) { 41 | $this->error('该组幻灯片显示数据为空'); 42 | } 43 | 44 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 45 | $response = [$data]; 46 | } else { 47 | $response = $data; 48 | } 49 | 50 | $this->success("该组幻灯片获取成功!", $response); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /api/home/controller/ThemeController.php: -------------------------------------------------------------------------------- 1 | 6 | // +---------------------------------------------------------------------- 7 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 8 | // +---------------------------------------------------------------------- 9 | namespace api\home\controller; 10 | 11 | use api\home\model\ThemeFileModel; 12 | use cmf\controller\RestBaseController; 13 | 14 | class ThemeController extends RestBaseController 15 | { 16 | /** 17 | * 获取模板扩展属性 18 | */ 19 | public function more() 20 | { 21 | $theme = $this->request->param('theme'); 22 | $themeFileModel = new ThemeFileModel(); 23 | $file = $this->request->param('file'); 24 | $file = $themeFileModel->where('theme', $theme)->where('file', $file)->find(); 25 | 26 | $vars = []; 27 | $widgets = []; 28 | $oldMore = $file['more']; 29 | if (!empty($oldMore['vars'])) { 30 | foreach ($oldMore['vars'] as $varName => $var) { 31 | switch ($var['type']) { 32 | case 'image': 33 | $vars[$varName] = cmf_get_image_url($var['value']); 34 | break; 35 | case 'file': 36 | $vars[$varName] = cmf_get_file_download_url($var['value']); 37 | break; 38 | case 'array': 39 | foreach ($var['value'] as $varKey => $varValue) { 40 | 41 | foreach ($varValue as $varValueKey => $varValueValue) { 42 | switch ($var['item'][$varValueKey]['type']) { 43 | case 'image': 44 | $var['value'][$varKey][$varValueKey] = cmf_get_image_url($varValueValue); 45 | break; 46 | case 'file': 47 | $var['value'][$varKey][$varValueKey] = cmf_get_file_download_url($varValueValue); 48 | break; 49 | default: 50 | $var['value'][$varKey][$varValueKey] = $varValueValue; 51 | 52 | } 53 | } 54 | } 55 | $vars[$varName] = $var['value']; 56 | break; 57 | default: 58 | $vars[$varName] = $var['value']; 59 | } 60 | 61 | } 62 | } 63 | 64 | if (!empty($oldMore['widgets'])) { 65 | foreach ($oldMore['widgets'] as $widgetName => $widget) { 66 | 67 | $widgetVars = []; 68 | if (!empty($widget['vars'])) { 69 | foreach ($widget['vars'] as $varName => $var) { 70 | 71 | switch ($var['type']) { 72 | case 'image': 73 | $widgetVars[$varName] = cmf_get_image_url($var['value']); 74 | break; 75 | case 'file': 76 | $widgetVars[$varName] = cmf_get_file_download_url($var['value']); 77 | break; 78 | case 'array': 79 | foreach ($var['value'] as $varKey => $varValue) { 80 | 81 | foreach ($varValue as $varValueKey => $varValueValue) { 82 | switch ($var['item'][$varValueKey]['type']) { 83 | case 'image': 84 | $var['value'][$varKey][$varValueKey] = cmf_get_image_url($varValueValue); 85 | break; 86 | case 'file': 87 | $var['value'][$varKey][$varValueKey] = cmf_get_file_download_url($varValueValue); 88 | break; 89 | default: 90 | $var['value'][$varKey][$varValueKey] = $varValueValue; 91 | 92 | } 93 | } 94 | } 95 | $widgetVars[$varName]=$var['value']; 96 | break; 97 | default: 98 | $widgetVars[$varName] = $var['value']; 99 | } 100 | } 101 | } 102 | 103 | $widget['vars'] = $widgetVars; 104 | $widgets[$widgetName] = $widget; 105 | } 106 | } 107 | 108 | $this->success('success', [ 109 | 'vars' => $vars, 110 | 'widgets' => $widgets 111 | ]); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /api/home/model/SlideItemModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-5-25 12 | // +---------------------------------------------------------------------- 13 | 14 | namespace api\home\model; 15 | 16 | use think\Model; 17 | 18 | class SlideItemModel extends Model 19 | { 20 | /** 21 | * [base 全局查询范围status=1显示状态] 22 | * @Author: wuwu<15093565100@163.com> 23 | * @DateTime: 2017-05-25T21:54:03+0800 24 | * @since: 1.0 25 | */ 26 | protected function base($query) 27 | { 28 | $query->where('status', 1); 29 | } 30 | 31 | /** 32 | * image 自动转化 33 | * @param $value 34 | * @return array 35 | */ 36 | public function getImageAttr($value) 37 | { 38 | return cmf_get_image_url($value); 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /api/home/model/SlideModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-5-25 12 | // +---------------------------------------------------------------------- 13 | 14 | namespace api\home\model; 15 | 16 | use think\Model; 17 | 18 | class SlideModel extends Model 19 | { 20 | 21 | /** 22 | * [base 全局查询范围status=1显示状态] 23 | * @Author: wuwu<15093565100@163.com> 24 | * @DateTime: 2017-05-25T21:54:03+0800 25 | * @since: 1.0 26 | */ 27 | protected function base($query) 28 | { 29 | $query->where('status', 1)->where('delete_time', 0); 30 | } 31 | 32 | /** 33 | * [SlideItemModel 一对一关联模型 关联分类下的幻灯片] 34 | * @Author: wuwu<15093565100@163.com> 35 | * @DateTime: 2017-05-25T23:30:27+0800 36 | * @since: 1.0 37 | */ 38 | protected function items() 39 | { 40 | return $this->hasMany('SlideItemModel')->order('list_order ASC'); 41 | } 42 | 43 | /** 44 | * [SlideList 幻灯片获取] 45 | * @Author: wuwu<15093565100@163.com> 46 | * @DateTime: 2017-05-25T20:52:27+0800 47 | * @since: 1.0 48 | */ 49 | public function SlideList($map) 50 | { 51 | $data = $this->relation('items')->field(true)->where($map)->find(); 52 | return $data; 53 | } 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /api/home/model/ThemeFileModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-5-25 12 | // +---------------------------------------------------------------------- 13 | 14 | namespace api\home\model; 15 | 16 | use think\Model; 17 | 18 | class ThemeFileModel extends Model 19 | { 20 | 21 | //类型转换 22 | protected $type = [ 23 | 'more' => 'array', 24 | ]; 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /api/home/route.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\controller; 11 | 12 | use api\user\model\UserFavoriteModel; 13 | use api\user\model\UserLikeModel; 14 | use cmf\controller\RestBaseController; 15 | use api\portal\model\PortalPostModel; 16 | use think\Db; 17 | 18 | class ArticlesController extends RestBaseController 19 | { 20 | protected $postModel; 21 | 22 | public function __construct(PortalPostModel $postModel) 23 | { 24 | parent::__construct(); 25 | $this->postModel = $postModel; 26 | } 27 | 28 | /** 29 | * 文章列表 30 | */ 31 | public function index() 32 | { 33 | $params = $this->request->get(); 34 | $params['where']['post_type'] = 1; 35 | $data = $this->postModel->getDatas($params); 36 | 37 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 38 | $response = $data; 39 | } else { 40 | $response = ['list' => $data,]; 41 | } 42 | $this->success('请求成功!', $response); 43 | } 44 | 45 | /** 46 | * 获取指定的文章 47 | * @param int $id 48 | */ 49 | public function read($id) 50 | { 51 | if (intval($id) === 0) { 52 | $this->error('无效的文章id!'); 53 | } else { 54 | $params = $this->request->get(); 55 | $params['where']['post_type'] = 1; 56 | $params['id'] = $id; 57 | $data = $this->postModel->getDatas($params); 58 | if (empty($data)) { 59 | $this->error('文章不存在!'); 60 | } else { 61 | $this->postModel->where('id', $id)->setInc('post_hits'); 62 | $url = cmf_url('portal/Article/index', ['id' => $id, 'cid' => $data['categories'][0]['id']], true, true); 63 | 64 | $data = $data->toArray(); 65 | $data['url'] = $url; 66 | $this->success('请求成功!', $data); 67 | } 68 | 69 | } 70 | } 71 | 72 | /** 73 | * 我的文章列表 74 | */ 75 | public function my() 76 | { 77 | $params = $this->request->get(); 78 | $userId = $this->getUserId(); 79 | $data = $this->postModel->getUserArticles($userId, $params); 80 | 81 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 82 | $response = [$data]; 83 | } else { 84 | $response = ['list' => $data]; 85 | } 86 | 87 | $this->success('请求成功!', $response); 88 | } 89 | 90 | /** 91 | * 添加文章 92 | */ 93 | public function save() 94 | { 95 | $data = $this->request->post(); 96 | $data['user_id'] = $this->getUserId(); 97 | $result = $this->validate($data, 'Articles.article'); 98 | if ($result !== true) { 99 | $this->error($result); 100 | } 101 | 102 | if (empty($data['published_time'])) { 103 | $data['published_time'] = time(); 104 | } 105 | 106 | $this->postModel->addArticle($data); 107 | $this->success('添加成功!'); 108 | } 109 | 110 | /** 111 | * 更新文章 112 | * @param int $id 113 | */ 114 | public function update($id) 115 | { 116 | $data = $this->request->put(); 117 | $result = $this->validate($data, 'Articles.article'); 118 | if ($result !== true) { 119 | $this->error($result); 120 | } 121 | if (empty($id)) { 122 | $this->error('无效的文章id'); 123 | } 124 | $result = $this->postModel->editArticle($data, $id, $this->getUserId()); 125 | if ($result === false) { 126 | $this->error('编辑失败!'); 127 | } else { 128 | $this->success('编辑成功!'); 129 | } 130 | } 131 | 132 | /** 133 | * 删除文章 134 | * @param int $id 135 | */ 136 | public function delete($id) 137 | { 138 | if (empty($id)) { 139 | $this->error('无效的文章id'); 140 | } 141 | $result = $this->postModel->deleteArticle($id, $this->getUserId()); 142 | if ($result == -1) { 143 | $this->error('文章已删除'); 144 | } 145 | if ($result) { 146 | $this->success('删除成功!'); 147 | } else { 148 | $this->error('删除失败!'); 149 | } 150 | } 151 | 152 | /** 153 | * 批量删除文章 154 | */ 155 | public function deletes() 156 | { 157 | $ids = $this->request->post('ids/a'); 158 | if (empty($ids)) { 159 | $this->error('文章id不能为空'); 160 | } 161 | $result = $this->postModel->deleteArticle($ids, $this->getUserId()); 162 | if ($result == -1) { 163 | $this->error('文章已删除'); 164 | } 165 | if ($result) { 166 | $this->success('删除成功!'); 167 | } else { 168 | $this->error('删除失败!'); 169 | } 170 | } 171 | 172 | public function search() 173 | { 174 | $params = $this->request->get(); 175 | if (!empty($params['keyword'])) { 176 | $params['where'] = [ 177 | 'post_type' => 1, 178 | 'post_title|post_keywords|post_excerpt' => ['like', '%' . $params['keyword'] . '%'] 179 | ]; 180 | $data = $this->postModel->getDatas($params); 181 | 182 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 183 | $response = $data; 184 | } else { 185 | $response = ['list' => $data,]; 186 | } 187 | 188 | $this->success('请求成功!', $response); 189 | } else { 190 | $this->error('搜索关键词不能为空!'); 191 | } 192 | 193 | } 194 | 195 | public function doLike() 196 | { 197 | $userId = $this->getUserId(); 198 | 199 | $articleId = $this->request->param('id', 0, 'intval'); 200 | 201 | $userLikeModel = new UserLikeModel(); 202 | 203 | $findLikeCount = $userLikeModel->where([ 204 | 'user_id' => $userId, 205 | 'object_id' => $articleId 206 | ])->where('table_name', 'portal_post')->count(); 207 | 208 | if (empty($findLikeCount)) { 209 | $article = $this->postModel->where(['id' => $articleId])->field('id,post_title,post_excerpt,more')->find(); 210 | if (empty($article)) { 211 | $this->error('文章不存在!'); 212 | } 213 | 214 | Db::startTrans(); 215 | try { 216 | $this->postModel->where(['id' => $articleId])->setInc('post_like'); 217 | $thumbnail = empty($article['more']['thumbnail']) ? '' : $article['more']['thumbnail']; 218 | $userLikeModel->insert([ 219 | 'user_id' => $userId, 220 | 'object_id' => $articleId, 221 | 'table_name' => 'portal_post', 222 | 'title' => $article['post_title'], 223 | 'thumbnail' => $thumbnail, 224 | 'description' => $article['post_excerpt'], 225 | 'url' => json_encode(['action' => 'portal/Article/index', 'param' => ['id' => $articleId, 'cid' => $article['categories'][0]['id']]]), 226 | 'create_time' => time() 227 | ]); 228 | Db::commit(); 229 | } catch (\Exception $e) { 230 | Db::rollback(); 231 | 232 | $this->error('点赞失败!'); 233 | } 234 | 235 | $likeCount = $this->postModel->where('id', $articleId)->value('post_like'); 236 | $this->success("赞好啦!", ['post_like' => $likeCount]); 237 | } else { 238 | $this->error("您已赞过啦!"); 239 | } 240 | } 241 | 242 | /** 243 | * 取消文章点赞 244 | */ 245 | public function cancelLike() 246 | { 247 | $userId = $this->getUserId(); 248 | 249 | $articleId = $this->request->param('id', 0, 'intval'); 250 | 251 | $userLikeModel = new UserLikeModel(); 252 | 253 | $findLikeCount = $userLikeModel->where([ 254 | 'user_id' => $userId, 255 | 'object_id' => $articleId 256 | ])->where('table_name', 'portal_post')->count(); 257 | 258 | if (!empty($findLikeCount)) { 259 | 260 | Db::startTrans(); 261 | try { 262 | $this->postModel->where(['id' => $articleId])->setDec('post_like'); 263 | $userLikeModel->where([ 264 | 'user_id' => $userId, 265 | 'object_id' => $articleId 266 | ])->where('table_name', 'portal_post')->delete(); 267 | Db::commit(); 268 | } catch (\Exception $e) { 269 | Db::rollback(); 270 | $this->error('取消点赞失败!'); 271 | } 272 | 273 | $likeCount = $this->postModel->where('id', $articleId)->value('post_like'); 274 | $this->success("取消点赞成功!", ['post_like' => $likeCount]); 275 | } else { 276 | $this->error("您还没赞过!"); 277 | } 278 | } 279 | 280 | /** 281 | * 文章收藏 282 | * @throws \think\Exception 283 | */ 284 | public function doFavorite() 285 | { 286 | $userId = $this->getUserId(); 287 | 288 | $articleId = $this->request->param('id', 0, 'intval'); 289 | 290 | $userFavoriteModel = new UserFavoriteModel(); 291 | 292 | $findFavoriteCount = $userFavoriteModel->where([ 293 | 'user_id' => $userId, 294 | 'object_id' => $articleId 295 | ])->where('table_name', 'portal_post')->count(); 296 | 297 | if (empty($findFavoriteCount)) { 298 | $article = $this->postModel->where(['id' => $articleId])->field('id,post_title,post_excerpt,more')->find(); 299 | if (empty($article)) { 300 | $this->error('文章不存在!'); 301 | } 302 | 303 | Db::startTrans(); 304 | try { 305 | $this->postModel->where(['id' => $articleId])->setInc('post_favorites'); 306 | $thumbnail = empty($article['more']['thumbnail']) ? '' : $article['more']['thumbnail']; 307 | $userFavoriteModel->insert([ 308 | 'user_id' => $userId, 309 | 'object_id' => $articleId, 310 | 'table_name' => 'portal_post', 311 | 'thumbnail' => $thumbnail, 312 | 'title' => $article['post_title'], 313 | 'description' => $article['post_excerpt'], 314 | 'url' => json_encode(['action' => 'portal/Article/index', 'param' => ['id' => $articleId, 'cid' => $article['categories'][0]['id']]]), 315 | 'create_time' => time() 316 | ]); 317 | Db::commit(); 318 | } catch (\Exception $e) { 319 | Db::rollback(); 320 | 321 | $this->error('收藏失败!'); 322 | } 323 | 324 | $favoriteCount = $this->postModel->where('id', $articleId)->value('post_favorites'); 325 | $this->success("收藏好啦!", ['post_favorites' => $favoriteCount]); 326 | } else { 327 | $this->error("您已收藏过啦!"); 328 | } 329 | } 330 | 331 | /** 332 | * 取消文章收藏 333 | */ 334 | public function cancelFavorite() 335 | { 336 | $userId = $this->getUserId(); 337 | 338 | $articleId = $this->request->param('id', 0, 'intval'); 339 | 340 | $userFavoriteModel = new UserFavoriteModel(); 341 | 342 | $findFavoriteCount = $userFavoriteModel->where([ 343 | 'user_id' => $userId, 344 | 'object_id' => $articleId 345 | ])->where('table_name', 'portal_post')->count(); 346 | 347 | if (!empty($findFavoriteCount)) { 348 | 349 | Db::startTrans(); 350 | try { 351 | $this->postModel->where(['id' => $articleId])->setDec('post_favorites'); 352 | $userFavoriteModel->where([ 353 | 'user_id' => $userId, 354 | 'object_id' => $articleId 355 | ])->where('table_name', 'portal_post')->delete(); 356 | Db::commit(); 357 | } catch (\Exception $e) { 358 | Db::rollback(); 359 | $this->error('取消失败!'); 360 | } 361 | 362 | $favoriteCount = $this->postModel->where('id', $articleId)->value('post_favorites'); 363 | $this->success("取消成功!", ['post_favorites' => $favoriteCount]); 364 | } else { 365 | $this->error("您还没收藏过!"); 366 | } 367 | } 368 | 369 | 370 | /** 371 | * 相关文章列表 372 | */ 373 | public function relatedArticles() 374 | { 375 | $articleId = $this->request->param('id', 0, 'intval'); 376 | $categoryId = Db::name('portal_category_post')->where('post_id', $articleId)->value('category_id'); 377 | 378 | 379 | $articles = $this->postModel->alias('post')->join('__PORTAL_CATEGORY_POST__ category_post', 'post.id=category_post.post_id') 380 | ->where(['post.delete_time' => 0, 'post.post_status' => 1, 'category_post.category_id' => $categoryId]) 381 | ->order(Db::raw('rand()')) 382 | ->limit(5) 383 | ->select(); 384 | 385 | $this->success('success', ['list' => $articles]); 386 | } 387 | } -------------------------------------------------------------------------------- /api/portal/controller/CategoriesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\controller; 11 | 12 | use cmf\controller\RestBaseController; 13 | use api\portal\model\PortalCategoryModel; 14 | 15 | class CategoriesController extends RestBaseController 16 | { 17 | protected $categoryModel; 18 | 19 | public function __construct(PortalCategoryModel $categoryModel) 20 | { 21 | parent::__construct(); 22 | $this->categoryModel = $categoryModel; 23 | } 24 | 25 | /** 26 | * 获取分类列表 27 | */ 28 | public function index() 29 | { 30 | $params = $this->request->get(); 31 | $data = $this->categoryModel->getDatas($params); 32 | 33 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 34 | $response = $data; 35 | } else { 36 | $response = ['list' => $data]; 37 | } 38 | 39 | $this->success('请求成功!', $response); 40 | } 41 | 42 | /** 43 | * 显示指定的分类 44 | * @param int $id 45 | */ 46 | public function read($id) 47 | { 48 | $params = $this->request->get(); 49 | $params['id'] = $id; 50 | $data = $this->categoryModel->getDatas($params); 51 | $this->success('请求成功!', $data); 52 | } 53 | 54 | /** 55 | * 获取指定分类的子分类列表 56 | * @throws \think\db\exception\DataNotFoundException 57 | * @throws \think\db\exception\ModelNotFoundException 58 | * @throws \think\exception\DbException 59 | */ 60 | public function subCategories() 61 | { 62 | $id = $this->request->get('category_id', 0, 'intval'); 63 | 64 | $categories = $this->categoryModel->where(['parent_id' => $id])->select(); 65 | 66 | $this->success('请求成功', ['categories' => $categories]); 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /api/portal/controller/ListsController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\model\PortalCategoryModel; 12 | use api\portal\model\PortalPostModel; 13 | use cmf\controller\RestBaseController; 14 | 15 | class ListsController extends RestBaseController 16 | { 17 | 18 | /** 19 | * [推荐文章列表] 20 | * @Author: wuwu<15093565100@163.com> 21 | * @DateTime: 2017-07-17T11:36:51+0800 22 | * @since: 1.0 23 | */ 24 | public function recommended() 25 | { 26 | $param = $this->request->param(); 27 | $portalPostModel = new PortalPostModel(); 28 | 29 | $param['where'] = ['recommended' => 1]; 30 | 31 | $articles = $portalPostModel->getDatas($param); 32 | 33 | $this->success('ok', ['list' => $articles]); 34 | } 35 | 36 | /** 37 | * [getCategoryPostLists 分类文章列表] 38 | * @Author: wuwu<15093565100@163.com> 39 | * @DateTime: 2017-07-17T15:22:41+0800 40 | * @since: 1.0 41 | */ 42 | public function getCategoryPostLists() 43 | { 44 | $categoryId = $this->request->param('category_id', 0, 'intval'); 45 | 46 | 47 | $portalCategoryModel = new PortalCategoryModel(); 48 | 49 | $findCategory = $portalCategoryModel->where('id', $categoryId)->find(); 50 | 51 | //分类是否存在 52 | if (empty($findCategory)) { 53 | $this->error('分类不存在!'); 54 | } 55 | 56 | $param = $this->request->param(); 57 | 58 | if(empty($param['order'])){ 59 | $param['order']='-post.published_time'; 60 | } 61 | 62 | $articles = $portalCategoryModel->paramsFilter($param, $findCategory->articles()->alias('post'))->select(); 63 | 64 | if (!empty($param['relation'])) { 65 | if (count($articles) > 0) { 66 | $articles->load('user'); 67 | $articles->append(['user']); 68 | } 69 | } 70 | 71 | $this->success('ok', ['list' => $articles]); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /api/portal/controller/PagesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\controller; 11 | 12 | use cmf\controller\RestBaseController; 13 | use api\portal\model\PortalPostModel; 14 | 15 | class PagesController extends RestBaseController 16 | { 17 | protected $postModel; 18 | 19 | public function __construct(PortalPostModel $postModel) 20 | { 21 | parent::__construct(); 22 | $this->postModel = $postModel; 23 | } 24 | 25 | /** 26 | * 页面列表 27 | */ 28 | public function index() 29 | { 30 | $params = $this->request->get(); 31 | $params['where']['post_type'] = 2; 32 | $data = $this->postModel->getDatas($params); 33 | 34 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 35 | $response = $data; 36 | } else { 37 | $response = ['list' => $data,]; 38 | } 39 | $this->success('请求成功!', $response); 40 | } 41 | 42 | /** 43 | * 获取页面 44 | * @param int $id 45 | */ 46 | public function read($id) 47 | { 48 | $params = $this->request->get(); 49 | $params['where']['post_type'] = 2; 50 | $params['id'] = $id; 51 | $data = $this->postModel->getDatas($params); 52 | $this->success('请求成功!', $data); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /api/portal/controller/TagsController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\model\PortalPostModel; 12 | use cmf\controller\RestBaseController; 13 | use api\portal\model\PortalTagModel; 14 | 15 | class TagsController extends RestBaseController 16 | { 17 | protected $tagModel; 18 | 19 | public function __construct(PortalTagModel $tagModel) 20 | { 21 | parent::__construct(); 22 | $this->tagModel = $tagModel; 23 | } 24 | 25 | /** 26 | * 获取标签列表 27 | */ 28 | public function index() 29 | { 30 | $params = $this->request->get(); 31 | $data = $this->tagModel->getDatas($params); 32 | 33 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 34 | $response = $data; 35 | } else { 36 | $response = ['list' => $data,]; 37 | } 38 | $this->success('请求成功!', $response); 39 | } 40 | 41 | /** 42 | * 获取热门标签列表 43 | */ 44 | public function hotTags() 45 | { 46 | $params = $this->request->get(); 47 | $params['where']['recommended'] = 1; 48 | $data = $this->tagModel->getDatas($params); 49 | 50 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 51 | $response = $data; 52 | } else { 53 | $response = ['list' => $data,]; 54 | } 55 | $this->success('请求成功!', $response); 56 | } 57 | 58 | /** 59 | * 获取标签文章列表 60 | * @param int $id 61 | */ 62 | public function articles($id) 63 | { 64 | if (intval($id) === 0) { 65 | $this->error('无效的标签id!'); 66 | } else { 67 | $params = $this->request->param(); 68 | $postModel = new PortalPostModel(); 69 | 70 | unset($params['id']); 71 | 72 | $articles = $postModel->paramsFilter($params)->alias('post') 73 | ->join('__PORTAL_TAG_POST__ tag_post', 'post.id = tag_post.post_id') 74 | ->where(['tag_post.tag_id' => $id])->select(); 75 | 76 | if (!empty($params['relation'])) { 77 | $allowedRelations = $postModel->allowedRelations($params['relation']); 78 | if (!empty($allowedRelations)) { 79 | if (count($articles) > 0) { 80 | $articles->load($allowedRelations); 81 | $articles->append($allowedRelations); 82 | } 83 | } 84 | } 85 | 86 | 87 | $this->success('请求成功!', ['articles' => $articles]); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /api/portal/controller/UserArticlesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use cmf\controller\RestUserBaseController; 12 | use api\portal\logic\PortalPostModel; 13 | 14 | class UserArticlesController extends RestUserBaseController 15 | { 16 | protected $postModel; 17 | 18 | public function __construct(PortalPostModel $postModel) 19 | { 20 | parent::__construct(); 21 | $this->postModel = $postModel; 22 | } 23 | 24 | /** 25 | * 显示资源列表 26 | */ 27 | public function index() 28 | { 29 | $params = $this->request->get(); 30 | $userId = $this->getUserId(); 31 | $datas = $this->postModel->getUserArticles($userId,$params); 32 | $this->success('请求成功!', $datas); 33 | } 34 | 35 | /** 36 | * 保存新建的资源 37 | */ 38 | public function save() 39 | { 40 | $datas = $this->request->post(); 41 | $datas['user_id'] = $this->getUserId(); 42 | $result = $this->validate($datas, 'Articles.article'); 43 | if ($result !== true) { 44 | $this->error($result); 45 | } 46 | if (empty($datas['published_time'])) { 47 | $datas['published_time'] = time(); 48 | } 49 | $this->postModel->addArticle($datas); 50 | $this->success('添加成功!'); 51 | } 52 | 53 | /** 54 | * 显示指定的资源 55 | * 56 | * @param int $id 57 | */ 58 | public function read($id) 59 | { 60 | if (empty($id)) { 61 | $this->error('无效的文章id'); 62 | } 63 | $params = $this->request->get(); 64 | $params['id'] = $id; 65 | $userId = $this->getUserId(); 66 | $datas = $this->postModel->getUserArticles($userId,$params); 67 | $this->success('请求成功!', $datas); 68 | } 69 | 70 | /** 71 | * 保存更新的资源 72 | * 73 | * @param int $id 74 | */ 75 | public function update($id) 76 | { 77 | $data = $this->request->put(); 78 | $result = $this->validate($data, 'Articles.article'); 79 | if ($result !== true) { 80 | $this->error($result); 81 | } 82 | if (empty($id)) { 83 | $this->error('无效的文章id'); 84 | } 85 | $result = $this->postModel->editArticle($data,$id,$this->getUserId()); 86 | if ($result === false) { 87 | $this->error('编辑失败!'); 88 | } else { 89 | $this->success('编辑成功!'); 90 | } 91 | } 92 | 93 | /** 94 | * 删除指定资源 95 | * 96 | * @param int $id 97 | */ 98 | public function delete($id) 99 | { 100 | if (empty($id)) { 101 | $this->error('无效的文章id'); 102 | } 103 | $result = $this->postModel->deleteArticle($id,$this->getUserId()); 104 | if ($result == -1) { 105 | $this->error('文章已删除'); 106 | } 107 | if ($result) { 108 | $this->success('删除成功!'); 109 | } else { 110 | $this->error('删除失败!'); 111 | } 112 | } 113 | /** 114 | * 批量删除文章 115 | */ 116 | public function deletes() 117 | { 118 | $ids = $this->request->post('ids/a'); 119 | if (empty($ids)) { 120 | $this->error('文章id不能为空'); 121 | } 122 | $result = $this->postModel->deleteArticle($ids,$this->getUserId()); 123 | if ($result == -1) { 124 | $this->error('文章已删除'); 125 | } 126 | if ($result) { 127 | $this->success('删除成功!'); 128 | } else { 129 | $this->error('删除失败!'); 130 | } 131 | } 132 | 133 | /** 134 | * 我的文章列表 135 | */ 136 | public function my() 137 | { 138 | $params = $this->request->get(); 139 | $userId = $this->getUserId(); 140 | $data = $this->postModel->getUserArticles($userId, $params); 141 | $this->success('请求成功!', $data); 142 | } 143 | } -------------------------------------------------------------------------------- /api/portal/controller/UserController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\model\PortalPostModel; 12 | use cmf\controller\RestBaseController; 13 | 14 | class UserController extends RestBaseController 15 | { 16 | protected $postModel; 17 | 18 | public function __construct(PortalPostModel $postModel) 19 | { 20 | parent::__construct(); 21 | $this->postModel = $postModel; 22 | } 23 | 24 | /** 25 | * 会员文章列表 26 | */ 27 | public function articles() 28 | { 29 | $userId = $this->request->param('user_id', 0, 'intval'); 30 | 31 | if(empty($userId)){ 32 | $this->error('用户id不能空!'); 33 | } 34 | 35 | $data = $this->request->param(); 36 | $articles = $this->postModel->setCondition($data)->where(['user_id' => $userId])->select(); 37 | 38 | if (count($articles) == 0) { 39 | $this->error('没有数据'); 40 | } else { 41 | $this->success('ok', ['list' => $articles]); 42 | } 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /api/portal/logic/PortalPostModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\logic; 11 | 12 | use api\portal\model\PortalPostModel as PortalPost; 13 | use think\Db; 14 | class PortalPostModel extends PortalPost 15 | { 16 | /** 17 | * 获取相关文章 18 | * @param int|string|array $postIds 文章id 19 | * @return array 20 | */ 21 | public function getRelationPosts($postIds) 22 | { 23 | $posts = $this->with('articleUser') 24 | ->field('id,post_title,user_id,is_top,post_hits,post_like,comment_count,more') 25 | ->whereIn('id', $postIds) 26 | ->select(); 27 | foreach ($posts as $post) { 28 | $post->appendRelationAttr('articleUser', 'user_nickname'); 29 | } 30 | return $posts; 31 | } 32 | /** 33 | * 获取用户文章 34 | */ 35 | public function getUserArticles($userId, $params) 36 | { 37 | $where = [ 38 | 'post_type' => 1, 39 | 'user_id' => $userId 40 | ]; 41 | if (!empty($params)) { 42 | $this->paramsFilter($params); 43 | } 44 | return $this->where($where)->select(); 45 | } 46 | 47 | /** 48 | * 会员添加文章 49 | * @param array $data 文章数据 50 | * @return $this 51 | */ 52 | public function addArticle($data) 53 | { 54 | //设置图片附件,写入字段过滤 55 | $dataField = $this->setMoreField($data); 56 | $data = $dataField[0]; 57 | array_push($dataField[1],'user_id'); 58 | $this->readonly = array_diff(['user_id'],$this->readonly); 59 | $this->allowField($dataField[1])->data($data, true)->isUpdate(false)->save(); 60 | $categories = $this->strToArr($data['categories']); 61 | $this->categories()->attach($categories); 62 | if (!empty($data['post_keywords']) && is_string($data['post_keywords'])) { 63 | //加入标签 64 | $data['post_keywords'] = str_replace(',', ',', $data['post_keywords']); 65 | $keywords = explode(',', $data['post_keywords']); 66 | $this->addTags($keywords, $this->id); 67 | } 68 | return $this; 69 | } 70 | 71 | /** 72 | * 会员文章编辑 73 | * @param array $data 文章数据 74 | * @param int $id 文章id 75 | * @param int $userId 文章所属用户id [可选] 76 | * @return boolean 成功 true 失败 false 77 | */ 78 | public function editArticle($data, $id, $userId = '') 79 | { 80 | if (!empty($userId)) { 81 | $isBelong = $this->isuserPost($id, $userId); 82 | if ($isBelong === false) { 83 | return $isBelong; 84 | } 85 | } 86 | //设置图片附件,写入字段过滤 87 | $dataField = $this->setMoreField($data); 88 | $data = $dataField[0]; 89 | $data['id'] = $id; 90 | $this->allowField($dataField[1])->data($data, true)->isUpdate(true)->save(); 91 | 92 | $categories = $this->strToArr($data['categories']); 93 | $oldCategoryIds = $this->categories()->column('category_id'); 94 | $sameCategoryIds = array_intersect($categories, $oldCategoryIds); 95 | $needDeleteCategoryIds = array_diff($oldCategoryIds, $sameCategoryIds); 96 | $newCategoryIds = array_diff($categories, $sameCategoryIds); 97 | if (!empty($needDeleteCategoryIds)) { 98 | $this->categories()->detach($needDeleteCategoryIds); 99 | } 100 | if (!empty($newCategoryIds)) { 101 | $this->categories()->attach(array_values($newCategoryIds)); 102 | } 103 | if (!isset($data['post_keywords'])) { 104 | $keywords = []; 105 | } elseif (is_string($data['post_keywords'])) { 106 | //加入标签 107 | $data['post_keywords'] = str_replace(',', ',', $data['post_keywords']); 108 | $keywords = explode(',', $data['post_keywords']); 109 | } 110 | $this->addTags($keywords, $data['id']); 111 | return $this; 112 | } 113 | 114 | /** 115 | * 根据文章关键字,增加标签 116 | * @param array $keywords 文章关键字数组 117 | * @param int $articleId 文章id 118 | * @return void 119 | */ 120 | public function addTags($keywords, $articleId) 121 | { 122 | foreach ($keywords as $key => $value) { 123 | $keywords[$key] = trim($value); 124 | } 125 | $continue = true; 126 | $names = $this->tags()->column('name'); 127 | if (!empty($keywords) || !empty($names)) { 128 | if (!empty($names)) { 129 | $sameNames = array_intersect($keywords, $names); 130 | $keywords = array_diff($keywords, $sameNames); 131 | $shouldDeleteNames = array_diff($names, $sameNames); 132 | if (!empty($shouldDeleteNames)) { 133 | $tagIdNames = $this->tags() 134 | ->where('name', 'in', $shouldDeleteNames) 135 | ->column('pivot.id', 'tag_id'); 136 | $tagIds = array_keys($tagIdNames); 137 | $tagPostIds = array_values($tagIdNames); 138 | $tagPosts = DB::name('portal_tag_post')->where('tag_id', 'in', $tagIds) 139 | ->field('id,tag_id,post_id') 140 | ->select(); 141 | $keepTagIds = []; 142 | foreach ($tagPosts as $key => $tagPost) { 143 | if ($articleId != $tagPost['post_id']) { 144 | array_push($keepTagIds, $tagPost['tag_id']); 145 | } 146 | } 147 | $keepTagIds = array_unique($keepTagIds); 148 | $shouldDeleteTagIds = array_diff($tagIds, $keepTagIds); 149 | DB::name('PortalTag')->delete($shouldDeleteTagIds); 150 | DB::name('PortalTagPost')->delete($tagPostIds); 151 | } 152 | } else { 153 | $tagIdNames = DB::name('portal_tag')->where('name', 'in', $keywords)->column('name', 'id'); 154 | if (!empty($tagIdNames)) { 155 | $tagIds = array_keys($tagIdNames); 156 | $this->tags()->attach($tagIds); 157 | $keywords = array_diff($keywords, array_values($tagIdNames)); 158 | if (empty($keywords)) { 159 | $continue = false; 160 | } 161 | } 162 | } 163 | if ($continue) { 164 | foreach ($keywords as $key => $value) { 165 | if (!empty($value)) { 166 | $this->tags()->attach(['name' => $value]); 167 | } 168 | } 169 | } 170 | } 171 | } 172 | 173 | /** 174 | * 设置缩略图,图片,附件 175 | * 懒人方法 176 | * @param $data 表单数据 177 | */ 178 | public function setMoreField($data) 179 | { 180 | $allowField = [ 181 | 'post_title','post_keywords','post_source', 182 | 'post_excerpt','post_content','more', 183 | 'published_time' 184 | ]; 185 | if (!empty($data['more'])) { 186 | $data['more'] = $this->setMoreUrl($data['more']); 187 | } 188 | if (!empty($data['thumbnail'])) { 189 | $data['more']['thumbnail'] = cmf_asset_relative_url($data['thumbnail']); 190 | } 191 | return [$data,$allowField]; 192 | } 193 | 194 | /** 195 | * 获取图片附件url相对地址 196 | * 默认上传名字 *_names 地址 *_urls 197 | * @param $annex 上传附件 198 | * @return array 199 | */ 200 | public function setMoreUrl($annex) 201 | { 202 | $more = []; 203 | if (!empty($annex)) { 204 | foreach ($annex as $key => $value) { 205 | $nameArr = $key . '_names'; 206 | $urlArr = $key . '_urls'; 207 | if (is_string($value[$nameArr]) && is_string($value[$urlArr])) { 208 | $more[$key] = [$value[$nameArr], $value[$urlArr]]; 209 | } elseif (!empty($value[$nameArr]) && !empty($value[$urlArr])) { 210 | $more[$key] = []; 211 | foreach ($value[$urlArr] as $k => $url) { 212 | $url = cmf_asset_relative_url($url); 213 | array_push($more[$key], ['url' => $url, 'name' => $value[$nameArr][$k]]); 214 | } 215 | } 216 | } 217 | } 218 | return $more; 219 | } 220 | 221 | /** 222 | * 删除文章 223 | * @param $ids int|array 文章id 224 | * @param int $userId 文章所属用户id [可选] 225 | * @return bool|int 删除结果 true 成功 false 失败 -1 文章不存在 226 | */ 227 | public function deleteArticle($ids, $userId) 228 | { 229 | $time = time(); 230 | $result = false; 231 | $where = []; 232 | 233 | if (!empty($userId)) { 234 | if (is_numeric($ids)) { 235 | $article = $this->find($ids); 236 | if (!empty($article)) { 237 | if ($this->isUserPost($ids, $userId) || $userId == 1) { 238 | $where['id'] = $ids; 239 | } 240 | } 241 | } else { 242 | $ids = $this->strToArr($ids); 243 | $articles = $this->where('id', 'in', $ids)->select(); 244 | if (!empty($articles)) { 245 | $deleteIds = $this->isUserPosts($ids, $userId); 246 | if (!empty($deleteIds)) { 247 | $where['id'] = ['in', $deleteIds]; 248 | } 249 | } 250 | } 251 | } else { 252 | if (is_numeric($ids)) { 253 | $article = $this->find($ids); 254 | if (!empty($article)) { 255 | $where['id'] = $ids; 256 | } 257 | } else { 258 | $ids = $this->strToArr($ids); 259 | $articles = $this->where('id', 'in', $ids)->select(); 260 | if (!empty($articles)) { 261 | $where['id'] = ['in', $ids]; 262 | } 263 | } 264 | } 265 | if (empty($article) && empty($articles)) { 266 | return -1; 267 | } 268 | if (!empty($where)) { 269 | $result = $this->useGlobalScope(false) 270 | ->where($where) 271 | ->setField('delete_time', $time); 272 | } 273 | if ($result) { 274 | $data = [ 275 | 'create_time' => $time, 276 | 'table_name' => 'portal_post' 277 | ]; 278 | if (!empty($article)) { 279 | $data['name'] = $article['post_title']; 280 | $article->recycleBin()->save($data); 281 | } 282 | 283 | if (!empty($articles)) { 284 | foreach ($articles as $article) { 285 | $data['name'] = $article['post_title']; 286 | $article->recycleBin()->save($data); 287 | } 288 | } 289 | } 290 | return $result; 291 | } 292 | 293 | /** 294 | * 判断文章所属用户是否为当前用户,超级管理员除外 295 | * @params int $id 文章id 296 | * @param int $userId 当前用户id 297 | * @return boolean 是 true , 否 false 298 | */ 299 | public function isUserPost($id, $userId) 300 | { 301 | $postUserId = $this->useGlobalScope(false) 302 | ->getFieldById($id, 'user_id'); 303 | if ($postUserId != $userId || $userId != 1) { 304 | return false; 305 | } else { 306 | return true; 307 | } 308 | } 309 | 310 | /** 311 | * 过滤属于当前用户的文章,超级管理员除外 312 | * @params array $ids 文章id的数组 313 | * @param int $userId 当前用户id 314 | * @return array 属于当前用户的文章id 315 | */ 316 | public function isUserPosts($ids, $userId) 317 | { 318 | $postIds = $this->useGlobalScope(false) 319 | ->where('user_id', $userId) 320 | ->where('id', 'in', $ids) 321 | ->column('id'); 322 | return array_intersect($ids, $postIds); 323 | } 324 | } 325 | -------------------------------------------------------------------------------- /api/portal/model/PortalCategoryModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | use api\common\model\CommonModel; 13 | 14 | class PortalCategoryModel extends CommonModel 15 | { 16 | //类型转换 17 | protected $type = [ 18 | 'more' => 'array', 19 | ]; 20 | 21 | //可查询字段 22 | protected $visible = [ 23 | 'id', 'name', 'description', 'post_count', 24 | 'seo_title', 'seo_keywords', 'seo_description', 25 | 'list_order','more', 'PostIds', 'articles' 26 | ]; 27 | 28 | //模型关联方法 29 | protected $relationFilter = ['articles']; 30 | 31 | /** 32 | * 基础查询 33 | */ 34 | protected function base($query) 35 | { 36 | $query->alias('portal_category')->where('delete_time', 0) 37 | ->where('portal_category.status', 1); 38 | } 39 | 40 | /** 41 | * more 自动转化 42 | * @param $value 43 | * @return array 44 | */ 45 | public function getMoreAttr($value) 46 | { 47 | $more = json_decode($value, true); 48 | if (!empty($more['thumbnail'])) { 49 | $more['thumbnail'] = cmf_get_image_url($more['thumbnail']); 50 | } 51 | 52 | if (!empty($more['photos'])) { 53 | foreach ($more['photos'] as $key => $value) { 54 | $more['photos'][$key]['url'] = cmf_get_image_url($value['url']); 55 | } 56 | } 57 | return $more; 58 | } 59 | 60 | /** 61 | * 关联文章表 62 | * @return $this 63 | */ 64 | public function articles() 65 | { 66 | return $this->belongsToMany('PortalPostModel', 'portal_category_post', 'post_id', 'category_id'); 67 | } 68 | 69 | /** 70 | * [PostIds 关联] 71 | * @Author: wuwu<15093565100@163.com> 72 | * @DateTime: 2017-07-17T15:20:31+0800 73 | * @since: 1.0 74 | */ 75 | public function PostIds() 76 | { 77 | return self::hasMany('PortalCategoryPostModel', 'category_id', 'id'); 78 | } 79 | 80 | /** 81 | * [categoryPostIds 此类文章id数组] 82 | * @Author: wuwu<15093565100@163.com> 83 | * @DateTime: 2017-07-17T15:21:08+0800 84 | * @since: 1.0 85 | * @param [type] $category_id [分类ID] 86 | * @return [type] [文章id数组] 87 | */ 88 | public static function categoryPostIds($category_id) 89 | { 90 | $ids = []; 91 | $post_ids = self::relation('PostIds')->field(true)->where('id', $category_id)->find(); 92 | foreach ($post_ids['PostIds'] as $key => $id) { 93 | $ids[] = $id['post_id']; 94 | } 95 | $post_ids['PostIds'] = $ids; 96 | return $post_ids; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /api/portal/model/PortalCategoryPostModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace api\portal\model; 12 | 13 | use think\Model; 14 | 15 | class PortalCategoryPostModel extends Model 16 | { 17 | /** 18 | * 基础查询 19 | */ 20 | protected function base($query) 21 | { 22 | $query->where('status', 1); 23 | } 24 | } -------------------------------------------------------------------------------- /api/portal/model/PortalPostModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\model; 10 | 11 | use think\Db; 12 | use api\common\model\CommonModel; 13 | 14 | class PortalPostModel extends CommonModel 15 | { 16 | //可查询字段 17 | protected $visible = [ 18 | 'id', 'articles.id', 'user_id', 'post_id', 'post_type', 'comment_status', 19 | 'is_top', 'recommended', 'post_hits', 'post_like', 'post_favorites','comment_count', 20 | 'create_time', 'update_time', 'published_time', 'post_title', 'post_keywords', 21 | 'post_excerpt', 'post_source', 'post_content', 'more', 'user_nickname', 22 | 'user', 'category_id' 23 | ]; 24 | 25 | //设置只读字段 26 | protected $readonly = ['user_id']; 27 | // 开启自动写入时间戳字段 28 | protected $autoWriteTimestamp = true; 29 | //类型转换 30 | protected $type = [ 31 | 'more' => 'array', 32 | ]; 33 | //模型关联方法 34 | protected $relationFilter = ['user', 'categories']; 35 | 36 | /** 37 | * 基础查询 38 | */ 39 | protected function base($query) 40 | { 41 | $query->where('delete_time', 0) 42 | ->where('post_status', 1) 43 | ->whereTime('published_time', 'between', [1, time()]); 44 | } 45 | 46 | /** 47 | * 关联 user表 48 | * @return $this 49 | */ 50 | public function user() 51 | { 52 | return $this->belongsTo('api\portal\model\UserModel', 'user_id'); 53 | } 54 | 55 | /** 56 | * 关联 user表 57 | * @return $this 58 | */ 59 | public function articleUser() 60 | { 61 | return $this->belongsTo('api\portal\model\UserModel', 'user_id')->field('id,user_nickname'); 62 | } 63 | 64 | /** 65 | * 关联分类表 66 | * @return $this 67 | */ 68 | public function categories() 69 | { 70 | return $this->belongsToMany('api\portal\model\PortalCategoryModel', 'portal_category_post', 'category_id', 'post_id'); 71 | } 72 | 73 | /** 74 | * 关联标签表 75 | * @return $this 76 | */ 77 | public function tags() 78 | { 79 | return $this->belongsToMany('api\portal\model\PortalTagModel', 'portal_tag_post', 'tag_id', 'post_id'); 80 | } 81 | 82 | /** 83 | * 关联 回收站 表 84 | */ 85 | public function recycleBin() 86 | { 87 | return $this->hasOne('api\portal\model\RecycleBinModel', 'object_id'); 88 | } 89 | 90 | /** 91 | * published_time 自动转化 92 | * @param $value 93 | * @return string 94 | */ 95 | public function getPublishedTimeAttr($value) 96 | { 97 | // 兼容老版本 1.0.0的客户端 98 | $apiVersion = request()->header('XX-Api-Version'); 99 | if (empty($apiVersion)) { 100 | return date('Y-m-d H:i:s', $value); 101 | } else { 102 | return $value; 103 | } 104 | } 105 | 106 | /** 107 | * published_time 自动转化 108 | * @param $value 109 | * @return int 110 | */ 111 | public function setPublishedTimeAttr($value) 112 | { 113 | if (is_numeric($value)) { 114 | return $value; 115 | } 116 | return strtotime($value); 117 | } 118 | 119 | public function getPostTitleAttr($value) 120 | { 121 | return htmlspecialchars_decode($value); 122 | } 123 | 124 | public function getPostExcerptAttr($value) 125 | { 126 | return htmlspecialchars_decode($value); 127 | } 128 | 129 | /** 130 | * post_content 自动转化 131 | * @param $value 132 | * @return string 133 | */ 134 | public function getPostContentAttr($value) 135 | { 136 | return cmf_replace_content_file_url(htmlspecialchars_decode($value)); 137 | } 138 | 139 | /** 140 | * post_content 自动转化 141 | * @param $value 142 | * @return string 143 | */ 144 | public function setPostContentAttr($value) 145 | { 146 | return htmlspecialchars(cmf_replace_content_file_url(htmlspecialchars_decode($value), true)); 147 | } 148 | 149 | /** 150 | * more 自动转化 151 | * @param $value 152 | * @return array 153 | */ 154 | public function getMoreAttr($value) 155 | { 156 | $more = json_decode($value, true); 157 | if (!empty($more['thumbnail'])) { 158 | $more['thumbnail'] = cmf_get_image_url($more['thumbnail']); 159 | } 160 | 161 | if (!empty($more['audio'])) { 162 | $more['audio'] = cmf_get_file_download_url($more['audio']); 163 | } 164 | 165 | if (!empty($more['video'])) { 166 | $more['video'] = cmf_get_file_download_url($more['video']); 167 | } 168 | 169 | if (!empty($more['photos'])) { 170 | foreach ($more['photos'] as $key => $value) { 171 | $more['photos'][$key]['url'] = cmf_get_image_url($value['url']); 172 | } 173 | } 174 | 175 | if (!empty($more['files'])) { 176 | foreach ($more['files'] as $key => $value) { 177 | $more['files'][$key]['url'] = cmf_get_file_download_url($value['url']); 178 | } 179 | } 180 | return $more; 181 | } 182 | 183 | /** 184 | * 获取用户文章 185 | */ 186 | public function getUserArticles($userId, $params) 187 | { 188 | $where = [ 189 | 'post_type' => 1, 190 | 'user_id' => $userId 191 | ]; 192 | 193 | $params['where'] = $where; 194 | 195 | return $this->getDatas($params);; 196 | } 197 | 198 | /** 199 | * 会员添加文章 200 | * @param array $data 文章数据 201 | * @return $this 202 | */ 203 | public function addArticle($data) 204 | { 205 | if (!empty($data['more'])) { 206 | $data['more'] = $this->setMoreUrl($data['more']); 207 | } 208 | if (!empty($data['thumbnail'])) { 209 | $data['more']['thumbnail'] = cmf_asset_relative_url($data['thumbnail']); 210 | } 211 | $this->allowField(true)->data($data, true)->isUpdate(false)->save(); 212 | $categories = $this->strToArr($data['categories']); 213 | $this->categories()->attach($categories); 214 | if (!empty($data['post_keywords']) && is_string($data['post_keywords'])) { 215 | //加入标签 216 | $data['post_keywords'] = str_replace(',', ',', $data['post_keywords']); 217 | $keywords = explode(',', $data['post_keywords']); 218 | $this->addTags($keywords, $this->id); 219 | } 220 | return $this; 221 | } 222 | 223 | /** 224 | * 会员文章编辑 225 | * @param array $data 文章数据 226 | * @param int $id 文章id 227 | * @param int $userId 文章所属用户id [可选] 228 | * @return boolean 成功 true 失败 false 229 | */ 230 | public function editArticle($data, $id, $userId = '') 231 | { 232 | if (!empty($userId)) { 233 | $isBelong = $this->isuserPost($id, $userId); 234 | if ($isBelong === false) { 235 | return $isBelong; 236 | } 237 | } 238 | if (!empty($data['more'])) { 239 | $data['more'] = $this->setMoreUrl($data['more']); 240 | } 241 | if (!empty($data['thumbnail'])) { 242 | $data['more']['thumbnail'] = cmf_asset_relative_url($data['thumbnail']); 243 | } 244 | $data['id'] = $id; 245 | $data['post_status'] = empty($data['post_status']) ? 0 : 1; 246 | $data['is_top'] = empty($data['is_top']) ? 0 : 1; 247 | $data['recommended'] = empty($data['recommended']) ? 0 : 1; 248 | $this->allowField(true)->data($data, true)->isUpdate(true)->save(); 249 | 250 | $categories = $this->strToArr($data['categories']); 251 | $oldCategoryIds = $this->categories()->column('category_id'); 252 | $sameCategoryIds = array_intersect($categories, $oldCategoryIds); 253 | $needDeleteCategoryIds = array_diff($oldCategoryIds, $sameCategoryIds); 254 | $newCategoryIds = array_diff($categories, $sameCategoryIds); 255 | if (!empty($needDeleteCategoryIds)) { 256 | $this->categories()->detach($needDeleteCategoryIds); 257 | } 258 | 259 | if (!empty($newCategoryIds)) { 260 | $this->categories()->attach(array_values($newCategoryIds)); 261 | } 262 | 263 | $keywords = []; 264 | 265 | if (!empty($data['post_keywords'])) { 266 | if (is_string($data['post_keywords'])) { 267 | //加入标签 268 | $data['post_keywords'] = str_replace(',', ',', $data['post_keywords']); 269 | $keywords = explode(',', $data['post_keywords']); 270 | } 271 | } 272 | 273 | $this->addTags($keywords, $data['id']); 274 | 275 | return $this; 276 | } 277 | 278 | /** 279 | * 根据文章关键字,增加标签 280 | * @param array $keywords 文章关键字数组 281 | * @param int $articleId 文章id 282 | * @return void 283 | */ 284 | public function addTags($keywords, $articleId) 285 | { 286 | foreach ($keywords as $key => $value) { 287 | $keywords[$key] = trim($value); 288 | } 289 | $continue = true; 290 | $names = $this->tags()->column('name'); 291 | if (!empty($keywords) || !empty($names)) { 292 | if (!empty($names)) { 293 | $sameNames = array_intersect($keywords, $names); 294 | $keywords = array_diff($keywords, $sameNames); 295 | $shouldDeleteNames = array_diff($names, $sameNames); 296 | if (!empty($shouldDeleteNames)) { 297 | $tagIdNames = $this->tags() 298 | ->where('name', 'in', $shouldDeleteNames) 299 | ->column('pivot.id', 'tag_id'); 300 | $tagIds = array_keys($tagIdNames); 301 | $tagPostIds = array_values($tagIdNames); 302 | $tagPosts = DB::name('portal_tag_post')->where('tag_id', 'in', $tagIds) 303 | ->field('id,tag_id,post_id') 304 | ->select(); 305 | $keepTagIds = []; 306 | foreach ($tagPosts as $key => $tagPost) { 307 | if ($articleId != $tagPost['post_id']) { 308 | array_push($keepTagIds, $tagPost['tag_id']); 309 | } 310 | } 311 | $keepTagIds = array_unique($keepTagIds); 312 | $shouldDeleteTagIds = array_diff($tagIds, $keepTagIds); 313 | DB::name('PortalTag')->delete($shouldDeleteTagIds); 314 | DB::name('PortalTagPost')->delete($tagPostIds); 315 | } 316 | } else { 317 | $tagIdNames = DB::name('portal_tag')->where('name', 'in', $keywords)->column('name', 'id'); 318 | if (!empty($tagIdNames)) { 319 | $tagIds = array_keys($tagIdNames); 320 | $this->tags()->attach($tagIds); 321 | $keywords = array_diff($keywords, array_values($tagIdNames)); 322 | if (empty($keywords)) { 323 | $continue = false; 324 | } 325 | } 326 | } 327 | if ($continue) { 328 | foreach ($keywords as $key => $value) { 329 | if (!empty($value)) { 330 | $this->tags()->attach(['name' => $value]); 331 | } 332 | } 333 | } 334 | } 335 | } 336 | 337 | /** 338 | * 获取图片附件url相对地址 339 | * 默认上传名字 *_names 地址 *_urls 340 | * @param $annex 上传附件 341 | * @return array 342 | */ 343 | public function setMoreUrl($annex) 344 | { 345 | $more = []; 346 | if (!empty($annex)) { 347 | foreach ($annex as $key => $value) { 348 | $nameArr = $key . '_names'; 349 | $urlArr = $key . '_urls'; 350 | if (is_string($value[$nameArr]) && is_string($value[$urlArr])) { 351 | $more[$key] = [$value[$nameArr], $value[$urlArr]]; 352 | } elseif (!empty($value[$nameArr]) && !empty($value[$urlArr])) { 353 | $more[$key] = []; 354 | foreach ($value[$urlArr] as $k => $url) { 355 | $url = cmf_asset_relative_url($url); 356 | array_push($more[$key], ['url' => $url, 'name' => $value[$nameArr][$k]]); 357 | } 358 | } 359 | } 360 | } 361 | return $more; 362 | } 363 | 364 | /** 365 | * 删除文章 366 | * @param $ids int|array 文章id 367 | * @param int $userId 文章所属用户id [可选] 368 | * @return bool|int 删除结果 true 成功 false 失败 -1 文章不存在 369 | */ 370 | public function deleteArticle($ids, $userId = '') 371 | { 372 | $time = time(); 373 | $result = false; 374 | $where = []; 375 | 376 | if (!empty($userId)) { 377 | if (is_numeric($ids)) { 378 | $article = $this->find($ids); 379 | if (!empty($article)) { 380 | if ($this->isUserPost($ids, $userId) || $userId == 1) { 381 | $where['id'] = $ids; 382 | } 383 | } 384 | } else { 385 | $ids = $this->strToArr($ids); 386 | $articles = $this->where('id', 'in', $ids)->select(); 387 | if (!empty($articles)) { 388 | $deleteIds = $this->isUserPosts($ids, $userId); 389 | if (!empty($deleteIds)) { 390 | $where['id'] = ['in', $deleteIds]; 391 | } 392 | } 393 | } 394 | } else { 395 | if (is_numeric($ids)) { 396 | $article = $this->find($ids); 397 | if (!empty($article)) { 398 | $where['id'] = $ids; 399 | } 400 | } else { 401 | $ids = $this->strToArr($ids); 402 | $articles = $this->where('id', 'in', $ids)->select(); 403 | if (!empty($articles)) { 404 | $where['id'] = ['in', $ids]; 405 | } 406 | } 407 | } 408 | if (empty($article) && empty($articles)) { 409 | return -1; 410 | } 411 | if (!empty($where)) { 412 | $result = $this->useGlobalScope(false) 413 | ->where($where) 414 | ->setField('delete_time', $time); 415 | } 416 | if ($result) { 417 | $data = [ 418 | 'create_time' => $time, 419 | 'table_name' => 'portal_post' 420 | ]; 421 | if (!empty($article)) { 422 | $data['name'] = $article['post_title']; 423 | $article->recycleBin()->save($data); 424 | } 425 | 426 | if (!empty($articles)) { 427 | foreach ($articles as $article) { 428 | $data['name'] = $article['post_title']; 429 | $article->recycleBin()->save($data); 430 | } 431 | } 432 | } 433 | return $result; 434 | } 435 | 436 | /** 437 | * 判断文章所属用户是否为当前用户,超级管理员除外 438 | * @params int $id 文章id 439 | * @param int $userId 当前用户id 440 | * @return boolean 是 true , 否 false 441 | */ 442 | public function isUserPost($id, $userId) 443 | { 444 | $postUserId = $this->useGlobalScope(false) 445 | ->getFieldById($id, 'user_id'); 446 | if ($postUserId == $userId || $userId == 1) { 447 | return true; 448 | } else { 449 | return false; 450 | } 451 | } 452 | 453 | /** 454 | * 过滤属于当前用户的文章,超级管理员除外 455 | * @params array $ids 文章id的数组 456 | * @param int $userId 当前用户id 457 | * @return array 属于当前用户的文章id 458 | */ 459 | public function isUserPosts($ids, $userId) 460 | { 461 | $postIds = $this->useGlobalScope(false) 462 | ->where('user_id', $userId) 463 | ->where('id', 'in', $ids) 464 | ->column('id'); 465 | return array_intersect($ids, $postIds); 466 | } 467 | } 468 | -------------------------------------------------------------------------------- /api/portal/model/PortalTagModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | use api\common\model\CommonModel; 13 | class PortalTagModel extends CommonModel 14 | { 15 | //可查询字段 16 | protected $visible = [ 17 | 'id','articles.id','recommended', 'post_count', 'name','articles' 18 | ]; 19 | //模型关联方法 20 | protected $relationFilter = ['articles']; 21 | 22 | /** 23 | * 基础查询 24 | */ 25 | protected function base($query) 26 | { 27 | $query->alias('post_tag')->where('post_tag.status', 1); 28 | } 29 | /** 30 | * 关联 文章表 31 | * @return $this 32 | */ 33 | public function articles() 34 | { 35 | return $this->belongsToMany('PortalPostModel','portal_tag_post','post_id','tag_id'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/portal/model/PortalTagPostModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | use think\Model; 13 | 14 | class PortalTagPostModel extends Model 15 | { 16 | /** 17 | * 获取指定id相关的文章id数组 18 | * @param $post_id 文章id 19 | * @return array 相关的文章id 20 | */ 21 | function getRelationPostIds($post_id) 22 | { 23 | $tagIds = $this->where('post_id', $post_id) 24 | ->column('tag_id'); 25 | $postIds = $this->whereIn('tag_id', $tagIds) 26 | ->column('post_id'); 27 | return array_unique($postIds); 28 | } 29 | } -------------------------------------------------------------------------------- /api/portal/model/RecycleBinModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\model; 10 | 11 | use think\Model; 12 | 13 | class RecycleBinModel extends Model 14 | { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /api/portal/model/UserModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | use api\common\model\CommonModel; 12 | 13 | class UserModel extends CommonModel 14 | { 15 | //可查询字段 16 | protected $visible = [ 17 | 'user_nickname', 'avatar', 'signature','user_url','user_login','birthday','sex' 18 | ]; 19 | //模型关联方法 20 | protected $relationFilter = ['user']; 21 | 22 | /** 23 | * 基础查询 24 | */ 25 | protected function base($query) 26 | { 27 | $query->alias('user')->where('user.user_status', 1); 28 | } 29 | 30 | /** 31 | * more 自动转化 32 | * @param $value 33 | * @return array 34 | */ 35 | public function getAvatarAttr($value) 36 | { 37 | $value = !empty($value) ? cmf_get_image_url($value) : $value; 38 | return $value; 39 | } 40 | 41 | /** 42 | * 关联 user表 43 | * @return $this 44 | */ 45 | public function user() 46 | { 47 | return $this->belongsTo('UserModel', 'user_id')->setEagerlyType(1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /api/portal/route.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\service; 10 | 11 | use api\portal\model\PortalPostModel as PortalPost; 12 | use api\portal\model\PortalCategoryModel as PortalCategory; 13 | 14 | class PortalPostModel extends PortalPost 15 | { 16 | protected $name = "portal_post"; 17 | 18 | /** 19 | * [recommendedList 推荐列表] 20 | * @Author: wuwu<15093565100@163.com> 21 | * @DateTime: 2017-07-17T11:06:47+0800 22 | * @since: 1.0 23 | * @param integer $next_id [最后索引值] 24 | * @param integer $num [一页多少条 默认10] 25 | * @return [type] [数据] 26 | */ 27 | public static function recommendedList($next_id = 0, $num = 10) 28 | { 29 | $limit = "{$next_id},{$num}"; 30 | $field = 'id,recommended,user_id,post_like,post_hits,comment_count,create_time,update_time,published_time,post_title,post_excerpt,more'; 31 | $list = self::with('user')->field($field)->where('recommended', 1)->order('published_time DESC')->limit($limit)->select(); 32 | return $list; 33 | } 34 | 35 | /** 36 | * [categoryPostList 分类文章列表] 37 | * @Author: wuwu<15093565100@163.com> 38 | * @DateTime: 2017-07-17T15:16:26+0800 39 | * @since: 1.0 40 | * @param [type] $category_id [分类ID] 41 | * @param integer $next_id [limit索引] 42 | * @param integer $num [limit每页数量] 43 | * @return [type] [description] 44 | */ 45 | public static function categoryPostList($category_id, $next_id = 0, $num = 10) 46 | { 47 | $limit = "{$next_id},{$num}"; 48 | $Postlist = PortalCategory::categoryPostIds($category_id); 49 | $field = 'id,recommended,user_id,post_like,post_hits,comment_count,create_time,update_time,published_time,post_title,post_excerpt,more'; 50 | $list = self::with('user')->field($field)->whereIn('id', $Postlist['PostIds'])->order('published_time DESC')->limit($limit)->select()->toJson(); 51 | return $list; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /api/portal/validate/ArticlesValidate.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace api\portal\validate; 12 | 13 | use think\Validate; 14 | 15 | class ArticlesValidate extends Validate 16 | { 17 | protected $rule = [ 18 | 'post_title' => 'require', 19 | 'post_content' => 'require', 20 | 'categories' => 'require' 21 | ]; 22 | protected $message = [ 23 | 'post_title.require' => '文章标题不能为空', 24 | 'post_content.require' => '内容不能为空', 25 | 'categories.require' => '文章分类不能为空' 26 | ]; 27 | 28 | protected $scene = [ 29 | 'article' => [ 'post_title' , 'post_content' , 'categories' ], 30 | 'page' => ['post_title'] 31 | ]; 32 | } -------------------------------------------------------------------------------- /api/release.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | return [ 13 | // 应用调试模式 14 | 'app_debug' => false, 15 | // 应用Trace 16 | 'app_trace' => false, 17 | 18 | ]; -------------------------------------------------------------------------------- /api/route.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | $apps = cmf_scan_dir(APP_PATH . '*', GLOB_ONLYDIR); 10 | 11 | foreach ($apps as $app) { 12 | $routeFile = APP_PATH . $app . '/route.php'; 13 | 14 | if (file_exists($routeFile)) { 15 | include_once $routeFile; 16 | } 17 | 18 | } 19 | 20 | 21 | if (file_exists(CMF_ROOT . "data/conf/route.php")) { 22 | $runtimeRoutes = include CMF_ROOT . "data/conf/route.php"; 23 | } else { 24 | $runtimeRoutes = []; 25 | } 26 | 27 | return $runtimeRoutes; -------------------------------------------------------------------------------- /api/tags.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | // 应用行为扩展定义文件 11 | return [ 12 | // 应用初始化 13 | 'app_init' => [ 14 | 'cmf\\behavior\\InitHookBehavior', 15 | ], 16 | // 应用开始 17 | 'app_begin' => [ 18 | 'cmf\\behavior\\LangBehavior', 19 | ], 20 | // 模块初始化 21 | 'module_init' => [], 22 | // 操作开始执行 23 | 'action_begin' => [], 24 | // 视图内容过滤 25 | 'view_filter' => [], 26 | // 日志写入 27 | 'log_write' => [], 28 | // 应用结束 29 | 'app_end' => [], 30 | ]; 31 | -------------------------------------------------------------------------------- /api/user/controller/CommentsController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-7-26 12 | // +---------------------------------------------------------------------- 13 | namespace api\user\controller; 14 | 15 | use api\user\model\CommentModel as Comment; 16 | use api\user\model\UserModel as User; 17 | use cmf\controller\RestBaseController; 18 | 19 | class CommentsController extends RestBaseController 20 | { 21 | 22 | /** 23 | * [getUserComments 获取用户评论] 24 | * @Author: wuwu<15093565100@163.com> 25 | * @DateTime: 2017-05-25T20:48:53+0800 26 | * @since: 1.0 27 | * @return [array_json] [获取Comment] 28 | */ 29 | public function getUserComments() 30 | { 31 | $input = $this->request->param(); 32 | 33 | $comment = new Comment(); 34 | $map['where']['user_id'] = $this->getUserId(); 35 | $map['order'] = '-create_time'; 36 | $map['relation'] = 'user,to_user'; 37 | if (!empty($input['page'])) { 38 | $map['page'] = $input['page']; 39 | } 40 | //处理不同的情况 41 | $data = $comment->getDatas($map); 42 | 43 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 44 | $response = [$data]; 45 | } else { 46 | $response = ['list' => $data]; 47 | } 48 | 49 | $this->success('请求成功', $response); 50 | 51 | } 52 | 53 | /** 54 | * [getComments 获取评论] 55 | * @Author: wuwu<15093565100@163.com> 56 | * @DateTime: 2017-05-25T20:48:53+0800 57 | * @since: 1.0 58 | * @return [array_json] [获取Comment] 59 | */ 60 | public function getComments() 61 | { 62 | $input = $this->request->param(); 63 | $id = $this->request->has('object_id') ? $input['object_id'] : $this->error('id参数不存在'); 64 | $table = $this->request->has('table_name') ? $input['table_name'] : $this->error('table参数不存在'); 65 | $comment = new Comment(); 66 | $map['where'] = [ 67 | 'object_id' => $id, 68 | 'table_name' => $table 69 | ]; 70 | $map['relation'] = 'user,to_user'; 71 | 72 | if (!empty($input['page'])) { 73 | $map['page'] = $input['page']; 74 | } 75 | 76 | $data = $comment->getDatas($map); 77 | 78 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 79 | $response = [$data]; 80 | } else { 81 | $response = ['list' => $data]; 82 | } 83 | 84 | //数据是否存在 85 | if ($data->isEmpty()) { 86 | $this->error('评论数据为空'); 87 | } else { 88 | $this->success('评论获取成功!', $response); 89 | } 90 | } 91 | 92 | /** 93 | * [delComments 删除评论] 94 | * @Author: wuwu<15093565100@163.com> 95 | * @DateTime: 2017-08-11T22:08:56+0800 96 | * @since: 1.0 97 | * @return 98 | */ 99 | public function delComments() 100 | { 101 | $input = $this->request->param(); 102 | $id = $this->request->has('id') ? intval($input['id']) : $this->error('id参数不存在'); 103 | $userId = $this->getUserId(); 104 | Comment::destroy(['id' => $id, 'user_id' => $userId]); 105 | 106 | $this->success('删除成功'); 107 | } 108 | 109 | /** 110 | * [setComments 添加评论] 111 | * @Author: wuwu<15093565100@163.com> 112 | * @DateTime: 2017-08-16T01:07:44+0800 113 | * @since: 1.0 114 | */ 115 | public function setComments() 116 | { 117 | $data = $this->_setComments(); 118 | if ($res = Comment::setComment($data)) { 119 | $this->success('评论成功', $res); 120 | } else { 121 | $this->error('评论失败'); 122 | } 123 | } 124 | 125 | /** 126 | * [_setComments 评论数据组织] 127 | * @Author: wuwu<15093565100@163.com> 128 | * @DateTime: 2017-08-16T01:00:02+0800 129 | * @since: 1.0 130 | */ 131 | protected function _setComments() 132 | { 133 | $input = $this->request->param(); 134 | $data['object_id'] = $this->request->has('object_id') ? $input['object_id'] : $this->error('object_id参数不存在'); 135 | $data['table_name'] = $this->request->has('table_name') ? $input['table_name'] : $this->error('table_name参数不存在'); 136 | $data['url'] = $this->request->has('url') ? $input['url'] : $this->error('url参数不存在'); 137 | $data['content'] = $this->request->has('content') ? $input['content'] : $this->error('内容不为空'); 138 | $data['parent_id'] = $this->request->has('parent_id') ? $input['parent_id'] : 0; 139 | $result = $this->validate($data, 140 | [ 141 | 'object_id' => 'require|number', 142 | 'content' => 'require', 143 | ]); 144 | if (true !== $result) { 145 | // 验证失败 输出错误信息 146 | $this->error($result); 147 | } 148 | $data['delete_time'] = 0; 149 | $data['create_time'] = time(); 150 | if ($data['parent_id']) { 151 | $res = Comment::field(['parent_id', 'path', 'user_id'])->find($data['parent_id']); 152 | if ($res) { 153 | $data['path'] = $res['path'] . $data['parent_id'] . ','; 154 | $data['to_user_id'] = $res['user_id']; 155 | } else { 156 | $this->error('回复的评论不存在'); 157 | } 158 | } else { 159 | $data['path'] = '0,'; 160 | } 161 | $data['user_id'] = $this->getUserId(); 162 | $userData = User::field(true)->find($data['user_id']); 163 | if (!$userData) { 164 | $this->error('评论用户不存在'); 165 | } 166 | 167 | $data['full_name'] = $userData['user_nickname']; 168 | $data['email'] = $userData['user_email']; 169 | return $data; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /api/user/controller/FavoritesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\user\controller; 11 | 12 | use api\user\model\UserFavoriteModel; 13 | use cmf\controller\RestBaseController; 14 | use think\Validate; 15 | 16 | class FavoritesController extends RestBaseController 17 | { 18 | protected $userFavoriteModel; 19 | 20 | public function __construct(UserFavoriteModel $userFavoriteModel) 21 | { 22 | parent::__construct(); 23 | $this->userFavoriteModel = $userFavoriteModel; 24 | } 25 | 26 | /** 27 | * 显示收藏列表 28 | */ 29 | public function getFavorites() 30 | { 31 | $userId = $this->getUserId(); 32 | 33 | $param = $this->request->param(); 34 | $param['where'] = [ 35 | 'user_id' => $userId 36 | ]; 37 | $param['order'] = '-create_time'; 38 | 39 | $favoriteData = $this->userFavoriteModel->getDatas($param); 40 | 41 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 42 | $response = $favoriteData; 43 | } else { 44 | $response = ['list' => $favoriteData,]; 45 | } 46 | $this->success('请求成功', $response); 47 | } 48 | 49 | /** 50 | * [setFavorites 添加收藏] 51 | * @Author: wuwu<15093565100@163.com> 52 | * @DateTime: 2017-08-03T09:03:40+0800 53 | * @since: 1.0 54 | */ 55 | public function setFavorites() 56 | { 57 | $input = $this->request->param(); 58 | 59 | //组装数据 60 | $data = $this->_FavoritesObject($input['title'], $input['url'], $input['description'], $input['table_name'], $input['object_id']); 61 | if (!$data) { 62 | $this->error('收藏失败'); 63 | } 64 | if ($this->userFavoriteModel->where(['user_id' => $this->getUserId(), 'object_id' => $input['object_id']])->where('table_name', $input['table_name'])->count() > 0) { 65 | $this->error('已收藏', ['code' => 1]); 66 | } 67 | 68 | $favoriteId = $this->userFavoriteModel->setFavorite($data); 69 | if ($favoriteId) { 70 | $this->success('收藏成功', ['id' => $favoriteId]); 71 | } else { 72 | $this->error('收藏失败'); 73 | } 74 | 75 | } 76 | 77 | /** 78 | * [_FavoritesObject 收藏数据组装] 79 | * @Author: wuwu<15093565100@163.com> 80 | * @DateTime: 2017-08-03T09:39:06+0800 81 | * @since: 1.0 82 | * @return [type] [description] 83 | */ 84 | protected function _FavoritesObject($title, $url, $description, $table_name, $object_id) 85 | { 86 | $data['user_id'] = $this->getUserId(); 87 | $data['create_time'] = THINK_START_TIME; 88 | 89 | if (empty($title)) { 90 | return false; 91 | } else if (empty($url)) { 92 | return false; 93 | } elseif (empty($table_name)) { 94 | return false; 95 | } elseif (empty($object_id)) { 96 | return false; 97 | } 98 | $data['title'] = $title; 99 | $data['url'] = htmlspecialchars_decode($url); 100 | $data['description'] = $description; 101 | $data['table_name'] = $table_name; 102 | $data['object_id'] = $object_id; 103 | return $data; 104 | } 105 | 106 | /** 107 | * [unsetFavorites 取消收藏] 108 | * @Author: wuwu<15093565100@163.com> 109 | * @DateTime: 2017-08-03T09:04:31+0800 110 | * @since: 1.0 111 | * @return [type] [description] 112 | */ 113 | public function unsetFavorites() 114 | { 115 | $id = $this->request->param('id', 0, 'intval'); 116 | $userId = $this->getUserId(); 117 | 118 | $count = $this->userFavoriteModel->where(['id' => $id, 'user_id' => $userId])->count(); 119 | 120 | if ($count == 0) { 121 | $this->error('收藏不存在,无法取消'); 122 | } 123 | 124 | $this->userFavoriteModel->where(['id' => $id])->delete(); 125 | 126 | $this->success('取消成功'); 127 | 128 | } 129 | 130 | /** 131 | * 判断是否已经收藏 132 | * @throws \think\db\exception\DataNotFoundException 133 | * @throws \think\db\exception\ModelNotFoundException 134 | * @throws \think\exception\DbException 135 | */ 136 | public function hasFavorite() 137 | { 138 | $input = $this->request->param(); 139 | 140 | $validate = new Validate([ 141 | 'table_name' => 'require', 142 | 'object_id' => 'require', 143 | ]); 144 | 145 | if (!$validate->check($input)) { 146 | $this->error($validate->getError()); 147 | } 148 | 149 | $userId = $this->userId; 150 | 151 | if (empty($this->userId)) { 152 | $this->error('用户登录'); 153 | } 154 | 155 | 156 | $findFavorite = $this->userFavoriteModel->where([ 157 | 'table_name' => $input['table_name'], 158 | 'user_id' => $userId, 159 | 'object_id' => intval($input['object_id']) 160 | ])->find(); 161 | 162 | if ($findFavorite) { 163 | $this->success('success', $findFavorite); 164 | } else { 165 | $this->error('用户未收藏'); 166 | } 167 | 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /api/user/controller/ProfileController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\user\controller; 10 | 11 | use cmf\controller\RestUserBaseController; 12 | use think\Db; 13 | use think\Validate; 14 | 15 | class ProfileController extends RestUserBaseController 16 | { 17 | // 用户密码修改 18 | public function changePassword() 19 | { 20 | $validate = new Validate([ 21 | 'old_password' => 'require', 22 | 'password' => 'require', 23 | 'confirm_password' => 'require|confirm:password' 24 | ]); 25 | 26 | $validate->message([ 27 | 'old_password.require' => '请输入您的旧密码!', 28 | 'password.require' => '请输入您的新密码!', 29 | 'confirm_password.require' => '请输入确认密码!', 30 | 'confirm_password.confirm' => '两次输入的密码不一致!' 31 | ]); 32 | 33 | $data = $this->request->param(); 34 | if (!$validate->check($data)) { 35 | $this->error($validate->getError()); 36 | } 37 | 38 | $userId = $this->getUserId(); 39 | $userPassword = Db::name("user")->where('id', $userId)->value('user_pass'); 40 | 41 | if (!cmf_compare_password($data['old_password'], $userPassword)) { 42 | $this->error('旧密码不正确!'); 43 | } 44 | 45 | Db::name("user")->where('id', $userId)->update(['user_pass' => cmf_password($data['password'])]); 46 | 47 | $this->success("密码修改成功!"); 48 | 49 | } 50 | 51 | // 用户绑定邮箱 52 | public function bindingEmail() 53 | { 54 | $validate = new Validate([ 55 | 'email' => 'require|email|unique:user,user_email', 56 | 'verification_code' => 'require' 57 | ]); 58 | 59 | $validate->message([ 60 | 'email.require' => '请输入您的邮箱!', 61 | 'email.email' => '请输入正确的邮箱格式!', 62 | 'email.unique' => '邮箱账号已存在!', 63 | 'verification_code.require' => '请输入数字验证码!' 64 | ]); 65 | 66 | $data = $this->request->param(); 67 | if (!$validate->check($data)) { 68 | $this->error($validate->getError()); 69 | } 70 | 71 | $userId = $this->getUserId(); 72 | $userEmail = Db::name("user")->where('id', $userId)->value('user_email'); 73 | 74 | if (!empty($userEmail)) { 75 | $this->error("您已经绑定邮箱!"); 76 | } 77 | 78 | $errMsg = cmf_check_verification_code($data['email'], $data['verification_code']); 79 | if (!empty($errMsg)) { 80 | $this->error($errMsg); 81 | } 82 | 83 | Db::name("user")->where('id', $userId)->update(['user_email' => $data['email']]); 84 | 85 | $this->success("绑定成功!"); 86 | } 87 | 88 | // 用户绑定手机号 89 | public function bindingMobile() 90 | { 91 | $validate = new Validate([ 92 | 'mobile' => 'require|unique:user,mobile', 93 | 'verification_code' => 'require' 94 | ]); 95 | 96 | $validate->message([ 97 | 'mobile.require' => '请输入您的手机号!', 98 | 'mobile.unique' => '手机号已经存在!', 99 | 'verification_code.require' => '请输入数字验证码!' 100 | ]); 101 | 102 | $data = $this->request->param(); 103 | if (!$validate->check($data)) { 104 | $this->error($validate->getError()); 105 | } 106 | 107 | if (!cmf_check_mobile($data['mobile'])) { 108 | $this->error("请输入正确的手机格式!"); 109 | } 110 | 111 | 112 | $userId = $this->getUserId(); 113 | $mobile = Db::name("user")->where('id', $userId)->value('mobile'); 114 | 115 | if (!empty($mobile)) { 116 | $this->error("您已经绑定手机!"); 117 | } 118 | 119 | $errMsg = cmf_check_verification_code($data['mobile'], $data['verification_code']); 120 | if (!empty($errMsg)) { 121 | $this->error($errMsg); 122 | } 123 | 124 | Db::name("user")->where('id', $userId)->update(['mobile' => $data['mobile']]); 125 | 126 | $this->success("绑定成功!"); 127 | } 128 | 129 | /** 130 | * 用户基本信息获取及修改 131 | * @param 请求为GET 获取信息 132 | * @param [string] $[field] [要获取的一个或多个字段名] 可选 133 | * @return 带参数,返回某个或多个字段信息。不带参数,返回所有信息 134 | * @param 请求为POST 修改信息 135 | */ 136 | public function userInfo($field = '') 137 | { 138 | //判断请求为GET,获取信息 139 | if ($this->request->isGet()) { 140 | $userId = $this->getUserId(); 141 | $fieldStr = 'user_type,user_login,mobile,user_email,user_nickname,avatar,signature,user_url,sex,birthday,score,coin,user_status,user_activation_key,create_time,last_login_time,last_login_ip'; 142 | if (empty($field)) { 143 | $userData = Db::name("user")->field($fieldStr)->find($userId); 144 | } else { 145 | $fieldArr = explode(',', $fieldStr); 146 | $postFieldArr = explode(',', $field); 147 | $mixedField = array_intersect($fieldArr, $postFieldArr); 148 | if (empty($mixedField)) { 149 | $this->error('您查询的信息不存在!'); 150 | } 151 | if (count($mixedField) > 1) { 152 | $fieldStr = implode(',', $mixedField); 153 | $userData = Db::name("user")->field($fieldStr)->find($userId); 154 | } else { 155 | $userData = Db::name("user")->where('id', $userId)->value($mixedField); 156 | } 157 | } 158 | $this->success('获取成功!', $userData); 159 | } 160 | //判断请求为POST,修改信息 161 | if ($this->request->isPost()) { 162 | $userId = $this->getUserId(); 163 | $fieldStr = 'user_nickname,avatar,signature,user_url,sex,birthday'; 164 | $data = $this->request->post(); 165 | if (empty($data)) { 166 | $this->error('修改失败,提交表单为空!'); 167 | } 168 | 169 | if (!empty($data['birthday'])) { 170 | $data['birthday'] = strtotime($data['birthday']); 171 | } 172 | 173 | $upData = Db::name("user")->where('id', $userId)->field($fieldStr)->update($data); 174 | if ($upData !== false) { 175 | $this->success('修改成功!'); 176 | } else { 177 | $this->error('修改失败!'); 178 | } 179 | } 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /api/user/controller/PublicController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\user\controller; 10 | 11 | use think\Db; 12 | use think\Validate; 13 | use cmf\controller\RestBaseController; 14 | 15 | class PublicController extends RestBaseController 16 | { 17 | // 用户注册 18 | public function register() 19 | { 20 | $validate = new Validate([ 21 | 'username' => 'require', 22 | 'password' => 'require', 23 | 'verification_code' => 'require' 24 | ]); 25 | 26 | $validate->message([ 27 | 'username.require' => '请输入手机号,邮箱!', 28 | 'password.require' => '请输入您的密码!', 29 | 'verification_code.require' => '请输入数字验证码!' 30 | ]); 31 | 32 | $data = $this->request->param(); 33 | if (!$validate->check($data)) { 34 | $this->error($validate->getError()); 35 | } 36 | 37 | $user = []; 38 | 39 | $findUserWhere = []; 40 | 41 | if (Validate::is($data['username'], 'email')) { 42 | $user['user_email'] = $data['username']; 43 | $findUserWhere['user_email'] = $data['username']; 44 | } else if (cmf_check_mobile($data['username'])) { 45 | $user['mobile'] = $data['username']; 46 | $findUserWhere['mobile'] = $data['username']; 47 | } else { 48 | $this->error("请输入正确的手机或者邮箱格式!"); 49 | } 50 | 51 | $errMsg = cmf_check_verification_code($data['username'], $data['verification_code']); 52 | if (!empty($errMsg)) { 53 | $this->error($errMsg); 54 | } 55 | 56 | $findUserCount = Db::name("user")->where($findUserWhere)->count(); 57 | 58 | if ($findUserCount > 0) { 59 | $this->error("此账号已存在!"); 60 | } 61 | 62 | $user['create_time'] = time(); 63 | $user['user_status'] = 1; 64 | $user['user_type'] = 2; 65 | $user['user_pass'] = cmf_password($data['password']); 66 | 67 | $result = Db::name("user")->insert($user); 68 | 69 | 70 | if (empty($result)) { 71 | $this->error("注册失败,请重试!"); 72 | } 73 | 74 | $this->success("注册并激活成功,请登录!"); 75 | 76 | } 77 | 78 | // 用户登录 TODO 增加最后登录信息记录,如 ip 79 | public function login() 80 | { 81 | $validate = new Validate([ 82 | 'username' => 'require', 83 | 'password' => 'require' 84 | ]); 85 | $validate->message([ 86 | 'username.require' => '请输入手机号,邮箱或用户名!', 87 | 'password.require' => '请输入您的密码!' 88 | ]); 89 | 90 | $data = $this->request->param(); 91 | if (!$validate->check($data)) { 92 | $this->error($validate->getError()); 93 | } 94 | 95 | $findUserWhere = []; 96 | 97 | if (Validate::is($data['username'], 'email')) { 98 | $findUserWhere['user_email'] = $data['username']; 99 | } else if (cmf_check_mobile($data['username'])) { 100 | $findUserWhere['mobile'] = $data['username']; 101 | } else { 102 | $findUserWhere['user_login'] = $data['username']; 103 | } 104 | 105 | $findUser = Db::name("user")->where($findUserWhere)->find(); 106 | 107 | if (empty($findUser)) { 108 | $this->error("用户不存在!"); 109 | } else { 110 | 111 | switch ($findUser['user_status']) { 112 | case 0: 113 | $this->error('您已被拉黑!'); 114 | case 2: 115 | $this->error('账户还没有验证成功!'); 116 | } 117 | 118 | if (!cmf_compare_password($data['password'], $findUser['user_pass'])) { 119 | $this->error("密码不正确!"); 120 | } 121 | } 122 | 123 | $allowedDeviceTypes = $this->allowedDeviceTypes; 124 | 125 | if (empty($data['device_type']) || !in_array($data['device_type'], $allowedDeviceTypes)) { 126 | $this->error("请求错误,未知设备!"); 127 | } 128 | 129 | $userTokenQuery = Db::name("user_token") 130 | ->where('user_id', $findUser['id']) 131 | ->where('device_type', $data['device_type']); 132 | $findUserToken = $userTokenQuery->find(); 133 | $currentTime = time(); 134 | $expireTime = $currentTime + 24 * 3600 * 180; 135 | $token = md5(uniqid()) . md5(uniqid()); 136 | if (empty($findUserToken)) { 137 | $result = $userTokenQuery->insert([ 138 | 'token' => $token, 139 | 'user_id' => $findUser['id'], 140 | 'expire_time' => $expireTime, 141 | 'create_time' => $currentTime, 142 | 'device_type' => $data['device_type'] 143 | ]); 144 | } else { 145 | $result = $userTokenQuery 146 | ->where('user_id', $findUser['id']) 147 | ->where('device_type', $data['device_type']) 148 | ->update([ 149 | 'token' => $token, 150 | 'expire_time' => $expireTime, 151 | 'create_time' => $currentTime 152 | ]); 153 | } 154 | 155 | 156 | if (empty($result)) { 157 | $this->error("登录失败!"); 158 | } 159 | 160 | $this->success("登录成功!", ['token' => $token, 'user' => $findUser]); 161 | } 162 | 163 | // 用户退出 164 | public function logout() 165 | { 166 | $userId = $this->getUserId(); 167 | Db::name('user_token')->where([ 168 | 'token' => $this->token, 169 | 'user_id' => $userId, 170 | 'device_type' => $this->deviceType 171 | ])->update(['token' => '']); 172 | 173 | $this->success("退出成功!"); 174 | } 175 | 176 | // 用户密码重置 177 | public function passwordReset() 178 | { 179 | $validate = new Validate([ 180 | 'username' => 'require', 181 | 'password' => 'require', 182 | 'verification_code' => 'require' 183 | ]); 184 | 185 | $validate->message([ 186 | 'username.require' => '请输入手机号,邮箱!', 187 | 'password.require' => '请输入您的密码!', 188 | 'verification_code.require' => '请输入数字验证码!' 189 | ]); 190 | 191 | $data = $this->request->param(); 192 | if (!$validate->check($data)) { 193 | $this->error($validate->getError()); 194 | } 195 | 196 | $userWhere = []; 197 | if (Validate::is($data['username'], 'email')) { 198 | $userWhere['user_email'] = $data['username']; 199 | } else if (cmf_check_mobile($data['username'])) { 200 | $userWhere['mobile'] = $data['username']; 201 | } else { 202 | $this->error("请输入正确的手机或者邮箱格式!"); 203 | } 204 | 205 | $errMsg = cmf_check_verification_code($data['username'], $data['verification_code']); 206 | if (!empty($errMsg)) { 207 | $this->error($errMsg); 208 | } 209 | 210 | $userPass = cmf_password($data['password']); 211 | Db::name("user")->where($userWhere)->update(['user_pass' => $userPass]); 212 | 213 | $this->success("密码重置成功,请使用新密码登录!"); 214 | 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /api/user/controller/UploadController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\user\controller; 10 | 11 | use cmf\controller\RestUserBaseController; 12 | use think\Db; 13 | 14 | class UploadController extends RestUserBaseController 15 | { 16 | // 上传一个文件 17 | public function one() 18 | { 19 | $file = $this->request->file('file'); 20 | // 移动到框架应用根目录/public/upload/ 目录下 21 | $info = $file->validate([ 22 | /*'size' => 15678,*/ 23 | 'ext' => 'jpg,png,gif' 24 | ]); 25 | $fileMd5 = $info->md5(); 26 | $fileSha1 = $info->sha1(); 27 | 28 | $findFile = Db::name("asset")->where('file_md5', $fileMd5)->where('file_sha1', $fileSha1)->find(); 29 | 30 | if (!empty($findFile)) { 31 | $this->success("上传成功!", ['url' => $findFile['file_path'], 'filename' => $findFile['filename']]); 32 | } 33 | $info = $info->move(ROOT_PATH . 'public' . DS . 'upload'); 34 | if ($info) { 35 | $saveName = $info->getSaveName(); 36 | $originalName = $info->getInfo('name');//name,type,size 37 | $fileSize = $info->getInfo('size'); 38 | $suffix = $info->getExtension(); 39 | 40 | $fileKey = $fileMd5 . md5($fileSha1); 41 | 42 | $userId = $this->getUserId(); 43 | Db::name('asset')->insert([ 44 | 'user_id' => $userId, 45 | 'file_key' => $fileKey, 46 | 'filename' => $originalName, 47 | 'file_size' => $fileSize, 48 | 'file_path' => $saveName, 49 | 'file_md5' => $fileMd5, 50 | 'file_sha1' => $fileSha1, 51 | 'create_time' => time(), 52 | 'suffix' => $suffix 53 | ]); 54 | 55 | $this->success("上传成功!", ['url' => $saveName, 'filename' => $originalName]); 56 | } else { 57 | // 上传失败获取错误信息 58 | $this->error($file->getError()); 59 | } 60 | 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /api/user/controller/VerificationCodeController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace api\user\controller; 12 | 13 | use cmf\controller\RestBaseController; 14 | use think\Validate; 15 | use think\View; 16 | 17 | class VerificationCodeController extends RestBaseController 18 | { 19 | public function send() 20 | { 21 | $validate = new Validate([ 22 | 'username' => 'require', 23 | ]); 24 | 25 | $validate->message([ 26 | 'username.require' => '请输入手机号或邮箱!', 27 | ]); 28 | 29 | $data = $this->request->param(); 30 | if (!$validate->check($data)) { 31 | $this->error($validate->getError()); 32 | } 33 | 34 | $accountType = ''; 35 | 36 | if (Validate::is($data['username'], 'email')) { 37 | $accountType = 'email'; 38 | } else if (cmf_check_mobile($data['username'])) { 39 | $accountType = 'mobile'; 40 | } else { 41 | $this->error("请输入正确的手机或者邮箱格式!"); 42 | } 43 | 44 | //TODO 限制 每个ip 的发送次数 45 | 46 | $code = cmf_get_verification_code($data['username']); 47 | if (empty($code)) { 48 | $this->error("验证码发送过多,请明天再试!"); 49 | } 50 | 51 | if ($accountType == 'email') { 52 | 53 | $emailTemplate = cmf_get_option('email_template_verification_code'); 54 | 55 | $user = cmf_get_current_user(); 56 | $username = empty($user['user_nickname']) ? $user['user_login'] : $user['user_nickname']; 57 | 58 | $message = htmlspecialchars_decode($emailTemplate['template']); 59 | $view = new View(); 60 | $message = $view->display($message, ['code' => $code, 'username' => $username]); 61 | $subject = empty($emailTemplate['subject']) ? 'ThinkCMF验证码' : $emailTemplate['subject']; 62 | $result = cmf_send_email($data['username'], $subject, $message); 63 | 64 | if (empty($result['error'])) { 65 | cmf_verification_code_log($data['username'], $code); 66 | $this->success("验证码已经发送成功!"); 67 | } else { 68 | $this->error("邮箱验证码发送失败:" . $result['message']); 69 | } 70 | 71 | } else if ($accountType == 'mobile') { 72 | 73 | $param = ['mobile' => $data['username'], 'code' => $code]; 74 | $result = hook_one("send_mobile_verification_code", $param); 75 | 76 | if ($result !== false && !empty($result['error'])) { 77 | $this->error($result['message']); 78 | } 79 | 80 | if ($result === false) { 81 | $this->error('未安装验证码发送插件,请联系管理员!'); 82 | } 83 | 84 | cmf_verification_code_log($data['username'], $code); 85 | 86 | if (!empty($result['message'])) { 87 | $this->success($result['message']); 88 | } else { 89 | $this->success('验证码已经发送成功!'); 90 | } 91 | 92 | } 93 | 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /api/user/model/CommentModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-7-29 12 | // +---------------------------------------------------------------------- 13 | 14 | namespace api\user\model; 15 | 16 | use api\common\model\CommonModel; 17 | use think\Db; 18 | 19 | class CommentModel extends CommonModel 20 | { 21 | 22 | //模型关联方法 23 | protected $relationFilter = ['user', 'to_user']; 24 | 25 | /** 26 | * 基础查询 27 | */ 28 | protected function base($query) 29 | { 30 | $query->where('delete_time', 0) 31 | ->where('status', 1); 32 | } 33 | 34 | /** 35 | * post_content 自动转化 36 | * @param $value 37 | * @return string 38 | */ 39 | public function getContentAttr($value) 40 | { 41 | return cmf_replace_content_file_url(htmlspecialchars_decode($value)); 42 | } 43 | 44 | /** 45 | * more 自动转化 46 | * @param $value 47 | * @return array 48 | */ 49 | public function getMoreAttr($value) 50 | { 51 | if (empty($value)) { 52 | return null; 53 | } 54 | 55 | $more = json_decode($value, true); 56 | if (!empty($more['thumbnail'])) { 57 | $more['thumbnail'] = cmf_get_image_url($more['thumbnail']); 58 | } 59 | 60 | if (!empty($more['photos'])) { 61 | foreach ($more['photos'] as $key => $value) { 62 | $more['photos'][$key]['url'] = cmf_get_image_url($value['url']); 63 | } 64 | } 65 | 66 | if (!empty($more['files'])) { 67 | foreach ($more['files'] as $key => $value) { 68 | $more['files'][$key]['url'] = cmf_get_image_url($value['url']); 69 | } 70 | } 71 | return $more; 72 | } 73 | 74 | /** 75 | * 关联 user表 76 | * @return $this 77 | */ 78 | public function user() 79 | { 80 | return $this->belongsTo('UserModel', 'user_id'); 81 | } 82 | 83 | public function toUser() 84 | { 85 | return $this->belongsTo('UserModel', 'to_user_id'); 86 | } 87 | 88 | /** 89 | * [CommentList 评论列表获取] 90 | * @Author: wuwu<15093565100@163.com> 91 | * @DateTime: 2017-05-25T20:52:27+0800 92 | * @since: 1.0 93 | */ 94 | public function CommentList($map, $limit, $order) 95 | { 96 | if (empty($map)) { 97 | return []; 98 | } 99 | $data = $this->with('to_user')->field(true)->where($map)->order($order)->limit($limit)->select(); 100 | return $data; 101 | } 102 | 103 | /** 104 | * [setComment 添加评论] 105 | * @Author: wuwu<15093565100@163.com> 106 | * @DateTime: 2017-08-15T23:57:04+0800 107 | * @since: 1.0 108 | */ 109 | public static function setComment($data) 110 | { 111 | if (!$data) { 112 | return false; 113 | } 114 | 115 | if ($obj = self::create($data)) { 116 | $objectId = intval($data['object_id']); 117 | try { 118 | $pk = Db::name($data['table_name'])->getPk(); 119 | 120 | Db::name($data['table_name'])->where([$pk => $objectId])->setInc('comment_count'); 121 | 122 | Db::name($data['table_name'])->where([$pk => $objectId])->update(['last_comment' => time()]); 123 | 124 | } catch (\Exception $e) { 125 | 126 | } 127 | return $obj->id; 128 | } else { 129 | return false; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /api/user/model/RecycleBinModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\user\model; 10 | 11 | use think\Model; 12 | 13 | class RecycleBinModel extends Model 14 | { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /api/user/model/UserFavoriteModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\user\model; 11 | 12 | use api\common\model\CommonModel; 13 | 14 | class UserFavoriteModel extends CommonModel 15 | { 16 | 17 | /** 18 | * 关联表 19 | * @param string $table_name [关联表名] 20 | * @return \think\model\relation\HasOne 21 | */ 22 | protected function unionTable($table_name) 23 | { 24 | return $this->hasOne($table_name . 'Model', 'object_id'); 25 | } 26 | 27 | /** 28 | * thumbnail 自动转化图片地址为绝对地址 29 | * @param $value 30 | * @return string 31 | */ 32 | public function getThumbnailAttr($value) 33 | { 34 | if (!empty($value)) { 35 | $value = cmf_get_image_url($value); 36 | } 37 | 38 | return $value; 39 | } 40 | 41 | /** 42 | * url 自动转化 43 | * @param $value 44 | * @return string 45 | */ 46 | public function getUrlAttr($value) 47 | { 48 | $url = json_decode($value, true); 49 | if (!empty($url)) { 50 | $url = url($url['action'], $url['param'], true, true); 51 | } else { 52 | $url = ''; 53 | } 54 | return $url; 55 | } 56 | 57 | /** 58 | * 获取收藏内容 59 | * @param array $data [select,find查询结果] 60 | * @return array|false|\PDOStatement|string|\think\Model 61 | */ 62 | public function getFavorite($data) 63 | { 64 | if (!is_string($data[0])) { 65 | foreach ($data as $key => $value) { 66 | $where[$value['table_name']][] = $value['object_id']; 67 | } 68 | foreach ($where as $key => $value) { 69 | $favoriteData[] = $this->unionTable($key)->select($value); 70 | } 71 | } else { 72 | $favoriteData = $this->unionTable($data['table_name'])->find($data['object_id']); 73 | } 74 | 75 | return $favoriteData; 76 | } 77 | 78 | /** 79 | * [setFavorite 设置收藏] 80 | * @Author: wuwu<15093565100@163.com> 81 | * @DateTime: 2017-08-03T09:16:37+0800 82 | * @since: 1.0 83 | */ 84 | public function setFavorite($data) 85 | { 86 | //获取收藏内容信息 87 | $Favorite = self::create($data); 88 | return $Favorite->id; 89 | } 90 | 91 | /** 92 | * [unsetFavorite 取消收藏] 93 | * @Author: wuwu<15093565100@163.com> 94 | * @DateTime: 2017-08-03T09:17:30+0800 95 | * @since: 1.0 96 | * @return [type] [description] 97 | */ 98 | public function unsetFavorite($id) 99 | { 100 | return self::destroy($id); //执行删除 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /api/user/model/UserLikeModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\user\model; 11 | 12 | use api\common\model\CommonModel; 13 | 14 | class UserLikeModel extends CommonModel 15 | { 16 | 17 | /** 18 | * url 自动转化 19 | * @param $value 20 | * @return string 21 | */ 22 | public function getUrlAttr($value) 23 | { 24 | $url = json_decode($value, true); 25 | if (!empty($url)) { 26 | $url = url($url['action'], $url['param'], true, true); 27 | } else { 28 | $url = ''; 29 | } 30 | return $url; 31 | } 32 | 33 | /** 34 | * thumbnail 自动转化图片地址为绝对地址 35 | * @param $value 36 | * @return string 37 | */ 38 | public function getThumbnailAttr($value) 39 | { 40 | if (!empty($value)) { 41 | $value = cmf_get_image_url($value); 42 | } 43 | 44 | return $value; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /api/user/model/UserModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) 10 | // +---------------------------------------------------------------------- 11 | // | Date: 2017-7-26 12 | // +---------------------------------------------------------------------- 13 | namespace api\user\model; 14 | 15 | use think\Model; 16 | 17 | class UserModel extends Model 18 | { 19 | protected $type = [ 20 | 'more' => 'array', 21 | ]; 22 | 23 | 24 | /** 25 | * avatar 自动转化 26 | * @param $value 27 | * @return string 28 | */ 29 | public function getAvatarAttr($value) 30 | { 31 | return cmf_get_user_avatar_url($value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /api/user/route.php: -------------------------------------------------------------------------------- 1 | 'user/favorites/getFavorites', //获取收藏列表 17 | 'user/comments/my' => 'user/comments/getUserComments', //获取我的评论列表 18 | 'user/comments' => 'user/comments/getComments', //获评论列表 19 | 'user/favorites/hasFavorite' => 'user/favorites/hasFavorite' // 判断是否已经收藏 20 | ]); 21 | 22 | Route::post([ 23 | 'user/articles/deletes' => 'user/Articles/deletes', 24 | 'user/favorites' => 'user/favorites/setFavorites', //添加收藏 25 | 'user/comments' => 'user/comments/setComments', //添加评论 26 | ]); 27 | 28 | Route::delete([ 29 | 'user/favorites/:id' => 'user/favorites/unsetFavorites', //删除收藏 30 | 'user/comments/:id' => 'user/comments/delComments', //删除评论 31 | ]); 32 | -------------------------------------------------------------------------------- /api/wxapp/controller/PublicController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\wxapp\controller; 10 | 11 | use think\Db; 12 | use cmf\controller\RestBaseController; 13 | use wxapp\aes\WXBizDataCrypt; 14 | use think\Validate; 15 | 16 | class PublicController extends RestBaseController 17 | { 18 | // 微信小程序用户登录 TODO 增加最后登录信息记录,如 ip 19 | public function login() 20 | { 21 | $validate = new Validate([ 22 | 'code' => 'require', 23 | 'encrypted_data' => 'require', 24 | 'iv' => 'require', 25 | 'raw_data' => 'require', 26 | 'signature' => 'require', 27 | ]); 28 | 29 | $validate->message([ 30 | 'code.require' => '缺少参数code!', 31 | 'encrypted_data.require' => '缺少参数encrypted_data!', 32 | 'iv.require' => '缺少参数iv!', 33 | 'raw_data.require' => '缺少参数raw_data!', 34 | 'signature.require' => '缺少参数signature!', 35 | ]); 36 | 37 | $data = $this->request->param(); 38 | if (!$validate->check($data)) { 39 | $this->error($validate->getError()); 40 | } 41 | 42 | $code = $data['code']; 43 | $wxappSettings = cmf_get_option('wxapp_settings'); 44 | 45 | $appId = $this->request->header('XX-Wxapp-AppId'); 46 | if (empty($appId)) { 47 | if (empty($wxappSettings['default'])) { 48 | $this->error('没有设置默认小程序!'); 49 | } else { 50 | $defaultWxapp = $wxappSettings['default']; 51 | $appId = $defaultWxapp['app_id']; 52 | $appSecret = $defaultWxapp['app_secret']; 53 | } 54 | } else { 55 | if (empty($wxappSettings['wxapps'][$appId])) { 56 | $this->error('小程序设置不存在!'); 57 | } else { 58 | $appId = $wxappSettings['wxapps'][$appId]['app_id']; 59 | $appSecret = $wxappSettings['wxapps'][$appId]['app_secret']; 60 | } 61 | } 62 | 63 | 64 | $response = cmf_curl_get("https://api.weixin.qq.com/sns/jscode2session?appid=$appId&secret=$appSecret&js_code=$code&grant_type=authorization_code"); 65 | 66 | $response = json_decode($response, true); 67 | if (!empty($response['errcode'])) { 68 | $this->error('操作失败!'); 69 | } 70 | 71 | $openid = $response['openid']; 72 | $sessionKey = $response['session_key']; 73 | 74 | $pc = new WXBizDataCrypt($appId, $sessionKey); 75 | $errCode = $pc->decryptData($data['encrypted_data'], $data['iv'], $wxUserData); 76 | 77 | if ($errCode != 0) { 78 | $this->error('操作失败!'); 79 | } 80 | 81 | $findThirdPartyUser = Db::name("third_party_user") 82 | ->where('openid', $openid) 83 | ->where('app_id', $appId) 84 | ->find(); 85 | 86 | $currentTime = time(); 87 | $ip = $this->request->ip(0, true); 88 | 89 | $wxUserData['sessionKey'] = $sessionKey; 90 | unset($wxUserData['watermark']); 91 | 92 | if ($findThirdPartyUser) { 93 | $userId = $findThirdPartyUser['user_id']; 94 | $token = cmf_generate_user_token($findThirdPartyUser['user_id'], 'wxapp'); 95 | 96 | $userData = [ 97 | 'last_login_ip' => $ip, 98 | 'last_login_time' => $currentTime, 99 | 'login_times' => Db::raw('login_times+1'), 100 | 'more' => json_encode($wxUserData) 101 | ]; 102 | 103 | if (isset($wxUserData['unionId'])) { 104 | $userData['union_id'] = $wxUserData['unionId']; 105 | } 106 | 107 | Db::name("third_party_user") 108 | ->where('openid', $openid) 109 | ->where('app_id', $appId) 110 | ->update($userData); 111 | 112 | } else { 113 | 114 | //TODO 使用事务做用户注册 115 | $userId = Db::name("user")->insertGetId([ 116 | 'create_time' => $currentTime, 117 | 'user_status' => 1, 118 | 'user_type' => 2, 119 | 'sex' => $wxUserData['gender'], 120 | 'user_nickname' => $wxUserData['nickName'], 121 | 'avatar' => $wxUserData['avatarUrl'], 122 | 'last_login_ip' => $ip, 123 | 'last_login_time' => $currentTime, 124 | ]); 125 | 126 | Db::name("third_party_user")->insert([ 127 | 'openid' => $openid, 128 | 'user_id' => $userId, 129 | 'third_party' => 'wxapp', 130 | 'app_id' => $appId, 131 | 'last_login_ip' => $ip, 132 | 'union_id' => isset($wxUserData['unionId']) ? $wxUserData['unionId'] : '', 133 | 'last_login_time' => $currentTime, 134 | 'create_time' => $currentTime, 135 | 'login_times' => 1, 136 | 'status' => 1, 137 | 'more' => json_encode($wxUserData) 138 | ]); 139 | 140 | $token = cmf_generate_user_token($userId, 'wxapp'); 141 | 142 | } 143 | 144 | $user = Db::name('user')->where('id', $userId)->find(); 145 | 146 | $this->success("登录成功!", ['token' => $token, 'user' => $user]); 147 | 148 | 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /api/wxapp/controller/UserController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\wxapp\controller; 10 | 11 | use cmf\controller\RestBaseController; 12 | use wxapp\aes\WXBizDataCrypt; 13 | 14 | class UserController extends RestBaseController 15 | { 16 | // 获取用户信息 17 | public function getUserInfo() 18 | { 19 | 20 | 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /public/api/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php?s=$1 [QSA,PT,L] 8 | 9 | -------------------------------------------------------------------------------- /public/api/index.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | // [ 应用入口文件 ] 11 | 12 | // 调试模式开关 13 | define("APP_DEBUG", true); 14 | 15 | // 定义 APP 命名空间 16 | define("APP_NAMESPACE", 'api'); 17 | 18 | // 定义CMF根目录,可更改此目录 19 | define('CMF_ROOT', __DIR__ . '/../../'); 20 | 21 | // 定义应用目录 22 | define('APP_PATH', CMF_ROOT . 'api/'); 23 | 24 | // 定义CMF目录 25 | define('CMF_PATH', __DIR__ . '/../../simplewind/cmf/'); 26 | 27 | // 定义网站入口目录 28 | define('WEB_ROOT', __DIR__ . '/../'); 29 | 30 | // 定义插件目录 31 | define('PLUGINS_PATH', __DIR__ . '/../plugins/'); 32 | 33 | // 定义扩展目录 34 | define('EXTEND_PATH', __DIR__ . '/../../simplewind/extend/'); 35 | define('VENDOR_PATH', __DIR__ . '/../../simplewind/vendor/'); 36 | 37 | // 定义应用的运行时目录 38 | define('RUNTIME_PATH',__DIR__.'/../../data/runtime/api/'); 39 | 40 | // 加载框架基础文件 41 | require __DIR__ . '/../../simplewind/thinkphp/base.php'; 42 | 43 | // 执行应用 44 | \think\App::run()->send(); 45 | --------------------------------------------------------------------------------