初始化提交
This commit is contained in:
125
app/admin/view/api/icon.html
Normal file
125
app/admin/view/api/icon.html
Normal file
@@ -0,0 +1,125 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{block name="title"}{$title|default=''}{if !empty($title)} · {/if}{:sysconf('site_name')}{/block}</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/iconfont.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/plugs/layui/css/layui.css?v={:date('ymd')}">
|
||||
<style>
|
||||
::-webkit-input-placeholder {
|
||||
color: #aaa
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
height: 3px
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #ccc
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #666
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: #ec494e;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background-color: #ec494e;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0 1000px white inset;
|
||||
-webkit-text-fill-color: #333
|
||||
}
|
||||
|
||||
ul li {
|
||||
width: 20%;
|
||||
height: 65px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: -1px;
|
||||
margin-left: -2px;
|
||||
margin-bottom: -2px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
padding: 15px 0 10px 0;
|
||||
border: 1px solid #e2e2e2;
|
||||
background-color: #efefef;
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
transition: all .2s linear;
|
||||
-o-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
-webkit-transition: all .2s linear
|
||||
}
|
||||
|
||||
ul li:hover {
|
||||
color: #fff;
|
||||
background-color: #563d7c
|
||||
}
|
||||
|
||||
ul li:hover i, ul li:hover div {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
ul li i {
|
||||
color: #333;
|
||||
display: inline-block;
|
||||
font-size: 30px !important
|
||||
}
|
||||
|
||||
ul li div {
|
||||
color: #333;
|
||||
height: 35px;
|
||||
font-size: 13px;
|
||||
line-height: 35px;
|
||||
white-space: nowrap
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<ul>
|
||||
{foreach $layuiIcons??[] as $icon}
|
||||
<li>
|
||||
<i class="layui-icon {$icon}"></i>
|
||||
<div class="icon-title">{$icon}</div>
|
||||
</li>
|
||||
{/foreach}
|
||||
{foreach $thinkIcons??[] as $icon}
|
||||
<li>
|
||||
<i class="iconfont {$icon}"></i>
|
||||
<div class="icon-title">{$icon}</div>
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
|
||||
<script src="__ROOT__/static/plugs/jquery/jquery.min.js" type="text/javascript"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
$('li').on('click', function (className) {
|
||||
if ((className = $(this).find('i').get(0).className)) {
|
||||
top.$('[name="{$field}"]').val(className).trigger('change');
|
||||
top.layer.close(top.layer.getFrameIndex(window.name));
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
327
app/admin/view/api/upload.js
Normal file
327
app/admin/view/api/upload.js
Normal file
@@ -0,0 +1,327 @@
|
||||
define(['md5', 'notify'], function (SparkMD5, Notify, allowMime) {
|
||||
allowMime = JSON.parse('{$exts|raw}');
|
||||
|
||||
function UploadAdapter(elem, done) {
|
||||
return new (function (elem, done) {
|
||||
let that = this;
|
||||
|
||||
/*! 初始化变量 */
|
||||
this.option = {elem: $(elem), exts: [], mimes: []};
|
||||
this.option.size = this.option.elem.data('size') || 0;
|
||||
this.option.safe = this.option.elem.data('safe') ? 1 : 0;
|
||||
this.option.hide = this.option.elem.data('hload') ? 1 : 0;
|
||||
this.option.mult = this.option.elem.data('multiple') > 0;
|
||||
this.option.path = (this.option.elem.data('path') || '').replace(/\W/g, '');
|
||||
this.option.type = this.option.safe ? 'local' : this.option.elem.attr('data-uptype') || '';
|
||||
this.option.quality = parseFloat(this.option.elem.data('quality') || '1.0');
|
||||
this.option.maxWidth = parseInt(this.option.elem.data('max-width') || '0');
|
||||
this.option.maxHeight = parseInt(this.option.elem.data('max-height') || '0');
|
||||
this.option.cutWidth = parseInt(this.option.elem.data('cut-width') || '0');
|
||||
this.option.cutHeight = parseInt(this.option.elem.data('cut-height') || '0');
|
||||
|
||||
/*! 查找表单元素, 如果没有找到将不会自动写值 */
|
||||
if (this.option.elem.data('input')) {
|
||||
this.option.input = $(this.option.elem.data('input'))
|
||||
} else if (this.option.elem.data('field')) {
|
||||
this.option.input = $('input[name="' + this.option.elem.data('field') + '"]:not([type=file])');
|
||||
this.option.elem.data('input', this.option.input.size() > 0 ? this.option.input.get(0) : null);
|
||||
}
|
||||
|
||||
/*! 文件选择筛选,使用 MIME 规则过滤文件列表 */
|
||||
$((this.option.elem.data('type') || '').split(',')).map(function (i, e) {
|
||||
if (allowMime[e]) that.option.exts.push(e), that.option.mimes.push(allowMime[e]);
|
||||
});
|
||||
|
||||
/*! 初始化上传组件 */
|
||||
this.adapter = new Adapter(this.option, layui.upload.render({
|
||||
url: '{:url("admin/api.upload/file",[],false,true)}', auto: false, elem: elem, accept: 'file', multiple: this.option.mult, exts: this.option.exts.join('|'), acceptMime: this.option.mimes.join(','), choose: function (obj) {
|
||||
obj.items = [], obj.files = obj.pushFile();
|
||||
layui.each(obj.files, function (idx, file) {
|
||||
obj.items.push(file);
|
||||
file.path = that.option.path;
|
||||
file.quality = that.option.quality;
|
||||
file.maxWidth = that.option.maxWidth;
|
||||
file.maxHeight = that.option.maxHeight;
|
||||
file.cutWidth = that.option.cutWidth;
|
||||
file.cutHeight = that.option.cutHeight;
|
||||
});
|
||||
that.adapter.event('upload.choose', obj.items);
|
||||
that.adapter.upload(obj.items, done);
|
||||
layui.each(obj.files, function (idx) {
|
||||
delete obj.files[idx];
|
||||
});
|
||||
}
|
||||
}));
|
||||
})(elem, done)
|
||||
}
|
||||
|
||||
// 创建对象
|
||||
UploadAdapter.adapter = window.AdminUploadAdapter = Adapter;
|
||||
|
||||
// 上传文件
|
||||
function Adapter(option, uploader) {
|
||||
this.uploader = uploader, this.config = function (option) {
|
||||
return (this.option = Object.assign({}, this.option || {}, option || {})), this;
|
||||
}, this.init = function (option) {
|
||||
this.uploader && this.uploader.config.elem.next().val('');
|
||||
this.files = {}, this.loader = 0, this.count = {total: 0, error: 0, success: 0};
|
||||
return this.config(option).config({safe: this.option.safe || 0, type: this.option.type || ''});
|
||||
}, this.init(option);
|
||||
}
|
||||
|
||||
// 文件推送
|
||||
Adapter.prototype.upload = function (files, done) {
|
||||
let that = this.init();
|
||||
layui.each(files, function (index, file) {
|
||||
that.count.total++, file.index = index, that.files[index] = file;
|
||||
if (!that.option.hide && !file.notify) {
|
||||
file.notify = new NotifyExtend(file);
|
||||
}
|
||||
if (that.option.size && file.size > that.option.size) {
|
||||
that.event('upload.error', {file: file}, file, '{:lang("大小超出限制!")}');
|
||||
}
|
||||
});
|
||||
layui.each(files, function (index, file) {
|
||||
// 禁传异常状态文件
|
||||
if (typeof file.xstate === 'number' && file.xstate === -1) return;
|
||||
// 图片限宽限高压缩
|
||||
let isGif = /^image\/gif/.test(file.type);
|
||||
if (!isGif && /^image\//.test(file.type) && (file.maxWidth + file.maxHeight + file.cutWidth + file.cutHeight > 0 || file.quality !== 1)) {
|
||||
require(['compressor'], function (Compressor) {
|
||||
let options = {quality: file.quality, resize: 'cover'};
|
||||
if (file.cutWidth) options.width = file.cutWidth;
|
||||
if (file.cutHeight) options.height = file.cutHeight;
|
||||
if (file.maxWidth) options.maxWidth = file.maxWidth;
|
||||
if (file.maxHeight) options.maxHeight = file.maxHeight;
|
||||
new Compressor(file, Object.assign(options, {
|
||||
success(blob) {
|
||||
blob.index = file.index, blob.notify = file.notify, blob.path = file.path, files[index] = blob;
|
||||
that.hash(files[index]).then(function (file) {
|
||||
that.event('upload.hash', file).request(file, done);
|
||||
});
|
||||
}, error: function () {
|
||||
that.event('upload.error', {file: file}, file, '{:lang("图片压缩失败!")}');
|
||||
}
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
that.hash(file).then(function (file) {
|
||||
that.event('upload.hash', file).request(file, done);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 文件上传
|
||||
Adapter.prototype.request = function (file, done) {
|
||||
let that = this, data = {key: file.xkey, safe: that.option.safe, uptype: that.option.type};
|
||||
data.size = file.size, data.name = file.name, data.hash = file.xmd5, data.mime = file.type, data.xext = file.xext;
|
||||
jQuery.ajax("{:url('admin/api.upload/state',[],false,true)}", {
|
||||
data: data, method: 'post', success: function (ret) {
|
||||
file.id = ret.data.id || 0, file.xurl = ret.data.url;
|
||||
file.xsafe = ret.data.safe, file.xpath = ret.data.key, file.xtype = ret.data.uptype;
|
||||
if (parseInt(ret.code) === 404) {
|
||||
let uploader = {};
|
||||
uploader.uptype = ret.data.uptype;
|
||||
uploader.url = ret.data.server;
|
||||
uploader.head = {};
|
||||
uploader.form = new FormData();
|
||||
uploader.form.append('key', ret.data.key);
|
||||
uploader.form.append('safe', ret.data.safe);
|
||||
uploader.form.append('uptype', ret.data.uptype);
|
||||
if (ret.data.uptype === 'qiniu') {
|
||||
uploader.form.append('token', ret.data.token);
|
||||
} else if (ret.data.uptype === 'alist') {
|
||||
uploader.type = 'put';
|
||||
uploader.head['file-path'] = ret.data['filepath'];
|
||||
uploader.head['authorization'] = ret.data['authorization'];
|
||||
uploader.form = new FormData();
|
||||
} else if (ret.data.uptype === 'alioss') {
|
||||
uploader.form.append('policy', ret.data['policy']);
|
||||
uploader.form.append('signature', ret.data['signature']);
|
||||
uploader.form.append('OSSAccessKeyId', ret.data['OSSAccessKeyId']);
|
||||
uploader.form.append('success_action_status', '200');
|
||||
uploader.form.append('Content-Disposition', 'inline;filename=' + encodeURIComponent(file.name));
|
||||
} else if (ret.data.uptype === 'txcos') {
|
||||
uploader.form.append('q-ak', ret.data['q-ak']);
|
||||
uploader.form.append('policy', ret.data['policy']);
|
||||
uploader.form.append('q-key-time', ret.data['q-key-time']);
|
||||
uploader.form.append('q-signature', ret.data['q-signature']);
|
||||
uploader.form.append('q-sign-algorithm', ret.data['q-sign-algorithm']);
|
||||
uploader.form.append('success_action_status', '200');
|
||||
uploader.form.append('Content-Disposition', 'inline;filename=' + encodeURIComponent(file.name));
|
||||
} else if (ret.data.uptype === 'upyun') {
|
||||
uploader.form.delete('key');
|
||||
uploader.form.delete('safe');
|
||||
uploader.form.delete('uptype');
|
||||
uploader.form.append('save-key', ret.data['key']);
|
||||
uploader.form.append('policy', ret.data['policy']);
|
||||
uploader.form.append('authorization', ret.data['authorization']);
|
||||
uploader.form.append('Content-Disposition', 'inline;filename=' + encodeURIComponent(file.name));
|
||||
}
|
||||
uploader.form.append('file', file, file.name), jQuery.ajax({
|
||||
xhrFields: {withCredentials: ret.data.uptype === 'local'}, headers: uploader.head, url: uploader.url, data: uploader.form, type: uploader.type || 'post', xhr: function (xhr) {
|
||||
xhr = new XMLHttpRequest();
|
||||
return xhr.upload.addEventListener('progress', function (event) {
|
||||
file.xtotal = event.total, file.xloaded = event.loaded || 0;
|
||||
that.progress((file.xloaded / file.xtotal * 100).toFixed(2), file)
|
||||
}), xhr;
|
||||
}, contentType: false, error: function () {
|
||||
that.event('upload.error', {file: file}, file, '{:lang("上传接口异常!")}');
|
||||
}, processData: false, success: function (ret) {
|
||||
// 兼容数据格式
|
||||
if (typeof ret === 'string' && ret.length > 0) try {
|
||||
ret = JSON.parse(ret) || ret;
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
if (typeof ret !== 'object') {
|
||||
ret = {code: 1, url: file.xurl, info: '{:lang("文件上传成功!")}'};
|
||||
}
|
||||
/*! 检查单个文件上传返回的结果 */
|
||||
if (typeof ret === 'object' && ret.code < 1) {
|
||||
that.event('upload.error', {file: file}, file, ret.info || '{:lang("文件上传失败!")}');
|
||||
} else if (uploader.uptype === 'alist' && parseInt(ret.code) !== 200) {
|
||||
that.event('upload.error', {file: file}, file, ret.message || '{:lang("文件上传失败!")}');
|
||||
} else {
|
||||
that.done(ret, file.index, file, done, '{:lang("文件上传成功!")}');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (parseInt(ret.code) === 200) {
|
||||
(file.xurl = ret.data.url), that.progress('100.00', file);
|
||||
that.done({code: 1, url: file.xurl, info: file.xstats, data: {code: 200, url: file.xurl}}, file.index, file, done, '{:lang("文件秒传成功!")}');
|
||||
} else {
|
||||
that.event('upload.error', {file: file}, file, ret.info || ret.error.message || '{:lang("文件上传出错!")}');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 上传进度
|
||||
Adapter.prototype.progress = function (number, file) {
|
||||
this.event('upload.progress', {number: number, file: file});
|
||||
if (file.notify) file.notify.setProgress(number);
|
||||
};
|
||||
|
||||
// 上传结果
|
||||
Adapter.prototype.done = function (ret, idx, file, done, message) {
|
||||
/*! 检查单个文件上传返回的结果 */
|
||||
if (ret.code < 1) return $.msg.tips(ret.info || '{:lang("文件上传失败!")}');
|
||||
if (typeof file.xurl !== 'string') return $.msg.tips('{:lang("无效的文件上传对象!")}');
|
||||
jQuery.post("{:url('admin/api.upload/done',[],false,true)}", {id: file.id, hash: file.xmd5});
|
||||
/*! 单个文件上传成功结果处理 */
|
||||
if (typeof done === 'function') {
|
||||
done.call(this.option.elem, file.xurl, this.files['id']);
|
||||
} else if (this.option.mult < 1 && this.option.elem.data('input')) {
|
||||
$(this.option.elem.data('input')).val(file.xurl).trigger('change', file);
|
||||
}
|
||||
// 文件上传成功事件
|
||||
this.event('push', file.xurl).event('upload.done', {file: file, data: ret}, file, message);
|
||||
/*! 所有文件上传完成后结果处理 */
|
||||
if (this.count.success + this.count.error >= this.count.total) {
|
||||
this.option.hide || $.msg.close(this.loader);
|
||||
if (this.option.mult > 0 && this.option.elem.data('input')) {
|
||||
let urls = this.option.elem.data('input').value || [];
|
||||
if (typeof urls === 'string') urls = urls.split('|');
|
||||
for (let i in this.files) urls.push(this.files[i].xurl);
|
||||
$(this.option.elem.data('input')).val(urls.join('|')).trigger('change', this.files);
|
||||
}
|
||||
this.event('upload.complete', {file: this.files}, file).init().uploader && this.uploader.reload();
|
||||
}
|
||||
};
|
||||
|
||||
/*! 触发事件过程 */
|
||||
Adapter.prototype.event = function (name, data, file, message) {
|
||||
if (name === 'upload.error') {
|
||||
this.count.error++, file.xstate = -1, file.xstats = message;
|
||||
if (file.notify) file.notify.setError(message || file.xstats || '');
|
||||
} else if (name === 'upload.done') {
|
||||
this.count.success++, file.xstate = 1, file.xstats = message;
|
||||
if (file.notify) file.notify.setSuccess(message || file.xstats || '')
|
||||
}
|
||||
if (this.option.elem) {
|
||||
this.option.elem.triggerHandler(name, data);
|
||||
if (this.option.input) this.option.input.triggerHandler(name, data);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* 计算文件 HASH 值
|
||||
* @param {File} file 文件对象
|
||||
* @return {Promise}
|
||||
*/
|
||||
Adapter.prototype.hash = function (file) {
|
||||
let defer = jQuery.Deferred();
|
||||
file.xext = file.name.indexOf('.') > -1 ? file.name.split('.').pop() : 'tmp';
|
||||
|
||||
/*! 兼容不能计算文件 HASH 的情况 */
|
||||
let IsDate = '{$nameType|default=""}'.indexOf('date') > -1;
|
||||
if (!window.FileReader || IsDate) return jQuery.when((function (xmd5, chars) {
|
||||
while (xmd5.length < 32) xmd5 += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
return SetFileXdata(file, xmd5, 6), defer.promise();
|
||||
})(layui.util.toDateString(Date.now(), 'yyyyMMddHHmmss-'), '0123456789'));
|
||||
|
||||
/*! 读取文件并计算 HASH 值 */
|
||||
return new LoadNextChunk(file).ReadAsChunk();
|
||||
|
||||
function SetFileXdata(file, xmd5, slice) {
|
||||
file.xmd5 = xmd5, file.xstate = 0, file.xstats = '';
|
||||
file.xkey = file.xmd5.substring(0, slice || 2) + '/' + file.xmd5.substring(slice || 2) + '.' + file.xext;
|
||||
if (file.path) file.xkey = file.path + '/' + file.xkey;
|
||||
return defer.resolve(file, file.xmd5, file.xkey), file;
|
||||
}
|
||||
|
||||
function LoadNextChunk(file) {
|
||||
let that = this, reader = new FileReader(), spark = new SparkMD5.ArrayBuffer();
|
||||
let slice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
|
||||
this.chunkIdx = 0, this.chunkSize = 2097152, this.chunkTotal = Math.ceil(file.size / this.chunkSize);
|
||||
reader.onload = function (event) {
|
||||
spark.append(event.target.result);
|
||||
++that.chunkIdx < that.chunkTotal ? that.ReadAsChunk() : SetFileXdata(file, spark.end());
|
||||
}, reader.onerror = function () {
|
||||
defer.reject();
|
||||
}, this.ReadAsChunk = function () {
|
||||
this.start = that.chunkIdx * that.chunkSize;
|
||||
this.loaded = this.start + that.chunkSize >= file.size ? file.size : this.start + that.chunkSize;
|
||||
reader.readAsArrayBuffer(slice.call(file, this.start, this.loaded));
|
||||
defer.notify(file, (this.loaded / file.size * 100).toFixed(2));
|
||||
return defer.promise();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return UploadAdapter;
|
||||
|
||||
/**
|
||||
* 上传状态提示扩展插件
|
||||
* @param {File} file 文件对象
|
||||
* @constructor
|
||||
*/
|
||||
function NotifyExtend(file) {
|
||||
let that = this, message = "{:lang('上传进度 %s', ['<span data-upload-progress>0%</span>'])}";
|
||||
this.notify = Notify.notify({width: 260, title: file.name, showProgress: true, description: message, type: 'default', position: 'top-right', closeTimeout: 0});
|
||||
this.$elem = $(this.notify.notification.nodes);
|
||||
this.$elem.find('.growl-notification__progress').addClass('is-visible');
|
||||
this.$elem.find('.growl-notification__progress-bar').addClass('transition');
|
||||
this.setProgress = function (number) {
|
||||
this.$elem.find('[data-upload-progress]').html(number + '%');
|
||||
this.$elem.find('.growl-notification__progress-bar').css({width: number + '%'});
|
||||
return this;
|
||||
}, this.setError = function (message) {
|
||||
this.$elem.find('.growl-notification__desc').html(message || '{:lang("文件上传失败!")}');
|
||||
this.$elem.removeClass('growl-notification--default').addClass('growl-notification--error')
|
||||
return this.close();
|
||||
}, this.setSuccess = function (message) {
|
||||
this.setProgress('100.00');
|
||||
this.$elem.find('.growl-notification__desc').html(message || '{:lang("文件上传成功!")}');
|
||||
this.$elem.removeClass('growl-notification--default').addClass('growl-notification--success');
|
||||
return this.close();
|
||||
}, this.close = function (timeout) {
|
||||
return setTimeout(function () {
|
||||
that.notify.close();
|
||||
}, timeout || 2000), this;
|
||||
};
|
||||
}
|
||||
});
|
||||
161
app/admin/view/api/upload/image.html
Normal file
161
app/admin/view/api/upload/image.html
Normal file
@@ -0,0 +1,161 @@
|
||||
<div class="image-dialog" id="ImageDialog">
|
||||
<div class="image-dialog-head">
|
||||
<label class="pull-left flex">
|
||||
<input class="layui-input margin-right-5" v-model="keys" style="height:30px;line-height:30px" placeholder="{:lang('请输入搜索关键词')}">
|
||||
<a class="layui-btn layui-btn-sm layui-btn-normal" @click="search">{:lang('搜 索')}</a>
|
||||
</label>
|
||||
<div class="pull-right">
|
||||
<a class="layui-btn layui-btn-sm layui-btn-normal" @click="uploadImage">{:lang('上传图片')}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-dialog-body">
|
||||
<div class="image-dialog-item" v-for="x in list" @click="setItem(x)" style="display:none" v-show="show" :class="{'image-dialog-checked':x.checked}">
|
||||
<div class="uploadimage" :style="x.style"></div>
|
||||
<p class="image-dialog-item-name layui-elip" v-text="x.name"></p>
|
||||
<div class="image-dialog-item-tool">
|
||||
<span class="image-dialog-item-type">{{x.xext.toUpperCase()}}</span>
|
||||
<span class="image-dialog-item-size">{{formatSize(x.size)}}</span>
|
||||
{if auth('admin/file/remove')}
|
||||
<span class="layui-icon layui-icon-close image-dialog-item-close" @click.stop="remove(x)"></span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-dialog-foot">
|
||||
<div id="ImageDialogPage" class="image-dialog-page"></div>
|
||||
<div id="ImageDialogButton layui-hide" class="image-dialog-button layui-btn layui-btn-normal" v-if="data.length>0" @click="confirm">
|
||||
{php} $tag = '{{data.length}}'; {/php}
|
||||
{:lang('已选 %s 张,确认', [$tag])}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
require(['vue'], function (vue) {
|
||||
var app = new vue({
|
||||
el: '#ImageDialog',
|
||||
data: {
|
||||
didx: 0,
|
||||
page: 1, limit: 15, show: false, mult: false,
|
||||
keys: '', list: [], data: [], idxs: {}, urls: [],
|
||||
},
|
||||
created: function () {
|
||||
this.didx = $.msg.mdx.pop();
|
||||
this.$btn = $('#{$get.id|default=""}');
|
||||
this.$ups = $('#ImageDialogUploadLayout [data-file]');
|
||||
this.mult = "{$get.file|default='image'}" === 'images';
|
||||
this.loadPage(), setTimeout(function () {
|
||||
$('#ImageDialogButton').removeClass('layui-hide');
|
||||
}, 1000);
|
||||
},
|
||||
methods: {
|
||||
// 搜索刷新数据
|
||||
search: function () {
|
||||
this.page = 1;
|
||||
this.loadPage();
|
||||
},
|
||||
// 确认选择数据
|
||||
confirm: function () {
|
||||
this.urls = [];
|
||||
this.data.forEach(function (file) {
|
||||
app.setValue(file.xurl);
|
||||
});
|
||||
this.setInput();
|
||||
},
|
||||
// 删除指定的图片
|
||||
remove: function (x) {
|
||||
$.msg.confirm('确认要移除这张图片吗?', function () {
|
||||
$.form.load('{:url("admin/file/remove")}', {id: x.id}, 'POST', function (ret) {
|
||||
ret.code > 0 ? app.loadPage() : $.msg.error(ret.info);
|
||||
return app.$forceUpdate(), false;
|
||||
})
|
||||
})
|
||||
},
|
||||
// 格式文件大小
|
||||
formatSize: function (size) {
|
||||
return $.formatFileSize(size);
|
||||
},
|
||||
// 设置单项数据
|
||||
setItem: function (item) {
|
||||
if (!this.mult) {
|
||||
this.setValue(item.xurl).setInput();
|
||||
} else if ((item.checked = !this.idxs[item.id])) {
|
||||
(this.idxs[item.id] = item) && this.data.push(item);
|
||||
} else {
|
||||
delete this.idxs[item.id];
|
||||
this.data.forEach(function (temp, idx) {
|
||||
temp.id === item.id && app.data.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
// 更新列表数据
|
||||
setList: function (items, count) {
|
||||
this.list = items;
|
||||
this.list.forEach(function (item) {
|
||||
item.checked = !!app.idxs[item.id]
|
||||
item.style = 'background-image:url(' + item.xurl + ')';
|
||||
});
|
||||
this.addPage(count);
|
||||
},
|
||||
// 设置选择数据
|
||||
setValue: function (xurl) {
|
||||
$.msg.close(this.didx);
|
||||
this.urls.push(xurl) && this.$btn.triggerHandler('push', xurl);
|
||||
return this;
|
||||
},
|
||||
// 设置输入表单
|
||||
setInput: function () {
|
||||
if (this.$btn.data('input')) {
|
||||
$(this.$btn.data('input')).val(this.urls.join('|')).trigger('change');
|
||||
}
|
||||
},
|
||||
// 创建分页工具条
|
||||
addPage: function (count) {
|
||||
this.show = true;
|
||||
layui.laypage.render({
|
||||
curr: this.page, count: count, limit: app.limit,
|
||||
layout: ['count', 'prev', 'page', 'next', 'refresh'],
|
||||
elem: 'ImageDialogPage', jump: function (obj, first) {
|
||||
if (!first) app.loadPage(app.page = obj.curr);
|
||||
},
|
||||
});
|
||||
},
|
||||
// 加载页面数据
|
||||
loadPage: function () {
|
||||
this.params = {page: this.page, limit: this.limit, output: 'layui.table', name: this.keys || ''};
|
||||
this.params.type = '{$get.type|default="gif,png,jpg,jpeg"}';
|
||||
$.form.load('{:url("image",[],false,true)}', this.params, 'get', function (ret) {
|
||||
return app.setList(ret.data, ret.count), false;
|
||||
});
|
||||
},
|
||||
// 上传图片文件
|
||||
uploadImage: function () {
|
||||
this.urls = [];
|
||||
this.$ups.off('push').on('push', function (e, xurl) {
|
||||
app.setValue(xurl);
|
||||
}).off('upload.complete').on('upload.complete', function () {
|
||||
app.setInput();
|
||||
}).click();
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<label class="layui-hide" id="ImageDialogUploadLayout">
|
||||
<!-- 图片上传组件 开始 -->
|
||||
{if isset($get.file) && $get.file eq 'image'}
|
||||
<button data-file="one" data-type="{$get.type|default='gif,png,jpg,jpeg'}"
|
||||
data-path="{$get.path|default=''}" data-size="{$get.size|default=0}"
|
||||
data-cut-width="{$get.cutWidth|default=0}" data-cut-height="{$get.cutHeight|default=0}"
|
||||
data-max-width="{$get.maxWidth|default=0}" data-max-height="{$get.maxHeight|default=0}"
|
||||
></button>
|
||||
{else}
|
||||
<button data-file="mul" data-type="{$get.type|default='gif,png,jpg,jpeg'}"
|
||||
data-path="{$get.path|default=''}" data-size="{$get.size|default=0}"
|
||||
data-cut-width="{$get.cutWidth|default=0}" data-cut-height="{$get.cutHeight|default=0}"
|
||||
data-max-width="{$get.maxWidth|default=0}" data-max-height="{$get.maxHeight|default=0}"
|
||||
></button>
|
||||
{/if}
|
||||
<!-- 图片上传组件 结束 -->
|
||||
</label>
|
||||
143
app/admin/view/auth/form.html
Normal file
143
app/admin/view/auth/form.html
Normal file
@@ -0,0 +1,143 @@
|
||||
{extend name='main'}
|
||||
|
||||
{block name="button"}
|
||||
<button data-target-submit class='layui-btn layui-btn-sm'>{:lang('保存数据')}</button>
|
||||
<button data-target-backup class="layui-btn layui-btn-sm layui-btn-danger">{:lang('取消编辑')}</button>
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
<form method="post" id="RoleForm" class="layui-form layui-card">
|
||||
<div class="layui-card-body">
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('权限名称')}</b>Auth Name</span>
|
||||
<input maxlength="100" class="layui-input" name="title" value='{$vo.title|default=""}' required vali-name="{:lang('权限名称')}" placeholder="{:lang('请输入权限名称')}">
|
||||
<span class="help-block">{:lang('访问权限名称需要保持不重复,在给用户授权时需要根据名称选择!')}</span>
|
||||
</label>
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('权限描述')}</b>Auth Remark</span>
|
||||
<textarea placeholder="{:lang('请输入权限描述')}" maxlength="200" class="layui-textarea" name="desc">{$vo.desc|default=""}</textarea>
|
||||
</label>
|
||||
<div class="layui-form-item">
|
||||
<span class="help-label label-required-prev"><b>{:lang('功能节点')}</b>Auth Nodes</span>
|
||||
<ul id="zTree" class="ztree notselect"></ul>
|
||||
</div>
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input name="id" value="{$vo.id}" type="hidden"/>{/notempty}
|
||||
<div class="layui-form-item text-center">
|
||||
<button data-target-submit class="layui-btn">{:lang('保存数据')}</button>
|
||||
<button data-target-backup class="layui-btn layui-btn-danger" type="button">{:lang('取消编辑')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name="script"}
|
||||
<script>
|
||||
require(['jquery.ztree'], function () {
|
||||
new function () {
|
||||
let that = this;
|
||||
this.data = {}, this.ztree = null, this.setting = {
|
||||
view: {showLine: false, showIcon: false, dblClickExpand: false},
|
||||
check: {enable: true, nocheck: false, chkboxType: {"Y": "ps", "N": "ps"}}, callback: {
|
||||
beforeClick: function (id, node) {
|
||||
node.children.length < 1 ? that.ztree.checkNode(node, !node.checked, true, true) : that.ztree.expandNode(node);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
this.renderChildren = function (list, level) {
|
||||
let childrens = [];
|
||||
for (let i in list) childrens.push({
|
||||
open: true, node: list[i].node, name: list[i].title || list[i].node,
|
||||
checked: list[i].checked || false, children: this.renderChildren(list[i]._sub_, level + 1)
|
||||
});
|
||||
return childrens;
|
||||
};
|
||||
this.syncData = function () {
|
||||
$.form.load('{:sysuri()}', {id: '{$vo.id|default=0}', action: 'json'}, 'post', function (ret) {
|
||||
return (that.data = that.renderChildren(ret.data, 1)), that.showTree(), false;
|
||||
});
|
||||
};
|
||||
this.showTree = function () {
|
||||
this.ztree = $.fn.zTree.init($("#zTree"), this.setting, this.data);
|
||||
while (true) {
|
||||
let nodes = this.ztree.getNodesByFilter(function (node) {
|
||||
return (!node.node && node.children.length < 1);
|
||||
});
|
||||
if (nodes.length < 1) break;
|
||||
for (let i in nodes) this.ztree.removeNode(nodes[i]);
|
||||
}
|
||||
};
|
||||
// 刷新数据
|
||||
this.syncData();
|
||||
// 监听表单提交
|
||||
$('#RoleForm').vali(function (form) {
|
||||
let data = that.ztree.getCheckedNodes(true);
|
||||
Object.assign(form, {nodes: [], action: 'save'})
|
||||
for (let i in data) if (data[i].node) form.nodes.push(data[i].node);
|
||||
$.form.load('{:sysuri()}', form, 'post');
|
||||
});
|
||||
};
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
|
||||
{block name="style"}
|
||||
<style>
|
||||
ul.ztree li {
|
||||
line-height: 24px;
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
ul.ztree li span.button.switch {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
ul.ztree ul ul li {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
ul.ztree > li {
|
||||
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||
padding: 15px;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 3px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
ul.ztree > li > ul {
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
ul.ztree > li > ul > li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
ul.ztree > li > a > span {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
ul.ztree .level2 .button.level2 {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
ul.ztree li span.button.noline_open {
|
||||
background-position-y: -73px;
|
||||
}
|
||||
|
||||
ul.ztree li span.button.noline_close {
|
||||
background-position-y: -73px;
|
||||
}
|
||||
|
||||
ul.ztree .level1 > .node_name {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
{/block}
|
||||
76
app/admin/view/auth/index.html
Normal file
76
app/admin/view/auth/index.html
Normal file
@@ -0,0 +1,76 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("add")}-->
|
||||
<button data-open='{:url("add")}' data-table-id="RoleTable" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('添加权限')}</button>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth("remove")}-->
|
||||
<button data-action='{:url("remove")}' data-rule="id#{id}" data-table-id="RoleTable" data-confirm="{:lang('确定要批量删除权限吗?')}" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量删除')}</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
{include file='auth/index_search'}
|
||||
<table id="RoleTable" data-url="{:request()->url()}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='script'}
|
||||
<script>
|
||||
$(function () {
|
||||
// 初始化表格组件
|
||||
$('#RoleTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'sort desc,id', type: 'desc'},
|
||||
cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field: 'sort', title: '{:lang("排序权重")}', align: 'center', width: 100, sort: true, templet: '#SortInputRoleTableTpl'},
|
||||
{field: 'title', title: '{:lang("权限名称")}', align: 'center', minWidth: 140},
|
||||
{field: 'desc', title: '{:lang("权限描述")}', align: 'center', minWidth: 110, templet: '<div>{{d.desc||"-"}}</div>'},
|
||||
{field: 'status', title: '{:lang("使用状态")}', align: 'center', minWidth: 110, templet: '#StatusSwitchRoleTableTpl'},
|
||||
{field: 'create_at', title: '{:lang("创建时间")}', align: 'center', minWidth: 170, sort: true},
|
||||
{toolbar: '#ToolbarRoleTableTpl', title: '{:lang("操作面板")}', align: 'center', minWidth: 210, fixed: 'right'},
|
||||
]]
|
||||
});
|
||||
|
||||
// 数据状态切换操作
|
||||
layui.form.on('switch(StatusSwitchRoleTable)', function (obj) {
|
||||
let data = {id: obj.value, status: obj.elem.checked > 0 ? 1 : 0};
|
||||
$.form.load("{:url('state')}", data, 'post', function (ret) {
|
||||
if (ret.code < 1) $.msg.error(ret.info, 3, function () {
|
||||
$('#RoleTable').trigger('reload');
|
||||
});
|
||||
return false;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- 列表排序权重模板 -->
|
||||
<script type="text/html" id="SortInputRoleTableTpl">
|
||||
<input type="number" min="0" data-blur-number="0" data-action-blur="{:request()->url()}" data-value="id#{{d.id}};action#sort;sort#{value}" data-loading="false" value="{{d.sort}}" class="layui-input text-center">
|
||||
</script>
|
||||
|
||||
<!-- 数据状态切换模板 -->
|
||||
<script type="text/html" id="StatusSwitchRoleTableTpl">
|
||||
<!--{if auth("state")}-->
|
||||
<input type="checkbox" value="{{d.id}}" lay-skin="switch" lay-text="{:lang('已激活')}|{:lang('已禁用')}" lay-filter="StatusSwitchRoleTable" {{-d.status>0?'checked':''}}>
|
||||
<!--{else}-->
|
||||
{{-d.status ? '<b class="color-green">{:lang("已启用")}</b>' : '<b class="color-red">{:lang("已禁用")}</b>'}}
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
|
||||
<!-- 数据操作工具条模板 -->
|
||||
<script type="text/html" id="ToolbarRoleTableTpl">
|
||||
<!--{if auth('edit')}-->
|
||||
<a class="layui-btn layui-btn-primary layui-btn-sm" data-open='{:url("edit")}?id={{d.id}}'>{:lang("编 辑")}</a>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth("remove")}-->
|
||||
<a class="layui-btn layui-btn-danger layui-btn-sm" data-action="{:url('remove')}" data-value="id#{{d.id}}" data-confirm="{:lang('确定要删除权限吗?')}">{:lang("删 除")}</a>
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
{/block}
|
||||
45
app/admin/view/auth/index_search.html
Normal file
45
app/admin/view/auth/index_search.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<fieldset>
|
||||
<legend>{:lang('条件搜索')}</legend>
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('权限名称')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="title" value="{$get.title|default=''}" placeholder="{:lang('请输入权限名称')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('权限描述')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="desc" value="{$get.desc|default=''}" placeholder="{:lang('请输入权限描述')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('使用状态')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select class="layui-select" name="status">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach [lang('已禁用记录'),lang('已激活记录')] as $k=>$v}
|
||||
{if isset($get.status) and $get.status eq $k.""}
|
||||
<option selected value="{$k}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('创建时间')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="{:lang('请选择创建时间')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
68
app/admin/view/base/form.html
Normal file
68
app/admin/view/base/form.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="BaseTable">
|
||||
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
<div class="layui-form-item label-required-prev">
|
||||
<div class="help-label"><b>数据类型</b>Data Type</div>
|
||||
{if isset($vo.type)}
|
||||
<label><input readonly value="{$vo.type|default=''}" class="layui-input think-bg-gray"></label>
|
||||
{else}
|
||||
<select class="layui-select" lay-filter="DataType">
|
||||
{foreach $types as $type}{if (isset($vo.type) and $type eq $vo.type) or ($type eq input('get.type'))}
|
||||
<option selected value="{$type}">{$type}</option>
|
||||
{else}
|
||||
<option value="{$type}">{$type}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
<script>
|
||||
(function (callable) {
|
||||
layui.form.on('select(DataType)', callable);
|
||||
callable({value: "{$vo.type|default=''}" || $('[lay-filter=DataType]').val()});
|
||||
})(function (data) {
|
||||
if (data.value === '--- 新增类型 ---') {
|
||||
$('#DataTypeInput').removeClass('layui-hide').find('input').val('').focus();
|
||||
} else {
|
||||
$('#DataTypeInput').addClass('layui-hide').find('input').val(data.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{/if}
|
||||
<p class="help-block">请选择数据类型,数据创建后不能再次修改哦 ~</p>
|
||||
<div id="DataTypeInput" class="layui-hide relative">
|
||||
<input class="layui-input" maxlength="20" name="type" required vali-name="数据类型" placeholder="请输入数据类型" value="{$vo.type|default=''}">
|
||||
<p class="help-block">请输入新的数据类型,数据创建后不能再次修改哦 ~</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>数据编码</b>Data Code</span>
|
||||
{if isset($vo.code)}
|
||||
<input readonly maxlength="100" class="layui-input think-bg-gray" name="code" value='{$vo.code|default=""}' required placeholder="请输入数据编码">
|
||||
{else}
|
||||
<input maxlength="100" class="layui-input" name="code" value='{$vo.code|default=""}' required vali-name="数据编码" placeholder="请输入数据编码">
|
||||
{/if}
|
||||
<span class="help-block">请输入新的数据编码,数据创建后不能再次修改,同种数据类型的数据编码不能出现重复 ~</span>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>数据名称</b>Data Name</span>
|
||||
<input maxlength="500" class="layui-input" name="name" value='{$vo.name|default=""}' required vali-name="数据名称" placeholder="请输入数据名称">
|
||||
<span class="help-block">请输入当前数据名称,请尽量保持名称的唯一性,数据名称尽量不要出现重复 ~</span>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>数据内容</b>Data Content</span>
|
||||
<textarea name="content" class="layui-textarea" placeholder="请输入数据内容">{$vo.content|default=''}</textarea>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>保存数据</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
86
app/admin/view/base/index.html
Normal file
86
app/admin/view/base/index.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("add")}-->
|
||||
<button data-table-id="BaseTable" data-modal='{:url("add")}?type={$type|default=""}' class='layui-btn layui-btn-sm layui-btn-primary'>添加数据</button>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth("remove")}-->
|
||||
<button data-table-id="BaseTable" data-action='{:url("remove")}' data-rule="id#{id}" data-confirm="确定要批量删除数据吗?" class='layui-btn layui-btn-sm layui-btn-primary'>批量删除</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="layui-tab layui-tab-card">
|
||||
<ul class="layui-tab-title">
|
||||
{foreach $types as $t}{if isset($type) and $type eq $t}
|
||||
<li class="layui-this" data-open="{:sysuri()}?type={$t}">{$t}</li>
|
||||
{else}
|
||||
<li data-open="{:sysuri()}?type={$t}">{$t}</li>
|
||||
{/if}{/foreach}
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
{include file='base/index_search'}
|
||||
<table id="BaseTable" data-url="{:request()->url()}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='script'}
|
||||
<script>
|
||||
$(function () {
|
||||
// 初始化表格组件
|
||||
$('#BaseTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'sort desc,id', type: 'asc'},
|
||||
where: {type: '{$type|default=""}'},
|
||||
cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field: 'sort', title: '{:lang("排序权重")}', width: 100, align: 'center', sort: true, templet: '#SortInputTpl'},
|
||||
// {field: 'type', title: '数据类型', minWidth: 140, align: 'center'},
|
||||
{field: 'code', title: '数据编码', width: '20%', align: 'left'},
|
||||
{field: 'name', title: '数据名称', width: '30%', align: 'left'},
|
||||
{field: 'status', title: '数据状态', minWidth: 110, align: 'center', templet: '#StatusSwitchTpl'},
|
||||
{field: 'create_at', title: '创建时间', minWidth: 170, align: 'center', sort: true},
|
||||
{toolbar: '#toolbar', align: 'center', minWidth: 150, title: '数据操作', fixed: 'right'},
|
||||
]]
|
||||
});
|
||||
|
||||
// 数据状态切换操作
|
||||
layui.form.on('switch(StatusSwitch)', function (obj) {
|
||||
var data = {id: obj.value, status: obj.elem.checked > 0 ? 1 : 0};
|
||||
$.form.load("{:url('state')}", data, 'post', function (ret) {
|
||||
if (ret.code < 1) $.msg.error(ret.info, 3, function () {
|
||||
$('#BaseTable').trigger('reload');
|
||||
});
|
||||
return false;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- 列表排序权重模板 -->
|
||||
<script type="text/html" id="SortInputTpl">
|
||||
<input type="number" min="0" data-blur-number="0" data-action-blur="{:sysuri()}" data-value="id#{{d.id}};action#sort;sort#{value}" data-loading="false" value="{{d.sort}}" class="layui-input text-center">
|
||||
</script>
|
||||
|
||||
<!-- 数据状态切换模板 -->
|
||||
<script type="text/html" id="StatusSwitchTpl">
|
||||
<!--{if auth("state")}-->
|
||||
<input type="checkbox" value="{{d.id}}" lay-skin="switch" lay-text="已激活|已禁用" lay-filter="StatusSwitch" {{-d.status>0?'checked':''}}>
|
||||
<!--{else}-->
|
||||
{{-d.status ? '<b class="color-green">已启用</b>' : '<b class="color-red">已禁用</b>'}}
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
|
||||
<!-- 数据操作工具条模板 -->
|
||||
<script type="text/html" id="toolbar">
|
||||
<!--{if auth('edit')}-->
|
||||
<a class="layui-btn layui-btn-primary layui-btn-sm" data-event-dbclick data-title="编辑数据" data-modal='{:url("edit")}?id={{d.id}}'>编 辑</a>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth("remove")}-->
|
||||
<a class="layui-btn layui-btn-danger layui-btn-sm" data-confirm="确定要删除数据吗?" data-action="{:url('remove')}" data-value="id#{{d.id}}">删 除</a>
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
{/block}
|
||||
42
app/admin/view/base/index_search.html
Normal file
42
app/admin/view/base/index_search.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('数据编码')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="code" value="{$get.code|default=''}" placeholder="{:lang('请输入数据编码')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('数据名称')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input name="name" value="{$get.name|default=''}" placeholder="{:lang('请输入数据名称')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('使用状态')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select class="layui-select" name="status">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach [lang('已禁用记录'),lang('已激活记录')] as $k=>$v}
|
||||
{if isset($get.status) and $get.status eq $k.""}
|
||||
<option selected value="{$k}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('创建时间')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="{:lang('请选择创建时间')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
</div>
|
||||
</form>
|
||||
234
app/admin/view/config/index.html
Normal file
234
app/admin/view/config/index.html
Normal file
@@ -0,0 +1,234 @@
|
||||
{extend name="main"}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if isset($super) and $super}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-primary" data-load="{:url('admin/api.system/config')}">{:lang('清理无效配置')}</a>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth('system')}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-primary" data-modal="{:url('system')}">{:lang('修改系统参数')}</a>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<!--{notempty name='issuper'}-->
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('运行模式')}</b>( {:lang('仅超级管理员可配置')} )
|
||||
</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-btn-group shadow-mini nowrap">
|
||||
<!--{if $app->isDebug()}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-active">{:lang('以开发模式运行')}</a>
|
||||
<a class="layui-btn layui-btn-sm layui-btn-primary" data-confirm="{:lang('确定要切换到生产模式运行吗?')}" data-load="{:url('admin/api.system/debug')}?state=1">{:lang('以生产模式运行')}</a>
|
||||
<!--{else}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-primary" data-confirm="{:lang('确定要切换到开发模式运行吗?')}" data-load="{:url('admin/api.system/debug')}?state=0">{:lang('以开发模式运行')}</a>
|
||||
<a class="layui-btn layui-btn-sm layui-btn-active">{:lang('以生产模式运行')}</a>
|
||||
<!--{/if}-->
|
||||
</div>
|
||||
<div class="margin-top-20">
|
||||
<p><b>{:lang('开发模式')}</b>:{:lang('开发人员或在功能调试时使用,系统异常时会显示详细的错误信息,同时还会记录操作日志及数据库 SQL 语句信息。')}</p>
|
||||
<p><b>{:lang('生产模式')}</b>:{:lang('项目正式部署上线后使用,系统异常时统一显示 “%s”,只记录重要的异常日志信息,强烈推荐上线后使用此模式。',[config('app.error_message')])}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('富编辑器')}</b>( {:lang('仅超级管理员可配置')} )
|
||||
</span>
|
||||
</div>
|
||||
<div class="layui-card-body layui-clear">
|
||||
<div class="layui-btn-group shadow-mini">
|
||||
{if !in_array(sysconf('base.editor'),['ckeditor4','ckeditor5','wangEditor','auto'])}{php}sysconf('base.editor','ckeditor4');{/php}{/if}
|
||||
{foreach ['ckeditor4'=>'CKEditor4','ckeditor5'=>'CKEditor5','wangEditor'=>'wangEditor','auto'=>lang('自适应模式')] as $k => $v}{if sysconf('base.editor') eq $k}
|
||||
{if auth('storage')}<a data-title="配置{$v}" class="layui-btn layui-btn-sm layui-btn-active">{$v}</a>{else}<a class="layui-btn layui-btn-sm layui-btn-active">{$v}</a>{/if}
|
||||
{else}
|
||||
{if auth('storage')}<a data-title="配置{$v}" data-action="{:url('admin/api.system/editor')}" data-value="editor#{$k}" class="layui-btn layui-btn-sm layui-btn-primary">{$v}</a>{else}<a class="layui-btn layui-btn-sm layui-btn-primary">{$v}</a>{/if}
|
||||
{/if}{/foreach}
|
||||
</div>
|
||||
<div class="margin-top-20 full-width pull-left">
|
||||
<p><b>CKEditor4</b>:{:lang('旧版本编辑器,对浏览器兼容较好,但内容编辑体验稍有不足。')}</p>
|
||||
<p><b>CKEditor5</b>:{:lang('新版本编辑器,只支持新特性浏览器,对内容编辑体验较好,推荐使用。')}</p>
|
||||
<p><b>wangEditor</b>:{:lang('国产优质富文本编辑器,对于小程序及App内容支持会更友好,推荐使用。')}</p>
|
||||
<p><b>{:lang('自适应模式')}</b>:{:lang('优先使用新版本编辑器,若浏览器不支持新版本时自动降级为旧版本编辑器。')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--{/notempty}-->
|
||||
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('存储引擎')}</b>( {:lang('文件默认存储方式')} )
|
||||
</span>
|
||||
</div>
|
||||
<!-- 初始化存储配置 -->
|
||||
{if !sysconf('storage.type')}{php}sysconf('storage.type','local');{/php}{/if}
|
||||
{if !sysconf('storage.link_type')}{php}sysconf('storage.link_type','none');{/php}{/if}
|
||||
{if !sysconf('storage.name_type')}{php}sysconf('storage.name_type','xmd5');{/php}{/if}
|
||||
{if !sysconf('storage.allow_exts')}{php}sysconf('storage.allow_exts','doc,gif,ico,jpg,mp3,mp4,p12,pem,png,rar,xls,xlsx');{/php}{/if}
|
||||
{if !sysconf('storage.local_http_protocol')}{php}sysconf('storage.local_http_protocol','follow');{/php}{/if}
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-btn-group shadow-mini nowrap">
|
||||
{foreach $files as $k => $v}{if sysconf('storage.type') eq $k}
|
||||
{if auth('storage')}<a data-title="配置{$v}" data-modal="{:url('storage')}?type={$k}" class="layui-btn layui-btn-sm layui-btn-active">{$v}</a>{else}<a class="layui-btn layui-btn-sm layui-btn-active">{$v}</a>{/if}
|
||||
{else}
|
||||
{if auth('storage')}<a data-title="配置{$v}" data-modal="{:url('storage')}?type={$k}" class="layui-btn layui-btn-sm layui-btn-primary">{$v}</a>{else}<a class="layui-btn layui-btn-sm layui-btn-primary">{$v}</a>{/if}
|
||||
{/if}{/foreach}
|
||||
</div>
|
||||
<div class="margin-top-20 full-width">
|
||||
<p><b>{:lang('本地服务器存储')}</b>:{:lang('文件上传到本地服务器的 `static/upload` 目录,不支持大文件上传,占用服务器磁盘空间,访问时消耗服务器带宽流量。')}</p>
|
||||
<p><b>{:lang('自建Alist存储')}</b>:{:lang('文件上传到 Alist 存储的服务器或云存储空间,根据服务配置可支持大文件上传,不占用本身服务器空间及服务器带宽流量。')}</p>
|
||||
<p><b>{:lang('七牛云对象存储')}</b>:{:lang('文件上传到七牛云存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。')}</p>
|
||||
<p><b>{:lang('又拍云USS存储')}</b>:{:lang('文件上传到又拍云 USS 存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。')}</p>
|
||||
<p><b>{:lang('阿里云OSS存储')}</b>:{:lang('文件上传到阿里云 OSS 存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。')}</p>
|
||||
<p><b>{:lang('腾讯云COS存储')}</b>:{:lang('文件上传到腾讯云 COS 存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('系统参数')}</b>( {:lang('当前系统配置参数')} )
|
||||
</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('网站名称')}</b>Website</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('site_name')}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('site_name')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<div class="help-block">{:lang('网站名称及网站图标,将显示在浏览器的标签上。')}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('管理程序名称')}</b>Name</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('app_name')}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('app_name')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<div class="help-block">{:lang('管理程序名称,将显示在后台左上角标题。')}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('管理程序版本')}</b>Version</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('app_version')}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('app_version')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<div class="help-block">{:lang('管理程序版本,将显示在后台左上角标题。')}</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('公安备案号')}</b>Beian</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('beian')?:'-'}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('beian')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<p class="help-block">
|
||||
{:lang('公安备案号,可以在 %s 查询获取,将在登录页面下面显示。',['<a target="_blank" href="https://www.beian.gov.cn/portal/registerSystemInfo">www.beian.gov.cn</a>'])}
|
||||
</p>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('网站备案号')}</b>Miitbeian</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('miitbeian')?:'-'}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('miitbeian')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<div class="help-block">
|
||||
{:lang('网站备案号,可以在 %s 查询获取,将显示在登录页面下面。',['<a target="_blank" href="https://beian.miit.gov.cn">beian.miit.gov.cn</a>'])}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>{:lang('网站版权信息')}</b>Copyright</div>
|
||||
<label class="relative block">
|
||||
<input readonly value="{:sysconf('site_copy')}" class="layui-input layui-bg-gray">
|
||||
<a data-copy="{:sysconf('site_copy')}" class="layui-icon layui-icon-release input-right-icon"></a>
|
||||
</label>
|
||||
<div class="help-block">{:lang('网站版权信息,在后台登录页面显示版本信息并链接到备案到信息备案管理系统。')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--{if $app->isDebug()}-->
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('系统信息')}</b>( {:lang('仅开发模式可见')} )
|
||||
</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table" lay-even>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('核心框架')}</th>
|
||||
<td><a target="_blank" href="https://www.thinkphp.cn">ThinkPHP Version {$framework.version|default='None'}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('平台框架')}</th>
|
||||
<td><a target="_blank" href="https://thinkadmin.top">ThinkAdmin Version {$thinkadmin.version|default='6.0.0'}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('操作系统')}</th>
|
||||
<td>{:php_uname()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('运行环境')}</th>
|
||||
<td>{:ucfirst($request->server('SERVER_SOFTWARE',php_sapi_name()))} & PHP {$Think.const.PHP_VERSION} & {:ucfirst(app()->db->connect()->getConfig('type'))}</td>
|
||||
</tr>
|
||||
<!-- {notempty name='systemid'} -->
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('系统序号')}</th>
|
||||
<td>{$systemid|default=''}</td>
|
||||
</tr>
|
||||
<!-- {/notempty} -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{notempty name='plugins'}
|
||||
<div class="layui-card padding-20 shadow">
|
||||
<div class="layui-card-header notselect">
|
||||
<span class="help-label">
|
||||
<b style="color:#333!important;">{:lang('应用插件')}</b>( {:lang('仅开发模式可见')} )
|
||||
</span>
|
||||
</div>
|
||||
<div class="layui-card-body">
|
||||
<table class="layui-table" lay-even>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="nowrap text-center">{:lang('应用名称')}</th>
|
||||
<th class="nowrap text-center">{:lang('插件名称')}</th>
|
||||
<th class="nowrap text-left">{:lang('插件包名')}</th>
|
||||
<th class="nowrap text-center">{:lang('插件版本')}</th>
|
||||
<th class="nowrap text-center">{:lang('授权协议')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $plugins as $key=>$plugin}
|
||||
<tr>
|
||||
<td class="nowrap text-center">{$key}</td>
|
||||
<td class="nowrap text-center">{$plugin.name|lang}</td>
|
||||
<td class="nowrap text-left">
|
||||
{if empty($plugin.install.document)}{$plugin.package}
|
||||
{else}<a target="_blank" href="{$plugin.install.document}">{$plugin.package}</a>{/if}
|
||||
</td>
|
||||
<td class="nowrap text-center">{$plugin.install.version|default='unknow'}</td>
|
||||
<td class="nowrap text-center">
|
||||
{if empty($plugin.install.license)} -
|
||||
{elseif is_array($plugin.install.license)}{$plugin.install.license|join='、',###}
|
||||
{else}{$plugin.install.license|default='-'}{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{/notempty}
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
49
app/admin/view/config/storage-0.html
Normal file
49
app/admin/view/config/storage-0.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">命名方式</b><br><span class="nowrap color-desc">NameType</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['xmd5'=>'文件哈希值 ( 支持秒传 )','date'=>'日期+随机 ( 普通上传 )'] as $k=>$v}
|
||||
<label class="think-radio notselect">
|
||||
{if sysconf('storage.name_type') eq $k}
|
||||
<input checked type="radio" name="storage.name_type" value="{$k}" lay-ignore> {$v}
|
||||
{else}
|
||||
<input type="radio" name="storage.name_type" value="{$k}" lay-ignore> {$v}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">类型为“文件哈希”时可以实现文件秒传功能,同一个文件只需上传一次节省存储空间,推荐使用。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">链接类型</b><br><span class="nowrap color-desc">LinkType</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['none'=>'简洁链接','full'=>'完整链接','none+compress'=>'简洁并压缩图片','full+compress'=>'完整并压缩图片'] as $k=>$v}
|
||||
<label class="think-radio notselect">
|
||||
{if sysconf('storage.link_type') eq $k}
|
||||
<input checked type="radio" name="storage.link_type" value="{$k}" lay-ignore> {$v}
|
||||
{else}
|
||||
<input type="radio" name="storage.link_type" value="{$k}" lay-ignore> {$v}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">类型为“简洁链接”时链接将只返回 hash 地址,而“完整链接”将携带参数保留文件名,图片压缩功能云平台会单独收费。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.allow_exts">
|
||||
<b class="color-green">允许类型</b><br><span class="nowrap color-desc">AllowExts</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.allow_exts" type="text" name="storage.allow_exts" value="{:sysconf('storage.allow_exts')}" required vali-name="文件后缀" placeholder="请输入系统文件上传后缀" class="layui-input">
|
||||
<p class="help-block">设置系统允许上传的文件后缀,多个以英文逗号隔开如:png,jpg,rar,doc,未包含在设置内的文件后缀将不被允许上传。</p>
|
||||
</div>
|
||||
</div>
|
||||
98
app/admin/view/config/storage-alioss.html
Normal file
98
app/admin/view/config/storage-alioss.html
Normal file
@@ -0,0 +1,98 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将上传到 <a target="_blank" href="https://www.aliyun.com/minisite/goods?taskCode=shareNew2205&recordId=3646641&userCode=ztlqlu4v">阿里云</a> OSS 存储,需要配置 OSS 公开访问及跨域策略</p>
|
||||
<p>配置跨域访问 CORS 规则,设置:来源 Origin 为 *,允许 Methods 为 POST,允许 Headers 为 *</p>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.alioss_http_protocol')}{php}sysconf('storage.alioss_http_protocol','http');{/php}{/if}
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['http'=>'HTTP','https'=>'HTTPS','auto'=>"AUTO"] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.alioss_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.alioss_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.alioss_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">阿里云OSS存储访问协议,其中 HTTPS 需要配置证书才能使用(AUTO 为相对协议)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">
|
||||
<b class="color-green">存储区域</b><br><span class="nowrap color-desc label-required">Region</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<select class="layui-select" name="storage.alioss_point" lay-search>
|
||||
{foreach $points as $point => $title}
|
||||
{if sysconf('storage.alioss_point') eq $point}
|
||||
<option selected value="{$point}">{$title}( {$point} )</option>
|
||||
{else}
|
||||
<option value="{$point}">{$title}( {$point} )</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
<p class="help-block">阿里云OSS存储空间所在区域,需要严格对应储存所在区域才能上传文件</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alioss_bucket">
|
||||
<b class="color-green">空间名称</b><br><span class="nowrap color-desc">Bucket</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alioss_bucket" type="text" name="storage.alioss_bucket" value="{:sysconf('storage.alioss_bucket')}" required vali-name="空间名称" placeholder="请输入阿里云OSS存储 Bucket (空间名称)" class="layui-input">
|
||||
<p class="help-block">填写阿里云OSS存储空间名称,如:think-admin-oss(需要是全区唯一的值,不存在时会自动创建)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alioss_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alioss_http_domain" type="text" name="storage.alioss_http_domain" value="{:sysconf('storage.alioss_http_domain')}" required vali-name="访问域名" placeholder="请输入阿里云OSS存储 Domain (访问域名)" class="layui-input">
|
||||
<p class="help-block">填写阿里云OSS存储外部访问域名,不需要填写访问协议,如:static.alioss.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alioss_access_key">
|
||||
<b class="color-green">访问密钥</b><br><span class="nowrap color-desc">AccessKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alioss_access_key" type="text" name="storage.alioss_access_key" value="{:sysconf('storage.alioss_access_key')}" required vali-name="访问密钥" placeholder="请输入阿里云OSS存储 AccessKey (访问密钥)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 阿里云 > 个人中心 ] 设置并获取到访问密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alioss_secret_key">
|
||||
<b class="color-green">安全密钥</b><br><span class="nowrap color-desc">SecretKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alioss_secret_key" type="text" name="storage.alioss_secret_key" value="{:sysconf('storage.alioss_secret_key')}" maxlength="43" required vali-name="安全密钥" placeholder="请输入阿里云OSS存储 SecretKey (安全密钥)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 阿里云 > 个人中心 ] 设置并获取到安全密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="alioss">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
81
app/admin/view/config/storage-alist.html
Normal file
81
app/admin/view/config/storage-alist.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将上传到 <a target="_blank" href="https://alist.nn.ci/zh/">Alist</a> 自建存储,需要自行搭建 <a target="_blank" href="https://alist.nn.ci/zh/">Alist</a> 存储服务器。</p>
|
||||
<p>Alist 是一个支持多种存储的文件列表程序,可将各种云盘及本地磁盘资源进行整合。</p>
|
||||
<p>建议不要开放匿名用户访问,尽量使用独立账号管理,需要关闭 “签名所有” 让文件可以直接访问。</p>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.alist_http_protocol')}{php}sysconf('storage.alist_http_protocol','http');{/php}{/if}
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['http'=>'HTTP','https'=>'HTTPS','auto'=>"AUTO"] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.alist_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.alist_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.alist_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">请选择 Alist 存储访问协议,其中 HTTPS 需要配置证书才能使用( AUTO 为相对协议 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alist_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alist_http_domain" type="text" name="storage.alist_http_domain" value="{:sysconf('storage.alist_http_domain')}" required vali-name="访问域名" placeholder="请输入 Alist 存储的访问域名" class="layui-input">
|
||||
<p class="help-block">请填写 Alist 存储访问域名,不需要填写访问协议,如:storage.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alist_savepath">
|
||||
<b class="color-green">存储目录</b><br><span class="nowrap color-desc">Directory</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alist_savepath" type="text" name="storage.alist_savepath" value="{:sysconf('storage.alist_savepath')}" required vali-name="存储目录" placeholder="请输入 Alist 存储目录" class="layui-input">
|
||||
<p class="help-block">请填写 Alist 用户基本目录的相对存储位置,填写 / 表示用户基本目录( 需要拥有读写权限 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alist_username">
|
||||
<b class="color-green">用户账号</b><br><span class="nowrap color-desc">Username</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alist_username" name="storage.alist_username" value="{:sysconf('storage.alist_username')}" maxlength="100" required vali-name="用户账号" placeholder="请输入 Alist 存储的用户账号" class="layui-input">
|
||||
<p class="help-block">请填写 Alist 用户账号,注意此账号需要拥有上面存储目录的访问权限。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.alist_password">
|
||||
<b class="color-green">用户密码</b><br><span class="nowrap color-desc">Password</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.alist_password" name="storage.alist_password" value="{:sysconf('storage.alist_password')}" maxlength="100" required vali-name="用户密码" placeholder="请输入 Alist 存储的用户密码" class="layui-input">
|
||||
<p class="help-block">请填写 Alist 用户登录密码,用于生成文件上传的接口认证令牌,如果填写错误将无法上传文件。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="alist">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
51
app/admin/view/config/storage-local.html
Normal file
51
app/admin/view/config/storage-local.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将存储在本地服务器,默认保存在 public/upload 目录,文件以 HASH 命名。</p>
|
||||
<p>文件存储的目录需要有读写权限,有足够的存储空间。<span class="color-red">特别注意,本地存储暂不支持图片压缩!</span></p>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.local_http_protocol')}{php}sysconf('storage.local_http_protocol','follow');{/php}{/if}
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['follow'=>'FOLLOW','http'=>'HTTP','https'=>'HTTPS','path'=>'PATH','auto'=>'AUTO'] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.local_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.local_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.local_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">本地存储访问协议,其中 HTTPS 需要配置证书才能使用( FOLLOW 跟随系统,PATH 文件路径,AUTO 相对协议 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.local_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.local_http_domain" type="text" name="storage.local_http_domain" value="{:sysconf('storage.local_http_domain')}" placeholder="请输入上传后的访问域名 (非必填项)" class="layui-input">
|
||||
<p class="help-block">填写上传后的访问域名(不指定时根据当前访问地址自动计算),不需要填写访问协议,如:static.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="local">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
97
app/admin/view/config/storage-qiniu.html
Normal file
97
app/admin/view/config/storage-qiniu.html
Normal file
@@ -0,0 +1,97 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将上传到 <a target="_blank" href="https://s.qiniu.com/rYr26v">七牛云</a> 存储,对象存储需要配置为公开访问的 Bucket 空间</p>
|
||||
完成实名认证后可获得 10G 免费存储空间哦!<a target="_blank" href="https://s.qiniu.com/rYr26v">我要免费申请</a>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.qiniu_http_protocol')}{php}sysconf('storage.qiniu_http_protocol','http');{/php}{/if}
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['http'=>'HTTP','https'=>'HTTPS','auto'=>"AUTO"] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.qiniu_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.qiniu_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.qiniu_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">七牛云存储访问协议,其中 HTTPS 需要配置证书才能使用( AUTO 为相对协议 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">
|
||||
<b class="color-green">存储区域</b><br><span class="nowrap color-desc label-required">Region</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<select class="layui-select" name="storage.qiniu_region" lay-search>
|
||||
{foreach $points as $point => $title}
|
||||
{if sysconf('storage.qiniu_region') eq $point}
|
||||
<option selected value="{$point}">{$title}( {$point} )</option>
|
||||
{else}
|
||||
<option value="{$point}">{$title}( {$point} )</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
<p class="help-block">七牛云存储空间所在区域,需要严格对应储存所在区域才能上传文件</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.qiniu_bucket">
|
||||
<b class="color-green">空间名称</b><br><span class="nowrap color-desc">Bucket</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.qiniu_bucket" type="text" name="storage.qiniu_bucket" value="{:sysconf('storage.qiniu_bucket')}" required vali-name="空间名称" placeholder="请输入七牛云存储 Bucket (空间名称)" class="layui-input">
|
||||
<p class="help-block">填写七牛云存储空间名称,如:static</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.qiniu_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.qiniu_http_domain" type="text" name="storage.qiniu_http_domain" value="{:sysconf('storage.qiniu_http_domain')}" required vali-name="访问域名" placeholder="请输入七牛云存储 Domain (访问域名)" class="layui-input">
|
||||
<p class="help-block">填写七牛云存储访问域名,不需要填写访问协议,如:static.qiniu.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.qiniu_access_key">
|
||||
<b class="color-green">访问密钥</b><br><span class="nowrap color-desc">AccessKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.qiniu_access_key" type="text" name="storage.qiniu_access_key" value="{:sysconf('storage.qiniu_access_key')}" required vali-name="访问密钥" placeholder="请输入七牛云授权 AccessKey (访问密钥)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 七牛云 > 个人中心 ] 设置并获取到访问密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.qiniu_secret_key">
|
||||
<b class="color-green">安全密钥</b><br><span class="nowrap color-desc">SecretKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.qiniu_secret_key" type="text" name="storage.qiniu_secret_key" value="{:sysconf('storage.qiniu_secret_key')}" maxlength="43" required vali-name="安全密钥" placeholder="请输入七牛云授权 SecretKey (安全密钥)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 七牛云 > 个人中心 ] 设置并获取到安全密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="qiniu">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
96
app/admin/view/config/storage-txcos.html
Normal file
96
app/admin/view/config/storage-txcos.html
Normal file
@@ -0,0 +1,96 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将上传到 <a target="_blank" href="https://curl.qcloud.com/4t0Mbw2K">腾讯云</a> COS 存储,需要配置 COS 公有读私有写访问权限及跨域策略</p>
|
||||
<p>配置跨域访问 CORS 规则,设置来源 Origin 为 *,允许 Methods 为 POST,允许 Headers 为 *</p>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.txcos_http_protocol')}{php}sysconf('storage.txcos_http_protocol','http');{/php}{/if}
|
||||
{foreach ['http'=>'HTTP','https'=>'HTTPS','auto'=>"AUTO"] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.txcos_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.txcos_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.txcos_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
<p class="help-block">腾讯云COS存储访问协议,其中 HTTPS 需要配置证书才能使用( AUTO 为相对协议 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">
|
||||
<b class="color-green">存储区域</b><br><span class="nowrap color-desc label-required">Region</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<select class="layui-select" name="storage.txcos_point" lay-search>
|
||||
{foreach $points as $point => $title}
|
||||
{if sysconf('storage.txcos_point') eq $point}
|
||||
<option selected value="{$point}">{$title}( {$point} )</option>
|
||||
{else}
|
||||
<option value="{$point}">{$title}( {$point} )</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
<p class="help-block">腾讯云COS存储空间所在区域,需要严格对应储存所在区域才能上传文件</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.txcos_bucket">
|
||||
<b class="color-green">空间名称</b><br><span class="nowrap color-desc">Bucket</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.txcos_bucket" type="text" name="storage.txcos_bucket" value="{:sysconf('storage.txcos_bucket')}" required vali-name="空间名称" placeholder="请输入腾讯云COS存储 Bucket" class="layui-input">
|
||||
<p class="help-block">填写腾讯云COS存储空间名称,如:thinkadmin-1251143395</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.txcos_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.txcos_http_domain" type="text" name="storage.txcos_http_domain" value="{:sysconf('storage.txcos_http_domain')}" required vali-name="访问域名" placeholder="请输入腾讯云COS存储 Domain" class="layui-input">
|
||||
<p class="help-block">填写腾讯云COS存储外部访问域名,不需要填写访问协议,如:static.txcos.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.txcos_access_key">
|
||||
<b class="color-green">访问密钥</b><br><span class="nowrap color-desc">AccessKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.txcos_access_key" type="text" name="storage.txcos_access_key" value="{:sysconf('storage.txcos_access_key')}" required vali-name="访问密钥" placeholder="请输入腾讯云COS存储 AccessKey" class="layui-input">
|
||||
<p class="help-block">可以在 [ 腾讯云 > 个人中心 ] 设置并获取到访问密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.txcos_secret_key">
|
||||
<b class="color-green">安全密钥</b><br><span class="nowrap color-desc">SecretKey</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.txcos_secret_key" type="text" name="storage.txcos_secret_key" value="{:sysconf('storage.txcos_secret_key')}" maxlength="43" required vali-name="安全密钥" placeholder="请输入腾讯云COS存储 SecretKey" class="layui-input">
|
||||
<p class="help-block">可以在 [ 腾讯云 > 个人中心 ] 设置并获取到安全密钥</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="txcos">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
81
app/admin/view/config/storage-upyun.html
Normal file
81
app/admin/view/config/storage-upyun.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-top-20">
|
||||
|
||||
<div class="color-text layui-code text-center layui-bg-gray" style="border-left-width:1px;margin:0 0 15px 40px">
|
||||
<p class="margin-bottom-5 font-w7">文件将上传到 <a target="_blank" href="https://console.upyun.com/register/?invite=PN1cRmjRb">又拍云</a> USS 存储,需要配置 USS 公开访问及跨域策略</p>
|
||||
<p>配置跨域访问 CORS 规则,设置来源 Origin 为 *,允许 Methods 为 POST,允许 Headers 为 *</p>
|
||||
</div>
|
||||
|
||||
{include file='config/storage-0'}
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required">
|
||||
<b class="color-green">访问协议</b><br><span class="nowrap color-desc">Protocol</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
{if !sysconf('storage.upyun_http_protocol')}{php}sysconf('storage.upyun_http_protocol','http');{/php}{/if}
|
||||
<div class="layui-input help-checks">
|
||||
{foreach ['http'=>'HTTP','https'=>'HTTPS','auto'=>"AUTO"] as $protocol=>$remark}
|
||||
<label class="think-radio">
|
||||
{if sysconf('storage.upyun_http_protocol') eq $protocol}
|
||||
<input checked type="radio" name="storage.upyun_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{else}
|
||||
<input type="radio" name="storage.upyun_http_protocol" value="{$protocol}" lay-ignore> {$remark}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">又拍云存储访问协议,其中 HTTPS 需要配置证书才能使用(AUTO 为相对协议)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.upyun_bucket">
|
||||
<b class="color-green">空间名称</b><br><span class="nowrap color-desc">Bucket</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.upyun_bucket" name="storage.upyun_bucket" value="{:sysconf('storage.upyun_bucket')}" required vali-name="空间名称" placeholder="请输入又拍云存储 Bucket (空间名称)" class="layui-input">
|
||||
<p class="help-block">填写又拍云存储空间名称,如:think-admin-uss(需要是全区唯一的值,不存在时会自动创建)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.upyun_http_domain">
|
||||
<b class="color-green">访问域名</b><br><span class="nowrap color-desc">Domain</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.upyun_http_domain" name="storage.upyun_http_domain" value="{:sysconf('storage.upyun_http_domain')}" required vali-name="访问域名" placeholder="请输入又拍云存储 Domain (访问域名)" class="layui-input">
|
||||
<p class="help-block">填写又拍云存储外部访问域名,不需要填写访问协议,如:static.uss.thinkadmin.top</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.upyun_access_key">
|
||||
<b class="color-green">操作账号</b><br><span class="nowrap color-desc">Username</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.upyun_access_key" name="storage.upyun_access_key" value="{:sysconf('storage.upyun_access_key')}" maxlength="100" required vali-name="操作员账号" placeholder="请输入又拍云存储 Username (操作员账号)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 账户管理 > 操作员 ] 设置操作员账号并将空间给予授权。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label" for="storage.upyun_secret_key">
|
||||
<b class="color-green">操作密码</b><br><span class="nowrap color-desc">Password</span>
|
||||
</label>
|
||||
<div class="layui-input-block">
|
||||
<input id="storage.upyun_secret_key" name="storage.upyun_secret_key" value="{:sysconf('storage.upyun_secret_key')}" maxlength="100" required vali-name="操作员密码" placeholder="请输入又拍云存储 Password (操作员密码)" class="layui-input">
|
||||
<p class="help-block">可以在 [ 账户管理 > 操作员 ] 设置操作员密码并将空间给予授权</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed margin-left-40"></div>
|
||||
<input type="hidden" name="storage.type" value="upyun">
|
||||
|
||||
<div class="layui-form-item text-center padding-left-40">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
129
app/admin/view/config/system.html
Normal file
129
app/admin/view/config/system.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card">
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
<div class="layui-row layui-col-space15 margin-bottom-5">
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>登录表单标题</b>Login Name</span>
|
||||
<input name="login_name" required placeholder="请输入登录页面的表单标题" vali-name="登录标题" value="{:sysconf('login_name')?:'系统管理'}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<div class="help-label label-required-prev"><b>后台登录入口</b>Login Entry</div>
|
||||
<label class="layui-input relative block nowrap label-required-null">
|
||||
<span>{:sysuri('@',[],false,true)}</span>
|
||||
<input autofocus required pattern="[a-zA-Z_][a-zA-Z0-9_]*" vali-name="登录入口" placeholder="请输入后台登录入口" class="layui-input inline-block padding-0 border-0" style="width:100px;background:none" value="{:substr(sysuri('admin/index/index',[],false), strlen(sysuri('@')))}" name="xpath">
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<div class="help-label label-required-prev"><b>后台默认配色</b>Theme Style</div>
|
||||
<select class="layui-select" name="site_theme" lay-filter="SiteTheme">
|
||||
{foreach $themes as $k=>$v}{if sysconf('base.site_theme') eq $k}
|
||||
<option selected value="{$k}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-col-xs12 padding-top-0 padding-bottom-0">
|
||||
<span class="help-block">后台登录入口是由英文字母开头,且不能有相同名称的模块,设置之后原地址不能继续访问,请谨慎配置 ~</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item margin-bottom-5">
|
||||
<div class="help-label"><b>登录背景图片</b>Background Image</div>
|
||||
<div class="layui-textarea help-images">
|
||||
<input type="hidden" value="{:sysconf('login_image')}" name="login_image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item margin-bottom-5">
|
||||
<div class="help-label label-required-prev"><b>JWT 接口密钥</b>Jwt Key</div>
|
||||
<label class="relative block label-required-null">
|
||||
<input class="layui-input" pattern=".{32}" maxlength="32" required vali-name="接口密钥" placeholder="请输入32位JWT接口密钥" name="data.jwtkey" value="{:sysconf('data.jwtkey')?:md5(uniqid(strval(rand(1000,9999)),true))}">
|
||||
<a class="input-right-icon layui-icon layui-icon-refresh" id="RefreshJwtKey"></a>
|
||||
</label>
|
||||
<div class="help-block sub-span-blue">
|
||||
请输入 <span>32</span> 位 <span>JWT</span> 接口密钥,在使用 <span>JWT</span> 接口时需要使用此密钥进行加密及签名!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item margin-bottom-5">
|
||||
<div class="help-label label-required-prev"><b>浏览器小图标</b>Browser Icon</div>
|
||||
<div class="relative block label-required-null">
|
||||
<input class="layui-input" required pattern="url" vali-name="图标文件" data-tips-image data-tips-hover placeholder="请上传浏览器图标" value="{:sysconf('site_icon')}" name="site_icon">
|
||||
<a class="input-right-icon layui-icon layui-icon-upload-drag" data-file="btn" data-type="png,jpg,jpeg" data-field="site_icon"></a>
|
||||
</div>
|
||||
<div class="help-block sub-span-blue">
|
||||
建议上传 <span>128x128</span> 或 <span>256x256</span> 的 <span>JPG</span>,<span>PNG</span>,<span>JPEG</span> 图片,保存后会自动生成 <span>48x48</span> 的 <span>ICO</span> 文件 ~
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-row layui-col-space15 margin-bottom-5">
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<label class="layui-form-item margin-bottom-5 relative block">
|
||||
<span class="help-label"><b>网站名称</b>Site Name</span>
|
||||
<input name="site_name" required placeholder="请输入网站名称" vali-name="网站名称" value="{:sysconf('site_name')}" class="layui-input">
|
||||
<span class="help-block">网站名称将显示在浏览器的标签上 ~</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<label class="layui-form-item margin-bottom-5 relative block">
|
||||
<span class="help-label"><b>后台程序名称</b>App Name</span>
|
||||
<input name="app_name" required placeholder="请输入程序名称" vali-name="程序名称" value="{:sysconf('app_name')}" class="layui-input">
|
||||
<span class="help-block">管理程序名称显示在后台左上标题处 ~</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-bottom-0">
|
||||
<label class="layui-form-item margin-bottom-5 relative block">
|
||||
<span class="help-label"><b>后台程序版本</b>App Version</span>
|
||||
<input name="app_version" placeholder="请输入程序版本" value="{:sysconf('app_version')}" class="layui-input">
|
||||
<span class="help-block">管理程序版本显示在后台左上标题处 ~</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-top-0 padding-bottom-0">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>公安安备号</b>Beian</span>
|
||||
<input name="beian" placeholder="请输入公安安备号" value="{:sysconf('beian')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-top-0 padding-bottom-0">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>网站备案号</b>Miitbeian</span>
|
||||
<input name="miitbeian" placeholder="请输入网站备案号" value="{:sysconf('miitbeian')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4 padding-top-0 padding-bottom-0">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>网站版权信息</b>Copyright</span>
|
||||
<input name="site_copy" required placeholder="请输入版权信息" vali-name="版权信息" value="{:sysconf('site_copy')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs12 help-block padding-top-0">
|
||||
网站备案号和公安备案号可以在<a target="_blank" href="https://beian.miit.gov.cn">备案管理中心</a>查询并获取,网站上线时必需配置备案号,备案号会链接到信息备案管理系统 ~
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消修改吗?" data-close>取消修改</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$('[name=login_image]').uploadMultipleImage();
|
||||
require(['md5'], function (md5) {
|
||||
$('body').off('click', '#RefreshJwtKey').on('click', '#RefreshJwtKey', function () {
|
||||
$(this).parent().find('input').val(md5.hash(Date.toString() + Math.random()));
|
||||
});
|
||||
});
|
||||
layui.form.on('select(SiteTheme)', function (data) {
|
||||
var alls = '', prox = 'layui-layout-theme-', curt = prox + data.value;
|
||||
$(data.elem.options).map(function () {
|
||||
if (this.value !== data.value) alls += ' ' + prox + this.value;
|
||||
});
|
||||
$('.layui-layout-body').removeClass(alls).addClass(curt)
|
||||
});
|
||||
</script>
|
||||
568
app/admin/view/error.php
Normal file
568
app/admin/view/error.php
Normal file
@@ -0,0 +1,568 @@
|
||||
<?php
|
||||
|
||||
if (!function_exists('parse_padding')) {
|
||||
function parse_padding($source)
|
||||
{
|
||||
$length = strlen(strval(count($source['source']) + $source['first']));
|
||||
return 40 + ($length - 1) * 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_class')) {
|
||||
function parse_class($name): string
|
||||
{
|
||||
$names = explode('\\', $name);
|
||||
return '<abbr title="' . $name . '">' . end($names) . '</abbr>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_file')) {
|
||||
function parse_file($file, $line): string
|
||||
{
|
||||
return '<a class="toggle" title="' . "{$file} line {$line}" . '">' . basename($file) . " line {$line}" . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_args')) {
|
||||
function parse_args($args): string
|
||||
{
|
||||
$result = [];
|
||||
foreach ($args as $key => $item) {
|
||||
switch (true) {
|
||||
case is_object($item):
|
||||
$value = sprintf('<em>object</em>(%s)', parse_class(get_class($item)));
|
||||
break;
|
||||
case is_array($item):
|
||||
if (count($item) > 3) {
|
||||
$value = sprintf('[%s, ...]', parse_args(array_slice($item, 0, 3)));
|
||||
} else {
|
||||
$value = sprintf('[%s]', parse_args($item));
|
||||
}
|
||||
break;
|
||||
case is_string($item):
|
||||
if (strlen($item) > 20) {
|
||||
$value = sprintf(
|
||||
'\'<a class="toggle" title="%s">%s...</a>\'',
|
||||
htmlentities($item),
|
||||
htmlentities(substr($item, 0, 20))
|
||||
);
|
||||
} else {
|
||||
$value = sprintf("'%s'", htmlentities($item));
|
||||
}
|
||||
break;
|
||||
case is_int($item):
|
||||
case is_float($item):
|
||||
$value = $item;
|
||||
break;
|
||||
case is_null($item):
|
||||
$value = '<em>null</em>';
|
||||
break;
|
||||
case is_bool($item):
|
||||
$value = '<em>' . ($item ? 'true' : 'false') . '</em>';
|
||||
break;
|
||||
case is_resource($item):
|
||||
$value = '<em>resource</em>';
|
||||
break;
|
||||
default:
|
||||
$value = htmlentities(str_replace("\n", '', var_export(strval($item), true)));
|
||||
break;
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $value : "'{$key}' => {$value}";
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
}
|
||||
if (!function_exists('echo_value')) {
|
||||
function echo_value($val)
|
||||
{
|
||||
if (is_array($val) || is_object($val)) {
|
||||
echo htmlentities(json_encode($val, JSON_PRETTY_PRINT));
|
||||
} elseif (is_bool($val)) {
|
||||
echo $val ? 'true' : 'false';
|
||||
} elseif (is_scalar($val)) {
|
||||
echo htmlentities($val);
|
||||
} else {
|
||||
echo 'Resource';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>系统发生错误</title>
|
||||
<meta name="robots" content="noindex,nofollow"/>
|
||||
<style>
|
||||
/* Base */
|
||||
body {
|
||||
color: #333;
|
||||
font: 16px Verdana, "Helvetica Neue", helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 10px 0 0;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #4288ce;
|
||||
font-weight: 400;
|
||||
padding: 6px 0;
|
||||
margin: 6px 0 0;
|
||||
font-size: 18px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
abbr {
|
||||
cursor: help;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #868686;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.line-error {
|
||||
background: #f8cbcb;
|
||||
}
|
||||
|
||||
.echo table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.echo pre {
|
||||
padding: 16px;
|
||||
overflow: auto;
|
||||
font-size: 85%;
|
||||
line-height: 1.45;
|
||||
background-color: #f7f7f7;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.echo pre > pre {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Exception Info */
|
||||
.exception {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.exception .message {
|
||||
padding: 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-bottom: 0 none;
|
||||
line-height: 18px;
|
||||
font-size: 16px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .code {
|
||||
float: left;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
margin-right: 12px;
|
||||
padding: 16px;
|
||||
border-radius: 4px;
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.exception .source-code {
|
||||
padding: 6px;
|
||||
border: 1px solid #ddd;
|
||||
|
||||
background: #f9f9f9;
|
||||
overflow-x: auto;
|
||||
|
||||
}
|
||||
|
||||
.exception .source-code pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.exception .source-code pre ol {
|
||||
margin: 0;
|
||||
color: #4288ce;
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
font-family: "Century Gothic", Consolas, "Liberation Mono", Courier, Verdana, serif;
|
||||
padding-left: <?php echo (isset($source) && ! empty($source)) ? parse_padding($source): 40;?> px;
|
||||
}
|
||||
|
||||
.exception .source-code pre li {
|
||||
border-left: 1px solid #ddd;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.exception .source-code pre code {
|
||||
color: #333;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-left: 1px solid #fff;
|
||||
font-size: 14px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .trace {
|
||||
padding: 6px;
|
||||
border: 1px solid #ddd;
|
||||
border-top: 0 none;
|
||||
line-height: 16px;
|
||||
font-size: 14px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .trace h2:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.exception .trace ol {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.exception .trace ol li {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.exception div:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/* Exception Variables */
|
||||
.exception-var table {
|
||||
width: 100%;
|
||||
margin: 12px 0;
|
||||
box-sizing: border-box;
|
||||
table-layout: fixed;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.exception-var table caption {
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.exception-var table caption small {
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.exception-var table tbody {
|
||||
font-size: 13px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception-var table td {
|
||||
padding: 0 6px;
|
||||
vertical-align: top;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.exception-var table td:first-child {
|
||||
width: 28%;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.exception-var table td pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Copyright Info */
|
||||
.copyright {
|
||||
margin-top: 24px;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
/* SPAN elements with the classes below are added by prettyprint. */
|
||||
pre.prettyprint .pln {
|
||||
color: #000
|
||||
}
|
||||
|
||||
/* plain text */
|
||||
pre.prettyprint .str {
|
||||
color: #080
|
||||
}
|
||||
|
||||
/* string content */
|
||||
pre.prettyprint .kwd {
|
||||
color: #008
|
||||
}
|
||||
|
||||
/* a keyword */
|
||||
pre.prettyprint .com {
|
||||
color: #800
|
||||
}
|
||||
|
||||
/* a comment */
|
||||
pre.prettyprint .typ {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a type name */
|
||||
pre.prettyprint .lit {
|
||||
color: #066
|
||||
}
|
||||
|
||||
/* a literal value */
|
||||
/* punctuation, lisp open bracket, lisp close bracket */
|
||||
pre.prettyprint .pun, pre.prettyprint .opn, pre.prettyprint .clo {
|
||||
color: #660
|
||||
}
|
||||
|
||||
pre.prettyprint .tag {
|
||||
color: #008
|
||||
}
|
||||
|
||||
/* a markup tag name */
|
||||
pre.prettyprint .atn {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a markup attribute name */
|
||||
pre.prettyprint .atv {
|
||||
color: #080
|
||||
}
|
||||
|
||||
/* a markup attribute value */
|
||||
pre.prettyprint .dec, pre.prettyprint .var {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a declaration; a variable name */
|
||||
pre.prettyprint .fun {
|
||||
color: red
|
||||
}
|
||||
|
||||
/* a function name */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php if (\think\facade\App::isDebug()) { ?>
|
||||
<?php foreach ($traces as $index => $trace) { ?>
|
||||
<div class="exception">
|
||||
<div class="message">
|
||||
<div class="info">
|
||||
<div>
|
||||
<h2><?php echo "#{$index} [{$trace['code']}]" . sprintf('%s in %s', parse_class($trace['name']), parse_file($trace['file'], $trace['line'])); ?></h2>
|
||||
</div>
|
||||
<div><h1><?php echo nl2br(htmlentities($trace['message'])); ?></h1></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (!empty($trace['source'])) { ?>
|
||||
<div class="source-code">
|
||||
<pre class="prettyprint lang-php">
|
||||
<ol start="<?php echo $trace['source']['first']; ?>"><!--<?php foreach ((array)$trace['source']['source'] as $key => $value) { ?>--><li class="line-<?php echo " {$index}-" . ($key + $trace['source']['first']) . ($trace['line'] === $key + $trace['source']['first'] ? ' line-error' : ''); ?>"><code><?php echo htmlentities($value); ?></code></li><!--<?php } ?>--></ol>
|
||||
</pre>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="trace">
|
||||
<h2 data-expand="<?php echo 0 === $index ? '1' : '0'; ?>">Call Stack</h2>
|
||||
<ol>
|
||||
<li><?php echo sprintf('in %s', parse_file($trace['file'], $trace['line'])); ?></li>
|
||||
<?php foreach ((array)$trace['trace'] as $value) { ?>
|
||||
<li>
|
||||
<?php
|
||||
// Show Function
|
||||
if ($value['function']) {
|
||||
echo sprintf('at %s%s%s(%s)', isset($value['class']) ? parse_class($value['class']) : '', $value['type'] ?? '', $value['function'], isset($value['args']) ? parse_args($value['args']) : '');
|
||||
}
|
||||
|
||||
// Show line
|
||||
if (isset($value['file']) && isset($value['line'])) {
|
||||
echo sprintf(' in %s', parse_file($value['file'], $value['line']));
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php } else { ?>
|
||||
<div class="exception">
|
||||
<div class="info"><h1><?php echo htmlentities(isset($message) ? $message : ''); ?></h1></div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (!empty($datas)) { ?>
|
||||
<div class="exception-var">
|
||||
<h2>Exception Datas</h2>
|
||||
<?php foreach ((array)$datas as $label => $value) { ?>
|
||||
<table>
|
||||
<?php if (empty($value)) { ?>
|
||||
<caption><?php echo $label; ?><small>empty</small></caption>
|
||||
<?php } else { ?>
|
||||
<caption><?php echo $label; ?></caption>
|
||||
<tbody>
|
||||
<?php foreach ((array)$value as $key => $val) { ?>
|
||||
<tr>
|
||||
<td><?php echo htmlentities($key); ?></td>
|
||||
<td><?php echo_value($val); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (!empty($tables)) { ?>
|
||||
<div class="exception-var">
|
||||
<h2>Environment Variables</h2>
|
||||
<?php foreach ((array)$tables as $label => $value) { ?>
|
||||
<table>
|
||||
<?php if (empty($value)) { ?>
|
||||
<caption><?php echo $label; ?><small>empty</small></caption>
|
||||
<?php } else { ?>
|
||||
<caption><?php echo $label; ?></caption>
|
||||
<tbody>
|
||||
<?php foreach ((array)$value as $key => $val) { ?>
|
||||
<tr>
|
||||
<td><?php echo htmlentities($key); ?></td>
|
||||
<td><?php echo_value($val); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (\think\facade\App::isDebug()) { ?>
|
||||
<script>
|
||||
function $(selector, node) {
|
||||
var elements;
|
||||
node = node || document;
|
||||
if (document.querySelectorAll) {
|
||||
elements = node.querySelectorAll(selector);
|
||||
} else {
|
||||
switch (selector.substr(0, 1)) {
|
||||
case '#':
|
||||
elements = [node.getElementById(selector.substr(1))];
|
||||
break;
|
||||
case '.':
|
||||
if (document.getElementsByClassName) {
|
||||
elements = node.getElementsByClassName(selector.substr(1));
|
||||
} else {
|
||||
elements = get_elements_by_class(selector.substr(1), node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
elements = node.getElementsByTagName();
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
|
||||
function get_elements_by_class(search_class, node, tag) {
|
||||
var elements = [], eles,
|
||||
pattern = new RegExp('(^|\\s)' + search_class + '(\\s|$)');
|
||||
|
||||
node = node || document;
|
||||
tag = tag || '*';
|
||||
|
||||
eles = node.getElementsByTagName(tag);
|
||||
for (var i = 0; i < eles.length; i++) {
|
||||
if (pattern.test(eles[i].className)) {
|
||||
elements.push(eles[i])
|
||||
}
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
$.getScript = function (src, func) {
|
||||
var script = document.createElement('script');
|
||||
|
||||
script.async = 'async';
|
||||
script.src = src;
|
||||
script.onload = func || function () {
|
||||
};
|
||||
|
||||
$('head')[0].appendChild(script);
|
||||
}
|
||||
|
||||
;(function () {
|
||||
var files = $('.toggle');
|
||||
var ol = $('ol', $('.prettyprint')[0]);
|
||||
var li = $('li', ol[0]);
|
||||
|
||||
// 短路径和长路径变换
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
files[i].ondblclick = function () {
|
||||
var title = this.title;
|
||||
|
||||
this.title = this.innerHTML;
|
||||
this.innerHTML = title;
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
var expand = function (dom, expand) {
|
||||
var ol = $('ol', dom.parentNode)[0];
|
||||
expand = undefined === expand ? dom.attributes['data-expand'].value === '0' : undefined;
|
||||
if (expand) {
|
||||
dom.attributes['data-expand'].value = '1';
|
||||
ol.style.display = 'none';
|
||||
dom.innerText = 'Call Stack (展开)';
|
||||
} else {
|
||||
dom.attributes['data-expand'].value = '0';
|
||||
ol.style.display = 'block';
|
||||
dom.innerText = 'Call Stack (折叠)';
|
||||
}
|
||||
};
|
||||
var traces = $('.trace');
|
||||
for (var i = 0; i < traces.length; i++) {
|
||||
var h2 = $('h2', traces[i])[0];
|
||||
expand(h2);
|
||||
h2.onclick = function () {
|
||||
expand(this);
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
$.getScript('//cdn.bootcss.com/prettify/r298/prettify.min.js', function () {
|
||||
prettyPrint();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php } ?>
|
||||
</body>
|
||||
</html>
|
||||
40
app/admin/view/file/form.html
Normal file
40
app/admin/view/file/form.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="FileTable">
|
||||
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('文件名称')}</b>Name</span>
|
||||
<input maxlength="100" class="layui-input" name="name" value='{$vo.name|default=""}' required vali-name="文件名称" placeholder="请输入文件名称">
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('文件大小')}</b>Size</span>
|
||||
<input maxlength="100" class="layui-input layui-bg-gray" value='{$vo.size|default=0|format_bytes}' readonly>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('存储方式')}</b>Type</span>
|
||||
<input maxlength="100" class="layui-input layui-bg-gray" value='{$types[$vo.type]??""}' readonly>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('文件哈希')}</b>Hash</span>
|
||||
<input maxlength="100" class="layui-input layui-bg-gray" value='{$vo.hash|default=""}' readonly>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>{:lang('文件链接')}</b>Link</span>
|
||||
<input maxlength="100" class="layui-input layui-bg-gray" value='{$vo.xurl|default=""}' readonly>
|
||||
</label>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>{:lang('保存数据')}</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="{:lang('确定要取消编辑吗?')}" data-close>{:lang('取消编辑')}</button>
|
||||
</div>
|
||||
</form>
|
||||
64
app/admin/view/file/index.html
Normal file
64
app/admin/view/file/index.html
Normal file
@@ -0,0 +1,64 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("distinct")}-->
|
||||
<a data-table-id="FileTable" data-load='{:url("distinct")}' class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('清理重复')}</a>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("remove")}-->
|
||||
<a data-confirm="{:lang('确定删除这些记录吗?')}" data-table-id="FileTable" data-action='{:url("remove")}' data-rule="id#{id}" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量删除')}</a>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
{include file='file/index_search'}
|
||||
<table id="FileTable" data-url="{:sysuri('index')}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$('#FileTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'id', type: 'desc'},
|
||||
cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field: 'id', title: 'ID', width: 80, align: 'center', sort: true},
|
||||
{field: 'name', title: '{:lang("文件名称")}', width: '12%', align: 'center'},
|
||||
{field: 'hash', title: '{:lang("文件哈希")}', width: '15%', align: 'center', templet: '<div><code>{{d.hash}}</code></div>'},
|
||||
{field: 'size', title: '{:lang("文件大小")}', align: 'center', width: '7%', sort: true, templet: '<div>{{-$.formatFileSize(d.size)}}</div>'},
|
||||
{field: 'xext', title: '{:lang("文件后缀")}', align: 'center', width: '7%', sort: true},
|
||||
{
|
||||
field: 'xurl', title: '{:lang("查看文件")}', width: '7%', align: 'center', templet: function (d) {
|
||||
if (typeof d.mime === 'string' && /^image\//.test(d.mime)) {
|
||||
return laytpl('<div><a target="_blank" data-tips-hover data-tips-image="{{d.xurl}}"><i class="layui-icon layui-icon-picture"></i></a></div>').render(d)
|
||||
}
|
||||
if (typeof d.mime === 'string' && /^video\//.test(d.mime)) {
|
||||
return laytpl('<div><a target="_blank" data-video-player="{{d.xurl}}" data-tips-text="{:lang(\'播放视频\')}"><i class="layui-icon layui-icon-video"></i></a></div>').render(d);
|
||||
}
|
||||
if (typeof d.mime === 'string' && /^audio\//.test(d.mime)) {
|
||||
return laytpl('<div><a target="_blank" data-video-player="{{d.xurl}}" data-tips-text="{:lang(\'播放音频\')}"><i class="layui-icon layui-icon-headset"></i></a></div>').render(d);
|
||||
}
|
||||
return laytpl('<div><a target="_blank" href="{{d.xurl}}" data-tips-text="{:lang(\'查看下载\')}"><i class="layui-icon layui-icon-file"></i></a></div>').render(d);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'isfast', title: '{:lang("上传方式")}', align: 'center', width: '8%', templet: function (d) {
|
||||
return d.isfast ? '<b class="color-green">{:lang("秒传")}</b>' : '<b class="color-blue">{:lang("普通")}</b>';
|
||||
}
|
||||
},
|
||||
{field: 'ctype', title: '{:lang("存储方式")}', align: 'center', width: '10%'},
|
||||
{field: 'create_at', title: '{:lang("创建时间")}', align: 'center', width: '15%', sort: true},
|
||||
{toolbar: '#toolbar', title: '{:lang("操作面板")}', align: 'center', minWidth: 150, fixed: 'right'}
|
||||
]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="toolbar">
|
||||
<!--{if auth("edit")}-->
|
||||
<a class="layui-btn layui-btn-sm" data-modal="{:url('edit')}?id={{d.id}}" data-title="编辑文件信息">{:lang("编 辑")}</a>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("remove")}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-action="{:url('remove')}" data-value="id#{{d.id}}">{:lang("删 除")}</a>
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
{/block}
|
||||
58
app/admin/view/file/index_search.html
Normal file
58
app/admin/view/file/index_search.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<fieldset>
|
||||
<legend>{:lang('条件搜索')}</legend>
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('文件名称')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="name" value="{$get.name|default=''}" placeholder="{:lang('请输入文件名称')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('文件哈希')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="hash" value="{$get.hash|default=''}" placeholder="{:lang('请输入文件哈希')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('文件后缀')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="xext" lay-search class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach $xexts as $v}{if isset($get.xext) and $k eq $get.xext}
|
||||
<option selected value="{$v}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$v}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('存储方式')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="type" lay-search class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach $types as $k=>$v}{if isset($get.type) and $k eq $get.type}
|
||||
<option selected value="{$k}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('创建时间')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="{:lang('请选择创建时间')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
32
app/admin/view/full.html
Normal file
32
app/admin/view/full.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<title>{block name="title"}{$title|default=''}{if !empty($title)} · {/if}{:sysconf('site_name')}{/block}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=0.4">
|
||||
<link rel="stylesheet" href="__ROOT__/static/plugs/layui/css/layui.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/iconfont.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/console.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/extra/style.css?at={:date('md')}">
|
||||
{block name="style"}{/block}
|
||||
<script src="__ROOT__/static/plugs/jquery/pace.min.js"></script>
|
||||
<script src="{:url('admin/api.plugs/script',[],false,false)}"></script>
|
||||
</head>
|
||||
<body class="layui-layout-body">
|
||||
{block name='body'}
|
||||
<div class="layui-layout layui-layout-admin layui-layout-left-hide">
|
||||
<div class="layui-body think-bg-white margin-0 padding-0" style="top:0">{block name='content'}{/block}</div>
|
||||
</div>
|
||||
{/block}
|
||||
<script src="__ROOT__/static/plugs/layui/layui.js"></script>
|
||||
<script src="__ROOT__/static/plugs/require/require.js"></script>
|
||||
<script src="__ROOT__/static/admin.js"></script>
|
||||
<script src="__ROOT__/static/extra/script.js"></script>
|
||||
{block name='script'}{/block}
|
||||
</body>
|
||||
</html>
|
||||
50
app/admin/view/index/index-left.html
Normal file
50
app/admin/view/index/index-left.html
Normal file
@@ -0,0 +1,50 @@
|
||||
<div class="layui-side">
|
||||
<a class="layui-side-target" data-target-menu-type></a>
|
||||
<a class="layui-logo layui-elip" href="{:sysuri('@')}" title="{:sysconf('app_name')}">
|
||||
<span class="headimg headimg-no headimg-xs" data-lazy-src="{:sysconf('site_icon')}"></span>
|
||||
<span class="headtxt">{:sysconf('app_name')} {if sysconf('app_version')}<sup>{:sysconf('app_version')}</sup>{/if}</span>
|
||||
</a>
|
||||
<div class="layui-side-scroll">
|
||||
<div class="layui-side-icon">
|
||||
{foreach $menus as $one}
|
||||
<div>
|
||||
<a data-menu-node="m-{$one.id}" data-open="{$one.url}" data-target-tips="{$one.title|default=''}">
|
||||
{notempty name='one.icon'}<i class="{$one.icon|default=''}"></i>{/notempty}
|
||||
<span>{$one.title|default=''}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
<div class="layui-side-tree">
|
||||
{foreach $menus as $one}{notempty name='one.sub'}
|
||||
<ul class="layui-nav layui-nav-tree layui-hide" data-menu-layout="m-{$one.id}">
|
||||
{foreach $one.sub as $two}{empty name='two.sub'}
|
||||
<li class="layui-nav-item">
|
||||
<a data-target-tips="{$two.title}" data-menu-node="m-{$one.id}-{$two.id}" data-open="{$two.url}">
|
||||
<span class='nav-icon {$two.icon|default="layui-icon layui-icon-senior"}'></span>
|
||||
<span class="nav-text">{$two.title|default=''}</span>
|
||||
</a>
|
||||
</li>
|
||||
{else}
|
||||
<li class="layui-nav-item" data-submenu-layout='m-{$one.id}-{$two.id}'>
|
||||
<a data-target-tips="{$two.title}">
|
||||
<span class='nav-icon layui-hide {$two.icon|default="layui-icon layui-icon-triangle-d"}'></span>
|
||||
<span class="nav-text">{$two.title|default=''}</span>
|
||||
</a>
|
||||
<dl class="layui-nav-child">
|
||||
{foreach $two.sub as $thr}
|
||||
<dd>
|
||||
<a data-target-tips="{$thr.title}" data-open="{$thr.url}" data-menu-node="m-{$one.id}-{$two.id}-{$thr.id}">
|
||||
<span class='nav-icon {$thr.icon|default="layui-icon layui-icon-senior"}'></span>
|
||||
<span class="nav-text">{$thr.title|default=''}</span>
|
||||
</a>
|
||||
</dd>
|
||||
{/foreach}
|
||||
</dl>
|
||||
</li>
|
||||
{/empty}{/foreach}
|
||||
</ul>
|
||||
{/notempty}{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
49
app/admin/view/index/index-top.html
Normal file
49
app/admin/view/index/index-top.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<div class="layui-header">
|
||||
<ul class="layui-nav layui-layout-left">
|
||||
<li class="layui-nav-item" lay-unselect>
|
||||
<a class="text-center" data-target-menu-type>
|
||||
<i class="layui-icon layui-icon-spread-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="layui-nav-item" lay-unselect>
|
||||
<a class="layui-logo-hide layui-elip" href="{:sysuri('@')}" title="{:sysconf('app_name')}">
|
||||
<span class="headimg headimg-no headimg-xs" data-lazy-src="{:sysconf('site_icon')}"></span>
|
||||
</a>
|
||||
</li>
|
||||
{foreach $menus as $one}
|
||||
<li class="layui-nav-item">
|
||||
<a data-menu-node="m-{$one.id}" data-open="{$one.url}"><span>{$one.title|default=''}</span></a>
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
<ul class="layui-nav layui-layout-right">
|
||||
<li lay-unselect class="layui-nav-item"><a data-reload><i class="layui-icon layui-icon-refresh-3"></i></a></li>
|
||||
{if session('user.username')}
|
||||
<li class="layui-nav-item">
|
||||
<dl class="layui-nav-child">
|
||||
{if isset($super) and $super}
|
||||
|
||||
<dd lay-unselect><a data-modal="{:sysuri('admin/index/info',['id'=>session('user.id')])}"><i class="layui-icon layui-icon-set-fill"></i> {:lang('基本资料')}</a></dd>
|
||||
{/if}
|
||||
<dd lay-unselect><a data-modal="{:sysuri('admin/index/pass',['id'=>session('user.id')])}"><i class="layui-icon layui-icon-component"></i> {:lang('安全设置')}</a></dd>
|
||||
{if isset($super) and $super}
|
||||
<dd lay-unselect><a data-load="{:sysuri('admin/api.system/push')}"><i class="layui-icon layui-icon-template-1"></i> {:lang('缓存加速')}</a></dd>
|
||||
<dd lay-unselect><a data-load="{:sysuri('admin/api.system/clear')}"><i class="layui-icon layui-icon-fonts-clear"></i> {:lang('清理缓存')}</a></dd>
|
||||
{/if}
|
||||
{if isset($super) and $super}
|
||||
<dd lay-unselect><a data-width="520px" data-modal="{:sysuri('admin/index/theme')}"><i class="layui-icon layui-icon-theme"></i> {:lang('配色方案')}</a></dd>
|
||||
{/if}
|
||||
<dd lay-unselect><a data-load="{:sysuri('admin/login/out')}" data-confirm="{:lang('确定要退出登录吗?')}"><i class="layui-icon layui-icon-release"></i> {:lang('退出登录')}</a></dd>
|
||||
</dl>
|
||||
<a class="layui-elip">
|
||||
<span class="headimg" data-lazy-src="{:htmlentities(session('user.headimg'))}"></span>
|
||||
<span>{:htmlentities(lang(session('user.nickname')?:session('user.username')))}</span>
|
||||
</a>
|
||||
</li>
|
||||
{else}
|
||||
<li class="layui-nav-item">
|
||||
<a data-href="{:sysuri('admin/login/index')}"><i class="layui-icon layui-icon-username"></i> {:lang('立即登录')}</a>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
62
app/admin/view/index/index.html
Normal file
62
app/admin/view/index/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<title>{block name="title"}{$title|default=''}{if !empty($title)} · {/if}{:sysconf('site_name')}{/block}</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=0.4">
|
||||
<link rel="stylesheet" href="__ROOT__/static/plugs/layui/css/layui.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/iconfont.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/console.css?at={:date('md')}">
|
||||
<link rel="stylesheet" href="__ROOT__/static/extra/style.css?at={:date('md')}">
|
||||
{block name="style"}{/block}
|
||||
<script src="__ROOT__/static/plugs/jquery/pace.min.js"></script>
|
||||
<script src="{:url('admin/api.plugs/script',[],false,false)}"></script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body layui-layout-theme-{$theme|default='default'}">
|
||||
|
||||
{block name='body'}
|
||||
<div class="layui-layout layui-layout-admin layui-layout-left-hide">
|
||||
|
||||
<!-- 左则菜单 开始 -->
|
||||
{include file="index/index-left"}
|
||||
<!-- 左则菜单 结束 -->
|
||||
|
||||
<!-- 顶部菜单 开始 -->
|
||||
{include file='index/index-top'}
|
||||
<!-- 顶部菜单 结束 -->
|
||||
|
||||
<!-- 主体内容 开始 -->
|
||||
<div class="layui-body">
|
||||
<div class="think-page-body">
|
||||
{block name='content'}{/block}
|
||||
</div>
|
||||
<!-- 页面加载动画 -->
|
||||
<div class="think-page-loader layui-hide">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 主体内容 结束 -->
|
||||
</div>
|
||||
|
||||
<!-- 加载动画 开始 -->
|
||||
<div class="think-page-loader">
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
<!-- 加载动画 结束 -->
|
||||
|
||||
{/block}
|
||||
<script src="__ROOT__/static/plugs/layui/layui.js"></script>
|
||||
<script src="__ROOT__/static/plugs/require/require.js"></script>
|
||||
<script src="__ROOT__/static/admin.js"></script>
|
||||
<script src="__ROOT__/static/extra/script.js"></script>
|
||||
{block name='script'}{/block}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
36
app/admin/view/index/theme.html
Normal file
36
app/admin/view/index/theme.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" id="theme">
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
<div class="layui-form-item margin-bottom-5 label-required-prev">
|
||||
<div class="help-label"><b>后台配色方案</b>Theme Style</div>
|
||||
<div class="layui-textarea think-bg-gray" style="min-height:unset">
|
||||
{foreach $themes as $k=>$v}
|
||||
<label class="think-radio">
|
||||
{if isset($theme) and $theme eq $k}
|
||||
<input name="site_theme" type="radio" value="{$k}" lay-ignore checked> {$v}
|
||||
{else}
|
||||
<input name="site_theme" type="radio" value="{$k}" lay-ignore> {$v}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
<p class="help-block">切换配色方案,需要保存成功后配色方案才会永久生效,下次登录也会有效哦 ~</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type="submit">保存配置</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-close>取消修改</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$('form#theme input[name=site_theme]').on('click', function () {
|
||||
var alls = '', that = this, prox = 'layui-layout-theme-', curt = prox + that.value;
|
||||
$('form#theme input[name=site_theme]').map(function () {
|
||||
if (this.value !== that.value) alls += ' ' + prox + this.value;
|
||||
});
|
||||
$('.layui-layout-body').removeClass(alls).addClass(curt)
|
||||
});
|
||||
</script>
|
||||
57
app/admin/view/login/index.html
Normal file
57
app/admin/view/login/index.html
Normal file
@@ -0,0 +1,57 @@
|
||||
{extend name="index/index"}
|
||||
|
||||
{block name='style'}
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
|
||||
<script>if (location.href.indexOf('#') > -1) location.replace(location.href.split('#')[0])</script>
|
||||
<link rel="stylesheet" href="__ROOT__/static/theme/css/login.css">
|
||||
{/block}
|
||||
|
||||
{block name="body"}
|
||||
<div class="login-container" {$loginStyle|raw}>
|
||||
<div class="header notselect layui-hide-xs">
|
||||
<a href="{:url('@')}" class="title">{:sysconf('app_name')}<span>{:sysconf('app_version')}</span></a>
|
||||
{notempty name='runtimeMode'}
|
||||
<a class="pull-right layui-anim layui-anim-fadein" target="_blank" href='https://gitee.com/zoujingli/ThinkAdmin'>
|
||||
<img src='https://gitee.com/zoujingli/ThinkAdmin/widgets/widget_1.svg' alt='Fork me on Gitee'>
|
||||
</a>
|
||||
{/notempty}
|
||||
</div>
|
||||
<form data-login-form onsubmit="return false" method="post" class="layui-anim layui-anim-upbit" autocomplete="off">
|
||||
<h2 class="notselect">{:sysconf('login_name')?:'系统管理'}</h2>
|
||||
<ul>
|
||||
<li class="username">
|
||||
<label class="label-required-null">
|
||||
<i class="layui-icon layui-icon-username"></i>
|
||||
<input class="layui-input" required pattern="^\S{4,}$" vali-name="登录账号" name="username" autofocus autocomplete="off" placeholder="登录账号">
|
||||
</label>
|
||||
</li>
|
||||
<li class="password">
|
||||
<label class="label-required-null">
|
||||
<i class="layui-icon layui-icon-password"></i>
|
||||
<input class="layui-input" required pattern="^\S{4,}$" vali-name="登录密码" name="password" maxlength="32" type="password" autocomplete="off" placeholder="登录密码" lay-affix="eye">
|
||||
</label>
|
||||
</li>
|
||||
<li class="verify layui-hide">
|
||||
<label class="inline-block relative label-required-null">
|
||||
<i class="layui-icon layui-icon-picture-fine"></i>
|
||||
<input class="layui-input" required pattern="^\S{4,}$" name="verify" maxlength="4" autocomplete="off" vali-name="验证码" placeholder="验证码">
|
||||
</label>
|
||||
<label data-captcha="{:url('admin/login/captcha',[],false)}" data-field-verify="verify" data-field-uniqid="uniqid" data-captcha-type="{$captchaType}" data-captcha-token="{$captchaToken}"></label>
|
||||
</li>
|
||||
<li class="text-center padding-top-20">
|
||||
<button type="submit" class="layui-btn layui-disabled full-width" data-form-loaded="立即登入">正在载入</button>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
<div class="footer notselect">
|
||||
<p class="layui-hide-xs">推荐使用 <a target="_blank" href="https://www.google.cn/chrome">Google Chrome</a> 或 <a target="_blank" href="https://www.microsoft.com/zh-cn/edge#platform">Microsoft Edge</a> 浏览器访问</p>
|
||||
{:sysconf('site_copy')}
|
||||
{if sysconf('beian')}<span class="padding-5">|</span><a target="_blank" href="https://www.beian.gov.cn/portal/registerSystemInfo">{:sysconf('beian')}</a>{/if}
|
||||
{if sysconf('miitbeian')}<span class="padding-5">|</span><a target="_blank" href="https://beian.miit.gov.cn/">{:sysconf('miitbeian')}</a>{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='script'}
|
||||
<script src="__ROOT__/static/login.js"></script>
|
||||
{/block}
|
||||
23
app/admin/view/main.html
Normal file
23
app/admin/view/main.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="layui-card">
|
||||
{block name='style'}{/block}
|
||||
{block name='header'}
|
||||
{notempty name='title'}
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-icon font-s10 color-desc margin-right-5"></span>{$title|lang}
|
||||
<div class="pull-right">{block name='button'}{/block}</div>
|
||||
</div>
|
||||
{/notempty}
|
||||
{/block}
|
||||
<div class="layui-card-line"></div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-card-html">
|
||||
{notempty name='showErrorMessage'}
|
||||
<div class="think-box-notify" type="error">
|
||||
<b>{:lang('系统提示:')}</b><span>{$showErrorMessage|raw}</span>
|
||||
</div>
|
||||
{/notempty}
|
||||
{block name='content'}{/block}
|
||||
</div>
|
||||
</div>
|
||||
{block name='script'}{/block}
|
||||
</div>
|
||||
97
app/admin/view/menu/form.html
Normal file
97
app/admin/view/menu/form.html
Normal file
@@ -0,0 +1,97 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="MenuTable">
|
||||
|
||||
<div class="layui-card-body">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label label-required-next">{:lang('上级菜单')}</label>
|
||||
<div class="layui-input-block">
|
||||
<select name='pid' class='layui-select' lay-search>
|
||||
{foreach $menus as $menu}{eq name='menu.id' value='$vo.pid|default=0'}
|
||||
<option selected value='{$menu.id}'>{$menu.spl|raw}{$menu.title}</option>
|
||||
{else}
|
||||
<option value='{$menu.id}'>{$menu.spl|raw}{$menu.title}</option>
|
||||
{/eq}{/foreach}
|
||||
</select>
|
||||
<p class="help-block"><b>必选</b>,请选择上级菜单或顶级菜单 ( 目前最多支持三级菜单 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{:lang('菜单名称')}</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="title" value='{$vo.title|default=""}' required vali-name="菜单名称" placeholder="请输入菜单名称" class="layui-input">
|
||||
<p class="help-block"><b>必选</b>,请填写菜单名称 ( 如:系统管理 ),建议字符不要太长,一般 4-6 个汉字</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{:lang('菜单链接')}</label>
|
||||
<div class="layui-input-block">
|
||||
<input onblur="this.value=this.value === ''?'#':this.value" name="url" required vali-name="菜单链接" placeholder="请输入菜单链接" value="{$vo.url|default='#'}" class="layui-input">
|
||||
<p class="help-block">
|
||||
<b>必选</b>,请填写链接地址或选择系统节点 ( 如:https://domain.com/admin/user/index.html 或 admin/user/index )
|
||||
<br>当填写链接地址时,以下面的 “权限节点” 来判断菜单自动隐藏或显示,注意未填写 “权限节点” 时将不会隐藏该菜单哦
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{:lang('链接参数')}</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="params" placeholder="请输入链接参数" value="{$vo.params|default=''}" class="layui-input">
|
||||
<p class="help-block"><b>可选</b>,设置菜单链接的 GET 访问参数 ( 如:name=1&age=3 )</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{:lang('权限节点')}</label>
|
||||
<div class="layui-input-block">
|
||||
<input name="node" placeholder="请输入权限节点" value="{$vo.node|default=''}" class="layui-input">
|
||||
<p class="help-block"><b>可选</b>,请填写系统权限节点 ( 如:admin/user/index ),未填写时默认解释"菜单链接"判断是否拥有访问权限;</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{:lang('菜单图标')}</label>
|
||||
<div class="layui-input-block">
|
||||
<div class="layui-input-inline">
|
||||
<input placeholder="请输入或选择图标" name="icon" value='{$vo.icon|default=""}' class="layui-input">
|
||||
</div>
|
||||
<span style="padding:0 12px;min-width:45px" class='layui-btn layui-btn-primary'>
|
||||
<i style="font-size:1.2em;margin:0;float:none" class='{$vo.icon|default=""}'></i>
|
||||
</span>
|
||||
<button data-icon='icon' type='button' class='layui-btn layui-btn-primary'>{:lang('选择图标')}</button>
|
||||
<p class="help-block"><b>可选</b>,设置菜单选项前置图标,目前支持 layui 字体图标及 iconfont 定制字体图标。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>{:lang('保存数据')}</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="{:lang('确定要取消编辑吗?')}" data-close>{:lang('取消编辑')}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
require(['jquery.autocompleter'], function () {
|
||||
$('[name="icon"]').on('change', function () {
|
||||
$(this).parent().next().find('i').get(0).className = this.value
|
||||
}), $('input[name=url]').autocompleter({
|
||||
limit: 6, highlightMatches: true, template: '{{ label }} <span> {{ title }} </span>', callback: function (node) {
|
||||
$('input[name=node]').val(node);
|
||||
}, source: (function (subjects, data) {
|
||||
for (var i in subjects) data.push({value: subjects[i].node, label: subjects[i].node, title: subjects[i].title});
|
||||
return data;
|
||||
})(JSON.parse('{$nodes|raw|json_encode}'), [])
|
||||
}), $('input[name=node]').autocompleter({
|
||||
limit: 5, highlightMatches: true, template: '{{ label }} <span> {{ title }} </span>', source: (function (subjects, data) {
|
||||
for (var i in subjects) data.push({value: subjects[i].node, label: subjects[i].node, title: subjects[i].title});
|
||||
return data;
|
||||
})(JSON.parse('{$auths|raw|json_encode}'), [])
|
||||
});
|
||||
});
|
||||
</script>
|
||||
114
app/admin/view/menu/index.html
Normal file
114
app/admin/view/menu/index.html
Normal file
@@ -0,0 +1,114 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if $type eq 'index' and auth("add")}-->
|
||||
<button data-modal='{:url("add")}' data-table-id="MenuTable" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('添加菜单')}</button>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if $type eq 'index' and auth("state")}-->
|
||||
<button data-action='{:url("state")}' data-table-id="MenuTable" data-rule="id#{sps};status#0" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('禁用菜单')}</button>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if $type eq 'recycle' and auth("state")}-->
|
||||
<button data-action='{:url("state")}' data-table-id="MenuTable" data-rule="id#{spp};status#1" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('激活菜单')}</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="layui-tab layui-tab-card">
|
||||
<ul class="layui-tab-title">
|
||||
{foreach ['index'=>lang('系统菜单'),'recycle'=>lang('回 收 站')] as $k=>$v}
|
||||
{if isset($type) and $type eq $k}
|
||||
<li class="layui-this" data-open="{:url('index')}?type={$k}">{$v}</li>
|
||||
{else}
|
||||
<li data-open="{:url('index')}?type={$k}">{$v}</li>
|
||||
{/if}{/foreach}
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<table id="MenuTable" data-url="{:request()->url()}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
$('#MenuTable').layTable({
|
||||
even: true, height: 'full', page: false,
|
||||
sort: {field: 'sort desc,id', type: 'asc'},
|
||||
where: {type: '{$type|default="index"}'},
|
||||
filter: function (items) {
|
||||
var type = this.where.type;
|
||||
return items.filter(function (item) {
|
||||
return !(type === 'index' && parseInt(item.status) === 0);
|
||||
});
|
||||
},
|
||||
cols: [[
|
||||
{checkbox: true, field: 'sps'},
|
||||
{field: 'sort', title: '{:lang("排序权重")}', width: 100, align: 'center', templet: '#SortInputTpl'},
|
||||
{field: 'icon', title: '{:lang("图 标")}', width: 80, align: 'center', templet: '<div><i class="{{d.icon}} font-s18"></i></div>'},
|
||||
{field: 'title', title: '{:lang("菜单名称")}', minWidth: 220, templet: '<div><span class="color-desc">{{d.spl}}</span>{{d.title}}</div>'},
|
||||
{field: 'url', title: '{:lang("跳转链接")}', minWidth: 200},
|
||||
{field: 'status', title: '{:lang("使用状态")}', minWidth: 120, align: 'center', templet: '#StatusSwitchTpl'},
|
||||
{toolbar: '#toolbar', title: '{:lang("操作面板")}', minWidth: 150, align: 'center', fixed: 'right'},
|
||||
]]
|
||||
});
|
||||
|
||||
// 数据状态切换操作
|
||||
layui.form.on('switch(StatusSwitch)', function (object) {
|
||||
object.data = {status: object.elem.checked > 0 ? 1 : 0};
|
||||
object.data.id = object.value.split('|')[object.data.status] || object.value;
|
||||
$.form.load("{:url('state')}", object.data, 'post', function (ret) {
|
||||
if (ret.code < 1) $.msg.error(ret.info, 3, function () {
|
||||
$('#MenuTable').trigger('reload');
|
||||
}); else {
|
||||
$('#MenuTable').trigger('reload');
|
||||
}
|
||||
return false;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- 数据状态切换模板 -->
|
||||
<script type="text/html" id="StatusSwitchTpl">
|
||||
<!--{if auth("state")}-->
|
||||
{{# if( "{$type|default='index'}"==='index' || (d.spc<1 || d.status<1)){ }}
|
||||
<input type="checkbox" value="{{d.sps}}|{{d.spp}}" lay-text="{:lang('已激活')}|{:lang('已禁用')}" lay-filter="StatusSwitch" lay-skin="switch" {{-d.status>0?'checked':''}}>
|
||||
{{# }else{ }}
|
||||
{{-d.status ? '<b class="color-green">{:lang('已激活')}</b>' : '<b class="color-red">{:lang('已禁用')}</b>'}}
|
||||
{{# } }}
|
||||
<!--{else}-->
|
||||
{{-d.status ? '<b class="color-green">{:lang('已激活')}</b>' : '<b class="color-red">{:lang('已禁用')}</b>'}}
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
|
||||
<!-- 列表排序权重模板 -->
|
||||
<script type="text/html" id="SortInputTpl">
|
||||
<input type="number" min="0" data-blur-number="0" data-action-blur="{:sysuri()}" data-value="id#{{d.id}};action#sort;sort#{value}" data-loading="false" value="{{d.sort}}" class="layui-input text-center">
|
||||
</script>
|
||||
|
||||
<!-- 操控面板的模板 -->
|
||||
<script type="text/html" id="toolbar">
|
||||
|
||||
<!-- {if isset($type) and $type eq 'index'} -->
|
||||
<!-- {if auth('add')} -->
|
||||
{{# if(d.spt<2){ }}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-primary" data-title="添加系统菜单" data-modal='{:url("add")}?pid={{d.id}}'>{:lang('添 加')}</a>
|
||||
{{# }else{ }}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-disabled">{:lang('添 加')}</a>
|
||||
{{# } }}
|
||||
<!-- {/if} -->
|
||||
{if auth('edit')}
|
||||
<a class="layui-btn layui-btn-sm" data-event-dbclick data-title="编辑系统菜单" data-modal='{:url("edit")}?id={{d.id}}'>{:lang('编 辑')}</a>
|
||||
{/if}
|
||||
<!-- {else} -->
|
||||
{if auth('remove')}
|
||||
{{# if( (d.spc<1 || d.status<1)){ }}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除菜单吗?" data-action="{:url('remove')}" data-value="id#{{d.sps}}">删 除</a>
|
||||
{{# }else{ }}
|
||||
<a class="layui-btn layui-btn-disabled layui-btn-sm">删 除</a>
|
||||
{{# } }}
|
||||
{/if}
|
||||
<!-- {/if} -->
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
48
app/admin/view/oplog/index.html
Normal file
48
app/admin/view/oplog/index.html
Normal file
@@ -0,0 +1,48 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
<!--{if auth("remove")}-->
|
||||
<button data-table-id="OplogTable" data-action='{:url("remove")}' data-rule="id#{id}" data-confirm="确定要删除选中的日志吗?" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量删除')}</button>
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth("clear")}-->
|
||||
<button data-table-id="OplogTable" data-load='{:url("clear")}' data-confirm="确定要清空所有日志吗?" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('清空数据')}</button>
|
||||
<!--{/if}-->
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-shadow">
|
||||
{include file='oplog/index_search'}
|
||||
<table id="OplogTable" data-url="{:request()->url()}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='script'}
|
||||
<script>
|
||||
$(function () {
|
||||
$('#OplogTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'id', type: 'desc'},
|
||||
cols: [[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: 'ID', width: 80, sort: true, align: 'center'},
|
||||
{field: 'username', title: '{:lang("操作账号")}', minWidth: 100, width: '8%', sort: true, align: 'center'},
|
||||
{field: 'node', title: '{:lang("操作节点")}', minWidth: 120},
|
||||
{field: 'action', title: '{:lang("操作行为")}', minWidth: 120},
|
||||
{field: 'content', title: '{:lang("操作内容")}', minWidth: 150},
|
||||
{field: 'request_content', title: '{:lang("请求内容")}', minWidth: 150},
|
||||
{field: 'geoip', title: '{:lang("访问地址")}', minWidth: 100, width: '10%'},
|
||||
{field: 'geoisp', title: '{:lang("网络服务商")}', minWidth: 100},
|
||||
{field: 'create_at', title: '{:lang("创建时间")}', minWidth: 170, align: 'center', sort: true},
|
||||
{toolbar: '#toolbar', title: '{:lang("操作面板")}', align: 'center', minWidth: 80, width: '8%', fixed: 'right'}
|
||||
]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="toolbar">
|
||||
<!--{if auth('remove')}-->
|
||||
<a data-action='{:url("remove")}' data-value="id#{{d.id}}" data-confirm="确认要删除这条记录吗?" class="layui-btn layui-btn-sm layui-btn-danger">{:lang('删 除')}</a>
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
{/block}
|
||||
87
app/admin/view/oplog/index_search.html
Normal file
87
app/admin/view/oplog/index_search.html
Normal file
@@ -0,0 +1,87 @@
|
||||
<fieldset>
|
||||
<legend>{:lang('条件搜索')}</legend>
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('操作账号')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name='username' lay-search class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach $users as $user}{if $user eq input('get.username')}
|
||||
<option selected value="{$user}">{$user}</option>
|
||||
{else}
|
||||
<option value="{$user}">{$user}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('操作行为')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="action" lay-search class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach $actions as $action}{if $action eq input('get.action')}
|
||||
<option selected value="{$action}">{$action}</option>
|
||||
{else}
|
||||
<option value="{$action}">{$action}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('操作节点')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="node" value="{$get.node|default=''}" placeholder="{:lang('请输入操作节点')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('操作内容')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="content" value="{$get.content|default=''}" placeholder="{:lang('请输入操作内容')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('访问地址')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="geoip" value="{$get.geoip|default=''}" placeholder="{:lang('请输入访问地址')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('创建时间')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="{:lang('请选择创建时间')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button type="submit" class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
<button type="button" data-form-export="{:url('index')}?type={$type|default=''}" class="layui-btn layui-btn-primary">
|
||||
<i class="layui-icon layui-icon-export"></i> {:lang('导 出')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
require(['excel'], function (excel) {
|
||||
excel.bind(function (data) {
|
||||
|
||||
// 设置表格内容
|
||||
data.forEach(function (item, index) {
|
||||
data[index] = [item.id, item.username, item.node, item.geoip, item.geoisp, item.action, item.content, item.create_at];
|
||||
});
|
||||
|
||||
// 设置表头内容
|
||||
data.unshift(['ID', '{:lang("操作账号")}', '{:lang("操作节点")}', '{:lang("访问地址")}', '{:lang("网络服务商")}', '{:lang("操作行为")}', '{:lang("操作内容")}', '{:lang("创建时间")}']);
|
||||
|
||||
// 应用表格样式
|
||||
return this.withStyle(data, {A: 60, B: 80, C: 99, E: 120, G: 120});
|
||||
|
||||
}, '{:lang("操作日志")}' + layui.util.toDateString(Date.now(), '_yyyyMMdd_HHmmss'));
|
||||
});
|
||||
</script>
|
||||
131
app/admin/view/queue/index.html
Normal file
131
app/admin/view/queue/index.html
Normal file
@@ -0,0 +1,131 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
|
||||
{if isset($super) and $super}
|
||||
|
||||
<a data-table-id="QueueTable" class="layui-btn layui-btn-sm layui-btn-primary" data-queue="{:url('admin/api.plugs/optimize')}">{:lang('优化数据库')}</a>
|
||||
|
||||
{if isset($iswin) and ($iswin or php_sapi_name() eq 'cli')}
|
||||
<button data-load='{:url("admin/api.queue/start")}' class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('开启服务')}</button>
|
||||
<button data-load='{:url("admin/api.queue/stop")}' class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('关闭服务')}</button>
|
||||
{/if}
|
||||
|
||||
{if auth("clean")}
|
||||
<button data-table-id="QueueTable" data-queue='{:url("clean")}' class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('定时清理')}</button>
|
||||
{/if}
|
||||
|
||||
{/if}
|
||||
|
||||
{if auth("remove")}
|
||||
<button data-table-id="QueueTable" data-action='{:url("remove")}' data-rule="id#{id}" data-confirm="{:lang('确定批量删除记录吗?')}" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量删除')}</button>
|
||||
{/if}
|
||||
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="think-box-notify" type="info">
|
||||
|
||||
<!--{if isset($super) and $super}-->
|
||||
<b>{:lang('服务状态')}:</b><b class="margin-right-5" data-queue-message><span class="color-desc">{:lang('检查中')}</span></b>
|
||||
<b data-tips-text="{:lang('点击可复制【服务启动指令】')}" class="layui-icon pointer margin-right-20" data-copy="{$command|default=''}"></b>
|
||||
<script>$('[data-queue-message]').load('{:sysuri("admin/api.queue/status")}');</script>
|
||||
<!--{/if}-->
|
||||
|
||||
<b>{:lang('任务统计')}:</b>{:lang('待处理 %s 个任务,处理中 %s 个任务,已完成 %s 个任务,已失败 %s 个任务。', [
|
||||
'<b class="color-text" data-extra="pre">..</b>',
|
||||
'<b class="color-blue" data-extra="dos">..</b>',
|
||||
'<b class="color-green" data-extra="oks">..</b>',
|
||||
'<b class="color-red" data-extra="ers">..</b>'
|
||||
])}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="think-box-shadow">
|
||||
{include file='queue/index_search'}
|
||||
<table id="QueueTable" data-line="2" data-url="{:request()->url()}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
{/block}
|
||||
|
||||
{block name='script'}
|
||||
<script>
|
||||
$(function () {
|
||||
$('#QueueTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'loops_time desc,id', type: 'desc'},
|
||||
// 扩展数据处理,需要返回原 items 数据
|
||||
filter: function (items, result) {
|
||||
return result && result.extra && $('[data-extra]').map(function () {
|
||||
this.innerHTML = result.extra[this.dataset.extra] || 0;
|
||||
}), items;
|
||||
},
|
||||
cols: [[
|
||||
{checkbox: true, fixed: 'left'},
|
||||
{
|
||||
field: 'id', title: '{:lang("任务名称")}', width: '25%', sort: true, templet: function (d) {
|
||||
if (d.loops_time > 0) {
|
||||
d.one = '<span class="layui-badge think-bg-blue">循</span>';
|
||||
} else {
|
||||
d.one = '<span class="layui-badge think-bg-red">次</span>';
|
||||
}
|
||||
if (parseInt(d.rscript) === 1) {
|
||||
d.two = '<span class="layui-badge layui-bg-green">复</span>';
|
||||
} else {
|
||||
d.two = '<span class="layui-badge think-bg-violet">单</span>';
|
||||
}
|
||||
return laytpl('{{-d.one}}任务编号:<b>{{d.code}}</b><br>{{-d.two}}任务名称:{{d.title}}').render(d);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'exec_time', title: '{:lang("任务计划")}', width: '25%', templet: function (d) {
|
||||
d.html = '执行指令:' + d.command + '<br>计划执行:' + d.exec_time;
|
||||
if (d.loops_time > 0) {
|
||||
return d.html + ' ( 每 <b class="color-blue">' + d.loops_time + '</b> 秒 ) ';
|
||||
} else {
|
||||
return d.html + ' <span class="color-desc">( 单次任务 )</span> ';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'loops_time', title: '{:lang("任务状态")}', width: '30%', templet: function (d) {
|
||||
d.html = ([
|
||||
'<span class="pull-left layui-badge layui-badge-middle layui-bg-gray">未知</span>',
|
||||
'<span class="pull-left layui-badge layui-badge-middle layui-bg-black">等待</span>',
|
||||
'<span class="pull-left layui-badge layui-badge-middle layui-bg-blue">执行</span>',
|
||||
'<span class="pull-left layui-badge layui-badge-middle layui-bg-green">完成</span>',
|
||||
'<span class="pull-left layui-badge layui-badge-middle layui-bg-red">失败</span>',
|
||||
][d.status] || '') + '执行时间:';
|
||||
d.enter_time = d.enter_time || '';
|
||||
d.outer_time = d.outer_time || '0.0000';
|
||||
if (d.enter_time.length > 12) {
|
||||
d.html += d.enter_time.substring(12) + '<span class="color-desc"> ( ' + d.outer_time + ' ) </span>';
|
||||
d.html += ' 已执行 <b class="color-blue">' + (d.attempts || 0) + '</b> 次';
|
||||
} else {
|
||||
d.html += '<span class="color-desc">任务未执行</span>'
|
||||
}
|
||||
return d.html + '<br>执行结果:<span class="color-blue">' + (d.exec_desc || '<span class="color-desc">未获取到执行结果</span>') + '</span>';
|
||||
}
|
||||
},
|
||||
{toolbar: '#toolbar', title: '{:lang("操作面板")}', align: 'center', minWidth: 210, fixed: 'right'}
|
||||
]]
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="toolbar">
|
||||
|
||||
<!--{if auth('redo')}-->
|
||||
{{# if(d.status===4||d.status===3){ }}
|
||||
<a class="layui-btn layui-btn-sm" data-confirm="确定要重置该任务吗?" data-queue="{:url('redo')}?code={{d.code}}">{:lang('重 置')}</a>
|
||||
{{# }else{ }}
|
||||
<a class="layui-btn layui-btn-sm layui-btn-disabled">{:lang('重 置')}</a>
|
||||
{{# } }}
|
||||
<!--{/if}-->
|
||||
|
||||
<!--{if auth('remove')}-->
|
||||
<a class='layui-btn layui-btn-sm layui-btn-danger' data-confirm="{:lang('确定要删除该记录吗?')}" data-action='{:url("remove")}' data-value="id#{{d.id}}">{:lang('删 除')}</a>
|
||||
<!--{/if}-->
|
||||
|
||||
<a class='layui-btn layui-btn-sm layui-btn-normal' onclick="$.loadQueue('{{d.code}}',false,this)">{:lang('日 志')}</a>
|
||||
</script>
|
||||
{/block}
|
||||
45
app/admin/view/queue/index_search.html
Normal file
45
app/admin/view/queue/index_search.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<fieldset>
|
||||
<legend>{:lang('条件搜索')}</legend>
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('编号名称')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="title" value="{$get.title|default=''}" placeholder="{:lang('请输入名称或编号')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('任务指令')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="command" value="{$get.command|default=''}" placeholder="{:lang('请输入任务指令')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('任务状态')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<select name="status" class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach ['1'=>lang('等待处理'),'2'=>lang('正在处理'),'3'=>lang('处理完成'),'4'=>lang('处理失败')] as $k=>$v}
|
||||
{if isset($get.status) and $get.status eq $k}
|
||||
<option selected value="{$k}">{$v}</option>
|
||||
{else}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('计划时间')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input data-date-range name="exec_time" value="{$get.exec_time|default=''}" placeholder="{:lang('请选择计划时间')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
</div>
|
||||
</form>
|
||||
</fieldset>
|
||||
23
app/admin/view/table.html
Normal file
23
app/admin/view/table.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="layui-card">
|
||||
{block name='style'}{/block}
|
||||
{block name='header'}
|
||||
{notempty name='title'}
|
||||
<div class="layui-card-header">
|
||||
<span class="layui-icon font-s10 color-desc margin-right-5"></span>{$title|lang}
|
||||
<div class="pull-right">{block name='button'}{/block}</div>
|
||||
</div>
|
||||
{/notempty}
|
||||
{/block}
|
||||
<div class="layui-card-line"></div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-card-table">
|
||||
{notempty name='showErrorMessage'}
|
||||
<div class="think-box-notify" type="error">
|
||||
<b>{:lang('系统提示:')}</b><span>{$showErrorMessage|raw}</span>
|
||||
</div>
|
||||
{/notempty}
|
||||
{block name='content'}{/block}
|
||||
</div>
|
||||
</div>
|
||||
{block name='script'}{/block}
|
||||
</div>
|
||||
114
app/admin/view/user/form.html
Normal file
114
app/admin/view/user/form.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="UserTable">
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
<fieldset class="layui-bg-gray">
|
||||
<legend><b class="layui-badge think-bg-violet">用户账号</b></legend>
|
||||
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-xs2 text-center padding-top-15">
|
||||
<input type="hidden" data-cut-width="500" data-cut-height="500" data-max-width="500" data-max-height="500" name="headimg" value="{$vo.headimg|default=''}">
|
||||
<script>$('[name=headimg]').uploadOneImage();</script>
|
||||
</div>
|
||||
<div class="layui-col-xs5">
|
||||
<label class="block relative">
|
||||
<span class="help-label"><b>登录账号</b>User Name</span>
|
||||
{if isset($vo) and isset($vo.username)}
|
||||
<input name="username" value='{$vo.username|default=""}' required readonly class="layui-input think-bg-gray">
|
||||
{else}
|
||||
<input name="username" value='{$vo.username|default=""}' required pattern="^.{4,}$" vali-name="登录账号" placeholder="请输入登录账号" class="layui-input">
|
||||
{/if}
|
||||
<span class="help-block">登录账号不能少于4位字符,创建后不能再次修改.</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs5">
|
||||
<label class="block relative">
|
||||
<span class="help-label"><b>用户名称</b>Nick Name</span>
|
||||
<input name="nickname" value='{$vo.nickname|default=""}' required vali-name="用户名称" placeholder="请输入用户名称" class="layui-input">
|
||||
<span class="help-block">用于区分用户数据的用户名称,请尽量不要重复.</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
{if !empty($bases) || !empty($auths)}
|
||||
<fieldset class="layui-bg-gray">
|
||||
<legend><b class="layui-badge think-bg-violet">用户权限</b></legend>
|
||||
{if !empty($bases)}
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>角色身份</b>Role Identity</div>
|
||||
<div class="layui-textarea help-checks">
|
||||
{foreach $bases as $base}
|
||||
<label class="think-checkbox">
|
||||
{if isset($vo.usertype) and $vo.usertype eq $base.code}
|
||||
<input type="radio" checked name="usertype" value="{$base.code}" lay-ignore>{$base.name}
|
||||
{else}
|
||||
<input type="radio" name="usertype" value="{$base.code}" lay-ignore>{$base.name}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{if !empty($auths)}
|
||||
<div class="layui-form-item">
|
||||
<div class="help-label"><b>访问权限</b>Role Permission</div>
|
||||
<div class="layui-textarea help-checks">
|
||||
{if isset($vo.username) and $vo.username eq $super}
|
||||
<span class="color-desc padding-left-5">超级用户拥所有访问权限,不需要配置权限。</span>
|
||||
{else}{foreach $auths as $authorize}
|
||||
<label class="think-checkbox">
|
||||
{if in_array($authorize.id, $vo.authorize)}
|
||||
<input type="checkbox" checked name="authorize[]" value="{$authorize.id}" lay-ignore>{$authorize.title}
|
||||
{else}
|
||||
<input type="checkbox" name="authorize[]" value="{$authorize.id}" lay-ignore>{$authorize.title}
|
||||
{/if}
|
||||
</label>
|
||||
{/foreach}{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
<fieldset class="layui-bg-gray">
|
||||
<legend><b class="layui-badge think-bg-violet">用户资料</b></legend>
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-xs4">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>联系邮箱</b>Contact Email</span>
|
||||
<input name="contact_mail" value='{$vo.contact_mail|default=""}' pattern="email" vali-name="联系邮箱" placeholder="请输入联系电子邮箱" class="layui-input">
|
||||
<span class="color-desc">可选,请填写用户常用的电子邮箱</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>联系手机</b>Contact Mobile</span>
|
||||
<input type="tel" maxlength="11" name="contact_phone" value='{$vo.contact_phone|default=""}' pattern="phone" vali-name="联系手机" placeholder="请输入用户联系手机" class="layui-input">
|
||||
<span class="color-desc">可选,请填写用户常用的联系手机号</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="layui-col-xs4">
|
||||
<label class="relative block">
|
||||
<span class="help-label"><b>联系QQ</b>Contact QQ</span>
|
||||
<input name="contact_qq" maxlength="11" value='{$vo.contact_qq|default=""}' pattern="qq" vali-name="联系QQ" placeholder="请输入常用的联系QQ" class="layui-input">
|
||||
<span class="color-desc">可选,请填写用户常用的联系QQ号</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<label class="layui-form-item block relative margin-top-10">
|
||||
<span class="help-label"><b>用户描述</b>User Remark</span>
|
||||
<textarea placeholder="请输入用户描述" class="layui-textarea" name="describe">{$vo.describe|default=""}</textarea>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>保存数据</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
|
||||
</div>
|
||||
</form>
|
||||
116
app/admin/view/user/index.html
Normal file
116
app/admin/view/user/index.html
Normal file
@@ -0,0 +1,116 @@
|
||||
{extend name='table'}
|
||||
|
||||
{block name="button"}
|
||||
{if isset($type) and $type eq 'index'}
|
||||
<!--{if auth("add")}-->
|
||||
<button data-modal='{:url("add")}' data-title="{:lang('添加用户')}" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('添加用户')}</button>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("state")}-->
|
||||
<a data-confirm="确定要禁用这些用户吗?" data-table-id="UserTable" data-action="{:url('state')}" data-rule="id#{id};status#0" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量禁用')}</a>
|
||||
<!--{/if}-->
|
||||
{else}
|
||||
<!--{if auth("state")}-->
|
||||
<a data-confirm="确定要恢复这些账号吗?" data-table-id="UserTable" data-action="{:url('state')}" data-rule="id#{id};status#1" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量恢复')}</a>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("remove")}-->
|
||||
<a data-confirm="确定永久删除这些账号吗?" data-table-id="UserTable" data-action='{:url("remove")}' data-rule="id#{id}" class='layui-btn layui-btn-sm layui-btn-primary'>{:lang('批量删除')}</a>
|
||||
<!--{/if}-->
|
||||
{/if}
|
||||
{/block}
|
||||
|
||||
{block name="content"}
|
||||
<div class="layui-tab layui-tab-card">
|
||||
<ul class="layui-tab-title">
|
||||
{foreach ['index'=>lang('系统用户'),'recycle'=>lang('回 收 站')] as $k=>$v}{if isset($type) and $type eq $k}
|
||||
<li data-open="{:url('index')}?type={$k}" class="layui-this">{$v}</li>
|
||||
{else}
|
||||
<li data-open="{:url('index')}?type={$k}">{$v}</li>
|
||||
{/if}{/foreach}
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
{include file='user/index_search'}
|
||||
<table id="UserTable" data-url="{:sysuri('index')}" data-target-search="form.form-search"></table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
$('#UserTable').layTable({
|
||||
even: true, height: 'full',
|
||||
sort: {field: 'sort desc,id', type: 'desc'},
|
||||
where: {type: '{$type|default="index"}'},
|
||||
cols: [[
|
||||
{checkbox: true, fixed: true},
|
||||
{field: 'sort', title: '{:lang("排序权重")}', width: 100, align: 'center', sort: true, templet: '#SortInputTpl'},
|
||||
{
|
||||
field: 'headimg', title: '{:lang("头像")}', width: 60, align: 'center', templet: function (d) {
|
||||
if (!d.headimg) return '-';
|
||||
return layui.laytpl('<div class="headimg headimg-ss shadow-inset margin-0" data-tips-image data-tips-hover data-lazy-src="{{d.headimg}}"></div>').render(d);
|
||||
}
|
||||
},
|
||||
{field: 'username', title: '{:lang("登录账号")}', minWidth: 100, align: 'center', templet: '<div>{{d.username||"-"}}</div>'},
|
||||
{field: 'nickname', title: '{:lang("用户名称")}', minWidth: 100, align: 'center', templet: '<div>{{d.nickname||"-"}}</div>'},
|
||||
/* {notempty name='bases'} */
|
||||
{
|
||||
field: 'usertype', title: '{:lang("角色身份")}', minWidth: 100, align: 'center', templet: function (d) {
|
||||
d.userinfo = d.userinfo || {};
|
||||
return d.userinfo.code ? (d.userinfo.name + ' ( ' + d.userinfo.code + ' ) ') : '-';
|
||||
}
|
||||
},
|
||||
/* {/notempty} */
|
||||
// {field: 'contact_mail', title: '联系邮箱', minWidth: 80, templet: '<div>{{d.contact_mail||"-"}}</div>'},
|
||||
// {field: 'contact_phone', title: '联系电话', minWidth: 80, templet: '<div>{{d.contact_phone||"-"}}</div>'},
|
||||
{field: 'status', title: '{:lang("使用状态")}', align: 'center', minWidth: 110, templet: '#StatusSwitchTpl'},
|
||||
{field: 'login_num', title: '{:lang("登录次数")}', align: 'center', minWidth: 100, sort: true},
|
||||
{field: 'login_at', title: '{:lang("最后登录")}', align: 'center', minWidth: 170, sort: true},
|
||||
{field: 'create_at', title: '{:lang("创建时间")}', align: 'center', minWidth: 170, sort: true},
|
||||
{toolbar: '#toolbar', title: '{:lang("操作面板")}', align: 'center', minWidth: 180, fixed: 'right'}
|
||||
]]
|
||||
});
|
||||
|
||||
// 数据状态切换操作
|
||||
layui.form.on('switch(StatusSwitch)', function (obj) {
|
||||
var data = {id: obj.value, status: obj.elem.checked > 0 ? 1 : 0};
|
||||
$.form.load("{:url('state')}", data, 'post', function (ret) {
|
||||
if (ret.code < 1) $.msg.error(ret.info, 3, function () {
|
||||
$('#UserTable').trigger('reload');
|
||||
}); else {
|
||||
$('#UserTable').trigger('reload')
|
||||
}
|
||||
return false;
|
||||
}, false);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- 数据状态切换模板 -->
|
||||
<script type="text/html" id="StatusSwitchTpl">
|
||||
<!--{if auth("state")}-->
|
||||
<input type="checkbox" value="{{d.id}}" lay-skin="switch" lay-text="{:lang('已激活')}|{:lang('已禁用')}" lay-filter="StatusSwitch" {{-d.status>0?'checked':''}}>
|
||||
<!--{else}-->
|
||||
{{-d.status ? '<b class="color-green">{:lang("已激活")}</b>' : '<b class="color-red">{:lang("已禁用")}</b>'}}
|
||||
<!--{/if}-->
|
||||
</script>
|
||||
|
||||
<!-- 列表排序权重模板 -->
|
||||
<script type="text/html" id="SortInputTpl">
|
||||
<input type="number" min="0" data-blur-number="0" data-action-blur="{:sysuri()}" data-value="id#{{d.id}};action#sort;sort#{value}" data-loading="false" value="{{d.sort}}" class="layui-input text-center">
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="toolbar">
|
||||
{if isset($type) and $type eq 'index'}
|
||||
<!--{if auth("edit")}-->
|
||||
<a class="layui-btn layui-btn-sm" data-event-dbclick data-title="{:lang('编辑用户')}" data-modal='{:url("edit")}?id={{d.id}}'>{:lang('编 辑')}</a>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("pass")}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-normal" data-title="{:lang('设置密码')}" data-modal='{:url("pass")}?id={{d.id}}'>{:lang('密 码')}</a>
|
||||
<!--{/if}-->
|
||||
{else}
|
||||
<!--{if auth("edit")}-->
|
||||
<a class="layui-btn layui-btn-sm" data-event-dbclick data-title="{:lang('编辑用户')}" data-modal='{:url("edit")}?id={{d.id}}'>{:lang('编 辑')}</a>
|
||||
<!--{/if}-->
|
||||
<!--{if auth("remove")}-->
|
||||
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="{:lang('确定要永久删除吗?')}" data-action="{:url('remove')}" data-value="id#{{d.id}}">{:lang('删 除')}</a>
|
||||
<!--{/if}-->
|
||||
{/if}
|
||||
</script>
|
||||
{/block}
|
||||
44
app/admin/view/user/index_search.html
Normal file
44
app/admin/view/user/index_search.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<form class="layui-form layui-form-pane form-search" action="{:sysuri()}" onsubmit="return false" method="get" autocomplete="off">
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('账号名称')}</label>
|
||||
<label class="layui-input-inline">
|
||||
<input name="username" value="{$get.username|default=''}" placeholder="{:lang('请输入账号或名称')}" class="layui-input">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!--{notempty name='bases'}-->
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('角色身份')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<select name="usertype" lay-search class="layui-select">
|
||||
<option value=''>-- {:lang('全部')} --</option>
|
||||
{foreach $bases as $base}{if $base.code eq input('get.usertype')}
|
||||
<option selected value="{$base.code|default=''}">{$base.name|default=''} ( {$base.code|default=''} )</option>
|
||||
{else}
|
||||
<option value="{$base.code|default=''}">{$base.name|default=''} ( {$base.code|default=''} )</option>
|
||||
{/if}{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<!--{/notempty}-->
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('最后登录')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="login_at" value="{$get.login_at|default=''}" placeholder="{:lang('请选择登录时间')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<label class="layui-form-label">{:lang('创建时间')}</label>
|
||||
<div class="layui-input-inline">
|
||||
<input data-date-range name="create_at" value="{$get.create_at|default=''}" placeholder="{:lang('请选择创建时间')}" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-inline">
|
||||
<input type="hidden" name="type" value="{$type|default='index'}">
|
||||
<button class="layui-btn layui-btn-primary"><i class="layui-icon"></i> {:lang('搜 索')}</button>
|
||||
</div>
|
||||
</form>
|
||||
40
app/admin/view/user/pass.html
Normal file
40
app/admin/view/user/pass.html
Normal file
@@ -0,0 +1,40 @@
|
||||
<form action="{:sysuri()}" method="post" data-auto="true" class="layui-form layui-card" data-table-id="UserTable">
|
||||
<div class="layui-card-body padding-left-40">
|
||||
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>登录用户账号</b>Username</span>
|
||||
<input disabled value='{$vo.username|default=""}' class="layui-input think-bg-gray">
|
||||
<span class="help-block">登录用户账号创建后,不允许再次修改。</span>
|
||||
</label>
|
||||
|
||||
<!--{if $verify}-->
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>旧的登录密码</b>Old Password</span>
|
||||
<input type="password" autofocus name="oldpassword" value='' pattern="^\S{1,}$" required vali-name="验证密码" placeholder="请输入旧的登录密码" class="layui-input">
|
||||
<span class="color-desc">请输入旧密码来验证修改权限,旧密码不限制格式。</span>
|
||||
</label>
|
||||
<!--{/if}-->
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>新的登录密码</b>New Password</span>
|
||||
<input type="password" name="password" maxlength="32" pattern="^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,32}$" required vali-name="登录密码" placeholder="请输入新的登录密码" class="layui-input">
|
||||
<span class="color-desc">密码必须包含大小写字母、数字、符号的任意两者组合。</span>
|
||||
</label>
|
||||
|
||||
<label class="layui-form-item relative block">
|
||||
<span class="help-label"><b>重复登录密码</b>Repeat Password</span>
|
||||
<input type="password" name="repassword" maxlength="32" pattern="^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,32}$" required vali-name="重复密码" placeholder="请重复输入登录密码" class="layui-input">
|
||||
<span class="color-desc">密码必须包含大小写字母、数字、符号的任意两者组合。</span>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
|
||||
|
||||
<div class="layui-form-item text-center">
|
||||
<button class="layui-btn" type='submit'>保存数据</button>
|
||||
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
|
||||
</div>
|
||||
</form>
|
||||
Reference in New Issue
Block a user