mirror of https://gitee.com/karson/fastadmin.git
parent
7045f0d02b
commit
bf720c176e
|
|
@ -80,6 +80,7 @@ CREATE TABLE `fa_area` (
|
|||
DROP TABLE IF EXISTS `fa_attachment`;
|
||||
CREATE TABLE `fa_attachment` (
|
||||
`id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`category` varchar(50) DEFAULT '' COMMENT '类别',
|
||||
`admin_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '管理员ID',
|
||||
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID',
|
||||
`url` varchar(255) DEFAULT '' COMMENT '物理路径',
|
||||
|
|
@ -103,7 +104,7 @@ CREATE TABLE `fa_attachment` (
|
|||
-- Records of fa_attachment
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_attachment` VALUES (1, 1, 0, '/assets/img/qrcode.png', '150', '150', 'png', 0, 'qrcode.png', 21859, 'image/png', '', 1491635035, 1491635035, 1491635035, 'local', '17163603d0263e4838b9387ff2cd4877e8b018f6');
|
||||
INSERT INTO `fa_attachment` VALUES (1, '', 1, 0, '/assets/img/qrcode.png', '150', '150', 'png', 0, 'qrcode.png', 21859, 'image/png', '', 1491635035, 1491635035, 1491635035, 'local', '17163603d0263e4838b9387ff2cd4877e8b018f6');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
|
@ -350,6 +351,7 @@ INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user',
|
|||
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码或授权码)', 'string', 'password', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', '(SMTP验证方式[推荐SSL])', 'select', '2', '[\"无\",\"TLS\",\"SSL\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '10000@qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (18, 'attachmentcategory', 'dictionary', 'Attachment category', '', 'array', '{\"category1\":\"Category1\",\"category2\":\"Category2\",\"custom\":\"Custom\"}', '', '', '', '');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use app\common\controller\Backend;
|
|||
* 附件管理
|
||||
*
|
||||
* @icon fa fa-circle-o
|
||||
* @remark 主要用于管理上传到又拍云的数据或上传至本服务的上传数据
|
||||
* @remark 主要用于管理上传到服务器或第三方存储的数据
|
||||
*/
|
||||
class Attachment extends Backend
|
||||
{
|
||||
|
|
@ -18,11 +18,15 @@ class Attachment extends Backend
|
|||
*/
|
||||
protected $model = null;
|
||||
|
||||
protected $searchFields = 'id,filename,url';
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = model('Attachment');
|
||||
$this->view->assign("mimetypeList", \app\common\model\Attachment::getMimetypeList());
|
||||
$this->view->assign("categoryList", \app\common\model\Attachment::getCategoryList());
|
||||
$this->assignconfig("categoryList", \app\common\model\Attachment::getCategoryList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -36,10 +40,15 @@ class Attachment extends Backend
|
|||
$mimetypeQuery = [];
|
||||
$filter = $this->request->request('filter');
|
||||
$filterArr = (array)json_decode($filter, true);
|
||||
if (isset($filterArr['category']) && $filterArr['category'] == 'unclassed') {
|
||||
$filterArr['category'] = '';
|
||||
$this->request->get(['filter' => json_encode(array_diff_key($filterArr, ['category' => '']))]);
|
||||
}
|
||||
if (isset($filterArr['mimetype']) && preg_match("/[]\,|\*]/", $filterArr['mimetype'])) {
|
||||
$this->request->get(['filter' => json_encode(array_diff_key($filterArr, ['mimetype' => '']))]);
|
||||
$mimetypeQuery = function ($query) use ($filterArr) {
|
||||
$mimetypeArr = explode(',', $filterArr['mimetype']);
|
||||
$mimetype = $filterArr['mimetype'];
|
||||
$filterArr = array_diff_key($filterArr, ['mimetype' => '']);
|
||||
$mimetypeQuery = function ($query) use ($mimetype) {
|
||||
$mimetypeArr = explode(',', $mimetype);
|
||||
foreach ($mimetypeArr as $index => $item) {
|
||||
if (stripos($item, "/*") !== false) {
|
||||
$query->whereOr('mimetype', 'like', str_replace("/*", "/", $item) . '%');
|
||||
|
|
@ -49,6 +58,7 @@ class Attachment extends Backend
|
|||
}
|
||||
};
|
||||
}
|
||||
$this->request->get(['filter' => json_encode($filterArr)]);
|
||||
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
|
|
@ -121,4 +131,25 @@ class Attachment extends Backend
|
|||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动
|
||||
*/
|
||||
public function move($ids = "")
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
$this->error(__("Invalid parameters"));
|
||||
}
|
||||
$category = $this->request->post('category', '');
|
||||
$ids = $this->request->post('ids');
|
||||
if (!$ids) {
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
}
|
||||
$categoryList = \app\common\model\Attachment::getCategoryList();
|
||||
if ($category && !isset($categoryList[$category])) {
|
||||
$this->error(__('Category not found'));
|
||||
}
|
||||
\app\common\model\Attachment::where('id', 'in', $ids)->update(['category' => $category]);
|
||||
$this->success();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,14 @@ class Config extends Backend
|
|||
$value['value'] = explode(',', $value['value']);
|
||||
}
|
||||
$value['content'] = json_decode($value['content'], true);
|
||||
if (in_array($value['name'], ['categorytype', 'configgroup', 'attachmentcategory'])) {
|
||||
$dictValue = (array)json_decode($value['value'], true);
|
||||
foreach ($dictValue as $index => &$item) {
|
||||
$item = __($item);
|
||||
}
|
||||
unset($item);
|
||||
$value['value'] = json_encode($dictValue, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$value['tip'] = htmlspecialchars($value['tip']);
|
||||
$siteList[$v['group']]['list'][] = $value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,17 @@ return [
|
|||
'Createtime' => '创建日期',
|
||||
'Uploadtime' => '上传时间',
|
||||
'Storage' => '存储引擎',
|
||||
'Category1' => '分类一',
|
||||
'Category2' => '分类二',
|
||||
'Custom' => '自定义',
|
||||
'Unclassed' => '未归类',
|
||||
'Category' => '类别',
|
||||
'Upload to third' => '上传到第三方',
|
||||
'Upload to local' => '上传到本地',
|
||||
'Upload to third by chunk' => '上传到第三方(分片模式)',
|
||||
'Upload to local by chunk' => '上传到本地(分片模式)',
|
||||
'Please enter a new name' => '请输入新的类别名称',
|
||||
'Please select category' => '请选择一个类别',
|
||||
'Category not found' => '指定的类别未找到',
|
||||
'Upload from editor' => '从编辑器上传'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ return [
|
|||
'Fixed page' => '后台固定页',
|
||||
'Category type' => '分类类型',
|
||||
'Config group' => '配置分组',
|
||||
'Attachment category' => '附件类别',
|
||||
'Category1' => '分类一',
|
||||
'Category2' => '分类二',
|
||||
'Rule tips' => '校验规则使用请参考Nice-validator文档',
|
||||
'Extend tips' => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换',
|
||||
'Mail type' => '邮件发送方式',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
|
||||
|
||||
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Category')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<select name="row[category]" class="form-control">
|
||||
<option value="">{:__('Please select category')}</option>
|
||||
{foreach name="categoryList" id="item"}
|
||||
<option value="{$key}" {if $key==$row.category}selected{/if}>{$item}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</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">
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
<div class="panel-heading">
|
||||
{:build_heading(null,FALSE)}
|
||||
<ul class="nav nav-tabs" data-field="mimetype">
|
||||
<ul class="nav nav-tabs" data-field="category">
|
||||
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
|
||||
{foreach name="mimetypeList" item="vo"}
|
||||
{foreach name="categoryList" item="vo"}
|
||||
<li><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh,add,edit,del')}
|
||||
<a class="btn btn-info btn-move dropdown-toggle btn-disabled disabled"><i class="fa fa-arrow-right"></i> {:__('Move')}</a>
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('general/attachment/edit')}"
|
||||
|
|
@ -28,3 +29,16 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script id="typetpl" type="text/html">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<select name="category" class="form-control">
|
||||
<option value="">{:__('Please select category')}</option>
|
||||
{foreach name="categoryList" id="item"}
|
||||
<option value="{$key}">{$item}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -6,17 +6,15 @@
|
|||
</style>
|
||||
{/if}
|
||||
<div class="panel panel-default panel-intro">
|
||||
{if !$Think.get.mimetype}
|
||||
<div class="panel-heading">
|
||||
{:build_heading(null,FALSE)}
|
||||
<ul class="nav nav-tabs" data-field="mimetype">
|
||||
<ul class="nav nav-tabs" data-field="category">
|
||||
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
|
||||
{foreach name="mimetypeList" item="vo"}
|
||||
{foreach name="categoryList" item="vo"}
|
||||
<li><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="panel-body no-padding">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
|
|
|
|||
|
|
@ -352,10 +352,13 @@ class Upload
|
|||
}
|
||||
}
|
||||
$this->file = $file;
|
||||
$category = request()->post('category');
|
||||
$category = array_key_exists($category, config('site.attachmentcategory') ?? []) ? $category : '';
|
||||
$params = array(
|
||||
'admin_id' => (int)session('admin.id'),
|
||||
'user_id' => (int)cookie('uid'),
|
||||
'filename' => substr(htmlspecialchars(strip_tags($this->fileInfo['name'])), 0, 100),
|
||||
'category' => $category,
|
||||
'filesize' => $this->fileInfo['size'],
|
||||
'imagewidth' => $this->fileInfo['imagewidth'],
|
||||
'imageheight' => $this->fileInfo['imageheight'],
|
||||
|
|
|
|||
|
|
@ -24,6 +24,16 @@ class Attachment extends Model
|
|||
return is_numeric($value) ? $value : strtotime($value);
|
||||
}
|
||||
|
||||
public function getCategoryAttr($value)
|
||||
{
|
||||
return $value == '' ? 'unclassed' : $value;
|
||||
}
|
||||
|
||||
public function setCategoryAttr($value)
|
||||
{
|
||||
return $value == 'unclassed' ? '' : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取云储存的缩略图样式字符
|
||||
*/
|
||||
|
|
@ -53,6 +63,20 @@ class Attachment extends Model
|
|||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取定义的附件类别列表
|
||||
* @return array
|
||||
*/
|
||||
public static function getCategoryList()
|
||||
{
|
||||
$data = config('site.attachmentcategory')??[];
|
||||
foreach ($data as $index => &$datum) {
|
||||
$datum = __($datum);
|
||||
}
|
||||
$data['unclassed'] = __('Unclassed');
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected static function init()
|
||||
{
|
||||
// 如果已经上传该资源,则不再记录
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ return [
|
|||
'user' => 'User',
|
||||
'example' => 'Example',
|
||||
],
|
||||
'attachmentcategory' => [
|
||||
'category1' => 'Category1',
|
||||
'category2' => 'Category2',
|
||||
'custom' => 'Custom',
|
||||
],
|
||||
'mail_type' => '1',
|
||||
'mail_smtp_host' => 'smtp.qq.com',
|
||||
'mail_smtp_port' => '465',
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
[
|
||||
{field: 'state', checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'category', title: __('Category'), formatter: Table.api.formatter.label, searchList: Config.categoryList},
|
||||
{field: 'admin_id', title: __('Admin_id'), visible: false, addClass: "selectpage", extend: "data-source='auth/admin/index' data-field='nickname'"},
|
||||
{field: 'user_id', title: __('User_id'), visible: false, addClass: "selectpage", extend: "data-source='user/user/index' data-field='nickname'"},
|
||||
{field: 'preview', title: __('Preview'), formatter: Controller.api.formatter.thumb, operate: false},
|
||||
{field: 'url', title: __('Url'), formatter: Controller.api.formatter.url, visible: false},
|
||||
{field: 'filename', title: __('Filename'), formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{field: 'filename', title: __('Filename'), sortable: true, formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{
|
||||
field: 'filesize', title: __('Filesize'), operate: 'BETWEEN', sortable: true, formatter: function (value, row, index) {
|
||||
var size = parseFloat(value);
|
||||
|
|
@ -38,7 +39,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), sortable: true},
|
||||
{field: 'imagetype', title: __('Imagetype'), formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'imagetype', title: __('Imagetype'), sortable: true, formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'storage', title: __('Storage'), formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'mimetype', title: __('Mimetype'), formatter: Table.api.formatter.search},
|
||||
{
|
||||
|
|
@ -47,7 +48,8 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
formatter: Table.api.formatter.datetime,
|
||||
operate: 'RANGE',
|
||||
addclass: 'datetimerange',
|
||||
sortable: true
|
||||
sortable: true,
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
field: 'operate',
|
||||
|
|
@ -63,6 +65,28 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
$(document).on('click', '.btn-move', function () {
|
||||
var ids = Table.api.selectedids(table);
|
||||
Layer.open({
|
||||
title: __('Move'),
|
||||
content: Template("typetpl", {}),
|
||||
btn: [__('Move')],
|
||||
yes: function (index, layero) {
|
||||
var category = $("select[name='category']", layero).val();
|
||||
Fast.api.ajax({
|
||||
url: "general/attachment/move",
|
||||
type: "post",
|
||||
data: {category: category, ids: ids.join(',')},
|
||||
}, function () {
|
||||
table.bootstrapTable('refresh', {});
|
||||
Layer.close(index);
|
||||
});
|
||||
},
|
||||
success: function (layero, index) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
select: function () {
|
||||
// 初始化表格参数配置
|
||||
|
|
@ -106,14 +130,15 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
[
|
||||
{field: 'state', checkbox: multiple, visible: multiple, operate: false},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'category', title: __('Category'), formatter: Table.api.formatter.label, searchList: Config.categoryList},
|
||||
{field: 'admin_id', title: __('Admin_id'), formatter: Table.api.formatter.search, visible: false},
|
||||
{field: 'user_id', title: __('User_id'), formatter: Table.api.formatter.search, visible: false},
|
||||
{field: 'url', title: __('Preview'), formatter: Controller.api.formatter.thumb, operate: false},
|
||||
{field: 'filename', title: __('Filename'), formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), operate: false},
|
||||
{field: 'imageheight', title: __('Imageheight'), operate: false},
|
||||
{field: 'filename', title: __('Filename'), sortable: true, formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), operate: false, sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), operate: false, sortable: true},
|
||||
{
|
||||
field: 'mimetype', title: __('Mimetype'), operate: 'LIKE %...%',
|
||||
field: 'mimetype', title: __('Mimetype'), sortable: true, operate: 'LIKE %...%',
|
||||
process: function (value, arg) {
|
||||
return value.replace(/\*/g, '%');
|
||||
}
|
||||
|
|
@ -162,7 +187,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
formatter: {
|
||||
thumb: function (value, row, index) {
|
||||
if (row.mimetype.indexOf("image") > -1) {
|
||||
return '<a href="' + row.fullurl + '" target="_blank"><img src="' + row.fullurl + row.thumb_style + '" alt="" style="max-height:90px;max-width:120px"></a>';
|
||||
return '<a href="' + row.fullurl + '" target="_blank"><img src="' + row.fullurl + row.thumb_style + '" alt="" style="max-height:60px;max-width:120px"></a>';
|
||||
} else {
|
||||
return '<a href="' + row.fullurl + '" target="_blank"><img src="' + Fast.api.fixurl("ajax/icon") + "?suffix=" + row.imagetype + '" alt="" style="max-height:90px;max-width:120px"></a>';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,10 +251,16 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
Upload.events.onUploadError(this, ret, file);
|
||||
},
|
||||
uploadprogress: function (file, progress, bytesSent) {
|
||||
|
||||
if (file.upload.chunked) {
|
||||
var totalBytesSent = 0;
|
||||
file.upload.chunks.forEach(function (item) {
|
||||
totalBytesSent += item.bytesSent;
|
||||
});
|
||||
$(this.element).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + Math.floor((totalBytesSent / file.size) * 100) + "%");
|
||||
}
|
||||
},
|
||||
totaluploadprogress: function (progress, bytesSent) {
|
||||
if (this.getActiveFiles().length > 0) {
|
||||
if (this.getActiveFiles().length > 0 && !this.options.chunking) {
|
||||
$(this.element).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + Math.floor(progress) + "%");
|
||||
}
|
||||
},
|
||||
|
|
@ -269,13 +275,13 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
var that = this;
|
||||
Fast.api.ajax({
|
||||
url: this.options.url,
|
||||
data: {
|
||||
data: $.extend({}, multipart, {
|
||||
action: 'merge',
|
||||
filesize: file.size,
|
||||
filename: file.name,
|
||||
chunkid: file.upload.uuid,
|
||||
chunkcount: file.upload.totalChunkCount,
|
||||
}
|
||||
})
|
||||
}, function (data, ret) {
|
||||
done(JSON.stringify(ret));
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue