├── .idea └── .gitignore ├── README.md ├── api └── portal │ ├── controller │ ├── ArticlesController.php │ ├── CategoriesController.php │ ├── IndexController.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 │ ├── PortalCategoryService.php │ ├── PortalPostService.php │ └── PortalTagService.php │ └── validate │ └── ArticlesValidate.php ├── app └── portal │ ├── PortalApp.php │ ├── api │ ├── CategoryApi.php │ └── PageApi.php │ ├── controller │ ├── AdminArticleController.php │ ├── AdminCategoryController.php │ ├── AdminIndexController.php │ ├── AdminPageController.php │ ├── AdminTagController.php │ ├── ArticleController.php │ ├── IndexController.php │ ├── ListController.php │ ├── PageController.php │ ├── SearchController.php │ └── TagController.php │ ├── data │ └── portal.sql │ ├── hooks.php │ ├── lang │ ├── en-us.php │ ├── en-us │ │ └── common.php │ ├── zh-cn.php │ └── zh-cn │ │ ├── common.php │ │ └── home.php │ ├── manifest.json │ ├── model │ ├── PortalCategoryModel.php │ ├── PortalCategoryPostModel.php │ ├── PortalPostModel.php │ ├── PortalTagModel.php │ ├── PortalTagPostModel.php │ ├── RecycleBinModel.php │ └── UserModel.php │ ├── nav.php │ ├── service │ ├── ApiService.php │ └── PostService.php │ ├── taglib │ └── Portal.php │ ├── url.php │ ├── user_action.php │ ├── validate │ ├── AdminArticleValidate.php │ ├── AdminPageValidate.php │ └── PortalCategoryValidate.php │ └── version └── public └── themes ├── admin_simpleboot3 └── portal │ ├── admin_article │ ├── add.html │ ├── copy.html │ ├── edit.html │ ├── index.html │ ├── move.html │ └── recyclebin.html │ ├── admin_category │ ├── add.html │ ├── edit.html │ ├── index.html │ └── select.html │ ├── admin_page │ ├── add.html │ ├── edit.html │ ├── index.html │ └── recyclebin.html │ └── admin_tag │ ├── add.html │ ├── index.html │ └── select.html └── simpleboot3 ├── README.md ├── manifest.json ├── portal ├── article.html ├── article.json ├── contact.html ├── contact.json ├── index.html ├── index.json ├── list.html ├── list.json ├── page.html ├── page.json ├── search.html ├── search.json └── tag.html ├── public ├── assets │ ├── css │ │ ├── slippry │ │ │ ├── assets │ │ │ │ └── img │ │ │ │ │ ├── arrows.png │ │ │ │ │ ├── arrows.svg │ │ │ │ │ └── sy-loader.gif │ │ │ └── slippry.css │ │ └── style.css │ ├── images │ │ ├── default-thumbnail.png │ │ ├── default_tupian1.png │ │ ├── default_tupian4.png │ │ ├── demo │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ └── 3.jpg │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── ghs.png │ │ ├── headicon.png │ │ ├── headicon_128.png │ │ ├── headicon_30.png │ │ ├── headicon_40.png │ │ ├── headicon_50.png │ │ ├── logo.png │ │ └── null_cart2.jpg │ ├── js │ │ ├── imagesloaded.pkgd.min.js │ │ ├── jquery-1.10.2.min.js │ │ ├── jquery-1.10.2.min.map │ │ ├── jquery-migrate-1.2.1.js │ │ ├── jquery.infiniteScroll.js │ │ ├── masonry.pkgd.min.js │ │ ├── qrcode.min.js │ │ ├── slippry.min.js │ │ └── slippry.min.map │ └── simpleboot3 │ │ ├── bootstrap │ │ └── js │ │ │ └── bootstrap.min.js │ │ ├── canvas-to-blob │ │ ├── canvas-to-blob.js │ │ ├── canvas-to-blob.min.js │ │ └── canvas-to-blob.min.js.map │ │ ├── cropper │ │ ├── cropper.css │ │ ├── cropper.js │ │ └── jquery-cropper.min.js │ │ ├── font-awesome │ │ ├── 4.2.0 │ │ │ ├── css │ │ │ │ ├── font-awesome-ie7.min.css │ │ │ │ └── font-awesome.min.css │ │ │ └── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ └── fontawesome-webfont.woff │ │ └── 4.4.0 │ │ │ ├── css │ │ │ ├── font-awesome-ie7.min.css │ │ │ └── font-awesome.min.css │ │ │ └── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ └── themes │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── simpleboot3 │ │ └── bootstrap.min.css ├── config.html ├── config.json ├── footer.html ├── function.html ├── head.html ├── nav.html ├── nav.json ├── scripts.html └── usernav.html └── user ├── comment └── index.html ├── favorite └── index.html ├── find_password.html ├── index.html ├── login.html ├── profile ├── avatar.html ├── binding.html ├── center.html ├── edit.html └── password.html └── register.html /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ThinkCMF企业门户解决方案,同时兼容ThinkCMF5.1和6.0 2 | =============== 3 | 帮助你更快地搭建企业门户网站 4 | 5 | ### 开发手册 6 | http://www.kancloud.cn/thinkcmf/doc5_1 7 | https://www.kancloud.cn/thinkcmf/theme_tutorial 8 | 9 | ### Git仓库 10 | 11 | 1. GitHub:https://github.com/thinkcmf/portal 主要仓库 12 | 2. 码云:https://gitee.com/thinkcmf/portal 国内仓库 13 | 14 | ### 环境推荐 15 | > php7.1 16 | 17 | > mysql 5.6+ 18 | 19 | > 打开rewrite 20 | 21 | 22 | ### 最低环境要求 23 | > php5.6+ 24 | 25 | > mysql 5.5+ (mysql5.1安装时选择utf8编码,不支持表情符) 26 | 27 | > 打开rewrite 28 | 29 | ### 安装步骤 30 | 1. 下载本仓库代码,覆盖到你的ThinkCMF里 31 | 2. 导入`app/portal/data/portal.sql`文件(注意把`cmf_`表前缀替换成自己的) 32 | 3. 在后台模板管理里安装`simpleboot3`模板 33 | 4. 如果想用`simpleboot3`模板,可以启用此模板 34 | 5. 导入后台菜单 35 | 36 | 详细安装步骤请查看[ThinkCMF FAQ](https://www.kancloud.cn/thinkcmf/faq/1005840) 37 | 38 | 39 | 40 | ### QQ群: 41 | `ThinkCMF 官方交流群`:316669417 42 | 43 | `ThinkCMF 高级交流群`:100828313 (付费) 44 | 45 | `ThinkCMF 铲屎官交流群`:415136742 (生活娱乐,为有喵的猿人准备) 46 | 47 | 48 | ### 反馈问题 49 | https://github.com/thinkcmf/portal/issues 50 | 51 | ### 更新日志 52 | #### 1.0.0 53 | * 移除所有演示应用、插件、模板代码 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /api/portal/controller/CategoriesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\controller; 11 | 12 | use api\portal\service\PortalCategoryService; 13 | use cmf\controller\RestBaseController; 14 | use api\portal\model\PortalCategoryModel; 15 | 16 | class CategoriesController extends RestBaseController 17 | { 18 | /** 19 | * 获取分类列表 20 | * @throws \think\db\exception\DataNotFoundException 21 | * @throws \think\db\exception\ModelNotFoundException 22 | * @throws \think\exception\DbException 23 | */ 24 | public function index() 25 | { 26 | 27 | $params = $this->request->get(); 28 | $categoryService = new PortalCategoryService(); 29 | $data = $categoryService->categories($params); 30 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 31 | $response = $data; 32 | } else { 33 | $response = ['list' => $data]; 34 | } 35 | 36 | $this->success('请求成功!', $response); 37 | } 38 | 39 | /** 40 | * 显示指定的分类 41 | * @param $id 42 | * @throws \think\db\exception\DataNotFoundException 43 | * @throws \think\db\exception\ModelNotFoundException 44 | * @throws \think\exception\DbException 45 | */ 46 | public function read($id) 47 | { 48 | $categoryModel = new PortalCategoryModel(); 49 | $data = $categoryModel 50 | ->where('delete_time', 0) 51 | ->where('status', 1) 52 | ->where('id', $id) 53 | ->find(); 54 | if ($data) { 55 | $this->success('请求成功!', $data); 56 | } else { 57 | $this->error('该分类不存在!'); 58 | } 59 | 60 | } 61 | 62 | /** 63 | * 获取指定分类的子分类列表 64 | * @throws \think\db\exception\DataNotFoundException 65 | * @throws \think\db\exception\ModelNotFoundException 66 | * @throws \think\exception\DbException 67 | */ 68 | public function subCategories() 69 | { 70 | $id = $this->request->get('category_id', 0, 'intval'); 71 | 72 | $categoryModel = new PortalCategoryModel(); 73 | $categories = $categoryModel->where(['parent_id' => $id])->select(); 74 | if (!$categories->isEmpty()) { 75 | $this->success('请求成功', ['categories' => $categories]); 76 | } else { 77 | $this->error('该分类下没有子分类!'); 78 | } 79 | 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /api/portal/controller/IndexController.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 IndexController extends RestBaseController 16 | { 17 | protected $tagModel; 18 | 19 | /** 20 | * 获取标签列表 21 | */ 22 | public function index() 23 | { 24 | $this->success('请求成功!', "DD"); 25 | } 26 | 27 | /** 28 | * 获取热门标签列表 29 | */ 30 | public function hotTags() 31 | { 32 | $params = $this->request->get(); 33 | $params['where']['recommended'] = 1; 34 | $data = $this->tagModel->getDatas($params); 35 | 36 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 37 | $response = $data; 38 | } else { 39 | $response = ['list' => $data,]; 40 | } 41 | $this->success('请求成功!', $response); 42 | } 43 | 44 | /** 45 | * 获取标签文章列表 46 | * @param int $id 47 | */ 48 | public function articles($id) 49 | { 50 | if (intval($id) === 0) { 51 | $this->error('无效的标签id!'); 52 | } else { 53 | $params = $this->request->param(); 54 | $postModel = new PortalPostModel(); 55 | 56 | unset($params['id']); 57 | 58 | $articles = $postModel->paramsFilter($params)->alias('post') 59 | ->join('__PORTAL_TAG_POST__ tag_post', 'post.id = tag_post.post_id') 60 | ->where(['tag_post.tag_id' => $id])->select(); 61 | 62 | if (!empty($params['relation'])) { 63 | $allowedRelations = $postModel->allowedRelations($params['relation']); 64 | if (!empty($allowedRelations)) { 65 | if (count($articles) > 0) { 66 | $articles->load($allowedRelations); 67 | $articles->append($allowedRelations); 68 | } 69 | } 70 | } 71 | 72 | 73 | $this->success('请求成功!', ['articles' => $articles]); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /api/portal/controller/ListsController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\model\PortalCategoryModel; 12 | use api\portal\service\PortalPostService; 13 | use cmf\controller\RestBaseController; 14 | 15 | class ListsController extends RestBaseController 16 | { 17 | 18 | /** 19 | * 推荐文章列表 20 | * @throws \think\db\exception\DataNotFoundException 21 | * @throws \think\db\exception\ModelNotFoundException 22 | * @throws \think\exception\DbException 23 | */ 24 | public function recommended() 25 | { 26 | $param = $this->request->param(); 27 | $param['recommended'] = true; 28 | 29 | $portalPostService = new PortalPostService(); 30 | $articles = $portalPostService->postArticles($param); 31 | //是否需要关联模型 32 | if (!$articles->isEmpty()) { 33 | if (!empty($param['relation'])) { 34 | $allowedRelations = allowed_relations(['user', 'categories'], $param['relation']); 35 | if (!empty($allowedRelations)) { 36 | $articles->load($allowedRelations); 37 | $articles->append($allowedRelations); 38 | } 39 | } 40 | } 41 | $this->success('ok', ['list' => $articles]); 42 | } 43 | 44 | /** 45 | * 分类文章列表 46 | * @throws \think\db\exception\DataNotFoundException 47 | * @throws \think\db\exception\ModelNotFoundException 48 | * @throws \think\exception\DbException 49 | */ 50 | public function getCategoryPostLists() 51 | { 52 | $categoryId = $this->request->param('category_id', 0, 'intval'); 53 | 54 | $portalCategoryModel = new PortalCategoryModel(); 55 | $findCategory = $portalCategoryModel->where('id', $categoryId)->find(); 56 | 57 | //分类是否存在 58 | if (empty($findCategory)) { 59 | $this->error('分类不存在!'); 60 | } 61 | 62 | $param = $this->request->param(); 63 | 64 | $portalPostService = new PortalPostService(); 65 | $articles = $portalPostService->postArticles($param); 66 | //是否需要关联模型 67 | if (!$articles->isEmpty()) { 68 | if (!empty($param['relation'])) { 69 | $allowedRelations = allowed_relations(['user', 'categories'], $param['relation']); 70 | if (!empty($allowedRelations)) { 71 | $articles->load($allowedRelations); 72 | $articles->append($allowedRelations); 73 | } 74 | } 75 | } 76 | $this->success('ok', ['list' => $articles]); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /api/portal/controller/PagesController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\controller; 11 | 12 | use api\portal\service\PortalPostService; 13 | use cmf\controller\RestBaseController; 14 | use api\portal\model\PortalPostModel; 15 | 16 | class PagesController extends RestBaseController 17 | { 18 | /** 19 | * 页面列表 20 | * @throws \think\db\exception\DataNotFoundException 21 | * @throws \think\db\exception\ModelNotFoundException 22 | * @throws \think\exception\DbException 23 | */ 24 | public function index() 25 | { 26 | $params = $this->request->get(); 27 | $postService = new PortalPostService(); 28 | $data = $postService->postArticles($params, true); 29 | 30 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 31 | $response = $data; 32 | } else { 33 | $response = ['list' => $data,]; 34 | } 35 | $this->success('请求成功!', $response); 36 | } 37 | 38 | /** 39 | * 获取页面 40 | * @param $id 41 | * @throws \think\db\exception\DataNotFoundException 42 | * @throws \think\db\exception\ModelNotFoundException 43 | * @throws \think\exception\DbException 44 | */ 45 | public function read($id) 46 | { 47 | 48 | $params = $this->request->get(); 49 | $field = empty($params['field']) ? '*' : $params['field']; 50 | $postModel = new PortalPostModel(); 51 | $data = $postModel 52 | ->field($field) 53 | ->where('id', $id) 54 | ->where('delete_time', 0) 55 | ->where('post_status', 1) 56 | ->where('post_type', 2) 57 | ->find(); 58 | if ($data){ 59 | $this->success('请求成功!', $data); 60 | }else{ 61 | $this->error('文章不存在!'); 62 | } 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /api/portal/controller/TagsController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\model\PortalTagModel; 12 | use api\portal\service\PortalTagService; 13 | use cmf\controller\RestBaseController; 14 | use think\db\Query; 15 | 16 | class TagsController extends RestBaseController 17 | { 18 | 19 | /** 20 | * 获取标签列表 21 | * @throws \think\db\exception\DataNotFoundException 22 | * @throws \think\db\exception\ModelNotFoundException 23 | * @throws \think\exception\DbException 24 | */ 25 | public function index() 26 | { 27 | $params = $this->request->get(); 28 | $tagService = new PortalTagService(); 29 | $data = $tagService->tagList($params); 30 | 31 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 32 | $response = $data; 33 | } else { 34 | $response = ['list' => $data,]; 35 | } 36 | if ($data->isEmpty()) { 37 | $this->error('没有标签!'); 38 | } 39 | $this->success('请求成功!', $response); 40 | } 41 | 42 | /** 43 | * 获取热门标签列表 44 | * @throws \think\db\exception\DataNotFoundException 45 | * @throws \think\db\exception\ModelNotFoundException 46 | * @throws \think\exception\DbException 47 | */ 48 | public function hotTags() 49 | { 50 | $params = $this->request->get(); 51 | $params['where']['recommended'] = 1; 52 | 53 | $tagService = new PortalTagService(); 54 | $data = $tagService->tagList($params); 55 | 56 | if (empty($this->apiVersion) || $this->apiVersion == '1.0.0') { 57 | $response = $data; 58 | } else { 59 | $response = ['list' => $data,]; 60 | } 61 | $this->success('请求成功!', $response); 62 | } 63 | 64 | /** 65 | * 获取标签文章列表 66 | * @param $id 67 | * @throws \think\db\exception\DataNotFoundException 68 | * @throws \think\db\exception\ModelNotFoundException 69 | * @throws \think\exception\DbException 70 | */ 71 | public function articles($id) 72 | { 73 | if (intval($id) === 0) { 74 | $this->error('无效的标签id!'); 75 | } else { 76 | $filter = $this->request->param(); 77 | $filter['id'] = $id; 78 | $tagService = new PortalTagService(); 79 | $tag = $tagService->portalTagArticles($filter); 80 | if ($tag) { 81 | $this->error('没有相关文章'); 82 | } 83 | $this->success('请求成功!', $tag); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /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 | /** 17 | * 显示资源列表 18 | */ 19 | public function index() 20 | { 21 | $params = $this->request->get(); 22 | $userId = $this->getUserId(); 23 | $postModel = new PortalPostModel(); 24 | $dates = $postModel->getUserArticles($userId, $params); 25 | $this->success('请求成功!', $dates); 26 | } 27 | 28 | /** 29 | * 保存新建的资源 30 | */ 31 | public function save() 32 | { 33 | $dates = $this->request->post(); 34 | $dates['user_id'] = $this->getUserId(); 35 | $result = $this->validate($dates, 'Articles.article'); 36 | if ($result !== true) { 37 | $this->error($result); 38 | } 39 | if (empty($dates['published_time'])) { 40 | $dates['published_time'] = time(); 41 | } 42 | $postModel = new PortalPostModel(); 43 | $postModel->addArticle($dates); 44 | $this->success('添加成功!'); 45 | } 46 | 47 | /** 48 | * 显示指定的资源 49 | * @param $id 50 | */ 51 | public function read($id) 52 | { 53 | if (empty($id)) { 54 | $this->error('无效的文章id'); 55 | } 56 | $params = $this->request->get(); 57 | $params['id'] = $id; 58 | $userId = $this->getUserId(); 59 | $postModel = new PortalPostModel(); 60 | $dates = $postModel->getUserArticles($userId, $params); 61 | $this->success('请求成功!', $dates); 62 | } 63 | 64 | /** 65 | * 保存更新的资源 66 | * @param $id 67 | */ 68 | public function update($id) 69 | { 70 | $data = $this->request->put(); 71 | $result = $this->validate($data, 'Articles.article'); 72 | if ($result !== true) { 73 | $this->error($result); 74 | } 75 | if (empty($id)) { 76 | $this->error('无效的文章id'); 77 | } 78 | $postModel = new PortalPostModel(); 79 | $result = $postModel->editArticle($data, $id, $this->getUserId()); 80 | if ($result === false) { 81 | $this->error('编辑失败!'); 82 | } else { 83 | $this->success('编辑成功!'); 84 | } 85 | } 86 | 87 | /** 88 | * 删除指定资源 89 | * @param $id 90 | */ 91 | public function delete($id) 92 | { 93 | if (empty($id)) { 94 | $this->error('无效的文章id'); 95 | } 96 | $postModel = new PortalPostModel(); 97 | $result = $postModel->deleteArticle($id, $this->getUserId()); 98 | if ($result == -1) { 99 | $this->error('文章已删除'); 100 | } 101 | if ($result) { 102 | $this->success('删除成功!'); 103 | } else { 104 | $this->error('删除失败!'); 105 | } 106 | } 107 | 108 | /** 109 | * 批量删除文章 110 | */ 111 | public function deletes() 112 | { 113 | $ids = $this->request->post('ids/a'); 114 | if (empty($ids)) { 115 | $this->error('文章id不能为空'); 116 | } 117 | $postModel = new PortalPostModel(); 118 | $result = $postModel->deleteArticle($ids, $this->getUserId()); 119 | if ($result == -1) { 120 | $this->error('文章已删除'); 121 | } 122 | if ($result) { 123 | $this->success('删除成功!'); 124 | } else { 125 | $this->error('删除失败!'); 126 | } 127 | } 128 | 129 | /** 130 | * 我的文章列表 131 | */ 132 | public function my() 133 | { 134 | $params = $this->request->get(); 135 | $userId = $this->getUserId(); 136 | $postModel = new PortalPostModel(); 137 | $data = $postModel->getUserArticles($userId, $params); 138 | $this->success('请求成功!', $data); 139 | } 140 | } -------------------------------------------------------------------------------- /api/portal/controller/UserController.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\controller; 10 | 11 | use api\portal\service\PortalPostService; 12 | use cmf\controller\RestBaseController; 13 | 14 | class UserController extends RestBaseController 15 | { 16 | /** 17 | * 会员文章列表 18 | * @throws \think\db\exception\DataNotFoundException 19 | * @throws \think\db\exception\ModelNotFoundException 20 | * @throws \think\exception\DbException 21 | */ 22 | public function articles() 23 | { 24 | $userId = $this->request->param('user_id', 0, 'intval'); 25 | 26 | if (empty($userId)) { 27 | $this->error('用户id不能空!'); 28 | } 29 | 30 | $param = $this->request->param(); 31 | $param['user_id'] = $userId; 32 | $portalPostService = new PortalPostService(); 33 | $articles = $portalPostService->postArticles($param); 34 | if ($articles->isEmpty()) { 35 | $this->error('没有数据'); 36 | } else { 37 | $this->success('ok', ['list' => $articles]); 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /api/portal/model/PortalCategoryModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | use think\Model; 13 | 14 | class PortalCategoryModel extends Model 15 | { 16 | /** 17 | * 模型名称 18 | * @var string 19 | */ 20 | protected $name = 'portal_category'; 21 | 22 | //类型转换 23 | protected $type = [ 24 | 'more' => 'array', 25 | ]; 26 | 27 | 28 | //模型关联方法 29 | protected $relationFilter = ['articles']; 30 | 31 | 32 | /** 33 | * more 自动转化 34 | * @param $value 35 | * @return array 36 | */ 37 | public function getMoreAttr($value) 38 | { 39 | $more = json_decode($value, true); 40 | if (!empty($more['thumbnail'])) { 41 | $more['thumbnail'] = cmf_get_image_url($more['thumbnail']); 42 | } 43 | 44 | if (!empty($more['photos'])) { 45 | foreach ($more['photos'] as $key => $value) { 46 | $more['photos'][$key]['url'] = cmf_get_image_url($value['url']); 47 | } 48 | } 49 | return $more; 50 | } 51 | 52 | /** 53 | * 关联文章表 54 | * @return \think\model\relation\BelongsToMany 55 | */ 56 | public function articles() 57 | { 58 | return $this->belongsToMany('PortalPostModel', 'portal_category_post', 'post_id', 'category_id'); 59 | } 60 | 61 | /** 62 | * 关联文章分类和文章表 63 | * @return \think\model\relation\HasMany 64 | */ 65 | public function PostIds() 66 | { 67 | return $this->hasMany('PortalCategoryPostModel', 'category_id', 'id'); 68 | } 69 | 70 | /** 71 | * 此类文章id数组 72 | * @param string $category_id 分类di 73 | * @return array|string|Model|null 74 | * @throws \think\db\exception\DataNotFoundException 75 | * @throws \think\db\exception\ModelNotFoundException 76 | * @throws \think\exception\DbException 77 | */ 78 | public static function categoryPostIds($category_id) 79 | { 80 | $ids = []; 81 | $post_ids = self::relation('PostIds')->field(true)->where('id', $category_id)->find(); 82 | foreach ($post_ids['PostIds'] as $key => $id) { 83 | $ids[] = $id['post_id']; 84 | } 85 | $post_ids['PostIds'] = $ids; 86 | return $post_ids; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /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 | * @var string 21 | */ 22 | protected $name = 'portal_category_post'; 23 | 24 | /** 25 | * 基础查询 26 | */ 27 | protected function base($query) 28 | { 29 | $query->where('status', 1); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /api/portal/model/PortalTagModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | use think\Model; 13 | 14 | class PortalTagModel extends Model 15 | { 16 | /** 17 | * 模型名称 18 | * @var string 19 | */ 20 | protected $name = 'portal_tag'; 21 | 22 | /** 23 | * 关联 文章表 24 | * @return \think\model\relation\BelongsToMany 25 | */ 26 | public function articles() 27 | { 28 | return $this->belongsToMany('PortalPostModel','portal_tag_post','post_id','tag_id')->alias('post'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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 | * 模型名称 18 | * @var string 19 | */ 20 | protected $name = 'portal_tag_post'; 21 | 22 | /** 23 | * 获取指定id相关的文章id数组 24 | * @param $post_id 文章id 25 | * @return array 相关的文章id 26 | */ 27 | function getRelationPostIds($post_id) 28 | { 29 | $tagIds = $this->where('post_id', $post_id) 30 | ->column('tag_id'); 31 | $postIds = $this->whereIn('tag_id', $tagIds) 32 | ->column('post_id'); 33 | return array_unique($postIds); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /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 | * @var string 18 | */ 19 | protected $name = 'recycle_bin'; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /api/portal/model/UserModel.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace api\portal\model; 11 | 12 | 13 | use think\Model; 14 | 15 | class UserModel extends Model 16 | { 17 | /** 18 | * 模型名称 19 | * @var string 20 | */ 21 | protected $name = 'user'; 22 | 23 | //模型关联方法 24 | protected $relationFilter = ['user']; 25 | 26 | 27 | /** 28 | * more 自动转化 29 | * @param $value 30 | * @return string 31 | */ 32 | public function getAvatarAttr($value) 33 | { 34 | $value = !empty($value) ? cmf_get_image_url($value) : $value; 35 | return $value; 36 | } 37 | 38 | /** 39 | * 关联 user表 40 | * @return string 关联数据 41 | */ 42 | public function user() 43 | { 44 | return $this->belongsTo('UserModel', 'user_id')->setEagerlyType(1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /api/portal/route.php: -------------------------------------------------------------------------------- 1 | 8 | // | Date: 2019/01/08 9 | // | Time:上午 10:32 10 | // +---------------------------------------------------------------------- 11 | 12 | 13 | namespace api\portal\service; 14 | 15 | 16 | use api\portal\model\PortalCategoryModel; 17 | use think\db\Query; 18 | 19 | class PortalCategoryService 20 | { 21 | /** 22 | * @param $filter 23 | * @return array|\PDOStatement|string|\think\Collection 24 | * @throws \think\db\exception\DataNotFoundException 25 | * @throws \think\db\exception\ModelNotFoundException 26 | * @throws \think\exception\DbException 27 | */ 28 | public function categories($filter) 29 | { 30 | $categoryModel = new PortalCategoryModel(); 31 | //条件分解 32 | $field = empty($filter['field']) ? '*' : $filter['field']; 33 | $order = empty($filter['order']) ? ['-id'] : explode(',', $filter['order']); 34 | $page = empty($filter['page']) ? '' : $filter['page']; 35 | $limit = empty($filter['limit']) ? '' : $filter['limit']; 36 | if (!empty($page)) { 37 | $categoryModel = $categoryModel->page($page); 38 | } elseif (!empty($limit)) { 39 | $categoryModel = $categoryModel->limit($limit); 40 | } else { 41 | $categoryModel = $categoryModel->limit(10); 42 | } 43 | //转化-+为desc、asc 44 | $orderArr = order_shift($order); 45 | 46 | $result = $categoryModel 47 | ->field($field) 48 | ->where('delete_time', 0) 49 | ->where('status', 1) 50 | ->where(function (Query $query) use ($filter) { 51 | if (!empty($filter['ids'])) { 52 | $query->where('id', 'in', $filter['ids']); 53 | } 54 | }) 55 | ->order($orderArr) 56 | ->select(); 57 | return $result; 58 | } 59 | } -------------------------------------------------------------------------------- /api/portal/service/PortalPostService.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | namespace api\portal\service; 10 | 11 | use api\portal\model\PortalPostModel; 12 | use think\db\Query; 13 | 14 | class PortalPostService 15 | { 16 | //模型关联方法 17 | protected $relationFilter = ['user']; 18 | 19 | /** 20 | * 文章列表 21 | * @param $filter 22 | * @param bool $isPage 23 | * @return array|string|\think\Collection 24 | * @throws \think\db\exception\DataNotFoundException 25 | * @throws \think\db\exception\ModelNotFoundException 26 | * @throws \think\exception\DbException 27 | */ 28 | public function postArticles($filter, $isPage = false) 29 | { 30 | $join = []; 31 | 32 | $field = empty($filter['field']) ? 'a.*' : explode(',', $filter['field']); 33 | //转为查询条件 34 | if (is_array($field)) { 35 | foreach ($field as $key => $value) { 36 | $field[$key] = 'a.' . $value; 37 | } 38 | $field = implode(',', $field); 39 | } 40 | $page = empty($filter['page']) ? '' : $filter['page']; 41 | $limit = empty($filter['limit']) ? '' : $filter['limit']; 42 | $order = empty($filter['order']) ? ['-update_time'] : explode(',', $filter['order']); 43 | $category = empty($filter['category_id']) ? 0 : intval($filter['category_id']); 44 | if (!empty($category)) { 45 | array_push($join, ['__PORTAL_CATEGORY_POST__ b', 'a.id = b.post_id']); 46 | $field = $field.',b.id AS post_category_id,b.list_order,b.category_id'; 47 | } 48 | 49 | $orderArr = order_shift($order); 50 | 51 | $portalPostModel = new PortalPostModel(); 52 | 53 | 54 | if (!empty($page)) { 55 | $portalPostModel = $portalPostModel->page($page); 56 | } elseif (!empty($limit)) { 57 | $portalPostModel = $portalPostModel->limit($limit); 58 | } else { 59 | $portalPostModel = $portalPostModel->limit(10); 60 | } 61 | 62 | $articles = $portalPostModel 63 | ->alias('a') 64 | ->field($field) 65 | ->join($join) 66 | ->where('a.create_time', '>=', 0) 67 | ->where('a.delete_time', 0) 68 | ->where('a.post_status', 1) 69 | ->where(function (Query $query) use ($filter, $isPage) { 70 | if (!empty($filter['user_id'])) { 71 | $query->where('a.user_id', $filter['user_id']); 72 | } 73 | $category = empty($filter['category_id']) ? 0 : intval($filter['category_id']); 74 | if (!empty($category)) { 75 | $query->where('b.category_id', $category); 76 | } 77 | $startTime = empty($filter['start_time']) ? 0 : strtotime($filter['start_time']); 78 | $endTime = empty($filter['end_time']) ? 0 : strtotime($filter['end_time']); 79 | if (!empty($startTime)) { 80 | $query->where('a.published_time', '>=', $startTime); 81 | } 82 | if (!empty($endTime)) { 83 | $query->where('a.published_time', '<=', $endTime); 84 | } 85 | $keyword = empty($filter['keyword']) ? '' : $filter['keyword']; 86 | if (!empty($keyword)) { 87 | $query->where('a.post_title', 'like', "%$keyword%"); 88 | } 89 | if ($isPage) { 90 | $query->where('a.post_type', 2); 91 | } else { 92 | $query->where('a.post_type', 1); 93 | } 94 | if (!empty($filter['recommended'])) { 95 | $query->where('a.recommended', 1); 96 | } 97 | if (!empty($filter['ids'])) { 98 | $ids = str_to_arr($filter['ids']); 99 | $query->where('a.id', 'in', $ids); 100 | } 101 | }) 102 | ->order($orderArr) 103 | ->select(); 104 | 105 | return $articles; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /api/portal/service/PortalTagService.php: -------------------------------------------------------------------------------- 1 | 8 | // | Date: 2019/01/09 9 | // | Time:下午 06:10 10 | // +---------------------------------------------------------------------- 11 | 12 | 13 | namespace api\portal\service; 14 | 15 | 16 | use api\portal\model\PortalPostModel; 17 | use api\portal\model\PortalTagModel; 18 | use think\db\Query; 19 | 20 | class PortalTagService 21 | { 22 | /** 23 | * 获取标签列表 24 | * @param array $filter 参数 25 | * @return array|\PDOStatement|string|\think\Collection 26 | * @throws \think\db\exception\DataNotFoundException 27 | * @throws \think\db\exception\ModelNotFoundException 28 | * @throws \think\exception\DbException 29 | */ 30 | public function tagList($filter) 31 | { 32 | $field = empty($filter['field']) ? '*' : $filter['field']; 33 | $page = empty($filter['page']) ? '' : $filter['page']; 34 | $limit = empty($filter['limit']) ? '' : $filter['limit']; 35 | $order = empty($filter['order']) ? ['-id'] : explode(',', $filter['order']); 36 | $orderArr = order_shift($order); 37 | $tagModel = new PortalTagModel(); 38 | if (!empty($page)) { 39 | $tagModel = $tagModel->page($page); 40 | } elseif (!empty($limit)) { 41 | $tagModel = $tagModel->limit($limit); 42 | } else { 43 | $tagModel = $tagModel->limit(10); 44 | } 45 | 46 | $result = $tagModel 47 | ->field($field) 48 | ->where('status', 1) 49 | ->where(function (Query $query) use ($filter) { 50 | if (!empty($filter['id'])) { 51 | $query->where('id', $filter['id']); 52 | } 53 | }) 54 | ->order($orderArr) 55 | ->select(); 56 | return $result; 57 | } 58 | 59 | /** 60 | * @param $filter 61 | * @return array|\PDOStatement|string|\think\Model|null 62 | * @throws \think\db\exception\DataNotFoundException 63 | * @throws \think\db\exception\ModelNotFoundException 64 | * @throws \think\exception\DbException 65 | */ 66 | public function portalTagArticles($filter) 67 | { 68 | $tagModel = new PortalTagModel(); 69 | $tag = $tagModel 70 | ->with([ 71 | 'articles' => function (Query $query) use ($filter) { 72 | $field = empty($filter['field']) ? 'post.*' : explode(',', $filter['field']); 73 | //转为查询条件 74 | if (is_array($field)) { 75 | foreach ($field as $key => $value) { 76 | $field[$key] = 'post.' . $value; 77 | } 78 | $field = implode(',', $field); 79 | } 80 | $page = empty($filter['page']) ? '' : $filter['page']; 81 | $limit = empty($filter['limit']) ? '10' : $filter['limit']; 82 | $order = empty($filter['order']) ? ['-post.id'] : explode(',', $filter['order']); 83 | $orderArr = order_shift($order); 84 | $query->field($field); 85 | if (!empty($page)) { 86 | $query->page($page); 87 | } elseif (!empty($limit)) { 88 | $query->limit($limit); 89 | } else { 90 | $query->limit(10); 91 | } 92 | $query->order($orderArr); 93 | $query->hidden(['pivot']); 94 | } 95 | ]) 96 | ->where('id', $filter['id']) 97 | ->find(); 98 | return $tag; 99 | } 100 | } -------------------------------------------------------------------------------- /api/portal/validate/ArticlesValidate.php: -------------------------------------------------------------------------------- 1 | 10 | // | Date: 2019/01/11 11 | // | Time:下午 03:24 12 | // +---------------------------------------------------------------------- 13 | namespace api\portal\validate; 14 | 15 | use think\Validate; 16 | 17 | class ArticlesValidate extends Validate 18 | { 19 | protected $rule = [ 20 | 'post_title' => 'require', 21 | 'post_content' => 'require', 22 | 'categories' => 'require' 23 | ]; 24 | protected $message = [ 25 | 'post_title.require' => '文章标题不能为空', 26 | 'post_content.require' => '内容不能为空', 27 | 'categories.require' => '文章分类不能为空' 28 | ]; 29 | 30 | protected $scene = [ 31 | 'article' => [ 'post_title' , 'post_content' , 'categories' ], 32 | 'page' => ['post_title'] 33 | ]; 34 | } -------------------------------------------------------------------------------- /app/portal/PortalApp.php: -------------------------------------------------------------------------------- 1 | 8 | // +---------------------------------------------------------------------- 9 | 10 | namespace app\portal; 11 | 12 | //Demo应用英文名,改成你的应用英文就行了 13 | class PortalApp 14 | { 15 | 16 | // 应用安装 17 | public function install() 18 | { 19 | return true; //安装成功返回true,失败false 20 | } 21 | 22 | // 应用卸载 23 | public function uninstall() 24 | { 25 | return true; //卸载成功返回true,失败false 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/portal/api/CategoryApi.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\api; 12 | 13 | use app\portal\model\PortalCategoryModel; 14 | use think\db\Query; 15 | 16 | class CategoryApi 17 | { 18 | /** 19 | * 分类列表 用于模板设计 20 | * @param array $param 21 | * @return false|\PDOStatement|string|\think\Collection 22 | * @throws \think\db\exception\DataNotFoundException 23 | * @throws \think\db\exception\ModelNotFoundException 24 | * @throws \think\exception\DbException 25 | */ 26 | public function index($param = []) 27 | { 28 | $portalCategoryModel = new PortalCategoryModel(); 29 | 30 | $where = ['delete_time' => 0]; 31 | 32 | //返回的数据必须是数据集或数组,item里必须包括id,name,如果想表示层级关系请加上 parent_id 33 | return $portalCategoryModel->where($where) 34 | ->where(function (Query $query) use ($param) { 35 | if (!empty($param['keyword'])) { 36 | $query->where('name', 'like', "%{$param['keyword']}%"); 37 | } 38 | })->select(); 39 | } 40 | 41 | /** 42 | * 分类列表 用于导航选择 43 | * @return array 44 | */ 45 | public function nav() 46 | { 47 | $portalCategoryModel = new PortalCategoryModel(); 48 | 49 | $where = ['delete_time' => 0]; 50 | 51 | $categories = $portalCategoryModel->where($where)->select(); 52 | 53 | $return = [ 54 | //'name' => '文章分类', 55 | 'rule' => [ 56 | 'action' => 'portal/List/index', 57 | 'param' => [ 58 | 'id' => 'id' 59 | ] 60 | ],//url规则 61 | 'items' => $categories //每个子项item里必须包括id,name,如果想表示层级关系请加上 parent_id 62 | ]; 63 | 64 | return $return; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /app/portal/api/PageApi.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\api; 12 | 13 | use app\portal\model\PortalPostModel; 14 | use think\db\Query; 15 | 16 | class PageApi 17 | { 18 | /** 19 | * 页面列表 用于模板设计 20 | * @param array $param 21 | * @return false|\PDOStatement|string|\think\Collection 22 | */ 23 | public function index($param = []) 24 | { 25 | $portalPostModel = new PortalPostModel(); 26 | 27 | $where = [ 28 | 'post_type' => 2, 29 | 'post_status' => 1, 30 | 'delete_time' => 0 31 | ]; 32 | 33 | //返回的数据必须是数据集或数组,item里必须包括id,name,如果想表示层级关系请加上 parent_id 34 | return $portalPostModel->field('id,post_title AS name') 35 | ->where($where) 36 | ->where('published_time', '<', time()) 37 | ->where('published_time', '>', 0) 38 | ->where(function (Query $query) use ($param) { 39 | if (!empty($param['keyword'])) { 40 | $query->where('post_title', 'like', "%{$param['keyword']}%"); 41 | } 42 | })->select(); 43 | } 44 | 45 | /** 46 | * 页面列表 用于导航选择 47 | * @return array 48 | */ 49 | public function nav() 50 | { 51 | $portalPostModel = new PortalPostModel(); 52 | 53 | $where = [ 54 | 'post_type' => 2, 55 | 'post_status' => 1, 56 | 'delete_time' => 0 57 | ]; 58 | 59 | 60 | $pages = $portalPostModel->field('id,post_title AS name') 61 | ->where('published_time', '<', time()) 62 | ->where('published_time', '>', 0) 63 | ->where($where)->select(); 64 | 65 | $return = [ 66 | 'rule' => [ 67 | 'action' => 'portal/Page/index', 68 | 'param' => [ 69 | 'id' => 'id' 70 | ] 71 | ],//url规则 72 | 'items' => $pages //每个子项item里必须包括id,name,如果想表示层级关系请加上 parent_id 73 | ]; 74 | 75 | return $return; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/portal/controller/AdminIndexController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\AdminBaseController; 14 | 15 | /** 16 | * Class AdminIndexController 17 | * @package app\portal\controller 18 | * @adminMenuRoot( 19 | * 'name' =>'门户管理', 20 | * 'action' =>'default', 21 | * 'parent' =>'', 22 | * 'display'=> true, 23 | * 'order' => 30, 24 | * 'icon' =>'th', 25 | * 'remark' =>'门户管理' 26 | * ) 27 | */ 28 | class AdminIndexController extends AdminBaseController 29 | { 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/portal/controller/AdminTagController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use app\portal\model\PortalTagModel; 14 | use app\portal\model\PortalTagPostModel; 15 | use cmf\controller\AdminBaseController; 16 | 17 | /** 18 | * Class AdminTagController 标签管理控制器 19 | * @package app\portal\controller 20 | */ 21 | class AdminTagController extends AdminBaseController 22 | { 23 | /** 24 | * 文章标签管理 25 | * @adminMenu( 26 | * 'name' => '文章标签', 27 | * 'parent' => 'portal/AdminIndex/default', 28 | * 'display'=> true, 29 | * 'hasView'=> true, 30 | * 'order' => 10000, 31 | * 'icon' => '', 32 | * 'remark' => '文章标签', 33 | * 'param' => '' 34 | * ) 35 | */ 36 | public function index() 37 | { 38 | $content = hook_one('portal_admin_tag_index_view'); 39 | 40 | if (!empty($content)) { 41 | return $content; 42 | } 43 | 44 | $portalTagModel = new PortalTagModel(); 45 | $tags = $portalTagModel->paginate(); 46 | 47 | $this->assign("arrStatus", $portalTagModel::$STATUS); 48 | $this->assign("tags", $tags); 49 | $this->assign('page', $tags->render()); 50 | return $this->fetch(); 51 | } 52 | 53 | /** 54 | * 添加文章标签 55 | * @adminMenu( 56 | * 'name' => '添加文章标签', 57 | * 'parent' => 'index', 58 | * 'display'=> false, 59 | * 'hasView'=> true, 60 | * 'order' => 10000, 61 | * 'icon' => '', 62 | * 'remark' => '添加文章标签', 63 | * 'param' => '' 64 | * ) 65 | */ 66 | public function add() 67 | { 68 | $portalTagModel = new PortalTagModel(); 69 | $this->assign("arrStatus", $portalTagModel::$STATUS); 70 | return $this->fetch(); 71 | } 72 | 73 | /** 74 | * 添加文章标签提交 75 | * @adminMenu( 76 | * 'name' => '添加文章标签提交', 77 | * 'parent' => 'index', 78 | * 'display'=> false, 79 | * 'hasView'=> false, 80 | * 'order' => 10000, 81 | * 'icon' => '', 82 | * 'remark' => '添加文章标签提交', 83 | * 'param' => '' 84 | * ) 85 | */ 86 | public function addPost() 87 | { 88 | 89 | $arrData = $this->request->param(); 90 | 91 | $portalTagModel = new PortalTagModel(); 92 | $portalTagModel->isUpdate(false)->allowField(true)->save($arrData); 93 | 94 | $this->success(lang("SAVE_SUCCESS")); 95 | 96 | } 97 | 98 | /** 99 | * 更新文章标签状态 100 | * @adminMenu( 101 | * 'name' => '更新标签状态', 102 | * 'parent' => 'index', 103 | * 'display'=> false, 104 | * 'hasView'=> false, 105 | * 'order' => 10000, 106 | * 'icon' => '', 107 | * 'remark' => '更新标签状态', 108 | * 'param' => '' 109 | * ) 110 | */ 111 | public function upStatus() 112 | { 113 | $intId = $this->request->param("id"); 114 | $intStatus = $this->request->param("status"); 115 | $intStatus = $intStatus ? 1 : 0; 116 | if (empty($intId)) { 117 | $this->error(lang("NO_ID")); 118 | } 119 | 120 | $portalTagModel = new PortalTagModel(); 121 | $portalTagModel->where("id", $intId)->update(["status" => $intStatus]); 122 | 123 | $this->success(lang("SAVE_SUCCESS")); 124 | 125 | } 126 | 127 | /** 128 | * 删除文章标签 129 | * @adminMenu( 130 | * 'name' => '删除文章标签', 131 | * 'parent' => 'index', 132 | * 'display'=> false, 133 | * 'hasView'=> false, 134 | * 'order' => 10000, 135 | * 'icon' => '', 136 | * 'remark' => '删除文章标签', 137 | * 'param' => '' 138 | * ) 139 | */ 140 | public function delete() 141 | { 142 | $intId = $this->request->param("id", 0, 'intval'); 143 | 144 | if (empty($intId)) { 145 | $this->error(lang("NO_ID")); 146 | } 147 | 148 | PortalTagModel::where('id', $intId)->delete(); 149 | PortalTagPostModel::where('tag_id', $intId)->delete(); 150 | $this->success(lang("DELETE_SUCCESS")); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /app/portal/controller/ArticleController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | use app\portal\model\PortalCategoryModel; 15 | use app\portal\service\PostService; 16 | use app\portal\model\PortalPostModel; 17 | 18 | class ArticleController extends HomeBaseController 19 | { 20 | /** 21 | * 文章详情 22 | * @return mixed 23 | * @throws \think\Exception 24 | * @throws \think\db\exception\DataNotFoundException 25 | * @throws \think\db\exception\ModelNotFoundException 26 | * @throws \think\exception\DbException 27 | */ 28 | public function index() 29 | { 30 | 31 | $portalCategoryModel = new PortalCategoryModel(); 32 | $postService = new PostService(); 33 | 34 | $articleId = $this->request->param('id', 0, 'intval'); 35 | $categoryId = $this->request->param('cid', 0, 'intval'); 36 | $article = $postService->publishedArticle($articleId, $categoryId); 37 | 38 | if (empty($article)) { 39 | abort(404, '文章不存在!'); 40 | } 41 | 42 | 43 | $prevArticle = $postService->publishedPrevArticle($articleId, $categoryId); 44 | $nextArticle = $postService->publishedNextArticle($articleId, $categoryId); 45 | 46 | $tplName = 'article'; 47 | 48 | if (empty($categoryId)) { 49 | $categories = $article['categories']; 50 | 51 | if (count($categories) > 0) { 52 | $this->assign('category', $categories[0]); 53 | } else { 54 | abort(404, '文章未指定分类!'); 55 | } 56 | 57 | } else { 58 | $category = $portalCategoryModel->where('id', $categoryId)->where('status', 1)->find(); 59 | 60 | if (empty($category)) { 61 | abort(404, '文章不存在!'); 62 | } 63 | 64 | $this->assign('category', $category); 65 | 66 | $tplName = empty($category["one_tpl"]) ? $tplName : $category["one_tpl"]; 67 | } 68 | 69 | PortalPostModel::where('id', $articleId)->inc('post_hits')->update(); 70 | 71 | 72 | hook('portal_before_assign_article', $article); 73 | 74 | $this->assign('article', $article); 75 | $this->assign('prev_article', $prevArticle); 76 | $this->assign('next_article', $nextArticle); 77 | 78 | $tplName = empty($article['more']['template']) ? $tplName : $article['more']['template']; 79 | 80 | return $this->fetch("/$tplName"); 81 | } 82 | 83 | // 文章点赞 84 | public function doLike() 85 | { 86 | $this->checkUserLogin(); 87 | $articleId = $this->request->param('id', 0, 'intval'); 88 | 89 | 90 | $canLike = cmf_check_user_action("posts$articleId", 1); 91 | 92 | if ($canLike) { 93 | PortalPostModel::where('id', $articleId)->inc('post_like')->update(); 94 | 95 | $this->success("赞好啦!"); 96 | } else { 97 | $this->error("您已赞过啦!"); 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /app/portal/controller/IndexController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | 15 | class IndexController extends HomeBaseController 16 | { 17 | public function index() 18 | { 19 | return $this->fetch(':index'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/portal/controller/ListController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | use app\portal\model\PortalCategoryModel; 15 | 16 | class ListController extends HomeBaseController 17 | { 18 | /*** 19 | * 文章列表 20 | * @return mixed 21 | * @throws \think\db\exception\DataNotFoundException 22 | * @throws \think\db\exception\ModelNotFoundException 23 | * @throws \think\exception\DbException 24 | */ 25 | public function index() 26 | { 27 | $id = $this->request->param('id', 0, 'intval'); 28 | $portalCategoryModel = new PortalCategoryModel(); 29 | 30 | $category = $portalCategoryModel->where('id', $id)->where('status', 1)->find(); 31 | 32 | $this->assign('category', $category); 33 | 34 | $listTpl = empty($category['list_tpl']) ? 'list' : $category['list_tpl']; 35 | 36 | return $this->fetch('/' . $listTpl); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/portal/controller/PageController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | use app\portal\service\PostService; 15 | 16 | class PageController extends HomeBaseController 17 | { 18 | /** 19 | * 页面管理 20 | * @return mixed 21 | * @throws \think\db\exception\DataNotFoundException 22 | * @throws \think\db\exception\ModelNotFoundException 23 | * @throws \think\exception\DbException 24 | */ 25 | public function index() 26 | { 27 | $postService = new PostService(); 28 | $pageId = $this->request->param('id', 0, 'intval'); 29 | $page = $postService->publishedPage($pageId); 30 | 31 | if (empty($page)) { 32 | abort(404, ' 页面不存在!'); 33 | } 34 | 35 | $this->assign('page', $page); 36 | 37 | $more = $page['more']; 38 | 39 | $tplName = empty($more['template']) ? 'page' : $more['template']; 40 | 41 | return $this->fetch("/$tplName"); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/portal/controller/SearchController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | 15 | class SearchController extends HomeBaseController 16 | { 17 | /** 18 | * 搜索 19 | * @return mixed 20 | */ 21 | public function index() 22 | { 23 | $keyword = $this->request->param('keyword'); 24 | 25 | if (empty($keyword)) { 26 | $this -> error("关键词不能为空!请重新输入!"); 27 | } 28 | 29 | $this -> assign("keyword", $keyword); 30 | return $this->fetch('/search'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/portal/controller/TagController.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\controller; 12 | 13 | use cmf\controller\HomeBaseController; 14 | use app\portal\model\PortalTagModel; 15 | 16 | class TagController extends HomeBaseController 17 | { 18 | /** 19 | * 标签 20 | * @return mixed 21 | * @throws \think\db\exception\DataNotFoundException 22 | * @throws \think\db\exception\ModelNotFoundException 23 | * @throws \think\exception\DbException 24 | */ 25 | public function index() 26 | { 27 | $id = $this->request->param('id'); 28 | 29 | $portalTagModel = new PortalTagModel(); 30 | 31 | if(is_numeric($id)){ 32 | $tag = $portalTagModel->where('id', $id)->where('status', 1)->find(); 33 | }else{ 34 | $tag = $portalTagModel->where('name', $id)->where('status', 1)->find(); 35 | } 36 | 37 | 38 | if (empty($tag)) { 39 | abort(404, '标签不存在!'); 40 | } 41 | 42 | $this->assign('tag', $tag); 43 | 44 | return $this->fetch('/tag'); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/portal/data/portal.sql: -------------------------------------------------------------------------------- 1 | 2 | -- 3 | -- 表的结构 `cmf_portal_category` 4 | -- 5 | 6 | CREATE TABLE IF NOT EXISTS `cmf_portal_category` ( 7 | `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '分类id', 8 | `parent_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '分类父id', 9 | `post_count` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '分类文章数', 10 | `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态,1:发布,0:不发布', 11 | `delete_time` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除时间', 12 | `list_order` float NOT NULL DEFAULT '10000' COMMENT '排序', 13 | `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '分类名称', 14 | `description` varchar(255) NOT NULL DEFAULT '' COMMENT '分类描述', 15 | `path` varchar(255) NOT NULL DEFAULT '' COMMENT '分类层级关系路径', 16 | `seo_title` varchar(100) NOT NULL DEFAULT '', 17 | `seo_keywords` varchar(255) NOT NULL DEFAULT '', 18 | `seo_description` varchar(255) NOT NULL DEFAULT '', 19 | `list_tpl` varchar(50) NOT NULL DEFAULT '' COMMENT '分类列表模板', 20 | `one_tpl` varchar(50) NOT NULL DEFAULT '' COMMENT '分类文章页模板', 21 | `more` text COMMENT '扩展属性', 22 | PRIMARY KEY (`id`) 23 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='portal应用 文章分类表'; 24 | 25 | -- -------------------------------------------------------- 26 | 27 | -- 28 | -- 表的结构 `cmf_portal_category_post` 29 | -- 30 | 31 | CREATE TABLE IF NOT EXISTS `cmf_portal_category_post` ( 32 | `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, 33 | `post_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '文章id', 34 | `category_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '分类id', 35 | `list_order` float NOT NULL DEFAULT '10000' COMMENT '排序', 36 | `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态,1:发布;0:不发布', 37 | PRIMARY KEY (`id`), 38 | KEY `term_taxonomy_id` (`category_id`) 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='portal应用 分类文章对应表'; 40 | 41 | -- -------------------------------------------------------- 42 | 43 | -- 44 | -- 表的结构 `cmf_portal_post` 45 | -- 46 | 47 | CREATE TABLE IF NOT EXISTS `cmf_portal_post` ( 48 | `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, 49 | `parent_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '父级id', 50 | `post_type` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '类型,1:文章;2:页面', 51 | `post_format` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '内容格式;1:html;2:md', 52 | `user_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '发表者用户id', 53 | `post_status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态;1:已发布;0:未发布;', 54 | `comment_status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '评论状态;1:允许;0:不允许', 55 | `is_top` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否置顶;1:置顶;0:不置顶', 56 | `recommended` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否推荐;1:推荐;0:不推荐', 57 | `post_hits` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '查看数', 58 | `post_like` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '点赞数', 59 | `comment_count` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '评论数', 60 | `create_time` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间', 61 | `update_time` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '更新时间', 62 | `published_time` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '发布时间', 63 | `delete_time` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除时间', 64 | `post_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT 'post标题', 65 | `post_keywords` varchar(150) NOT NULL DEFAULT '' COMMENT 'seo keywords', 66 | `post_excerpt` varchar(500) NOT NULL DEFAULT '' COMMENT 'post摘要', 67 | `post_source` varchar(150) NOT NULL DEFAULT '' COMMENT '转载文章的来源', 68 | `post_content` text COMMENT '文章内容', 69 | `post_content_filtered` text COMMENT '处理过的文章内容', 70 | `more` text COMMENT '扩展属性,如缩略图;格式为json', 71 | PRIMARY KEY (`id`), 72 | KEY `type_status_date` (`post_type`,`post_status`,`create_time`,`id`), 73 | KEY `parent_id` (`parent_id`), 74 | KEY `user_id` (`user_id`), 75 | KEY `create_time` (`create_time`) USING BTREE 76 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='portal应用 文章表' ROW_FORMAT=COMPACT; 77 | 78 | -- -------------------------------------------------------- 79 | 80 | -- 81 | -- 表的结构 `cmf_portal_tag` 82 | -- 83 | 84 | CREATE TABLE IF NOT EXISTS `cmf_portal_tag` ( 85 | `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '分类id', 86 | `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态,1:发布,0:不发布', 87 | `recommended` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否推荐;1:推荐;0:不推荐', 88 | `post_count` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '标签文章数', 89 | `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '标签名称', 90 | PRIMARY KEY (`id`) 91 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='portal应用 文章标签表'; 92 | 93 | -- -------------------------------------------------------- 94 | 95 | -- 96 | -- 表的结构 `cmf_portal_tag_post` 97 | -- 98 | 99 | CREATE TABLE IF NOT EXISTS `cmf_portal_tag_post` ( 100 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 101 | `tag_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '标签 id', 102 | `post_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '文章 id', 103 | `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '1' COMMENT '状态,1:发布;0:不发布', 104 | PRIMARY KEY (`id`), 105 | KEY `post_id` (`post_id`) 106 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='portal应用 标签文章对应表'; 107 | 108 | -- -------------------------------------------------------- 109 | 110 | 111 | -- 增缩略图字段 112 | ALTER TABLE `cmf_portal_post` ADD `thumbnail` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '缩略图' AFTER `post_source`; 113 | ALTER TABLE `cmf_portal_post` ADD `post_favorites` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '收藏数' AFTER `post_hits`; 114 | -------------------------------------------------------------------------------- /app/portal/hooks.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'portal_before_assign_article' => [ 13 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 14 | "name" => '文章显示之前', // 钩子名称 15 | "description" => "文章显示之前", //钩子描述 16 | "once" => 0 // 是否只执行一次 17 | ], 18 | 'portal_admin_after_save_article' => [ 19 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 20 | "name" => '后台文章保存之后', // 钩子名称 21 | "description" => "后台文章保存之后", //钩子描述 22 | "once" => 0 // 是否只执行一次 23 | ], 24 | 'portal_admin_article_index_view' => [ 25 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 26 | "name" => '门户后台文章管理列表界面', // 钩子名称 27 | "description" => "门户后台文章管理列表界面", //钩子描述 28 | "once" => 1 // 是否只执行一次 29 | ], 30 | 'portal_admin_article_add_view' => [ 31 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 32 | "name" => '门户后台文章添加界面', // 钩子名称 33 | "description" => "门户后台文章添加界面", //钩子描述 34 | "once" => 1 // 是否只执行一次 35 | ], 36 | 'portal_admin_article_edit_view' => [ 37 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 38 | "name" => '门户后台文章编辑界面', // 钩子名称 39 | "description" => "门户后台文章编辑界面", //钩子描述 40 | "once" => 1 // 是否只执行一次 41 | ], 42 | 'portal_admin_category_index_view' => [ 43 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 44 | "name" => '门户后台文章分类管理列表界面', // 钩子名称 45 | "description" => "门户后台文章分类管理列表界面", //钩子描述 46 | "once" => 1 // 是否只执行一次 47 | ], 48 | 'portal_admin_category_add_view' => [ 49 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 50 | "name" => '门户后台文章分类添加界面', // 钩子名称 51 | "description" => "门户后台文章分类添加界面", //钩子描述 52 | "once" => 1 // 是否只执行一次 53 | ], 54 | 'portal_admin_category_edit_view' => [ 55 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 56 | "name" => '门户后台文章分类编辑界面', // 钩子名称 57 | "description" => "门户后台文章分类编辑界面", //钩子描述 58 | "once" => 1 // 是否只执行一次 59 | ], 60 | 'portal_admin_page_index_view' => [ 61 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 62 | "name" => '门户后台页面管理列表界面', // 钩子名称 63 | "description" => "门户后台页面管理列表界面", //钩子描述 64 | "once" => 1 // 是否只执行一次 65 | ], 66 | 'portal_admin_page_add_view' => [ 67 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 68 | "name" => '门户后台页面添加界面', // 钩子名称 69 | "description" => "门户后台页面添加界面", //钩子描述 70 | "once" => 1 // 是否只执行一次 71 | ], 72 | 'portal_admin_page_edit_view' => [ 73 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 74 | "name" => '门户后台页面编辑界面', // 钩子名称 75 | "description" => "门户后台页面编辑界面", //钩子描述 76 | "once" => 1 // 是否只执行一次 77 | ], 78 | 'portal_admin_tag_index_view' => [ 79 | "type" => 2,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 80 | "name" => '门户后台文章标签管理列表界面', // 钩子名称 81 | "description" => "门户后台文章标签管理列表界面", //钩子描述 82 | "once" => 1 // 是否只执行一次 83 | ], 84 | 'portal_admin_article_edit_view_right_sidebar' => [ 85 | "type" => 4,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 86 | "name" => '门户后台文章添加编辑界面右侧栏', // 钩子名称 87 | "description" => "门户后台文章添加编辑界面右侧栏", //钩子描述 88 | "once" => 0 // 是否只执行一次 89 | ], 90 | 'portal_admin_article_edit_view_main' => [ 91 | "type" => 4,//钩子类型(默认为应用钩子;2:应用钩子;3:模板钩子;4:后台模板钩子) 92 | "name" => '门户后台文章添加编辑界面主要内容', // 钩子名称 93 | "description" => "门户后台文章添加编辑界面主要内容", //钩子描述 94 | "once" => 0 // 是否只执行一次 95 | ], 96 | ]; -------------------------------------------------------------------------------- /app/portal/lang/en-us.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'ADMIN_CENTER' => 'Admin Center', 13 | ]; -------------------------------------------------------------------------------- /app/portal/lang/en-us/common.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'TABLE_PORTAL_CATEGORY' => 'Article Category', 13 | 'TABLE_PORTAL_POST' => 'Article', 14 | 'TABLE_PORTAL_POST#PAGE' => 'Page' 15 | ]; -------------------------------------------------------------------------------- /app/portal/lang/zh-cn.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'ADMIN_TAG_ADD' => '添加标签', 13 | 'ADMIN_TAG_DELETE' => '删除标签', 14 | 'ADMIN_TAG_INDEX' => '标签列表', 15 | 'SAVE_SUCCESS' => '保存成功!', 16 | 'DELETE_SUCCESS' => '删除成功!', 17 | 'ADD_SUCCESS' => '添加成功', 18 | 'DELETE_FAILED' => '删除失败', 19 | 'ADD_FAILED' => '添加失败', 20 | ]; 21 | 22 | -------------------------------------------------------------------------------- /app/portal/lang/zh-cn/common.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'TABLE_PORTAL_CATEGORY' => '文章分类', 13 | 'TABLE_PORTAL_POST' => '文章', 14 | 'TABLE_SLIDE' => '幻灯片', 15 | 'TABLE_PORTAL_POST#PAGE' => '页面' 16 | ]; -------------------------------------------------------------------------------- /app/portal/lang/zh-cn/home.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | /*前台通用语言包*/ 12 | return [ 13 | ]; -------------------------------------------------------------------------------- /app/portal/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "门户应用", 3 | "name": "portal", 4 | "version": "1.0.0", 5 | "demo_url": "http://demo.thinkcmf.com", 6 | "author": "ThinkCMF", 7 | "author_url": "http://www.thinkcmf.com", 8 | "keywords": "ThinkCMF portal应用", 9 | "description": "ThinkCMF portal应用" 10 | } 11 | -------------------------------------------------------------------------------- /app/portal/model/PortalCategoryPostModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\model; 12 | 13 | use think\Model; 14 | 15 | class PortalCategoryPostModel extends Model 16 | { 17 | /** 18 | * 模型名称 19 | * @var string 20 | */ 21 | protected $name = 'portal_category_post'; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/portal/model/PortalTagModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\model; 12 | 13 | use think\Model; 14 | 15 | class PortalTagModel extends Model 16 | { 17 | /** 18 | * 模型名称 19 | * @var string 20 | */ 21 | protected $name = 'portal_tag'; 22 | 23 | public static $STATUS = array( 24 | 0=>"未启用", 25 | 1=>"已启用", 26 | ); 27 | } -------------------------------------------------------------------------------- /app/portal/model/PortalTagPostModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\model; 12 | 13 | use think\Model; 14 | 15 | class PortalTagPostModel extends Model 16 | { 17 | /** 18 | * 模型名称 19 | * @var string 20 | */ 21 | protected $name = 'portal_tag_post'; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/portal/model/RecycleBinModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\model; 12 | 13 | use think\Model; 14 | 15 | class RecycleBinModel extends Model 16 | { 17 | /** 18 | * 模型名称 19 | * @var string 20 | */ 21 | protected $name = 'recycle_bin'; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/portal/model/UserModel.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\model; 12 | 13 | use think\Model; 14 | 15 | class UserModel extends Model 16 | { 17 | 18 | /** 19 | * 模型名称 20 | * @var string 21 | */ 22 | protected $name = 'user'; 23 | 24 | protected $type = [ 25 | 'more' => 'array', 26 | ]; 27 | 28 | 29 | } -------------------------------------------------------------------------------- /app/portal/nav.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | ['name' => '文章分类', 'api' => "Category/nav"], 13 | ['name' => '所有页面', 'api' => "Page/nav"] 14 | ]; -------------------------------------------------------------------------------- /app/portal/url.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | return [ 12 | 'List/index' => [ 13 | 'name' => '门户应用-文章列表', 14 | 'vars' => [ 15 | 'id' => [ 16 | 'pattern' => '\d+', 17 | 'require' => true 18 | ] 19 | ], 20 | 'simple' => true 21 | ], 22 | 'Page/index' => [ 23 | 'name' => '门户应用-页面页', 24 | 'vars' => [ 25 | 'id' => [ 26 | 'pattern' => '\d+', 27 | 'require' => true 28 | ] 29 | ], 30 | 'simple' => true 31 | ], 32 | 'Article/index' => [ 33 | 'name' => '门户应用-文章页', 34 | 'vars' => [ 35 | 'id' => [ 36 | 'pattern' => '\d+', 37 | 'require' => true 38 | ], 39 | 'cid' => [ 40 | 'pattern' => '\d+', 41 | 'require' => false 42 | ] 43 | ], 44 | 'simple' => true 45 | ], 46 | 'Search/index' => [ 47 | 'name' => '门户应用-搜索页', 48 | 'vars' => [ 49 | 50 | ], 51 | 'simple' => false 52 | ], 53 | ]; -------------------------------------------------------------------------------- /app/portal/user_action.php: -------------------------------------------------------------------------------- 1 | [ 4 | // 'name' => '用户登录',//用户操作名称 5 | // 'score' => 1,//更改积分,可以为负 6 | // 'coin' => 0,//更改金币,可以为负 7 | // 'cycle_time' => 1,//周期时间值 8 | // 'cycle_type' => 1,//周期类型;0:不限;1:按天;2:按小时;3:永久 9 | // 'reward_number' => 1,//奖励次数 10 | // 'url' => [ 11 | // 'action' => 'portal/Test/test', 12 | // 'param' => ['id' => 1] 13 | // ],//执行操作的url 14 | // ] 15 | ]; -------------------------------------------------------------------------------- /app/portal/validate/AdminArticleValidate.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\validate; 12 | 13 | use think\Validate; 14 | 15 | class AdminArticleValidate extends Validate 16 | { 17 | protected $rule = [ 18 | 'categories' => 'require', 19 | 'post_title' => 'require', 20 | ]; 21 | protected $message = [ 22 | 'categories.require' => '请指定文章分类!', 23 | 'post_title.require' => '文章标题不能为空!', 24 | ]; 25 | 26 | protected $scene = [ 27 | // 'add' => ['user_login,user_pass,user_email'], 28 | // 'edit' => ['user_login,user_email'], 29 | ]; 30 | } -------------------------------------------------------------------------------- /app/portal/validate/AdminPageValidate.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\validate; 12 | 13 | use app\admin\model\RouteModel; 14 | use think\Validate; 15 | 16 | class AdminPageValidate extends Validate 17 | { 18 | protected $rule = [ 19 | 'post_title' => 'require', 20 | 'post_alias' => 'checkAlias' 21 | ]; 22 | protected $message = [ 23 | 'post_title.require' => '页面标题不能为空', 24 | ]; 25 | 26 | protected $scene = [ 27 | // 'add' => ['user_login,user_pass,user_email'], 28 | // 'edit' => ['user_login,user_email'], 29 | ]; 30 | 31 | // 自定义验证规则 32 | protected function checkAlias($value, $rule, $data) 33 | { 34 | if (empty($value)) { 35 | return true; 36 | } 37 | 38 | if (preg_match("/^\d+$/", $value)) { 39 | return "别名不能为纯数字!"; 40 | } 41 | 42 | $routeModel = new RouteModel(); 43 | $fullUrl = $routeModel->buildFullUrl('portal/Page/index', ['id' => $data['id']]); 44 | if (!$routeModel->existsRoute($value, $fullUrl)) { 45 | return true; 46 | } else { 47 | return "别名已经存在!"; 48 | } 49 | 50 | } 51 | } -------------------------------------------------------------------------------- /app/portal/validate/PortalCategoryValidate.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | namespace app\portal\validate; 12 | 13 | use app\admin\model\RouteModel; 14 | use think\Validate; 15 | 16 | class PortalCategoryValidate extends Validate 17 | { 18 | protected $rule = [ 19 | 'name' => 'require', 20 | 'alias' => 'checkAlias', 21 | ]; 22 | protected $message = [ 23 | 'name.require' => '分类名称不能为空', 24 | ]; 25 | 26 | protected $scene = [ 27 | // 'add' => ['user_login,user_pass,user_email'], 28 | // 'edit' => ['user_login,user_email'], 29 | ]; 30 | 31 | // 自定义验证规则 32 | protected function checkAlias($value, $rule, $data) 33 | { 34 | if (empty($value)) { 35 | return true; 36 | } 37 | 38 | if (preg_match("/^\d+$/", $value)) { 39 | return "别名不能为纯数字!"; 40 | } 41 | 42 | $routeModel = new RouteModel(); 43 | if (isset($data['id']) && $data['id'] > 0) { 44 | $fullUrl = $routeModel->buildFullUrl('portal/List/index', ['id' => $data['id']]); 45 | } else { 46 | $fullUrl = $routeModel->getFullUrlByUrl($data['alias']); 47 | } 48 | if (!$routeModel->existsRoute($value, $fullUrl)) { 49 | return true; 50 | } else { 51 | return "别名已经存在!"; 52 | } 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /app/portal/version: -------------------------------------------------------------------------------- 1 | 1.0.0 -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_article/copy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 |
7 | 8 | 11 |
12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_article/move.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 |
7 | 8 | 11 |
12 | 13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_article/recyclebin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 8 |
9 | 分类: 10 |    13 | 时间: 14 | - 15 |     16 | 关键字: 17 | 18 | 19 | 清空 20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | $status=array("1"=>"已审核","0"=>"未审核"); 42 | $top_status=array("1"=>"已置顶","0"=>"未置顶"); 43 | $recommend_status=array("1"=>"已推荐","0"=>"未推荐"); 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 59 | 83 | 84 | 97 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
ID{:L('TITLE')}{:L('AUTHOR')}{:L('HITS')}{:L('COMMENT_COUNT')}{:L('KEYWORDS')}/{:L('SOURCE')}/{:L('ABSTRACT')}/{:L('THUMBNAIL')}{:L('PUBLISH_DATE')}{:L('STATUS')}{:L('ACTIONS')}
{$vo.id}{$vo.post_title}{$vo.user_nickname|default=$vo.user_login}{$vo.post_hits} 53 | 54 | {$vo.comment_count} 55 | 56 | {$vo.comment_count} 57 | 58 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | $smeta=json_decode($vo['smeta'],true); 77 | 78 | 79 | 80 | 81 | 82 | {:date('Y-m-d H:i',strtotime($vo['post_date']))} 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 98 | 还原| 99 | 删除 100 |
ID{:L('TITLE')}{:L('AUTHOR')}{:L('HITS')}{:L('COMMENT_COUNT')}{:L('KEYWORDS')}/{:L('SOURCE')}/{:L('ABSTRACT')}/{:L('THUMBNAIL')}{:L('PUBLISH_DATE')}{:L('STATUS')}{:L('ACTIONS')}
118 |
119 | 120 |
121 | 122 |
123 |
124 | 125 | 126 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_category/select.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 33 | {$categories_tree} 34 | 35 |
10 | 13 | ID分类名称
36 |
37 |
38 | 39 | 78 | 79 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 9 |
10 | 标题: 11 | 13 | 14 |
15 |
16 |
17 | 20 |
21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | $status=array("1"=>'已发布',"0"=>'未发布'); 38 | 39 | 40 | 44 | 45 | 50 | 51 | 58 | 65 | 69 | 70 | 71 | 72 | 73 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
25 | 28 | ID标题作者发布时间状态操作
41 | 43 | {$vo.id} 46 | 47 | {$vo.post_title} 48 | 49 | {$vo.user_nickname} 52 | 53 | 未发布 54 | 55 | {:date('Y-m-d H:i',$vo['published_time'])} 56 | 57 | 59 | 60 | 61 | 62 | 63 | 64 | 66 | {:lang('EDIT')} 67 | {:lang('DELETE')} 68 |
74 | 77 | ID标题作者发布时间状态操作
87 |
88 | 91 |
92 | 93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_page/recyclebin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 8 |
9 | 时间: 10 | - 11 | 12 | 关键字: 13 | 14 | 15 |
16 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
ID标题发布人发布时间{:L('ACTIONS')}
{$vo.id}{$vo.post_title}{$users[$vo['post_author']]['user_login']}{$vo.post_date} 41 | 还原| 42 | {:L('DELETE')} 43 |
ID标题发布人发布时间{:L('ACTIONS')}
58 |
59 | 60 |
61 | 62 |
63 |
64 | 65 | 66 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_tag/add.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 10 |
11 | 12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 |
21 | 26 |
27 |
28 |
29 | 30 | 返回 31 |
32 |
33 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_tag/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 9 |
10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
ID标签名称状态操作
{$vo.id}{$vo.name}{$arrStatus[$vo['status']]} 29 | 30 | 禁用 32 | 33 | 启用 35 | 36 | 删除 38 |
ID标签名称状态操作
51 |
52 | 53 |
54 |
55 |
    {$page|default=''}
56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /public/themes/admin_simpleboot3/portal/admin_tag/select.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
10 | 13 | ID分类名称分类描述
23 | $checked = in_array($vo['id'],$selectedIds)?'checked':''; 24 | 26 | {$vo.id}{$vo.name}{$vo.description}
34 |
35 |
36 | 37 | 60 | 61 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/README.md: -------------------------------------------------------------------------------- 1 | ThinkCMF默认模板,主要用于基础功能演示 2 | 3 | ### 更新日志 4 | #### 1.0.2 5 | * 规范 jq,和 wind.js 引入 6 | * 更改 comment钩子参数 7 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simpleboot3", 3 | "version": "1.0.2", 4 | "demo_url": "http://demo.thinkcmf.com", 5 | "author": "ThinkCMF", 6 | "lang": "zh-cn", 7 | "author_url": "http://www.thinkcmf.com", 8 | "keywords": "ThinkCMF模板", 9 | "description": "ThinkCMF默认模板" 10 | } 11 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/article.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$article.post_title} 5 | 6 | 7 | 8 | 18 | 19 | 20 | 21 | 22 |
23 |
24 |
25 |
26 |

{$article.post_title}

27 | 44 |
45 | 46 | $before_content_hook_param=[ 47 | 'object_id'=>$article['id'], 48 | 'table_name'=>'portal_post', 49 | 'object_title'=>$article['post_title'], 50 | 'user_id'=>$article['user_id'], 51 | 'url'=>cmf_url_encode('portal/Article/index',array('id'=>$article['id'],'cid'=>$category['id'])), 52 | 'object'=>$article 53 | ]; 54 | 55 | 56 | 57 |
58 | {$article.post_content} 59 |
60 | 61 |
62 | 注:本文转载自{$article.post_source},转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除。 63 |
64 |
65 | 66 | 67 | $after_content_hook_param=[ 68 | 'object_id'=>$article['id'], 69 | 'table_name'=>'portal_post', 70 | 'object_title'=>$article['post_title'], 71 | 'user_id'=>$article['user_id'], 72 | 'url'=>cmf_url_encode('portal/Article/index',array('id'=>$article['id'],'cid'=>$category['id'])), 73 | 'object'=>$article 74 | ]; 75 | 76 | 77 | 78 | 79 | $comment_hook_param=[ 80 | 'object_id'=>$article['id'], 81 | 'table_name'=>'portal_post', 82 | 'object_title'=>$article['post_title'], 83 | 'url'=>cmf_url_encode('portal/Article/index',array('id'=>$article['id'],'cid'=>$category['id'])), 84 | 'user_id'=>$article['user_id'], 85 | ]; 86 | $comment=hook_one('comment',$comment_hook_param); 87 | 88 | 89 | 90 |
91 | 95 |
96 |
97 | {$comment} 98 |
99 | 100 | 101 |
102 |
103 |
104 |
105 |

热门文章

106 |
107 |
108 | 109 | $hot_articles=[]; 110 | 111 | 123 |
124 |
125 | 126 |
127 | 128 |
129 | 130 | 131 |
132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/article.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "文章页", 3 | "action": "portal/Article/index", 4 | "description": "文章页模板文件", 5 | "order": 10.0, 6 | "more": { 7 | "vars": { 8 | "hot_articles_category_id": { 9 | "title": "Hot Articles分类ID", 10 | "value": "1", 11 | "type": "text", 12 | "tip": "", 13 | "rule": [] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 联系我们 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 | 25 | $company_location=empty($theme_vars['company_location'])?'121.449222,31.193348':$theme_vars['company_location']; 26 | $company_location=explode(',',$company_location); 27 | $company_location_lng=$company_location[0]; 28 | $company_location_lat=$company_location[1]; 29 | 30 | 45 |
46 |
47 |
48 |
49 |
50 | $guestbook=hook_one('guestbook'); 51 | 52 |
53 | 57 |
58 |
59 | {$guestbook} 60 |
61 |
62 |
63 |
64 |

联系方式

65 |
66 |
地址
67 |

{$theme_vars.address_cn|default=''}

68 | 69 |
邮箱
70 |

{$theme_vars.email|default=''}

71 | 72 |
电话
73 |

{$theme_vars.phone_cn|default=''}

74 |
75 |
76 |
77 |

Contact

78 |
79 |
Address
80 |

{$theme_vars.address_en|default=''}

81 | 82 |
Email
83 |

{$theme_vars.email|default=''}

84 | 85 |
Phone
86 |

{$theme_vars.phone_en|default=''}

87 |
88 |
89 |
90 | 91 | $company_qq=empty($theme_vars['qq'])?'':$theme_vars['qq']; 92 | $company_qq=explode(',',$company_qq); 93 | 94 | 95 |

快捷交流

96 |

点击以下QQ图标,免加好友即时洽谈合作

97 | 107 |
108 |
109 |
110 | 111 |
112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/contact.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "联系我们页", 3 | "action": "portal/Page/index", 4 | "description": "联系我们页模板文件", 5 | "order": 10.0, 6 | "more": { 7 | "vars": { 8 | "baidu_map_info_window_text": { 9 | "title": "百度地图标注文字", 10 | "name": "baidu_map_info_window_text", 11 | "value": "ThinkCMF
地址:上海市徐汇区斜土路2601号", 12 | "type": "text", 13 | "tip": "百度地图标注文字,支持简单html代码", 14 | "rule": [] 15 | }, 16 | "company_location": { 17 | "title": "公司坐标", 18 | "value": "", 19 | "type": "location", 20 | "tip": "", 21 | "rule": { 22 | "require": true 23 | } 24 | }, 25 | "address_cn": { 26 | "title": "公司地址", 27 | "value": "上海市徐汇区斜土路0001号", 28 | "type": "text", 29 | "tip": "", 30 | "rule": { 31 | "require": true 32 | } 33 | }, 34 | "address_en": { 35 | "title": "公司地址(英文)", 36 | "value": "NO.0001 Xie Tu Road, Shanghai China", 37 | "type": "text", 38 | "tip": "", 39 | "rule": { 40 | "require": true 41 | } 42 | }, 43 | "email": { 44 | "title": "公司邮箱", 45 | "value": "catman@thinkcmf.com", 46 | "type": "text", 47 | "tip": "", 48 | "rule": { 49 | "require": true 50 | } 51 | }, 52 | "phone_cn": { 53 | "title": "公司电话", 54 | "value": "021 1000 0001", 55 | "type": "text", 56 | "tip": "", 57 | "rule": { 58 | "require": true 59 | } 60 | }, 61 | "phone_en": { 62 | "title": "公司电话(英文)", 63 | "value": "+8621 1000 0001", 64 | "type": "text", 65 | "tip": "", 66 | "rule": { 67 | "require": true 68 | } 69 | }, 70 | "qq": { 71 | "title": "联系QQ", 72 | "value": "478519726", 73 | "type": "text", 74 | "tip": "多个 QQ以英文逗号隔开", 75 | "rule": { 76 | "require": true 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "首页", 3 | "action": "portal/Index/index", 4 | "description": "首页模板文件", 5 | "order": 5.0, 6 | "more": { 7 | "vars": { 8 | "top_slide": { 9 | "title": "顶部幻灯片", 10 | "value": "", 11 | "type": "text", 12 | "dataSource": { 13 | "api": "admin/Slide/index", 14 | "multi": false 15 | }, 16 | "placeholder": "请选择顶部幻灯片", 17 | "tip": "顶部幻灯片", 18 | "rule": { 19 | "require": true 20 | } 21 | } 22 | }, 23 | "widgets": { 24 | "features": { 25 | "title": "快速了解ThinkCMF", 26 | "display": "1", 27 | "vars": { 28 | "sub_title": { 29 | "title": "副标题", 30 | "value": "Quickly understand the ThinkCMF", 31 | "type": "text", 32 | "placeholder": "请输入副标题", 33 | "tip": "", 34 | "rule": { 35 | "require": true 36 | } 37 | }, 38 | "features": { 39 | "title": "特性介绍", 40 | "value": [ 41 | { 42 | "title": "MVC分层模式", 43 | "icon": "bars", 44 | "content": "使用MVC应用程序被分成三个核心部件:模型(M)、视图(V)、控制器(C),他不是一个新的概念,只是ThinkCMF将其发挥到了极致。" 45 | }, 46 | { 47 | "title": "用户管理", 48 | "icon": "group", 49 | "content": "ThinkCMF内置了灵活的用户管理方式,并可直接与第三方站点进行互联互通,如果你愿意甚至可以对单个用户或群体用户的行为进行记录及分享,为您的运营决策提供有效参考数据。" 50 | }, 51 | { 52 | "title": "云端部署", 53 | "icon": "cloud", 54 | "content": "通过驱动的方式可以轻松支持云平台的部署,让你的网站无缝迁移,内置已经支持SAE、BAE,正式版将对云端部署进行进一步优化。" 55 | }, 56 | { 57 | "title": "安全策略", 58 | "icon": "heart", 59 | "content": "提供的稳健的安全策略,包括备份恢复,容错,防治恶意攻击登陆,网页防篡改等多项安全管理功能,保证系统安全,可靠,稳定的运行。" 60 | }, 61 | { 62 | "title": "应用模块化", 63 | "icon": "cubes", 64 | "content": "提出全新的应用模式进行扩展,不管是你开发一个小功能还是一个全新的站点,在ThinkCMF中你只是增加了一个APP,每个独立运行互不影响,便于灵活扩展和二次开发。" 65 | }, 66 | { 67 | "title": "免费开源", 68 | "icon": "certificate", 69 | "content": "代码遵循Apache2开源协议,免费使用,对商业用户也无任何限制。" 70 | } 71 | ], 72 | "type": "array", 73 | "item": { 74 | "title": { 75 | "title": "标题", 76 | "value": "", 77 | "type": "text", 78 | "rule": { 79 | "require": true 80 | } 81 | }, 82 | "icon": { 83 | "title": "图标", 84 | "value": "", 85 | "type": "text" 86 | }, 87 | "content": { 88 | "title": "描述", 89 | "value": "", 90 | "type": "textarea" 91 | } 92 | }, 93 | "tip": "" 94 | 95 | } 96 | } 97 | }, 98 | "last_news": { 99 | "title": "最新资讯", 100 | "display": "1", 101 | "vars": { 102 | "last_news_category_id": { 103 | "title": "文章分类ID", 104 | "value": "", 105 | "type": "text", 106 | "dataSource": { 107 | "api": "portal/Category/index", 108 | "multi": true 109 | }, 110 | "placeholder": "请选择分类", 111 | "tip": "", 112 | "rule": { 113 | "require": true 114 | } 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "文章列表页", 3 | "action": "portal/List/index", 4 | "description": "文章列表模板文件", 5 | "order": 10.0, 6 | "more": { 7 | "vars": { 8 | 9 | }, 10 | "widgets":{ 11 | "hottest_articles": { 12 | "title": "热门文章", 13 | "display": "1", 14 | "vars": { 15 | "hottest_articles_category_id": { 16 | "title": "文章分类ID", 17 | "value": "", 18 | "type": "text", 19 | "dataSource": { 20 | "api": "portal/category/index", 21 | "multi": true 22 | }, 23 | "placeholder": "请选择分类", 24 | "tip": "", 25 | "rule": { 26 | "require": true 27 | } 28 | } 29 | } 30 | }, 31 | "last_articles": { 32 | "title": "最新发布", 33 | "display": "1", 34 | "vars": { 35 | "last_articles_category_id": { 36 | "title": "文章分类ID", 37 | "value": "", 38 | "type": "text", 39 | "dataSource": { 40 | "api": "portal/category/index", 41 | "multi": true 42 | }, 43 | "placeholder": "请选择分类", 44 | "tip": "", 45 | "rule": { 46 | "require": true 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$page.post_title} 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |
21 |
22 |

{$page.post_title|default=''}

23 |
24 |
25 | {$page.post_content|default=''} 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 |
34 |

{$widget.title}

35 |
36 |
37 | 38 | $hot_articles=[]; 39 | 40 | 53 |
54 |
55 |
56 | 57 | 58 | 59 |
60 |
61 |

{$widget.title}

62 |
63 |
64 | 66 |
67 |
68 | 70 | 71 | {$vo.post_title} 73 | 74 | {$vo.post_title} 76 | 77 | 78 |
79 |
80 | {$vo.post_title} 81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | 89 | 90 |
91 | 92 | 93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/page.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "单页面", 3 | "action": "portal/Page/index", 4 | "description": "单页面模板文件", 5 | "order": 10.0, 6 | "more": { 7 | "widgets":{ 8 | "hottest_articles": { 9 | "title": "热门文章", 10 | "display": "1", 11 | "vars": { 12 | "hottest_articles_category_id": { 13 | "title": "文章分类ID", 14 | "value": "", 15 | "type": "text", 16 | "dataSource": { 17 | "api": "portal/category/index", 18 | "multi": true 19 | }, 20 | "placeholder": "请选择分类", 21 | "tip": "", 22 | "rule": { 23 | "require": true 24 | } 25 | } 26 | } 27 | }, 28 | "last_articles": { 29 | "title": "最新发布", 30 | "display": "1", 31 | "vars": { 32 | "last_articles_category_id": { 33 | "title": "文章分类ID", 34 | "value": "", 35 | "type": "text", 36 | "dataSource": { 37 | "api": "portal/category/index", 38 | "multi": true 39 | }, 40 | "placeholder": "请选择分类", 41 | "tip": "", 42 | "rule": { 43 | "require": true 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 搜索 {$theme_vars.varName1|default=''} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |

'{$keyword}' 搜索结果

17 |
18 | 19 | $where=function($query)use($keyword){ 20 | $query->where('post.create_time','>=',0)->where('post.post_title','like',"%$keyword%"); 21 | }; 22 | 23 | 24 | 25 | 26 |
27 |

{$vo.post_title} 28 |

29 |

{$vo.post_excerpt}

30 |
31 |
32 |
33 | {$vo.post_hits} 34 | {$vo.post_like} 36 | 37 | 38 | 39 |
40 |
41 | 查看更多 43 |
44 |
45 |
46 | 49 | 50 |
51 | 52 |
53 | 54 | 55 |
56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/search.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "搜索页面", 3 | "action": "portal/search/index", 4 | "description": "搜索模板文件", 5 | "order": 10.0, 6 | "more": { 7 | "vars": { 8 | "varName1": { 9 | "title": "热门搜索", 10 | "value": "1", 11 | "type": "text", 12 | "tip": "这是一个text", 13 | "rule": { 14 | "require": true 15 | } 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /public/themes/simpleboot3/portal/tag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$tag.name} {$site_info.site_name|default=''} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | $demo_time=2; 14 |

{$tag.name}

15 |
16 |
17 |
18 | 19 | $where= function($query){ 20 | $query->where('post.create_time','>',0); 21 | }; 22 | $page=[ 23 | 'list_rows'=>1, 24 | 'next'=>'下一页', 25 | 'prev'=>'上一页' 26 | ]; 27 | 28 | 32 |
33 |

{$vo.post_title} 34 |

35 |

{$vo.post_excerpt}

36 |
37 |
38 | 52 |
53 | 查看更多 55 |
56 |
57 |
58 | 59 |
60 |
    61 | 62 |
63 |
64 |
65 | 66 | 67 |
68 |
69 |

{$widget.title}

70 |
71 |
72 | 73 | $hot_articles=[]; 74 | 75 | 88 |
89 |
90 |
91 | 92 | 93 | 94 |
95 |
96 |

{$widget.title}

97 |
98 |
99 | 101 |
102 |
103 | 105 | 106 | {$vo.post_title} 108 | 109 | {$vo.post_title} 111 | 112 | 113 |
114 |
115 | {$vo.post_title} 116 |
117 |
118 |
119 |
120 |
121 |
122 | 123 |
124 |
125 | 126 | 127 |
128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/css/slippry/assets/img/arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/css/slippry/assets/img/arrows.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/css/slippry/assets/img/arrows.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/css/slippry/assets/img/sy-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/css/slippry/assets/img/sy-loader.gif -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/default-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/default-thumbnail.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/default_tupian1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/default_tupian1.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/default_tupian4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/default_tupian4.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/demo/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/demo/1.jpg -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/demo/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/demo/2.jpg -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/demo/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/demo/3.jpg -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/favicon.ico -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/favicon.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/ghs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/ghs.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/headicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/headicon.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/headicon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/headicon_128.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/headicon_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/headicon_30.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/headicon_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/headicon_40.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/headicon_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/headicon_50.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/logo.png -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/images/null_cart2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/images/null_cart2.jpg -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/js/jquery.infiniteScroll.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQuery infiniteScroll v1.0.0 3 | * 无限滚动插件 4 | * http://www.thinkcmf.com 5 | * MIT License 6 | * by Dean(老猫) 7 | * 8 | */ 9 | // examples 10 | // $('#nextpage').infiniteScroll({ 11 | // total_pages:5, 12 | // pageParam:'page', 13 | // loading:'.js-infinite-scroll-loading', 14 | // success:function(content){ 15 | // var $items=$(content).find('#container .item'); 16 | // if($items.length>0){ 17 | // $container.append( $items ); 18 | // } 19 | // }, 20 | // finish:function(){ 21 | // 22 | // } 23 | // }); 24 | ;(function ($) { 25 | $.fn.infiniteScroll = function (options) { 26 | var opts = $.extend({}, $.fn.infiniteScroll.defaults, options); 27 | var url = location.href; 28 | var $loading = $(opts.loading); 29 | $loading.hide(); 30 | return this.each(function () { 31 | var $document = $(document); 32 | var $window = $(window); 33 | var $this = $(this); 34 | var page = opts.page; 35 | 36 | function _loadData() { 37 | if ($this.data('loading')) { 38 | return; 39 | } 40 | $this.data('loading', true); 41 | $loading.show(); 42 | var data = {}; 43 | page++; 44 | if (page > opts.total_pages) { 45 | $loading.hide(); 46 | opts.finish(); 47 | return; 48 | } 49 | data[opts.pageParam] = page; 50 | opts.startLoading(); 51 | $.ajax({ 52 | url: url, 53 | data: data, 54 | type: 'GET', 55 | dateType: 'html', 56 | success: function (content) { 57 | opts.success(content, page); 58 | }, 59 | error: function () { 60 | opts.error(); 61 | }, 62 | complete: function () { 63 | $loading.hide(); 64 | $this.data('loading', false); 65 | } 66 | }); 67 | } 68 | 69 | if (opts.trigger == 'scroll') { 70 | $(window).scroll(function () { 71 | if ($this.data('loading') || $this.is(':hidden')) return; 72 | if ($document.scrollTop() > $this.position().top - $window.height()) { 73 | _loadData(); 74 | } 75 | }); 76 | } 77 | 78 | if (opts.trigger == 'click') { 79 | $this.click(function () { 80 | if ($this.data('loading') || $this.is(':hidden')) return; 81 | 82 | _loadData(); 83 | }); 84 | } 85 | 86 | 87 | }); 88 | }; 89 | $.fn.infiniteScroll.defaults = { 90 | pageParam: 'page', 91 | loading: '.js-infinite-scroll-loading', 92 | page: 1, 93 | trigger: 'scroll',//scroll,click 94 | success: function () { 95 | }, 96 | finish: function () { 97 | }, 98 | error: function () { 99 | }, 100 | startLoading: function () { 101 | // 102 | }, 103 | complete: function () { 104 | // 数据加载完成 105 | } 106 | 107 | }; 108 | })(jQuery); -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/js/slippry.min.map: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/portal/04bdebb49746488a122741bc6d9da81429d8945b/public/themes/simpleboot3/public/assets/js/slippry.min.map -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/simpleboot3/canvas-to-blob/canvas-to-blob.js: -------------------------------------------------------------------------------- 1 | /* 2 | * JavaScript Canvas to Blob 3 | * https://github.com/blueimp/JavaScript-Canvas-to-Blob 4 | * 5 | * Copyright 2012, Sebastian Tschan 6 | * https://blueimp.net 7 | * 8 | * Licensed under the MIT license: 9 | * https://opensource.org/licenses/MIT 10 | * 11 | * Based on stackoverflow user Stoive's code snippet: 12 | * http://stackoverflow.com/q/4998908 13 | */ 14 | 15 | /* global define, Uint8Array, ArrayBuffer, module */ 16 | 17 | ;(function(window) { 18 | 'use strict' 19 | 20 | var CanvasPrototype = 21 | window.HTMLCanvasElement && window.HTMLCanvasElement.prototype 22 | var hasBlobConstructor = 23 | window.Blob && 24 | (function() { 25 | try { 26 | return Boolean(new Blob()) 27 | } catch (e) { 28 | return false 29 | } 30 | })() 31 | var hasArrayBufferViewSupport = 32 | hasBlobConstructor && 33 | window.Uint8Array && 34 | (function() { 35 | try { 36 | return new Blob([new Uint8Array(100)]).size === 100 37 | } catch (e) { 38 | return false 39 | } 40 | })() 41 | var BlobBuilder = 42 | window.BlobBuilder || 43 | window.WebKitBlobBuilder || 44 | window.MozBlobBuilder || 45 | window.MSBlobBuilder 46 | var dataURIPattern = /^data:((.*?)(;charset=.*?)?)(;base64)?,/ 47 | var dataURLtoBlob = 48 | (hasBlobConstructor || BlobBuilder) && 49 | window.atob && 50 | window.ArrayBuffer && 51 | window.Uint8Array && 52 | function(dataURI) { 53 | var matches, 54 | mediaType, 55 | isBase64, 56 | dataString, 57 | byteString, 58 | arrayBuffer, 59 | intArray, 60 | i, 61 | bb 62 | // Parse the dataURI components as per RFC 2397 63 | matches = dataURI.match(dataURIPattern) 64 | if (!matches) { 65 | throw new Error('invalid data URI') 66 | } 67 | // Default to text/plain;charset=US-ASCII 68 | mediaType = matches[2] 69 | ? matches[1] 70 | : 'text/plain' + (matches[3] || ';charset=US-ASCII') 71 | isBase64 = !!matches[4] 72 | dataString = dataURI.slice(matches[0].length) 73 | if (isBase64) { 74 | // Convert base64 to raw binary data held in a string: 75 | byteString = atob(dataString) 76 | } else { 77 | // Convert base64/URLEncoded data component to raw binary: 78 | byteString = decodeURIComponent(dataString) 79 | } 80 | // Write the bytes of the string to an ArrayBuffer: 81 | arrayBuffer = new ArrayBuffer(byteString.length) 82 | intArray = new Uint8Array(arrayBuffer) 83 | for (i = 0; i < byteString.length; i += 1) { 84 | intArray[i] = byteString.charCodeAt(i) 85 | } 86 | // Write the ArrayBuffer (or ArrayBufferView) to a blob: 87 | if (hasBlobConstructor) { 88 | return new Blob([hasArrayBufferViewSupport ? intArray : arrayBuffer], { 89 | type: mediaType 90 | }) 91 | } 92 | bb = new BlobBuilder() 93 | bb.append(arrayBuffer) 94 | return bb.getBlob(mediaType) 95 | } 96 | if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { 97 | if (CanvasPrototype.mozGetAsFile) { 98 | CanvasPrototype.toBlob = function(callback, type, quality) { 99 | var self = this 100 | setTimeout(function() { 101 | if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { 102 | callback(dataURLtoBlob(self.toDataURL(type, quality))) 103 | } else { 104 | callback(self.mozGetAsFile('blob', type)) 105 | } 106 | }) 107 | } 108 | } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { 109 | CanvasPrototype.toBlob = function(callback, type, quality) { 110 | var self = this 111 | setTimeout(function() { 112 | callback(dataURLtoBlob(self.toDataURL(type, quality))) 113 | }) 114 | } 115 | } 116 | } 117 | if (typeof define === 'function' && define.amd) { 118 | define(function() { 119 | return dataURLtoBlob 120 | }) 121 | } else if (typeof module === 'object' && module.exports) { 122 | module.exports = dataURLtoBlob 123 | } else { 124 | window.dataURLtoBlob = dataURLtoBlob 125 | } 126 | })(window) 127 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/assets/simpleboot3/canvas-to-blob/canvas-to-blob.min.js: -------------------------------------------------------------------------------- 1 | !function(t){"use strict";var r=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,f=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),b=f&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),d=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,B=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,a=(f||d)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,o,n,r,a,i,l,u,c;if(!(e=t.match(B)))throw new Error("invalid data URI");for(o=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),n=!!e[4],r=t.slice(e[0].length),a=n?atob(r):decodeURIComponent(r),i=new ArrayBuffer(a.length),l=new Uint8Array(i),u=0;u 2 | 3 |
4 | 37 |
38 | 39 |
40 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/function.html: -------------------------------------------------------------------------------- 1 | 2 | /*可以加多个方法哟!*/ 3 | if (!function_exists('_sp_helloworld')) { 4 | function _sp_helloworld(){ 5 | echo "hello ThinkCMF!"; 6 | } 7 | } 8 | 9 | if (!function_exists('_sp_helloworld2')) { 10 | function _sp_helloworld2(){ 11 | echo "hello ThinkCMF2!"; 12 | } 13 | } 14 | 15 | if (!function_exists('_sp_helloworld3')) { 16 | function _sp_helloworld3(){ 17 | echo "hello ThinkCMF3!"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 23 | 26 | 27 | 47 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/nav.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/nav.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "导航条", 3 | "action": "public/Nav", 4 | "description": "导航条模板文件", 5 | "is_public": "1", 6 | "order": 1.0, 7 | "more": { 8 | "vars": { 9 | "company_name": { 10 | "title": "公司名称", 11 | "name": "company_name", 12 | "value": "ThinkCMF", 13 | "type": "text", 14 | "tip": "", 15 | "rule": [] 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/scripts.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 72 | 73 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/public/usernav.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/comment/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 我的评论 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 50 | 51 | 52 | 53 |
#评论内容评论时间操作
{$vo.id}{$vo.content}{$vo.create_time} 42 | 43 | $url = json_decode($vo['url'],true); 44 | 45 | 查看 | 46 | 删除评论 49 |
54 |
55 | 56 |
    {$page}
57 |
58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/favorite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 我的收藏 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 48 | 49 | 50 | 51 |
#标题描述操作
{$vo.id}{$vo.title}{$vo.description} 42 | 43 | $url = json_decode($vo['url'],true); 44 | 45 | 查看 | 46 | 取消收藏 47 |
52 | 53 |
54 |
55 |
56 |
57 |
58 | 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 |
20 |
21 |
22 |
23 |
24 | 33 |
34 |
35 | 36 |
{$user_nickname|default='未填写'}
37 |
38 |
39 | 40 |
41 | $sexs=array("0"=>"保密","1"=>"程序猿","2"=>"程序媛");echo $sexs[$sex]; 42 |
43 |
44 |
45 | 46 |
{:date('Y-m-d',$birthday)}
47 |
48 |
49 | 50 |
{$user_url|default='未填写'}
51 |
52 |
53 | 54 |
{$signature|default='未填写'}
55 |
56 |
57 |
58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |

用户登录

17 |
18 |
19 | 20 |
21 | 22 |
23 | 24 |
25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 | 33 |
34 | 35 | 36 |
37 | 38 |
39 | 43 |
44 |
45 |
46 |
47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/profile/binding.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 绑定账号 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 22 |
23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |

40 |
41 |
42 |
43 | 44 |
45 |
46 |
47 | 50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | 59 |
60 | 61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | 72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |

86 |
87 |
88 |
89 |
90 |
91 |
92 | 95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | 104 |
105 | 106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | 117 |
118 |
119 |
120 |
121 |
122 | 123 |
124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/profile/center.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 个人中心 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 |
19 |
20 |
21 | 22 |
23 |
24 |
25 | 28 |
29 |
30 |
31 |
32 | 41 |
42 |
43 | 44 |
{$user_login|default='未填写'}
45 |
46 |
47 | 48 |
{$user_nickname|default='未填写'}
49 |
50 |
51 | 52 |
53 | $sexs=array("0"=>"保密","1"=>"程序猿","2"=>"程序媛");echo $sexs[$sex]; 54 |
55 |
56 |
57 | 58 |
{:date('Y-m-d',$birthday)}
59 |
60 |
61 | 62 |
{$user_url|default='未填写'}
63 |
64 |
65 | 66 |
{$signature|default='未填写'}
67 |
68 |
69 | 编辑 70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | 79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/profile/edit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 修改资料 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 22 |
23 |
24 |
25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 | $sexs=array("0"=>"保密","1"=>"程序猿","2"=>"程序媛"); 34 | 35 | 41 |
42 |
43 | 44 | 45 |
46 |
47 | 48 | 49 |
50 |
51 | 52 | 53 |
54 |
55 | 56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /public/themes/simpleboot3/user/profile/password.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$user_login} - 修改密码 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 22 |
23 |
24 |
25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 | 37 |
38 |
39 | 40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 48 |
49 | 50 | 51 | 52 | --------------------------------------------------------------------------------