Skip to content

Commit 96c6f61

Browse files
authored
Merge pull request #114 from YouZiXiL/main
feat(admin): 添加多图上传功能
2 parents 84ec707 + 76f646a commit 96c6f61

File tree

4 files changed

+237
-49
lines changed

4 files changed

+237
-49
lines changed

src/plugin/admin/app/common/Layui.php

Lines changed: 165 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
namespace plugin\admin\app\common;
34

45
use support\exception\BusinessException;
@@ -45,19 +46,19 @@ public function js($indent = 0): string
4546
*/
4647
protected function options($options): array
4748
{
48-
array_walk_recursive($options, function(&$item, $key){
49+
array_walk_recursive($options, function (&$item, $key) {
4950
if (is_string($item)) {
5051
$item = htmlspecialchars($item);
5152
if ($key === 'url') {
5253
$item = str_replace('&amp;', '&', $item);
5354
}
5455
}
5556
});
56-
$field = $options['field']??'';
57+
$field = $options['field'] ?? '';
5758
$props = !empty($options['props']) ? $options['props'] : [];
58-
$verify_string = !empty($props['lay-verify']) ? ' lay-verify="'.$props['lay-verify'].'"' : '';
59+
$verify_string = !empty($props['lay-verify']) ? ' lay-verify="' . $props['lay-verify'] . '"' : '';
5960
$required_string = strpos($verify_string, 'required') ? ' required' : '';
60-
$label = !empty($options['label']) ? '<label class="layui-form-label'.$required_string.'">'.$options['label'].'</label>' : '';
61+
$label = !empty($options['label']) ? '<label class="layui-form-label' . $required_string . '">' . $options['label'] . '</label>' : '';
6162
$value = $props['value'] ?? '';
6263
$class = $props['class'] ?? 'layui-input-block';
6364

@@ -73,8 +74,8 @@ public function input($options)
7374
{
7475
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
7576

76-
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : '';
77-
$autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="'.$props['autocomplete'].'"' : '';
77+
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="' . $props['placeholder'] . '"' : '';
78+
$autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="' . $props['autocomplete'] . '"' : '';
7879
$disabled_string = !empty($props['disabled']) ? ' disabled' : '';
7980
$type = $props['type'] ?? 'text';
8081

@@ -194,7 +195,7 @@ public function textArea($options)
194195
{
195196
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
196197

197-
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : '';
198+
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="' . $props['placeholder'] . '"' : '';
198199
$disabled_string = !empty($props['disabled']) ? ' disabled' : '';
199200

200201
$this->htmlContent .= <<<EOF
@@ -218,7 +219,7 @@ public function richText($options)
218219
{
219220
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
220221

221-
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : '';
222+
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="' . $props['placeholder'] . '"' : '';
222223
$disabled_string = !empty($props['disabled']) ? ' disabled' : '';
223224
$id = $field;
224225

@@ -264,12 +265,12 @@ public function jsonEditor($options)
264265
{
265266
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
266267

267-
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="'.$props['placeholder'].'"' : '';
268-
$autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="'.$props['autocomplete'].'"' : '';
268+
$placeholder_string = !empty($props['placeholder']) ? ' placeholder="' . $props['placeholder'] . '"' : '';
269+
$autocomplete_string = !empty($props['autocomplete']) ? ' autocomplete="' . $props['autocomplete'] . '"' : '';
269270
$disabled_string = !empty($props['disabled']) ? ' disabled' : '';
270271
$type = $props['type'] ?? 'text';
271-
if (empty($value)){
272-
$value='{}';
272+
if (empty($value)) {
273+
$value = '{}';
273274
}
274275
$this->htmlContent .= <<<EOF
275276
@@ -368,6 +369,8 @@ public function uploadImage($options)
368369
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
369370
$props['acceptMime'] = $props['acceptMime'] ?? 'image/gif,image/jpeg,image/jpg,image/png';
370371
$props['url'] = $props['url'] ?? '/app/admin/upload/image';
372+
$props['multiple'] = $props['multiple'] ? 1 : 0;
373+
371374
$id = $this->createId($field);
372375

373376
unset($props['lay-verify']);
@@ -376,7 +379,8 @@ public function uploadImage($options)
376379
$props = $this->prepareProps($props);
377380
$options_string .= "\n" . $this->preparePropsToJsObject($props, 1, true);
378381

379-
$this->htmlContent .= <<<EOF
382+
if ($props['multiple'] == 0) {
383+
$this->htmlContent .= <<<EOF
380384
381385
<div class="layui-form-item">
382386
$label
@@ -393,7 +397,7 @@ public function uploadImage($options)
393397
</div>
394398
395399
EOF;
396-
$this->jsContent .= <<<EOF
400+
$this->jsContent .= <<<EOF
397401
398402
// 字段 {$options['label']} $field
399403
layui.use(["upload", "layer"], function() {
@@ -422,6 +426,123 @@ public function uploadImage($options)
422426
});
423427
424428
EOF;
429+
} else {
430+
$this->htmlContent .= <<<EOF
431+
432+
<div class="layui-form-item">
433+
$label
434+
<div class="$class">
435+
436+
<div class="layui-upload">
437+
<input type="text" class="uploader-list" style="display:none" name="$field" value="$value" id="$id"/>
438+
<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
439+
预览图:
440+
<div class="layui-upload-list uploader-list" style="overflow: auto;" id="uploader-list-$id">
441+
</div>
442+
</blockquote>
443+
444+
<button type="button" class="pear-btn pear-btn-primary pear-btn-sm" id="multi-upload-$id" permission="app.admin.upload.image">
445+
<i class="layui-icon layui-icon-upload"></i>多图上传
446+
</button>
447+
448+
<button type="button" class="pear-btn pear-btn-primary pear-btn-sm" id="attachment-choose-$id" permission="app.admin.upload.attachment">
449+
<i class="layui-icon layui-icon-align-left"></i>选择图片
450+
</button>
451+
</div>
452+
</div>
453+
</div>
454+
455+
EOF;
456+
$this->jsContent .= <<<EOF
457+
458+
// 字段 {$options['label']} $field
459+
layui.use(["upload", "layer"], function() {
460+
var upload = layui.upload;
461+
var $ = layui.$;
462+
let multiple_images = layui.$("#$id").attr("value").split(",");
463+
464+
465+
$("#attachment-choose-$id").on("click", function() {
466+
parent.layer.open({
467+
type: 2,
468+
title: "选择附件",
469+
content: "/app/admin/upload/attachment?ext=jpg,jpeg,png,gif,bmp",
470+
area: ["95%", "90%"],
471+
success: function (layero, index) {
472+
parent.layui.$("#layui-layer" + index).data("callback", function (data) {
473+
//上传完毕
474+
$('#uploader-list-$id').append(
475+
'<div class="file-iteme">' +
476+
'<div class="handle"><i class="layui-icon layui-icon-delete"></i></div>' +
477+
'<img src='+ data.url +' alt="'+ data.name +'" >' +
478+
'</div>'
479+
);
480+
481+
//追加图片成功追加文件名至图片容器
482+
multiple_images.push(data.url);
483+
$('#$id').val(multiple_images);
484+
});
485+
}
486+
});
487+
});
488+
489+
upload.render({
490+
elem: '#multi-upload-$id',$options_string
491+
before: function(obj){
492+
layer.msg('图片上传中...', {
493+
icon: 16,
494+
shade: 0.01,
495+
time: 0
496+
})
497+
},
498+
done: function(res){
499+
layer.close(layer.msg());//关闭上传提示窗口
500+
//上传完毕
501+
$('#uploader-list-$id').append(
502+
'<div class="file-iteme">' +
503+
'<div class="handle"><i class="layui-icon layui-icon-delete"></i></div>' +
504+
'<img src='+ res.data.url +' alt="'+ res.data.name +'" >' +
505+
'</div>'
506+
);
507+
508+
//追加图片成功追加文件名至图片容器
509+
multiple_images.push(res.data.url);
510+
$('#$id').val(multiple_images);
511+
}
512+
});
513+
514+
//鼠标悬浮事件
515+
$(document).on("mouseenter mouseleave", ".file-iteme", function(event){
516+
if(event.type === "mouseenter"){
517+
//鼠标悬浮
518+
$(this).children(".info").fadeIn("fast");
519+
$(this).children(".handle").fadeIn("fast");
520+
}else if(event.type === "mouseleave") {
521+
//鼠标离开
522+
$(this).children(".info").hide();
523+
$(this).children(".handle").hide();
524+
}
525+
});
526+
527+
// 删除图片
528+
$(document).on("click", ".file-iteme .handle", function(event){
529+
var delImg = $(this).parent().children("img").attr("src")
530+
var index = multiple_images.indexOf(delImg);
531+
if (index !== -1) {
532+
multiple_images.splice(index, 1);
533+
}
534+
//重新赋值
535+
$('#$id').val(multiple_images);
536+
//删除标签
537+
$(this).parent().remove();
538+
});
539+
//多图上传 end
540+
541+
});
542+
543+
EOF;
544+
}
545+
425546

426547
}
427548

@@ -444,7 +565,7 @@ public function dateTimePicker($options)
444565
public function datePicker($options)
445566
{
446567
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
447-
$value_string = $value ? ' value="'.$value.'"' : '';
568+
$value_string = $value ? ' value="' . $value . '"' : '';
448569
$options_string = '';
449570
unset($props['required'], $props['lay-verify'], $props['value']);
450571
$props = $this->prepareProps($props);
@@ -463,7 +584,7 @@ public function datePicker($options)
463584
EOF;
464585
$this->jsContent .= <<<EOF
465586
466-
// 字段 {$options["label"]} $field
587+
// 字段 {$options['label']} $field
467588
layui.use(["laydate"], function() {
468589
layui.laydate.render({
469590
elem: "#$id",$options_string
@@ -548,7 +669,7 @@ public function iconPicker($options)
548669
{
549670
[$label, $field, $value, $props, $verify_string, $required_string, $class] = $this->options($options);
550671

551-
$value_string = $value ? ' value="'.$value.'"' : '';
672+
$value_string = $value ? ' value="' . $value . '"' : '';
552673
$id = $this->createId($field);
553674
$options_string = '';
554675
$props = $this->prepareProps($props);
@@ -647,7 +768,7 @@ public function selectMulti($options)
647768
{
648769
$options['props']['toolbar'] = array_merge_recursive([
649770
'show' => true,
650-
'list' => [ 'ALL', 'CLEAR', 'REVERSE' ]
771+
'list' => ['ALL', 'CLEAR', 'REVERSE']
651772
], $options['props']['toolbar'] ?? []);
652773
$this->apiSelect($options);
653774
}
@@ -686,7 +807,7 @@ public function treeSelectMulti($options)
686807
'$expandedKeys' => '$initValue'], $options['props']['tree'] ?? []);
687808
$options['props']['toolbar'] = array_merge_recursive([
688809
'$show' => true,
689-
'$list' => [ 'ALL', 'CLEAR', 'REVERSE' ]
810+
'$list' => ['ALL', 'CLEAR', 'REVERSE']
690811
], $options['props']['toolbar'] ?? []);
691812
$this->apiSelect($options);
692813
}
@@ -712,11 +833,11 @@ public function apiSelect($options)
712833
if (is_array($item)) {
713834
$item = json_encode($item, JSON_UNESCAPED_UNICODE);
714835
$item = preg_replace('/"\$([^"]+)"/', '$1', $item);
715-
$options_string .= "\n".($url?' ':' ')."$key: $item,";
836+
$options_string .= "\n" . ($url ? ' ' : ' ') . "$key: $item,";
716837
} else if (is_string($item)) {
717-
$options_string .= "\n".($url?' ':' ')."$key: \"$item\",";
838+
$options_string .= "\n" . ($url ? ' ' : ' ') . "$key: \"$item\",";
718839
} else {
719-
$options_string .= "\n".($url?' ':' ')."$key: ".var_export($item, true).",";
840+
$options_string .= "\n" . ($url ? ' ' : ' ') . "$key: " . var_export($item, true) . ',';
720841
}
721842
}
722843

@@ -824,7 +945,7 @@ public static function buildForm($table, string $type = 'insert'): Layui
824945
if ($filter == 'form_show' && !$columns[$key]['nullable'] && $default === null && ($field !== 'password' || $type === 'insert')) {
825946
if (!isset($props['lay-verify'])) {
826947
$props['lay-verify'] = 'required';
827-
// 非类似字符串类型不允许传空
948+
// 非类似字符串类型不允许传空
828949
} elseif (!in_array($columns[$key]['type'], ['string', 'text', 'mediumText', 'longText', 'char', 'binary', 'json'])
829950
&& strpos($props['lay-verify'], 'required') === false) {
830951
$props['lay-verify'] = 'required|' . $props['lay-verify'];
@@ -938,12 +1059,27 @@ public static function buildTable($table, int $indent = 0)
9381059
EOF;
9391060
break;
9401061
case 'uploadimage':
941-
$templet = <<<EOF
1062+
$props = Util::getControlProps($info['control'], $info['control_args']);
1063+
$multiple = $props['multiple'] ?? 0;
1064+
if ($multiple == 0) {
1065+
$templet = <<<EOF
9421066
9431067
templet: function (d) {
9441068
return '<img src="'+encodeURI(d['$field'])+'" style="max-width:32px;max-height:32px;" alt="" />'
9451069
}
9461070
EOF;
1071+
} else {
1072+
$templet = <<<EOF
1073+
templet: function (d) {
1074+
const images = d['$field'].split(',');
1075+
let html = '';
1076+
for (let img of images) {
1077+
html += '<img src="' + encodeURI(img.trim()) + '" style="max-width:32px;max-height:32px;" alt="" />';
1078+
}
1079+
return html;
1080+
}
1081+
EOF;
1082+
}
9471083
break;
9481084

9491085
}
@@ -961,7 +1097,7 @@ public static function buildTable($table, int $indent = 0)
9611097
$options[$option['value']] = $option['name'];
9621098
}
9631099
}
964-
$api_result .= "\napiResults[\"$field\"] = " . json_encode($options, JSON_UNESCAPED_UNICODE) . ";";
1100+
$api_result .= "\napiResults[\"$field\"] = " . json_encode($options, JSON_UNESCAPED_UNICODE) . ';';
9651101
} else {
9661102
$api_result .= "\napiResults[\"$field\"] = [];";
9671103
}
@@ -1122,12 +1258,12 @@ function travel(items) {
11221258
*/
11231259
private function prepareProps($props)
11241260
{
1125-
$raw_list = ['true','false','null','undefined'];
1261+
$raw_list = ['true', 'false', 'null', 'undefined'];
11261262
foreach ($props as $k => $v) {
11271263
if (is_array($v)) {
11281264
$props[$k] = $this->prepareProps($v);
11291265
} elseif (!in_array($v, $raw_list) && !is_numeric($v)) {
1130-
if (strpos($v, "#") === 0){
1266+
if (strpos($v, '#') === 0) {
11311267
$props[$k] = substr($v, 1);
11321268
} else {
11331269
$props[$k] = "\"$v\"";
@@ -1145,7 +1281,7 @@ private function preparePropsToJsObject($props, $indent = 0, $sub = false)
11451281
$string .= "$indent_string{\n";
11461282
}
11471283
foreach ($props as $k => $v) {
1148-
if (!preg_match("#^[a-zA-Z0-9_]+$#", $k)) {
1284+
if (!preg_match('#^[a-zA-Z0-9_]+$#', $k)) {
11491285
$k = "'$k'";
11501286
}
11511287
if (is_array($v)) {
@@ -1157,7 +1293,7 @@ private function preparePropsToJsObject($props, $indent = 0, $sub = false)
11571293
if (!$sub) {
11581294
$string .= "$indent_string}\n";
11591295
}
1160-
return trim($string,"\n");
1296+
return trim($string, "\n");
11611297
}
11621298

11631299

0 commit comments

Comments
 (0)