mirror of https://gitee.com/karson/fastadmin.git
新增菜单类upgrade方法
新增上传存储文件名功能 新增文件分片上传功能 优化上传组件及方法 优化系统配置中冗余的JS代码 优化下拉框显示样式 优化大数据列表时表格列表渲染速度 修复在PHP高版本下Token验证错误的BUG 修复在PHP高版本下会员登录页错误的BUG 修复Token::get默认值不生效的BUGpull/220/head
parent
e29a9e41fc
commit
ed20e5ac6f
10
README.md
10
README.md
|
|
@ -17,17 +17,17 @@ FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架。
|
|||
* 基于`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)、[在线投票系统](https://www.fastadmin.net/store/vote.html))
|
||||
* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
|
||||
* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)、[博客](https://www.fastadmin.net/store/blog.html)、[知识付费问答](https://www.fastadmin.net/store/ask.html)、[在线投票系统](https://www.fastadmin.net/store/vote.html)、[商城系统](https://www.fastadmin.net/store/shopro.html))
|
||||
* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)
|
||||
* 第三方小程序支持([预订小程序](https://www.fastadmin.net/store/ball.html)、[问答小程序](https://www.fastadmin.net/store/questions.html)、[活动报名小程序](https://www.fastadmin.net/store/huodong.html)、[商城小程序](https://www.fastadmin.net/store/xshop.html)、[博客小程序](https://www.fastadmin.net/store/blog.html))
|
||||
* 整合第三方短信接口(阿里云、腾讯云短信)
|
||||
* 无缝整合第三方云存储(七牛、阿里云OSS、又拍云)功能
|
||||
* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能
|
||||
* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
|
||||
* 第三方登录(QQ、微信、微博)整合
|
||||
* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
|
||||
|
|
@ -80,6 +80,10 @@ Nice-validator: https://validator.niceue.com
|
|||
|
||||
SelectPage: https://github.com/TerryZ/SelectPage
|
||||
|
||||
Layer: https://layer.layui.com
|
||||
|
||||
DropzoneJS: https://www.dropzonejs.com
|
||||
|
||||
|
||||
## 版权信息
|
||||
|
||||
|
|
|
|||
|
|
@ -1394,12 +1394,12 @@ EOD;
|
|||
}
|
||||
$multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"';
|
||||
$preview = ' data-preview-id="p-' . $field . '"';
|
||||
$previewcontainer = $preview ? '<ul class="row list-inline plupload-preview" id="p-' . $field . '"></ul>' : '';
|
||||
$previewcontainer = $preview ? '<ul class="row list-inline faupload-preview" id="p-' . $field . '"></ul>' : '';
|
||||
return <<<EOD
|
||||
<div class="input-group">
|
||||
{$content}
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="plupload-{$field}" class="btn btn-danger plupload" data-input-id="c-{$field}"{$uploadfilter}{$multiple}{$preview}><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$field}" class="btn btn-danger faupload" data-input-id="c-{$field}"{$uploadfilter}{$multiple}{$preview}><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$field}" class="btn btn-primary fachoose" data-input-id="c-{$field}"{$selectfilter}{$multiple}><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-{$field}"></span>
|
||||
|
|
|
|||
|
|
@ -441,8 +441,8 @@ CREATE TABLE `fa_user` (
|
|||
`gender` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '性别',
|
||||
`birthday` date DEFAULT NULL COMMENT '生日',
|
||||
`bio` varchar(100) NOT NULL DEFAULT '' COMMENT '格言',
|
||||
`money` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '余额',
|
||||
`score` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '积分',
|
||||
`money` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '余额',
|
||||
`score` int(10) NOT NULL DEFAULT '0' COMMENT '积分',
|
||||
`successions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '连续登录天数',
|
||||
`maxsuccessions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '最大连续登录天数',
|
||||
`prevtime` int(10) DEFAULT NULL COMMENT '上次登录时间',
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
namespace app\admin\controller;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\common\exception\UploadException;
|
||||
use app\common\library\Upload;
|
||||
use fast\Random;
|
||||
use think\addons\Service;
|
||||
use think\Cache;
|
||||
|
|
@ -54,99 +56,61 @@ class Ajax extends Backend
|
|||
public function upload()
|
||||
{
|
||||
Config::set('default_return_type', 'json');
|
||||
$file = $this->request->file('file');
|
||||
if (empty($file)) {
|
||||
$this->error(__('No file upload or server upload limit exceeded'));
|
||||
}
|
||||
|
||||
//判断是否已经存在附件
|
||||
$sha1 = $file->hash();
|
||||
$extparam = $this->request->post();
|
||||
|
||||
$upload = Config::get('upload');
|
||||
|
||||
preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
|
||||
$type = strtolower($matches[2]);
|
||||
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
|
||||
$size = (int)$upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
|
||||
$fileInfo = $file->getInfo();
|
||||
$suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
|
||||
$suffix = $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';
|
||||
|
||||
$mimetypeArr = explode(',', strtolower($upload['mimetype']));
|
||||
$typeArr = explode('/', $fileInfo['type']);
|
||||
|
||||
//禁止上传PHP和HTML文件
|
||||
if (in_array($fileInfo['type'], ['text/x-php', 'text/html']) || in_array($suffix, ['php', 'html', 'htm'])) {
|
||||
$this->error(__('Uploaded file format is limited'));
|
||||
}
|
||||
//验证文件后缀
|
||||
if ($upload['mimetype'] !== '*' &&
|
||||
(
|
||||
!in_array($suffix, $mimetypeArr)
|
||||
|| (stripos($typeArr[0] . '/', $upload['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
|
||||
)
|
||||
) {
|
||||
$this->error(__('Uploaded file format is limited'));
|
||||
}
|
||||
//验证是否为图片文件
|
||||
$imagewidth = $imageheight = 0;
|
||||
if (in_array($fileInfo['type'], ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']) || in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
|
||||
$imgInfo = getimagesize($fileInfo['tmp_name']);
|
||||
if (!$imgInfo || !isset($imgInfo[0]) || !isset($imgInfo[1])) {
|
||||
$this->error(__('Uploaded file is not a valid image'));
|
||||
$chunkid = $this->request->post("chunkid");
|
||||
if ($chunkid) {
|
||||
if (!Config::get('upload.chunking')) {
|
||||
$this->error(__('Chunk file disabled'));
|
||||
}
|
||||
$action = $this->request->post("action");
|
||||
$chunkindex = $this->request->post("chunkindex/d");
|
||||
$chunkcount = $this->request->post("chunkcount/d");
|
||||
$filename = $this->request->post("filename");
|
||||
$method = $this->request->method(true);
|
||||
if ($action == 'merge') {
|
||||
$attachment = null;
|
||||
//合并分片文件
|
||||
try {
|
||||
$upload = new Upload();
|
||||
$attachment = $upload->merge($chunkid, $chunkcount, $filename);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success(__('Uploaded successful'), '', ['url' => $attachment->url]);
|
||||
} elseif ($method == 'clean') {
|
||||
//删除冗余的分片文件
|
||||
try {
|
||||
$upload = new Upload();
|
||||
$upload->clean($chunkid);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success();
|
||||
} else {
|
||||
//上传分片文件
|
||||
//默认普通上传文件
|
||||
$file = $this->request->file('file');
|
||||
try {
|
||||
$upload = new Upload($file);
|
||||
$upload->chunk($chunkid, $chunkindex, $chunkcount);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
$imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
|
||||
$imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
|
||||
}
|
||||
$replaceArr = [
|
||||
'{year}' => date("Y"),
|
||||
'{mon}' => date("m"),
|
||||
'{day}' => date("d"),
|
||||
'{hour}' => date("H"),
|
||||
'{min}' => date("i"),
|
||||
'{sec}' => date("s"),
|
||||
'{random}' => Random::alnum(16),
|
||||
'{random32}' => Random::alnum(32),
|
||||
'{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
|
||||
'{suffix}' => $suffix,
|
||||
'{.suffix}' => $suffix ? '.' . $suffix : '',
|
||||
'{filemd5}' => md5_file($fileInfo['tmp_name']),
|
||||
];
|
||||
$savekey = $upload['savekey'];
|
||||
$savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);
|
||||
|
||||
$uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
|
||||
$fileName = substr($savekey, strripos($savekey, '/') + 1);
|
||||
//
|
||||
$splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
|
||||
if ($splInfo) {
|
||||
$params = array(
|
||||
'admin_id' => (int)$this->auth->id,
|
||||
'user_id' => 0,
|
||||
'filesize' => $fileInfo['size'],
|
||||
'imagewidth' => $imagewidth,
|
||||
'imageheight' => $imageheight,
|
||||
'imagetype' => $suffix,
|
||||
'imageframes' => 0,
|
||||
'mimetype' => $fileInfo['type'],
|
||||
'url' => $uploadDir . $splInfo->getSaveName(),
|
||||
'uploadtime' => time(),
|
||||
'storage' => 'local',
|
||||
'sha1' => $sha1,
|
||||
'extparam' => json_encode($extparam),
|
||||
);
|
||||
$attachment = model("attachment");
|
||||
$attachment->data(array_filter($params));
|
||||
$attachment->save();
|
||||
\think\Hook::listen("upload_after", $attachment);
|
||||
$this->success(__('Upload successful'), null, [
|
||||
'url' => $uploadDir . $splInfo->getSaveName()
|
||||
]);
|
||||
} else {
|
||||
// 上传失败获取错误信息
|
||||
$this->error($file->getError());
|
||||
$attachment = null;
|
||||
//默认普通上传文件
|
||||
$file = $this->request->file('file');
|
||||
try {
|
||||
$upload = new Upload($file);
|
||||
$attachment = $upload->upload();
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success(__('Uploaded successful'), '', ['url' => $attachment->url]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -105,9 +105,11 @@ class Attachment extends Backend
|
|||
{
|
||||
if ($ids) {
|
||||
\think\Hook::add('upload_delete', function ($params) {
|
||||
$attachmentFile = ROOT_PATH . '/public' . $params['url'];
|
||||
if (is_file($attachmentFile)) {
|
||||
@unlink($attachmentFile);
|
||||
if ($params['storage'] == 'local') {
|
||||
$attachmentFile = ROOT_PATH . '/public' . $params['url'];
|
||||
if (is_file($attachmentFile)) {
|
||||
@unlink($attachmentFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
$attachmentlist = $this->model->where('id', 'in', $ids)->select();
|
||||
|
|
|
|||
|
|
@ -143,8 +143,24 @@ return [
|
|||
'Please enter your username' => '请输入你的用户名',
|
||||
'Please enter your password' => '请输入你的密码',
|
||||
'Please login first' => '请登录后操作',
|
||||
'Uploaded successful' => '上传成功',
|
||||
'You can upload up to %d file%s' => '你最多还可以上传%d个文件',
|
||||
'You can choose up to %d file%s' => '你最多还可以选择%d个文件',
|
||||
'Chunk file write error' => '分片写入失败',
|
||||
'Chunk file info error' => '分片文件错误',
|
||||
'Chunk file merge error' => '分片合并错误',
|
||||
'Chunk file disabled' => '未开启分片上传功能',
|
||||
'Cancel upload' => '取消上传',
|
||||
'Upload canceled' => '上传已取消',
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Are you sure you want to cancel this upload?' => '确定取消上传?',
|
||||
'Remove file' => '移除文件',
|
||||
'You can only upload a maximum of %s files' => '你最多允许上传 %s 个文件',
|
||||
'You can\'t upload files of this type' => '不允许上传的文件类型',
|
||||
'Server responded with %s code' => '服务端响应(Code:%s)',
|
||||
'File is too big (%sMiB), Max filesize: %sMiB' => '当前上传(%sM),最大允许上传文件大小:%sM',
|
||||
'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中',
|
||||
'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转',
|
||||
//菜单
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Upload successful' => '上传成功',
|
||||
];
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ return [
|
|||
'Imagetype' => '图片类型',
|
||||
'Imageframes' => '图片帧数',
|
||||
'Preview' => '预览',
|
||||
'Filename' => '文件名',
|
||||
'Filesize' => '文件大小',
|
||||
'Mimetype' => 'Mime类型',
|
||||
'Extparam' => '透传数据',
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ trait Backend
|
|||
*/
|
||||
public function del($ids = "")
|
||||
{
|
||||
$ids = $this->request->post("ids");
|
||||
if ($ids) {
|
||||
$pk = $this->model->getPk();
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
|
|
@ -307,6 +308,7 @@ trait Backend
|
|||
public function multi($ids = "")
|
||||
{
|
||||
$ids = $ids ? $ids : $this->request->param("ids");
|
||||
$ids = $this->request->param("ids");
|
||||
if ($ids) {
|
||||
if ($this->request->has('params')) {
|
||||
parse_str($this->request->post("params"), $values);
|
||||
|
|
|
|||
|
|
@ -70,16 +70,16 @@
|
|||
{case value="images"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="35" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><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-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
|
||||
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
|
||||
</div>
|
||||
{/case}
|
||||
{case value="file" break="0"}{/case}
|
||||
{case value="files"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="35" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<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'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><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'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
{/case}
|
||||
|
|
@ -105,4 +105,4 @@
|
|||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@
|
|||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh')}
|
||||
<button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i>
|
||||
<button type="button" id="faupload-addon" class="btn btn-danger faupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i>
|
||||
{:__('Offline install')}
|
||||
</button>
|
||||
{if $Think.config.fastadmin.api_url}
|
||||
|
|
@ -293,4 +293,4 @@
|
|||
<% } %>
|
||||
</div>
|
||||
</script>
|
||||
<!--@formatter:on-->
|
||||
<!--@formatter:on-->
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@
|
|||
<div class="input-group">
|
||||
<input id="c-image" class="form-control" size="35" 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="faupload-image" class="btn btn-danger faupload" 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"></span>
|
||||
</div>
|
||||
<ul class="row list-inline plupload-preview" id="p-image"></ul>
|
||||
<ul class="row list-inline faupload-preview" id="p-image"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -54,12 +54,12 @@
|
|||
<div class="input-group">
|
||||
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="{$row.image}">
|
||||
<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="faupload-image" class="btn btn-danger faupload" 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"></span>
|
||||
</div>
|
||||
<ul class="row list-inline plupload-preview" id="p-image"></ul>
|
||||
<ul class="row list-inline faupload-preview" id="p-image"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-third" class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button id="plupload-third" class="btn btn-danger plupload" data-multiple="true" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
|
||||
<button type="button" id="faupload-third" class="btn btn-danger faupload" data-multiple="true" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-local" class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button id="plupload-local" class="btn btn-primary plupload" data-input-id="c-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
|
||||
<button type="button" id="faupload-local" class="btn btn-primary faupload" data-input-id="c-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@
|
|||
<input type="number" name="row[imageframes]" value="{$row.imageframes}" id="c-imageframes" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-filename" class="control-label col-xs-12 col-sm-2">{:__('Filename')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[filename]" value="{$row.filename|htmlentities}" id="c-filename" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-filesize" class="control-label col-xs-12 col-sm-2">{:__('Filesize')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh')}
|
||||
<span><button type="button" id="plupload-image" class="btn btn-success plupload" data-mimetype="{$Think.get.mimetype|default=''}" data-multiple="true"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-image" class="btn btn-success faupload" data-mimetype="{$Think.get.mimetype|default=''}" data-multiple="true"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
{if request()->get('multiple') == 'true'}
|
||||
<a class="btn btn-danger btn-choose-multi"><i class="fa fa-check"></i> {:__('Choose')}</a>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -111,17 +111,17 @@
|
|||
{case value="images"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><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-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
|
||||
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
|
||||
</div>
|
||||
{/case}
|
||||
{case value="file" break="0"}{/case}
|
||||
{case value="files"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<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'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><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'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@
|
|||
<div class="box-body box-profile">
|
||||
|
||||
<div class="profile-avatar-container">
|
||||
<img class="profile-user-img img-responsive img-circle plupload" src="{$admin.avatar|cdnurl|htmlentities}" alt="">
|
||||
<img class="profile-user-img img-responsive img-circle faupload" src="{$admin.avatar|cdnurl|htmlentities}" alt="">
|
||||
<div class="profile-avatar-text img-circle">{:__('Click to edit')}</div>
|
||||
<button id="plupload-avatar" class="plupload" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
|
||||
<button id="faupload-avatar" class="faupload" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
|
||||
</div>
|
||||
|
||||
<h3 class="profile-username text-center">{$admin.username|htmlentities}</h3>
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@
|
|||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="form-group">
|
||||
<div class="form-group checkbox">
|
||||
<label class="inline" for="keeplogin">
|
||||
<input type="checkbox" name="keeplogin" id="keeplogin" value="1" />
|
||||
{:__('Keep login')}
|
||||
|
|
@ -102,4 +102,4 @@
|
|||
</div>
|
||||
{include file="common/script" /}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -43,12 +43,12 @@
|
|||
<div class="input-group">
|
||||
<input id="c-avatar" data-rule="" class="form-control" size="50" name="row[avatar]" type="text" value="{$row.avatar}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="plupload-avatar" class="btn btn-danger plupload" data-input-id="c-avatar" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-avatar" class="btn btn-danger faupload" data-input-id="c-avatar" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-avatar" class="btn btn-primary fachoose" data-input-id="c-avatar" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-avatar"></span>
|
||||
</div>
|
||||
<ul class="row list-inline plupload-preview" id="p-avatar"></ul>
|
||||
<ul class="row list-inline faupload-preview" id="p-avatar"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
namespace app\api\controller;
|
||||
|
||||
use app\common\controller\Api;
|
||||
use app\common\exception\UploadException;
|
||||
use app\common\library\Upload;
|
||||
use app\common\model\Area;
|
||||
use app\common\model\Version;
|
||||
use fast\Random;
|
||||
|
|
@ -47,96 +49,61 @@ class Common extends Api
|
|||
*/
|
||||
public function upload()
|
||||
{
|
||||
$file = $this->request->file('file');
|
||||
if (empty($file)) {
|
||||
$this->error(__('No file upload or server upload limit exceeded'));
|
||||
}
|
||||
|
||||
//判断是否已经存在附件
|
||||
$sha1 = $file->hash();
|
||||
|
||||
$upload = Config::get('upload');
|
||||
|
||||
preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
|
||||
$type = strtolower($matches[2]);
|
||||
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
|
||||
$size = (int)$upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
|
||||
$fileInfo = $file->getInfo();
|
||||
$suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
|
||||
$suffix = $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';
|
||||
|
||||
$mimetypeArr = explode(',', strtolower($upload['mimetype']));
|
||||
$typeArr = explode('/', $fileInfo['type']);
|
||||
|
||||
//禁止上传PHP和HTML文件
|
||||
if (in_array($fileInfo['type'], ['text/x-php', 'text/html']) || in_array($suffix, ['php', 'html', 'htm'])) {
|
||||
$this->error(__('Uploaded file format is limited'));
|
||||
}
|
||||
//验证文件后缀
|
||||
if ($upload['mimetype'] !== '*' &&
|
||||
(
|
||||
!in_array($suffix, $mimetypeArr)
|
||||
|| (stripos($typeArr[0] . '/', $upload['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
|
||||
)
|
||||
) {
|
||||
$this->error(__('Uploaded file format is limited'));
|
||||
}
|
||||
//验证是否为图片文件
|
||||
$imagewidth = $imageheight = 0;
|
||||
if (in_array($fileInfo['type'], ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']) || in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
|
||||
$imgInfo = getimagesize($fileInfo['tmp_name']);
|
||||
if (!$imgInfo || !isset($imgInfo[0]) || !isset($imgInfo[1])) {
|
||||
$this->error(__('Uploaded file is not a valid image'));
|
||||
Config::set('default_return_type', 'json');
|
||||
$chunkid = $this->request->post("chunkid");
|
||||
if ($chunkid) {
|
||||
if (!Config::get('upload.chunking')) {
|
||||
$this->error(__('Chunk file disabled'));
|
||||
}
|
||||
$action = $this->request->post("action");
|
||||
$chunkindex = $this->request->post("chunkindex/d");
|
||||
$chunkcount = $this->request->post("chunkcount/d");
|
||||
$filename = $this->request->post("filename");
|
||||
$method = $this->request->method(true);
|
||||
if ($action == 'merge') {
|
||||
$attachment = null;
|
||||
//合并分片文件
|
||||
try {
|
||||
$upload = new Upload();
|
||||
$attachment = $upload->merge($chunkid, $chunkcount, $filename);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success(__('Uploaded successful'), '', ['url' => $attachment->url]);
|
||||
} elseif ($method == 'clean') {
|
||||
//删除冗余的分片文件
|
||||
try {
|
||||
$upload = new Upload();
|
||||
$upload->clean($chunkid);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success();
|
||||
} else {
|
||||
//上传分片文件
|
||||
//默认普通上传文件
|
||||
$file = $this->request->file('file');
|
||||
try {
|
||||
$upload = new Upload($file);
|
||||
$upload->chunk($chunkid, $chunkindex, $chunkcount);
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
$imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
|
||||
$imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
|
||||
}
|
||||
$replaceArr = [
|
||||
'{year}' => date("Y"),
|
||||
'{mon}' => date("m"),
|
||||
'{day}' => date("d"),
|
||||
'{hour}' => date("H"),
|
||||
'{min}' => date("i"),
|
||||
'{sec}' => date("s"),
|
||||
'{random}' => Random::alnum(16),
|
||||
'{random32}' => Random::alnum(32),
|
||||
'{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
|
||||
'{suffix}' => $suffix,
|
||||
'{.suffix}' => $suffix ? '.' . $suffix : '',
|
||||
'{filemd5}' => md5_file($fileInfo['tmp_name']),
|
||||
];
|
||||
$savekey = $upload['savekey'];
|
||||
$savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);
|
||||
|
||||
$uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
|
||||
$fileName = substr($savekey, strripos($savekey, '/') + 1);
|
||||
//
|
||||
$splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
|
||||
if ($splInfo) {
|
||||
$params = array(
|
||||
'admin_id' => 0,
|
||||
'user_id' => (int)$this->auth->id,
|
||||
'filesize' => $fileInfo['size'],
|
||||
'imagewidth' => $imagewidth,
|
||||
'imageheight' => $imageheight,
|
||||
'imagetype' => $suffix,
|
||||
'imageframes' => 0,
|
||||
'mimetype' => $fileInfo['type'],
|
||||
'url' => $uploadDir . $splInfo->getSaveName(),
|
||||
'uploadtime' => time(),
|
||||
'storage' => 'local',
|
||||
'sha1' => $sha1,
|
||||
);
|
||||
$attachment = model("attachment");
|
||||
$attachment->data(array_filter($params));
|
||||
$attachment->save();
|
||||
\think\Hook::listen("upload_after", $attachment);
|
||||
$this->success(__('Upload successful'), [
|
||||
'url' => $uploadDir . $splInfo->getSaveName()
|
||||
]);
|
||||
} else {
|
||||
// 上传失败获取错误信息
|
||||
$this->error($file->getError());
|
||||
$attachment = null;
|
||||
//默认普通上传文件
|
||||
$file = $this->request->file('file');
|
||||
try {
|
||||
$upload = new Upload($file);
|
||||
$attachment = $upload->upload();
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success(__('Uploaded successful'), '', ['url' => $attachment->url]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +1,102 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Keep login' => '保持会话',
|
||||
'Username' => '用户名',
|
||||
'User id' => '会员ID',
|
||||
'Nickname' => '昵称',
|
||||
'Password' => '密码',
|
||||
'Sign up' => '注 册',
|
||||
'Sign in' => '登 录',
|
||||
'Sign out' => '注 销',
|
||||
'Guest' => '游客',
|
||||
'Welcome' => '%s,你好!',
|
||||
'Add' => '添加',
|
||||
'Edit' => '编辑',
|
||||
'Delete' => '删除',
|
||||
'Move' => '移动',
|
||||
'Name' => '名称',
|
||||
'Status' => '状态',
|
||||
'Weigh' => '权重',
|
||||
'Operate' => '操作',
|
||||
'Warning' => '温馨提示',
|
||||
'Default' => '默认',
|
||||
'Article' => '文章',
|
||||
'Page' => '单页',
|
||||
'OK' => '确定',
|
||||
'Cancel' => '取消',
|
||||
'Loading' => '加载中',
|
||||
'More' => '更多',
|
||||
'Normal' => '正常',
|
||||
'Hidden' => '隐藏',
|
||||
'Submit' => '提交',
|
||||
'Reset' => '重置',
|
||||
'Execute' => '执行',
|
||||
'Close' => '关闭',
|
||||
'Search' => '搜索',
|
||||
'Refresh' => '刷新',
|
||||
'First' => '首页',
|
||||
'Previous' => '上一页',
|
||||
'Next' => '下一页',
|
||||
'Last' => '末页',
|
||||
'None' => '无',
|
||||
'Home' => '主页',
|
||||
'Online' => '在线',
|
||||
'Logout' => '注销',
|
||||
'Profile' => '个人资料',
|
||||
'Index' => '首页',
|
||||
'Hot' => '热门',
|
||||
'Recommend' => '推荐',
|
||||
'Dashboard' => '控制台',
|
||||
'Code' => '编号',
|
||||
'Message' => '内容',
|
||||
'Line' => '行号',
|
||||
'File' => '文件',
|
||||
'Menu' => '菜单',
|
||||
'Type' => '类型',
|
||||
'Title' => '标题',
|
||||
'Content' => '内容',
|
||||
'Append' => '追加',
|
||||
'Memo' => '备注',
|
||||
'Parent' => '父级',
|
||||
'Params' => '参数',
|
||||
'Permission' => '权限',
|
||||
'Advance search' => '高级搜索',
|
||||
'Check all' => '选中全部',
|
||||
'Expand all' => '展开全部',
|
||||
'Begin time' => '开始时间',
|
||||
'End time' => '结束时间',
|
||||
'Create time' => '创建时间',
|
||||
'Flag' => '标志',
|
||||
'Please login first' => '请登录后操作',
|
||||
'Redirect now' => '立即跳转',
|
||||
'Operation completed' => '操作成功!',
|
||||
'Operation failed' => '操作失败!',
|
||||
'Unknown data format' => '未知的数据格式!',
|
||||
'Network error' => '网络错误!',
|
||||
'Advanced search' => '高级搜索',
|
||||
'Invalid parameters' => '未知参数',
|
||||
'No results were found' => '记录未找到',
|
||||
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||
'You have no permission' => '你没有权限访问',
|
||||
'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中',
|
||||
'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转',
|
||||
'Keep login' => '保持会话',
|
||||
'Username' => '用户名',
|
||||
'User id' => '会员ID',
|
||||
'Nickname' => '昵称',
|
||||
'Password' => '密码',
|
||||
'Sign up' => '注 册',
|
||||
'Sign in' => '登 录',
|
||||
'Sign out' => '注 销',
|
||||
'Guest' => '游客',
|
||||
'Welcome' => '%s,你好!',
|
||||
'Add' => '添加',
|
||||
'Edit' => '编辑',
|
||||
'Delete' => '删除',
|
||||
'Move' => '移动',
|
||||
'Name' => '名称',
|
||||
'Status' => '状态',
|
||||
'Weigh' => '权重',
|
||||
'Operate' => '操作',
|
||||
'Warning' => '温馨提示',
|
||||
'Default' => '默认',
|
||||
'Article' => '文章',
|
||||
'Page' => '单页',
|
||||
'OK' => '确定',
|
||||
'Cancel' => '取消',
|
||||
'Loading' => '加载中',
|
||||
'More' => '更多',
|
||||
'Normal' => '正常',
|
||||
'Hidden' => '隐藏',
|
||||
'Submit' => '提交',
|
||||
'Reset' => '重置',
|
||||
'Execute' => '执行',
|
||||
'Close' => '关闭',
|
||||
'Search' => '搜索',
|
||||
'Refresh' => '刷新',
|
||||
'First' => '首页',
|
||||
'Previous' => '上一页',
|
||||
'Next' => '下一页',
|
||||
'Last' => '末页',
|
||||
'None' => '无',
|
||||
'Home' => '主页',
|
||||
'Online' => '在线',
|
||||
'Logout' => '注销',
|
||||
'Profile' => '个人资料',
|
||||
'Index' => '首页',
|
||||
'Hot' => '热门',
|
||||
'Recommend' => '推荐',
|
||||
'Dashboard' => '控制台',
|
||||
'Code' => '编号',
|
||||
'Message' => '内容',
|
||||
'Line' => '行号',
|
||||
'File' => '文件',
|
||||
'Menu' => '菜单',
|
||||
'Type' => '类型',
|
||||
'Title' => '标题',
|
||||
'Content' => '内容',
|
||||
'Append' => '追加',
|
||||
'Memo' => '备注',
|
||||
'Parent' => '父级',
|
||||
'Params' => '参数',
|
||||
'Permission' => '权限',
|
||||
'Advance search' => '高级搜索',
|
||||
'Check all' => '选中全部',
|
||||
'Expand all' => '展开全部',
|
||||
'Begin time' => '开始时间',
|
||||
'End time' => '结束时间',
|
||||
'Create time' => '创建时间',
|
||||
'Flag' => '标志',
|
||||
'Please login first' => '请登录后操作',
|
||||
'Uploaded successful' => '上传成功',
|
||||
'You can upload up to %d file%s' => '你最多还可以上传%d个文件',
|
||||
'You can choose up to %d file%s' => '你最多还可以选择%d个文件',
|
||||
'Chunk file write error' => '分片写入失败',
|
||||
'Chunk file info error' => '分片文件错误',
|
||||
'Chunk file merge error' => '分片合并错误',
|
||||
'Chunk file disabled' => '未开启分片上传功能',
|
||||
'Cancel upload' => '取消上传',
|
||||
'Upload canceled' => '上传已取消',
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Are you sure you want to cancel this upload?' => '确定取消上传?',
|
||||
'Remove file' => '移除文件',
|
||||
'You can only upload a maximum of %s files' => '你最多允许上传 %s 个文件',
|
||||
'You can\'t upload files of this type' => '不允许上传的文件类型',
|
||||
'Server responded with %s code' => '服务端响应(Code:%s)',
|
||||
'File is too big (%sMiB), Max filesize: %sMiB' => '当前上传(%sM),最大允许上传文件大小:%sM',
|
||||
'Redirect now' => '立即跳转',
|
||||
'Operation completed' => '操作成功!',
|
||||
'Operation failed' => '操作失败!',
|
||||
'Unknown data format' => '未知的数据格式!',
|
||||
'Network error' => '网络错误!',
|
||||
'Advanced search' => '高级搜索',
|
||||
'Invalid parameters' => '未知参数',
|
||||
'No results were found' => '记录未找到',
|
||||
'Parameter %s can not be empty' => '参数%s不能为空',
|
||||
'You have no permission' => '你没有权限访问',
|
||||
'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中',
|
||||
'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Upload successful' => '上传成功',
|
||||
];
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ class Backend extends Controller
|
|||
*/
|
||||
protected function loadlang($name)
|
||||
{
|
||||
$name = Loader::parseName($name);
|
||||
$name = Loader::parseName($name);
|
||||
Lang::load(APP_PATH . $this->request->module() . '/lang/' . $this->request->langset() . '/' . str_replace('.', '/', $name) . '.php');
|
||||
}
|
||||
|
||||
|
|
@ -456,8 +456,11 @@ class Backend extends Controller
|
|||
$where = function ($query) use ($word, $andor, $field, $searchfield, $custom) {
|
||||
$logic = $andor == 'AND' ? '&' : '|';
|
||||
$searchfield = is_array($searchfield) ? implode($logic, $searchfield) : $searchfield;
|
||||
foreach ($word as $k => $v) {
|
||||
$query->where(str_replace(',', $logic, $searchfield), "like", "%{$v}%");
|
||||
$word = array_filter($word);
|
||||
if ($word) {
|
||||
foreach ($word as $k => $v) {
|
||||
$query->where(str_replace(',', $logic, $searchfield), "like", "%{$v}%");
|
||||
}
|
||||
}
|
||||
if ($custom && is_array($custom)) {
|
||||
foreach ($custom as $k => $v) {
|
||||
|
|
@ -517,7 +520,7 @@ class Backend extends Controller
|
|||
$token = $this->request->post('__token__');
|
||||
|
||||
//验证Token
|
||||
if (!Validate::is($token, "token", ['__token__' => $token])) {
|
||||
if (!Validate::make()->check(['__token__' => $token], ['__token__' => 'require|token'])) {
|
||||
$this->error(__('Token verification error'), '', ['__token__' => $this->request->token()]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class Frontend extends Controller
|
|||
$token = $this->request->post('__token__');
|
||||
|
||||
//验证Token
|
||||
if (!Validate::is($token, "token", ['__token__' => $token])) {
|
||||
if (!Validate::make()->check(['__token__' => $token], ['__token__' => 'require|token'])) {
|
||||
$this->error(__('Token verification error'), '', ['__token__' => $this->request->token()]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace app\common\exception;
|
||||
|
||||
use think\Exception;
|
||||
use Throwable;
|
||||
|
||||
class UploadException extends Exception
|
||||
{
|
||||
public function __construct($message = "", $code = 0, $data = [])
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->code = $code;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -89,6 +89,21 @@ class Menu
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 升级菜单
|
||||
* @param string $name 插件名称
|
||||
* @param array $menu 新菜单
|
||||
* @return bool
|
||||
*/
|
||||
public static function upgrade($name, $menu)
|
||||
{
|
||||
$old = AuthRule::where('name', 'like', "{$name}%")->select();
|
||||
$old = collection($old)->toArray();
|
||||
$old = array_column($old, null, 'name');
|
||||
self::menuUpdate($menu, $old);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出指定名称的菜单规则
|
||||
* @param string $name
|
||||
|
|
@ -109,6 +124,44 @@ class Menu
|
|||
return $menuList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单升级
|
||||
* @param array $newMenu
|
||||
* @param array $oldMenu
|
||||
* @param int $parent
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function menuUpdate($newMenu, $oldMenu, $parent = 0)
|
||||
{
|
||||
if (!is_numeric($parent)) {
|
||||
$parentRule = AuthRule::getByName($parent);
|
||||
$pid = $parentRule ? $parentRule['id'] : 0;
|
||||
} else {
|
||||
$pid = $parent;
|
||||
}
|
||||
$allow = array_flip(['file', 'name', 'title', 'icon', 'condition', 'remark', 'ismenu', 'weigh']);
|
||||
foreach ($newMenu as $k => $v) {
|
||||
$hasChild = isset($v['sublist']) && $v['sublist'] ? true : false;
|
||||
$data = array_intersect_key($v, $allow);
|
||||
$data['ismenu'] = isset($data['ismenu']) ? $data['ismenu'] : ($hasChild ? 1 : 0);
|
||||
$data['icon'] = isset($data['icon']) ? $data['icon'] : ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
|
||||
$data['pid'] = $pid;
|
||||
$data['status'] = 'normal';
|
||||
try {
|
||||
if (!isset($oldMenu[$data['name']])) {
|
||||
$menu = AuthRule::create($data);
|
||||
} else {
|
||||
$menu = $oldMenu[$data['name']];
|
||||
}
|
||||
if ($hasChild) {
|
||||
self::menuUpdate($v['sublist'], $oldMenu, $menu['id']);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称获取规则IDS
|
||||
* @param string $name
|
||||
|
|
|
|||
|
|
@ -0,0 +1,323 @@
|
|||
<?php
|
||||
|
||||
namespace app\common\library;
|
||||
|
||||
use app\common\exception\UploadException;
|
||||
use app\common\model\Attachment;
|
||||
use fast\Random;
|
||||
use FilesystemIterator;
|
||||
use think\Config;
|
||||
use think\File;
|
||||
use think\Hook;
|
||||
|
||||
/**
|
||||
* 文件上传类
|
||||
*/
|
||||
class Upload
|
||||
{
|
||||
|
||||
/**
|
||||
* 验证码有效时长
|
||||
* @var int
|
||||
*/
|
||||
protected static $expire = 120;
|
||||
|
||||
/**
|
||||
* 最大允许检测的次数
|
||||
* @var int
|
||||
*/
|
||||
protected static $maxCheckNums = 10;
|
||||
|
||||
protected $chunkDir = null;
|
||||
|
||||
protected $config = [];
|
||||
|
||||
protected $error = '';
|
||||
|
||||
/**
|
||||
* @var \think\File
|
||||
*/
|
||||
protected $file = null;
|
||||
protected $fileInfo = null;
|
||||
|
||||
public function __construct($file = null)
|
||||
{
|
||||
$this->config = Config::get('upload');
|
||||
$this->chunkDir = RUNTIME_PATH . 'chunks';
|
||||
if ($file) {
|
||||
$this->setFile($file);
|
||||
}
|
||||
}
|
||||
|
||||
public function setChunkDir($dir)
|
||||
{
|
||||
$this->chunkDir = $dir;
|
||||
}
|
||||
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function setFile($file)
|
||||
{
|
||||
if (empty($file)) {
|
||||
throw new UploadException(__('No file upload or server upload limit exceeded'));
|
||||
}
|
||||
|
||||
$fileInfo = $file->getInfo();
|
||||
$suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
|
||||
$suffix = $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';
|
||||
$fileInfo['suffix'] = $suffix;
|
||||
$fileInfo['imagewidth'] = 0;
|
||||
$fileInfo['imageheight'] = 0;
|
||||
|
||||
$this->file = $file;
|
||||
$this->fileInfo = $fileInfo;
|
||||
}
|
||||
|
||||
protected function checkExecutable()
|
||||
{
|
||||
//禁止上传PHP和HTML文件
|
||||
if (in_array($this->fileInfo['type'], ['text/x-php', 'text/html']) || in_array($this->fileInfo['suffix'], ['php', 'html', 'htm'])) {
|
||||
throw new UploadException(__('Uploaded file format is limited'));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkMimetype()
|
||||
{
|
||||
$mimetypeArr = explode(',', strtolower($this->config['mimetype']));
|
||||
$typeArr = explode('/', $this->fileInfo['type']);
|
||||
//验证文件后缀
|
||||
if ($this->config['mimetype'] !== '*' &&
|
||||
(!in_array($this->fileInfo['suffix'], $mimetypeArr) || (stripos($typeArr[0] . '/', $this->config['mimetype']) !== false && (!in_array($this->fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr))))
|
||||
) {
|
||||
throw new UploadException(__('Uploaded file format is limited'));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkImage($force = false)
|
||||
{
|
||||
//验证是否为图片文件
|
||||
if (in_array($this->fileInfo['type'], ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']) || in_array($this->fileInfo['suffix'], ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
|
||||
$imgInfo = getimagesize($this->fileInfo['tmp_name']);
|
||||
if (!$imgInfo || !isset($imgInfo[0]) || !isset($imgInfo[1])) {
|
||||
throw new UploadException(__('Uploaded file is not a valid image'));
|
||||
}
|
||||
$this->fileInfo['imagewidth'] = isset($imgInfo[0]) ? $imgInfo[0] : 0;
|
||||
$this->fileInfo['imageheight'] = isset($imgInfo[1]) ? $imgInfo[1] : 0;
|
||||
return true;
|
||||
} else {
|
||||
return !$force;
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkSize()
|
||||
{
|
||||
preg_match('/([0-9\.]+)(\w+)/', $this->config['maxsize'], $matches);
|
||||
$size = $matches ? $matches[1] : $this->config['maxsize'];
|
||||
$type = $matches ? strtolower($matches[2]) : 'b';
|
||||
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
|
||||
$size = (int)($size * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0));
|
||||
if ($this->fileInfo['size'] > $size) {
|
||||
throw new UploadException(__('File is too big (%sMiB). Max filesize: %sMiB.',
|
||||
round($this->fileInfo['size'] / pow(1024, 2), 2),
|
||||
round($size / pow(1024, 2), 2)));
|
||||
}
|
||||
}
|
||||
|
||||
public function getSuffix()
|
||||
{
|
||||
return $this->fileInfo['suffix'] ?: 'file';
|
||||
}
|
||||
|
||||
public function getSavekey($savekey = null, $filename = null, $md5 = null)
|
||||
{
|
||||
if ($filename) {
|
||||
$suffix = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
$suffix = $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';
|
||||
} else {
|
||||
$suffix = $this->fileInfo['suffix'];
|
||||
}
|
||||
$filename = $filename ? $filename : ($suffix ? substr($this->fileInfo['name'], 0, strripos($this->fileInfo['name'], '.')) : $this->fileInfo['name']);
|
||||
$md5 = $md5 ? $md5 : md5_file($this->fileInfo['tmp_name']);
|
||||
$replaceArr = [
|
||||
'{year}' => date("Y"),
|
||||
'{mon}' => date("m"),
|
||||
'{day}' => date("d"),
|
||||
'{hour}' => date("H"),
|
||||
'{min}' => date("i"),
|
||||
'{sec}' => date("s"),
|
||||
'{random}' => Random::alnum(16),
|
||||
'{random32}' => Random::alnum(32),
|
||||
'{filename}' => $filename,
|
||||
'{suffix}' => $suffix,
|
||||
'{.suffix}' => $suffix ? '.' . $suffix : '',
|
||||
'{filemd5}' => $md5,
|
||||
];
|
||||
$savekey = $savekey ? $savekey : $this->config['savekey'];
|
||||
$savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);
|
||||
|
||||
return $savekey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理分片文件
|
||||
* @param $chunkid
|
||||
*/
|
||||
public function clean($chunkid)
|
||||
{
|
||||
$iterator = new \GlobIterator($this->chunkDir . DS . $chunkid . '-*', FilesystemIterator::KEY_AS_FILENAME);
|
||||
$array = iterator_to_array($iterator);
|
||||
var_dump($array);
|
||||
}
|
||||
|
||||
public function merge($chunkid, $chunkcount, $filename)
|
||||
{
|
||||
$filePath = $this->chunkDir . DS . $chunkid;
|
||||
|
||||
$completed = true;
|
||||
//检查所有分片是否都存在
|
||||
for ($i = 0; $i < $chunkcount; $i++) {
|
||||
if (!file_exists("{$filePath}-{$i}.part")) {
|
||||
$completed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$completed) {
|
||||
throw new UploadException(__('Chunk file info error'));
|
||||
}
|
||||
|
||||
//如果所有文件分片都上传完毕,开始合并
|
||||
$uploadPath = $filePath;
|
||||
|
||||
if (!$destFile = @fopen($uploadPath, "wb")) {
|
||||
throw new UploadException(__('Chunk file merge error'));
|
||||
}
|
||||
if (flock($destFile, LOCK_EX)) { // 进行排他型锁定
|
||||
for ($i = 0; $i < $chunkcount; $i++) {
|
||||
$partFile = "{$filePath}-{$i}.part";
|
||||
if (!$handle = @fopen($partFile, "rb")) {
|
||||
break;
|
||||
}
|
||||
while ($buff = fread($handle, filesize($partFile))) {
|
||||
fwrite($destFile, $buff);
|
||||
}
|
||||
@fclose($handle);
|
||||
@unlink($partFile); //删除分片
|
||||
}
|
||||
|
||||
flock($destFile, LOCK_UN);
|
||||
}
|
||||
@fclose($destFile);
|
||||
|
||||
$file = new File($uploadPath);
|
||||
$info = [
|
||||
'name' => $filename,
|
||||
'type' => $file->getMime(),
|
||||
'tmp_name' => $uploadPath,
|
||||
'error' => 0,
|
||||
'size' => $file->getSize()
|
||||
];
|
||||
$file->setUploadInfo($info);
|
||||
$file->isTest(true);
|
||||
|
||||
//重新设置文件
|
||||
$this->setFile($file);
|
||||
|
||||
//允许大文件
|
||||
$this->config['maxsize'] = "1024G";
|
||||
|
||||
return $this->upload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 分片上传
|
||||
* @throws UploadException
|
||||
*/
|
||||
public function chunk($chunkid, $chunkindex, $chunkcount, $chunkfilesize = null, $chunkfilename = null, $direct = false)
|
||||
{
|
||||
|
||||
if ($this->fileInfo['type'] != 'application/octet-stream') {
|
||||
throw new UploadException(__('Uploaded file format is limited'));
|
||||
}
|
||||
|
||||
$destDir = RUNTIME_PATH . 'chunks';
|
||||
$fileName = $chunkid . "-" . $chunkindex . '.part';
|
||||
$destFile = $destDir . DS . $fileName;
|
||||
if (!move_uploaded_file($this->file->getPathname(), $destFile)) {
|
||||
throw new UploadException(__('Chunk file write error'));
|
||||
}
|
||||
$file = new File($destFile);
|
||||
$this->setFile($file);
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通上传
|
||||
* @return \app\common\model\attachment|\think\Model
|
||||
* @throws UploadException
|
||||
*/
|
||||
public function upload($savekey = null)
|
||||
{
|
||||
if (empty($this->file)) {
|
||||
throw new UploadException(__('No file upload or server upload limit exceeded'));
|
||||
}
|
||||
|
||||
$this->checkSize();
|
||||
$this->checkExecutable();
|
||||
$this->checkMimetype();
|
||||
$this->checkImage();
|
||||
|
||||
$savekey = $savekey ? $savekey : $this->getSavekey();
|
||||
$savekey = '/' . ltrim($savekey, '/');
|
||||
$uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
|
||||
$fileName = substr($savekey, strripos($savekey, '/') + 1);
|
||||
|
||||
$destDir = ROOT_PATH . 'public' . $uploadDir;
|
||||
|
||||
$sha1 = $this->file->hash();
|
||||
|
||||
$file = $this->file->move($destDir, $fileName);
|
||||
if (!$file) {
|
||||
// 上传失败获取错误信息
|
||||
throw new UploadException($this->file->getError());
|
||||
}
|
||||
$this->file = $file;
|
||||
$params = array(
|
||||
'admin_id' => (int)session('admin.id'),
|
||||
'user_id' => (int)cookie('uid'),
|
||||
'filename' => htmlspecialchars(strip_tags($this->fileInfo['name'])),
|
||||
'filesize' => $this->fileInfo['size'],
|
||||
'imagewidth' => $this->fileInfo['imagewidth'],
|
||||
'imageheight' => $this->fileInfo['imageheight'],
|
||||
'imagetype' => $this->fileInfo['suffix'],
|
||||
'imageframes' => 0,
|
||||
'mimetype' => $this->fileInfo['type'],
|
||||
'url' => $uploadDir . $file->getSaveName(),
|
||||
'uploadtime' => time(),
|
||||
'storage' => 'local',
|
||||
'sha1' => $sha1,
|
||||
'extparam' => '',
|
||||
);
|
||||
$attachment = new Attachment();
|
||||
$attachment->data(array_filter($params));
|
||||
$attachment->save();
|
||||
|
||||
\think\Hook::listen("upload_after", $attachment);
|
||||
return $attachment;
|
||||
}
|
||||
|
||||
public function setError($msg)
|
||||
{
|
||||
$this->error = $msg;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ class Attachment extends Model
|
|||
{
|
||||
// 如果已经上传该资源,则不再记录
|
||||
self::beforeInsert(function ($model) {
|
||||
if (self::where('url', '=', $model['url'])->find()) {
|
||||
if (self::where('url', '=', $model['url'])->where('storage', $model['storage'])->find()) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,24 +29,27 @@ class Config extends Model
|
|||
public static function getTypeList()
|
||||
{
|
||||
$typeList = [
|
||||
'string' => __('String'),
|
||||
'text' => __('Text'),
|
||||
'editor' => __('Editor'),
|
||||
'number' => __('Number'),
|
||||
'date' => __('Date'),
|
||||
'time' => __('Time'),
|
||||
'datetime' => __('Datetime'),
|
||||
'select' => __('Select'),
|
||||
'selects' => __('Selects'),
|
||||
'image' => __('Image'),
|
||||
'images' => __('Images'),
|
||||
'file' => __('File'),
|
||||
'files' => __('Files'),
|
||||
'switch' => __('Switch'),
|
||||
'checkbox' => __('Checkbox'),
|
||||
'radio' => __('Radio'),
|
||||
'array' => __('Array'),
|
||||
'custom' => __('Custom'),
|
||||
'string' => __('String'),
|
||||
'text' => __('Text'),
|
||||
'editor' => __('Editor'),
|
||||
'number' => __('Number'),
|
||||
'date' => __('Date'),
|
||||
'time' => __('Time'),
|
||||
'datetime' => __('Datetime'),
|
||||
'select' => __('Select'),
|
||||
'selects' => __('Selects'),
|
||||
'image' => __('Image'),
|
||||
'images' => __('Images'),
|
||||
'file' => __('File'),
|
||||
'files' => __('Files'),
|
||||
'switch' => __('Switch'),
|
||||
'checkbox' => __('Checkbox'),
|
||||
'radio' => __('Radio'),
|
||||
'city' => __('City'),
|
||||
'selectpage' => __('Selectpage'),
|
||||
'selectpages' => __('Selectpages'),
|
||||
'array' => __('Array'),
|
||||
'custom' => __('Custom'),
|
||||
];
|
||||
return $typeList;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ return [
|
|||
//自动检测更新
|
||||
'checkupdate' => false,
|
||||
//版本号
|
||||
'version' => '1.1.0.20200612_beta',
|
||||
'version' => '1.2.0',
|
||||
//API接口地址
|
||||
'api_url' => 'https://api.fastadmin.net',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -26,4 +26,8 @@ return [
|
|||
* 是否支持批量上传
|
||||
*/
|
||||
'multiple' => false,
|
||||
/**
|
||||
* 是否支持分片上传
|
||||
*/
|
||||
'chunking' => false,
|
||||
];
|
||||
|
|
|
|||
|
|
@ -107,6 +107,24 @@ return [
|
|||
'User center' => '会员中心',
|
||||
'Change password' => '修改密码',
|
||||
'Please login first' => '请登录后再操作',
|
||||
'Uploaded successful' => '上传成功',
|
||||
'You can upload up to %d file%s' => '你最多还可以上传%d个文件',
|
||||
'You can choose up to %d file%s' => '你最多还可以选择%d个文件',
|
||||
'Chunk file write error' => '分片写入失败',
|
||||
'Chunk file info error' => '分片文件错误',
|
||||
'Chunk file merge error' => '分片合并错误',
|
||||
'Chunk file disabled' => '未开启分片上传功能',
|
||||
'Cancel upload' => '取消上传',
|
||||
'Upload canceled' => '上传已取消',
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Are you sure you want to cancel this upload?' => '确定取消上传?',
|
||||
'Remove file' => '移除文件',
|
||||
'You can only upload a maximum of %s files' => '你最多允许上传 %s 个文件',
|
||||
'You can\'t upload files of this type' => '不允许上传的文件类型',
|
||||
'Server responded with %s code' => '服务端响应(Code:%s)',
|
||||
'File is too big (%sMiB), Max filesize: %sMiB' => '当前上传(%sM),最大允许上传文件大小:%sM',
|
||||
'Send verification code' => '发送验证码',
|
||||
'Redirect now' => '立即跳转',
|
||||
'Operation completed' => '操作成功!',
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'No file upload or server upload limit exceeded' => '未上传文件或超出服务器上传限制',
|
||||
'Uploaded file format is limited' => '上传文件格式受限制',
|
||||
'Uploaded file is not a valid image' => '上传文件不是有效的图片文件',
|
||||
'Upload successful' => '上传成功',
|
||||
];
|
||||
return [];
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ return [
|
|||
'New mobile' => '新手机号',
|
||||
'Change password successful' => '修改密码成功',
|
||||
'Captcha is incorrect' => '验证码不正确',
|
||||
'Upload successful' => '上传成功',
|
||||
'Logged in successful' => '登录成功',
|
||||
'Logout successful' => '注销成功',
|
||||
'User center already closed' => '会员中心已经关闭',
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<div id="content-container" class="container">
|
||||
<div class="user-section login-section">
|
||||
<div class="logon-tab clearfix"> <a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|urlencode}">{:__('Sign up')}</a> </div>
|
||||
<div class="login-main">
|
||||
<div class="logon-tab clearfix"><a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|urlencode}">{:__('Sign up')}</a></div>
|
||||
<div class="login-main">
|
||||
<form name="form" id="login-form" class="form-vertical" method="POST" action="">
|
||||
<input type="hidden" name="url" value="{$url}" />
|
||||
<input type="hidden" name="url" value="{$url}"/>
|
||||
{:token()}
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="account">{:__('Account')}</label>
|
||||
|
|
@ -20,7 +20,11 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="controls">
|
||||
<input type="checkbox" name="keeplogin" checked="checked" value="1"> {:__('Keep login')}
|
||||
<div class="checkbox inline">
|
||||
<label>
|
||||
<input type="checkbox" name="keeplogin" checked="checked" value="1"> {:__('Keep login')}
|
||||
</label>
|
||||
</div>
|
||||
<div class="pull-right"><a href="javascript:;" class="btn-forgot">{:__('Forgot password')}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -34,27 +38,27 @@
|
|||
<script type="text/html" id="resetpwdtpl">
|
||||
<form id="resetpwd-form" class="form-horizontal form-layer" method="POST" action="{:url('api/user/resetpwd')}">
|
||||
<div class="form-body">
|
||||
<input type="hidden" name="action" value="resetpwd" />
|
||||
<input type="hidden" name="action" value="resetpwd"/>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-3">{:__('Type')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="radio">
|
||||
<label for="type-email"><input id="type-email" checked="checked" name="type" data-send-url="{:url('api/ems/send')}" data-check-url="{:url('api/validate/check_ems_correct')}" type="radio" value="email"> {:__('Reset password by email')}</label>
|
||||
<label for="type-mobile"><input id="type-mobile" name="type" type="radio" data-send-url="{:url('api/sms/send')}" data-check-url="{:url('api/validate/check_sms_correct')}" value="mobile"> {:__('Reset password by mobile')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" data-type="email">
|
||||
<label for="email" class="control-label col-xs-12 col-sm-3">{:__('Email')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="email" name="email" value="" data-rule="required(#type-email:checked);email;remote({:url('api/validate/check_email_exist')}, event=resetpwd, id={$user.id})" placeholder="">
|
||||
<input type="text" class="form-control" id="email" name="email" value="" data-rule="required(#type-email:checked);email;remote({:url('api/validate/check_email_exist')}, event=resetpwd, id=0)" placeholder="">
|
||||
<span class="msg-box"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group hide" data-type="mobile">
|
||||
<label for="mobile" class="control-label col-xs-12 col-sm-3">{:__('Mobile')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="mobile" name="mobile" value="" data-rule="required(#type-mobile:checked);mobile;remote({:url('api/validate/check_mobile_exist')}, event=resetpwd, id={$user.id})" placeholder="">
|
||||
<input type="text" class="form-control" id="mobile" name="mobile" value="" data-rule="required(#type-mobile:checked);mobile;remote({:url('api/validate/check_mobile_exist')}, event=resetpwd, id=0)" placeholder="">
|
||||
<span class="msg-box"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -62,7 +66,7 @@
|
|||
<label for="captcha" class="control-label col-xs-12 col-sm-3">{:__('Captcha')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input type="text" name="captcha" class="form-control" data-rule="required;length(4);integer[+];remote({:url('api/validate/check_ems_correct')}, event=resetpwd, email:#email)" />
|
||||
<input type="text" name="captcha" class="form-control" data-rule="required;length(4);integer[+];remote({:url('api/validate/check_ems_correct')}, event=resetpwd, email:#email)"/>
|
||||
<span class="input-group-btn" style="padding:0;border:none;">
|
||||
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="resetpwd">{:__('Send verification code')}</a>
|
||||
</span>
|
||||
|
|
@ -85,4 +89,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@
|
|||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<div class="profile-avatar-container">
|
||||
<img class="profile-user-img img-responsive img-circle plupload" src="{$user.avatar|cdnurl}" alt="">
|
||||
<img class="profile-user-img img-responsive img-circle" src="{$user.avatar|cdnurl}" alt="">
|
||||
<div class="profile-avatar-text img-circle">{:__('Click to edit')}</div>
|
||||
<button id="plupload-avatar" class="plupload" data-mimetype="png,jpg,jpeg,gif" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
|
||||
<button type="button" id="faupload-avatar" class="faupload" data-mimetype="png,jpg,jpeg,gif" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -199,4 +199,4 @@
|
|||
margin-left:0;
|
||||
margin-right:0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
"bootstrap-table": "fastadmin-bootstraptable#~1.11.3",
|
||||
"jstree": "~3.3.2",
|
||||
"moment": "^2.20.1",
|
||||
"plupload": "~2.2.0",
|
||||
"toastr": "~2.1.3",
|
||||
"jcrop": "~2.0.4",
|
||||
"eonasdan-bootstrap-datetimepicker": "~4.17.43",
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
"topthink/framework": "~5.0.24",
|
||||
"topthink/think-captcha": "^1.0",
|
||||
"phpmailer/phpmailer": "~6.1.6",
|
||||
"karsonzhang/fastadmin-addons": "~1.1.11",
|
||||
"karsonzhang/fastadmin-addons": "~1.2.0",
|
||||
"overtrue/pinyin": "~3.0",
|
||||
"phpoffice/phpspreadsheet": "^1.2",
|
||||
"overtrue/wechat": "4.2.11",
|
||||
"league/oauth2-server": "8.0",
|
||||
"topthink/think-queue": "v1.1.6"
|
||||
"ext-json": "*",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
|
|
|
|||
209
public/api.html
209
public/api.html
|
|
@ -186,11 +186,12 @@
|
|||
<div class="child collapse" id="验证接口">
|
||||
<a href="javascript:;" data-id="23" class="list-group-item">检测邮箱</a>
|
||||
<a href="javascript:;" data-id="24" class="list-group-item">检测用户名</a>
|
||||
<a href="javascript:;" data-id="25" class="list-group-item">检测手机</a>
|
||||
<a href="javascript:;" data-id="25" class="list-group-item">检测昵称</a>
|
||||
<a href="javascript:;" data-id="26" class="list-group-item">检测手机</a>
|
||||
<a href="javascript:;" data-id="27" class="list-group-item">检测邮箱</a>
|
||||
<a href="javascript:;" data-id="28" class="list-group-item">检测手机验证码</a>
|
||||
<a href="javascript:;" data-id="29" class="list-group-item">检测邮箱验证码</a>
|
||||
<a href="javascript:;" data-id="27" class="list-group-item">检测手机</a>
|
||||
<a href="javascript:;" data-id="28" class="list-group-item">检测邮箱</a>
|
||||
<a href="javascript:;" data-id="29" class="list-group-item">检测手机验证码</a>
|
||||
<a href="javascript:;" data-id="30" class="list-group-item">检测邮箱验证码</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3137,7 +3138,7 @@
|
|||
<div class="panel-heading" id="heading-25">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion25" href="#collapseOne25"> 检测手机 <span class="text-muted">/api/validate/check_mobile_available</span></a>
|
||||
<a data-toggle="collapse" data-parent="#accordion25" href="#collapseOne25"> 检测昵称 <span class="text-muted">/api/validate/check_nickname_available</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne25" class="panel-collapse collapse">
|
||||
|
|
@ -3155,7 +3156,7 @@
|
|||
|
||||
<div class="tab-pane active" id="info25">
|
||||
<div class="well">
|
||||
检测手机 </div>
|
||||
检测昵称 </div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Headers</strong></div>
|
||||
<div class="panel-body">
|
||||
|
|
@ -3176,10 +3177,10 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>mobile</td>
|
||||
<td>nickname</td>
|
||||
<td>string</td>
|
||||
<td>是</td>
|
||||
<td>手机号</td>
|
||||
<td>昵称</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>id</td>
|
||||
|
|
@ -3204,10 +3205,10 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_mobile_available" method="get" name="form25" id="form25">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_nickname_available" method="get" name="form25" id="form25">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="mobile">mobile</label>
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="手机号" name="mobile">
|
||||
<label class="control-label" for="nickname">nickname</label>
|
||||
<input type="string" class="form-control input-sm" id="nickname" required placeholder="昵称" name="nickname">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="id">id</label>
|
||||
|
|
@ -3257,7 +3258,7 @@
|
|||
<div class="panel-heading" id="heading-26">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion26" href="#collapseOne26"> 检测手机 <span class="text-muted">/api/validate/check_mobile_exist</span></a>
|
||||
<a data-toggle="collapse" data-parent="#accordion26" href="#collapseOne26"> 检测手机 <span class="text-muted">/api/validate/check_mobile_available</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne26" class="panel-collapse collapse">
|
||||
|
|
@ -3300,6 +3301,12 @@
|
|||
<td>string</td>
|
||||
<td>是</td>
|
||||
<td>手机号</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>id</td>
|
||||
<td>string</td>
|
||||
<td>是</td>
|
||||
<td>排除会员ID</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -3318,10 +3325,14 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_mobile_exist" method="get" name="form26" id="form26">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_mobile_available" method="get" name="form26" id="form26">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="mobile">mobile</label>
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="手机号" name="mobile">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="id">id</label>
|
||||
<input type="string" class="form-control input-sm" id="id" required placeholder="排除会员ID" name="id">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success send" rel="26">提交</button>
|
||||
|
|
@ -3367,7 +3378,7 @@
|
|||
<div class="panel-heading" id="heading-27">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion27" href="#collapseOne27"> 检测邮箱 <span class="text-muted">/api/validate/check_email_exist</span></a>
|
||||
<a data-toggle="collapse" data-parent="#accordion27" href="#collapseOne27"> 检测手机 <span class="text-muted">/api/validate/check_mobile_exist</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne27" class="panel-collapse collapse">
|
||||
|
|
@ -3385,7 +3396,7 @@
|
|||
|
||||
<div class="tab-pane active" id="info27">
|
||||
<div class="well">
|
||||
检测邮箱 </div>
|
||||
检测手机 </div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Headers</strong></div>
|
||||
<div class="panel-body">
|
||||
|
|
@ -3409,7 +3420,7 @@
|
|||
<td>mobile</td>
|
||||
<td>string</td>
|
||||
<td>是</td>
|
||||
<td>邮箱</td>
|
||||
<td>手机号</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -3428,10 +3439,10 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_email_exist" method="get" name="form27" id="form27">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_mobile_exist" method="get" name="form27" id="form27">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="mobile">mobile</label>
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="邮箱" name="mobile">
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="手机号" name="mobile">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success send" rel="27">提交</button>
|
||||
|
|
@ -3477,7 +3488,7 @@
|
|||
<div class="panel-heading" id="heading-28">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion28" href="#collapseOne28"> 检测手机验证码 <span class="text-muted">/api/validate/check_sms_correct</span></a>
|
||||
<a data-toggle="collapse" data-parent="#accordion28" href="#collapseOne28"> 检测邮箱 <span class="text-muted">/api/validate/check_email_exist</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne28" class="panel-collapse collapse">
|
||||
|
|
@ -3494,6 +3505,116 @@
|
|||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="info28">
|
||||
<div class="well">
|
||||
检测邮箱 </div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Headers</strong></div>
|
||||
<div class="panel-body">
|
||||
无
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>类型</th>
|
||||
<th>必选</th>
|
||||
<th>描述</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>mobile</td>
|
||||
<td>string</td>
|
||||
<td>是</td>
|
||||
<td>邮箱</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>正文</strong></div>
|
||||
<div class="panel-body">
|
||||
无 </div>
|
||||
</div>
|
||||
</div><!-- #info -->
|
||||
|
||||
<div class="tab-pane" id="sandbox28">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_email_exist" method="get" name="form28" id="form28">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="mobile">mobile</label>
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="邮箱" name="mobile">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success send" rel="28">提交</button>
|
||||
<button type="reset" class="btn btn-info" rel="28">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>响应输出</strong></div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="overflow-x:auto">
|
||||
<pre id="response_headers28"></pre>
|
||||
<pre id="response28"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>返回参数</strong></div>
|
||||
<div class="panel-body">
|
||||
无
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- #sandbox -->
|
||||
|
||||
<div class="tab-pane" id="sample28">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<pre id="sample_response28">无</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- #sample -->
|
||||
|
||||
</div><!-- .tab-content -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" id="heading-29">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion29" href="#collapseOne29"> 检测手机验证码 <span class="text-muted">/api/validate/check_sms_correct</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne29" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" id="doctab29">
|
||||
<li class="active"><a href="#info29" data-toggle="tab">基础信息</a></li>
|
||||
<li><a href="#sandbox29" data-toggle="tab">在线测试</a></li>
|
||||
<li><a href="#sample29" data-toggle="tab">返回示例</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="info29">
|
||||
<div class="well">
|
||||
检测手机验证码 </div>
|
||||
<div class="panel panel-default">
|
||||
|
|
@ -3544,13 +3665,13 @@
|
|||
</div>
|
||||
</div><!-- #info -->
|
||||
|
||||
<div class="tab-pane" id="sandbox28">
|
||||
<div class="tab-pane" id="sandbox29">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_sms_correct" method="get" name="form28" id="form28">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_sms_correct" method="get" name="form29" id="form29">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="mobile">mobile</label>
|
||||
<input type="string" class="form-control input-sm" id="mobile" required placeholder="手机号" name="mobile">
|
||||
|
|
@ -3564,8 +3685,8 @@
|
|||
<input type="string" class="form-control input-sm" id="event" required placeholder="事件" name="event">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success send" rel="28">提交</button>
|
||||
<button type="reset" class="btn btn-info" rel="28">重置</button>
|
||||
<button type="submit" class="btn btn-success send" rel="29">提交</button>
|
||||
<button type="reset" class="btn btn-info" rel="29">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -3575,8 +3696,8 @@
|
|||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="overflow-x:auto">
|
||||
<pre id="response_headers28"></pre>
|
||||
<pre id="response28"></pre>
|
||||
<pre id="response_headers29"></pre>
|
||||
<pre id="response29"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3591,10 +3712,10 @@
|
|||
</div>
|
||||
</div><!-- #sandbox -->
|
||||
|
||||
<div class="tab-pane" id="sample28">
|
||||
<div class="tab-pane" id="sample29">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<pre id="sample_response28">无</pre>
|
||||
<pre id="sample_response29">无</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- #sample -->
|
||||
|
|
@ -3604,26 +3725,26 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" id="heading-29">
|
||||
<div class="panel-heading" id="heading-30">
|
||||
<h4 class="panel-title">
|
||||
<span class="label label-success">GET</span>
|
||||
<a data-toggle="collapse" data-parent="#accordion29" href="#collapseOne29"> 检测邮箱验证码 <span class="text-muted">/api/validate/check_ems_correct</span></a>
|
||||
<a data-toggle="collapse" data-parent="#accordion30" href="#collapseOne30"> 检测邮箱验证码 <span class="text-muted">/api/validate/check_ems_correct</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseOne29" class="panel-collapse collapse">
|
||||
<div id="collapseOne30" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" id="doctab29">
|
||||
<li class="active"><a href="#info29" data-toggle="tab">基础信息</a></li>
|
||||
<li><a href="#sandbox29" data-toggle="tab">在线测试</a></li>
|
||||
<li><a href="#sample29" data-toggle="tab">返回示例</a></li>
|
||||
<ul class="nav nav-tabs" id="doctab30">
|
||||
<li class="active"><a href="#info30" data-toggle="tab">基础信息</a></li>
|
||||
<li><a href="#sandbox30" data-toggle="tab">在线测试</a></li>
|
||||
<li><a href="#sample30" data-toggle="tab">返回示例</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="info29">
|
||||
<div class="tab-pane active" id="info30">
|
||||
<div class="well">
|
||||
检测邮箱验证码 </div>
|
||||
<div class="panel panel-default">
|
||||
|
|
@ -3674,13 +3795,13 @@
|
|||
</div>
|
||||
</div><!-- #info -->
|
||||
|
||||
<div class="tab-pane" id="sandbox29">
|
||||
<div class="tab-pane" id="sandbox30">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>参数</strong></div>
|
||||
<div class="panel-body">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_ems_correct" method="get" name="form29" id="form29">
|
||||
<form enctype="application/x-www-form-urlencoded" role="form" action="/api/validate/check_ems_correct" method="get" name="form30" id="form30">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="email">email</label>
|
||||
<input type="string" class="form-control input-sm" id="email" required placeholder="邮箱" name="email">
|
||||
|
|
@ -3694,8 +3815,8 @@
|
|||
<input type="string" class="form-control input-sm" id="event" required placeholder="事件" name="event">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success send" rel="29">提交</button>
|
||||
<button type="reset" class="btn btn-info" rel="29">重置</button>
|
||||
<button type="submit" class="btn btn-success send" rel="30">提交</button>
|
||||
<button type="reset" class="btn btn-info" rel="30">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -3705,8 +3826,8 @@
|
|||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="overflow-x:auto">
|
||||
<pre id="response_headers29"></pre>
|
||||
<pre id="response29"></pre>
|
||||
<pre id="response_headers30"></pre>
|
||||
<pre id="response30"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -3721,10 +3842,10 @@
|
|||
</div>
|
||||
</div><!-- #sandbox -->
|
||||
|
||||
<div class="tab-pane" id="sample29">
|
||||
<div class="tab-pane" id="sample30">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<pre id="sample_response29">无</pre>
|
||||
<pre id="sample_response30">无</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- #sample -->
|
||||
|
|
@ -3739,7 +3860,7 @@
|
|||
|
||||
<div class="row mt0 footer">
|
||||
<div class="col-md-6" align="left">
|
||||
Generated on 2020-02-16 16:01:35 </div>
|
||||
Generated on 2020-08-12 21:00:33 </div>
|
||||
<div class="col-md-6" align="right">
|
||||
<a href="./" target="_blank">我的网站</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -119,6 +119,20 @@ table.table-template {
|
|||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.sp_container .sp_element_box {
|
||||
overflow: unset;
|
||||
}
|
||||
.sp_container .sp_element_box > li.input_box {
|
||||
position: unset;
|
||||
}
|
||||
.sp_container .sp_element_box .msg-box {
|
||||
right: -24px;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.sp_container .sp_element_box .msg-box {
|
||||
left: inherit;
|
||||
}
|
||||
}
|
||||
.toast-top-right-index {
|
||||
top: 62px;
|
||||
right: 12px;
|
||||
|
|
@ -133,6 +147,12 @@ table.table-template {
|
|||
margin-bottom: -5px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
select.bs-select-hidden,
|
||||
select.selectpicker {
|
||||
display: inherit !important;
|
||||
max-height: 31px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.img-center {
|
||||
margin: 0 auto;
|
||||
display: inline;
|
||||
|
|
@ -599,6 +619,7 @@ form.form-horizontal .control-label {
|
|||
.nice-validator select,
|
||||
.nice-validator textarea,
|
||||
.nice-validator [contenteditable] {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
|
|
@ -608,23 +629,29 @@ form.form-horizontal .control-label {
|
|||
display: inherit;
|
||||
}
|
||||
/*预览区域*/
|
||||
.plupload-preview {
|
||||
.plupload-preview,
|
||||
.faupload-preview {
|
||||
padding: 0 10px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.plupload-preview li {
|
||||
.plupload-preview li,
|
||||
.faupload-preview li {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.plupload-preview .thumbnail {
|
||||
.plupload-preview .thumbnail,
|
||||
.faupload-preview .thumbnail {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.plupload-preview a {
|
||||
.plupload-preview a,
|
||||
.faupload-preview a {
|
||||
display: block;
|
||||
}
|
||||
.plupload-preview a:first-child {
|
||||
.plupload-preview a:first-child,
|
||||
.faupload-preview a:first-child {
|
||||
height: 90px;
|
||||
}
|
||||
.plupload-preview a img {
|
||||
.plupload-preview a img,
|
||||
.faupload-preview a img {
|
||||
height: 80px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
|
@ -877,7 +904,7 @@ table.table-nowrap thead > tr > th {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.n-bootstrap .input-group > .n-right {
|
||||
.input-group > .msg-box.n-right {
|
||||
position: absolute;
|
||||
}
|
||||
@media (min-width: 564px) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -943,8 +943,7 @@ a:focus {
|
|||
*/
|
||||
/*Dropdowns in general*/
|
||||
.dropdown-menu {
|
||||
box-shadow: none;
|
||||
border-color: #eee;
|
||||
border: none;
|
||||
}
|
||||
.dropdown-menu > li > a {
|
||||
/*color: #777;*/
|
||||
|
|
@ -5829,4 +5828,4 @@ fieldset[disabled] .btn-yahoo.active {
|
|||
white-space: normal !important;
|
||||
}
|
||||
}
|
||||
/*# sourceMappingURL=../css/fastadmin.css.map */
|
||||
/*# sourceMappingURL=fastadmin.css.map */
|
||||
|
|
@ -21,7 +21,7 @@ body {
|
|||
.navbar {
|
||||
border: none;
|
||||
}
|
||||
.navbar-nav li > a {
|
||||
.navbar-nav > li > a {
|
||||
font-size: 14px;
|
||||
}
|
||||
.toast-top-center {
|
||||
|
|
@ -37,23 +37,29 @@ body {
|
|||
display: inherit;
|
||||
}
|
||||
/*预览区域*/
|
||||
.plupload-preview {
|
||||
.plupload-preview,
|
||||
.faupload-preview {
|
||||
padding: 0 10px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.plupload-preview li {
|
||||
.plupload-preview li,
|
||||
.faupload-preview li {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.plupload-preview .thumbnail {
|
||||
.plupload-preview .thumbnail,
|
||||
.faupload-preview .thumbnail {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.plupload-preview a {
|
||||
.plupload-preview a,
|
||||
.faupload-preview a {
|
||||
display: block;
|
||||
}
|
||||
.plupload-preview a:first-child {
|
||||
.plupload-preview a:first-child,
|
||||
.faupload-preview a:first-child {
|
||||
height: 90px;
|
||||
}
|
||||
.plupload-preview a img {
|
||||
.plupload-preview a img,
|
||||
.faupload-preview a img {
|
||||
height: 80px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
|
@ -70,6 +76,18 @@ body {
|
|||
padding: 12px 25px;
|
||||
text-align: center;
|
||||
}
|
||||
.input-group > .msg-box.n-right {
|
||||
position: absolute;
|
||||
}
|
||||
/*修复radio和checkbox样式对齐*/
|
||||
.radio > label,
|
||||
.checkbox > label {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.radio > label > input,
|
||||
.checkbox > label > input {
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
#header-navbar li.dropdown ul.dropdown-menu {
|
||||
min-width: 94px;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -164,7 +164,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
|||
|
||||
// 离线安装
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.plupload("#plupload-addon", function (data, ret) {
|
||||
Upload.api.upload("#faupload-addon", function (data, ret) {
|
||||
Config['addons'][data.addon.name] = data.addon;
|
||||
Toastr.success(ret.msg);
|
||||
operate(data.addon.name, 'enable', false);
|
||||
|
|
@ -585,4 +585,4 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
|
|||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,11 +27,8 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
{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: 'url', title: __('Preview'), formatter: Controller.api.formatter.thumb, operate: false},
|
||||
{field: 'url', title: __('Url'), formatter: Controller.api.formatter.url},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), sortable: true},
|
||||
{field: 'imagetype', title: __('Imagetype'), formatter: Table.api.formatter.search},
|
||||
{field: 'storage', title: __('Storage'), formatter: Table.api.formatter.search},
|
||||
{field: 'url', title: __('Url'), formatter: Controller.api.formatter.url, visible: false},
|
||||
{field: 'filename', title: __('Filename'), formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{
|
||||
field: 'filesize', title: __('Filesize'), operate: 'BETWEEN', sortable: true, formatter: function (value, row, index) {
|
||||
var size = parseFloat(value);
|
||||
|
|
@ -39,6 +36,10 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
return (size / Math.pow(1024, i)).toFixed(i < 2 ? 0 : 2) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];
|
||||
}
|
||||
},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), sortable: true},
|
||||
{field: 'imagetype', title: __('Imagetype'), 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},
|
||||
{
|
||||
field: 'createtime',
|
||||
|
|
@ -105,6 +106,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
{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: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), operate: false},
|
||||
{field: 'imageheight', title: __('Imageheight'), operate: false},
|
||||
{
|
||||
|
|
@ -143,7 +145,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.plupload($("#toolbar .plupload"), function () {
|
||||
Upload.api.faupload($("#toolbar .faupload"), function () {
|
||||
$(".btn-refresh").trigger("click");
|
||||
});
|
||||
});
|
||||
|
|
@ -175,4 +177,4 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
|
|||
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,47 +2,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'general/config/index',
|
||||
add_url: 'general/config/add',
|
||||
edit_url: 'general/config/edit',
|
||||
del_url: 'general/config/del',
|
||||
multi_url: 'general/config/multi',
|
||||
table: 'config',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'name', title: __('Name')},
|
||||
{field: 'intro', title: __('Intro')},
|
||||
{field: 'group', title: __('Group')},
|
||||
{field: 'type', title: __('Type')},
|
||||
{
|
||||
field: 'operate',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
events: Table.api.events.operate,
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
$("form.edit-form").data("validator-options", {
|
||||
display: function (elem) {
|
||||
return $(elem).closest('tr').find("td:first").text();
|
||||
|
|
@ -131,4 +90,4 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function (
|
|||
Table.api.bindevent(table);//当内容渲染完成后
|
||||
|
||||
// 给上传按钮添加上传成功事件
|
||||
$("#plupload-avatar").data("upload-success", function (data) {
|
||||
$("#faupload-avatar").data("upload-success", function (data) {
|
||||
var url = Backend.api.cdnurl(data.url);
|
||||
$(".profile-user-img").prop("src", url);
|
||||
Toastr.success("上传成功!");
|
||||
});
|
||||
|
||||
|
||||
// 给表单绑定事件
|
||||
Form.api.bindevent($("#update-form"), function () {
|
||||
$("input[name='row[password]']").val('');
|
||||
|
|
@ -54,4 +54,4 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function (
|
|||
},
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -74,7 +74,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
|
|||
},
|
||||
profile: function () {
|
||||
// 给上传按钮添加上传成功事件
|
||||
$("#plupload-avatar").data("upload-success", function (data) {
|
||||
$("#faupload-avatar").data("upload-success", function (data) {
|
||||
var url = Fast.api.cdnurl(data.url);
|
||||
$(".profile-user-img").prop("src", url);
|
||||
Toastr.success(__('Upload successful'));
|
||||
|
|
@ -101,4 +101,4 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
|
|||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ require.config({
|
|||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}
|
||||
],
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'backend', 'backend-init', 'table', 'form', 'dragsort', 'drag', 'drop', 'addtabs', 'selectpage'],
|
||||
paths: {
|
||||
|
|
@ -16,6 +15,7 @@ require.config({
|
|||
'validator': 'require-validator',
|
||||
'drag': 'jquery.drag.min',
|
||||
'drop': 'jquery.drop.min',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
'adminlte': 'adminlte',
|
||||
|
|
@ -42,7 +42,6 @@ require.config({
|
|||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||
'plupload': '../libs/plupload/js/plupload.min',
|
||||
'toastr': '../libs/toastr/toastr',
|
||||
'jstree': '../libs/jstree/dist/jstree.min',
|
||||
'layer': '../libs/fastadmin-layer/dist/layer',
|
||||
|
|
@ -114,11 +113,7 @@ require.config({
|
|||
// 'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css',],
|
||||
'bootstrap-select-lang': ['bootstrap-select'],
|
||||
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css',],
|
||||
'plupload': {
|
||||
deps: ['../libs/plupload/js/moxie.min'],
|
||||
exports: "plupload"
|
||||
},
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
|
||||
// 'layer': ['css!../libs/fastadmin-layer/dist/theme/default/layer.css'],
|
||||
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
||||
'validator-lang': ['validator-core'],
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -221,10 +221,22 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
|||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 绑定上传事件
|
||||
* @param form
|
||||
* @deprecated Use faupload instead.
|
||||
*/
|
||||
plupload: function (form) {
|
||||
//绑定plupload上传元素事件
|
||||
if ($(".plupload", form).size() > 0) {
|
||||
Upload.api.plupload($(".plupload", form));
|
||||
Form.events.faupload(form);
|
||||
},
|
||||
/**
|
||||
* 绑定上传事件
|
||||
* @param form
|
||||
*/
|
||||
faupload: function (form) {
|
||||
//绑定上传元素事件
|
||||
if ($(".plupload,.faupload", form).size() > 0) {
|
||||
Upload.api.upload($(".plupload,.faupload", form));
|
||||
}
|
||||
},
|
||||
faselect: function (form) {
|
||||
|
|
@ -495,7 +507,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
|
|||
|
||||
events.datetimepicker(form);
|
||||
|
||||
events.plupload(form);
|
||||
events.faupload(form);
|
||||
|
||||
events.faselect(form);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
require.config({
|
||||
urlArgs: "v=" + requirejs.s.contexts._.config.config.site.version,
|
||||
packages: [{
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}
|
||||
],
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init'],
|
||||
paths: {
|
||||
|
|
@ -16,6 +15,7 @@ require.config({
|
|||
'validator': 'require-validator',
|
||||
'drag': 'jquery.drag.min',
|
||||
'drop': 'jquery.drop.min',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
'adminlte': 'adminlte',
|
||||
|
|
@ -41,7 +41,6 @@ require.config({
|
|||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||
'plupload': '../libs/plupload/js/plupload.min',
|
||||
'toastr': '../libs/toastr/toastr',
|
||||
'jstree': '../libs/jstree/dist/jstree.min',
|
||||
'layer': '../libs/fastadmin-layer/dist/layer',
|
||||
|
|
@ -113,11 +112,7 @@ require.config({
|
|||
// 'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
||||
'bootstrap-select-lang': ['bootstrap-select'],
|
||||
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
||||
'plupload': {
|
||||
deps: ['../libs/plupload/js/moxie.min'],
|
||||
exports: "plupload"
|
||||
},
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
|
||||
// 'layer': ['css!../libs/fastadmin-layer/dist/theme/default/layer.css'],
|
||||
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
||||
'validator-lang': ['validator-core'],
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@ define("bootstrap", ["jquery"], function(){});
|
|||
require.config({
|
||||
urlArgs: "v=" + requirejs.s.contexts._.config.config.site.version,
|
||||
packages: [{
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}
|
||||
],
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init'],
|
||||
paths: {
|
||||
|
|
@ -29,6 +28,7 @@ require.config({
|
|||
'validator': 'require-validator',
|
||||
'drag': 'jquery.drag.min',
|
||||
'drop': 'jquery.drop.min',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
'adminlte': 'adminlte',
|
||||
|
|
@ -54,7 +54,6 @@ require.config({
|
|||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||
'validator-core': '../libs/nice-validator/dist/jquery.validator',
|
||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||
'plupload': '../libs/plupload/js/plupload.min',
|
||||
'toastr': '../libs/toastr/toastr',
|
||||
'jstree': '../libs/jstree/dist/jstree.min',
|
||||
'layer': '../libs/fastadmin-layer/dist/layer',
|
||||
|
|
@ -126,11 +125,7 @@ require.config({
|
|||
// 'bootstrap-select': ['css!../libs/bootstrap-select/dist/css/bootstrap-select.min.css', ],
|
||||
'bootstrap-select-lang': ['bootstrap-select'],
|
||||
// 'toastr': ['css!../libs/toastr/toastr.min.css'],
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css', ],
|
||||
'plupload': {
|
||||
deps: ['../libs/plupload/js/moxie.min'],
|
||||
exports: "plupload"
|
||||
},
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
|
||||
// 'layer': ['css!../libs/fastadmin-layer/dist/theme/default/layer.css'],
|
||||
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
|
||||
'validator-lang': ['validator-core'],
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
valign: 'middle',
|
||||
},
|
||||
config: {
|
||||
firsttd: 'tbody tr td:first-child:not(:has(div.card-views))',
|
||||
firsttd: 'tbody>tr>td.bs-checkbox',
|
||||
toolbar: '.toolbar',
|
||||
refreshbtn: '.btn-refresh',
|
||||
addbtn: '.btn-add',
|
||||
|
|
@ -169,10 +169,11 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
||||
$(Table.config.refreshbtn, toolbar).find(".fa").removeClass("fa-spin");
|
||||
$(Table.config.disabledbtn, toolbar).toggleClass('disabled', true);
|
||||
if ($(Table.config.firsttd, table).find("input[type='checkbox'][data-index]").size() > 0) {
|
||||
// 挺拽选择,需要重新绑定事件
|
||||
if ($(Table.config.firsttd + ":first", table).find("input[type='checkbox'][data-index]").size() > 0) {
|
||||
// 拖拽选择,需要重新绑定事件
|
||||
require(['drag', 'drop'], function () {
|
||||
$(Table.config.firsttd, table).drag("start", function (ev, dd) {
|
||||
var firsttd = $(Table.config.firsttd, table);
|
||||
firsttd.drag("start", function (ev, dd) {
|
||||
return $('<div class="selection" />').css('opacity', .65).appendTo(document.body);
|
||||
}).drag(function (ev, dd) {
|
||||
$(dd.proxy).css({
|
||||
|
|
@ -184,7 +185,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
}).drag("end", function (ev, dd) {
|
||||
$(dd.proxy).remove();
|
||||
});
|
||||
$(Table.config.firsttd, table).drop("start", function () {
|
||||
firsttd.drop("start", function () {
|
||||
Table.api.toggleattr(this);
|
||||
}).drop(function () {
|
||||
Table.api.toggleattr(this);
|
||||
|
|
@ -231,7 +232,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
// 导入按钮事件
|
||||
if ($(Table.config.importbtn, toolbar).size() > 0) {
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.plupload($(Table.config.importbtn, toolbar), function (data, ret) {
|
||||
Upload.api.upload($(Table.config.importbtn, toolbar), function (data, ret) {
|
||||
Fast.api.ajax({
|
||||
url: options.extend.import_url,
|
||||
data: {file: data.url},
|
||||
|
|
@ -382,8 +383,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
|
|||
var options = table.bootstrapTable('getOptions');
|
||||
var data = element ? $(element).data() : {};
|
||||
var ids = ($.isArray(ids) ? ids.join(",") : ids);
|
||||
var url = typeof data.url !== "undefined" ? data.url : (action == "del" ? options.extend.del_url : options.extend.multi_url);
|
||||
url = this.replaceurl(url, {ids: ids}, table);
|
||||
var url = typeof data.url !== "undefined" ? Table.api.replaceurl(data.url, {ids: ids}, table) : (action == "del" ? options.extend.del_url : options.extend.multi_url);
|
||||
var params = typeof data.params !== "undefined" ? (typeof data.params == 'object' ? $.param(data.params) : data.params) : '';
|
||||
var options = {url: url, data: {action: action, ids: ids, params: params}};
|
||||
Fast.api.ajax(options, function (data, ret) {
|
||||
|
|
|
|||
|
|
@ -1,62 +1,21 @@
|
|||
define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined, Plupload, Template) {
|
||||
define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined, Dropzone, Template) {
|
||||
var Upload = {
|
||||
list: {},
|
||||
options: {},
|
||||
config: {
|
||||
container: document.body,
|
||||
classname: '.plupload:not([initialized])',
|
||||
classname: '.plupload:not([initialized]),.faupload:not([initialized])',
|
||||
previewtpl: '<li class="col-xs-3"><a href="<%=fullurl%>" data-url="<%=url%>" target="_blank" class="thumbnail"><img src="<%=fullurl%>" onerror="this.src=\'' + Fast.api.fixurl("ajax/icon") + '?suffix=<%=suffix%>\';this.onerror=null;" class="img-responsive"></a><a href="javascript:;" class="btn btn-danger btn-xs btn-trash"><i class="fa fa-trash"></i></a></li>',
|
||||
},
|
||||
events: {
|
||||
onInit: function (up) {
|
||||
//修复少数安卓浏览器无法上传图片的Bug
|
||||
var input = $("input[type=file]", up.settings.container);
|
||||
if (input && input.prop("accept") && input.prop("accept").match(/image\//)) {
|
||||
input.prop("accept", "image/jpg," + input.prop("accept"));
|
||||
}
|
||||
},
|
||||
//初始化完成
|
||||
onPostInit: function (up) {
|
||||
|
||||
},
|
||||
//文件添加成功后
|
||||
onFileAdded: function (up, files) {
|
||||
var button = up.settings.button;
|
||||
$(button).data("bakup-html", $(button).html());
|
||||
var maxcount = $(button).data("maxcount");
|
||||
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
|
||||
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
|
||||
if (maxcount > 0 && input_id) {
|
||||
var inputObj = $("#" + input_id);
|
||||
if (inputObj.size() > 0) {
|
||||
var value = $.trim(inputObj.val());
|
||||
var nums = value === '' ? 0 : value.split(/\,/).length;
|
||||
var remains = maxcount - nums;
|
||||
if (files.length > remains) {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
up.removeFile(files[i]);
|
||||
}
|
||||
Toastr.error(__('You can upload up to %d file%s', remains));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//添加后立即上传
|
||||
setTimeout(function () {
|
||||
up.start();
|
||||
}, 1);
|
||||
},
|
||||
//上传进行中的回调
|
||||
onUploadProgress: function (up, file) {
|
||||
|
||||
},
|
||||
//上传之前的回调
|
||||
onBeforeUpload: function (up, file) {
|
||||
//初始化
|
||||
onInit: function () {
|
||||
|
||||
},
|
||||
//上传成功的回调
|
||||
onUploadSuccess: function (up, ret) {
|
||||
var button = up.settings.button;
|
||||
var onUploadSuccess = up.settings.onUploadSuccess;
|
||||
onUploadSuccess: function (up, ret, file) {
|
||||
var button = up.element;
|
||||
var onUploadSuccess = up.options.onUploadSuccess;
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
//上传成功后回调
|
||||
if (button) {
|
||||
|
|
@ -92,9 +51,9 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
}
|
||||
},
|
||||
//上传错误的回调
|
||||
onUploadError: function (up, ret) {
|
||||
var button = up.settings.button;
|
||||
var onUploadError = up.settings.onUploadError;
|
||||
onUploadError: function (up, ret, file) {
|
||||
var button = up.element;
|
||||
var onUploadError = up.options.onUploadError;
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
if (button) {
|
||||
var onDomUploadError = $(button).data("upload-error");
|
||||
|
|
@ -119,7 +78,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
Toastr.error(ret.msg + "(code:" + ret.code + ")");
|
||||
},
|
||||
//服务器响应数据后
|
||||
onUploadResponse: function (response) {
|
||||
onUploadResponse: function (response, up, file) {
|
||||
try {
|
||||
var ret = typeof response === 'object' ? response : JSON.parse(response);
|
||||
if (!ret.hasOwnProperty('code')) {
|
||||
|
|
@ -132,8 +91,8 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
},
|
||||
//上传全部结束后
|
||||
onUploadComplete: function (up, files) {
|
||||
var button = up.settings.button;
|
||||
var onUploadComplete = up.settings.onUploadComplete;
|
||||
var button = up.element;
|
||||
var onUploadComplete = up.options.onUploadComplete;
|
||||
if (button) {
|
||||
var onDomUploadComplete = $(button).data("upload-complete");
|
||||
if (onDomUploadComplete) {
|
||||
|
|
@ -157,8 +116,8 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
}
|
||||
},
|
||||
api: {
|
||||
//Plupload上传
|
||||
plupload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
//上传接口
|
||||
upload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
element = typeof element === 'undefined' ? Upload.config.classname : element;
|
||||
$(element, Upload.config.container).each(function () {
|
||||
if ($(this).attr("initialized")) {
|
||||
|
|
@ -169,6 +128,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
var id = $(this).prop("id");
|
||||
var url = $(this).data("url");
|
||||
var maxsize = $(this).data("maxsize");
|
||||
var maxcount = $(this).data("maxcount");
|
||||
var mimetype = $(this).data("mimetype");
|
||||
var multipart = $(this).data("multipart");
|
||||
var multiple = $(this).data("multiple");
|
||||
|
|
@ -189,65 +149,136 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
multipart = typeof multipart !== "undefined" ? multipart : Config.upload.multipart;
|
||||
//是否支持批量上传
|
||||
multiple = typeof multiple !== "undefined" ? multiple : Config.upload.multiple;
|
||||
var mimetypeArr = new Array();
|
||||
//支持后缀和Mimetype格式,以,分隔
|
||||
if (mimetype && mimetype !== "*" && mimetype.indexOf("/") === -1) {
|
||||
var tempArr = mimetype.split(',');
|
||||
for (var i = 0; i < tempArr.length; i++) {
|
||||
mimetypeArr.push({title: __('Files'), extensions: tempArr[i]});
|
||||
}
|
||||
mimetype = mimetypeArr;
|
||||
}
|
||||
//生成Plupload实例
|
||||
Upload.list[id] = new Plupload.Uploader({
|
||||
runtimes: 'html5,flash,silverlight,html4',
|
||||
multi_selection: multiple, //是否允许多选批量上传
|
||||
browse_button: id, // 浏览按钮的ID
|
||||
container: $(this).parent().get(0), //取按钮的上级元素
|
||||
flash_swf_url: '/assets/libs/plupload/js/Moxie.swf',
|
||||
silverlight_xap_url: '/assets/libs/plupload/js/Moxie.xap',
|
||||
drop_element: [id, $(this).data("input-id")],
|
||||
filters: {
|
||||
max_file_size: maxsize,
|
||||
mime_types: mimetype,
|
||||
},
|
||||
//后缀特殊处理
|
||||
mimetype = mimetype.split(",").map(function (k) {
|
||||
return k.indexOf("/") > -1 ? k : (!k || k === "*" || k.charAt(0) === "." ? k : "." + k);
|
||||
}).join(",");
|
||||
|
||||
//最大文件限制转换成mb
|
||||
var maxFilesize = (function (maxsize) {
|
||||
var matches = maxsize.toString().match(/^([0-9\.]+)(\w+)$/);
|
||||
var size = matches ? parseFloat(matches[1]) : parseFloat(maxsize),
|
||||
unit = matches ? matches[2].toLowerCase() : 'b';
|
||||
var unitDict = {'b': 0, 'k': 1, 'kb': 1, 'm': 2, 'mb': 2, 'gb': 3, 'g': 3, 'tb': 4, 't': 4};
|
||||
var y = typeof unitDict[unit] !== 'undefined' ? unitDict[unit] : 0;
|
||||
var bytes = size * Math.pow(1024, y);
|
||||
return bytes / Math.pow(1024, 2);
|
||||
}(maxsize));
|
||||
|
||||
var options = $("#" + id).data() || {};
|
||||
delete options.success;
|
||||
delete options.url;
|
||||
multipart = $.isArray(multipart) ? {} : multipart;
|
||||
|
||||
Upload.list[id] = new Dropzone("#" + id, $.extend({
|
||||
url: url,
|
||||
multipart_params: $.isArray(multipart) ? {} : multipart,
|
||||
init: {
|
||||
Init: Upload.events.onInit,
|
||||
PostInit: Upload.events.onPostInit,
|
||||
FilesAdded: Upload.events.onFileAdded,
|
||||
BeforeUpload: Upload.events.onBeforeUpload,
|
||||
UploadProgress: function (up, file) {
|
||||
var button = up.settings.button;
|
||||
$(button).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + file.percent + "%");
|
||||
Upload.events.onUploadProgress(up, file);
|
||||
},
|
||||
FileUploaded: function (up, file, info) {
|
||||
var button = up.settings.button;
|
||||
//还原按钮文字及状态
|
||||
$(button).prop("disabled", false).html($(button).data("bakup-html"));
|
||||
var ret = Upload.events.onUploadResponse(info.response, info, up, file);
|
||||
file.ret = ret;
|
||||
if (ret.code === 1) {
|
||||
Upload.events.onUploadSuccess(up, ret, file);
|
||||
} else {
|
||||
Upload.events.onUploadError(up, ret, file);
|
||||
}
|
||||
},
|
||||
UploadComplete: Upload.events.onUploadComplete,
|
||||
Error: function (up, err) {
|
||||
var button = up.settings.button;
|
||||
$(button).prop("disabled", false).html($(button).data("bakup-html"));
|
||||
var ret = {code: err.code, msg: err.message, data: null};
|
||||
Upload.events.onUploadError(up, ret);
|
||||
params: function (files, xhr, chunk) {
|
||||
var params = multipart;
|
||||
if (chunk) {
|
||||
return $.extend({}, params, {
|
||||
filesize: chunk.file.size,
|
||||
filename: chunk.file.name,
|
||||
chunkid: chunk.file.upload.uuid,
|
||||
chunkindex: chunk.index,
|
||||
chunkcount: chunk.file.upload.totalChunkCount,
|
||||
chunksize: this.options.chunkSize,
|
||||
chunkfilesize: chunk.dataBlock.data.size,
|
||||
width: chunk.file.width || 0,
|
||||
height: chunk.file.height || 0,
|
||||
type: chunk.file.type,
|
||||
});
|
||||
}
|
||||
return params;
|
||||
},
|
||||
maxFilesize: maxFilesize,
|
||||
acceptedFiles: mimetype,
|
||||
maxFiles: (maxcount && parseInt(maxcount) > 1 ? maxcount : (multiple ? null : 1)),
|
||||
previewsContainer: false,
|
||||
dictDefaultMessage: __("Drop files here to upload"),
|
||||
dictFallbackMessage: __("Your browser does not support drag'n'drop file uploads"),
|
||||
dictFallbackText: __("Please use the fallback form below to upload your files like in the olden days"),
|
||||
dictFileTooBig: __("File is too big (%sMiB), Max filesize: %sMiB", "{{filesize}}", "{{maxFilesize}}"),
|
||||
dictInvalidFileType: __("You can't upload files of this type"),
|
||||
dictResponseError: __("Server responded with %s code.", "{{statusCode}}"),
|
||||
dictCancelUpload: __("Cancel upload"),
|
||||
dictUploadCanceled: __("Upload canceled"),
|
||||
dictCancelUploadConfirmation: __("Are you sure you want to cancel this upload?"),
|
||||
dictRemoveFile: __("Remove file"),
|
||||
dictMaxFilesExceeded: __("You can only upload a maximum of %s files", "{{maxFiles}}"),
|
||||
init: function () {
|
||||
Upload.events.onInit.call(this);
|
||||
//必须添加dz-message,否则点击icon无法唤起上传窗口
|
||||
$(">i", this.element).addClass("dz-message");
|
||||
this.options.elementHtml = $(this.element).html();
|
||||
},
|
||||
addedfiles: function (files) {
|
||||
if (this.options.maxFiles && this.options.maxFiles > 0 && this.options.inputId) {
|
||||
var inputObj = $("#" + this.options.inputId);
|
||||
if (inputObj.size() > 0) {
|
||||
var value = $.trim(inputObj.val());
|
||||
var nums = value === '' ? 0 : value.split(/\,/).length;
|
||||
var remain = this.options.maxFiles - nums;
|
||||
if (remain === 0 || files.length > remain) {
|
||||
files = Array.prototype.slice.call(files, remain);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
this.removeFile(files[i]);
|
||||
}
|
||||
Toastr.error(__("You can only upload a maximum of %s files", this.options.maxFiles));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
success: function (file, response) {
|
||||
var ret = Upload.events.onUploadResponse(response, this, file);
|
||||
file.ret = ret;
|
||||
if (ret.code === 1) {
|
||||
Upload.events.onUploadSuccess(this, ret, file);
|
||||
} else {
|
||||
Upload.events.onUploadError(this, ret, file);
|
||||
}
|
||||
},
|
||||
error: function (file, response, xhr) {
|
||||
var ret = {code: 0, data: null, msg: response};
|
||||
Upload.events.onUploadError(this, ret, file);
|
||||
},
|
||||
uploadprogress: function (file, progress, bytesSent) {
|
||||
|
||||
},
|
||||
totaluploadprogress: function (progress, bytesSent) {
|
||||
if (this.getActiveFiles().length > 0) {
|
||||
$(this.element).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + Math.floor(progress) + "%");
|
||||
}
|
||||
},
|
||||
queuecomplete: function () {
|
||||
Upload.events.onUploadComplete(this, this.files);
|
||||
this.removeAllFiles(true);
|
||||
$(this.element).prop("disabled", false).html(this.options.elementHtml);
|
||||
},
|
||||
chunkSuccess: function (chunk, file, response) {
|
||||
},
|
||||
chunksUploaded: function (file, done) {
|
||||
var that = this;
|
||||
Fast.api.ajax({
|
||||
url: this.options.url,
|
||||
data: {
|
||||
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;
|
||||
}, function (data, ret) {
|
||||
file.accepted = false;
|
||||
that._errorProcessing([file], ret.msg);
|
||||
});
|
||||
},
|
||||
onUploadSuccess: onUploadSuccess,
|
||||
onUploadError: onUploadError,
|
||||
onUploadComplete: onUploadComplete,
|
||||
button: that
|
||||
});
|
||||
}, Upload.options, options));
|
||||
|
||||
//拖动排序
|
||||
if (preview_id && multiple) {
|
||||
|
|
@ -335,70 +366,46 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
});
|
||||
}
|
||||
if (input_id) {
|
||||
//粘贴上传
|
||||
$("body").on('paste', "#" + input_id, function (event) {
|
||||
var that = this;
|
||||
var image, pasteEvent;
|
||||
pasteEvent = event.originalEvent;
|
||||
if (pasteEvent.clipboardData && pasteEvent.clipboardData.items) {
|
||||
image = Upload.api.getImageFromClipboard(pasteEvent);
|
||||
if (image) {
|
||||
event.preventDefault();
|
||||
var button = $(".plupload[data-input-id='" + $(that).attr("id") + "']");
|
||||
Upload.api.send(image, function (data) {
|
||||
var urlArr = [];
|
||||
if (button && button.data("multiple") && $(that).val() !== '') {
|
||||
urlArr.push($(that).val());
|
||||
}
|
||||
urlArr.push(data.url);
|
||||
$(that).val(urlArr.join(",")).trigger("change").trigger("validate");
|
||||
});
|
||||
//粘贴上传、拖拽上传
|
||||
$("body").on('paste drop', "#" + input_id, function (event) {
|
||||
var originEvent = event.originalEvent;
|
||||
var button = $(".plupload[data-input-id='" + $(this).attr("id") + "'],.faupload[data-input-id='" + $(this).attr("id") + "']");
|
||||
if (event.type === 'paste' && originEvent.clipboardData && originEvent.clipboardData.items) {
|
||||
var items = originEvent.clipboardData.items;
|
||||
if ((items.length === 1 && items[0].type.indexOf("text") > -1) || (items.length === 2 && items[1].type.indexOf("text") > -1)) {
|
||||
|
||||
} else {
|
||||
Upload.list[button.attr("id")].paste(originEvent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
//拖拽上传
|
||||
$("body").on('drop', "#" + input_id, function (event) {
|
||||
var that = this;
|
||||
var images, pasteEvent;
|
||||
pasteEvent = event.originalEvent;
|
||||
if (pasteEvent.dataTransfer && pasteEvent.dataTransfer.files) {
|
||||
images = Upload.api.getImageFromDrop(pasteEvent);
|
||||
if (images.length > 0) {
|
||||
event.preventDefault();
|
||||
var button = $(".plupload[data-input-id='" + $(that).attr("id") + "']");
|
||||
$.each(images, function (i, image) {
|
||||
Upload.api.send(image, function (data) {
|
||||
var urlArr = [];
|
||||
if (button && button.data("multiple") && $(that).val() !== '') {
|
||||
urlArr.push($(that).val());
|
||||
}
|
||||
urlArr.push(data.url);
|
||||
$(that).val(urlArr.join(",")).trigger("change").trigger("validate");
|
||||
});
|
||||
});
|
||||
}
|
||||
if (event.type === 'drop' && originEvent.dataTransfer && originEvent.dataTransfer.files) {
|
||||
Upload.list[button.attr("id")].drop(originEvent);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
Upload.list[id].init();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @deprecated Use upload instead.
|
||||
*/
|
||||
plupload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
return Upload.api.upload(element, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
},
|
||||
// AJAX异步上传
|
||||
send: function (file, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
var index = Layer.msg(__('Uploading'), {offset: 't', time: 0});
|
||||
var id = Plupload.guid();
|
||||
var _onPostInit = Upload.events.onPostInit;
|
||||
Upload.events.onPostInit = function () {
|
||||
// 当加载完成后添加文件并上传
|
||||
Upload.list[id].addFile(file);
|
||||
//Upload.list[id].start();
|
||||
};
|
||||
$('<button type="button" id="' + id + '" class="btn btn-danger hidden plupload" />').appendTo("body");
|
||||
var id = "dropzone-" + Dropzone.uuidv4();
|
||||
$('<button type="button" id="' + id + '" class="btn btn-danger hidden faupload" />').appendTo("body");
|
||||
$("#" + id).data("upload-complete", function (files) {
|
||||
Upload.events.onPostInit = _onPostInit;
|
||||
Layer.close(index);
|
||||
Upload.list[id].removeAllFiles(true);
|
||||
});
|
||||
Upload.api.plupload("#" + id, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
Upload.api.upload("#" + id, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
setTimeout(function () {
|
||||
Upload.list[id].addFile(file);
|
||||
}, 1);
|
||||
},
|
||||
custom: {
|
||||
//自定义上传完成回调
|
||||
|
|
@ -406,31 +413,6 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
|
|||
console.log(this, response);
|
||||
alert("Custom Callback,Response URL:" + response.url);
|
||||
},
|
||||
},
|
||||
getImageFromClipboard: function (data) {
|
||||
var i, item;
|
||||
i = 0;
|
||||
while (i < data.clipboardData.items.length) {
|
||||
item = data.clipboardData.items[i];
|
||||
if (item.type.indexOf("image") !== -1) {
|
||||
return item.getAsFile() || false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getImageFromDrop: function (data) {
|
||||
var i, item, images;
|
||||
i = 0;
|
||||
images = [];
|
||||
while (i < data.dataTransfer.files.length) {
|
||||
item = data.dataTransfer.files[i];
|
||||
if (item.type.indexOf("image") !== -1) {
|
||||
images.push(item);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return images;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,10 +151,30 @@ table.table-template {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sp_container .msg-box {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
.sp_container {
|
||||
.msg-box {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sp_element_box {
|
||||
overflow: unset;
|
||||
|
||||
> li.input_box {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.msg-box {
|
||||
right: -24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.sp_container .sp_element_box .msg-box {
|
||||
left: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.toast-top-right-index {
|
||||
|
|
@ -173,6 +193,12 @@ table.table-template {
|
|||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
select.bs-select-hidden, select.selectpicker {
|
||||
display: inherit !important;
|
||||
max-height: 31px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.img-center {
|
||||
margin: 0 auto;
|
||||
display: inline;
|
||||
|
|
@ -738,6 +764,7 @@ form.form-horizontal .control-label {
|
|||
/*修复nice-validator新版下的一处BUG*/
|
||||
.nice-validator {
|
||||
input, select, textarea, [contenteditable] {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
*zoom: 1;
|
||||
|
|
@ -750,7 +777,7 @@ form.form-horizontal .control-label {
|
|||
}
|
||||
|
||||
/*预览区域*/
|
||||
.plupload-preview {
|
||||
.plupload-preview, .faupload-preview {
|
||||
padding: 0 10px;
|
||||
margin-bottom: 0;
|
||||
|
||||
|
|
@ -1081,10 +1108,8 @@ table.table-nowrap {
|
|||
}
|
||||
}
|
||||
|
||||
.n-bootstrap {
|
||||
.input-group > .n-right {
|
||||
position: absolute;
|
||||
}
|
||||
.input-group > .msg-box.n-right {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media (min-width: 564px) {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
/*Dropdowns in general*/
|
||||
.dropdown-menu {
|
||||
box-shadow: none;
|
||||
border-color: #eee;
|
||||
border:none;
|
||||
> li > a {
|
||||
/*color: #777;*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ body {
|
|||
border:none;
|
||||
}
|
||||
.navbar-nav {
|
||||
li > a {
|
||||
> li > a {
|
||||
font-size:14px;
|
||||
}
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ body {
|
|||
}
|
||||
|
||||
/*预览区域*/
|
||||
.plupload-preview {
|
||||
.plupload-preview,.faupload-preview {
|
||||
padding:0 10px;
|
||||
margin-bottom:0;
|
||||
li {
|
||||
|
|
@ -92,6 +92,21 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.input-group > .msg-box.n-right {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/*修复radio和checkbox样式对齐*/
|
||||
.radio, .checkbox {
|
||||
> label {
|
||||
margin-right: 10px;
|
||||
|
||||
> input {
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#header-navbar li.dropdown ul.dropdown-menu {
|
||||
min-width:94px;
|
||||
}
|
||||
|
|
@ -485,4 +500,4 @@ main.content {
|
|||
margin-right: 5px;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue