首先需要重写表单,继承ActiveForm
namespace common\widgets;
use Yii;
use yii\helpers\Html;
use yii\base\InvalidConfigException;
class HorizontalActiveForm extends \yii\widgets\ActiveForm
{
/**
* @var string the default field class name when calling [[field()]] to create a new field.
* @see fieldConfig
*/
/**
* @var array HTML attributes for the form tag. Default is `[]`.
*/
public $options = [];
/**
* @var string the form layout. Either 'default', 'horizontal' or 'inline'.
* By choosing a layout, an appropriate default field configuration is applied. This will
* render the form fields with slightly different markup for each layout. You can
* override these defaults through [[fieldConfig]].
* @see \yii\bootstrap\ActiveField for details on Bootstrap 3 field configuration
*/
public $layout = 'horizontal';
/**
* {@inheritdoc}
*/
public function init()
{
if (!in_array($this->layout, ['default', 'horizontal', 'inline'])) {
throw new InvalidConfigException('Invalid layout type: ' . $this->layout);
}
if ($this->layout !== 'default') {
Html::addCssClass($this->options, 'row form-' . $this->layout);
}
$this->fieldConfig = [
'template' => "<div class='row row-box'>
<div class='col-xs-2 col-sm-2 text-right'>
{label}
</div>
<div class='col-xs-9 col-sm-9'>
{input}
<div class='help-block'>{hint}</div>
<div class='help-block'>{error}</div>
</div>
</div>",
];
parent::init();
}
/**
* {@inheritdoc}
* @return ActiveField the created ActiveField object
*/
public function field($model, $attribute, $options = [])
{
$hidden = '';
if(isset($options['options']['hidden'])) {
$hidden = ' hide';
}
if(isset($options['options']['whole_row'])) {
$options = [
'options' => ['class' => 'col-md-12 col-sm-12 whole-row form-group' . $hidden],
'template' => "<div class='row row-box'>
<div class='col-xs-1 col-sm-1 text-right'>
{label}
</div>
<div class='col-xs-10 col-sm-10'>
{input}
<div class='help-block'>{hint}</div>
<div class='help-block'>{error}</div>
</div>
</div>",
];
} else if(isset($options['options']['media_field'])) {
$data = " data-id='". $attribute ."' ";
$data .= " id='".$attribute."_uploader' ";
if(isset($options['options']['multi_selection'])) {
$data .= " data-multiple='multiple' ";
}
if(isset($options['options']['save_path'])) {
$data .= " data-oss-path='". $options['options']['save_path']."' ";
}
$media_list = '';
if(isset($options['options']['attachment'])) {
$attachment = $options['options']['attachment'];
if(!empty($attachment)) {
$media_list = '<li><div class="img-info"><img src="/' . $attachment . '" /><p data-id="' .$model->id. '"></p><div class="delete-image"> X </div></div></li>';
}
}
$options = [
'options' => ['class' => 'col-md-12 col-sm-12 whole-row form-group' . $hidden],
'template' => "<div class='row row-box'>
<div class='col-xs-1 col-sm-1 text-right'>
{label}
</div>
<div class='col-xs-10 col-sm-10'>
<div class='media-picker'>
<a class='media-picker-button' ".$data." href='javascript:void(0)'>
<span class='fa fa-cloud-upload'></span>
</a>
{input}
<div class='help-block'>{hint}</div>
<div class='help-block'>{error}</div>
<div class='media-list'>
<ul>". $media_list ."</ul>
</div>
</div>
</div>
</div>",
];
} else {
$options = [
'options' => ['class' => 'col-md-6 col-sm-12 double-row form-group' . $hidden]
];
}
return parent::field($model, $attribute, $options);
}
}
这里只考虑了单个文件,多个文件循环显示就好,如果是直接存在当前表中,则更简单,只需要$model->image就行,不需要再传入attachment
使用
<?php $form = HorizontalActiveForm::begin(); ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'attachment_id', [
'options' => [
'media_field' => true,
'save_path' => 'common',
//'multi_selection' => true, // 多文件上传使用
'attachment' => empty($model->attachment) ? '' : $model->attachment->url
]
])->hiddenInput()->hint('单图上传,格式:png,jpg,jpeg,gif') ?>
<?= $form->field($model, 'describe', ['options' => ['whole_row' => true]])->textarea(['rows' => 6]) ?>
<?= RightSubmitButton::widget() ?>
<?php HorizontalActiveForm::end(); ?>
上传图片
namespace backend\controllers;
use Yii;
use yii\web\Controller;
use common\models\attachment\Attachment;
use yii\web\UploadedFile;
class UploaderController extends Controller {
public $enableCsrfValidation = false;
public function actionUploader() {
$updir = Yii::$app->request->post('updir');
$files = UploadedFile::getInstanceByName('ysx_media');
$savePath = $this->getDir($updir);
$ext = $files->getExtension();
$type = 1;
$cover_url = '';
if(in_array($ext, ['mp4', '3gp'])) {
$type = 2;
} else if(in_array($ext, ['mp3', '0gg'])) {
$type = 4;
}
$saveName = $this->getName($ext);
$result = $savePath . '/' . $saveName;
$isSave = $files->saveAs($result);
if($isSave) {
$attachementModel = new Attachment();
$attachementModel->name = $saveName;
$attachementModel->url = $result;
$attachementModel->save();
$data = [
'error' => 0,
'attachement_id' => $attachementModel->id,
'url' => $result
];
} else {
$data = [
'error' => 1,
'msg' => '上传失败!'
];
}
return json_encode($data);
}
public function actionDeluploader() {
$attachement_id = Yii::$app->request->post('attachement_id');
$attachementModel = Attachment::findOne($attachement_id);
@unlink($attachementModel->url);
$attachementModel->delete();
$data = [
'error' => 0,
'msg' => '删除成功!'
];
}
/**
* 获取上传目录
*/
private function getDir($dir) {
$baseDir = "uploads/";
if(!empty($dir)) {
$baseDir = $baseDir . $dir;
if(!file_exists($baseDir)) {
@mkdir($baseDir, 777);
}
}
return $baseDir;
}
/**
* 重命名
*/
private function getName($ext) {
$str = time() . rand(1000, 99999);
return $str . '.' . $ext;
}
}
js
gObjectName = ''
gObjectAttachements = new Array() //多图片上传id
gObjectNames = new Array() //多图片上传保持
videoAttachmentId = ''; // 由于需要单独上传视频封面,这里保存下视频id
currentUrl = window.location.href;
baseBackend = window.location.protocol + "//" +window.location.host;
ossUrl = 'http://oss.yishixue.com/';
$(document).ready(function() {
//上传
$('.media-picker').each(function() {
var el = $(this);
var elbtn = el.find('.media-picker-button');
var multiSelection = false;
// 上传目录
var inputField = el.find('input[type=hidden]');
var token = $('input[name="_csrf-backend"]').val();
// 视频封面,需要获取attachment_id
var attachementId = '';
// 类型
var mediaType = elbtn.attr('data-type');
var mimeTypes = [
{ title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" },
{ title: "Video files", extensions: "mp4,3gp" },
{ title: "Video files", extensions: "pdf,doc,docx,ppt,pptx,xls,xlsx,zip,rar" }
];
if(mediaType == 'video') {
mimeTypes = [
{ title: "Video files", extensions: "mp4,3gp" }
];
} else if(mediaType == 'file') {
mimeTypes = [
{ title: "Video files", extensions: "pdf,doc,docx,ppt,pptx,xls,xlsx,zip,rar" }
];
} else if(mediaType == 'image') {
mimeTypes = [
{ title: "Image files", extensions: "jpg,jpeg,gif,png,bmp" }
];
}
// 是否多文件上传
if (elbtn.attr('data-multiple') == 'multiple') {
multiSelection = true;
// 如果已经有文件
var oldFiles = inputField.val();
if (oldFiles != '') {
var oldFilesArr = $.parseJSON(oldFiles);
for (var x = 0; x < oldFilesArr.length; x++) {
gObjectNames.push(oldFilesArr[x]);
}
}
}
var updir = elbtn.attr('data-oss-path');
var uploader = new plupload.Uploader({
runtimes: 'html5,flash,silverlight,html4',
browse_button: elbtn.attr('data-id') + '_uploader',
url: baseBackend + '/uploader/uploader',
file_data_name: 'ysx_media',
multi_selection: multiSelection,
auto_start: true,
flash_swf_url: '../plupload/js/Moxie.swf',
silverlight_xap_url: '../plupload/js/Moxie.xap',
//只允许上传图片和zip,rar文件
filters: {
mime_types: mimeTypes,
max_file_size: '50mb', //最大只能上传10mb的文件
prevent_duplicates: false //不允许选取重复文件
},
init: {
PostInit: function() {
gObjectAttachements = new Array() //多图片上传id
gObjectNames = new Array() //多图片上传保持
},
FilesAdded: function(up) {
var videoCover = el.parents('.form-video-cover');
if(videoCover != undefined) {
attachementId = videoAttachmentId;
}
uploader.setOption("multipart_params", {"updir": updir, "_token": token, "attachement_id":attachementId});
up.start(); //选择完后直接上传
},
FileUploaded: function(up, file, info) {
if (info.status == 200) {
var fileType = file.type;
var isImage = fileType.indexOf('image');
var isVideo = fileType.indexOf('video');
var isApplication = fileType.indexOf('application');
// 获取返回德数据
var fileInfos = $.parseJSON(info.response);
if(fileInfos.error == 0) {
var fileAttachementId = fileInfos.attachement_id
var fileUrl = fileInfos.url;
if (multiSelection) {
// 多文件转为json
gObjectAttachements.push(fileAttachementId);
inputField.val(JSON.stringify(gObjectAttachements));
// 把图片显示出来
gObjectNames.push(fileUrl);
var imageHtml = '';
for (var i = 0; i < gObjectNames.length; i++) {
if (isImage > -1) {
imageHtml += '<li class="image-info"><div class="info"><img src="' + gObjectNames[i] + '"/><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
}
if (isVideo > -1) {
imageHtml += '<li class="video-info"><div class="info"><video controls src="' + gObjectNames[i] + '"></video><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
}
if (isApplication > -1) {
imageHtml += '<li class="file-info"><div class="info"><div class="attachment-file">' + gObjectNames[i] + '</div><p data-id="' + gObjectAttachements[i] + '">' + gObjectNames[i] + '</p><div class="delete-image"> X </div></div></li>';
}
}
el.find('.media-list ul').html(imageHtml);
} else {
// 单文件直接用名称,
inputField.val(fileAttachementId);
gObjectName = fileUrl
// 把图片显示出来
var imageHtml = '';
if (isImage > -1) {
imageHtml = '<li class="image-info"><div class="info"><img src="' + gObjectName + '"/><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
}
if (isVideo > -1) {
imageHtml = '<li class="video-info"><div class="info"><video controls src="' + gObjectName + '"></video><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
}
if (isApplication > -1) {
imageHtml += '<li class="file-info"><div class="info"><div class="attachment-file">' + gObjectName + '</div><p data-id="' + fileAttachementId + '">' + gObjectName + '</p><div class="delete-image"> X </div></div></li>';
}
// 视频不让多选
if (isVideo > -1) {
// 封面
coverDom = el.parents('.form-video').find('.form-video-cover');
if(coverDom.hasClass('hide')) {
coverDom.removeClass('hide');
}
videoAttachmentId = fileAttachementId;
}
el.find('.media-list ul').html(imageHtml);
}
} else {
alert(fileInfos.msg);
}
} else {
alert(info.response);
}
},
Error: function(up, err) {
if (err.code == -600) {
alert("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小");
} else if (err.code == -601) {
alert("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型");
} else if (err.code == -602) {
alert("\n这个文件已经上传过一遍了");
} else {
alert("\nError xml:" + err.response);
}
}
}
})
uploader.init();
})
// 删除
$('.media-picker').each(function() {
var el = $(this)
var inputField = el.find('input[type=hidden]');
var fileAttachement = inputField.val();
var elbtn = el.find('.media-picker-button');
var multiSelection = false;
// 是否多文件上传
if (elbtn.attr('data-multiple') == 'multiple') {
multiSelection = true;
}
if (multiSelection) {
el.on('click', '.delete-image', function() {
var elDel = $(this);
// 得到filename
var currentFileName = elDel.prev('p').html();
// 得到id
var currentAttachementId = elDel.prev('p').attr('data-id');
// 删除当前的父级li
elDel.parent().parent().remove();
// 重新赋值数组
// 去掉url数组中的当前url
for(var i in gObjectNames) {
if(gObjectNames[i] == currentFileName) {
gObjectNames.splice(i,1);
break;
}
}
// 去掉id数组中的当前id
for(var i in gObjectAttachements) {
if(gObjectAttachements[i] == currentAttachementId) {
gObjectAttachements.splice(i,1);
break;
}
}
// 后端不做删除
/*$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
$.ajax({
type: "POST",
url: baseBackend + "uploader/deluploader",
data: "attachement_id=" + currentAttachementId,
success: function(msg) {
}
});*/
inputField.val(JSON.stringify(gObjectAttachements));
})
} else {
el.on('click', '.delete-image', function() {
// 显示值为空
el.find('.media-list ul').html('');
inputField.val('');
// oss删除
if (gObjectName != '') {
fileAttachement = gObjectName;
}
// 后端不做删除
/*$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
$.ajax({
type: "POST",
url: baseBackend + "uploader/deluploader",
data: "attachement_id=" + fileAttachement,
success: function(msg) {
}
});*/
})
}
})
})