STT 4 months ago
parent ba98978a8b
commit b5a170b221

File diff suppressed because it is too large Load Diff

@ -0,0 +1,478 @@
layui.define(['laypage', 'form'], function (exports) {
"use strict";
// 定义 IconPicker 构造函数
var IconPicker = function () {
// 设置版本号为1.1
this.v = '1.1';
}, _MOD = 'iconPickerFa',
// 使用 _this 存储当前的 this 上下文
_this = this,
// 引入 jQuery
$ = layui.jquery,
// 引入 laypage 模块
laypage = layui.laypage,
// 引入 form 模块
form = layui.form,
// 定义 BODY 选择器
BODY = 'body',
// 定义提示信息
TIPS = '请选择图标';
})
IconPicker.prototype.render = function (options) {
// 渲染图标选择器的方法
var opts = options,
// DOM选择器
elem = opts.elem,
// 数据类型fontClass/unicode
url = opts.url,
// 是否分页true/false
page = opts.page == null ? true : opts.page,
// 每页显示数量
limit = opts.limit == null ? 12 : opts.limit,
// 是否开启搜索true/false
search = opts.search == null ? true : opts.search,
// 每个图标格子的宽度:'43px'或'20%'
cellWidth = opts.cellWidth,
// 点击图标后的回调函数
click = opts.click,
// 渲染成功后的回调函数
success = opts.success,
// 存储图标数据的json对象
data = {},
// 唯一标识符,基于当前时间戳生成
tmp = new Date().getTime(),
// 初始化时input的值
ORIGINAL_ELEM_VALUE = $(elem).val(),
// 下拉标题的类名
TITLE = 'layui-select-title',
// 下拉标题的唯一ID
TITLE_ID = 'layui-select-title-' + tmp,
// 图标选择器主体的唯一ID
ICON_BODY = 'layui-iconpicker-' + tmp,
// 图标选择器内容区域的唯一ID
PICKER_BODY = 'layui-iconpicker-body-' + tmp,
// 图标选择器分页区域的唯一ID
PAGE_ID = 'layui-iconpicker-page-' + tmp,
// 图标列表容器的类名
LIST_BOX = 'layui-iconpicker-list-box',
// 表单项选中状态的类名
selected = 'layui-form-selected',
// 表单项未选中状态的类名
unselect = 'layui-unselect';
var a = {
// 初始化函数,设置基本数据并绑定事件
init: function () {
// 从指定URL获取数据
data = common.getData(url);
// 隐藏元素、创建选择框、创建主体内容、切换选择状态
a.hideElem().createSelect().createBody().toggleSelect();
// 防止默认事件和监听输入事件
a.preventEvent().inputListen();
// 加载CSS样式
common.loadCss();
// 如果成功回调函数存在,则调用成功处理函数
if (success) {
success(this.successHandle());
}
// 返回当前对象以支持链式调用
return a;
},
// 处理成功后的数据返回
successHandle: function () {
// 创建一个包含选项、数据、ID和元素的对象
var d = {
options: opts,
data: data,
id: tmp,
elem: $('#' + ICON_BODY)
};
// 返回创建的对象
return d;
},
hideElem: function () {
// 隐藏指定的元素
$(elem).hide();
// 返回变量 a
return a;
},
createSelect: function () {
// 定义一个变量oriIcon并赋值为包含图标类名的HTML字符串
var oriIcon = '<i class="fa">';
// 如果ORIGINAL_ELEM_VALUE为空字符串
if (ORIGINAL_ELEM_VALUE === '') {
// 将ORIGINAL_ELEM_VALUE设置为默认图标类名'fa-adjust'
ORIGINAL_ELEM_VALUE = 'fa-adjust';
}
createSelect: 该方法用于创建一个选择元素主要用于图标选择功能
// 创建原始图标的HTML字符串使用ORIGINAL_ELEM_VALUE作为图标类名
oriIcon = '<i class="fa ' + ORIGINAL_ELEM_VALUE + '">';
// 关闭原始图标的HTML标签
oriIcon += '</i>';
// 创建选择器HTML字符串包含标题和图标选择区域
var selectHtml = '<div class="layui-iconpicker layui-unselect layui-form-select" id="' + ICON_BODY + '">' +
'<div class="' + TITLE + '" id="' + TITLE_ID + '">' +
'<div class="layui-iconpicker-item">' +
'<span class="layui-iconpicker-icon layui-unselect">' +
// 插入原始图标HTML
oriIcon +
'</span>' +
// 添加一个用于显示边缘效果的图标
'<i class="layui-edge"></i>' +
'</div>' +
'</div>' +
'<div class="layui-anim layui-anim-upbit" style="">' +
// 占位符内容,可能是将来要替换的内容
'123' +
'</div>';
// 在目标元素之后插入生成的选择器HTML
$(elem).after(selectHtml);
// 返回变量a假设是函数的返回值
return a;
toggleSelect: function () {
// 切换图标的选中状态
var item = '#' + TITLE_ID + ' .layui-iconpicker-item,#' + TITLE_ID + ' .layui-iconpicker-item .layui-edge';
a.event('click', item, function (e) {
// 获取图标元素
var $icon = $('#' + ICON_BODY);
if ($icon.hasClass(selected)) {
// 如果图标已经被选中,则取消选中状态
$icon.removeClass(selected).addClass(unselect);
} else {
// 隐藏其他picker
$('.layui-form-select').removeClass(selected);
// 显示当前picker并设置为选中状态
$icon.addClass(selected).removeClass(unselect);
}
// 阻止事件冒泡
e.stopPropagation();
});
}
return a;
},
createBody: function () {
// 初始化搜索框的 HTML 内容为空字符串
var searchHtml = '';
// 如果 search 为真,则创建搜索框的 HTML 结构
if (search) {
searchHtml = '<div class="layui-iconpicker-search">' +
'<input class="layui-input">' +
'<i class="layui-icon">&#xe615;</i>' +
'</div>';
}
}
// 组合dom
// 创建包含图标选择器主体的HTML字符串并设置其ID为PICKER_BODY
var bodyHtml = '<div class="layui-iconpicker-body" id="' + PICKER_BODY + '">' +
// 添加搜索框的HTML内容
searchHtml +
// 添加一个空的列表容器,用于显示图标列表
'<div class="' + LIST_BOX + '"></div> ' +
'</div>';
// 在指定的ICON_BODY元素中找到第一个带有layui-anim类的元素并将其HTML内容替换为bodyHtml
$('#' + ICON_BODY).find('.layui-anim').eq(0).html(bodyHtml);
// 调用a对象的search方法创建图标列表检查图标状态并进行分页处理
a.search().createList().check().page();
// 返回对象a
return a;
createList: function (text) {
// 创建列表的函数,根据传入的文本过滤图标数据
var d = data, // 获取全局数据
l = d.length, // 获取数据长度
pageHtml = '', // 初始化分页HTML字符串
listHtml = $('<div class="layui-iconpicker-list">'); // 创建一个包含类名'layui-iconpicker-list'的div元素
// 计算分页数据
var _limit = limit, // 每页显示数量
_pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1), // 计算总页数如果整除则直接除否则加1取整
_id = PAGE_ID; // 获取当前页面ID
// 图标列表
var icons = [];
for (var i = 0; i < l; i++) {
var obj = d[i];
// 判断是否模糊查询如果text存在且obj中不包含text则跳过当前循环
if (text && obj.indexOf(text) === -1) {
continue;
}
// 初始化样式字符串为空
var style = '';
// 如果自定义格子宽度不为空
if (cellWidth !== null) {
// 将自定义的格子宽度添加到样式字符串中
style += ' style="width:' + cellWidth + '"';
}
// 创建一个包含图标的HTML字符串
var icon = '<div class="layui-iconpicker-icon-item" title="' + obj + '" ' + style + '>';
// 在div中添加一个i元素并设置其class为FontAwesome图标类名
icon += '<i class="fa ' + obj + '"></i>';
// 关闭div标签
icon += '</div>';
// 将生成的图标HTML字符串添加到icons数组中
icons.push(icon);
// 查询出图标后再分页
// 获取图标数组的长度
l = icons.length;
// 计算总页数如果图标总数不能被每页限制数量整除则总页数加1
_pages = l % _limit === 0 ? l / _limit : parseInt(l / _limit + 1);
// 循环遍历每一页
for (var i = 0; i < _pages; i++) {
// 创建一个新的div元素用于存放当前页的图标并设置其class和id
var lm = $('<div class="layui-iconpicker-icon-limit" id="layui-iconpicker-icon-limit-' + tmp + (i + 1) + '">');
// 循环遍历当前页的所有图标
for (var j = i * _limit; j < (i + 1) * _limit && j < l; j++) {
// 将当前图标添加到当前页的div中
lm.append(icons[j]);
}
// 将当前页的div添加到列表的HTML中
listHtml.append(lm);
}
// 根据图标的数量和每页显示的限制,将图标分页并添加到列表中
// 无数据
if (l === 0) {
listHtml.append('<p class="layui-iconpicker-tips">无数据</p>');
}
// 判断是否分页
// 检查是否存在分页参数
if (page) {
// 为图标选择器主体添加分页样式类
$('#' + PICKER_BODY).addClass('layui-iconpicker-body-page');
// 生成分页HTML结构
pageHtml = '<div class="layui-iconpicker-page" id="' + PAGE_ID + '">' +
'<div class="layui-iconpicker-page-count">' +
'<span id="' + PAGE_ID + '-current">1</span>/' +
'<span id="' + PAGE_ID + '-pages">' + _pages + '</span>' +
' (<span id="' + PAGE_ID + '-length">' + l + '</span>)' +
'</div>' +
'<div class="layui-iconpicker-page-operate">' +
'<i class="layui-icon" id="' + PAGE_ID + '-prev" data-index="0" prev>&#xe603;</i> ' +
'<i class="layui-icon" id="' + PAGE_ID + '-next" data-index="2" next>&#xe602;</i> ' +
'</div>' +
'</div>';
}
// 清空并更新列表和分页的HTML内容
$('#' + ICON_BODY).find('.layui-anim').find('.' + LIST_BOX).html('').append(listHtml).append(pageHtml);
return a;
},
preventEvent: function () {
// 定义需要绑定事件的元素选择器
var item = '#' + ICON_BODY + ' .layui-anim';
// 为元素绑定点击事件,阻止事件冒泡
a.event('click', item, function (e) {
e.stopPropagation();
});
return a;
},
// 分页功能
page: function () {
// 获取分页操作图标的选择器
var icon = '#' + PAGE_ID + ' .layui-iconpicker-page-operate .layui-icon';
// 解除之前绑定的点击事件
$(icon).unbind('click');
// 为分页操作图标绑定点击事件
a.event('click', icon, function (e) {
// 获取当前点击的元素
var elem = e.currentTarget,
// 获取总页数
total = parseInt($('#' + PAGE_ID + '-pages').html()),
// 判断是否为上一页按钮
isPrev = $(elem).attr('prev') !== undefined,
// 获取按钮上的页码索引
index = parseInt($(elem).attr('data-index')),
// 获取当前显示页码的元素
$cur = $('#' + PAGE_ID + '-current'),
// 获取当前显示的页码
current = parseInt($cur.html());
// 分页数据
if (isPrev && current > 1) {
// 如果点击的是上一页且当前页码大于1则将当前页码减1
current = current - 1;
// 更新上一页图标的data-index属性为新的当前页码
$(icon + '[prev]').attr('data-index', current);
} else if (!isPrev && current < total) {
// 如果点击的是下一页且当前页码小于总页数则将当前页码加1
current = current + 1;
// 更新下一页图标的data-index属性为新的当前页码
$(icon + '[next]').attr('data-index', current);
}
// 更新当前页码显示
$cur.html(current);
// 图标数据
// 隐藏所有图标限制元素
$('#' + ICON_BODY + ' .layui-iconpicker-icon-limit').hide();
// 显示对应页码的图标限制元素
$('#layui-iconpicker-icon-limit-' + tmp + current).show();
// 阻止事件冒泡
e.stopPropagation();
});
return a;
},
search: function () {
// 为图标搜索输入框绑定输入事件监听器
var item = '#' + PICKER_BODY + ' .layui-iconpicker-search .layui-input';
a.event('input propertychange', item, function (e) {
// 获取输入框元素及其值
var elem = e.target,
t = $(elem).val();
// 根据输入值创建图标列表
a.createList(t);
});
// 返回模块对象 a
return a;
},
// 定义一个名为 check 的函数,用于处理图标选择器的点击事件
check: function () {
// 选择图标项的 CSS 选择器
var item = '#' + PICKER_BODY + ' .layui-iconpicker-icon-item';
// 为图标项添加点击事件监听器
a.event('click', item, function (e) {
// 获取当前点击的图标元素和图标类名
var el = $(e.currentTarget).find('.fa'),
icon = '';
// 分割图标的 class 属性,提取图标类名
var clsArr = el.attr('class').split(/[\s\n]/),
cls = clsArr[1],
icon = cls;
// 更新标题区域显示的图标
$('#' + TITLE_ID).find('.layui-iconpicker-item .fa').html('').attr('class', clsArr.join(' '));
// 移除所有图标的选中状态并设置当前图标的选中状态
$('#' + ICON_BODY).removeClass(selected).addClass(unselect);
// 设置输入框的值为当前图标的类名
$(elem).val(icon).attr('value', icon);
// 回调函数,如果存在则执行
if (click) {
click({
icon: icon
});
}
});
// 返回对象 a
return a;
},
// 监听原始input数值改变
inputListen: function () {
// 获取元素并转换为jQuery对象
var el = $(elem);
// 为元素绑定'change'事件监听器
a.event('change', elem, function () {
// 获取元素的当前值
var value = el.val();
})
// 返回对象a
return a;
},
// 绑定事件到指定元素
event: function (evt, el, fn) {
// 使用jQuery在BODY元素上绑定事件处理函数
$(BODY).on(evt, el, fn);
}
var common = {
// 加载CSS样式函数
loadCss: function () {
var css = '.layui-iconpicker {max-width: 280px;}.layui-iconpicker .layui-anim{display:none;position:absolute;left:0;top:42px;padding:5px 0;z-index:899;min-width:100%;border:1px solid #d2d2d2;max-height:300px;overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box;}.layui-iconpicker-item{border:1px solid #e6e6e6;width:90px;height:38px;border-radius:4px;cursor:pointer;position:relative;}.layui-iconpicker-icon{border-right:1px solid #e6e6e6;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;width:60px;height
// 获取数据的函数
getData: function (url) {
// 初始化图标列表数组
var iconlist = [];
// 发起同步的AJAX请求以获取数据
$.ajax({
url: url,
type: 'get',
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
async: false,
// 请求成功时的回调函数
success: function (ret) {
// 正则表达式用于匹配图标名称
var exp = /fa-var-(.*):/ig;
var result;
// 遍历匹配结果并将图标名称添加到列表中
while ((result = exp.exec(ret)) != null) {
iconlist.push('fa-' + result[1]);
}
},
// 请求失败时的回调函数
error: function (xhr, textstatus, thrown) {
layer.msg('fa图标接口有误');
}
});
// 返回获取到的图标列表
return iconlist;
}
};
a.init();
return new IconPicker();
};
IconPicker.prototype.checkIcon = function (filter, iconName) {
// 根据过滤器找到对应的元素获取其下一个元素中的图标项并设置当前图标名为c
var el = $('*[lay-filter=' + filter + ']'),
p = el.next().find('.layui-iconpicker-item .fa'),
c = iconName;
// 检查图标名是否包含'#xe'如果包含则直接设置图标内容否则设置图标类名为c
if (c.indexOf('#xe') > 0) {
p.html(c);
} else {
p.html('').attr('class', 'fa ' + c);
}
// 设置元素的value属性和实际值为当前图标名c
el.attr('value', c).val(c);
};
var iconPicker = new IconPicker();
// 导出iconPicker模块
exports(_MOD, iconPicker);
});

@ -0,0 +1,229 @@
<!DOCTYPE html>
<html>
<head>
<!-- 设置文档的字符编码为UTF-8 -->
<meta charset="utf-8">
<!-- 设置网页标题 -->
<title>高校宿舍管理系统</title>
<!-- 设置网页关键词,便于搜索引擎优化 -->
<meta name="keywords" content="高校宿舍管理系统">
<!-- 设置网页描述,便于搜索引擎优化 -->
<meta name="description" content="高校宿舍管理系统">
<!-- 设置渲染引擎为webkit -->
<meta name="renderer" content="webkit">
<!-- 设置IE浏览器兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 允许所有来源的跨域请求 -->
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<!-- 设置视口宽度和缩放比例 -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- 设置苹果设备的状态栏样式为黑色 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- 允许将网站添加到主屏幕 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- 禁用电话识别 -->
<meta name="format-detection" content="telephone=no">
<!-- 设置网页图标 -->
<link rel="icon" href="../images/favicon.ico">
<!-- 引入layui框架的CSS文件 -->
<link rel="stylesheet" href="../lib/layui-v2.5.5/css/layui.css" media="all">
<!-- 引入FontAwesome字体库的CSS文件 -->
<link rel="stylesheet" href="../lib/font-awesome-4.7.0/css/font-awesome.min.css" media="all">
<!-- 引入自定义的layuimini CSS文件 -->
<link rel="stylesheet" href="../css/layuimini.css?v=2.0.1" media="all">
<!-- 引入默认主题的CSS文件 -->
<link rel="stylesheet" href="../css/themes/default.css" media="all">
<!-- 引入公共CSS文件 -->
<link rel="stylesheet" href="../css/public.css" media="all">
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<!-- 引入 HTML5 shiv用于使旧版 IE 浏览器支持 HTML5 元素 -->
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<!-- 引入 respond.js用于使旧版 IE 浏览器支持媒体查询 -->
<![endif]-->
<!-- 结束条件注释 -->
<style id="layuimini-bg-color">
</style>
<!-- 定义一个空的样式标签,用于动态设置背景颜色 -->
</head>
<body class="layui-layout-body layuimini-all">
<!-- 页面主体部分,使用 layui 布局类 -->
<div class="layui-layout layui-layout-admin">
<!-- 使用 layui 布局容器 -->
<div class="layui-header header">
<!-- 页头部分 -->
<div class="layui-logo layuimini-logo layuimini-back-home"></div>
<!-- 网站 logo点击可返回首页 -->
<div class="layuimini-header-content">
<!-- 页头内容区域 -->
<a>
<div class="layuimini-tool"><i title="展开" class="fa fa-outdent" data-side-fold="1"></i></div>
<!-- 折叠按钮,点击后展开菜单 -->
</a>
<!--电脑端头部菜单-->
<ul class="layui-nav layui-layout-left layuimini-header-menu layuimini-menu-header-pc layuimini-pc-show">
<!-- 电脑端头部菜单列表 -->
</ul>
<!--手机端头部菜单-->
<ul class="layui-nav layui-layout-left layuimini-header-menu layuimini-mobile-show">
<!-- 手机端头部菜单列表 -->
<li class="layui-nav-item">
<!-- 单个菜单项 -->
<a href="javascript:;"><i class="fa fa-list-ul"></i> 选择模块</a>
<!-- 菜单项链接和图标 -->
<dl class="layui-nav-child layuimini-menu-header-mobile">
<!-- 子菜单列表 -->
</dl>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<!-- 刷新按钮 -->
<li class="layui-nav-item" lay-unselect>
<!-- 点击后触发刷新操作 -->
<a href="javascript:;" data-refresh="刷新"><i class="fa fa-refresh"></i></a>
</li>
<!-- 清理按钮(已注释) -->
<!-- <li class="layui-nav-item" lay-unselect>
<a href="javascript:;" data-clear="清理" class="layuimini-clear"><i class="fa fa-trash-o"></i></a>
</li> -->
<!-- 全屏按钮,仅在移动设备上显示 -->
<li class="layui-nav-item mobile layui-hide-xs" lay-unselect>
<!-- 点击后触发全屏操作 -->
<a href="javascript:;" data-check-screen="full"><i class="fa fa-arrows-alt"></i></a>
</li>
<!-- 设置菜单项 -->
<li class="layui-nav-item layuimini-setting">
<!-- 用户名链接 -->
<a href="javascript:;" id="userName"></a>
<!-- 下拉菜单内容 -->
<dl class="layui-nav-child">
<!-- 基本资料子菜单项 -->
<dd>
<a href="javascript:;" layuimini-content-href="user/info.html" data-title="基本资料" data-icon="fa fa-gears">基本资料</a>
</dd>
<!-- 修改密码子菜单项 -->
<dd>
<a href="javascript:;" layuimini-content-href="user/password.html" data-title="修改密码" data-icon="fa fa-gears">修改密码</a>
</dd>
<!-- 分隔线 -->
<dd>
<hr>
</dd>
<!-- 其他子菜单项可以继续添加在这里 -->
<dd>
<!-- 退出登录链接 -->
<a href="javascript:;" class="login-out">退出登录</a>
</dd>
</dl>
</li>
<!-- 配色方案选择项 -->
<li class="layui-nav-item layuimini-select-bgcolor" lay-unselect>
<!-- 点击后触发背景颜色选择功能 -->
<a href="javascript:;" data-bgcolor="配色方案"><i class="fa fa-ellipsis-v"></i></a>
</li>
</ul>
</div>
</div>
<!-- 无限极左侧菜单容器 -->
<div class="layui-side layui-bg-black layuimini-menu-left">
</div>
<!-- 初始化加载层 -->
<div class="layuimini-loader">
<!-- 加载动画的内部容器 -->
<div class="layuimini-loader-inner"></div>
</div>
<!-- 手机端遮罩层 -->
<div class="layuimini-make"></div>
<!-- 移动导航 -->
<div class="layuimini-site-mobile"><i class="layui-icon"></i></div>
<!-- 页面主体内容 -->
<div class="layui-body">
<!-- 隐藏的卡片,用于显示面包屑导航 -->
<div class="layui-card layuimini-page-header layui-hide">
<!-- 面包屑导航 -->
<div class="layui-breadcrumb layuimini-page-title">
<!-- 主页链接 -->
<a lay-href="" href="/">主页</a><span lay-separator="">/</span>
<!-- 常规管理链接 -->
<a><cite>常规管理</cite></a><span lay-separator="">/</span>
<!-- 系统设置链接 -->
<a><cite>系统设置</cite></a>
</div>
</div>
<!-- 页面主要内容区域 -->
<div class="layuimini-content-page">
</div>
</div>
</div>
<script src="../lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<!-- 引入 layui 框架 -->
<script src="../js/lay-config.js?v=2.0.0" charset="utf-8"></script>
<!-- 引入自定义的 lay-config 配置文件 -->
<script>
// 使用 layui 模块
layui.use(['jquery', 'layer', 'miniAdmin','store'], function () {
var $ = layui.jquery,
// 获取 layui 的 jQuery 模块
layer = layui.layer,
// 获取 layui 的 layer 模块,用于弹出层和消息提示
store = layui.store,
// 获取 layui 的 store 模块,用于本地存储
miniAdmin = layui.miniAdmin;
// 获取 layui 的 miniAdmin 模块,用于后台管理界面
if(!store.getToken()){
// 如果本地存储中没有 token则跳转到登录页面
location.href ='login.html';
}
if(store.getLoginInfo()){
// 如果本地存储中有登录信息,则显示用户名
$('#userName').html(store.getLoginInfo());
}
<script>
// 定义配置选项对象
let options = {
iniUrl: "menu/query", // 功能菜单请求接口地址
clearUrl: "", // 缓存清理接口
renderPageVersion: true, // 初始化页面是否加版本号
bgColorDefault: false, // 主题默认配置
multiModule: false, // 是否开启多模块
menuChildOpen: false, // 是否默认展开菜单
loadingTime: 0, // 初始化加载时间
pageAnim: true, // 切换菜单动画
logoInfo: {
title: "宿舍管理系统", // 系统标题
image: "../images/logo.png", // 系统Logo图片路径
href: "" // 系统链接
},
homeInfo: {
title: "首页", // 首页标题
href: "main.html" // 首页链接
},
};
// 调用miniAdmin的render方法传入配置选项
miniAdmin.render(options);
// 为退出按钮绑定点击事件
$('.login-out').on("click", function () {
// 弹出确认对话框,询问用户是否确定退出
layer.confirm("确定要退出吗?",function () {
// 清除本地存储数据
store.clear();
// 跳转到登录页面
window.location = 'login.html';
})
});
});
</script>
</body>
</html>

@ -0,0 +1,246 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 设置文档的字符编码为UTF-8 -->
<title>后台管理-登陆</title>
<!-- 设置网页标题为“后台管理-登陆” -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!-- 设置浏览器兼容模式优先使用最新版本的IE和Chrome内核 -->
<meta http-equiv="Access-Control-Allow-Origin" content="*">
<!-- 允许所有来源的跨域请求 -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- 设置视口宽度等于设备宽度初始缩放比例为1最大缩放比例为1 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- 设置苹果移动设备上的状态栏样式为黑色 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- 允许将网页添加到主屏幕,作为应用程序运行 -->
<meta name="format-detection" content="telephone=no">
<!-- 禁止自动检测电话号码 -->
<link rel="stylesheet" href="../lib/layui-v2.5.5/css/layui.css"
<!-- 引入Layui框架的CSS文件用于美化页面 -->
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<style>
/* 设置主内容区域的样式,使其居中显示 */
.main-body {top:50%;left:50%;position:absolute;-webkit-transform:translate(-50%,-50%);-moz-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);-o-transform:translate(-50%,-50%);transform:translate(-50%,-50%);overflow:hidden;}
/* 设置登录输入框的样式 */
.login-main .login-bottom .center .item input {display:inline-block;width:227px;height:22px;padding:0;position:absolute;border:0;outline:0;font-size:14px;letter-spacing:0;}
/* 设置图标1的背景图片位置 */
.login-main .login-bottom .center .item .icon-1 {background:url(../images/icon-login.png) no-repeat 1px 0;}
/* 设置图标2的背景图片位置 */
.login-main .login-bottom .center .item .icon-2 {background:url(../images/icon-login.png) no-repeat -54px 0;}
/* 设置图标3的背景图片位置 */
.login-main .login-bottom .center .item .icon-3 {background:url(../images/icon-login.png) no-repeat -106px 0;}
/* 设置图标4的背景图片位置和样式 */
.login-main .login-bottom .center .item .icon-4 {background:url(../images/icon-login.png) no-repeat 0 -43px;position:absolute;right:-10px;cursor:pointer;}
/* 设置图标5的背景图片位置 */
.login-main .login-bottom .center .item .icon-5 {background:url(../images/icon-login.png) no-repeat -55px -43px;}
/* 设置图标6的背景图片位置和样式 */
.login-main .login-bottom .center .item .icon-6 {background:url(../images/icon-login.png) no-repeat 0 -93px;position:absolute;right:-10px;margin-top:8px;cursor:pointer;}
/* 设置未选中提示图标的样式 */
.login-main .login-bottom .tip .icon-nocheck {display:inline-block;width:10px;height:10px;border-radius:2px;border:solid 1px #9abcda;position:relative;top:2px;margin:1px 8px 1px 1px;cursor:pointer;}
/* 设置选中提示图标的样式 */
.login-main .login-bottom .tip .icon-check {margin:0 7px 0 0;width:14px;height:14px;border:none;background:url(../images/icon-login.png) no-repeat -111px -48px;}
/* 设置图标的通用样式 */
.login-main .login-bottom .center .item .icon {display:inline-block;width:33px;height:22px;}
/* 设置每个输入项的样式 */
.login-main .login-bottom .center .item {width:288px;height:35px;border-bottom:1px solid #dae1e6;margin-bottom:35px;}
/* 设置登录框的宽度和浮动属性 */
.login-main {width:428px;position:relative;float:left;}
/* 设置顶部区域的高度、背景颜色等样式 */
.login-main .login-top {height:117px;background-color:#148be4;border-radius:12px 12px 0 0;font-family:SourceHanSansCN-Regular;font-size:30px;font-weight:400;font-stretch:normal;letter-spacing:0;color:#fff;line-height:117px;text-align:center;overflow:hidden;-webkit-transform:rotate(0);-moz-transform:rotate(0);-ms-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0);}
/* 设置顶部区域的第一个背景图标样式 */
.login-main .login-top .bg1 {display:inline-block;width:74px;height:74px;background:#fff;opacity:.1;border-radius:0 74px 0 0;position:absolute;left:0;top:43px;}
/* 设置顶部区域的第二个背景图标样式 */
.login-main .login-top .bg2 {display:inline-block;width:94px;height:94px;background:#fff;opacity:.1;border-radius:50%;position:absolute;right:-16px;top:-16px;}
/* 设置底部区域的宽度、背景颜色等样式 */
.login-main .login-bottom {width:428px;background:#fff;border-radius:0 0 12px 12px;padding-bottom:53px;}
/* 设置底部中心区域的样式 */
.login-main .login-bottom .center {width:288px;margin:0 auto;padding-top:40px;padding-bottom:15px;position:relative;}
/* 设置提示信息的样式 */
.login-main .login-bottom .tip {clear:both;height:16px;line-height:16px;width:288px;margin:0 auto;}
/* 设置页面背景图片和字体大小 */
body {background:url(../images/login-bg3.jpg) 0% 0% / cover no-repeat;position:static;font-size:12px;}
/* 设置输入框在Webkit浏览器中的占位符样式 */
input::-webkit-input-placeholder {color:#a6aebf;}
/* 设置输入框在Mozilla Firefox浏览器中的占位符样式 */
input::-moz-placeholder {color:#a6aebf;}
/* 设置输入框在旧版Mozilla Firefox浏览器中的占位符样式 */
input:-moz-placeholder {color:#a6aebf;}
/* 设置输入框在Internet Explorer浏览器中的占位符样式 */
input:-ms-input-placeholder {color:#a6aebf;}
/* 取消Chrome记住密码的背景颜色 */
input:-webkit-autofill {-webkit-box-shadow:0 0 0 1000px white inset !important;}
/* 设置html元素的高度为100% */
html {height:100%;}
.login-main .login-bottom .tip {clear:both;height:16px;line-height:16px;width:288px;margin:0 auto;}
.login-main .login-bottom .tip .login-tip {font-family:MicrosoftYaHei;font-size:12px;font-weight:400;font-stretch:normal;letter-spacing:0;color:#9abcda;cursor:pointer;}
.login-main .login-bottom .tip .forget-password {font-stretch:normal;letter-spacing:0;color:#1391ff;text-decoration:none;position:absolute;right:62px;}
.login-main .login-bottom .login-btn {width:288px;height:40px;background-color:#1E9FFF;border-radius:16px;margin:24px auto 0;text-align:center;line-height:40px;color:#fff;font-size:14px;letter-spacing:0;cursor:pointer;border:none;}
.login-main .login-bottom .center .item .validateImg {position:absolute;right:1px;cursor:pointer;height:36px;border:1px solid #e6e6e6;}
.footer {left:0;bottom:0;color:#fff;width:100%;position:absolute;text-align:center;line-height:30px;padding-bottom:10px;text-shadow:#000 0.1em 0.1em 0.1em;font-size:14px;}
.padding-5 {padding:5px !important;}
.footer a,.footer span {color:#fff;}
@media screen and (max-width:428px) {.login-main {width:360px !important;}
.login-main .login-top {width:360px !important;}
.login-main .login-bottom {width:360px !important;}
}
</style>
</head>
<body>
<div class="main-body">
<!-- 主内容区域 -->
<div class="login-main">
<!-- 登录界面主体部分 -->
<div class="login-top">
<!-- 顶部标题和装饰背景 -->
<span>高校宿舍管理系统</span>
<!-- 背景装饰1 -->
<span class="bg1"></span>
<!-- 背景装饰2 -->
<span class="bg2"></span>
</div>
<!-- 登录表单 -->
<form class="layui-form login-bottom">
<!-- 居中对齐 -->
<div class="center">
<!-- 用户名输入框 -->
<div class="item">
<!-- 用户名图标 -->
<span class="icon icon-2"></span>
<!-- 用户名输入框验证必填默认值为admin自动完成关闭占位符为请输入登录账号最大长度24 -->
<input type="text" name="userName" lay-verify="required" value="admin" autocomplete="off" placeholder="请输入登录账号" maxlength="24"/>
</div>
<!-- 密码输入框 -->
<div class="item">
<!-- 密码图标 -->
<span class="icon icon-3"></span>
<!-- 密码输入框验证必填默认值为123456自动完成关闭占位符为请输入密码最大长度20 -->
<input type="password" name="password" lay-verify="required" value="123456" autocomplete="off" placeholder="请输入密码" maxlength="20">
<!-- 绑定密码图标 -->
<span class="bind-password icon icon-4"></span>
</div>
<!-- 角色选择下拉框 -->
<div class="item">
<!-- 角色选择图标 -->
<span class="icon icon-2" style="float: left"></span>
<div>
<!-- 角色选择下拉框,验证必填 -->
<select name="type" lay-verify="required">
<!-- 提示选择登陆角色 -->
<option value="">请选择登陆角色</option>
<!-- 管理员选项,默认选中 -->
<option value="0" selected>管理员</option>
<!-- 宿管员选项 -->
<option value="1">宿管员</option>
<!-- 学生选项 -->
<option value="2">学生</option>
</select>
</div>
</div>
</div>
<div class="layui-form-item" style="text-align:center; width:100%;height:100%;margin:0px;">
<button class="login-btn" lay-submit="" lay-filter="login">立即登录</button>
</div>
</form>
</div>
</div>
<div class="footer">
©版权所有 2020 研真教育
</div>
<script src="../lib/layui-v2.5.5/layui.js" charset="utf-8"></script>
<script src="../js/lay-config.js" charset="utf-8"></script>
<script>
// 使用layui模块
layui.use(['form','jquery','axios','layer','store'], function () {
var $ = layui.jquery,
form = layui.form,
axios = layui.axios,
layer = layui.layer,
store = layui.store,
layer = layui.layer;
// 如果当前页面不是顶层窗口则将顶层窗口的地址设置为当前页面地址跳出iframe框架
if (top.location != self.location) top.location = self.location;
// 绑定点击事件到密码显示按钮
$('.bind-password').on('click', function () {
// 如果按钮有'icon-5'类,移除该类并设置密码输入框类型为'password'
if ($(this).hasClass('icon-5')) {
$(this).removeClass('icon-5');
$("input[name='password']").attr('type', 'password');
} else {
// 否则添加'icon-5'类并设置密码输入框类型为'text'
$(this).addClass('icon-5');
$("input[name='password']").attr('type', 'text');
}
});
// 进行登录操作
form.on('submit(login)', function (data) {
// 获取表单数据
data = data.field;
axios({
// 设置请求方法为POST
method: 'post',
// 设置请求URL为/login
url: '/login',
// 将表单数据作为请求体发送
data: data
}).then(function(data){
// 如果返回的code为200表示登录成功
if(data.code == 200){
// 存储服务器返回的token
store.setToken(data.data.token)
// 如果返回的用户信息存在,则存储用户信息
if(data.data.user){
store.setLoginInfo(data.data.user,0);
}
// 如果返回的学生信息存在,则存储学生信息
if(data.data.student){
store.setLoginInfo(data.data.student,1);
}
// 跳转到首页
location.href='index.html'
}else{
// 如果登录失败,显示错误信息
layer.msg(data.msg);
}
}).catch(function(error){
// 捕获并处理请求过程中的错误
layer.msg(error);
});
// 阻止表单默认提交行为
return false;
});
</script>
</body>
</html>

@ -0,0 +1,287 @@
<style>
.welcome .layui-card {border:1px solid #f2f2f2;border-radius:5px;}
<!-- 设置卡片的边框和圆角 -->
.welcome .icon {margin-right:10px;color:#1aa094;}
<!-- 设置图标的右边距和颜色 -->
.welcome .icon-cray {color:#ffb800 !important;}
<!-- 设置特定图标的颜色为黄色 -->
.welcome .icon-blue {color:#1e9fff !important;}
<!-- 设置特定图标的颜色为蓝色 -->
.welcome .icon-tip {color:#ff5722 !important;}
<!-- 设置特定图标的颜色为橙色 -->
.welcome .layuimini-qiuck-module {text-align:center;margin-top:10px}
<!-- 设置快速模块的文本居中和上边距 -->
.welcome .layuimini-qiuck-module a i {display:inline-block;width:100%;height:60px;line-height:60px;text-align:center;border-radius:2px;font-size:30px;background-color:#F8F8F8;color:#333;transition:all .3s;-webkit-transition:all .3s;}
<!-- 设置快速模块中的链接图标样式,包括尺寸、对齐方式、背景色等 -->
.welcome .layuimini-qiuck-module a cite {position:relative;top:2px;display:block;color:#666;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:14px;}
<!-- 设置快速模块中的引用文本样式,包括位置、颜色、溢出处理等 -->
.welcome .welcome-module {width:100%;height:210px;}
<!-- 设置欢迎模块的宽度和高度 -->
.welcome .panel {background-color:#fff;border:1px solid transparent;border-radius:3px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}
<!-- 设置面板的背景色、边框和阴影效果 -->
.welcome .panel-body {padding:10px}
<!-- 设置面板主体的内边距 -->
.welcome .panel-title {margin-top:0;margin-bottom:0;font-size:12px;color:inherit}
<!-- 设置面板标题的外边距和字体大小 -->
.welcome .label {display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em;margin-top:.3em;}
<!-- 设置标签的显示方式、内边距、字体大小、行高、颜色、对齐方式等 -->
.welcome .layui-red {color:red}
<!-- 设置红色文字的颜色 -->
.welcome .main_btn > p {height:40px;}
<!-- 设置主按钮中段落的高度 -->
.welcome .layui-bg-number {background-color:#F8F8F8;}
<!-- 设置数字背景的颜色 -->
.welcome .layuimini-notice:hover {background:#f6f6f6;}
<!-- 设置通知悬停时的背景颜色 -->
.welcome .layuimini-notice {padding:7px 16px;clear:both;font-size:12px !important;cursor:pointer;position:relative;transition:background 0.2s ease-in-out;}
<!-- 设置通知的内边距、清除浮动、字体大小、光标类型、位置和过渡效果 -->
.welcome .layuimini-notice-title,.layuimini-notice-label {padding-right:70px !important;text-overflow:ellipsis !important;overflow:hidden !important;white-space:nowrap !important;}
<!-- 设置通知标题和标签的右内边距、文本溢出处理、隐藏溢出内容和不换行 -->
.welcome .layuimini-notice-title {line-height:28px;font-size:14px;}
<!-- 设置通知标题的行高和字体大小 -->
.welcome .layuimini-notice-extra {position:absolute;top:50%;margin-top:-8px;right:16px;display:inline-block;height:16px;color:#999;}
<!-- 设置通知额外信息的绝对定位、顶部偏移、右边距、显示方式、高度和颜色 -->
</style>
<!-- 主容器,包含页面动画效果 -->
<div class="layuimini-container layuimini-page-anim">
<!-- 主要内容区域class为welcome -->
<div class="layuimini-main welcome">
<!-- 行布局列间距为15px -->
<div class="layui-row layui-col-space15">
<!-- 占据8个栅格的列 -->
<div class="layui-col-md8">
<!-- 嵌套行布局 -->
<div class="layui-row">
<!-- 卡片组件高度400px -->
<div class="layui-card" style="height: 400px;">
<!-- 卡片头部,包含警告图标和标题 -->
<div class="layui-card-header"><i class="fa fa-warning icon"></i>数据统计</div>
<!-- 卡片主体部分 -->
<div class="layui-card-body">
<!-- 欢迎模块高度350px内容溢出时自动滚动 -->
<div class="welcome-module" style="height: 350px;overflow: auto;">
<!-- 表格组件使用line风格 -->
<table class="layui-table" lay-skin="line">
<tr>
<!-- 表头:楼宇 -->
<th>楼宇</th>
<!-- 表头:宿舍数量 -->
<th>宿舍数量</th>
<!-- 表头:入住人数 -->
<th>入住人数</th>
<!-- 表头:闲置数量 -->
<th>闲置数量</th>
<!-- 表头:使用率 -->
<th>使用率</th>
</tr>
<!-- 表格主体部分id为building-data -->
<tbody id="building-data"></tbody>
</table>
</div>
</div>
</div>
<div class="layui-card">
<!-- 报表统计卡片头部,包含图标和标题 -->
<div class="layui-card-header"><i class="fa fa-line-chart icon"></i>报表统计</div>
<div class="layui-card-body">
<!-- 报表统计的ECharts容器最小高度为365px -->
<div id="echarts-records" style="min-height:365px"></div>
</div>
</div>
</div>
</div>
<div class="layui-col-md4">
<div class="layui-card" style="height: 400px;">
<!-- 系统公告卡片头部,包含图标和标题 -->
<div class="layui-card-header"><i class="fa fa-bullhorn icon icon-tip"></i>系统公告</div>
<!-- 系统公告内容展示区域id为notice-data -->
<div class="layui-card-body layui-text" id="notice-data"></div>
</div>
<div class="layui-card">
<!-- 版本信息卡片头部,包含图标和标题 -->
<div class="layui-card-header"><i class="fa fa-fire icon"></i>版本信息</div>
<div class="layui-card-body layui-text">
<!-- 版本信息的表格结构 -->
<table class="layui-table">
<colgroup>
<col width="100">
<col>
</colgroup>
<tbody>
<tr>
<td>项目名称</td>
<td>
高校宿舍管理系统
</td>
</tr>
<tr>
<td>当前版本</td>
<td>v1.0.0</td>
</tr>
<tr>
<td>后端技术</td>
<td>SpringBoot</td>
</tr>
<tr>
<td>前端技术</td>
<td>Layui框架</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
layui.use(['layer','echarts'], function () {
// 引入layui的jquery、layer和echarts模块
var $ = layui.jquery,
layer = layui.layer,
echarts = layui.echarts;
// 判断登录类型是否为1如果是则清空欢迎信息并显示特定文本
if(store.getLoginType() == 1){
$('.welcome').empty(); // 清空欢迎信息
$('.welcome').append("欢迎高校学生宿舍管理系统"); // 添加特定文本到欢迎信息中
return; // 结束函数执行
}
/**
* 加载建筑信息的函数
* 通过axios发送GET请求获取建筑数据并将数据渲染到页面上
*/
function loadBuilding(){
// 发送GET请求获取建筑数据限制返回的数据条数为1000
axios.get('main/building',{limit:1000}).then(function (response) {
// 遍历响应数据中的每一项
response.data.forEach(item=>{
// 创建包含建筑信息的HTML字符串
let html = `<tr>
<td>${item.name}</td> <!-- 建筑名称 -->
<td>${item.all}</td> <!-- 总床位数 -->
<td>${item.used}</td> <!-- 已使用床位数 -->
<td>${item.unused}</td> <!-- 未使用床位数 -->
<td>${item.percent}%</td> <!-- 使用率百分比 -->
</tr>`
$('#building-data').append(html);
})
});
}
loadBuilding();
function loadNotice() {
axios.get('main/notice').then(function (response) {
response.data.forEach(item=>{
let html = `<div class="layuimini-notice">
<div class="layuimini-notice-title">${item.title}</div>
<div class="layuimini-notice-extra">${item.createTime}</div>
<div class="layuimini-notice-content layui-hide">${item.content}</div>
</div>`
$('#notice-data').append(html);
})
});
}
loadNotice();
$('body').on('click', '.layuimini-notice', function () {
// 获取公告标题文本
let title = $(this).children('.layuimini-notice-title').text(),
// 获取公告时间文本
noticeTime = $(this).children('.layuimini-notice-extra').text(),
// 获取公告内容HTML
content = $(this).children('.layuimini-notice-content').html();
// 构建公告弹窗的HTML内容
let html = '<div style="padding:15px 20px; text-align:justify; line-height: 22px;border-bottom:1px solid #e2e2e2;background-color: #eeeeee;color: #222222;">\n' +
'<div style="text-align: center;margin-bottom: 20px;font-weight: bold;border-bottom:1px solid #718fb5;padding-bottom: 5px"><h4 class="text-danger">' + title + '</h4></div>\n' +
'<div style="font-size: 14px">' + content + '</div>\n' +
'</div>\n';
// 使用layer插件打开公告弹窗
parent.layer.open({
// 弹窗类型为页面层
type: 1,
// 设置弹窗标题,包含系统公告和公告时间
title: '系统公告' + '<span style="float: right;right: 1px;font-size: 12px;color: #b1b3b9;margin-top: 1px">' + noticeTime + '</span>',
// 设置弹窗宽度
area: '400px;',
// 设置遮罩透明度
shade: 0.8,
// 设置弹窗ID
id: 'layuimini-notice',
// 设置弹窗按钮
btn: ['取消'],
// 设置按钮对齐方式为居中
btnAlign: 'c',
// 设置拖拽类型
moveType: 1,
// 设置弹窗内容为构建的HTML
content: html
});
});
});
function loadReport(){
// 使用axios发送GET请求获取建筑数据限制返回1000条记录
axios.get('main/building',{limit:1000}).then(function (response) {
// 从响应数据中提取每个建筑的used属性值
let used = response.data.map(item=>item.used);
// 从响应数据中提取每个建筑的name属性值
let name = response.data.map(item=>item.name);
// 调用loadEchars函数将提取到的名称和数值传递给它
loadEchars(name,used);
});
}
// 调用loadReport函数加载报告数据
loadReport();
function loadEchars(name,values){
// 初始化echarts实例绑定到页面中的'echarts-records'元素,并使用'walden'主题
let echartsRecords = echarts.init(document.getElementById('echarts-records'), 'walden');
// 配置echarts图表的选项
let option = {
xAxis: {
// x轴类型为类目轴
type: 'category',
// x轴的数据为建筑名称
data: name
},
tooltip: {}, // 提示框组件,默认配置
yAxis: {
// y轴类型为数值轴
type: 'value'
},
series: [{
// 系列数据为传入的数值数组
data: values,
// 系列类型为柱状图
type: 'bar',
// 显示背景
showBackground: true,
backgroundStyle: {
// 设置背景颜色为半透明灰色
color: 'rgba(220, 220, 220, 0.8)'
}
}]
};
// 设置 ECharts 图表的配置项和数据
echartsRecords.setOption(option);
// 定义窗口大小变化时的事件处理函数,使 ECharts 图表自适应窗口大小
window.onresize = function () {
// 调用 ECharts 实例的 resize 方法,调整图表大小以适应新的窗口尺寸
echartsRecords.resize();
}
}
});
</script>

@ -0,0 +1,120 @@
layui.define(['ztree', 'jquery','axios'], function (exports) {
"use strict";
// 定义模块名称为 'selectOrg'
let MOD_NAME = 'selectOrg',
// 引入 layui 的 jQuery 模块
$ = layui.jquery,
// 引入 layui 的 axios 模块
axios = layui.axios,
// 引入 layui 的 ztree 模块
ztree = layui.ztree;
// 定义 selectOrg 类
let selectOrg = function () {
// 初始化版本号为 '1.1.0'
this.v = '1.1.0';
};
selectOrg.prototype.render = function (opt) {
// 获取目标元素
let elem = $(opt.elem);
// 获取渲染完成后的回调函数,默认为空函数
let tableDone = opt.done || function(){};
// 设置表格高度默认为315px
opt.height = opt.height || 315;
// 设置表格最小宽度默认为300px
opt.width = opt.width || 300;
// 为元素绑定点击事件,防止事件冒泡
elem.off('click').on('click', function(e) {
// 阻止事件冒泡
e.stopPropagation();
// 如果页面上已经存在treeSelect元素则返回false
if($('div.treeSelect').length >= 1){
return false;
}
// 计算treeSelect的top和left位置
let t = elem.offset().top + elem.outerHeight()+"px";
let l = elem.offset().left +"px";
// 构建treeSelect的HTML结构
let treeBox = '<div class="treeSelect layui-anim layui-anim-upbit" style="left:'+l+';top:'+t+';border: 1px solid #d2d2d2;background-color: #fff;box-shadow: 0 2px 4px rgba(0,0,0,.12);padding:10px 10px 0 10px;position: absolute;z-index:66666666;margin: 5px 0;border-radius: 2px;min-width:'+opt.width+'px;max-height: 300px;overflow: auto;">';
// 如果opt.checked为真则添加确定按钮
if(opt.checked){
treeBox += '<div><button type="button" style="float: right" class="layui-btn layui-btn-normal layui-btn-sm tree-sure">确定</button></div>';
}
// 添加ztree容器
treeBox += '<div class="ztree" id="ztree_xx">';
treeBox += '</div>';
// 将treeBox转换为jQuery对象
treeBox = $(treeBox);
// 将treeBox添加到body元素中
$('body').append(treeBox);
let setting = {
// 定义树结构的基本数据格式
data: {
simpleData: {
enable: true // 启用简单数据模式
}
},
// 定义点击事件的回调函数
callback:{
onClick:function (event, treeId, treeNode) {
// 如果未选中任何节点
if(!opt.checked){
$('.treeSelect').remove(); // 移除树选择元素
opt.done([treeNode]); // 执行完成回调函数并传递当前点击的节点
}
}
},
// 定义树节点的选中状态
check:{
enable: opt.checked // 根据外部传入的 opt.checked 决定是否启用节点选中功能
}
};
// 使用 axios 获取组织树数据,并初始化 ztree
axios.get('org/tree').then(function (response) {
// 初始化 ztree传入目标元素、配置和数据
ztree.init($("#ztree_xx"), setting, response.data);
// 获取 ztree 对象
let treeObj = ztree.getZTreeObj("ztree_xx");
if(opt.checked){
// 如果 opt.checked 为真,初始化 checked 节点
opt.selected.forEach(v=>{
// 根据 id 获取节点
let checkNodes = treeObj.getNodesByParam("id", v, null);
// 设置节点为选中状态
treeObj.checkNode(checkNodes[0], true);
});
// 确定按钮点击事件,获取选中的节点并处理
$('.tree-sure').click(function () {
// 获取所有选中的节点
let arr = treeObj.getCheckedNodes(true);
// 调用 done 方法处理选中的节点
opt.done(arr);
// 更新 opt.selected 为选中节点的 id 数组
opt.selected = arr.map(item=>item.id);
// 移除树框
treeBox.remove();
});
}
}).catch(function (error) {
// 捕获并打印错误信息
console.log(error);
});
// 监听文档的 mouseup 事件,用于移除树选择框
$(document).mouseup(function(e){
// 获取用户设置的容器元素和树选择框元素
let userSet_con = $(''+opt.elem+',.treeSelect');
// 如果点击的目标不是用户设置的容器或其子元素,则移除树选择框
if(!userSet_con.is(e.target) && userSet_con.has(e.target).length === 0){
treeBox.remove();
}
});
}); // elem end
// 导出模块,创建新的 selectOrg 实例
exports(MOD_NAME, new selectOrg());

@ -0,0 +1,135 @@
layui.define(['layer', 'carousel'], function (exports) {
// 引入 jQuery 模块
var $ = layui.jquery;
// 引入 layer 模块
var layer = layui.layer;
// 引入 carousel 模块
var carousel = layui.carousel;
// 添加步骤条dom节点
var renderDom = function (elem, stepItems, postion) {
// 初始化步骤条的 HTML 字符串
var stepDiv = '<div class="lay-step">';
// 遍历步骤项数组,生成每个步骤项的 HTML
for (var i = 0; i < stepItems.length; i++) {
// 为每个步骤项添加一个包含类名 "step-item" 的 div 标签
stepDiv += '<div class="step-item">';
// 线
// 检查当前索引是否小于步骤项数组的最后一个索引
if (i < (stepItems.length - 1)) {
// 如果当前索引小于目标位置
if (i < postion) {
// 添加已完成的步骤项尾部HTML代码
stepDiv += '<div class="step-item-tail"><i class="step-item-tail-done"></i></div>';
} else {
// 添加未完成的步骤项尾部HTML代码
stepDiv += '<div class="step-item-tail"><i class=""></i></div>';
}
}
// 数字
// 获取当前步骤的编号
var number = stepItems[i].number;
// 如果当前步骤没有编号则使用默认编号步骤索引加1
if (!number) {
number = i + 1;
}
// 根据当前步骤的位置生成相应的HTML代码
if (i == postion) {
// 如果当前步骤是活动步骤,添加活动状态的样式
stepDiv += '<div class="step-item-head step-item-head-active"><i class="layui-icon">' + number + '</i></div>';
} else if (i < postion) {
// 如果当前步骤在活动步骤之前,添加已完成状态的样式
stepDiv += '<div class="step-item-head"><i class="layui-icon layui-icon-ok"></i></div>';
} else {
// 如果当前步骤在活动步骤之后,添加未完成状态的样式
stepDiv += '<div class="step-item-head "><i class="layui-icon">' + number + '</i></div>';
}
// 获取当前步骤的标题和描述
var title = stepItems[i].title;
var desc = stepItems[i].desc;
// 如果标题或描述存在则创建包含标题和描述的HTML结构
if (title || desc) {
stepDiv += '<div class="step-item-main">';
// 如果标题存在添加标题的HTML结构
if (title) {
stepDiv += '<div class="step-item-main-title">' + title + '</div>';
}
// 如果描述存在添加描述的HTML结构
if (desc) {
stepDiv += '<div class="step-item-main-desc">' + desc + '</div>';
}
stepDiv += '</div>';
}
// 关闭当前步骤的div标签
stepDiv += '</div>';
}
// 关闭所有步骤的容器div标签
stepDiv += '</div>';
// 将生成的HTML插入到指定的元素中
$(elem).prepend(stepDiv);
// 计算每一个条目的宽度,使其平均分布
var bfb = 100 / stepItems.length;
$('.step-item').css('width', bfb + '%');
};
var step = {
// 渲染步骤条
render: function (param) {
param.indicator = 'none'; // 不显示指示器
param.arrow = 'always'; // 始终显示箭头
param.autoplay = false; // 关闭自动播放
if (!param.stepWidth) {
param.stepWidth = '400px'; // 如果未设置步骤条宽度则默认为400px
}
// 渲染轮播图
carousel.render(param);
// 渲染步骤条
var stepItems = param.stepItems;
renderDom(param.elem, stepItems, 0); // 初始渲染步骤条DOM元素
$('.lay-step').css('width', param.stepWidth); // 设置步骤条的宽度
//监听轮播切换事件
carousel.on('change(' + param.filter + ')', function (obj) {
$(param.elem).find('.lay-step').remove(); // 移除旧的步骤条DOM元素
renderDom(param.elem, stepItems, obj.index); // 根据当前索引重新渲染步骤条DOM元素
$('.lay-step').css('width', param.stepWidth); // 设置步骤条的宽度
});
// 隐藏左右箭头按钮
$(param.elem).find('.layui-carousel-arrow').css('display', 'none');
// 去掉轮播图的背景颜色
$(param.elem).css('background-color', 'transparent');
},
// 下一步
next: function (elem) {
// 触发点击事件,使轮播图切换到下一张
$(elem).find('.layui-carousel-arrow[lay-type=add]').trigger('click');
},
// 上一步
pre: function (elem) {
// 触发点击事件,使轮播图切换到上一张
$(elem).find('.layui-carousel-arrow[lay-type=sub]').trigger('click');
}
};
// 加载外部CSS文件
layui.link(layui.cache.base + 'step-lay/step.css');
// 导出模块
exports('step', step);
});

@ -0,0 +1,41 @@
layui.define([], function (exports) {
// 定义一个存储模块,用于处理本地存储操作
exports("store", store = {
// 设置 token 到本地存储
setToken: function (token) {
// 将传入的 token 值保存到 localStorage 中,键名为 "token"
localStorage.setItem("token", token)
},
// 从本地存储获取 token
getToken: function () {
// 从本地存储中获取名为 "token" 的项并返回其值
return localStorage.getItem("token");
},
// 清除本地存储中的 token
clear: function () {
return localStorage.removeItem("token");
},
// 设置登录信息到本地存储
setLoginInfo: function (obj, type) {
// 如果传入的用户对象存在
if (obj) {
// 将用户名存储到本地存储中
localStorage.setItem("userName", obj.name);
// 将用户类型存储到本地存储中
localStorage.setItem("type", type);
}
}
}
},
// 从本地存储获取用户名
getLoginInfo: function () {
// 从localStorage中获取键为"userName"的值并返回
return localStorage.getItem("userName");
}
},
// 从本地存储获取登录类型
getLoginType: function () {
return localStorage.getItem("type");
}
});
});

@ -0,0 +1,301 @@
layui.define(['layer', 'table'], function (exports) {
// 引入jQuery库
var $ = layui.jquery;
// 引入layer模块
var layer = layui.layer;
// 引入table模块
var table = layui.table;
var treetable = {
render: function (param) {
// 检查参数是否合法
if (!treetable.checkParam(param)) {
// 如果参数不合法,直接返回
return;
}
// 获取数据
if (param.data) {
// 如果参数中包含数据,则直接初始化树表
treetable.init(param, param.data);
} else {
// 如果参数中不包含数据则通过AJAX请求获取数据并初始化树表
$.getJSON(param.url, param.where, function (res) {
treetable.init(param, res.data);
});
}
},
};
});
// 渲染表格
init: function (param, data) {
// 存储处理后的数据
var mData = [];
// 保存回调函数
var doneCallback = param.done;
// 获取传入的节点数据
var tNodes = data;
// 补上id和pid字段
for (var i = 0; i < tNodes.length; i++) {
var tt = tNodes[i];
// 检查tt对象是否有id属性如果没有则进行以下操作
if (!tt.id) {
// 如果param对象中没有treeIdName属性提示错误信息并返回
if (!param.treeIdName) {
layer.msg('参数treeIdName不能为空', {icon: 5});
return;
}
// 将tt对象的id属性设置为tt对象中对应treeIdName属性的值
tt.id = tt[param.treeIdName];
}
// 检查tt对象是否有pid属性如果没有则进行以下操作
if (!tt.pid) {
// 如果param对象中没有treePidName属性提示错误信息并返回
if (!param.treePidName) {
layer.msg('参数treePidName不能为空', {icon: 5});
return;
}
// 将tt对象的pid属性设置为tt对象中对应treePidName属性的值
tt.pid = tt[param.treePidName];
}
var sort = function (s_pid, data) {
// 遍历数据数组中的每一个元素
for (var i = 0; i < data.length; i++) {
// 如果当前元素的父节点ID等于传入的父节点ID
if (data[i].pid == s_pid) {
// 获取mData数组的长度
var len = mData.length;
// 如果mData数组不为空且最后一个元素的ID等于传入的父节点ID
if (len > 0 && mData[len - 1].id == s_pid) {
// 将最后一个元素的isParent属性设置为true
mData[len - 1].isParent = true;
}
// 将当前元素添加到mData数组中
mData.push(data[i]);
// 递归调用sort函数处理当前元素的子节点
sort(data[i].id, data);
}
}
};
sort(param.treeSpid, tNodes);
// 对树形节点进行排序
param.url = undefined;
// 将参数中的URL设置为undefined
param.data = mData;
// 将处理后的数据赋值给参数的data属性
param.page = {
count: param.data.length,
limit: param.data.length
};
// 设置分页信息count和limit都为数据的长度
param.cols[0][param.treeColIndex].templet = function (d) {
// 定义树表列的模板函数
var mId = d.id;
// 获取当前节点的ID
var mPid = d.pid;
// 获取当前节点的父节点ID
var isDir = d.isParent;
// 判断当前节点是否为目录(是否有子节点)
var emptyNum = treetable.getEmptyNum(mPid, mData);
// 计算当前节点前面的空位数量
var iconHtml = '';
// 初始化图标HTML字符串
for (var i = 0; i < emptyNum; i++) {
iconHtml += '<span class="treeTable-empty"></span>';
// 根据空位数量生成相应数量的空位图标
}
if (isDir) {
// 如果是目录,添加两个图标:一个三角形和一个图层图标
iconHtml += '<i class="layui-icon layui-icon-triangle-d"></i> <i class="layui-icon layui-icon-layer"></i>';
} else {
// 如果是文件,添加一个文件图标
iconHtml += '<i class="layui-icon layui-icon-file"></i>';
}
// 添加两个空格作为间隔
iconHtml += '&nbsp;&nbsp;';
// 根据是否是目录设置类型为'dir'或'file'
var ttype = isDir ? 'dir' : 'file';
// 创建包含图标和名称的HTML字符串
var vg = '<span class="treeTable-icon open" lay-tid="' + mId + '" lay-tpid="' + mPid + '" lay-ttype="' + ttype + '">';
// 返回完整的HTML字符串
return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '</span>'
param.done = function (res, curr, count) {
// 在目标元素后插入一个带有'class'为'treeTable'的元素
$(param.elem).next().addClass('treeTable');
// 隐藏'treeTable'中的分页控件
$('.treeTable .layui-table-page').css('display', 'none');
// 设置'treeTable'元素的'treeLinkage'属性
$(param.elem).next().attr('treeLinkage', param.treeLinkage);
// 如果设置了默认关闭树形结构,则折叠所有节点
if (param.treeDefaultClose) {
treetable.foldAll(param.elem);
}
// 如果存在回调函数,则执行回调函数
if (doneCallback) {
doneCallback(res, curr, count);
}
};
// 渲染表格
table.render(param);
},
// 计算缩进的数量
getEmptyNum: function (pid, data) {
// 初始化缩进数量为0
var num = 0;
// 如果pid不存在直接返回缩进数量0
if (!pid) {
return num;
}
// 临时变量tPid用于存储当前节点的父节点ID
var tPid;
// 遍历数据数组
for (var i = 0; i < data.length; i++) {
if (pid == data[i].id) {
// 如果当前节点的父ID与目标ID匹配则计数器加1
num += 1;
// 更新tPid为当前节点的父ID
tPid = data[i].pid;
// 跳出循环
break;
}
return num + treetable.getEmptyNum(tPid, data);
// 返回当前节点及其子节点的数量总和
},
// 展开/折叠行
toggleRows: function ($dom, linkage) {
// 获取当前行的lay-ttype属性值
var type = $dom.attr('lay-ttype');
// 如果类型是'file',直接返回
if ('file' == type) {
return;
}
// 获取当前行的lay-tid属性值
var mId = $dom.attr('lay-tid');
// 判断当前行是否处于打开状态
var isOpen = $dom.hasClass('open');
if (isOpen) {
// 如果当前状态是打开的,移除 'open' 类
$dom.removeClass('open');
} else {
// 如果当前状态是关闭的,添加 'open' 类
$dom.addClass('open');
}
// 遍历当前元素最近的父级 <tbody> 中的所有 <tr> 元素
$dom.closest('tbody').find('tr').each(function () {
// 获取当前行中的树表图标元素
var $ti = $(this).find('.treeTable-icon');
// 获取图标元素的父节点 ID
var pid = $ti.attr('lay-tpid');
// 获取图标元素的类型(目录或文件)
var ttype = $ti.attr('lay-ttype');
// 判断图标元素是否处于打开状态
var tOpen = $ti.hasClass('open');
// 如果当前行的父节点 ID 与目标 ID 相同
if (mId == pid) {
if (isOpen) {
// 如果当前状态是打开的,隐藏当前行
$(this).hide();
// 如果当前行的类型是目录且其打开状态与当前状态一致,触发点击事件
if ('dir' == ttype && tOpen == isOpen) {
$ti.trigger('click');
}
} else {
// 如果当前状态是关闭的,显示当前行
$(this).show();
// 如果需要联动且当前行的类型是目录且其打开状态与当前状态一致,触发点击事件
if (linkage && 'dir' == ttype && tOpen == isOpen) {
$ti.trigger('click');
}
}
}
});
// 检查参数
checkParam: function (param) {
if (!param.treeSpid && param.treeSpid != 0) {
// 如果参数treeSpid为空且不等于0则弹出提示信息并返回false
layer.msg('参数treeSpid不能为空', {icon: 5});
return false;
}
if (!param.treeColIndex && param.treeColIndex != 0) {
// 如果参数treeColIndex为空且不等于0则弹出提示信息并返回false
layer.msg('参数treeColIndex不能为空', {icon: 5});
return false;
}
// 参数验证通过返回true
return true;
},
// 展开所有
expandAll: function (dom) {
// 查找指定DOM元素的下一个兄弟元素中的树表遍历其每一行
$(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () {
// 获取当前行的树图标元素
var $ti = $(this).find('.treeTable-icon');
// 获取树图标的类型属性
var ttype = $ti.attr('lay-ttype');
// 判断树图标是否处于打开状态
var tOpen = $ti.hasClass('open');
// 如果类型是目录且未打开,则触发点击事件以展开目录
if ('dir' == ttype && !tOpen) {
$ti.trigger('click');
}
});
},
// 折叠所有树节点
foldAll: function (dom) {
// 遍历指定DOM元素下的所有树表行
$(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () {
// 获取当前行的图标元素
var $ti = $(this).find('.treeTable-icon');
// 获取图标元素的类型属性
var ttype = $ti.attr('lay-ttype');
// 判断图标是否处于打开状态
var tOpen = $ti.hasClass('open');
// 如果图标类型为目录且处于打开状态,则触发点击事件以折叠该节点
if ('dir' == ttype && tOpen) {
$ti.trigger('click');
}
});
}
};
// 加载树表样式文件
layui.link(layui.cache.base + 'treetable-lay/treetable.css');
// 给图标列绑定点击事件
$('body').on('click', '.treeTable .treeTable-icon', function () {
// 获取当前树表的联动属性值
var treeLinkage = $(this).parents('.treeTable').attr('treeLinkage');
// 根据联动属性值决定是否联动展开或折叠行
if ('true' == treeLinkage) {
treetable.toggleRows($(this), true);
} else {
treetable.toggleRows($(this), false);
}
});
// 导出 treetable 模块,使其可以在其他文件中被引用和使用
exports('treetable', treetable);
});

File diff suppressed because one or more lines are too long

@ -0,0 +1,3 @@
张淑淇3000
施彤彤3000
程芳芳3000
Loading…
Cancel
Save