作者 sgj

init

正在显示 63 个修改的文件 包含 4784 行增加0 行删除

要显示太多修改。

为保证性能只显示 63 of 63+ 个文件。

{
"directory" : "public/assets/libs",
"ignoredDependencies": [
"file-saver",
"html2canvas",
"jspdf",
"jspdf-autotable"
]
}
\ No newline at end of file
... ...
[app]
debug = false
trace = false
[database]
hostname = 127.0.0.1
database = fastadmin
username = root
password = root
hostport = 3306
prefix = fa_
... ...
/nbproject/
/runtime/*
/public/uploads/*
.idea
composer.lock
*.log
*.css.map
!.gitkeep
.vscode
... ...
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2017 Karson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\ No newline at end of file
... ...
FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。
## **主要特性**
* 基于`Auth`验证的权限管理系统
* 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置
* 支持单管理员多角色
* 支持管理子级数据或个人数据
* 强大的一键生成功能
* 一键生成CRUD,包括控制器、模型、视图、JS、语言包、菜单、回收站等
* 一键压缩打包JS和CSS文件,一键CDN静态资源部署
* 一键生成控制器菜单和规则
* 一键生成API接口文档
* 完善的前端功能组件开发
* 基于`AdminLTE`二次开发
* 基于`Bootstrap`开发,自适应手机、平板、PC
* 基于`RequireJS`进行JS模块管理,按需加载
* 基于`Less`进行样式开发
* 基于`Bower`进行前端组件包管理
* 强大的插件扩展功能,在线安装卸载升级插件
* 通用的会员模块和API模块
* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证
* 二级域名部署支持,同时域名支持绑定到插件
* 多语言支持,服务端及客户端支持
* 强大的第三方模块支持([CMS](https://www.fastadmin.net/store/cms.html)[博客](https://www.fastadmin.net/store/blog.html)[知识付费问答](https://www.fastadmin.net/store/ask.html))
* 整合第三方短信接口(阿里云、腾讯云短信)
* 无缝整合第三方云存储(七牛、阿里云OSS、又拍云)功能
* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
* 第三方登录(QQ、微信、微博)整合
* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
* 丰富的插件应用市场
## **安装使用**
https://doc.fastadmin.net
## **在线演示**
https://demo.fastadmin.net
用户名:admin
密 码:123456
提 示:演示站数据无法进行修改,请下载源码安装体验全部功能
## **界面截图**
![控制台](https://gitee.com/uploads/images/2017/0411/113717_e99ff3e7_10933.png "控制台")
## **问题反馈**
在使用中有任何问题,请使用以下联系方式联系我们
交流社区: https://forum.fastadmin.net
QQ群: [636393962](https://jq.qq.com/?_wv=1027&k=487PNBb)() [708784003](https://jq.qq.com/?_wv=1027&k=5ObjtwM)(满) [964776039](https://jq.qq.com/?_wv=1027&k=59qjU2P)(3群)
Email: (karsonzhang#163.com, 把#换成@)
Github: https://github.com/karsonzhang/fastadmin
Gitee: https://gitee.com/karson/fastadmin
## **特别鸣谢**
感谢以下的项目,排名不分先后
ThinkPHP:http://www.thinkphp.cn
AdminLTE:https://adminlte.io
Bootstrap:http://getbootstrap.com
jQuery:http://jquery.com
Bootstrap-table:https://github.com/wenzhixin/bootstrap-table
Nice-validator: https://validator.niceue.com
SelectPage: https://github.com/TerryZ/SelectPage
## **版权信息**
FastAdmin遵循Apache2开源协议发布,并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2017-2019 by FastAdmin (https://www.fastadmin.net)
All rights reserved。
\ No newline at end of file
... ...
<?php
namespace addons\cms;
use addons\cms\model\Archives;
use addons\cms\model\Channel;
use app\common\library\Auth;
use app\common\library\Menu;
use fast\Tree;
use think\Addons;
use think\exception\PDOException;
use think\Request;
use think\View;
/**
* CMS插件
*/
class Cms extends Addons
{
/**
* 插件安装方法
* @return bool
*/
public function install()
{
$menu = [
[
'name' => 'cms',
'title' => 'CMS管理',
'sublist' => [
[
'name' => 'cms/archives',
'title' => '内容管理',
'icon' => 'fa fa-file-text-o',
'sublist' => [
['name' => 'cms/archives/index', 'title' => '查看'],
['name' => 'cms/archives/content', 'title' => '副表管理', 'remark' => '用于管理模型副表的数据列表,不建议在此进行删除操作'],
['name' => 'cms/archives/add', 'title' => '添加'],
['name' => 'cms/archives/edit', 'title' => '修改'],
['name' => 'cms/archives/del', 'title' => '删除'],
['name' => 'cms/archives/multi', 'title' => '批量更新'],
]
],
[
'name' => 'cms/channel',
'title' => '栏目管理',
'icon' => 'fa fa-list',
'sublist' => [
['name' => 'cms/channel/index', 'title' => '查看'],
['name' => 'cms/channel/add', 'title' => '添加'],
['name' => 'cms/channel/edit', 'title' => '修改'],
['name' => 'cms/channel/del', 'title' => '删除'],
['name' => 'cms/channel/multi', 'title' => '批量更新'],
['name' => 'cms/channel/admin', 'title' => '栏目授权', 'remark' => '分配管理员可管理的栏目数据,此功能需要先开启插件管理CMS配置的栏目授权开关'],
],
'remark' => '用于管理网站的分类,可进行无限级分类,注意只有类型为列表的才可以添加文章'
],
[
'name' => 'cms/modelx',
'title' => '模型管理',
'icon' => 'fa fa-th',
'sublist' => [
['name' => 'cms/modelx/index', 'title' => '查看'],
['name' => 'cms/modelx/add', 'title' => '添加'],
['name' => 'cms/modelx/edit', 'title' => '修改'],
['name' => 'cms/modelx/del', 'title' => '删除'],
['name' => 'cms/modelx/multi', 'title' => '批量更新'],
[
'name' => 'cms/fields',
'title' => '字段管理',
'icon' => 'fa fa-fields',
'ismenu' => 0,
'sublist' => [
['name' => 'cms/fields/index', 'title' => '查看'],
['name' => 'cms/fields/add', 'title' => '添加'],
['name' => 'cms/fields/edit', 'title' => '修改'],
['name' => 'cms/fields/del', 'title' => '删除'],
['name' => 'cms/fields/duplicate', 'title' => '复制'],
['name' => 'cms/fields/multi', 'title' => '批量更新'],
],
'remark' => '用于管理模型或表单的字段,进行相关的增删改操作,灰色为主表字段无法修改'
]
],
'remark' => '在线添加修改删除模型,管理模型字段和相关模型数据'
],
[
'name' => 'cms/tags',
'title' => '标签管理',
'icon' => 'fa fa-tags',
'sublist' => [
['name' => 'cms/tags/index', 'title' => '查看'],
['name' => 'cms/tags/add', 'title' => '添加'],
['name' => 'cms/tags/edit', 'title' => '修改'],
['name' => 'cms/tags/del', 'title' => '删除'],
['name' => 'cms/tags/multi', 'title' => '批量更新'],
],
'remark' => '用于管理文章关联的标签,标签的添加在添加文章时自动维护,无需手动添加标签'
],
[
'name' => 'cms/block',
'title' => '区块管理',
'icon' => 'fa fa-th-large',
'sublist' => [
['name' => 'cms/block/index', 'title' => '查看'],
['name' => 'cms/block/add', 'title' => '添加'],
['name' => 'cms/block/edit', 'title' => '修改'],
['name' => 'cms/block/del', 'title' => '删除'],
['name' => 'cms/block/multi', 'title' => '批量更新'],
],
'remark' => '用于管理站点的自定义区块内容,常用于广告、JS脚本、焦点图、片段代码等'
],
[
'name' => 'cms/page',
'title' => '单页管理',
'icon' => 'fa fa-file',
'sublist' => [
['name' => 'cms/page/index', 'title' => '查看'],
['name' => 'cms/page/add', 'title' => '添加'],
['name' => 'cms/page/edit', 'title' => '修改'],
['name' => 'cms/page/del', 'title' => '删除'],
['name' => 'cms/page/multi', 'title' => '批量更新'],
],
'remark' => '用于管理网站的单页面,可任意创建修改删除单页面'
],
[
'name' => 'cms/comment',
'title' => '评论管理',
'icon' => 'fa fa-comment',
'sublist' => [
['name' => 'cms/comment/index', 'title' => '查看'],
['name' => 'cms/comment/add', 'title' => '添加'],
['name' => 'cms/comment/edit', 'title' => '修改'],
['name' => 'cms/comment/del', 'title' => '删除'],
['name' => 'cms/comment/multi', 'title' => '批量更新'],
],
'remark' => '用于管理用户在网站上发表的评论,可任意修改或隐藏评论'
],
[
'name' => 'cms/diyform',
'title' => '自定义表单管理',
'icon' => 'fa fa-list',
'sublist' => [
['name' => 'cms/diyform/index', 'title' => '查看'],
['name' => 'cms/diyform/add', 'title' => '添加'],
['name' => 'cms/diyform/edit', 'title' => '修改'],
['name' => 'cms/diyform/del', 'title' => '删除'],
['name' => 'cms/diyform/multi', 'title' => '批量更新'],
],
'remark' => '可在线创建自定义表单,管理表单字段和数据列表'
],
[
'name' => 'cms/diydata',
'title' => '自定义表单数据管理',
'icon' => 'fa fa-list',
'ismenu' => 0,
'sublist' => [
['name' => 'cms/diydata/index', 'title' => '查看'],
['name' => 'cms/diydata/add', 'title' => '添加'],
['name' => 'cms/diydata/edit', 'title' => '修改'],
['name' => 'cms/diydata/del', 'title' => '删除'],
['name' => 'cms/diydata/multi', 'title' => '批量更新'],
['name' => 'cms/diydata/import', 'title' => '导入'],
],
'remark' => '可在线管理自定义表单的数据列表'
],
[
'name' => 'cms/order',
'title' => '订单管理',
'icon' => 'fa fa-cny',
'ismenu' => 1,
'sublist' => [
['name' => 'cms/order/index', 'title' => '查看'],
['name' => 'cms/order/add', 'title' => '添加'],
['name' => 'cms/order/edit', 'title' => '修改'],
['name' => 'cms/order/del', 'title' => '删除'],
['name' => 'cms/order/multi', 'title' => '批量更新'],
],
'remark' => '可在线管理付费查看所产生的订单'
],
[
'name' => 'cms/special',
'title' => '专题管理',
'icon' => 'fa fa-newspaper-o',
'ismenu' => 1,
'sublist' => [
['name' => 'cms/special/index', 'title' => '查看'],
['name' => 'cms/special/add', 'title' => '添加'],
['name' => 'cms/special/edit', 'title' => '修改'],
['name' => 'cms/special/del', 'title' => '删除'],
['name' => 'cms/special/multi', 'title' => '批量更新'],
],
'remark' => '可在线管理专题列表'
]
]
]
];
Menu::create($menu);
return true;
}
/**
* 插件卸载方法
* @return bool
*/
public function uninstall()
{
Menu::delete('cms');
return true;
}
/**
* 插件启用方法
*/
public function enable()
{
Menu::enable('cms');
}
/**
* 插件禁用方法
*/
public function disable()
{
Menu::disable('cms');
}
/**
* 应用初始化
*/
public function appInit()
{
// 自定义路由变量规则
\think\Route::pattern([
'diyname' => "[a-zA-Z0-9\-_]+",
'id' => "\d+",
]);
}
/**
* 脚本替换
* @param \think\Response $response
*/
public function responseSend(\think\Response $response)
{
$style = '';
$script = '';
$content = $response->getContent();
$result = preg_replace_callback("/<(script|style)\s(data\-render=\"(script|style)\")([\s\S]*?)>([\s\S]*?)<\/(script|style)>/i", function ($match) use (&$style, &$script) {
if (isset($match[1]) && in_array($match[1], ['style', 'script'])) {
${$match[1]} .= str_replace($match[2], '', $match[0]);
}
return '';
}, $content);
$content = str_replace(['{__STYLE__}', '{__SCRIPT__}'], [$style, $script], $result ? $result : $content);
$response->content($content);
}
/**
* 会员中心边栏后
* @return mixed
* @throws \Exception
*/
public function userSidenavAfter()
{
$request = Request::instance();
$actionname = strtolower($request->action());
$data = [
'actionname' => $actionname
];
return $this->fetch('view/hook/user_sidenav_after', $data);
}
}
... ...
### 插件协议
在使用FastAdmin付费插件前认真阅读FastAdmin插件使用协议
https://www.fastadmin.net/page/addon-agreement.html
### 交流专区
如果你在使用CMS内容管理系统有遇到什么问题,请到FastAdmin交流专区进行交流
https://ask.fastadmin.net/zone/cms.html
### 温馨提示
此插件为FastAdmin的商业产品,禁止分享、转售、复制CMS插件源码给他人使用,违者将追究法律责任
... ...
<?php
namespace app\admin\controller\cms;
use addons\cms\library\aip\AipContentCensor;
use addons\cms\library\SensitiveHelper;
use addons\cms\library\Service;
use app\common\controller\Backend;
/**
* Ajax
*
* @icon fa fa-circle-o
* @internal
*/
class Ajax extends Backend
{
/**
* 模型对象
*/
protected $model = null;
protected $noNeedRight = ['*'];
public function _initialize()
{
parent::_initialize();
}
/**
* 获取模板列表
* @internal
*/
public function get_template_list()
{
$files = [];
$keyValue = $this->request->request("keyValue");
if (!$keyValue) {
$type = $this->request->request("type");
$name = $this->request->request("name");
if ($name) {
//$files[] = ['name' => $name . '.html'];
}
//设置过滤方法
$this->request->filter(['strip_tags']);
$config = get_addon_config('cms');
$themeDir = ADDON_PATH . 'cms' . DS . 'view' . DS . $config['theme'] . DS;
$dh = opendir($themeDir);
while (false !== ($filename = readdir($dh))) {
if ($filename == '.' || $filename == '..') {
continue;
}
if ($type) {
$rule = $type == 'channel' ? '(channel|list)' : $type;
if (!preg_match("/^{$rule}(.*)/i", $filename)) {
continue;
}
}
$files[] = ['name' => $filename];
}
} else {
$files[] = ['name' => $keyValue];
}
return $result = ['total' => count($files), 'list' => $files];
}
/**
* 检查内容是否包含违禁词
* @throws \Exception
*/
public function check_content_islegal()
{
$config = get_addon_config('cms');
$content = $this->request->post('content');
if (!$content) {
$this->error(__('Please input your content'));
}
if ($config['audittype'] == 'local') {
// 敏感词过滤
$handle = SensitiveHelper::init()->setTreeByFile(ADDON_PATH . 'cms/data/words.dic');
//首先检测是否合法
$arr = $handle->getBadWord($content);
if ($arr) {
$this->error(__('The content is not legal'), null, $arr);
} else {
$this->success(__('The content is legal'));
}
} else {
$client = new AipContentCensor($config['aip_appid'], $config['aip_apikey'], $config['aip_secretkey']);
$result = $client->antiSpam($content);
if (isset($result['result']) && $result['result']['spam'] > 0) {
$arr = [];
foreach (array_merge($result['result']['review'], $result['result']['reject']) as $index => $item) {
$arr[] = $item['hit'];
}
$this->error(__('The content is not legal'), null, $arr);
} else {
$this->success(__('The content is legal'));
}
}
}
/**
* 获取关键字
* @throws \Exception
*/
public function get_content_keywords()
{
$config = get_addon_config('cms');
$title = $this->request->post('title');
$tags = $this->request->post('tags', '');
$content = $this->request->post('content');
if (!$content) {
$this->error(__('Please input your content'));
}
$keywords = Service::getContentTags($title);
$keywords = in_array($title, $keywords) ? [] : $keywords;
$keywords = array_filter(array_merge([$tags], $keywords));
$description = mb_substr(strip_tags($content), 0, 200);
$data = [
"keywords" => implode(',', $keywords),
"description" => $description
];
$this->success("提取成功", null, $data);
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\admin\model\cms\Channel;
use app\admin\model\cms\ChannelAdmin;
use app\admin\model\cms\Modelx;
use app\common\controller\Backend;
use fast\Tree;
use think\Db;
use think\db\Query;
/**
* 内容表
*
* @icon fa fa-file-text-o
*/
class Archives extends Backend
{
/**
* Archives模型对象
*/
protected $model = null;
protected $noNeedRight = ['get_channel_fields', 'check_element_available'];
protected $channelIds = [];
protected $isSuperAdmin = false;
protected $searchFields = 'id,title';
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Archives;
$cms = get_addon_config('cms');
//是否超级管理员
$this->isSuperAdmin = $this->auth->isSuperAdmin();
$channelList = [];
$disabledIds = [];
$all = collection(Channel::order("weigh desc,id desc")->select())->toArray();
//允许的栏目
$this->channelIds = $this->isSuperAdmin || !$cms['channelallocate'] ? Channel::column('id') : ChannelAdmin::getAdminChanneIds();
$parentChannelIds = Channel::where('id', 'in', $this->channelIds)->column('parent_id');
foreach ($all as $k => $v) {
$state = ['opened' => true];
if ($v['type'] != 'list') {
$disabledIds[] = $v['id'];
}
if ($v['type'] == 'link') {
$state['checkbox_disabled'] = true;
}
if (!$this->isSuperAdmin) {
if (($v['type'] != 'list' && !in_array($v['id'], $parentChannelIds)) || ($v['type'] == 'list' && !in_array($v['id'], $this->channelIds))) {
unset($all[$k]);
continue;
}
}
$channelList[] = [
'id' => $v['id'],
'parent' => $v['parent_id'] ? $v['parent_id'] : '#',
'text' => __($v['name']),
'type' => $v['type'],
'state' => $state
];
}
$tree = Tree::instance()->init($all, 'parent_id');
$channelOptions = $tree->getTree(0, "<option model='@model_id' value=@id @selected @disabled>@spacer@name</option>", '', $disabledIds);
$this->view->assign('channelOptions', $channelOptions);
$this->assignconfig('channelList', $channelList);
$this->assignconfig("flagList", $this->model->getFlagList());
$this->view->assign("flagList", $this->model->getFlagList());
$this->view->assign("statusList", $this->model->getStatusList());
$this->assignconfig('cms', ['archiveseditmode' => $cms['archiveseditmode']]);
}
/**
* 查看
*/
public function index()
{
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
$this->relationSearch = true;
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
if (!$this->auth->isSuperAdmin()) {
$this->model->where('channel_id', 'in', $this->channelIds);
}
$total = $this->model
->with('Channel')
->where($where)
->order($sort, $order)
->count();
if (!$this->auth->isSuperAdmin()) {
$this->model->where('channel_id', 'in', $this->channelIds);
}
$list = $this->model
->with('Channel')
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
$modelList = \app\admin\model\cms\Modelx::all();
$this->view->assign('modelList', $modelList);
return $this->view->fetch();
}
/**
* 副表内容
*/
public function content($model_id = null)
{
$model = \app\admin\model\cms\Modelx::get($model_id);
if (!$model) {
$this->error('未找到对应模型');
}
$fieldsList = \app\admin\model\cms\Fields::where('model_id', $model['id'])->where('type', '<>', 'text')->select();
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
$fields = [];
foreach ($fieldsList as $index => $item) {
$fields[] = "addon." . $item['name'];
}
$table = $this->model->getTable();
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$sort = 'main.id';
$isSuperAdmin = $this->isSuperAdmin;
$channelIds = $this->channelIds;
$customWhere = function ($query) use ($isSuperAdmin, $channelIds, $model_id) {
if (!$isSuperAdmin) {
$query->where('main.channel_id', 'in', $channelIds);
}
if ($model_id) {
$query->where('main.model_id', $model_id);
}
};
$total = Db::table($table)
->alias('main')
->join('cms_channel channel', 'channel.id=main.channel_id', 'LEFT')
->join($model['table'] . ' addon', 'addon.id=main.id', 'LEFT')
->field('main.id,main.channel_id,main.title,channel.name as channel_name,addon.id as aid' . ($fields ? ',' . implode(',', $fields) : ''))
->where($customWhere)
->where($where)
->order($sort, $order)
->count();
$list = Db::table($table)
->alias('main')
->join('cms_channel channel', 'channel.id=main.channel_id', 'LEFT')
->join($model['table'] . ' addon', 'addon.id=main.id', 'LEFT')
->field('main.id,main.channel_id,main.title,channel.name as channel_name,addon.id as aid' . ($fields ? ',' . implode(',', $fields) : ''))
->where($customWhere)
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
$fields = [];
foreach ($fieldsList as $index => $item) {
$fields[] = ['field' => $item['name'], 'title' => $item['title'], 'type' => $item['type'], 'content' => $item['content_list']];
}
$this->assignconfig('fields', $fields);
$this->view->assign('fieldsList', $fieldsList);
$this->view->assign('model', $model);
$this->assignconfig('model_id', $model_id);
$modelList = \app\admin\model\cms\Modelx::all();
$this->view->assign('modelList', $modelList);
return $this->view->fetch();
}
/**
* 编辑
*
* @param mixed $ids
* @return string
*/
public function edit($ids = null)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
if (!in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
}
if (!$this->isSuperAdmin && !in_array($row['channel_id'], $this->channelIds)) {
$this->error(__('You have no permission'));
}
if ($this->request->isPost()) {
return parent::edit($ids);
}
$channel = Channel::get($row['channel_id']);
if (!$channel) {
$this->error(__('No specified channel found'));
}
$model = \app\admin\model\cms\Modelx::get($channel['model_id']);
if (!$model) {
$this->error(__('No specified model found'));
}
$addon = db($model['table'])->where('id', $row['id'])->find();
if ($addon) {
$row->setData($addon);
}
$disabledIds = [];
$all = collection(Channel::order("weigh desc,id desc")->select())->toArray();
foreach ($all as $k => $v) {
if ($v['type'] != 'list' || $v['model_id'] != $channel['model_id']) {
$disabledIds[] = $v['id'];
}
}
$tree = Tree::instance()->init($all, 'parent_id');
$channelOptions = $tree->getTree(0, "<option model='@model_id' value=@id @selected @disabled>@spacer@name</option>", $row['channel_id'], $disabledIds);
$this->view->assign('channelOptions', $channelOptions);
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 删除
* @param mixed $ids
*/
public function del($ids = "")
{
\app\admin\model\cms\Archives::event('after_delete', function ($row) {
Channel::where('id', $row['channel_id'])->where('items', '>', 0)->setDec('items');
});
parent::del($ids);
}
/**
* 销毁
* @param string $ids
*/
public function destroy($ids = "")
{
\app\admin\model\cms\Archives::event('after_delete', function ($row) {
//删除副表
$channel = Channel::get($row->channel_id);
if ($channel) {
$model = Modelx::get($channel['model_id']);
if ($model) {
db($model['table'])->where("id", $row['id'])->delete();
}
}
});
parent::destroy($ids);
}
/**
* 还原
* @param mixed $ids
*/
public function restore($ids = "")
{
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
if ($ids) {
$this->model->where($pk, 'in', $ids);
}
$archivesChannelIds = $this->model->onlyTrashed()->column('id,channel_id');
$archivesChannelIds = array_filter($archivesChannelIds);
$this->model->where('id', 'in', array_keys($archivesChannelIds));
$count = $this->model->restore('1=1');
if ($count) {
$channelNums = array_count_values($archivesChannelIds);
foreach ($channelNums as $k => $v) {
Channel::where('id', $k)->setInc('items', $v);
}
$this->success();
}
$this->error(__('No rows were updated'));
}
/**
* 移动
* @param string $ids
*/
public function move($ids = "")
{
if ($ids) {
$channel_id = $this->request->post('channel_id');
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
$this->model->where($pk, 'in', $ids);
$channel = Channel::get($channel_id);
if ($channel && $channel['type'] === 'list') {
$channelNums = \app\admin\model\cms\Archives::
with('channel')
->where('archives.' . $pk, 'in', $ids)
->where('channel_id', '<>', $channel['id'])
->field('channel_id,COUNT(*) AS nums')
->group('channel_id')
->select();
$result = $this->model
->where('model_id', '=', $channel['model_id'])
->where('channel_id', '<>', $channel['id'])
->update(['channel_id' => $channel_id]);
if ($result) {
$count = 0;
foreach ($channelNums as $k => $v) {
if ($v['channel']) {
Channel::where('id', $v['channel_id'])->where('items', '>', 0)->setDec('items', min($v['channel']['items'], $v['nums']));
}
$count += $v['nums'];
}
Channel::where('id', $channel_id)->setInc('items', $count);
$this->success();
} else {
$this->error(__('No rows were updated'));
}
} else {
$this->error(__('No rows were updated'));
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
}
/**
* 获取栏目列表
* @internal
*/
public function get_channel_fields()
{
$this->view->engine->layout(false);
$channel_id = $this->request->post('channel_id');
$archives_id = $this->request->post('archives_id');
$channel = Channel::get($channel_id, 'model');
if ($channel && $channel['type'] === 'list') {
$values = [];
if ($archives_id) {
$values = db($channel['model']['table'])->where('id', $archives_id)->find();
}
$fields = \app\admin\model\cms\Fields::where('model_id', $channel['model_id'])
->order('weigh desc,id desc')
->select();
foreach ($fields as $k => $v) {
//优先取编辑的值,再次取默认值
$v->value = isset($values[$v['name']]) ? $values[$v['name']] : (is_null($v['defaultvalue']) ? '' : $v['defaultvalue']);
$v->rule = str_replace(',', '; ', $v->rule);
if (in_array($v->type, ['checkbox', 'lists', 'images'])) {
$checked = '';
if ($v['minimum'] && $v['maximum']) {
$checked = "{$v['minimum']}~{$v['maximum']}";
} elseif ($v['minimum']) {
$checked = "{$v['minimum']}~";
} elseif ($v['maximum']) {
$checked = "~{$v['maximum']}";
}
if ($checked) {
$v->rule .= (';checked(' . $checked . ')');
}
}
if (in_array($v->type, ['checkbox', 'radio']) && stripos($v->rule, 'required') !== false) {
$v->rule = str_replace('required', 'checked', $v->rule);
}
if (in_array($v->type, ['selects'])) {
$v->extend .= (' ' . 'data-max-options="' . $v['maximum'] . '"');
}
}
$this->view->assign('fields', $fields);
$this->view->assign('values', $values);
$this->success('', null, ['html' => $this->view->fetch('fields')]);
} else {
$this->error(__('Please select channel'));
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available()
{
$id = $this->request->request('id');
$name = $this->request->request('name');
$value = $this->request->request('value');
$name = substr($name, 4, -1);
if (!$name) {
$this->error(__('Parameter %s can not be empty', 'name'));
}
if ($id) {
$this->model->where('id', '<>', $id);
}
$exist = $this->model->where($name, $value)->find();
if ($exist) {
$this->error(__('The data already exist'));
} else {
$this->success();
}
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 区块表
*
* @icon fa fa-th-large
*/
class Block extends Backend
{
/**
* Block模型对象
*/
protected $model = null;
protected $noNeedRight = ['selectpage_type'];
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Block;
$this->view->assign("statusList", $this->model->getStatusList());
}
public function index()
{
$typeArr = \app\admin\model\cms\Block::distinct('type')->column('type');
$this->view->assign('typeList', $typeArr);
$this->assignconfig('typeList', $typeArr);
return parent::index();
}
public function selectpage_type()
{
$list = [];
$word = (array)$this->request->request("q_word/a");
$field = $this->request->request('showField');
$keyValue = $this->request->request('keyValue');
if (!$keyValue) {
if (array_filter($word)) {
foreach ($word as $k => $v) {
$list[] = ['id' => $v, $field => $v];
}
}
$typeArr = \app\admin\model\cms\Block::column('type');
$typeArr = array_unique($typeArr);
foreach ($typeArr as $index => $item) {
$list[] = ['id' => $item, $field => $item];
}
} else {
$list[] = ['id' => $keyValue, $field => $keyValue];
}
return json(['total' => count($list), 'list' => $list]);
}
public function import()
{
return parent::import();
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\admin\model\Admin;
use app\admin\model\AuthGroupAccess;
use app\admin\model\cms\ChannelAdmin;
use app\common\controller\Backend;
use app\admin\model\cms\Channel as ChannelModel;
use fast\Tree;
use think\Exception;
/**
* 栏目表
*
* @icon fa fa-list
*/
class Channel extends Backend
{
protected $channelList = [];
protected $modelList = [];
protected $multiFields = ['weigh', 'status', 'iscontribute', 'isnav'];
/**
* Channel模型对象
*/
protected $model = null;
protected $noNeedRight = ['check_element_available'];
public function _initialize()
{
parent::_initialize();
$this->request->filter(['strip_tags']);
$this->model = new \app\admin\model\cms\Channel;
$tree = Tree::instance();
$tree->init(collection($this->model->order('weigh desc,id desc')->select())->toArray(), 'parent_id');
$this->channelList = $tree->getTreeList($tree->getTreeArray(0), 'name');
$this->modelList = \app\admin\model\cms\Modelx::order('id asc')->select();
$this->view->assign("modelList", $this->modelList);
$this->view->assign("channelList", $this->channelList);
$this->view->assign("typeList", ChannelModel::getTypeList());
$this->view->assign("statusList", ChannelModel::getStatusList());
}
/**
* 查看
*/
public function index()
{
if ($this->request->isAjax()) {
$search = $this->request->request("search");
$model_id = $this->request->request("model_id");
//构造父类select列表选项数据
$list = [];
if ($search) {
foreach ($this->channelList as $k => $v) {
if (stripos($v['name'], $search) !== false || stripos($v['nickname'], $search) !== false) {
$list[] = $v;
}
}
} else {
$list = $this->channelList;
}
foreach ($list as $index => $item) {
if ($model_id && $model_id != $item['model_id']) {
unset($list[$index]);
}
}
$list = array_values($list);
$modelNameArr = [];
foreach ($this->modelList as $k => $v) {
$modelNameArr[$v['id']] = $v['name'];
}
foreach ($list as $k => &$v) {
$v['pid'] = $v['parent_id'];
$v['model_name'] = $v['model_id'] && isset($modelNameArr[$v['model_id']]) ? $modelNameArr[$v['model_id']] : __('None');
}
$total = count($list);
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
{
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = basename(str_replace('\\', '/', get_class($this->model)));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->model->validate($validate);
}
$nameArr = array_filter(explode("\n", str_replace("\r\n", "\n", $params['name'])));
if (count($nameArr) > 1) {
foreach ($nameArr as $index => $item) {
$itemArr = array_filter(explode('|', $item));
$params['name'] = $itemArr[0];
$params['diyname'] = isset($itemArr[1]) ? $itemArr[1] : '';
$result = $this->model->allowField(true)->isUpdate(false)->data($params)->save();
}
} else {
$result = $this->model->allowField(true)->save($params);
}
if ($result !== false) {
$this->success();
} else {
$this->error($this->model->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
return $this->view->fetch();
}
/**
* 栏目授权
*/
public function admin()
{
$act = $this->request->param('act');
$ids = $this->request->param('ids');
if ($act == 'remove') {
ChannelAdmin::where('admin_id', $ids)->delete();
$this->success('删除成功!');
} elseif ($act == 'authorization') {
$selected = ChannelAdmin::getAdminChanneIds($ids);
$all = collection(ChannelModel::order("weigh desc,id desc")->select())->toArray();
foreach ($all as $k => $v) {
$state = ['opened' => true];
if ($v['type'] != 'list') {
$disabledIds[] = $v['id'];
}
if ($v['type'] == 'link') {
$state['checkbox_disabled'] = true;
}
$state['selected'] = in_array($v['id'], $selected);
$channelList[] = [
'id' => $v['id'],
'parent' => $v['parent_id'] ? $v['parent_id'] : '#',
'text' => __($v['name']),
'type' => $v['type'],
'state' => $state
];
}
$this->success('成功', '', $channelList);
} elseif ($act == 'save') {
\think\Db::startTrans();
try {
ChannelAdmin::where('admin_id', $ids)->delete();
$channelIds = explode(",", $this->request->post("ids"));
if ($channelIds) {
$listChannelIds = ChannelModel::where('type', 'list')->column('id');
$channelIds = array_intersect($channelIds, $listChannelIds);
$data = [];
foreach ($channelIds as $key => $item) {
$data[] = ['admin_id' => $ids, 'channel_id' => $item];
}
$model = new ChannelAdmin();
$model->saveAll($data, true);
}
\think\Db::commit();
} catch (Exception $e) {
\think\Db::rollback();
$this->error($e->getMessage());
}
$this->success("保存成功!");
}
if ($this->request->isAjax()) {
$list = \think\Db::name("cms_channel_admin")
->group("admin_id")
->field("COUNT(*) as channels,admin_id")
->select();
$adminChannelList = [];
foreach ($list as $index => $item) {
$adminChannelList[$item['admin_id']] = $item['channels'];
}
$superAdminIds = AuthGroupAccess::where('group_id', 1)->column('uid');
$adminList = Admin::order('id', 'desc')->field('id,username')->select();
foreach ($adminList as $index => $item) {
$item->channels = isset($adminChannelList[$item['id']]) ? $adminChannelList[$item['id']] : 0;
$item->superadmin = in_array($item['id'], $superAdminIds);
}
$total = count($adminList);
$result = array("total" => $total, "rows" => $adminList);
return json($result);
}
return $this->view->fetch();
}
/**
* Selectpage搜索
*
* @internal
*/
public function selectpage()
{
return parent::selectpage();
}
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available()
{
$id = $this->request->request('id');
$name = $this->request->request('name');
$value = $this->request->request('value');
$name = substr($name, 4, -1);
if (!$name) {
$this->error(__('Parameter %s can not be empty', 'name'));
}
if ($name == 'diyname') {
if ($id) {
$this->model->where('id', '<>', $id);
}
$exist = $this->model->where($name, $value)->find();
if ($exist) {
$this->error(__('The data already exist'));
} else {
$this->success();
}
} elseif ($name == 'name') {
$nameArr = array_filter(explode("\n", str_replace("\r\n", "\n", $value)));
if (count($nameArr) > 1) {
foreach ($nameArr as $index => $item) {
$itemArr = array_filter(explode('|', $item));
if (!isset($itemArr[1])) {
$this->error('格式:分类名称|自定义名称');
}
$exist = \app\admin\model\cms\Channel::getByDiyname($itemArr[1]);
if ($exist) {
$this->error('自定义名称[' . $itemArr[1] . ']已经存在');
}
}
$this->success();
} else {
$this->success();
}
}
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 评论管理
*
* @icon fa fa-comment
*/
class Comment extends Backend
{
/**
* Comment模型对象
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Comment;
$this->view->assign("typeList", $this->model->getTypeList());
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 查看
*/
public function index()
{
$this->relationSearch = true;
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->with(['archives', 'spage', 'user'])
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->with(['archives', 'spage', 'user'])
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
foreach ($list as $index => $item) {
$item->user->visible(['id', 'username', 'nickname', 'avatar']);
}
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
$this->assignconfig("typeList", $this->model->getTypeList());
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 自定义表单数据表
*
* @icon fa fa-circle-o
*/
class Diydata extends Backend
{
/**
* 自定义表单模型对象
*/
protected $diyform = null;
/**
* 定义表单数据表模型
* @var null
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$diyform_id = $this->request->param('diyform_id');
$this->diyform = \app\admin\model\cms\Diyform::get($diyform_id);
if (!$this->diyform) {
$this->error('未找到对应自定义表单');
}
$this->model = \think\Db::name($this->diyform['table']);
$this->assignconfig('diyform_id', $diyform_id);
}
/**
* 查看
*/
public function index()
{
$fieldsList = \app\admin\model\cms\Fields::where('diyform_id', $this->diyform['id'])->where('type', '<>', 'text')->select();
$fields = [];
foreach ($fieldsList as $index => $item) {
$fields[] = ['field' => $item['name'], 'title' => $item['title'], 'type' => $item['type'], 'content' => $item['content_list']];
}
$this->assignconfig('fields', $fields);
$diyformList = \app\admin\model\cms\Diyform::all();
$this->view->assign('diyform', $this->diyform);
$this->view->assign('diyformList', $diyformList);
return parent::index();
}
/**
* 添加
*/
public function add()
{
$this->assignFields();
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
try {
$result = $this->model->insert($params);
if ($result !== false) {
$this->success();
} else {
$this->error($this->model->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
return $this->view->fetch();
}
/**
* 编辑
*/
public function edit($ids = null)
{
$row = $this->model->where('id', $ids)->find();
if (!$row) {
$this->error(__('No Results were found'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
if (!in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
}
if ($this->request->isPost()) {
$params = $this->request->post("row/a");
if ($params) {
try {
$result = $this->model->where('id', $ids)->update($params);
if ($result !== false) {
$this->success();
} else {
$this->error($row->getError());
}
} catch (\think\exception\PDOException $e) {
$this->error($e->getMessage());
} catch (\think\Exception $e) {
$this->error($e->getMessage());
}
}
$this->error(__('Parameter %s can not be empty', ''));
}
$this->assignFields($ids);
$this->view->assign("row", $row);
return $this->view->fetch();
}
/**
* 删除
*/
public function del($ids = "")
{
if ($ids) {
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$count = $this->model->where($this->dataLimitField, 'in', $adminIds);
}
$count = $this->model->where($pk, 'in', $ids)->delete();
if ($count) {
$this->success();
} else {
$this->error(__('No rows were deleted'));
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
private function assignFields($diydata_id = 0)
{
$values = [];
if ($diydata_id) {
$values = db($this->diyform['table'])->where('id', $diydata_id)->find();
}
$fields = \app\admin\model\cms\Fields::where('diyform_id', $this->diyform['id'])
->order('weigh desc,id desc')
->select();
foreach ($fields as $k => $v) {
$v->value = isset($values[$v['name']]) ? $values[$v['name']] : '';
$v->rule = str_replace(',', '; ', $v->rule);
if (in_array($v->type, ['checkbox', 'lists', 'images'])) {
$checked = '';
if ($v['minimum'] && $v['maximum']) {
$checked = "{$v['minimum']}~{$v['maximum']}";
} elseif ($v['minimum']) {
$checked = "{$v['minimum']}~";
} elseif ($v['maximum']) {
$checked = "~{$v['maximum']}";
}
if ($checked) {
$v->rule .= (';checked(' . $checked . ')');
}
}
if (in_array($v->type, ['checkbox', 'radio']) && stripos($v->rule, 'required') !== false) {
$v->rule = str_replace('required', 'checked', $v->rule);
}
if (in_array($v->type, ['selects'])) {
$v->extend .= (' ' . 'data-max-options="' . $v['maximum'] . '"');
}
}
$this->view->assign('fields', $fields);
$this->view->assign('values', $values);
}
/**
* 导入
*/
public function import($ids = "")
{
$this->model = new \addons\cms\model\Diydata($this->diyform->table);
return parent::import();
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 自定义表单表
*
* @icon fa fa-list
*/
class Diyform extends Backend
{
/**
* Model模型对象
*/
protected $model = null;
protected $noNeedRight = ['check_element_available'];
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Diyform;
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available()
{
$id = $this->request->request('id');
$name = $this->request->request('name');
$value = $this->request->request('value');
$name = substr($name, 4, -1);
if (!$name) {
$this->error(__('Parameter %s can not be empty', 'name'));
}
if ($id) {
$this->model->where('id', '<>', $id);
}
$exist = $this->model->where($name, $value)->find();
if ($exist) {
$this->error(__('The data already exist'));
} else {
$this->success();
}
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
use app\common\model\Config;
/**
* 模型字段表
*
* @icon fa fa-circle-o
*/
class Fields extends Backend
{
/**
* Fields模型对象
*/
protected $model = null;
protected $modelValidate = true;
protected $modelSceneValidate = true;
protected $noNeedRight = ['rulelist'];
protected $multiFields = 'isfilter,iscontribute';
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Fields;
$this->view->assign("statusList", $this->model->getStatusList());
$this->view->assign('typeList', Config::getTypeList());
$this->view->assign('regexList', Config::getRegexList());
}
/**
* 查看
*/
public function index()
{
$model_id = $this->request->param('model_id', 0);
$diyform_id = $this->request->param('diyform_id', 0);
$condition = $model_id ? ['model_id' => $model_id] : ['diyform_id' => $diyform_id];
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($condition)
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->where($condition)
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$nameArr = [
'id' => '主键',
'user_id' => '会员ID',
'channel_id' => '栏目ID',
'model_id' => '模型ID',
'special_id' => '专题ID',
'title' => '标题',
'style' => '样式',
'flag' => '标志',
'image' => '缩略图',
'keywords' => '关键字',
'description' => '描述',
'tags' => '标签',
'weigh' => '权重',
'views' => '浏览次数',
'comments' => '评论次数',
'likes' => '点赞次数',
'dislikes' => '点踩次数',
'diyname' => '自定义名称',
'createtime' => '创建时间',
'updatetime' => '更新时间',
'publishtime' => '发布时间',
'deletetime' => '删除时间',
'memo' => '备注',
'status' => '状态'
];
if ($model_id) {
$list = collection($list)->toArray();
$tableInfoList = \think\Db::name('cms_archives')->getTableInfo();
$tableInfoList['fields'] = array_reverse($tableInfoList['fields']);
foreach ($tableInfoList['fields'] as $index => $field) {
$type = isset($tableInfoList['type'][$field]) ? substr($tableInfoList['type'][$field], 0, stripos($tableInfoList['type'][$field], '(')) : 'unknown';
$item = [
'state' => false, 'model_id' => $model_id, 'diyform_id' => '-', 'name' => $field, 'title' => isset($nameArr[$field]) ? $nameArr[$field] : '',
'type' => $type, 'issystem' => true, 'isfilter' => 0, 'iscontribute' => 0, 'status' => 'normal', 'createtime' => 0, 'updatetime' => 0
];
$list[] = $item;
}
}
$result = array("total" => $total, "rows" => $list);
return json($result);
}
$this->assignconfig('model_id', $model_id);
$this->assignconfig('diyform_id', $diyform_id);
$this->view->assign('model_id', $model_id);
$this->view->assign('diyform_id', $diyform_id);
$model = $model_id ? \app\admin\model\cms\Modelx::get($model_id) : \app\admin\model\cms\Diyform::get($diyform_id);
$this->view->assign('model', $model);
$modelList = $model_id ? \app\admin\model\cms\Modelx::all() : \app\admin\model\cms\Diyform::all();
$this->view->assign('modelList', $modelList);
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
{
$model_id = $this->request->param('model_id', 0);
$diyform_id = $this->request->param('diyform_id', 0);
$this->view->assign('model_id', $model_id);
$this->view->assign('diyform_id', $diyform_id);
return parent::add();
}
/**
* 批量操作
* @param string $ids
*/
public function multi($ids = "")
{
$params = $this->request->request('params');
parse_str($params, $paramsArr);
if (isset($paramsArr['isfilter'])) {
$field = \app\admin\model\cms\Fields::get($ids);
if (!$field || !in_array($field['type'], ['radio', 'checkbox', 'select', 'selects', 'array'])) {
$this->error('只有类型为单选、复选、下拉列表、数组才可以加入列表筛选');
}
}
return parent::multi($ids);
}
/**
* 规则列表
* @internal
*/
public function rulelist()
{
//主键
$primarykey = $this->request->request("keyField");
//主键值
$keyValue = $this->request->request("keyValue", "");
$keyValueArr = array_filter(explode(',', $keyValue));
$regexList = Config::getRegexList();
$list = [];
foreach ($regexList as $k => $v) {
if ($keyValueArr) {
if (in_array($k, $keyValueArr)) {
$list[] = ['id' => $k, 'name' => $v];
}
} else {
$list[] = ['id' => $k, 'name' => $v];
}
}
return json(['list' => $list]);
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
use think\Exception;
/**
* 内容模型表
*
* @icon fa fa-th
*/
class Modelx extends Backend
{
/**
* Model模型对象
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Modelx;
}
/**
* 复制模型
*/
public function duplicate($ids = "")
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
if (!in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
}
if ($this->request->isPost()) {
$table = $this->request->request("table");
try {
$data = [
'name' => $row->getData('name') . '_copy',
'table' => $table,
'fields' => $row->fields,
'channeltpl' => $row->channeltpl,
'listtpl' => $row->listtpl,
'showtpl' => $row->showtpl,
'setting' => $row->setting,
];
$modelx = \app\admin\model\cms\Modelx::create($data, true);
$fieldsList = \app\admin\model\cms\Fields::where('model_id', $row['id'])->select();
foreach ($fieldsList as $index => $item) {
$data = $item->toArray();
$data['model_id'] = $modelx->id;
unset($data['id'], $data['createtime'], $data['updatetime']);
\app\admin\model\cms\Fields::create($data, true);
}
} catch (Exception $e) {
$this->error("复制失败,错误:" . $e->getMessage());
}
$this->success();
}
$this->view->assign("row", $row);
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 订单管理
*
* @icon fa fa-cny
*/
class Order extends Backend
{
/**
* Order模型对象
* @var \app\admin\model\cms\Order
*/
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Order;
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 查看
*/
public function index()
{
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
$this->relationSearch = true;
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->with(['user', 'archives'])
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->with(['user', 'archives'])
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
foreach ($list as $item) {
$item->user->visible(['id', 'username', 'nickname', 'avatar']);
$item->archives->visible(['id', 'title', 'diyname']);
}
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 单页表
*
* @icon fa fa-file
*/
class Page extends Backend
{
/**
* Page模型对象
*/
protected $model = null;
protected $noNeedRight = ['selectpage_type', 'check_element_available'];
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Page;
$this->view->assign("flagList", $this->model->getFlagList());
$this->view->assign("statusList", $this->model->getStatusList());
}
public function index()
{
$typeArr = \app\admin\model\cms\Page::distinct('type')->column('type');
$this->view->assign('typeList', $typeArr);
$this->assignconfig('typeList', $typeArr);
return parent::index();
}
/**
* 查看
*/
public function select()
{
$typeArr = \app\admin\model\cms\Page::distinct('type')->column('type');
$this->view->assign('typeList', $typeArr);
$this->assignconfig('typeList', $typeArr);
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax()) {
//如果发送的来源是Selectpage,则转发到Selectpage
if ($this->request->request('keyField')) {
return $this->selectpage();
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$list = collection($list)->toArray();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
/**
* 动态下拉选择类型
* @internal
*/
public function selectpage_type()
{
$list = [];
$word = (array)$this->request->request("q_word/a");
$field = $this->request->request('showField');
$keyValue = $this->request->request('keyValue');
if (!$keyValue) {
if (array_filter($word)) {
foreach ($word as $k => $v) {
$list[] = ['id' => $v, $field => $v];
}
}
$typeArr = \app\admin\model\cms\Page::column('type');
$typeArr = array_unique($typeArr);
foreach ($typeArr as $index => $item) {
$list[] = ['id' => $item, $field => $item];
}
} else {
$list[] = ['id' => $keyValue, $field => $keyValue];
}
return json(['total' => count($list), 'list' => $list]);
}
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available()
{
$id = $this->request->request('id');
$name = $this->request->request('name');
$value = $this->request->request('value');
$name = substr($name, 4, -1);
if (!$name) {
$this->error(__('Parameter %s can not be empty', 'name'));
}
if ($id) {
$this->model->where('id', '<>', $id);
}
$exist = $this->model->where($name, $value)->find();
if ($exist) {
$this->error(__('The data already exist'));
} else {
$this->success();
}
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 专题管理
*
* @icon fa fa-newspaper-o
*/
class Special extends Backend
{
/**
* Special模型对象
* @var \app\admin\model\cms\Special
*/
protected $model = null;
protected $noNeedRight = ['check_element_available'];
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Special;
$this->view->assign("flagList", $this->model->getFlagList());
$this->view->assign("statusList", $this->model->getStatusList());
}
/**
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
*/
/**
* 检测元素是否可用
* @internal
*/
public function check_element_available()
{
$id = $this->request->request('id');
$name = $this->request->request('name');
$value = $this->request->request('value');
$name = substr($name, 4, -1);
if (!$name) {
$this->error(__('Parameter %s can not be empty', 'name'));
}
if ($id) {
$this->model->where('id', '<>', $id);
}
$exist = $this->model->where($name, $value)->find();
if ($exist) {
$this->error(__('The data already exist'));
} else {
$this->success();
}
}
}
... ...
<?php
namespace app\admin\controller\cms;
use app\common\controller\Backend;
/**
* 标签表
*
* @icon fa fa-tags
*/
class Tags extends Backend
{
/**
* Tags模型对象
*/
protected $model = null;
protected $noNeedRight = ['selectpage', 'autocomplete'];
public function _initialize()
{
parent::_initialize();
$this->model = new \app\admin\model\cms\Tags;
}
public function selectpage()
{
$response = parent::selectpage();
$word = (array)$this->request->request("q_word/a");
if (array_filter($word)) {
$result = $response->getData();
$list = [];
foreach ($result['list'] as $index => $item) {
$list[] = strtolower($item['name']);
}
foreach ($word as $k => $v) {
if (!in_array(strtolower($v), $list)) {
array_unshift($result['list'], ['id' => $v, 'name' => $v]);
}
$result['total']++;
}
$response->data($result);
}
return $response;
}
public function autocomplete()
{
$q = $this->request->request('q');
$list = \app\admin\model\cms\Tags::where('name', 'like', '%' . $q . '%')->column('name');
echo json_encode($list);
return;
}
}
... ...
<?php
return [
'Please input your content' => '请输入检测内容',
'The content is not legal' => '发现违禁词',
'The content is legal' => '未发现违禁词',
];
\ No newline at end of file
... ...
<?php
return [
'Channel' => '栏目',
'Channel_id' => '栏目ID',
'Channel_name' => '栏目名称',
'Channel list' => '栏目列表',
'Addon list' => '副表列表',
'Model' => '模型',
'Model_id' => '模型ID',
'User_id' => '发布会员',
'Special_id' => '所属专题',
'Title' => '文章标题',
'Flag' => '标志',
'Top' => '置顶',
'Image' => '缩略图',
'Keywords' => '关键字',
'Description' => '描述',
'Tags' => 'TAG',
'Weigh' => '权重',
'Views' => '浏览',
'Comments' => '评论',
'Likes' => '点赞',
'Dislikes' => '点踩',
'Diyname' => '自定义URL',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Deletetime' => '删除时间',
'Recycle bin' => '回收站',
'Restore' => '还原',
'Restore all' => '还原全部',
'Destroy' => '销毁',
'Destroy all' => '清空回收站',
'Nothing need restore' => '没有需要还原的数据',
'Move tips' => '只能将数据移动到相同模型的栏目下,不同模型的数据移动将被忽略',
'Are you sure you want to truncate?' => '确认清空回收站?',
'Can not be digital' => '不能为数字',
'Check content is legal' => '检查内容是否有违禁词',
'Get the keyword and description' => '提取关键字和描述',
'Please select channel' => '请选择分类',
'The data already exist' => '已经存在',
'Banned words' => '违禁词',
'Status' => '状态',
'Status normal' => '正常',
'Status hidden' => '隐藏',
'Status rejected' => '已拒绝',
'Status pulloff' => '已下线',
'Set to rejected' => '设为拒绝',
'Set to pulloff' => '设为下线',
'Publish and continue' => '发布并新增',
'Array key' => '键',
'Array value' => '值',
'Publish' => '发布'
];
\ No newline at end of file
... ...
<?php
return [
'Type' => '类型',
'Name' => '名称',
'Title' => '标题',
'Image' => '图片',
'Url' => '链接',
'Content' => '内容',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Status' => '状态'
];
... ...
<?php
return [
'Type' => '类型',
'Model_id' => '模型ID',
'Model_name' => '模型名称',
'Parent_id' => '父ID',
'Parent_ids' => '父ID集合',
'Child_ids' => '子ID集合',
'Name' => '名称',
'Image' => '图片',
'Keywords' => '关键字',
'Description' => '描述',
'Diyname' => '自定义名称',
'Outlink' => '外部链接',
'Items' => '文章数量',
'Channels' => '栏目数量',
'Authorization' => '授权',
'Save' => '保存',
'Weigh' => '权重',
'Channeltpl' => '栏目页模板',
'Listtpl' => '列表页模板',
'Showtpl' => '详情页模板',
'Pagesize' => '分页大小',
'Remove' => '移除',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'The data already exist' => '已经存在',
'You must choose at least one channel' => '必须选择一个栏目',
'Are you sure you want to remove this item?' => '确认要取消此管理员的所有栏目授权?',
'Toggle all' => '显示全部',
'Toggle menu visible' => '点击切换菜单显示',
'Toggle sub menu' => '点击切换子菜单显示',
'Iscontribute' => '是否允许投稿',
'Isnav' => '是否导航显示',
'Status' => '状态',
'Channel' => '栏目',
'List' => '列表',
'Link' => '外部链接'
];
... ...
<?php
return [
'Id' => 'ID',
'Type' => '类型',
'Archives' => '文档',
'Page' => '单页',
'Special' => '专题',
'Aid' => '关联ID',
'Pid' => '父ID',
'User_id' => '会员ID',
'Content' => '内容',
'Comments' => '评论数',
'Ip' => 'IP',
'Useragent' => 'User Agent',
'Subscribe' => '订阅',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Status' => '状态'
];
... ...
<?php
return [
'User_id' => '会员ID',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Status' => '状态'
];
... ...
<?php
return [
'Type' => '类型',
'Name' => '名称',
'Table' => '表名',
'Keywords' => '关键字',
'Description' => '描述',
'Successtips' => '成功提交提示文字',
'Redirecturl' => '成功后跳转链接',
'Diyname' => '自定义URL名称',
'Needlogin' => '是否需要登录',
'Formtpl' => '表单模板',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Status' => '状态',
'Redirecturl tips' => '为空时将跳转到CMS首页',
'The data already exist' => '已经存在'
];
... ...
<?php
return [
'Model_id' => '模型ID',
'Name' => '名称',
'Type' => '类型',
'Title' => '标题',
'Content' => '条目列表',
'Rule' => '验证规则',
'Validate Msg' => '错误消息',
'Validate Ok' => '成功消息',
'Validate Tip' => '提示消息',
'Extend' => '扩展信息',
'Weigh' => '排序',
'Setting' => '字段设置',
'Length' => '字段长度',
'Decimals' => '小数点长度',
'Minimum' => '最少选择',
'Maximum' => '最大选择',
'Defaultvalue' => '默认值',
'Iscontribute' => '是否可投稿',
'Isfilter' => '是否列表筛选',
'String' => '字符',
'Text' => '文本',
'Editor' => '编辑器',
'Number' => '数字',
'Date' => '日期',
'Time' => '时间',
'Datetime' => '日期时间',
'Image' => '图片',
'Images' => '图片(多)',
'File' => '文件',
'Files' => '文件(多)',
'Select' => '列表',
'Selects' => '列表(多选)',
'Switch' => '开关',
'Checkbox' => '复选',
'Radio' => '单选',
'Array' => '数组',
'Array key' => '键名',
'Array value' => '键值',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Status' => '状态'
];
... ...
<?php
return [
'Name' => '模型名称',
'Table' => '表名',
'Fields' => '字段列表',
'Channeltpl' => '栏目页模板',
'Listtpl' => '列表页模板',
'Showtpl' => '详情页模板',
'Main list' => '主表列表',
'Addon list' => '副表列表',
'Duplicate' => '复制模型',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Setting' => '配置'
];
... ...
<?php
return [
'Orderid' => '订单ID',
'User_id' => '会员ID',
'Archives_id' => '文档ID',
'Archives_title' => '文档标题',
'Title' => '订单标题',
'Amount' => '订单金额',
'Payamount' => '支付金额',
'Paytype' => '支付类型',
'Paytime' => '支付时间',
'Ip' => 'IP地址',
'Useragent' => 'UserAgent',
'Memo' => '备注',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Status' => '状态',
'Paid' => '已支付',
'Expired' => '已过期',
'Created' => '未支付',
'Set to created' => '设为未支付',
'Set to paid' => '设为已支付',
'Set to expired' => '设为已过期',
];
... ...
<?php
return [
'Id' => 'ID',
'Category_id' => '分类ID',
'Type' => '类型',
'Title' => '标题',
'Keywords' => '关键字',
'Description' => '描述',
'Flag' => '标志',
'Image' => '图片',
'Content' => '内容',
'Icon' => '图标',
'Views' => '点击',
'Comments' => '评论',
'Diyname' => '自定义URL名称',
'Showtpl' => '视图模板',
'Createtime' => '创建时间',
'Updatetime' => '更新时间',
'Check content is legal' => '检查内容是否有违禁词',
'Get the keyword and description' => '提取关键字和描述',
'The data already exist' => '已经存在',
'Weigh' => '权重',
'Select' => '选择',
'Status' => '状态'
];
... ...
<?php
return [
'Title' => '标题',
'Tag_ids' => '标签筛选集合',
'Andor' => '标签筛选条件',
'And' => '与',
'Or' => '或',
'Flag' => '标志',
'Label' => '标题标签',
'Image' => '图片',
'Banner' => 'Banner图片',
'Diyname' => '自定义URL名称',
'Keywords' => '关键字',
'Description' => '描述',
'Intro' => '专题介绍',
'Views' => '浏览次数',
'Comments' => '评论次数',
'Createtime' => '添加时间',
'Updatetime' => '更新时间',
'Template' => '专题模板',
'The data already exist' => '已经存在',
'Status' => '状态'
];
... ...
<?php
return [
'Name' => '标签名称',
'Archives' => '文档ID集合',
'Nums' => '文档数量'
];
... ...
<?php
namespace app\admin\model\cms;
use addons\cms\library\Service;
use app\common\model\Config;
use app\common\model\User;
use think\Model;
use traits\model\SoftDelete;
class Archives extends Model
{
use SoftDelete;
// 表名
protected $name = 'cms_archives';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = 'deletetime';
// 追加属性
protected $append = [
'flag_text',
'status_text',
'publishtime_text',
'url',
'style_bold',
'style_color',
];
public function getUrlAttr($value, $data)
{
$diyname = $data['diyname'] ? $data['diyname'] : $data['id'];
return addon_url('cms/archives/index', [':id' => $data['id'], ':diyname' => $diyname, ':channel' => $data['channel_id']]);
}
public function getOriginData()
{
return $this->origin;
}
/**
* 批量设置数据
* @param $data
* @return $this
*/
public function setData($data)
{
if (is_object($data)) {
$data = get_object_vars($data);
}
$this->data = array_merge($this->data, $data);
return $this;
}
protected static function init()
{
$config = get_addon_config('cms');
self::afterInsert(function ($row) {
$pk = $row->getPk();
$channel = Channel::get($row['channel_id']);
$row->getQuery()->where($pk, $row[$pk])->update(['model_id' => $channel ? $channel['model_id'] : 0]);
Channel::where('id', $row['channel_id'])->setInc('items');
});
self::beforeWrite(function ($row) {
$changedData = $row->getChangedData();
if (isset($changedData['flag'])) {
$row['weigh'] = is_array($changedData['flag']) && in_array('top', $changedData['flag'])
? ($row['weigh'] == 0 ? 9999 : $row['weigh'])
: ($row['weigh'] == 9999 ? 0 : $row['weigh']);
}
if (isset($row['content'])) {
$row['content'] = Service::autolinks($row['content']);
}
//在更新之前对数组进行处理
foreach ($row->getData() as $k => $value) {
if (is_array($value) && is_array(reset($value))) {
$value = json_encode(self::getArrayData($value), JSON_UNESCAPED_UNICODE);
} else {
$value = is_array($value) ? implode(',', $value) : $value;
}
$row->$k = $value;
}
});
self::afterWrite(function ($row) use ($config) {
if (isset($row['channel_id'])) {
//在更新成功后刷新副表、TAGS表数据、栏目表
$channel = Channel::get($row->channel_id);
if ($channel) {
$model = Modelx::get($channel['model_id']);
if ($model && isset($row['content'])) {
$values = array_intersect_key($row->getData(), array_flip($model->fields));
$values['id'] = $row['id'];
$values['content'] = $row['content'];
db($model['table'])->insert($values, true);
}
}
}
if (isset($row['tags'])) {
$tags = array_filter(explode(',', $row['tags']));
if ($tags) {
$tagslist = Tags::where('name', 'in', $tags)->select();
foreach ($tagslist as $k => $v) {
$archives = explode(',', $v['archives']);
if (!in_array($row['id'], $archives)) {
$archives[] = $row['id'];
$v->archives = implode(',', $archives);
$v->nums++;
$v->save();
}
$tags = array_diff($tags, [$v['name']]);
}
$list = [];
foreach ($tags as $k => $v) {
$list[] = ['name' => $v, 'archives' => $row['id'], 'nums' => 1];
}
if ($list) {
(new Tags())->saveAll($list);
}
}
}
$changedData = $row->getChangedData();
if (isset($changedData['status']) && $changedData['status'] == 'normal') {
User::score($config['score']['postarchives'], $row['user_id'], '发布文章');
}
});
self::afterDelete(function ($row) use ($config) {
if ($row['status'] == 'normal') {
User::score(-$config['score']['postarchives'], $row['user_id'], '删除文章');
}
});
}
public function getFlagList()
{
return ['hot' => __('Hot'), 'new' => __('New'), 'recommend' => __('Recommend'), 'top' => __('Top')];
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden'), 'rejected' => __('Status rejected'), 'pulloff' => __('Status pulloff')];
}
public function getStyleBoldAttr($value, $data)
{
return in_array('b', explode('|', $data['style']));
}
public function getStyleColorAttr($value, $data)
{
$result = preg_match("/(#([0-9a-z]{6}))/i", $data['style'], $matches);
return $result ? $matches[1] : '';
}
public function getFlagTextAttr($value, $data)
{
$value = $value ? $value : $data['flag'];
$valueArr = $value ? explode(',', $value) : [];
$list = $this->getFlagList();
return implode(',', array_intersect_key($list, array_flip($valueArr)));
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getPublishtimeTextAttr($value, $data)
{
$value = $value ? $value : $data['publishtime'];
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
protected function setPublishtimeAttr($value)
{
return $value && !is_numeric($value) ? strtotime($value) : $value;
}
public static function getArrayData($data)
{
if (!isset($data['value'])) {
$result = [];
foreach ($data as $index => $datum) {
$result['field'][$index] = $datum['key'];
$result['value'][$index] = $datum['value'];
}
$data = $result;
}
$fieldarr = $valuearr = [];
$field = isset($data['field']) ? $data['field'] : (isset($data['key']) ? $data['key'] : []);
$value = isset($data['value']) ? $data['value'] : [];
foreach ($field as $m => $n) {
if ($n != '') {
$fieldarr[] = $field[$m];
$valuearr[] = $value[$m];
}
}
return $fieldarr ? array_combine($fieldarr, $valuearr) : [];
}
public function channel()
{
return $this->belongsTo('Channel', 'channel_id', '', [], 'LEFT')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Block extends Model
{
// 表名
protected $name = 'cms_block';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'status_text'
];
protected static function init()
{
self::afterInsert(function ($row) {
$row->save(['weigh' => $row['id']]);
});
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Channel extends Model
{
// 表名
protected $name = 'cms_channel';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'type_text',
'status_text',
'url'
];
public function getUrlAttr($value, $data)
{
$diyname = $data['diyname'] ? $data['diyname'] : $data['id'];
return isset($data['type']) && isset($data['outlink']) && $data['type'] == 'link' ? $data['outlink'] : addon_url('cms/channel/index', [':id' => $data['id'], ':diyname' => $diyname]);
}
protected static function init()
{
self::beforeInsert(function ($row) {
if ($row->getData('type') == 'link') {
$row->model_id = 0;
}
});
self::afterInsert(function ($row) {
//创建时自动添加权重值
$pk = $row->getPk();
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
});
self::afterDelete(function ($row) {
//删除时,删除子节点,同时将所有相关文档移入回收站
static $tree;
if (!$tree) {
$tree = \fast\Tree::instance();
$tree->init(collection(Channel::order('weigh desc,id desc')->field('id,parent_id,name,type,diyname,status')->select())->toArray(), 'parent_id');
}
$childIds = $tree->getChildrenIds($row['id']);
if ($childIds) {
Channel::destroy(function ($query) use ($childIds) {
$query->where('id', 'in', $childIds);
});
}
$childIds[] = $row['id'];
db('cms_archives')->where('channel_id', 'in', $childIds)->update(['deletetime' => time()]);
});
self::afterWrite(function ($row) {
$changed = $row->getChangedData();
//隐藏时判断是否有子节点,有则隐藏
if (isset($changed['status']) && $changed['status'] == 'hidden') {
static $tree;
if (!$tree) {
$tree = \fast\Tree::instance();
$tree->init(collection(Channel::order('weigh desc,id desc')->field('id,parent_id,name,type,diyname,status')->select())->toArray(), 'parent_id');
}
$childIds = $tree->getChildrenIds($row['id']);
db('cms_channel')->where('id', 'in', $childIds)->update(['status' => 'hidden']);
}
//隐藏栏目显示时判断是否有子节点
if (isset($changed['isnav']) && !$changed['isnav']) {
static $tree;
if (!$tree) {
$tree = \fast\Tree::instance();
$tree->init(collection(Channel::order('weigh desc,id desc')->field('id,parent_id,name,type,diyname,isnav,status')->select())->toArray(), 'parent_id');
}
$childIds = $tree->getChildrenIds($row['id']);
db('cms_channel')->where('id', 'in', $childIds)->update(['isnav' => 0]);
}
});
}
public static function getTypeList()
{
return ['channel' => __('Channel'), 'list' => __('List'), 'link' => __('Link')];
}
public static function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getTypeTextAttr($value, $data)
{
$value = $value ? $value : $data['type'];
$list = $this->getTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function model()
{
return $this->belongsTo('Modelx', 'model_id')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use app\admin\library\Auth;
use think\Model;
class ChannelAdmin extends Model
{
// 表名
protected $name = 'cms_channel_admin';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
// 追加属性
protected $append = [
];
public static function getAdminChanneIds($admin_id = null)
{
$admin_id = $admin_id ? $admin_id : Auth::instance()->id;
$selected = ChannelAdmin::where('admin_id', $admin_id)->column('channel_id');
return $selected;
}
public function admin()
{
return $this->belongsTo('\app\admin\model\Admin', 'admin_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function channel()
{
return $this->belongsTo('\app\admin\model\cms\Channel', 'channel_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use app\common\model\User;
use think\Model;
class Comment extends Model
{
// 表名
protected $name = 'cms_comment';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'type_text',
'status_text'
];
protected static function init()
{
$config = get_addon_config('cms');
self::afterWrite(function ($row) use ($config) {
$changedData = $row->getChangedData();
if (isset($changedData['status']) && $changedData['status'] == 'normal') {
User::score($config['score']['postcomment'], $row['user_id'], '发表评论');
}
});
self::afterDelete(function ($row) use ($config) {
if ($row['status'] == 'normal') {
User::score(-$config['score']['postcomment'], $row['user_id'], '删除评论');
}
});
}
public function getTypeList()
{
return ['archives' => __('Archives'), 'page' => __('Page')];
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getTypeTextAttr($value, $data)
{
$value = $value ? $value : $data['type'];
$list = $this->getTypeList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function user()
{
return $this->belongsTo('\app\common\model\User', 'user_id', '', [], 'LEFT')->setEagerlyType(0);
}
public function archives()
{
return $this->belongsTo('Archives', 'aid', '', [], 'LEFT')->setEagerlyType(0);
}
/**
* 关联单页模型
*/
public function spage()
{
return $this->belongsTo("addons\cms\model\Page", 'aid', '', [], 'LEFT')->field('id,title,createtime')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Config;
use think\Model;
class Diyform extends Model
{
// 表名
protected $name = 'cms_diyform';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'url'
];
public static function init()
{
self::afterInsert(function ($row) {
$prefix = Config::get('database.prefix');
$sql = "CREATE TABLE `{$prefix}{$row['table']}` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) DEFAULT NULL COMMENT '会员ID',
`createtime` int(10) DEFAULT NULL COMMENT '添加时间',
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='{$row['name']}'";
db()->query($sql);
});
}
public function getUrlAttr($value, $data)
{
$diyname = $data['diyname'] ? $data['diyname'] : $data['id'];
return addon_url('cms/diyform/index', [':id' => $data['id'], ':diyname' => $diyname]);
}
public function getFieldsAttr($value, $data)
{
return is_array($value) ? $value : ($value ? explode(',', $value) : []);
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
}
... ...
<?php
namespace app\admin\model\cms;
use addons\cms\library\Alter;
use app\common\model\Config;
use think\Exception;
use think\exception\PDOException;
use think\Model;
class Fields extends Model
{
// 表名
protected $name = 'cms_fields';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'status_text',
'content_list',
];
protected static $listField = ['select', 'selects', 'checkbox', 'radio', 'array'];
public function setError($error)
{
$this->error = $error;
}
protected static function init()
{
$beforeUpdateCallback = function ($row) {
if (!preg_match("/^([a-zA-Z0-9_]+)$/i", $row['name'])) {
throw new Exception("字段只支持字母数字下划线");
}
if (is_numeric(substr($row['name'], 0, 1))) {
throw new Exception("字段不能以数字开始");
}
if ($row->model_id) {
$tableFields = \think\Db::name('cms_archives')->getTableFields();
if (in_array(strtolower($row['name']), $tableFields)) {
throw new Exception("字段已经在主表存在了");
}
} else {
$tableFields = ['id', 'user_id', 'createtime', 'updatetime'];
if (in_array(strtolower($row['name']), $tableFields)) {
throw new Exception("字段为保留字段,请使用其它字段");
}
}
};
$afterInsertCallback = function ($row) {
//为了避免引起更新的事件回调,这里采用直接执行SQL的写法
$row->query($row->fetchSql(true)->update(['id' => $row['id'], 'weigh' => $row['id']]));
$field = $row['model_id'] ? 'model_id' : 'diyform_id';
$model = $row['model_id'] ? Modelx::get($row[$field]) : Diyform::get($row[$field]);
if ($model) {
$sql = Alter::instance()
->setTable($model['table'])
->setName($row['name'])
->setLength($row['length'])
->setContent($row['content'])
->setDecimals($row['decimals'])
->setDefaultvalue($row['defaultvalue'])
->setComment($row['title'])
->setType($row['type'])
->getAddSql();
try {
db()->query($sql);
$fields = Fields::where($field, $model['id'])->field('name')->column('name');
$model->fields = implode(',', $fields);
$model->save();
} catch (PDOException $e) {
$row->getQuery()->where('id', $row->id)->delete();
throw new Exception($e->getMessage());
}
}
};
$afterUpdateCallback = function ($row) {
$field = $row['model_id'] ? 'model_id' : 'diyform_id';
$model = $row['model_id'] ? Modelx::get($row[$field]) : Diyform::get($row[$field]);
if ($model) {
$alter = Alter::instance();
if (isset($row['oldname']) && $row['oldname'] != $row['name']) {
$alter->setOldname($row['oldname']);
}
$sql = $alter
->setTable($model['table'])
->setName($row['name'])
->setLength($row['length'])
->setContent($row['content'])
->setDecimals($row['decimals'])
->setDefaultvalue($row['defaultvalue'])
->setComment($row['title'])
->setType($row['type'])
->getModifySql();
db()->query($sql);
$fields = Fields::where($field, $model['id'])->field('name')->column('name');
$model->fields = implode(',', $fields);
$model->save();
}
};
self::beforeInsert($beforeUpdateCallback);
self::beforeUpdate($beforeUpdateCallback);
self::afterInsert($afterInsertCallback);
self::afterUpdate($afterUpdateCallback);
self::afterDelete(function ($row) {
$field = $row['model_id'] ? 'model_id' : 'diyform_id';
$model = $row['model_id'] ? Modelx::get($row[$field]) : Diyform::get($row[$field]);
if ($model) {
$sql = Alter::instance()
->setTable($model['table'])
->setName($row['name'])
->getDropSql();
try {
db()->query($sql);
$fields = Fields::where($field, $model['id'])->field('name')->column('name');
$model->fields = implode(',', $fields);
$model->save();
} catch (PDOException $e) {
}
}
});
}
public function getContentListAttr($value, $data)
{
return in_array($data['type'], self::$listField) ? Config::decode($data['content']) : $data['content'];
}
public function getDownloadListAttr($value, $data)
{
$config = get_addon_config('cms');
$downloadtype = $config['downloadtype'];
$result = [];
foreach ($downloadtype as $index => $item) {
$result[] = ['name' => $index, 'url' => '', 'password' => ''];
}
return json_encode($result);
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function model()
{
return $this->belongsTo('Modelx', 'model_id')->setEagerlyType(0);
}
public function diyform()
{
return $this->belongsTo('Diyform', 'diyform_id')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Config;
use think\Model;
class Modelx extends Model
{
// 表名
protected $name = 'cms_model';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
];
public static function init()
{
self::afterInsert(function ($row) {
$prefix = Config::get('database.prefix');
$sql = "CREATE TABLE `{$prefix}{$row['table']}` (`id` int(10) NOT NULL,`content` longtext NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='{$row['name']}'";
db()->query($sql);
});
}
public function getFieldsAttr($value, $data)
{
return is_array($value) ? $value : ($value ? explode(',', $value) : []);
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Order extends Model
{
// 表名
protected $name = 'cms_order';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'paytime_text',
'status_text'
];
public function getStatusList()
{
return ['created' => __('Created'), 'paid' => __('Paid'), 'expired' => __('Expired')];
}
public function getPaytimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['paytime']) ? $data['paytime'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
protected function setPaytimeAttr($value)
{
return $value && !is_numeric($value) ? strtotime($value) : $value;
}
public function user()
{
return $this->belongsTo("\app\common\model\User", 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
public function archives()
{
return $this->belongsTo("Archives", 'archives_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Page extends Model
{
// 表名
protected $name = 'cms_page';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'flag_text',
'status_text',
'url'
];
protected static function init()
{
self::afterInsert(function ($row) {
$row->save(['weigh' => $row['id']]);
});
}
public function getUrlAttr($value, $data)
{
return addon_url('cms/page/index', [':diyname' => $data['diyname']]);
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : $data['status'];
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
public function getFlagList()
{
return ['hot' => __('Hot'), 'index' => __('Index'), 'recommend' => __('Recommend')];
}
public function getFlagTextAttr($value, $data)
{
$value = $value ? $value : $data['flag'];
$valueArr = explode(',', $value);
$list = $this->getFlagList();
return implode(',', array_intersect_key($list, array_flip($valueArr)));
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Special extends Model
{
//数据库
protected $connection = 'database';
// 表名
protected $name = 'cms_special';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
protected $deleteTime = false;
// 追加属性
protected $append = [
'url',
'flag_text',
'status_text'
];
public function getUrlAttr($value, $data)
{
$diyname = $data['diyname'] ? $data['diyname'] : $data['id'];
return addon_url('cms/special/index', [':id' => $data['id'], ':diyname' => $diyname]);
}
public function getFlagList()
{
return ['hot' => __('Hot'), 'new' => __('New'), 'recommend' => __('Recommend'), 'top' => __('Top')];
}
public function getStatusList()
{
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
}
public function getFlagTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['flag']) ? $data['flag'] : '');
$valueArr = explode(',', $value);
$list = $this->getFlagList();
return implode(',', array_intersect_key($list, array_flip($valueArr)));
}
public function getStatusTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
$list = $this->getStatusList();
return isset($list[$value]) ? $list[$value] : '';
}
protected function setFlagAttr($value)
{
return is_array($value) ? implode(',', $value) : $value;
}
}
... ...
<?php
namespace app\admin\model\cms;
use think\Model;
class Tags extends Model
{
// 表名
protected $name = 'cms_tags';
// 自动写入时间戳字段
protected $autoWriteTimestamp = false;
// 定义时间戳字段名
protected $createTime = false;
protected $updateTime = false;
// 追加属性
protected $append = [
'url'
];
public function getUrlAttr($value, $data)
{
return addon_url('cms/tags/index', [':name' => $data['name']]);
}
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Archives extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Block extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Channel extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Comment extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Fields extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'name|名称' => 'require|unique:cms_fields,model_id^name',
'title|管理员' => 'require',
'model_id|模型ID' => 'require|integer',
'diyform_id|自定义表单ID' => 'require|integer',
'status|状态' => 'require|in:normal,hidden',
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [
'name', 'title', 'model_id', 'diyform_id', 'status'
],
'edit' => [
'name', 'title', 'model_id', 'diyform_id', 'status'
],
];
public function __construct(array $rules = array(), $message = array(), $field = array())
{
//如果是编辑模式,则排除下主键
$ids = request()->param("ids");
$model_id = request()->param('model_id');
$fieldName = $model_id ? 'model_id' : 'diyform_id';
if ($ids) {
$this->rule['name|名称'] = "require|unique:cms_fields,{$fieldName}^name,{$ids},id";
} else {
$this->rule['name|名称'] = "require|unique:cms_fields,{$fieldName}^name";
}
parent::__construct($rules, $message, $field);
}
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Modelx extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Order extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Page extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Special extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<?php
namespace app\admin\validate\cms;
use think\Validate;
class Tags extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
... ...
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<input type="hidden" name="row[style]" value=""/>
<div class="row">
<div class="col-md-9 col-sm-12">
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active"><a href="#basic" data-toggle="tab">基础信息</a></li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="basic">
<div class="form-group">
<label for="c-channel_id" class="control-label col-xs-12 col-sm-2">{:__('Channel_id')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-channel_id" data-rule="required" class="form-control selectpicker" data-live-search="true" name="row[channel_id]">
{$channelOptions}
</select>
</div>
</div>
<div class="form-group">
<label for="c-user_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control selectpage" data-source="user/user/index" placeholder="发布会员,可为空" data-field="nickname" name="row[user_id]"/>
</div>
</div>
<div class="form-group">
<label for="c-special_id" class="control-label col-xs-12 col-sm-2">{:__('Special_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control selectpage" data-source="cms/special/index" placeholder="所属专题,可为空" data-field="title" name="row[special_id]"/>
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text" value="">
<span class="input-group-btn">
<button class="btn btn-default btn-bold" style="margin:0 1px;" type="button"></button>
<button type="button" class="btn btn-default btn-color colorpicker" style="padding:0;margin-left:1px;" title="选择标题颜色"><img src="__CDN__/assets/addons/cms/img/colorful.png" height="29" alt=""></button>
<span class="msg-box n-right" for="c-title"></span>
</span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" class="form-control" size="50" name="row[image]" type="text" value="">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-tags" class="control-label col-xs-12 col-sm-2">{:__('Tags')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-tags" data-rule="" class="form-control" placeholder="请输入后回车或空格确认" name="row[tags]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-diyname" class="control-label col-xs-12 col-sm-2">{:__('Diyname')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">{:addon_url('cms/archives/index', [':diyname'=>''])}</button>
</div>
<input type="text" id="c-diyname" data-rule="diyname" name="row[diyname]" class="form-control" placeholder="请输入自定义的名称,为空将使用主键ID"/>
</div>
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" data-rule="required" class="form-control editor" name="row[content]" rows="15"></textarea>
<div style="margin-top:5px;">
<a href="javascript:" class="btn btn-xs btn-default btn-legal">{:__('Check content is legal')}</a>
<a href="javascript:" class="btn btn-xs btn-default btn-keywords">{:__('Get the keyword and description')}</a>
</div>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" data-rule="" class="form-control" name="row[keywords]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" cols="60" rows="5" data-rule="" class="form-control" name="row[description]"></textarea>
</div>
</div>
<div id="extend"></div>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled"><i class="fa fa-check"></i> {:__('OK')}</button>
<button type="button" class="btn btn-info btn-embossed btn-continue"><i class="fa fa-pencil"></i> {:__('Publish and continue')}</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-sm-12">
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead"><em>相关信息</em></div>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade active in">
<div class="form-group">
<label for="c-views" class="control-label col-xs-12 col-sm-3">{:__('Views')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-views" data-rule="required" class="form-control" name="row[views]" placeholder="{:__('Views')}" type="number" value="0">
<span class="input-group-addon"><i class="fa fa-eye text-success"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-comments" class="control-label col-xs-12 col-sm-3">{:__('Comments')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-comments" data-rule="required" class="form-control" name="row[comments]" placeholder="{:__('Comments')}" type="number" value="0">
<span class="input-group-addon"><i class="fa fa-comment text-info"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-likes" class="control-label col-xs-12 col-sm-3">{:__('Likes')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-likes" data-rule="required" class="form-control" name="row[likes]" placeholder="{:__('Likes')}" type="number" value="0">
<span class="input-group-addon"><i class="fa fa-thumbs-up text-danger"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-dislikes" class="control-label col-xs-12 col-sm-3">{:__('Dislikes')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-dislikes" data-rule="required" class="form-control" name="row[dislikes]" placeholder="{:__('Dislikes')}" type="number" value="0">
<span class="input-group-addon"><i class="fa fa-thumbs-down text-gray"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-3">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" data-rule="required" class="form-control" name="row[weigh]" placeholder="{:__('Weigh')}" type="number" value="0">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead"><em>状态</em></div>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade active in">
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-3">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key}" {in name="key" value="" }selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-3">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-status" class="form-control selectpicker" name="row[status]">
{foreach name="statusList" item="vo"}
<option value="{$key}" {in name="key" value="" }selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-3">{:__('Publish')}:</label>
<div class="col-xs-12 col-sm-8">
<div class='input-group date'>
<input type='text' name="row[publishtime]" data-date-format="YYYY-MM-DD HH:mm:ss" value="{:date('Y-m-d H:i:s')}" class="form-control datetimepicker"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
\ No newline at end of file
... ...
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="main.model_id">
{foreach name="modelList" item="vo"}
<li class="{:$model['id']==$vo['id']?'active':''}"><a href="cms/archives/content/model_id/{$vo.id}" data-value="{$vo.id}">{$vo.name}</a></li>
{/foreach}
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,edit,del')}
</div>
<table id="table" class="table table-striped table-bordered table-hover"
data-operate-edit="{:$auth->check('cms/model/edit')}"
data-operate-del="{:$auth->check('cms/model/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
... ...
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<input type="hidden" value="{$row.id}" id="archive-id"/>
<input type="hidden" name="row[style]" value="{$row.style}"/>
<div class="row">
<div class="col-md-9 col-sm-12">
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active"><a href="#basic" data-toggle="tab">基础信息</a></li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="basic">
<div class="form-group">
<label for="c-channel_id" class="control-label col-xs-12 col-sm-2">{:__('Channel_id')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-channel_id" data-rule="required" class="form-control selectpicker" data-live-search="true" name="row[channel_id]">
{$channelOptions}
</select>
</div>
</div>
<div class="form-group">
<label for="c-channel_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control selectpage" data-source="user/user/index" placeholder="发布会员,可为空" data-field="nickname" name="row[user_id]" value="{$row.user_id}"/>
</div>
</div>
<div class="form-group">
<label for="c-special_id" class="control-label col-xs-12 col-sm-2">{:__('Special_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control selectpage" data-source="cms/special/index" placeholder="所属专题,可为空" data-field="title" name="row[special_id]" value="{$row.special_id}"/>
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-title" data-rule="required" class="form-control {:$row.style_bold?'text-bold':''}" name="row[title]" type="text" value="{$row.title|htmlentities}" style="color:{:$row.style_color?$row.style_color:'inherit'};">
<span class="input-group-btn">
<button class="btn btn-default btn-bold {:$row.style_bold?'text-bold active':''}" style="margin:0 1px;" type="button"></button>
<button type="button" class="btn btn-default btn-color colorpicker {:$row.style_color?'active':''}" style="padding:0;margin-left:1px;" title="选择标题颜色"><img src="__CDN__/assets/addons/cms/img/colorful.png" height="29" alt=""></button>
<span class="msg-box n-right" for="c-title"></span>
</span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-tags" class="control-label col-xs-12 col-sm-2">{:__('Tags')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-tags" data-rule="" class="form-control" placeholder="请输入后回车或空格确认" name="row[tags]" type="text" value="{$row.tags|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-diyname" class="control-label col-xs-12 col-sm-2">{:__('Diyname')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">{:addon_url('cms/archives/index', [':diyname'=>''])}</button>
</div>
<input type="text" id="c-diyname" data-rule="diyname" name="row[diyname]" class="form-control" placeholder="请输入自定义的名称,为空将使用主键ID" value="{$row.diyname}"/>
</div>
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" data-rule="required" class="form-control editor" name="row[content]" rows="15">{$row.content|htmlentities}</textarea>
<div style="margin-top:5px;">
<a href="javascript:" class="btn btn-xs btn-default btn-legal">{:__('Check content is legal')}</a>
<a href="javascript:" class="btn btn-xs btn-default btn-keywords">{:__('Get the keyword and description')}</a>
</div>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" data-rule="" class="form-control" name="row[keywords]" type="text" value="{$row.keywords|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" cols="60" rows="5" data-rule="" class="form-control" name="row[description]">{$row.description|htmlentities}</textarea>
</div>
</div>
<div id="extend"></div>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-sm-12">
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead"><em>相关信息</em></div>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade active in">
<div class="form-group">
<label for="c-views" class="control-label col-xs-12 col-sm-3">{:__('Views')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-views" data-rule="required" class="form-control" name="row[views]" placeholder="{:__('Views')}" type="number" value="{$row.views}">
<span class="input-group-addon"><i class="fa fa-eye text-success"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-comments" class="control-label col-xs-12 col-sm-3">{:__('Comments')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-comments" data-rule="required" class="form-control" name="row[comments]" placeholder="{:__('Comments')}" type="number" value="{$row.comments}">
<span class="input-group-addon"><i class="fa fa-comment text-info"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-likes" class="control-label col-xs-12 col-sm-3">{:__('Likes')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-likes" data-rule="required" class="form-control" name="row[likes]" placeholder="{:__('Likes')}" type="number" value="{$row.likes}">
<span class="input-group-addon"><i class="fa fa-thumbs-up text-danger"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-dislikes" class="control-label col-xs-12 col-sm-3">{:__('Dislikes')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group margin-bottom-sm">
<input id="c-dislikes" data-rule="required" class="form-control" name="row[dislikes]" placeholder="{:__('Dislikes')}" type="number" value="{$row.dislikes}">
<span class="input-group-addon"><i class="fa fa-thumbs-down text-gray"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-3">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" data-rule="required" class="form-control" name="row[weigh]" placeholder="{:__('Weigh')}" type="number" value="{$row.weigh}">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead"><em>状态</em></div>
</div>
<div class="panel-body">
<div class="tab-content">
<div class="tab-pane fade active in">
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-3">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key}" {in name="key" value="$row.flag" }selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-3">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-status" class="form-control selectpicker" name="row[status]">
{foreach name="statusList" item="vo"}
<option value="{$key}" {in name="key" value="$row.status" }selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-3">{:__('Publish')}:</label>
<div class="col-xs-12 col-sm-8">
<div class='input-group date datetimepicker'>
<input type='text' name="row[publishtime]" data-date-format="YYYY-MM-DD HH:mm:ss" value="{$row.publishtime_text}" class="form-control datetimepicker"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
\ No newline at end of file
... ...
<style>
.font-bold {
font-weight: bold;
}
.font-underline {
font-weight: bold;
}
.radio-inline, .checkbox-inline {
padding-left: 0;
}
</style>
{foreach $fields as $item}
<div class="form-group">
<div class="control-label col-xs-12 col-sm-2">{$item.title}</div>
<div class="col-xs-12 col-sm-8">
{switch $item.type}
{case string}
<input type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}" {$item.extend}/>
{/case}
{case value="text" break="0"}{/case}
{case editor}
<textarea name="row[{$item.name}]" id="c-{$item.name}" class="form-control {eq name='$item.type' value='editor'}editor{/eq}" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}" {$item.extend}>{$item.value|htmlentities}</textarea>
{/case}
{case array}
{if $item.name=='downloadurl'}
{php}$item['value']=isset($values[$item['name']])?$item['value']:$item['download_list'];{/php}
<dl class="fieldlist downloadlist" data-name="row[{$item.name}]" data-template="downloadurltpl">
<dd>
<ins style="width:70px;">来源</ins>
<ins style="width:250px;">地址</ins>
<ins>密码(可为空)</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
</dl>
{else /}
{php}$arrList=isset($values[$item['name']])?(array)json_decode($item['value'],true):$item['content_list'];{/php}
<dl class="fieldlist" data-name="row[{$item.name}]">
<dd>
<ins>{:__('Array key')}</ins>
<ins>{:__('Array value')}</ins>
</dd>
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name}]" class="form-control hide" cols="30" rows="5">{$arrList|json_encode|htmlentities}</textarea>
</dl>
{/if}
{/case}
{case date}
<input type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend}/>
{/case}
{case time}
<input type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend}/>
{/case}
{case datetime}
<input type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend}/>
{/case}
{case number}
<input type="number" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}" {$item.extend}/>
{/case}
{case checkbox}
{foreach name="item.content_list" item="vo"}
<div class="checkbox checkbox-inline">
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-rule="{$item.rule}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
</div>
{/foreach}
{/case}
{case radio}
{foreach name="item.content_list" item="vo"}
<div class="radio radio-inline">
<label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-rule="{$item.rule}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
</div>
{/foreach}
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-rule="{$item.rule}" data-tip="{$item.tip}" {$item.extend} {$item.type=='selects'?'multiple':''}>
{foreach name="item.content_list" item="vo"}
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="input-group">
<input id="c-{$item.name}" class="form-control" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-rule="{$item.rule}" data-tip="{$item.tip}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-preview-id="p-{$item.name}" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="{$item.type=='file'?'false':'true'}" {if $item.maximum}data-maxcount="{$item.maximum}" {/if}><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-preview-id="p-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='file'?'false':'true'}" {if $item.maximum}data-maxcount="{$item.maximum}" {/if}><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-{$item.name}"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="input-group">
<input id="c-{$item.name}" class="form-control" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value}" data-rule="{$item.rule}" data-tip="{$item.tip}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}" {if $item.maximum}data-maxcount="{$item.maximum}" {/if}><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}" {if $item.maximum}data-maxcount="{$item.maximum}" {/if}><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-{$item.name}"></span>
</div>
{/case}
{case switch}
<input id="c-{$item.name}" name="row[{$item.name}]" type="hidden" value="{:$item.value?1:0}">
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name}" data-yes="1" data-no="0">
<i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
</a>
{/case}
{case bool}
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
{/case}
{case custom}
{$item.content}
{/case}
{/switch}
</div>
</div>
{/foreach}
<script type="text/html" id="downloadurltpl">
<dd class="form-inline">
<input type="text" name="<%=name%>[<%=index%>][name]" class="form-control" value="<%=row.name%>" style="width:70px;"/>
<input type="text" name="<%=name%>[<%=index%>][url]" id="c-downloadurl-<%=index%>" class="form-control" value="<%=row.url%>" style="width:170px;"/>
<div class="btn-group">
<button type="button" id="plupload-downloadurl-<%=index%>" class="btn btn-danger plupload" data-input-id="c-downloadurl-<%=index%>" data-mimetype="*" data-multiple="false"><i class="fa fa-upload"></i></button>
<button type="button" id="fachoose-downloadurl-<%=index%>" class="btn btn-primary fachoose" data-input-id="c-downloadurl-<%=index%>" data-mimetype="*" data-multiple="false"><i class="fa fa-list"></i></button>
</div>
<input type="text" name="<%=name%>[<%=index%>][password]" class="form-control" value="<%=row.password%>" style="width:70px;"/>
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
</dd>
</script>
\ No newline at end of file
... ...
<style>
.form-commonsearch .form-group {
margin-left: 0;
margin-right: 0;
padding: 0;
}
form.form-commonsearch .control-label {
padding-right: 0;
}
.tdtitle {
margin-bottom: 5px;
font-weight: 600;
}
#channeltree {
margin-left: -6px;
}
#channelbar .panel-heading {
height: 55px;
line-height: 25px;
font-size:14px;
}
@media (max-width: 1230px) {
.fixed-table-toolbar .search .form-control {
display: none;
}
}
@media (min-width: 1200px) {
#channelbar {
width: 20%;
}
#archivespanel {
width: 80%;
}
}
</style>
<div class="row">
<div class="col-md-3 hidden-xs hidden-sm" id="channelbar" style="padding-right:0;">
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<div class="panel-lead">
<em>{:__('Channel list')}</em>
</div>
</div>
<div class="panel-body">
<span class="text-muted"><input type="checkbox" name="" id="checkall"/> <label for="checkall"><small>{:__('Check all')}</small></label></span>
<span class="text-muted"><input type="checkbox" name="" id="expandall" checked=""/> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
<div id="channeltree">
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-9" id="archivespanel">
<div class="panel panel-default panel-intro" style="background: #f1f4f6;padding-top: 0;padding-bottom: 0;box-shadow: none;">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="status">
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="statusList" item="vo"}
<li><a href="#t-{$vo}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
{/foreach}
</ul>
</div>
<div id="myTabContent" class="tab-content" style="background:#fff;padding:15px;">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,add,del')}
<a class="btn btn-info btn-move dropdown-toggle btn-disabled disabled"><i class="fa fa-arrow-right"></i> {:__('Move')}</a>
<div class="dropdown btn-group {:$auth->check('cms/archives/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=rejected"><i class="fa fa-exclamation-circle"></i> {:__('Set to rejected')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=pulloff"><i class="fa fa-arrow-circle-down"></i> {:__('Set to pulloff')}</a></li>
</ul>
</div>
<a class="btn btn-success btn-recyclebin btn-dialog" href="cms/archives/recyclebin" title="{:__('Recycle bin')}"><i class="fa fa-recycle"></i> {:__('Recycle bin')}</a>
<div class="dropdown btn-group {:$auth->check('cms/archives/content')?'':'hide'}">
<a href="javascript:;" class="btn btn-info dropdown-toggle" title="{:__('Addon list')}" data-toggle="dropdown"><i class="fa fa-file"></i> {:__('Addon list')}</a>
<ul class="dropdown-menu text-left" role="menu">
{volist name="modelList" id="item"}
<li><a class="btn btn-link btn-addtabs" href="{:url('cms.archives/content')}/model_id/{$item.id}" title="{$item.name}"><i class="fa fa-file"></i> {$item.name}</a></li>
{/volist}
</ul>
</div>
<a href="javascript:;" class="btn btn-default btn-channel hidden-xs hidden-sm hidden-lg"><i class="fa fa-bars"></i></a>
</div>
<table id="table" class="table table-striped table-bordered table-hover"
data-operate-edit="{:$auth->check('cms/archives/edit')}"
data-operate-del="{:$auth->check('cms/archives/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script id="channeltpl" type="text/html">
<div class="box box-solid bg-red-gradient">
<div class="box-header ui-sortable-handle" style="cursor: move;">
{:__('Warning')}
</div>
<!-- /.box-header -->
<div class="box-body">
{:__('Move tips')}
</div>
<!-- /.box-body -->
<div class="box-footer text-black">
<div class="row">
<div class="col-sm-12">
<select name="channel" class="form-control" id="">
<option value="0">{:__('Please select channel')}</option>
{$channelOptions}
</select>
</div>
</div>
<!-- /.row -->
</div>
</div>
</script>
... ...
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh')}
<a class="btn btn-info btn-multi btn-disabled disabled" href="javascript:;" data-url="{:url('cms.archives/restore')}" data-action="restore"><i class="fa fa-rotate-left"></i> {:__('Restore')}</a>
<a class="btn btn-danger btn-multi btn-disabled disabled" href="javascript:;" data-url="{:url('cms.archives/destroy')}" data-action="destroy"><i class="fa fa-times"></i> {:__('Destroy')}</a>
<a class="btn btn-success btn-restoreall" href="{:url('cms.archives/restore')}" title="{:__('Restore all')}"><i class="fa fa-rotate-left"></i> {:__('Restore all')}</a>
<a class="btn btn-danger btn-destroyall" href="{:url('cms.archives/destroy')}" title="{:__('Destroy all')}"><i class="fa fa-times"></i> {:__('Destroy all')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
... ...
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="c-type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-type" data-rule="required" class="form-control selectpage" data-source="cms/block/selectpage_type" placeholder="类型为自定义,可任意输入" data-primary-key="type" data-field="type" name="row[type]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" placeholder="用于模板中标签调用" type="text">
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text">
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" data-rule="" class="form-control" size="50" name="row[image]" type="text" value="">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-url" data-rule="" class="form-control" name="row[url]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" data-rule="" class="form-control editor" rows="15" name="row[content]" cols="50"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="normal"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="c-type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-type" data-rule="required" class="form-control selectpage" data-source="cms/block/selectpage_type" placeholder="类型为自定义,可任意输入" data-primary-key="type" data-field="type" name="row[type]" type="text" value="{$row.type}">
</div>
</div>
<div class="form-group">
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}" placeholder="用于模板中标签调用">
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" data-rule="required" class="form-control" name="row[title]" type="text" value="{$row.title|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" data-rule="" class="form-control" size="50" name="row[image]" type="text" value="{$row.image|htmlentities}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right" for="c-image"></span>
</div>
<ul class="row list-inline plupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-url" data-rule="" class="form-control" name="row[url]" type="text" value="{$row.url|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-content" data-rule="" class="form-control editor" rows="15" name="row[content]" cols="50">{$row.content|htmlentities}</textarea>
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-4">
<input id="c-weigh" data-rule="required" class="form-control" name="row[weigh]" type="number" value="{$row.weigh}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
{/foreach}
</div>
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
... ...