├── LICENSE
├── README.md
├── composer.json
├── logo.png
├── resources
├── assets
│ ├── field.css
│ ├── field.js
│ └── jquery.dragsort.js
├── lang
│ ├── en
│ │ └── form-media.php
│ ├── zh_CN
│ │ └── form-media.php
│ └── zh_TW
│ │ └── form-media.php
└── views
│ └── field.blade.php
├── routes
└── admin.php
├── src
├── Form
│ ├── Field.php
│ └── Field
│ │ ├── Audio.php
│ │ ├── Files.php
│ │ ├── Photo.php
│ │ ├── Photos.php
│ │ └── Video.php
├── Http
│ └── Controllers
│ │ └── FormMedia.php
├── MediaManager.php
├── ServiceProvider.php
└── Support
│ └── helpers.php
└── version.php
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 deatil(https://github.com/deatil)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dcat-admin 表单媒体拓展
2 |
3 |
4 | ## 预览
5 |
6 | ### 表单
7 | 
8 |
9 | ### 动态表单
10 | 
11 |
12 | ### 弹出选择框
13 | 
14 |
15 |
16 | ## 环境
17 | - PHP >= 7.2.5
18 | - Dcat-admin ^2.0
19 |
20 |
21 | ## 安装
22 |
23 | ### composer 安装
24 |
25 | ```
26 | composer require lake/form-media
27 | ```
28 |
29 | ### 安装扩展
30 |
31 | 在 `开发工具->扩展` 安装本扩展
32 |
33 |
34 | ## 使用
35 |
36 | #### 单图 数据库结构 varchar
37 |
38 | ##### 可删除
39 |
40 | ```
41 | $form->photo('photo','图片')
42 | ->nametype('datetime')
43 | ->remove(true)
44 | ->help('单图,可删除');
45 | ```
46 |
47 | ##### 不可删除
48 |
49 | ```
50 | $form->photo('photo','图片')
51 | ->path('pic')
52 | ->nametype('uniqid')
53 | ->remove(false)
54 | ->help('单图,不可删除');
55 |
56 | $form->photo('photo','图片')
57 | ->nametype('uniqid')
58 | ->help('单图,不可删除');
59 | ```
60 |
61 | #### 多图 数据库结构 json
62 |
63 | ```
64 | $form->photos('photo', '图片')
65 | ->path('pic')
66 | ->pageSize(16)
67 | ->nametype('uniqid')
68 | ->limit(9)
69 | ->remove(true); //可删除
70 | ```
71 |
72 | #### 视频 数据库结构 json/varchar
73 |
74 | ```
75 | $form->video('video','视频')
76 | ->path('video')
77 | ->nametype('uniqid')
78 | ->remove(true); //可删除
79 | ```
80 |
81 | ### 参数说明
82 | ```
83 | path(string) : 快速定位目录,默认为根目录
84 | nametype(string) : 文件重命名方式 uniqid|datetime|sequence|original,默认 uniqid
85 | accept(string) : 设置 input accept 属性, 自定义,默认类型不设置
86 | pageSize(int) : 弹出层列表每页显示数量
87 | limit(int) : 限制条数
88 | remove(boolean) : 是否有删除按钮
89 | saveFullUrl(boolean) : 是否保存完整链接
90 | disk(string) : 文件存储的磁盘,具体信息可以查看 `config/filesystems.php`
91 |
92 | photo 、 photos 、 video 的参数默认值不一样
93 |
94 | photo 默认 limit = 1 remove = false
95 |
96 | photos 默认 limit = 9 remove = true
97 |
98 | video 默认 limit = 1 remove = true
99 | ```
100 |
101 | ##### 多图上传提交的数据为 json 字符串,如需输出数组,请在对应模型中加入下面代码
102 | ```
103 | namespace App\Models;
104 |
105 | use Illuminate\Database\Eloquent\Model;
106 |
107 | class Demo extends Model
108 | {
109 |
110 | public function getPicturesAttribute($pictures)
111 | {
112 |
113 | return json_decode($pictures, true);
114 |
115 | }
116 |
117 | }
118 | ```
119 |
120 |
121 | ## 开源协议
122 |
123 | * 本扩展遵循 `MIT` 开源协议发布,在保留本扩展版权的情况下提供个人及商业免费使用。
124 |
125 |
126 | ## 版权
127 |
128 | * 该系统所属版权归 deatil(https://github.com/deatil) 所有。
129 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lake/form-media",
3 | "alias": "表单媒体扩展",
4 | "description": "Dcat-admin image/video input extension. / Dcat-admin表单媒体扩展。",
5 | "type": "library",
6 | "keywords": [
7 | "dcat-admin",
8 | "lake",
9 | "media",
10 | "form-media",
11 | "extension"
12 | ],
13 | "homepage": "https://github.com/deatil/dcat-form-media",
14 | "license": "MIT",
15 | "authors": [
16 | {
17 | "name": "deatil",
18 | "email": "deatil@github.com",
19 | "homepage": "https://github.com/deatil"
20 | }
21 | ],
22 | "require": {
23 | "php": ">=7.2.5",
24 | "dcat/laravel-admin": "^2.0"
25 | },
26 | "autoload": {
27 | "psr-4": {
28 | "Lake\\FormMedia\\": "src/"
29 | },
30 | "files": [
31 | "src/Support/helpers.php"
32 | ]
33 | },
34 | "extra": {
35 | "dcat-admin": "Lake\\FormMedia\\ServiceProvider",
36 | "laravel": {
37 | "providers": [
38 | "Lake\\FormMedia\\ServiceProvider"
39 | ]
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deatil/dcat-form-media/2981651fa73e5c56f0cf06cd5de67a1c20e59d3a/logo.png
--------------------------------------------------------------------------------
/resources/assets/field.css:
--------------------------------------------------------------------------------
1 | .lake-form-media .lake-form-media-img-show {
2 | border-radius: 5px;
3 | border: 1px solid #e9ecec;
4 | padding: 8px;
5 | width: 100%;
6 | margin-bottom: 5px;
7 | }
8 | .lake-form-media .lake-form-media-preview-item {
9 | margin: 3px 0;
10 | }
11 | .lake-form-media .lake-form-media-row-col {
12 | overflow: hidden;
13 | padding: 5px 6px;
14 | position: relative;
15 | border: 1px solid #f5f6f9;
16 | border-radius: 5px;
17 | background: #fff;
18 | }
19 | .lake-form-media .lake-form-media-row-col:hover {
20 | border: 1px solid #dfe1e6;
21 | }
22 | .lake-form-media .lake-form-media-row-col .lake-form-media-row-img {
23 | height: 110px;
24 | text-align: center;
25 | font-size: 65px;
26 | overflow: hidden;
27 | }
28 | .lake-form-media .lake-form-media-row-col .lake-form-media-row-img > img {
29 | vertical-align: middle;
30 | }
31 | .lake-form-media .lake-form-media-row-col .lake-form-media-row-img .lake-form-media-preview-fa {
32 | vertical-align: middle;
33 | border: 1px solid #f9f7f7;
34 | display: block;
35 | width: 100%;
36 | height: 100%;
37 | font-size: 65px;
38 | padding-top: 20px;
39 | }
40 | .lake-form-media .lake-form-media-row-col .row-icon {
41 | position: absolute;
42 | top: 5px;
43 | left: 6px;
44 | background: #fff;
45 | border-radius: .15rem;
46 | }
47 | .lake-form-media .lake-form-media-row-col .row-icon .fa {
48 | color: #abafb5;
49 | font-size: 13px;
50 | }
51 | .lake-form-media .lake-form-media-row-col .row-title {
52 | text-align: center;
53 | overflow: hidden;
54 | text-overflow:ellipsis;
55 | white-space: nowrap;
56 | color: #a4a9ad;
57 | font-size: 12px;
58 | padding: 3px 0;
59 | }
60 | .lake-form-media .lake-form-media-row-col .caption {
61 | text-align: right;
62 | }
63 | .lake-form-media .lake-form-media-row-col .caption .btn {
64 | line-height: 1.1 !important;
65 | padding: .25rem 0 .25rem 1.1rem !important;
66 | height: auto !important;
67 | box-shadow: none !important;
68 | border: 0px !important;
69 | color: #8f98a7 !important;
70 | }
71 | .lake-form-media .lake-form-media-row-col .caption .btn:first-child {
72 | padding-left: 0 !important;
73 | }
74 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-preview i {
75 | color: #abafb5;
76 | }
77 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-preview:hover i {
78 | color: #292e35;
79 | }
80 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-delete i {
81 | color: #f76687;
82 | }
83 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-delete:hover i {
84 | color: #f7055e;
85 | font-weight: bold;
86 | }
87 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-dragsort i {
88 | color: #abafb5;
89 | }
90 | .lake-form-media .lake-form-media-row-col .caption .btn.lake-form-media-img-show-item-dragsort:hover i {
91 | color: #292e35;
92 | }
93 |
94 | .lake-form-media-modal {
95 | z-index: 99999999 !important;
96 | }
97 | .lake-form-media-modal .modal-dialog {
98 | border: 1px solid #d4d6da;
99 | }
100 | .lake-form-media-modal .lake-form-media-body-table .files>li {
101 | float: left;
102 | width: 150px;
103 | border: 1px solid #eee;
104 | margin-bottom: 10px;
105 | margin-right: 10px;
106 | position: relative;
107 | }
108 | .lake-form-media-modal .lake-form-media-body-table .files>li>.file-select {
109 | position: absolute;
110 | top: -4px;
111 | left: -1px;
112 | }
113 | .lake-form-media-modal .lake-form-media-body-table .file-icon {
114 | text-align: center;
115 | font-size: 65px;
116 | color: #666;
117 | display: block;
118 | height: 110px;
119 | overflow: hidden;
120 | }
121 | .lake-form-media-modal .lake-form-media-body-table .file-info {
122 | text-align: center;
123 | padding: 10px;
124 | background: #f4f4f4;
125 | }
126 | .lake-form-media-modal .lake-form-media-body-table .file-name {
127 | font-weight: bold;
128 | color: #666;
129 | display: block;
130 | overflow: hidden !important;
131 | white-space: nowrap !important;
132 | text-overflow: ellipsis !important;
133 | }
134 | .lake-form-media-modal .lake-form-media-body-table .file-size {
135 | color: #999;
136 | font-size: 12px;
137 | display: block;
138 | }
139 | .lake-form-media-modal .lake-form-media-body-table .files {
140 | list-style: none;
141 | margin: 0;
142 | padding: 0;
143 | }
144 | .lake-form-media-modal .lake-form-media-body-table .file-icon.has-img {
145 | padding: 0;
146 | }
147 | .lake-form-media-modal .lake-form-media-body-table .file-icon.has-img>img {
148 | max-width: 100%;
149 | height: auto;
150 | max-height: 92px;
151 | }
152 | .lake-form-media-modal .thumbnail {
153 | border: 1px solid #fff;
154 | margin: 3px 0;
155 | }
156 | .lake-form-media-modal .thumbnail:hover {
157 | cursor: pointer;
158 | border: 1px solid #ededed;
159 | }
160 | .lake-form-media-modal .thumbnail.lake-form-media-selected {
161 | border: 1px solid #4c60a3;
162 | }
163 | .lake-form-media-modal .lake-form-media-empty {
164 | text-align: center;
165 | padding: 35px 0;
166 | color: #bfc2cc;
167 | background: #f7f5f5;
168 | border-radius: .5rem;
169 | }
170 | .lake-form-media-modal .lake-form-media-modal-page {
171 | position: absolute;
172 | bottom: 1rem;
173 | margin-left: 1rem;
174 | }
175 | .lake-form-media-modal .lake-form-media-modal-page .btn {
176 | margin-right: .25rem;
177 | }
178 |
--------------------------------------------------------------------------------
/resources/assets/field.js:
--------------------------------------------------------------------------------
1 | /**
2 | * LakeFormMedia-field.js v1.0.18
3 | *
4 | * @create 2020-11-28
5 | * @author deatil
6 | */
7 | $(function () {
8 | var LakeFormMedia = {
9 | init: function() {
10 | var thiz = this;
11 |
12 | // 刷新预览
13 | this.onEvent('change', '.lake-form-media-input', function() {
14 | thiz.refreshInputPreview(this);
15 | });
16 |
17 | // 拖拽排序
18 | this.onEvent('mouseenter', '.js-dragsort', function() {
19 | var showRowCont = $(this).parents(".lake-form-media-img-show-row");
20 | if (showRowCont.hasClass('bind-dragsort')) {
21 | return ;
22 | }
23 |
24 | var mediaCont = $(this).parents('.lake-form-media');
25 | var name = mediaCont.data('name');
26 |
27 | showRowCont.dragsort({
28 | itemSelector: 'div.lake-form-media-preview-item',
29 | dragSelector: ".js-dragsort",
30 | dragEnd: function () {
31 | thiz.refreshInputString(name);
32 | },
33 | placeHolderTemplate: $('
'),
34 | scrollSpeed: 15
35 | });
36 | showRowCont.addClass('bind-dragsort')
37 | });
38 |
39 | // 删除
40 | this.onEvent("click", ".lake-form-media-img-show-item-delete", function(){
41 | var $this = $(this);
42 |
43 | var mediaCont = $this.parents('.lake-form-media');
44 | var name = mediaCont.data('name');
45 |
46 | var mediaShowCont = mediaCont.find('.lake-form-media-img-show');
47 |
48 | var options = mediaCont.data('options');
49 |
50 | var limit = options.limit;
51 |
52 | // 可多选时
53 | var multiplechoice = options.multiplechoice
54 |
55 | var itemurl = $this.data('url');
56 |
57 | layer.confirm(thiz.lang("remove_tip", {
58 | data: itemurl,
59 | }), {
60 | icon: 3,
61 | title: thiz.lang("system_tip"),
62 | }, function(index) {
63 |
64 | // 不是多选时
65 | if (multiplechoice != 1 && limit > 1) {
66 | var itemIndex = mediaCont
67 | .find('.lake-form-media-preview-item')
68 | .index($this.parents('.lake-form-media-preview-item'));
69 |
70 | mediaCont.find('.lake-form-media-preview-item').eq(itemIndex).remove();
71 | } else {
72 | mediaCont.find('.lake-form-media-preview-item[data-src="' + itemurl + '"]').remove();
73 | }
74 |
75 | thiz.refreshInputString(name);
76 |
77 | if (mediaShowCont.find('.lake-form-media-preview-item').length < 1) {
78 | mediaShowCont.hide();
79 | }
80 |
81 | // 关闭提示框
82 | layer.close(index);
83 | });
84 |
85 | return 1;
86 | });
87 |
88 | // 弹出选择器
89 | this.onEvent('click', '.lake-form-media-btn-file', function (event) {
90 | event.preventDefault();
91 | event.stopPropagation();
92 |
93 | var modal = $(this);
94 | var modalId = modal.data("target");
95 |
96 | $("#" + modalId).remove();
97 | $("#" + modalId + "Body")
98 | .clone(true, true)
99 | .find(".modal")
100 | .attr("id", modalId)
101 | .appendTo('body');
102 |
103 | $("#" + modalId).modal({
104 | show: true,
105 | backdrop: 'static',
106 | keyboard: false
107 | });
108 |
109 | var title = modal.data('title');
110 |
111 | var mediaCont = $(this).parents('.lake-form-media');
112 | var name = mediaCont.data('name');
113 |
114 | var options = mediaCont.data('options');
115 | options = $.extend({}, options);
116 |
117 | var path = options.path;
118 | var uploadUrl = options.upload_url;
119 | var createFolderUrl = options.create_folder_url;
120 |
121 | var mediaModalCont = $("#" + modalId);
122 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
123 | mediaModalPageCont.data('current-page', 1);
124 |
125 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
126 | mediaModalNavOlCont.data('current-path', path);
127 |
128 | if (uploadUrl.length <= 0) {
129 | mediaModalCont.find('.lake-form-media-upload-label').addClass('hidden');
130 | }
131 | if (createFolderUrl.length <= 0) {
132 | mediaModalCont.find('.lake-form-media-create-folder-label').addClass('hidden');
133 | }
134 |
135 | mediaModalCont.find('.modal-title').text(thiz.lang("select_type", {
136 | "title": title,
137 | }));
138 |
139 | thiz.getdata(name, path, options);
140 | });
141 |
142 | // 关闭弹出的选择器
143 | this.onEvent('click', '.lake-form-media-close', function (event) {
144 | var modalId = $(this).data("modal");
145 | $("#" + modalId).modal("hide");
146 | });
147 |
148 | // 点击排序切换
149 | this.onEvent('click', ".lake-form-media-modal-order", function() {
150 | var order = $(this).data('order');
151 |
152 | if (order == 'name') {
153 | $(this).data('order', 'time');
154 |
155 | $(this).find('.fa')
156 | .removeClass('fa-sort-alpha-asc')
157 | .addClass('fa-calendar-times-o');
158 | } else {
159 | $(this).data('order', 'name');
160 |
161 | $(this).find('.fa')
162 | .removeClass('fa-calendar-times-o')
163 | .addClass('fa-sort-alpha-asc');
164 | }
165 |
166 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
167 | var mediaId = mediaModalCont.data('media');
168 | var mediaCont = $("." + mediaId);
169 |
170 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
171 | var name = mediaCont.data('name');
172 | var path = mediaModalNavOlCont.data('current-path');
173 | var options = mediaCont.data('options');
174 |
175 | thiz.getdata(name, path, options)
176 | });
177 |
178 | // 双击复制文件名
179 | this.onEvent("dblclick", '.lake-form-media-row-col .row-title', function() {
180 | var data = $(this).text();
181 |
182 | thiz.copyData(data);
183 |
184 | return false;
185 | });
186 |
187 | // 点击文件夹
188 | this.onEvent('click', ".lake-form-media-dir-op", function() {
189 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
190 | var mediaId = mediaModalCont.data('media');
191 | var mediaCont = $("." + mediaId);
192 |
193 | var name = mediaCont.data('name');
194 | var path = $(this).data('path');
195 |
196 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
197 | mediaModalPageCont.data('current-page', 1);
198 |
199 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
200 | mediaModalNavOlCont.data('current-path', path);
201 |
202 | var options = mediaCont.data('options');
203 |
204 | thiz.getdata(name, path, options)
205 | });
206 |
207 | // 点击 nav
208 | this.onEvent("click", ".lake-form-media-nav-li", function(){
209 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
210 | var mediaId = mediaModalCont.data('media');
211 | var mediaCont = $("." + mediaId);
212 |
213 | var name = mediaCont.data('name');
214 | var path = $(this).data('path');
215 |
216 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
217 | mediaModalPageCont.data('current-page', 1);
218 |
219 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
220 | mediaModalNavOlCont.data('current-path', path);
221 |
222 | var options = mediaCont.data('options');
223 |
224 | thiz.getdata(name, path, options)
225 | });
226 |
227 | // 分页 - 上一页
228 | this.onEvent("click", '.lake-form-media-modal-prev-page', function() {
229 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
230 | var mediaId = mediaModalCont.data('media');
231 | var mediaCont = $("." + mediaId);
232 |
233 | var name = mediaCont.data('name');
234 |
235 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
236 | var currentPage = mediaModalPageCont.data('current-page');
237 |
238 | currentPage = parseInt(currentPage);
239 | if (currentPage > 1) {
240 | currentPage -= 1;
241 | mediaModalPageCont.data('current-page', currentPage);
242 | } else {
243 | mediaModalPageCont.data('current-page', 1);
244 | }
245 |
246 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
247 | var path = mediaModalNavOlCont.data('current-path');
248 |
249 | var options = mediaCont.data('options');
250 |
251 | thiz.getdata(name, path, options)
252 | });
253 |
254 | // 分页 - 下一页
255 | this.onEvent("click", '.lake-form-media-modal-next-page', function() {
256 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
257 | var mediaId = mediaModalCont.data('media');
258 | var mediaCont = $("." + mediaId);
259 |
260 | var name = mediaCont.data('name');
261 |
262 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
263 | var currentPage = mediaModalPageCont.data('current-page');
264 | var totalPage = mediaModalPageCont.data('total-page');
265 |
266 | currentPage = parseInt(currentPage);
267 | totalPage = parseInt(totalPage);
268 | if (currentPage < totalPage) {
269 | currentPage += 1;
270 | mediaModalPageCont.data('current-page', currentPage);
271 | } else {
272 | mediaModalPageCont.data('current-page', totalPage);
273 | }
274 |
275 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
276 | var path = mediaModalNavOlCont.data('current-path');
277 |
278 | var options = mediaCont.data('options');
279 |
280 | thiz.getdata(name, path, options)
281 | });
282 |
283 | // 页码提示
284 | this.onEvent('mouseover', '.lake-form-media-modal-prev-page,.lake-form-media-modal-next-page', function () {
285 | var pageCont = $(this).parents('.lake-form-media-modal-page');
286 |
287 | var currentPage = pageCont.data('current-page');
288 | var totalPage = pageCont.data('total-page');
289 | var pageSize = pageCont.data('page-size');
290 | var title = thiz.lang("page_render", {
291 | page: currentPage,
292 | total: totalPage,
293 | perpage: pageSize,
294 | });
295 | var idx = layer.tips(title, this, {
296 | tips: [1, '#586cb1'],
297 | time: 0,
298 | maxWidth: 210,
299 | });
300 |
301 | $(this).attr('layer-idx', idx);
302 | });
303 | this.onEvent('mouseleave', '.lake-form-media-modal-prev-page,.lake-form-media-modal-next-page', function () {
304 | layer.close($(this).attr('layer-idx'));
305 |
306 | $(this).attr('layer-idx', '');
307 | });
308 |
309 | // 新建文件夹
310 | this.onEvent('click', ".lake-form-media-dir-button", function(res){
311 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
312 | var mediaId = mediaModalCont.data('media');
313 | var mediaCont = $("." + mediaId);
314 |
315 | var name = mediaCont.data('name');
316 |
317 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
318 | var currentPath = mediaModalNavOlCont.data('current-path');
319 |
320 | var options = mediaCont.data('options');
321 |
322 | var obj = mediaModalCont.find(".lake-form-media-dir-input");
323 | var dir = obj.val();
324 |
325 | if (dir == "") {
326 | toastr.error(thiz.lang("dir_not_empty"));
327 | return false;
328 | }
329 |
330 | var form = new FormData();
331 | form.append("name", dir);
332 | form.append("dir", currentPath);
333 | form.append("disk", options.disk);
334 | form.append("_token", Dcat.token);
335 | $.ajax({
336 | type: 'post',
337 | url: options.create_folder_url,
338 | data: form,
339 | processData: false,
340 | contentType : false,
341 | success: function(data){
342 | if (data['code'] == 200) {
343 | toastr.success(data['msg']);
344 | obj.val('');
345 | thiz.getdata(name, currentPath, options)
346 | } else {
347 | toastr.error(data['msg']);
348 | }
349 | },
350 | error: function(XmlHttpRequest, textStatus, errorThrown){
351 | toastr.error(thiz.lang("create_dir_error"));
352 | }
353 | });
354 | });
355 |
356 | // 上传图片
357 | this.onEvent('change', '.lake-form-media-upload', function() {
358 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
359 | var mediaId = mediaModalCont.data('media');
360 | var mediaCont = $("." + mediaId);
361 |
362 | var name = mediaCont.data('name');
363 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
364 |
365 | var currentPath = mediaModalNavOlCont.data('current-path');
366 | var options = mediaCont.data('options');
367 |
368 | var files = $(this).prop('files');
369 |
370 | var form = new FormData();
371 | for (var i = 0; i < files.length; i++) {
372 | form.append("files[]", files[i]);
373 | }
374 |
375 | form.append("path", currentPath);
376 | form.append("type", options.type);
377 | form.append("disk", options.disk);
378 | form.append("nametype", options.nametype);
379 | form.append("resize", options.resize);
380 | form.append("_token", Dcat.token);
381 | $.ajax({
382 | type: 'post',
383 | url: options.upload_url,
384 | data: form,
385 | processData: false,
386 | contentType : false,
387 | success: function(data){
388 | if (data['code'] == 200) {
389 | toastr.success(data['msg']);
390 | thiz.getdata(name, currentPath, options)
391 | } else {
392 | toastr.error(data['msg']);
393 | }
394 | },
395 | error: function(XmlHttpRequest, textStatus, errorThrown){
396 | toastr.error(thiz.lang("upload_error"));
397 | }
398 | });
399 | });
400 |
401 | // 提交
402 | this.onEvent('click', '.lake-form-media-submit', function(res){
403 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
404 | var mediaId = mediaModalCont.data('media');
405 | var mediaCont = $("." + mediaId);
406 |
407 | var name = mediaCont.data('name');
408 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
409 |
410 | var currentPath = mediaModalNavOlCont.data('current-path');
411 | var options = mediaCont.data('options');
412 |
413 | var inputCont = mediaCont.find('.lake-form-media-input');
414 |
415 | var limit = options.limit;
416 | var type = options.type
417 |
418 | var rootpath = options.rootpath
419 | var saveFullUrl = options.saveFullUrl
420 |
421 | // 可多选时
422 | var multiplechoice = options.multiplechoice
423 |
424 | // 列表
425 | var urlList = [];
426 | var urlListStr = inputCont.val();
427 | if (urlListStr == '[]') {
428 | urlListStr = '';
429 | }
430 |
431 | if (urlListStr) {
432 | if (limit == 1) {
433 | // 去掉预览
434 | thiz.refreshPreview(name, [], options)
435 | } else {
436 | urlList = thiz.isJSON( urlListStr );
437 | }
438 | }
439 |
440 | // 不是多选时
441 | if (multiplechoice != 1 && limit > 1) {
442 | $('.lake-form-media-close').trigger("click");
443 | return false;
444 | }
445 |
446 | if (type == 'blend') {
447 | select_true_list = mediaModalCont
448 | .find('.lake-form-media-selected');
449 | } else {
450 | select_true_list = mediaModalCont
451 | .find('.lake-form-media-selected[data-type="'+type+'"]');
452 | }
453 |
454 | for (var i = 0; i < select_true_list.length; i++) {
455 | var url = $(select_true_list[i]).data('url');
456 |
457 | if (saveFullUrl == 1) {
458 | url = rootpath + url
459 | }
460 |
461 | urlList.push(url);
462 | }
463 |
464 | urlList = thiz.unique(urlList);
465 |
466 | if (limit == 1) {
467 | inputCont.val(urlList[0]);
468 | inputCont.attr("value", urlList[0]);
469 | } else {
470 | // 提交限制数量
471 | var newUrlList = [];
472 |
473 | if (urlList.length < limit) {
474 | limit = urlList.length;
475 | }
476 |
477 | for (var i = 0; i < limit; i++) {
478 | newUrlList.push(urlList[i]);
479 | }
480 | urlList = newUrlList;
481 |
482 | urlListJson = JSON.stringify( urlList );
483 | if (urlListJson == '[]') {
484 | $('#LakeFormMediaModel'+name).modal('hide');
485 | return null;
486 | }
487 | inputCont.val(urlListJson);
488 | inputCont.attr("value", urlListJson);
489 | }
490 |
491 | thiz.refreshPreview(name, urlList, options)
492 | $('#LakeFormMediaModel'+name).modal('hide');
493 | });
494 |
495 | // 选中点击
496 | this.onEvent("click", ".lake-form-media-field-item-op", function(){
497 | var mediaModalCont = $(this).parents('.lake-form-media-modal');
498 | var mediaId = mediaModalCont.data('media');
499 | var mediaCont = $("." + mediaId);
500 |
501 | var itemType = $(this).data('type');
502 |
503 | var name = mediaCont.data('name');
504 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
505 |
506 | var currentPath = mediaModalNavOlCont.data('current-path');
507 | var options = mediaCont.data('options');
508 |
509 | var inputCont = mediaCont.find('.lake-form-media-input');
510 |
511 | var type = options.type;
512 | var limit = options.limit;
513 |
514 | // 可多选时
515 | var multiplechoice = options.multiplechoice
516 |
517 | if (type != 'blend') {
518 | if (type != itemType) {
519 | return false;
520 | }
521 | }
522 |
523 | // 现有多少张
524 | var nowNumVal = inputCont.val();
525 | if (nowNumVal == '[]') {
526 | nowNumVal = '';
527 | }
528 | var nowNumArr = [];
529 | if (nowNumVal) {
530 | if (limit == 1) {
531 | nowNumArr.push(nowNumVal)
532 | } else {
533 | nowNumArr = thiz.isJSON( nowNumVal );
534 | }
535 | }
536 |
537 | // 不是多选时
538 | if (multiplechoice != 1 && limit > 1) {
539 | // 添加当前选中
540 | nowNumArr.push($(this).data('url'));
541 |
542 | if (nowNumArr.length > limit) {
543 | toastr.error(thiz.lang("selected_error", {
544 | num: limit,
545 | }));
546 | return 1;
547 | }
548 |
549 | urlListJson = JSON.stringify(nowNumArr);
550 | if (urlListJson == '[]') {
551 | $('#LakeFormMediaModel'+name).modal('hide');
552 | return null;
553 | }
554 | inputCont.val(urlListJson);
555 | inputCont.attr("value", urlListJson);
556 |
557 | thiz.refreshPreview(name, nowNumArr, options)
558 | $('#LakeFormMediaModel'+name).modal('hide');
559 |
560 | return false;
561 | }
562 |
563 | var noNeedSelectArr = [];
564 | if (type != 'blend') {
565 | var imgItem = mediaModalCont.find('.lake-form-media-field-item[data-type="'+itemType+'"]');
566 | } else {
567 | var imgItem = mediaModalCont.find('.lake-form-media-field-item');
568 | }
569 | for (var i = 0; i < imgItem.length; i++) {
570 | var itemUrl = $(imgItem[i]).data('url');
571 | if ($.inArray(itemUrl, nowNumArr) != -1) {
572 | noNeedSelectArr.push(itemUrl);
573 | }
574 | }
575 | var selectedItem = mediaModalCont.find('.lake-form-media-selected');
576 |
577 | var selectNum = nowNumArr.length - noNeedSelectArr.length + selectedItem.length;
578 |
579 | var tag = $(this).hasClass('lake-form-media-selected');
580 |
581 | if (tag) {
582 | // 取消选中
583 | $(this).removeClass('lake-form-media-selected');
584 | } else {
585 | // 选中
586 | if (limit == 1) {
587 | // 取消之前选中的
588 | mediaModalCont
589 | .find('.lake-form-media-selected')
590 | .removeClass('lake-form-media-selected')
591 | } else {
592 | if (selectNum >= limit) {
593 | toastr.error(thiz.lang("selected_error", {
594 | num: limit,
595 | }));
596 | return 1;
597 | }
598 | }
599 |
600 | $(this).addClass('lake-form-media-selected');
601 | }
602 |
603 | return 1;
604 | });
605 |
606 | // 图片/视频预览
607 | this.onEvent('click', ".lake-form-media-img-show-item-preview", function() {
608 | var type = $(this).data('type');
609 | var url = $(this).data('url');
610 |
611 | var preview = '';
612 | var height = '85%';
613 | if (type == 'image') {
614 | preview = '
';
615 | } else if (type == 'video') {
616 | preview = '';
617 | } else if (type == 'audio') {
618 | height = 'auto';
619 | preview = '';
620 | }
621 |
622 | layer.open({
623 | type: 1,
624 | area: ['auto', height],
625 | title: thiz.lang("preview_title"),
626 | end: function(index, layero) {
627 | return false;
628 | },
629 | content: ''+preview+'
',
630 | });
631 | });
632 | },
633 |
634 | onEvent: function(bind, elements, callback) {
635 | return $("body").off(bind, elements)
636 | .on(bind, elements, callback);
637 | },
638 |
639 | getdata: function(name, path = '/', options = []) {
640 | var mediaCont = $('.lake-form-media-' + name);
641 |
642 | var type = options.type;
643 | var disk = options.disk;
644 | var limit = options.limit;
645 | var remove = options.remove;
646 | var pageSize = options.pagesize;
647 |
648 | var mediaModalCont = $('#LakeFormMediaModel' + name);
649 | var mediaModalTableCont = mediaModalCont.find('.lake-form-media-body-table');
650 | var mediaModalNavOlCont = mediaModalCont.find('.lake-form-media-nav-ol');
651 | var mediaModalPageCont = mediaModalCont.find('.lake-form-media-modal-page');
652 | var mediaModalOrderCont = mediaModalCont.find('.lake-form-media-modal-order');
653 |
654 | var inputCont = mediaCont.find('.lake-form-media-input');
655 |
656 | var order = mediaModalOrderCont.data('order');
657 | var currentPath = mediaModalNavOlCont.data('current-path');
658 | var currentPage = mediaModalPageCont.data('current-page');
659 | var pageSize = mediaModalPageCont.data('page-size');
660 |
661 | var thiz = this;
662 |
663 | var baseUrl = options.get_files_url;
664 | if (baseUrl.indexOf("?") == -1) {
665 | baseUrl = baseUrl + "?";
666 | } else {
667 | baseUrl = baseUrl + "&";
668 | }
669 |
670 | $.ajax({
671 | url: baseUrl
672 | + "path=" + path
673 | + "&type=" + type
674 | + "&disk=" + disk
675 | + "&order=" + order
676 | + "&page=" + currentPage
677 | + "&pageSize=" + pageSize,
678 | method: 'GET',
679 | datatype:'json',
680 | async: true,
681 | success: function (res) {
682 | var list = res['data']['list'];
683 | var nav = res['data']['nav'];
684 |
685 | mediaModalTableCont.html('');
686 | if (JSON.stringify(list) != '[]') {
687 | for (var i in list) {
688 | if (list[i]['isDir']) {
689 | var htmltemp = '';
690 | htmltemp += '';
691 | htmltemp += '
';
697 | htmltemp += '
';
698 | mediaModalTableCont.append(htmltemp);
699 | } else {
700 | var htmltemp = '';
701 | htmltemp += '';
702 |
703 | htmltemp += '
';
709 | htmltemp += '
';
710 |
711 | mediaModalTableCont.append(htmltemp);
712 | }
713 | }
714 |
715 | } else {
716 | var htmltemp = '' + thiz.lang("empty") + '
';
717 | mediaModalTableCont.append(htmltemp);
718 | }
719 |
720 | mediaModalNavOlCont.html(' ');
721 | mediaModalNavOlCont.data('current-path', '/');
722 | for (var i = 0; i < nav.length; i++) {
723 | mediaModalNavOlCont.append(' '+nav[i]['name']+'');
724 | mediaModalNavOlCont.data('current-path', nav[i]['url']);
725 | }
726 |
727 | var urlListStr = inputCont.val();
728 | var urlList = [];
729 | if (limit == 1) {
730 | var urlLists = thiz.isJSON(urlListStr);
731 | if (urlLists.length > 0) {
732 | mediaModalTableCont.find('[data-url="'+urlLists[0]+'"]')
733 | .addClass('lake-form-media-selected');
734 | }
735 | } else {
736 | urlList = thiz.isJSON( urlListStr );
737 | for (var index in urlList) {
738 | mediaModalTableCont.find('[data-url="'+urlList[index]+'"]')
739 | .addClass('lake-form-media-selected');
740 | }
741 | }
742 |
743 | var totalPage = parseInt(res['data']['total_page']);
744 | var currentPage = parseInt(res['data']['current_page']);
745 | var perPage = parseInt(res['data']['per_page']);
746 |
747 | mediaModalPageCont.data('current-page', currentPage);
748 | mediaModalPageCont.data('total-page', totalPage);
749 |
750 | if (totalPage > 1) {
751 | if (currentPage > 1) {
752 | mediaModalPageCont.find('.lake-form-media-modal-prev-page').removeClass('hidden');
753 | } else {
754 | mediaModalPageCont.find('.lake-form-media-modal-prev-page').addClass('hidden');
755 | }
756 |
757 | if (currentPage < totalPage) {
758 | mediaModalPageCont.find('.lake-form-media-modal-next-page').removeClass('hidden');
759 | } else {
760 | mediaModalPageCont.find('.lake-form-media-modal-next-page').addClass('hidden');
761 | }
762 | } else {
763 | mediaModalPageCont.find('.lake-form-media-modal-prev-page').addClass('hidden');
764 | mediaModalPageCont.find('.lake-form-media-modal-next-page').addClass('hidden');
765 | }
766 |
767 | },
768 | error: function(XmlHttpRequest, textStatus, errorThrown){
769 | toastr.error(thiz.lang("getdata_error"));
770 | },
771 | cache: false,
772 | contentType: false,
773 | processData: false
774 | });
775 | },
776 |
777 | // 刷新表单预览
778 | refreshInputPreview: function(cont) {
779 | var mediaCont = $(cont).parents('.lake-form-media');
780 | var name = mediaCont.data('name');
781 |
782 | var mediaModalCont = $('#LakeFormMediaModel' + name);
783 |
784 | var value = $(cont).val();
785 |
786 | var options = mediaCont.data('options');
787 | options = $.extend({}, options);
788 |
789 | var limit = options.limit;
790 |
791 | var valueArr = [];
792 | if (limit > 1) {
793 | if (value != "") {
794 | valueArr = this.isJSON(value);
795 | }
796 | } else {
797 | if (value != '[]' && value != '') {
798 | valueArr.push(value)
799 | }
800 | }
801 | this.refreshPreview(name, valueArr, options);
802 |
803 | if (value == "") {
804 | mediaModalCont
805 | .find('.lake-form-media-img-show')
806 | .hide();
807 | }
808 | },
809 |
810 | // 刷新表单数据
811 | refreshInputString: function(name) {
812 | var mediaCont = $('.lake-form-media-'+name);
813 | var inputCont = mediaCont.find('.lake-form-media-input');
814 |
815 | var urlList = [];
816 | mediaCont.find('.lake-form-media-preview-item')
817 | .each(function(i, cont) {
818 | urlList.push($(cont).data('src'));
819 | });
820 |
821 | var inputString = JSON.stringify( urlList );
822 | if (inputString == '[]' || inputString == '[""]') {
823 | inputString = '';
824 | }
825 |
826 | inputCont.val(inputString);
827 | },
828 |
829 | // 刷新/显示 预览
830 | refreshPreview: function(name, urlList, options = []) {
831 | var thiz = this;
832 |
833 | var limit = options.limit;
834 | var remove = options.remove;
835 | var rootpath = options.rootpath;
836 | var showtitle = options.showtitle;
837 | var showicon = options.showicon;
838 |
839 | var saveFullUrl = options.saveFullUrl;
840 |
841 | var mediaCont = $('.lake-form-media-'+name);
842 | var imgShowCont = mediaCont.find('.lake-form-media-img-show');
843 | var imgShowRowCont = mediaCont.find('.lake-form-media-img-show-row');
844 |
845 | imgShowRowCont.html('');
846 | if (urlList.length > 0) {
847 | imgShowCont.show();
848 | } else {
849 | imgShowCont.hide();
850 | }
851 |
852 | for (var i = 0; i < urlList.length; i++) {
853 | var src = urlList[i];
854 | if (! this.isUrl(src)) {
855 | if (saveFullUrl != 1) {
856 | src = rootpath + urlList[i];
857 | }
858 | }
859 |
860 | var html = '';
898 |
899 | imgShowRowCont.append(html);
900 | }
901 | },
902 |
903 | unique: function (arr){
904 | var hash = [];
905 | for (var i = 0; i < arr.length; i++) {
906 | if(hash.indexOf(arr[i])==-1){
907 | hash.push(arr[i]);
908 | }
909 | }
910 |
911 | return hash;
912 | },
913 |
914 | isJSON: function(str) {
915 | if (typeof str == 'string') {
916 | try {
917 | return JSON.parse(str);
918 | } catch(e) {
919 | return [str];
920 | }
921 | }
922 | return [];
923 | },
924 |
925 | isUrl: function(url) {
926 | if (url.substr(0, 7).toLowerCase() == "http://"
927 | || url.substr(0, 8).toLowerCase() == "https://"
928 | || url.substr(0, 2).toLowerCase() == "//"
929 | ) {
930 | return true;
931 | }
932 |
933 | return false;
934 | },
935 |
936 | // 判断是否是 object
937 | isObj: function(object) {
938 | return object
939 | && typeof (object) == 'object'
940 | && Object.prototype
941 | .toString.call(object)
942 | .toLowerCase() == "[object object]";
943 | },
944 |
945 | // 判断是否是 array
946 | isArray: function(object) {
947 | return Object.prototype
948 | .toString.call(object)
949 | .toLowerCase() === '[object array]';
950 | },
951 |
952 | getFileSuffix: function (src) {
953 | try {
954 | var srcArr = src.split('.');
955 | var suffix = srcArr[srcArr.length - 1];
956 | } catch(err) {
957 | var suffix = '';
958 | }
959 |
960 | if (suffix) {
961 | var type = this.getFileType(suffix.toLocaleLowerCase());
962 | } else {
963 | var type = '';
964 | }
965 |
966 | return type;
967 | },
968 |
969 | getFileExt: function (filename) {
970 | try {
971 | var srcArr = filename.split('.');
972 | var ext = srcArr[srcArr.length - 1];
973 | } catch(err) {
974 | var ext = '';
975 | }
976 |
977 | return ext;
978 | },
979 |
980 | getFileDisplay: function (src) {
981 | var type = this.getFileSuffix(src);
982 |
983 | var html = '';
984 | if (type === 'image') {
985 | html += '
';
986 | } else if (type === 'video') {
987 | // html += '';
988 | html += '';
989 | } else if (type === 'audio') {
990 | html += '';
991 | } else if (type === 'pdf') {
992 | html += '';
993 | } else if (type === 'word') {
994 | html += '';
995 | } else if (type === 'ppt') {
996 | html += '';
997 | } else if (type === 'xls') {
998 | html += '';
999 | } else if (type === 'text') {
1000 | html += '';
1001 | } else if (type === 'code') {
1002 | html += '';
1003 | } else if (type === 'zip') {
1004 | html += '';
1005 | } else {
1006 | html += '';
1007 | }
1008 |
1009 | return html;
1010 | },
1011 |
1012 | getFileShowType: function (src) {
1013 | var type = this.getFileSuffix(src);
1014 |
1015 | var html = '';
1016 | if (type === 'image') {
1017 | html += '';
1018 | } else if (type === 'video') {
1019 | html += '';
1020 | } else if (type === 'audio') {
1021 | html += '';
1022 | } else if (type === 'pdf') {
1023 | html += '';
1024 | } else if (type === 'word') {
1025 | html += '';
1026 | } else if (type === 'ppt') {
1027 | html += '';
1028 | } else if (type === 'xls') {
1029 | html += '';
1030 | } else if (type === 'text') {
1031 | html += '';
1032 | } else if (type === 'code') {
1033 | html += '';
1034 | } else if (type === 'zip') {
1035 | html += '';
1036 | } else {
1037 | html += '';
1038 | }
1039 |
1040 | return html;
1041 | },
1042 |
1043 | getFileType: function (suffix) {
1044 | // 匹配图片
1045 | var image = [
1046 | 'jpeg', 'jpg', 'bmp', 'png', 'svg', 'wbmp', 'pic',
1047 | 'cgm', 'djv', 'djvu', 'gif', 'ico', 'ief', 'jp2',
1048 | 'jpe', 'mac', 'pbm', 'pct', 'pgm', 'pict', 'pnm',
1049 | 'pnt', 'pntg', 'ppm', 'qti', 'qtif', 'ras', 'rgb',
1050 | 'tif', 'tiff', 'xbm', 'xpm', 'xwd', 'avif'
1051 | ];
1052 |
1053 | // 匹配视频
1054 | var video = [
1055 | 'mkv', 'avi', 'mp4', 'rmvb', 'rm',
1056 | 'flv', 'wmv', 'asf', 'mpeg', 'mov'
1057 | ];
1058 |
1059 | // 匹配音频
1060 | var audio = [
1061 | 'mp3', 'wav', 'flac', '3pg', 'aa', 'aac', 'ape',
1062 | 'au', 'm4a', 'mpc', 'ogg'
1063 | ];
1064 |
1065 | // 匹配 pdf
1066 | var pdf = [
1067 | 'pdf'
1068 | ];
1069 |
1070 | // 匹配 word
1071 | var word = [
1072 | 'doc', 'dot', 'docx', 'dotx', 'docm', 'dotm', 'wps'
1073 | ];
1074 |
1075 | // 匹配 ppt
1076 | var ppt = [
1077 | 'ppt', 'pptx', 'pptm', 'pot', 'pps', 'ppa', 'pptx',
1078 | 'potx', 'ppsx', 'ppam', 'potm', 'ppsm'
1079 | ];
1080 |
1081 | // 匹配 xls
1082 | var xls = [
1083 | 'xls', 'xlt', 'xla', 'xlsx', 'xltx', 'xlsm',
1084 | 'xltm', 'xlam', 'xlsb'
1085 | ];
1086 |
1087 | // 匹配文本
1088 | var text = [
1089 | 'txt', 'pac', 'log', 'md'
1090 | ];
1091 |
1092 | // 匹配代码
1093 | var code = [
1094 | 'html', 'htm', 'js', 'css', 'vue', 'json',
1095 | 'php', 'java', 'go', 'py', 'ruby', 'rb',
1096 | 'aspx', 'asp', 'c', 'cpp', 'sql', 'm', 'h',
1097 | 'python', 'ruby', 'rs', 'zig', 'v'
1098 | ];
1099 |
1100 | // 匹配压缩包
1101 | var zip = [
1102 | 'zip', 'tar', 'gz', 'rar', 'rpm'
1103 | ];
1104 |
1105 | var list = {
1106 | 'image': image,
1107 | 'video': video,
1108 | 'audio': audio,
1109 | 'pdf': pdf,
1110 | 'word': word,
1111 | 'ppt': ppt,
1112 | 'xls': xls,
1113 | 'text': text,
1114 | 'code': code,
1115 | 'zip': zip,
1116 | }
1117 |
1118 | for (var key in list) {
1119 | if (list[key].indexOf(suffix) != -1) {
1120 | return key;
1121 | }
1122 | };
1123 |
1124 | return "other";
1125 | },
1126 |
1127 | // 复制
1128 | copyData: function(data) {
1129 | let target = document.createElement('div');
1130 | target.id = 'tempTarget';
1131 | target.style.opacity = '0';
1132 | target.innerText = data;
1133 | document.body.appendChild(target);
1134 |
1135 | try {
1136 | let range = document.createRange();
1137 | range.selectNode(target);
1138 | window.getSelection().removeAllRanges();
1139 | window.getSelection().addRange(range);
1140 | document.execCommand('copy');
1141 | window.getSelection().removeAllRanges();
1142 |
1143 | layer.msg(this.lang("copy_success"));
1144 | } catch (e) {
1145 | layer.msg(this.lang("copy_error"));
1146 | }
1147 |
1148 | target.parentElement.removeChild(target);
1149 | },
1150 |
1151 | // 翻译
1152 | lang: function () {
1153 | var args = arguments,
1154 | string = args[0],
1155 | i = 1;
1156 |
1157 | var thiz = this;
1158 |
1159 | // 语言包
1160 | var Lang = window.LakeFormMediaLang;
1161 |
1162 | string = string.toLowerCase();
1163 | if (typeof Lang !== 'undefined' && typeof Lang[string] !== 'undefined') {
1164 | if (typeof Lang[string] == 'object') {
1165 | return Lang[string];
1166 | }
1167 |
1168 | string = Lang[string];
1169 | } else if (string.indexOf('.') !== -1 && false) {
1170 | var arr = string.split('.');
1171 | var current = Lang[arr[0]];
1172 |
1173 | for (var i = 1; i < arr.length; i++) {
1174 | current = typeof current[arr[i]] != 'undefined'
1175 | ? current[arr[i]]
1176 | : '';
1177 | if (typeof current != 'object') {
1178 | break;
1179 | }
1180 | }
1181 |
1182 | if (typeof current == 'object') {
1183 | return current;
1184 | }
1185 |
1186 | string = current;
1187 | } else {
1188 | string = args[0];
1189 | }
1190 |
1191 | // 原始按序替换
1192 | string = string.replace(/%((%)|s|d)/g, function (m) {
1193 | // m 是匹配到的格式, e.g. %s, %d
1194 | var val = null;
1195 |
1196 | if (m[2]) {
1197 | val = m[2];
1198 | } else {
1199 | val = args[i];
1200 | // 默认是 %s
1201 | switch (m) {
1202 | case '%d':
1203 | val = parseFloat(val);
1204 | if (isNaN(val)) {
1205 | val = 0;
1206 | }
1207 | break;
1208 | }
1209 | i++;
1210 | }
1211 |
1212 | return val;
1213 | });
1214 |
1215 | // 键值翻译
1216 | string = string.replace(/:([a-zA-Z0-9:\-\_]+)/g, function (m) {
1217 | if (args.length < 2) {
1218 | return m;
1219 | }
1220 |
1221 | if (m[1] && m[1] == ":") {
1222 | return m.substr(1);
1223 | }
1224 |
1225 | // 默认
1226 | var val = null;
1227 |
1228 | // 翻译数据
1229 | var data = args[1];
1230 |
1231 | // 对象判断
1232 | if (! thiz.isObj(data)) {
1233 | return m;
1234 | }
1235 |
1236 | // 键值
1237 | var key = m.substr(1);
1238 |
1239 | // 键值判断
1240 | if (! (key in data)) {
1241 | return m;
1242 | }
1243 |
1244 | // 设置值
1245 | val = data[key];
1246 |
1247 | return val;
1248 | });
1249 |
1250 | return string;
1251 | },
1252 | }
1253 |
1254 | LakeFormMedia.init();
1255 |
1256 | window.LakeFormMedia = LakeFormMedia;
1257 | });
1258 |
1259 |
--------------------------------------------------------------------------------
/resources/assets/jquery.dragsort.js:
--------------------------------------------------------------------------------
1 | // jQuery List DragSort v0.5.5
2 | // Website: http://dragsort.codeplex.com/
3 | // License: http://dragsort.codeplex.com/license
4 |
5 | // update deatil
6 | // date 20201128
7 |
8 | !(function(a){
9 | if ("function" == typeof define&&define.amd) {
10 | define(["jquery"], a);
11 | } else if ("object" == typeof exports) {
12 | a(require("jquery"));
13 | } else {
14 | a(jQuery);
15 | }
16 | })(function($) {
17 |
18 | $.fn.dragsort = function(options) {
19 | if (options == "destroy") {
20 | $(this.selector).trigger("dragsort-uninit");
21 | return;
22 | }
23 |
24 | var opts = $.extend({}, $.fn.dragsort.defaults, options);
25 | var lists = [];
26 | var list = null, lastPos = null;
27 |
28 | this.each(function(i, cont) {
29 |
30 | //if list container is table, the browser automatically wraps rows in tbody if not specified so change list container to tbody so that children returns rows as user expected
31 | if ($(cont).is("table") && $(cont).children().length == 1 && $(cont).children().is("tbody"))
32 | cont = $(cont).children().get(0);
33 |
34 | var newList = {
35 | draggedItem: null,
36 | placeHolderItem: null,
37 | pos: null,
38 | offset: null,
39 | offsetLimit: null,
40 | scroll: null,
41 | container: cont,
42 |
43 | init: function() {
44 | //set options to default values if not set
45 | opts.tagName = opts.tagName == "" ? ($(this.container).children().length == 0 ? "li" : $(this.container).children().get(0).tagName.toLowerCase()) : opts.tagName;
46 | if (opts.itemSelector == "")
47 | opts.itemSelector = opts.tagName;
48 | if (opts.dragSelector == "")
49 | opts.dragSelector = opts.tagName;
50 | if (opts.placeHolderTemplate == "")
51 | opts.placeHolderTemplate = "<" + opts.tagName + "> " + opts.tagName + ">";
52 |
53 | //listidx allows reference back to correct list variable instance
54 | $(this.container).attr("data-listidx", i).mousedown(this.grabItem).bind("dragsort-uninit", this.uninit);
55 | this.styleDragHandlers(true);
56 | },
57 |
58 | uninit: function() {
59 | var list = lists[$(this).attr("data-listidx")];
60 | $(list.container).unbind("mousedown", list.grabItem).unbind("dragsort-uninit");
61 | list.styleDragHandlers(false);
62 | },
63 |
64 | getItems: function() {
65 | return $(this.container).children(opts.itemSelector);
66 | },
67 |
68 | styleDragHandlers: function(cursor) {
69 | this.getItems().map(function() { return $(this).is(opts.dragSelector) ? this : $(this).find(opts.dragSelector).get(); }).css("cursor", cursor ? "pointer" : "");
70 | },
71 |
72 | grabItem: function(e) {
73 | var list = lists[$(this).attr("data-listidx")];
74 | var item = $(e.target).closest("[data-listidx] > " + opts.tagName).get(0);
75 | var insideMoveableItem = list.getItems().filter(function() { return this == item; }).length > 0;
76 |
77 | //if not left click or if clicked on excluded element (e.g. text box) or not a moveable list item return
78 | if (e.which != 1 || $(e.target).is(opts.dragSelectorExclude) || $(e.target).closest(opts.dragSelectorExclude).length > 0 || !insideMoveableItem)
79 | return;
80 |
81 | //prevents selection, stops issue on Fx where dragging hyperlink doesn't work and on IE where it triggers mousemove even though mouse hasn't moved,
82 | //does also stop being able to click text boxes hence dragging on text boxes by default is disabled in dragSelectorExclude
83 | //e.preventDefault();
84 |
85 | //change cursor to move while dragging
86 | var dragHandle = e.target;
87 | while (!$(dragHandle).is(opts.dragSelector)) {
88 | if (dragHandle == this) return;
89 | dragHandle = dragHandle.parentNode;
90 | }
91 | $(dragHandle).attr("data-cursor", $(dragHandle).css("cursor"));
92 | $(dragHandle).css("cursor", "move");
93 |
94 | //on mousedown wait for movement of mouse before triggering dragsort script (dragStart) to allow clicking of hyperlinks to work
95 | var listElem = this;
96 | var trigger = function() {
97 | list.dragStart.call(listElem, e);
98 | $(list.container).unbind("mousemove", trigger);
99 | };
100 | $(list.container).mousemove(trigger).mouseup(function() { $(list.container).unbind("mousemove", trigger); $(dragHandle).css("cursor", $(dragHandle).attr("data-cursor")); });
101 | },
102 |
103 | dragStart: function(e) {
104 | if (list != null && list.draggedItem != null)
105 | list.dropItem();
106 |
107 | list = lists[$(this).attr("data-listidx")];
108 | list.draggedItem = $(e.target).closest("[data-listidx] > " + opts.tagName)
109 |
110 | //record current position so on dragend we know if the dragged item changed position or not, not using getItems to allow dragsort to restore dragged item to original location in relation to fixed items
111 | list.draggedItem.attr("data-origpos", $(this).attr("data-listidx") + "-" + $(list.container).children().index(list.draggedItem));
112 |
113 | //calculate mouse offset relative to draggedItem
114 | var mt = parseInt(list.draggedItem.css("marginTop"));
115 | var ml = parseInt(list.draggedItem.css("marginLeft"));
116 | list.offset = list.draggedItem.offset();
117 | list.offset.top = e.pageY - list.offset.top + (isNaN(mt) ? 0 : mt) - 1;
118 | list.offset.left = e.pageX - list.offset.left + (isNaN(ml) ? 0 : ml) - 1;
119 |
120 | //calculate box the dragged item can't be dragged outside of
121 | if (!opts.dragBetween) {
122 | var containerHeight = $(list.container).outerHeight() == 0 ? Math.max(1, Math.round(0.5 + list.getItems().length * list.draggedItem.outerWidth() / $(list.container).outerWidth())) * list.draggedItem.outerHeight() : $(list.container).outerHeight();
123 | list.offsetLimit = $(list.container).offset();
124 | list.offsetLimit.right = list.offsetLimit.left + $(list.container).outerWidth() - list.draggedItem.outerWidth();
125 | list.offsetLimit.bottom = list.offsetLimit.top + containerHeight - list.draggedItem.outerHeight();
126 | }
127 |
128 | //create placeholder item
129 | var h = list.draggedItem.height();
130 | var w = list.draggedItem.width();
131 | if (opts.tagName == "tr") {
132 | list.draggedItem.children().each(function() { $(this).width($(this).width()); });
133 | list.placeHolderItem = list.draggedItem.clone().attr("data-placeholder", true);
134 | list.draggedItem.after(list.placeHolderItem);
135 | //list.placeHolderItem.children().each(function() { $(this).css({ borderWidth:0, width: $(this).width() + 1, height: $(this).height() + 1 }).html(" "); });
136 | list.placeHolderItem.children().each(function() { $(this).html(" "); });
137 | } else {
138 | list.draggedItem.after(opts.placeHolderTemplate);
139 | list.placeHolderItem = list.draggedItem.next().css({ height: h, width: w }).attr("data-placeholder", true);
140 | }
141 |
142 | if (opts.tagName == "td") {
143 | var listTable = list.draggedItem.closest("table").get(0);
144 | $("").appendTo("body").children().append(list.draggedItem);
145 | }
146 |
147 | //style draggedItem while dragging
148 | var orig = list.draggedItem.attr("style");
149 | list.draggedItem.attr("data-origstyle", orig ? orig : "");
150 | list.draggedItem.css({ position: "absolute", opacity: 0.8, "z-index": 999, height: h, width: w });
151 |
152 | //auto-scroll setup
153 | list.scroll = { moveX: 0, moveY: 0, maxX: $(document).width() - $(window).width(), maxY: $(document).height() - $(window).height() };
154 | list.scroll.scrollY = window.setInterval(function() {
155 | if (opts.scrollContainer != window) {
156 | $(opts.scrollContainer).scrollTop($(opts.scrollContainer).scrollTop() + list.scroll.moveY);
157 | return;
158 | }
159 | var t = $(opts.scrollContainer).scrollTop();
160 | if (list.scroll.moveY > 0 && t < list.scroll.maxY || list.scroll.moveY < 0 && t > 0) {
161 | $(opts.scrollContainer).scrollTop(t + list.scroll.moveY);
162 | list.draggedItem.css("top", list.draggedItem.offset().top + list.scroll.moveY + 1);
163 | }
164 | }, 10);
165 | list.scroll.scrollX = window.setInterval(function() {
166 | if (opts.scrollContainer != window) {
167 | $(opts.scrollContainer).scrollLeft($(opts.scrollContainer).scrollLeft() + list.scroll.moveX);
168 | return;
169 | }
170 | var l = $(opts.scrollContainer).scrollLeft();
171 | if (list.scroll.moveX > 0 && l < list.scroll.maxX || list.scroll.moveX < 0 && l > 0) {
172 | $(opts.scrollContainer).scrollLeft(l + list.scroll.moveX);
173 | list.draggedItem.css("left", list.draggedItem.offset().left + list.scroll.moveX + 1);
174 | }
175 | }, 10);
176 |
177 | //misc
178 | $(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
179 | list.setPos(e.pageX, e.pageY);
180 | $(document).bind("mousemove", list.swapItems);
181 | $(document).bind("mouseup", list.dropItem);
182 | if (opts.scrollContainer != window)
183 | $(window).bind("wheel", list.wheel);
184 | },
185 |
186 | //set position of draggedItem
187 | setPos: function(x, y) {
188 | //remove mouse offset so mouse cursor remains in same place on draggedItem instead of top left corner
189 | var top = y - this.offset.top;
190 | var left = x - this.offset.left;
191 |
192 | //limit top, left to within box draggedItem can't be dragged outside of
193 | if (!opts.dragBetween) {
194 | top = Math.min(this.offsetLimit.bottom, Math.max(top, this.offsetLimit.top));
195 | left = Math.min(this.offsetLimit.right, Math.max(left, this.offsetLimit.left));
196 | }
197 |
198 | //adjust top & left calculations to parent offset
199 | var parent = this.draggedItem.offsetParent().not("body").offset(); //offsetParent returns body even when it's static, if not static offset is only factoring margin
200 | if (parent != null) {
201 | top -= parent.top;
202 | left -= parent.left;
203 | }
204 |
205 | //set x or y auto-scroll amount
206 | if (opts.scrollContainer == window) {
207 | y -= $(window).scrollTop();
208 | x -= $(window).scrollLeft();
209 | y = Math.max(0, y - $(window).height() + 5) + Math.min(0, y - 5);
210 | x = Math.max(0, x - $(window).width() + 5) + Math.min(0, x - 5);
211 | } else {
212 | var cont = $(opts.scrollContainer);
213 | var offset = cont.offset();
214 | y = Math.max(0, y - cont.height() - offset.top) + Math.min(0, y - offset.top);
215 | x = Math.max(0, x - cont.width() - offset.left) + Math.min(0, x - offset.left);
216 | }
217 |
218 | list.scroll.moveX = x == 0 ? 0 : x * opts.scrollSpeed / Math.abs(x);
219 | list.scroll.moveY = y == 0 ? 0 : y * opts.scrollSpeed / Math.abs(y);
220 |
221 | //move draggedItem to new mouse cursor location
222 | this.draggedItem.css({ top: top, left: left });
223 | },
224 |
225 | //if scroll container is a div allow mouse wheel to scroll div instead of window when mouse is hovering over
226 | wheel: function(e) {
227 | if (list && opts.scrollContainer != window) {
228 | var cont = $(opts.scrollContainer);
229 | var offset = cont.offset();
230 | e = e.originalEvent;
231 | if (e.clientX > offset.left && e.clientX < offset.left + cont.width() && e.clientY > offset.top && e.clientY < offset.top + cont.height()) {
232 | var deltaY = (e.deltaMode == 0 ? 1 : 10) * e.deltaY;
233 | cont.scrollTop(cont.scrollTop() + deltaY);
234 | e.preventDefault();
235 | }
236 | }
237 | },
238 |
239 | //build a table recording all the positions of the moveable list items
240 | buildPositionTable: function() {
241 | var pos = [];
242 | this.getItems().not([list.draggedItem[0], list.placeHolderItem[0]]).each(function(i) {
243 | var loc = $(this).offset();
244 | loc.right = loc.left + $(this).outerWidth();
245 | loc.bottom = loc.top + $(this).outerHeight();
246 | loc.elm = this;
247 | pos[i] = loc;
248 | });
249 | this.pos = pos;
250 | },
251 |
252 | dropItem: function() {
253 | if (list.draggedItem == null)
254 | return;
255 |
256 | //list.draggedItem.attr("style", "") doesn't work on IE8 and jQuery 1.5 or lower
257 | //list.draggedItem.removeAttr("style") doesn't work on chrome and jQuery 1.6 (works jQuery 1.5 or lower)
258 | var orig = list.draggedItem.attr("data-origstyle");
259 | list.draggedItem.attr("style", orig);
260 | if (orig == "")
261 | list.draggedItem.removeAttr("style");
262 | list.draggedItem.removeAttr("data-origstyle");
263 |
264 | list.styleDragHandlers(true);
265 |
266 | list.placeHolderItem.before(list.draggedItem);
267 | list.placeHolderItem.remove();
268 |
269 | $("[data-droptarget], .dragSortItem").remove();
270 |
271 | window.clearInterval(list.scroll.scrollY);
272 | window.clearInterval(list.scroll.scrollX);
273 |
274 | //if position changed call dragEnd
275 | if (list.draggedItem.attr("data-origpos") != $(lists).index(list) + "-" + $(list.container).children().index(list.draggedItem))
276 | if (opts.dragEnd.apply(list.draggedItem) == false) { //if dragEnd returns false revert order
277 | var pos = list.draggedItem.attr("data-origpos").split('-');
278 | var nextItem = $(lists[pos[0]].container).children().not(list.draggedItem).eq(pos[1]);
279 | if (nextItem.length > 0)
280 | nextItem.before(list.draggedItem);
281 | else if (pos[1] == 0) //was the only item in list
282 | $(lists[pos[0]].container).prepend(list.draggedItem);
283 | else //was the last item in list
284 | $(lists[pos[0]].container).append(list.draggedItem);
285 | }
286 | list.draggedItem.removeAttr("data-origpos");
287 |
288 | list.draggedItem = null;
289 | $(document).unbind("mousemove", list.swapItems);
290 | $(document).unbind("mouseup", list.dropItem);
291 | if (opts.scrollContainer != window)
292 | $(window).unbind("wheel", list.wheel);
293 | return false;
294 | },
295 |
296 | //swap the draggedItem (represented visually by placeholder) with the list item the it has been dragged on top of
297 | swapItems: function(e) {
298 | if (list.draggedItem == null)
299 | return false;
300 |
301 | //move draggedItem to mouse location
302 | list.setPos(e.pageX, e.pageY);
303 |
304 | //retrieve list and item position mouse cursor is over
305 | var ei = list.findPos(e.pageX, e.pageY);
306 | var nlist = list;
307 | for (var i = 0; ei == -1 && opts.dragBetween && i < lists.length; i++) {
308 | ei = lists[i].findPos(e.pageX, e.pageY);
309 | nlist = lists[i];
310 | }
311 |
312 | //if not over another moveable list item return
313 | if (ei == -1)
314 | return false;
315 |
316 | //save fixed items locations
317 | var children = function() { return $(nlist.container).children().not(nlist.draggedItem); };
318 | var fixed = children().not(opts.itemSelector).each(function(i) { this.idx = children().index(this); });
319 |
320 | //if moving draggedItem up or left place placeHolder before list item the dragged item is hovering over otherwise place it after
321 | if (lastPos == null || lastPos.top > list.draggedItem.offset().top || lastPos.left > list.draggedItem.offset().left)
322 | $(nlist.pos[ei].elm).before(list.placeHolderItem);
323 | else
324 | $(nlist.pos[ei].elm).after(list.placeHolderItem);
325 |
326 | //restore fixed items location
327 | fixed.each(function() {
328 | var elm = children().eq(this.idx).get(0);
329 | if (this != elm && children().index(this) < this.idx)
330 | $(this).insertAfter(elm);
331 | else if (this != elm)
332 | $(this).insertBefore(elm);
333 | });
334 |
335 | //misc
336 | $(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
337 | lastPos = list.draggedItem.offset();
338 | return false;
339 | },
340 |
341 | //returns the index of the list item the mouse is over
342 | findPos: function(x, y) {
343 | for (var i = 0; i < this.pos.length; i++) {
344 | if (this.pos[i].left < x && this.pos[i].right > x && this.pos[i].top < y && this.pos[i].bottom > y)
345 | return i;
346 | }
347 | return -1;
348 | },
349 |
350 | //create drop targets which are placeholders at the end of other lists to allow dragging straight to the last position
351 | createDropTargets: function() {
352 | if (!opts.dragBetween)
353 | return;
354 |
355 | $(lists).each(function() {
356 | var ph = $(this.container).find("[data-placeholder]");
357 | var dt = $(this.container).find("[data-droptarget]");
358 | if (ph.length > 0 && dt.length > 0)
359 | dt.remove();
360 | else if (ph.length == 0 && dt.length == 0) {
361 | if (opts.tagName == "td")
362 | $(opts.placeHolderTemplate).attr("data-droptarget", true).appendTo(this.container);
363 | else
364 | //list.placeHolderItem.clone().removeAttr("data-placeholder") crashes in IE7 and jquery 1.5.1 (doesn't in jquery 1.4.2 or IE8)
365 | $(this.container).append(list.placeHolderItem.removeAttr("data-placeholder").clone().attr("data-droptarget", true));
366 |
367 | list.placeHolderItem.attr("data-placeholder", true);
368 | }
369 | });
370 | }
371 | };
372 |
373 | newList.init();
374 | lists.push(newList);
375 | });
376 |
377 | return this;
378 | };
379 |
380 | $.fn.dragsort.defaults = {
381 | tagName:"",
382 | itemSelector: "",
383 | dragSelector: "",
384 | dragSelectorExclude: "input, textarea",
385 | dragEnd: function() { },
386 | dragBetween: false,
387 | placeHolderTemplate: "",
388 | scrollContainer: window,
389 | scrollSpeed: 5
390 | };
391 |
392 | });
393 |
--------------------------------------------------------------------------------
/resources/lang/en/form-media.php:
--------------------------------------------------------------------------------
1 | 'Select',
5 | 'check_image' => 'Select image',
6 | 'upload' => 'Upload',
7 | 'change_sort' => 'Change sort',
8 | 'create' => 'Create',
9 | 'close' => 'Close',
10 | 'save' => 'Save',
11 | 'prev' => 'Prev',
12 | 'next' => 'Next',
13 |
14 | 'get_success' => 'Get success',
15 | 'upload_file_ext_error' => 'Upload file\'ext error',
16 | 'upload_success' => 'Upload success',
17 | 'upload_error' => 'Upload error',
18 | 'create_success' => 'Create success',
19 | 'create_error' => 'Create error',
20 | 'create_dirname_empty' => 'Dirname don\'t empty',
21 |
22 | // js 使用语言包部分
23 | 'js_empty' => 'Empty',
24 | 'js_system_tip' => 'System Tip',
25 | 'js_remove_tip' => 'You will remove the info [:data] ?',
26 | 'js_select_type' => 'Pleace select :title',
27 | 'js_page_render' => ':page / :total,:perpage page',
28 | 'js_dir_not_empty' => 'Dirname dont empty',
29 | 'js_create_dir_error' => 'Create dir error',
30 | 'js_upload_error' => 'Upload error',
31 | 'js_selected_error' => 'Selected data top need :num',
32 | 'js_getdata_error' => 'Getdata error',
33 | 'js_preview_title' => 'Preview',
34 | 'js_preview' => 'Preview',
35 | 'js_remove' => 'Remove',
36 | 'js_dragsort' => 'Dragsort',
37 | 'js_copy_success' => 'Copy success',
38 | 'js_copy_error' => 'Copy error',
39 | ];
40 |
--------------------------------------------------------------------------------
/resources/lang/zh_CN/form-media.php:
--------------------------------------------------------------------------------
1 | '浏览',
5 | 'check_image' => '选择图片',
6 | 'upload' => '上传',
7 | 'change_sort' => '点击切换排序',
8 | 'create' => '新建',
9 | 'close' => '关闭',
10 | 'save' => '确定',
11 | 'prev' => '上一页',
12 | 'next' => '下一页',
13 |
14 | 'get_success' => '获取成功',
15 | 'upload_file_ext_error' => '上传文件格式不被允许',
16 | 'upload_success' => '上传成功',
17 | 'upload_error' => '上传失败',
18 | 'create_success' => '创建成功',
19 | 'create_error' => '创建失败',
20 | 'create_dirname_empty' => '文件夹名称不能为空',
21 |
22 | // js 使用语言包部分
23 | 'js_empty' => '空',
24 | 'js_system_tip' => '系统提示',
25 | 'js_remove_tip' => '确认要移除当前数据 [:data] 吗?',
26 | 'js_select_type' => '请选择:title',
27 | 'js_page_render' => '第:page页 / 共:total页,每页:perpage条',
28 | 'js_dir_not_empty' => '文件夹名称不能为空',
29 | 'js_create_dir_error' => '创建文件夹失败',
30 | 'js_upload_error' => '上传失败',
31 | 'js_selected_error' => '选择数量不能超过 :num 条',
32 | 'js_getdata_error' => '数据获取失败',
33 | 'js_preview_title' => '预览',
34 | 'js_preview' => '预览',
35 | 'js_remove' => '移除',
36 | 'js_dragsort' => '拖动',
37 | 'js_copy_success' => '复制成功',
38 | 'js_copy_error' => '复制失败',
39 | ];
40 |
--------------------------------------------------------------------------------
/resources/lang/zh_TW/form-media.php:
--------------------------------------------------------------------------------
1 | '瀏覽',
5 | 'check_image' => '選擇圖片',
6 | 'upload' => '上傳',
7 | 'change_sort' => '點擊切換排序',
8 | 'create' => '新建',
9 | 'close' => '關閉',
10 | 'save' => '確定',
11 | 'prev' => '上一頁',
12 | 'next' => '下一頁',
13 |
14 | 'get_success' => '獲取成功',
15 | 'upload_file_ext_error' => '上傳文件格式不被允許',
16 | 'upload_success' => '上傳成功',
17 | 'upload_error' => '上傳失敗',
18 | 'create_success' => '創建成功',
19 | 'create_error' => '創建失敗',
20 | 'create_dirname_empty' => '文件夾名稱不能為空',
21 |
22 | // js 使用语言包部分
23 | 'js_empty' => '空',
24 | 'js_system_tip' => '系統提示',
25 | 'js_remove_tip' => '確認要移除當前數據 [:data] 嗎? ',
26 | 'js_select_type' => '請選擇:title',
27 | 'js_page_render' => '第:page頁 / 共:total頁,每頁:perpage條',
28 | 'js_dir_not_empty' => '文件夾名稱不能為空',
29 | 'js_create_dir_error' => '創建文件夾失敗',
30 | 'js_upload_error' => '上傳失敗',
31 | 'js_selected_error' => '選擇數量不能超過 :num 條',
32 | 'js_getdata_error' => '數據獲取失敗',
33 | 'js_preview_title' => '預覽',
34 | 'js_preview' => '預覽',
35 | 'js_remove' => '移除',
36 | 'js_dragsort' => '拖動',
37 | 'js_copy_success' => '複製成功',
38 | 'js_copy_error' => '複製失敗',
39 | ];
--------------------------------------------------------------------------------
/resources/views/field.blade.php:
--------------------------------------------------------------------------------
1 |
120 |
121 |
128 |
--------------------------------------------------------------------------------
/routes/admin.php:
--------------------------------------------------------------------------------
1 | name('admin.lake-form-media.get-files');
7 |
8 | // 上传图片
9 | Route::post('lake-form-media/upload', FormMedia::class.'@upload')->name('admin.lake-form-media.upload');
10 |
11 | // 新建文件夹
12 | Route::post('lake-form-media/create-folder', FormMedia::class.'@createFolder')->name('admin.lake-form-media.create-folder');
--------------------------------------------------------------------------------
/src/Form/Field.php:
--------------------------------------------------------------------------------
1 | uploadUrl = $uploadUrl;
66 |
67 | return $this;
68 | }
69 |
70 | /**
71 | * 设置数据列表链接
72 | *
73 | * @param string $listUrl
74 | * @return $this
75 | */
76 | public function listUrl($listUrl = null)
77 | {
78 | $this->listUrl = $listUrl;
79 |
80 | return $this;
81 | }
82 |
83 | /**
84 | * 设置新建文件夹链接
85 | *
86 | * @param string $createFolderUrl
87 | * @return $this
88 | */
89 | public function createFolderUrl($createFolderUrl = null)
90 | {
91 | $this->createFolderUrl = $createFolderUrl;
92 |
93 | return $this;
94 | }
95 |
96 | /**
97 | * 设置预览前缀
98 | *
99 | * @param string $rootpath
100 | * @return $this
101 | */
102 | public function rootpath($rootpath = null)
103 | {
104 | $this->rootpath = $rootpath;
105 |
106 | return $this;
107 | }
108 |
109 | /**
110 | * 禁止上传
111 | *
112 | * @param boolen $value
113 | * @return $this
114 | */
115 | public function disableUpload(bool $value = true)
116 | {
117 | $this->disableUpload = $value;
118 |
119 | return $this;
120 | }
121 |
122 | /**
123 | * 禁止创建文件夹
124 | *
125 | * @param boolen $value
126 | * @return $this
127 | */
128 | public function disableCreateFolder(bool $value = true)
129 | {
130 | $this->disableCreateFolder = $value;
131 |
132 | return $this;
133 | }
134 |
135 | /**
136 | * 显示标题
137 | *
138 | * @param boolen $value
139 | * @return $this
140 | */
141 | public function showTitle(bool $value = true)
142 | {
143 | $this->showTitle = $value;
144 |
145 | return $this;
146 | }
147 |
148 | /**
149 | * 可多选,默认为可多选
150 | *
151 | * @param boolen $value
152 | * @return $this
153 | */
154 | public function multipleChoice(bool $value = true)
155 | {
156 | $this->multipleChoice = $value;
157 |
158 | return $this;
159 | }
160 |
161 | /**
162 | * 显示图标
163 | *
164 | * @param boolen $value
165 | * @return $this
166 | */
167 | public function showIcon(bool $value = true)
168 | {
169 | $this->showIcon = $value;
170 |
171 | return $this;
172 | }
173 |
174 | /**
175 | * 图片裁剪
176 | *
177 | * @return $this
178 | */
179 | public function resize($width, $height)
180 | {
181 | $this->resize = [$width, $height];
182 |
183 | return $this;
184 | }
185 |
186 | /**
187 | * 保存完整链接
188 | *
189 | * @param boolen $value
190 | * @return $this
191 | */
192 | public function saveFullUrl(bool $value = true)
193 | {
194 | $this->saveFullUrl = $value;
195 |
196 | return $this;
197 | }
198 |
199 | /**
200 | * 设置类型
201 | *
202 | * 类型包括:blend、image、xls、word、
203 | * ppt、pdf、code、zip、text、audio、video
204 | * 其中 blend 为全部类型
205 | *
206 | * @param string $type
207 | * @return $this
208 | */
209 | public function type($type = 'image')
210 | {
211 | $this->type = $type;
212 |
213 | return $this;
214 | }
215 |
216 | /**
217 | * 设置驱动磁盘
218 | *
219 | * @param string $disk
220 | * @return $this
221 | */
222 | public function disk($disk = '')
223 | {
224 | $this->disk = $disk;
225 |
226 | return $this;
227 | }
228 |
229 | /**
230 | * 设置当前可用目录
231 | *
232 | * @param string $path
233 | * @return $this
234 | */
235 | public function path($path = '')
236 | {
237 | $this->path = $path;
238 |
239 | return $this;
240 | }
241 |
242 | /**
243 | * 设置限制数量.
244 | *
245 | * @param int $limit
246 | * @return $this
247 | */
248 | public function limit($limit = 1)
249 | {
250 | $this->limit = $limit;
251 |
252 | return $this;
253 | }
254 |
255 | /**
256 | * 移除
257 | *
258 | * @param boolen $value
259 | * @return $this
260 | */
261 | public function remove(bool $value = true)
262 | {
263 | $this->remove = $value;
264 |
265 | return $this;
266 | }
267 |
268 | /**
269 | * 设置 input accept 属性
270 | * 常用类型 * /* audio/* video/* image/*
271 | *
272 | * @return $this
273 | */
274 | public function accept(string $accept)
275 | {
276 | $this->accept = $accept;
277 |
278 | return $this;
279 | }
280 |
281 | /**
282 | * 设置上传保存文件名类型
283 | *
284 | * @param string $type uniqid|datetime|sequence|original
285 | * @return $this
286 | */
287 | public function nametype($type = 'uniqid')
288 | {
289 | if (! in_array($type, ['uniqid', 'datetime', 'sequence', 'original'])) {
290 | $type = 'uniqid';
291 | }
292 |
293 | $this->nametype = $type;
294 | return $this;
295 | }
296 |
297 | /**
298 | * 唯一 ID 命名
299 | *
300 | * @return $this
301 | */
302 | public function uniqidName()
303 | {
304 | $this->nametype("uniqid");
305 |
306 | return $this;
307 | }
308 |
309 | /**
310 | * 时间格式命名
311 | *
312 | * @return $this
313 | */
314 | public function datetimeName()
315 | {
316 | $this->nametype("datetime");
317 |
318 | return $this;
319 | }
320 |
321 | /**
322 | * sequence 格式命名
323 | *
324 | * @return $this
325 | */
326 | public function sequenceName()
327 | {
328 | $this->nametype("sequence");
329 |
330 | return $this;
331 | }
332 |
333 | /**
334 | * 原始名称命名
335 | *
336 | * @return $this
337 | */
338 | public function originalName()
339 | {
340 | $this->nametype("original");
341 |
342 | return $this;
343 | }
344 |
345 | /**
346 | * 设置每页数量
347 | *
348 | * @param int $pageSize
349 | * @return $this
350 | */
351 | public function pageSize($pageSize = 120)
352 | {
353 | $this->pageSize = $pageSize;
354 |
355 | return $this;
356 | }
357 |
358 | /**
359 | * 渲染
360 | *
361 | * @return mixed
362 | */
363 | public function render()
364 | {
365 | $path = $this->path;
366 | $limit = $this->limit;
367 | $type = $this->type;
368 | $disk = $this->disk;
369 | $accept = $this->accept;
370 | $nametype = $this->nametype;
371 | $pageSize = $this->pageSize;
372 | $remove = ($this->remove == true) ? 1 : 0;
373 |
374 | $rootpath = "";
375 | if (! empty($this->rootpath)) {
376 | $rootpath = $this->rootpath;
377 | } else {
378 | if (! empty($disk)) {
379 | $rootpath = MediaManager::create()
380 | ->withDisk($disk)
381 | ->buildUrl('');
382 | } else {
383 | $rootpath = MediaManager::create()
384 | ->defaultDisk()
385 | ->buildUrl('');
386 | }
387 | }
388 |
389 | if (empty($this->uploadUrl)) {
390 | $this->uploadUrl = admin_route('admin.lake-form-media.upload');
391 | }
392 |
393 | if (empty($this->listUrl)) {
394 | $this->listUrl = admin_route('admin.lake-form-media.get-files');
395 | }
396 |
397 | if (empty($this->createFolderUrl)) {
398 | $this->createFolderUrl = admin_route('admin.lake-form-media.create-folder');
399 | }
400 |
401 | if ($this->disableUpload) {
402 | $this->uploadUrl = '';
403 | }
404 | if ($this->disableCreateFolder) {
405 | $this->createFolderUrl = '';
406 | }
407 |
408 | $showTitle = ($this->showTitle == true) ? 1 : 0;
409 | $multipleChoice = ($this->multipleChoice == true) ? 1 : 0;
410 | $showIcon = ($this->showIcon == true) ? 1 : 0;
411 |
412 | $resize = $this->resize;
413 |
414 | $saveFullUrl = ($this->saveFullUrl == true) ? 1 : 0;
415 |
416 | $this->addVariables([
417 | 'options' => [
418 | 'path' => $path,
419 | 'limit' => $limit,
420 | 'remove' => $remove,
421 | 'type' => $type,
422 | 'disk' => $disk,
423 |
424 | 'accept' => $accept,
425 | 'nametype' => $nametype,
426 | 'pagesize' => $pageSize,
427 |
428 | 'showtitle' => $showTitle,
429 | 'multiplechoice' => $multipleChoice,
430 | 'showicon' => $showIcon,
431 |
432 | 'resize' => implode(',', $resize),
433 |
434 | 'saveFullUrl' => $saveFullUrl,
435 |
436 | 'rootpath' => $rootpath,
437 | 'get_files_url' => $this->listUrl,
438 | 'upload_url' => $this->uploadUrl,
439 | 'create_folder_url' => $this->createFolderUrl,
440 | ],
441 | ]);
442 |
443 | return parent::render();
444 | }
445 |
446 | }
447 |
--------------------------------------------------------------------------------
/src/Form/Field/Audio.php:
--------------------------------------------------------------------------------
1 | input('path', '/');
18 |
19 | $currentPage = (int) request()->input('page', 1);
20 | $perPage = (int) request()->input('pageSize', 120);
21 |
22 | $manager = MediaManager::create()
23 | ->defaultDisk()
24 | ->setPath($path);
25 |
26 | // 驱动磁盘
27 | $disk = request()->input('disk', '');
28 | if (! empty($disk)) {
29 | $manager = $manager->withDisk($disk);
30 | }
31 |
32 | $type = (string) request()->input('type', 'image');
33 | $order = (string) request()->input('order', 'time');
34 |
35 | $files = $manager->ls($type, $order);
36 | $list = collect($files)
37 | ->slice(($currentPage - 1) * $perPage, $perPage)
38 | ->values();
39 |
40 | $totalPage = count(collect($files)->chunk($perPage));
41 |
42 | $data = [
43 | 'list' => $list, // 数据
44 | 'total_page' => $totalPage, // 数量
45 | 'current_page' => $currentPage, // 当前页码
46 | 'per_page' => $perPage, // 每页数量
47 | 'nav' => $manager->navigation() // 导航
48 | ];
49 |
50 | return $this->renderJson(LakeFormMedia::trans('form-media.get_success'), 200, $data);
51 | }
52 |
53 | /**
54 | * 上传
55 | */
56 | public function upload()
57 | {
58 | $files = request()->file('files');
59 | $path = request()->get('path', '/');
60 |
61 | $type = request()->get('type');
62 | $nametype = request()->get('nametype', 'uniqid');
63 |
64 | // 裁剪
65 | $resize = request()->get('resize', '');
66 |
67 | $manager = MediaManager::create()
68 | ->defaultDisk()
69 | ->setPath($path)
70 | ->setNametype($nametype);
71 |
72 | // 驱动磁盘
73 | $disk = request()->input('disk', '');
74 | if (! empty($disk)) {
75 | $manager = $manager->withDisk($disk);
76 | }
77 |
78 | if ($type != 'blend') {
79 | if (! $manager->checkType($files, $type)) {
80 | return $this->renderJson(LakeFormMedia::trans('form-media.upload_file_ext_error'), -1);
81 | }
82 | }
83 |
84 | // 图片裁剪操作
85 | $resizes = explode(",", $resize);
86 | if (
87 | $type == 'image'
88 | && !empty($resize)
89 | && count($resizes) == 2
90 | ) {
91 | try {
92 | foreach ($files as $file) {
93 | $manager->prepareFile([
94 | [
95 | 'method' => 'resize',
96 | 'arguments' => $resizes,
97 | ],
98 | ], $file);
99 | }
100 | } catch (\Exception $e) {}
101 | }
102 |
103 | try {
104 | if ($manager->upload($files)) {
105 | return $this->renderJson(LakeFormMedia::trans('form-media.upload_success'), 200);
106 | }
107 | } catch (\Exception $e) {
108 | return $this->renderJson($e->getMessage(), -1);
109 | }
110 |
111 | return $this->renderJson(LakeFormMedia::trans('form-media.upload_error'), -1);
112 | }
113 |
114 | /**
115 | * 新建文件夹
116 | */
117 | public function createFolder()
118 | {
119 | $dir = request()->input('dir');
120 | $name = request()->input('name');
121 |
122 | if (empty($dir)) {
123 | return $this->renderJson(LakeFormMedia::trans('form-media.create_dirname_empty'), -1);
124 | }
125 |
126 | $manager = MediaManager::create()
127 | ->defaultDisk()
128 | ->setPath($dir);
129 |
130 | // 驱动磁盘
131 | $disk = request()->input('disk', '');
132 | if (! empty($disk)) {
133 | $manager = $manager->withDisk($disk);
134 | }
135 |
136 | try {
137 | if ($manager->createFolder($name)) {
138 | return $this->renderJson(LakeFormMedia::trans('form-media.create_success'), 200);
139 | }
140 | } catch (\Exception $e) {}
141 |
142 | return $this->renderJson(LakeFormMedia::trans('form-media.create_error'), -1);
143 | }
144 |
145 | /**
146 | * 输出json
147 | */
148 | protected function renderJson($msg, $code = 200, $data = [])
149 | {
150 | return response()->json([
151 | 'code' => $code,
152 | 'msg' => $msg,
153 | 'data' => $data,
154 | ]);
155 | }
156 | }
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/src/MediaManager.php:
--------------------------------------------------------------------------------
1 | 'jpeg|jpg|bmp|png|svg|wbmp|pic|cgm|djv|djvu|gif|ico|ief|jp2|jpe|mac|pbm|pct|pgm|pict|pnm|pnt|pntg|ppm|qti|qtif|ras|rgb|tif|tiff|xbm|xpm|xwd|avif',
45 | 'video' => 'mkv|avi|mp4|rmvb|rm|flv|wmv|asf|mpeg|mov',
46 | 'audio' => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
47 | 'pdf' => 'pdf',
48 | 'word' => 'doc|docx|dot|dotx|docm|dotm|wps',
49 | 'ppt' => 'ppt|pptx|pptm|pot|pps|ppa|pptx|potx|ppsx|ppam|potm|ppsm',
50 | 'xls' => 'xls|xlt|xla|xlsx|xltx|xlsm|xltm|xlam|xlsb',
51 | 'text' => 'txt|pac|log|md',
52 | 'code' => 'html|htm|js|css|vue|json|php|java|go|py|ruby|rb|aspx|asp|c|cpp|sql|m|h|python|ruby|rs|zig|v',
53 | 'zip' => 'zip|tar|gz|tar\.gz|rar|rpm',
54 | ];
55 |
56 | /**
57 | * 创建
58 | */
59 | public static function create()
60 | {
61 | return new static();
62 | }
63 |
64 | /**
65 | * 默认驱动
66 | */
67 | public function defaultDisk()
68 | {
69 | $disk = config('admin.upload.disk');
70 |
71 | return $this->withDisk($disk);
72 | }
73 |
74 | /**
75 | * 使用驱动
76 | */
77 | public function withDisk($disk)
78 | {
79 | $this->storage = Storage::disk($disk);
80 |
81 | return $this;
82 | }
83 |
84 | /**
85 | * 设置目录
86 | */
87 | public function setPath($path = '/')
88 | {
89 | $this->path = $path;
90 | return $this;
91 | }
92 |
93 | /**
94 | * 列出数据
95 | */
96 | public function ls($type = 'image', $order = 'time')
97 | {
98 | $files = $this->storage->files($this->path);
99 |
100 | $directories = $this->storage->directories($this->path);
101 |
102 | $manager = $this;
103 | $files = $this->formatFiles($files)
104 | ->map(function($item) use($type, $manager) {
105 | if ($type == 'blend') {
106 | return $item;
107 | }
108 |
109 | $fileType = $manager->detectFileType($item['name']);
110 | if ($type == $fileType) {
111 | return $item;
112 | }
113 |
114 | return null;
115 | })
116 | ->filter(function($item) {
117 | return ! empty($item);
118 | });
119 |
120 | $list = $this->formatDirectories($directories)
121 | ->merge($files);
122 |
123 | if ($order == 'name') {
124 | $list = $list->sort(function ($item) {
125 | return $item['name'];
126 | });
127 | } else {
128 | $list = $list->sortByDesc(function ($item) {
129 | return $item['time'];
130 | });
131 | }
132 |
133 | return $list->all();
134 | }
135 |
136 | /**
137 | * 获取完整路径
138 | *
139 | * @param string $path
140 | *
141 | * @return string
142 | */
143 | protected function getFullPath($path)
144 | {
145 | return $this->storage->path($path);
146 | }
147 |
148 | /**
149 | * 下载
150 | */
151 | public function download($file)
152 | {
153 | $fullPath = $this->getFullPath($file);
154 |
155 | if (File::isFile($fullPath)) {
156 | return response()->download($fullPath);
157 | }
158 |
159 | return response('', 404);
160 | }
161 |
162 | /**
163 | * 删除
164 | */
165 | public function delete($path)
166 | {
167 | $paths = is_array($path) ? $path : func_get_args();
168 |
169 | foreach ($paths as $path) {
170 | $fullPath = $this->getFullPath($path);
171 |
172 | if (is_file($fullPath)) {
173 | $this->storage->delete($path);
174 | } else {
175 | $this->storage->deleteDirectory($path);
176 | }
177 | }
178 |
179 | return true;
180 | }
181 |
182 | /**
183 | * 移动
184 | */
185 | public function move($new)
186 | {
187 | return $this->storage->move($this->path, $new);
188 | }
189 |
190 | /**
191 | * 上传
192 | *
193 | * @param UploadedFile[] $files
194 | * @param string $dir
195 | *
196 | * @return mixed
197 | */
198 | public function upload($files = [])
199 | {
200 | if (empty($files)) {
201 | return false;
202 | }
203 |
204 | foreach ($files as $file) {
205 | $this->storage->putFileAs(
206 | $this->path,
207 | $file,
208 | $this->getPutFileName($file)
209 | );
210 | }
211 |
212 | return true;
213 | }
214 |
215 | /**
216 | * 检测文件上传类型
217 | */
218 | public function checkType($files = [], $type = null)
219 | {
220 | if (empty($files)) {
221 | return false;
222 | }
223 |
224 | foreach ($files as $file) {
225 | $fileExtension = $file->getClientOriginalExtension();
226 | $fileType = $this->detectFileType('file.'.$fileExtension);
227 | if ($fileType != $type) {
228 | return false;
229 | }
230 | }
231 |
232 | return true;
233 | }
234 |
235 | /**
236 | * 设置命名方式
237 | */
238 | public function setNametype($type = 'uniqid')
239 | {
240 | $this->nametype = $type;
241 |
242 | return $this;
243 | }
244 |
245 | /**
246 | * 获取最后的命名
247 | */
248 | public function getPutFileName($file)
249 | {
250 | switch ($this->nametype) {
251 | // 时间命名
252 | case 'datetime':
253 | return $this->generateDatetimeName($file);
254 | break;
255 |
256 | // 原始命名,不覆盖已传同名文件
257 | case 'sequence':
258 | return $this->generateSequenceName($file);
259 | break;
260 |
261 | // 原始命名,将覆盖已传同名文件
262 | case 'original':
263 | return $this->generateClientOriginalName($file);
264 | break;
265 |
266 | // 哈希命名
267 | case 'uniqid':
268 | default:
269 | return $this->generateUniqueName($file);
270 | break;
271 | }
272 | }
273 |
274 | /**
275 | * 时间命名
276 | */
277 | public function generateDatetimeName($file)
278 | {
279 | $name = date('YmdHis').mt_rand(10000, 99999);
280 | $extension = $file->getClientOriginalExtension();
281 |
282 | if (empty($extension)) {
283 | return $name;
284 | }
285 |
286 | return $name.'.'.$extension;
287 | }
288 |
289 | /**
290 | * 哈希命名
291 | */
292 | public function generateUniqueName($file)
293 | {
294 | $name = md5(uniqid().microtime());
295 | $extension = $file->getClientOriginalExtension();
296 |
297 | if (empty($extension)) {
298 | return $name;
299 | }
300 |
301 | return $name.'.'.$extension;
302 | }
303 |
304 | /**
305 | * 原始命名,不覆盖已传同名文件
306 | */
307 | public function generateSequenceName($file)
308 | {
309 | $index = 1;
310 | $original = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
311 | $extension = $file->getClientOriginalExtension();
312 |
313 | if (! empty($extension)) {
314 | $new = sprintf('%s_%s.%s', $original, $index, $extension);
315 | } else {
316 | $new = sprintf('%s_%s', $original, $index);
317 | }
318 |
319 | while ($this->storage->exists($this->formatPath($this->path, $new))) {
320 | $index++;
321 |
322 | if (! empty($extension)) {
323 | $new = sprintf('%s_%s.%s', $original, $index, $extension);
324 | } else {
325 | $new = sprintf('%s_%s', $original, $index);
326 | }
327 | }
328 |
329 | return $new;
330 | }
331 |
332 | /**
333 | * 原始命名,将覆盖已传同名文件
334 | */
335 | public function generateClientOriginalName($file)
336 | {
337 | $name = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
338 | $extension = $file->getClientOriginalExtension();
339 |
340 | if (empty($extension)) {
341 | return $name;
342 | }
343 |
344 | return $name.'.'.$extension;
345 | }
346 |
347 | /**
348 | * 创建文件夹
349 | */
350 | public function createFolder($name)
351 | {
352 | $path = $this->formatPath($this->path, $name);
353 |
354 | return $this->storage->makeDirectory($path);
355 | }
356 |
357 | /**
358 | * 是否存在
359 | */
360 | public function exists($name)
361 | {
362 | $path = $this->formatPath($this->path, $name);
363 |
364 | return $this->storage->exists($path);
365 | }
366 |
367 | /**
368 | * @return array
369 | */
370 | public function urls()
371 | {
372 | return [
373 | 'path' => $this->path,
374 | ];
375 | }
376 |
377 | /**
378 | * 生成url
379 | */
380 | public function buildUrl($url = '')
381 | {
382 | if (URL::isValidUrl($url)) {
383 | return $url;
384 | }
385 |
386 | return $this->storage->url($url);
387 | }
388 |
389 | /**
390 | * 格式化文件
391 | */
392 | public function formatFiles($files = [])
393 | {
394 | $files = array_map(function ($file) {
395 | return [
396 | 'icon' => '',
397 | 'name' => $file,
398 | 'namesmall' => pathinfo($file, PATHINFO_BASENAME),
399 | 'preview' => $this->getFilePreview($file),
400 | 'isDir' => false,
401 | 'size' => $this->getFilesize($file),
402 | 'url' => $this->storage->url($file),
403 | 'time' => $this->getFileChangeTime($file),
404 | 'type' => $this->detectFileType($file)
405 | ];
406 | }, $files);
407 |
408 | return collect($files);
409 | }
410 |
411 | /**
412 | * 格式化文件夹
413 | */
414 | public function formatDirectories($dirs = [])
415 | {
416 | $preview = '';
417 |
418 | $dirs = array_map(function ($dir) use ($preview) {
419 | return [
420 | 'icon' => '',
421 | 'name' => $dir,
422 | 'namesmall' => basename($dir),
423 | 'preview' => str_replace('__path__', $dir, $preview),
424 | 'isDir' => true,
425 | 'size' => '-',
426 | 'url' => $this->storage->url($dir),
427 | 'time' => $this->getFileChangeTime($dir),
428 | 'type' => 'dir',
429 | ];
430 | }, $dirs);
431 |
432 | return collect($dirs);
433 | }
434 |
435 | public function navigation()
436 | {
437 | $folders = explode('/', $this->path);
438 |
439 | $folders = array_filter($folders);
440 |
441 | $path = '';
442 |
443 | $navigation = [];
444 |
445 | foreach ($folders as $folder) {
446 | $path = rtrim($path, '/').'/'.$folder;
447 |
448 | $navigation[] = [
449 | 'name' => $folder,
450 | 'url' => $path,
451 | ];
452 | }
453 |
454 | return $navigation;
455 | }
456 |
457 | public function getFilePreview($file)
458 | {
459 | switch ($this->detectFileType($file)) {
460 | case 'image':
461 | $url = $this->storage->url($file);
462 | if ($url) {
463 | $preview = '
';
464 | } else {
465 | $preview = '';
466 | }
467 | break;
468 |
469 | case 'video':
470 | /**
471 | if ($this->storage->getDriver()->getConfig()->has('url')) {
472 | $url = $this->storage->url($file);
473 | $preview = "";
474 | } else {
475 | $preview = '';
476 | }
477 | */
478 | $preview = '';
479 | break;
480 |
481 | case 'audio':
482 | $preview = '';
483 | break;
484 |
485 | case 'pdf':
486 | $preview = '';
487 | break;
488 |
489 | case 'word':
490 | $preview = '';
491 | break;
492 |
493 | case 'ppt':
494 | $preview = '';
495 | break;
496 |
497 | case 'xls':
498 | $preview = '';
499 | break;
500 |
501 | case 'text':
502 | $preview = '';
503 | break;
504 |
505 | case 'code':
506 | $preview = '';
507 | break;
508 |
509 | case 'zip':
510 | $preview = '';
511 | break;
512 |
513 | default:
514 | $preview = '';
515 | }
516 |
517 | return $preview;
518 | }
519 |
520 | protected function detectFileType($file)
521 | {
522 | $extension = File::extension($file);
523 |
524 | foreach ($this->fileTypes as $type => $regex) {
525 | if (preg_match("/^($regex)$/i", $extension) !== 0) {
526 | return $type;
527 | }
528 | }
529 |
530 | return 'other';
531 | }
532 |
533 | /**
534 | * 提前完成裁剪等操作
535 | *
536 | * @param array $methods arguments = []
537 | * @param UploadedFile $file
538 | */
539 | public function prepareFile($methods, UploadedFile $file)
540 | {
541 | $this->callInterventionMethods($methods, $file->getRealPath(), $file->getMimeType());
542 | }
543 |
544 | /**
545 | * 执行裁剪等操作
546 | *
547 | * @param array $methods arguments = []
548 | * @param string $target
549 | * @param string $mime
550 | *
551 | * @return mixed
552 | */
553 | public function callInterventionMethods($methods, $target, $mime)
554 | {
555 | if (! empty($methods)) {
556 | $image = ImageManagerStatic::make($target);
557 |
558 | $mime = $mime ?: finfo_file(finfo_open(FILEINFO_MIME_TYPE), $target);
559 |
560 | // 常用方法
561 | // $call['method'] = resize(320, 240)
562 | // $call['method'] = insert('public/watermark.png')
563 | // $call['method'] = rotate(-45);
564 | foreach ($methods as $call) {
565 | call_user_func_array(
566 | [$image, $call['method']],
567 | $call['arguments']
568 | )->save($target, null, $mime);
569 | }
570 | }
571 |
572 | return $target;
573 | }
574 |
575 | /**
576 | * 删除缩略图
577 | *
578 | * @param array $thumbnails
579 | * @param string|array $file
580 | *
581 | * @return void.
582 | */
583 | public function destroyThumbnail($thumbnails, $file = null)
584 | {
585 | if (! $file) {
586 | return;
587 | }
588 |
589 | if (is_array($file)) {
590 | foreach ($file as $f) {
591 | $this->destroyThumbnail($f);
592 | }
593 |
594 | return;
595 | }
596 |
597 | foreach ($thumbnails as $name => $_) {
598 | $ext = pathinfo($file, PATHINFO_EXTENSION);
599 |
600 | $path = Str::replaceLast('.'.$ext, '', $file);
601 |
602 | $path = $path.'-'.$name.'.'.$ext;
603 |
604 | if ($this->storage->exists($path)) {
605 | $this->storage->delete($path);
606 | }
607 | }
608 | }
609 |
610 | /**
611 | * 上传并删除缩略图
612 | *
613 | * @param array $thumbnails
614 | * @param UploadedFile $file
615 | * @return $this
616 | */
617 | public function uploadAndDeleteOriginalThumbnail($thumbnails, UploadedFile $file)
618 | {
619 | foreach ($thumbnails as $name => $size) {
620 | $ext = pathinfo($this->name, PATHINFO_EXTENSION);
621 |
622 | $path = Str::replaceLast('.'.$ext, '', $this->name);
623 |
624 | $path = $path.'-'.$name.'.'.$ext;
625 |
626 | /** @var \Intervention\Image\Image $image */
627 | $image = InterventionImage::make($file);
628 |
629 | $action = $size[2] ?? 'resize';
630 | $image->$action($size[0], $size[1], function (Constraint $constraint) {
631 | $constraint->aspectRatio();
632 | });
633 |
634 | if (! is_null($this->storagePermission)) {
635 | $this->storage->put($this->formatPath($this->path, $path), $image->encode(), $this->storagePermission);
636 | } else {
637 | $this->storage->put($this->formatPath($this->path, $path), $image->encode());
638 | }
639 | }
640 |
641 | $this->destroyThumbnail($thumbnails);
642 |
643 | return $this;
644 | }
645 |
646 | /**
647 | * 获取文件大小
648 | */
649 | public function getFilesize($file)
650 | {
651 | try {
652 | $bytes = filesize($this->getFullPath($file));
653 | $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
654 |
655 | for ($i = 0; $bytes > 1024; $i++) {
656 | $bytes /= 1024;
657 | }
658 | return round($bytes, 2).' '.$units[$i];
659 | } catch (\ErrorException $e) {
660 | return '未知';
661 | }
662 | }
663 |
664 | public function getFileChangeTime($file)
665 | {
666 | try {
667 | $time = filectime($this->getFullPath($file));
668 | return date('Y-m-d H:i:s', $time);
669 | } catch (\ErrorException $e) {
670 | return '';
671 | }
672 | }
673 |
674 | /**
675 | * 格式化路径
676 | */
677 | public function formatPath($path, $name)
678 | {
679 | return rtrim($path, '/') . '/' . trim($name, '/');
680 | }
681 |
682 | }
--------------------------------------------------------------------------------
/src/ServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->booted(function () {
33 | $this->registerRoutes(__DIR__.'/../routes/admin.php');
34 | });
35 |
36 | // 视图
37 | $this->loadViewsFrom(__DIR__.'/../resources/views', 'lake-form-media');
38 |
39 | // 加载插件
40 | Admin::booting(function () {
41 | Form::extend('photo', Field\Photo::class);
42 | Form::extend('photos', Field\Photos::class);
43 | Form::extend('video', Field\Video::class);
44 | Form::extend('audio', Field\Audio::class);
45 | Form::extend('files', Field\Files::class);
46 | });
47 |
48 | // 加载语言包
49 | Admin::booting(function () {
50 | $script = "
51 | window.LakeFormMediaLang = {
52 | 'empty': '" . static::trans('form-media.js_empty') . "',
53 | 'system_tip': '" . static::trans('form-media.js_system_tip') . "',
54 | 'remove_tip': '" . static::trans('form-media.js_remove_tip') . "',
55 | 'select_type': '" . static::trans('form-media.js_select_type') . "',
56 | 'page_render': '" . static::trans('form-media.js_page_render') . "',
57 | 'dir_not_empty': '" . static::trans('form-media.js_dir_not_empty') . "',
58 | 'create_dir_error': '" . static::trans('form-media.js_create_dir_error') . "',
59 | 'upload_error': '" . static::trans('form-media.js_upload_error') . "',
60 | 'selected_error': '" . static::trans('form-media.js_selected_error') . "',
61 | 'getdata_error': '" . static::trans('form-media.js_getdata_error') . "',
62 | 'preview_title': '" . static::trans('form-media.js_preview_title') . "',
63 | 'preview': '" . static::trans('form-media.js_preview') . "',
64 | 'remove': '" . static::trans('form-media.js_remove') . "',
65 | 'dragsort': '" . static::trans('form-media.js_dragsort') . "',
66 | 'copy_success': '" . static::trans('form-media.js_copy_success') . "',
67 | 'copy_error': '" . static::trans('form-media.js_copy_error') . "',
68 | };
69 | ";
70 | Admin::script($script);
71 | });
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/src/Support/helpers.php:
--------------------------------------------------------------------------------
1 | withDisk($disk)
19 | ->buildUrl($url);
20 | } else {
21 | $path = MediaManager::create()
22 | ->defaultDisk()
23 | ->buildUrl($url);
24 | }
25 |
26 | return $path;
27 | }
28 | }
29 |
30 | if (! function_exists('lake_form_media_urls')) {
31 | /**
32 | * 生成url链接列表
33 | *
34 | * @param array $urls
35 | *
36 | * @create 2020-11-26
37 | * @author deatil
38 | */
39 | function lake_form_media_urls($urls = []) {
40 | $newUrls = [];
41 | foreach ($urls as $disk => $url) {
42 | if (is_string($disk)) {
43 | $newUrls[] = lake_form_media_url($url, $disk);
44 | } else {
45 | $newUrls[] = lake_form_media_url($url);
46 | }
47 | }
48 |
49 | return $newUrls;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/version.php:
--------------------------------------------------------------------------------
1 | [
5 | '修复上传文件原始命名保存名称错误问题。',
6 | ],
7 | '1.0.35' => [
8 | '优化原始命名逻辑。',
9 | ],
10 | '1.0.36' => [
11 | '添加更多翻译。',
12 | ],
13 | '1.0.37' => [
14 | '修复预览图标不准确问题。',
15 | ],
16 | '1.0.38' => [
17 | '增加设置 input accept 属性。',
18 | ],
19 | ];
20 |
--------------------------------------------------------------------------------