cooladmin/admin/view/index/index.html

583 lines
23 KiB
HTML

<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,
maximum-scale=1, user-scalable=no" />
<title>首页 - {$admin_page_title|default=''}</title>
<link rel="icon" href="{$admin_favicon|default=''}" type="image/ico">
<meta name="description" content="{$admin_page_description|default=''}">
<link rel="stylesheet" href="/assets/elementui/css/index.css?v={$admin_assets_ver|default='1.0'}" />
<link rel="stylesheet"
href="/assets/lightyearadmin/css/materialdesignicons.min.css?v={$admin_assets_ver|default='1.0'}">
</head>
<body>
<div id="app" class="hidden" element-loading-background="rgba(0, 0, 0, 0.3)">
<div class="page-layout" :class="{ collapse: menuCollapse }">
<!-- 遮罩层 -->
<div class="page-layout__mask" @click="collapseMenu(true)"></div>
<div class="page-layout__left">
<!-- 侧栏 -->
<div class="app-slider">
<div class="app-slider__logo">
<template v-if="menuCollapse || browser.isMini">
<span @click="collapseMenu(false)"><img class="mini"
src="/assets/elementui/icon/logo/silder-simple.png" /></span>
</template>
<template v-else>
{$admin_logo|raw|default='admin'}
</template>
</div>
<div class="app-slider__menu">
<div class="cl-slider-menu">
<el-menu :default-active="activeTabId" background-color="transparent" :collapse-transition="false"
:collapse="browser.isMini ? false : menuCollapse" @select="leftMenuSelect">
<template v-for="(item, index) in leftMenu">
<el-submenu v-show="!hasTopMenu || item.pid == topActiveId"
v-if="item.children && item.children.length" popper-class="cl-slider-menu__submenu"
:index="item.id">
<template slot="title">
<i class="icon-svg" :class="item.icon"></i>
<span slot="title">{{item.name}}</span>
</template>
<template v-for="(subitem1, index) in item.children">
<el-submenu v-if="subitem1.children && subitem1.children.length"
popper-class="cl-slider-menu__submenu" :index="subitem1.id">
<template slot="title">
<i class="icon-svg" :class="subitem1.icon"></i>
<span slot="title">{{subitem1.name}}</span>
</template>
<template v-for="(subitem2, index) in subitem1.children">
<el-submenu v-if="subitem2.children && subitem2.children.length"
popper-class="cl-slider-menu__submenu" :index="subitem2.id">
<template slot="title">
<i class="icon-svg" :class="subitem2.icon"></i>
<span slot="title" @contextmenu.prevent="stopDefault">{{subitem2.name}}</span>
</template>
</el-submenu>
<el-menu-item v-else :index="subitem2.id">
<i class="icon-svg" :class="subitem2.icon"></i>
<span slot="title" @contextmenu.prevent="stopDefault">{{subitem2.name}}</span>
</el-menu-item>
</template>
</el-submenu>
<el-menu-item v-else :index="subitem1.id">
<i class="icon-svg" :class="subitem1.icon"></i>
<span slot="title" @contextmenu.prevent="stopDefault">{{subitem1.name}}</span>
</el-menu-item>
</template>
</el-submenu>
<el-menu-item v-show="!hasTopMenu || item.pid == topActiveId" v-else :index="item.id" :key="item.id">
<i class="icon-svg" :class="item.icon"></i>
<span slot="title" @contextmenu.prevent="stopDefault">{{item.name}}</span>
</el-menu-item>
</template>
</el-menu>
</div>
</div>
</div>
</div>
<div class="page-layout__right">
<!-- 顶栏 -->
<div class="page-layout__topbar">
<div class="app-topbar">
<div class="app-topbar__collapse" @click="collapseMenu(!menuCollapse)">
<i :class="[menuCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold']"></i>
</div>
<!-- 一级菜单 -->
<div class="app-topbar__menu" v-if="hasTopMenu">
<div class="cl-menu-topbar">
<el-menu :default-active="topActiveId" mode="horizontal" background-color="transparent"
@select="topMenuSelect">
<el-menu-item v-for="(item, index) in topMenu" :index="item.id" :key="item.id">
<i class="icon-svg" :class="item.icon"></i>
<span>{{ item.name }}</span>
</el-menu-item>
</el-menu>
</div>
</div>
<div class="cl-route-nav" v-if="!browser.isMini && !hasTopMenu">
<p class="title">
{$admin_page_title|default='admin'}
</p>
</div>
<div class="flex1"></div>
<!-- 工具栏 -->
<ul class="app-topbar__tools">
<li>
<a title="打开首页" href="/" target="_blank"><i class="el-icon-house"></i></a>
</li>
{if condition="checkUrl(url('/admin/index/clearcache'))"}
<li>
<a title="清空缓存" @click="onCommand('清空缓存|{:url('/admin/index/clearcache')}')"><i
class="el-icon-delete"></i></a>
</li>
{/if}
<!-- 主题 -->
<li @click="openTheme">
<a title="主题"><i class="el-icon-magic-stick"></i></a>
</li>
{:\\tpext\\common\\ExtLoader::trigger('topbar_right_links')}
</ul>
<div class="cl-theme">
<!-- 系统设置 -->
<el-drawer title="系统设置" :visible.sync="drawer.visible" size="300px">
<div class="cl-theme__container">
<div class="cl-theme__color is-card">
<p>主题</p>
<ul>
<el-tooltip v-for="(item, name) in themes" :key="name" :content="item.label" placement="top">
<li :style="{
backgroundColor: item.color
}" @click="setTheme(item)">
<i class="el-icon-check" v-show="item.color == themeInfo.color"></i>
</li>
</el-tooltip>
</ul>
</div>
<div class="cl-theme__switch is-card">
<p>内容区域</p>
<ul>
<li v-if="!browser.isMini">
<el-tooltip class="item" effect="dark" content="顶级菜单放到顶部显示,点击切换左边子菜单" placement="top-start">
<span>显示顶部菜单栏</span>
</el-tooltip>
<el-switch size="mini" v-model="hasTopMenu"></el-switch>
</li>
<li>
<el-tooltip class="item" effect="dark" content="切换顶部菜时激活其所属的第一个子菜单" placement="top-start">
<span>激活第一个子菜单</span>
</el-tooltip>
<el-switch v-popover:popover :disabled="!hasTopMenu" size="mini" v-model="activeFirst">
</el-switch>
</li>
<li>
<el-tooltip class="item" effect="dark" content="收起来或展开左侧菜单" placement="top-start">
<span>收缩左侧菜单栏</span>
</el-tooltip>
<el-switch size="mini" v-model="menuCollapse"></el-switch>
</li>
<li>
<el-tooltip class="item" effect="dark" content="多页面选项卡,可控制在多个页面之间切换" placement="top-start">
<span>显示页面切换栏</span>
</el-tooltip>
<el-switch size="mini" v-model="showProcess"></el-switch>
</li>
</ul>
</div>
</div>
</el-drawer>
</div>
<!-- 用户信息 -->
<div class="app-topbar__user">
<el-dropdown trigger="click" @command="onCommand">
<span class="el-dropdown-link">
<span class="name"
title="{$admin_user.group_name|default=''}">{$admin_user.name|default='Tpext'}</span>
<img class="avatar" src="{$admin_user.avatar|default='/assets/lightyearadmin/images/no-avatar.jpg'}"
alt />
</span>
<el-dropdown-menu slot="dropdown" class="popper-dropdown-menu-user">
<el-dropdown-item command="个人中心|{:url('/admin/index/profile')}">个人中心</el-dropdown-item>
<el-dropdown-item command="修改密码|{:url('/admin/index/changepwd')}">修改密码</el-dropdown-item>
<el-dropdown-item command="exit">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
<!-- 页面进程 -->
<div v-if="showProcess" class="page-layout__process">
<div class="app-process">
<div class="app-process__left hidden-xs-only" @click="toScroll(true)">
<i class="el-icon-arrow-left"></i>
</div>
<div class="app-process__scroller" ref="scroller">
<div @dblclick="reloadItem(item)" class="app-process__item" v-for="(item, index) in processList"
:key="index" :ref="`item-${item.id}`" :class="{ active: activeTabId == item.id}" :data-index="index"
@click="activeItem(item,index)">
<span>{{ item.label }}</span>
<i class="el-icon-close" v-if="index > 0" @click.stop="onDel(index)"></i>
</div>
</div>
<div class="app-process__right hidden-xs-only" @click="toScroll(false)">
<i class="el-icon-arrow-right"></i>
</div>
<el-dropdown @command="tabDropdownAction">
<span class="el-dropdown-link">
操作<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="current" icon="el-icon-minus">关闭当前</el-dropdown-item>
<el-dropdown-item command="other" icon="el-icon-remove-outline">关闭其他</el-dropdown-item>
<el-dropdown-item command="all" icon="el-icon-circle-close">关闭所有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
<!-- 页面视图 -->
<div class="page-layout__container" v-loading="iframeLoading">
<div class="page-layout__view">
<iframe @load="iframeLoading=false" :ref="`iframe-${item.id}`" :class="{ hidden: activeTabId != item.id}"
v-for="(item, index) in processList" :key="index" :name="'iframe'+index" width="100%" height="100%"
:src="item.value" frameborder="0" :data-url="item.value" seamless></iframe>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/assets/elementui/lib/vue.min.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript" src="/assets/elementui/lib/index.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript" src="/assets/elementui/js/index.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript" src="/assets/elementui/lib/axios.min.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript" src="/assets/lightyearadmin/js/jquery.min.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript" src="/assets/tpextbuilder/js/layer/layer.js?v={$admin_assets_ver|default='1.0'}"
charset="utf-8"></script>
<script type="text/javascript">
var that = null;
var browser = getBrowser();
var themes = getThemes();
var json_str = '{$menus|raw}';
var menuJson = JSON.parse(json_str);
var app = new Vue({
el: "#app",
data() {
return {
hasTopMenu: '{$index_top_menu ?? 0}' == '1' && !browser.isMini,
activeFirst: localStorage.getItem('activeFirst') == 'y',
showProcess: true,
menuCollapse: localStorage.getItem('menuCollapse') == 'y',
topMenu: [],
leftMenu: [],
processList: [
{
id: '{$dashbord.id}',
label: '{$dashbord.name}',
value: '{$dashbord.url}',
}
],
iframeLoading: true,
activeTabId: '{$dashbord.id}',
activeTabIndex: 0,
topActiveId: 0,
drawer: {
visible: false
},
themeInfo: {
label: "",
name: "",
color: ""
},
themes: themes,
}
},
watch: {
hasTopMenu(v) {
this.buildMenu();
},
activeFirst(v) {
localStorage.setItem('activeFirst', v ? 'y' : 'n');
},
menuCollapse(v) {
localStorage.setItem('menuCollapse', v ? 'y' : 'n');
}
},
mounted() {
that = this;
this.buildMenu();
var theme = JSON.parse(localStorage.getItem('index_theme') || '{}');
if (!theme || !theme.name || !theme.color) {
theme = this.themes[0];
}
that.setTheme(theme);
Vue.nextTick(function () {
document.getElementById('app').className = ''
});
},
methods: {
buildMenu() {
var treeObj = treeData(menuJson, 'id', 'pid', 'children');
if (this.hasTopMenu) {
var menuInfo = getSubMenu(treeObj);
this.leftMenu = menuInfo.left;
this.topMenu = menuInfo.top;
}
else {
this.leftMenu = treeObj;
this.topMenu = [];
}
},
collapseMenu(is) {
that.menuCollapse = is;
localStorage.setItem('menuCollapse', is ? 'y' : 'n');
},
onCommand(e) {
if (e == 'exit') {
that.$confirm('确定要注销登录?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
location.replace("{:url('/admin/index/logout')}");
}).catch(() => {
//
});
}
else {
var arr = e.split('|');
var url = arr[1].replace(/\.html/i, '');
var find = this.processList.find(e => (e.value == url || e.value == url + '.html'));
if (find) {
this.activeItem(find);
}
else {
var find0 = menuJson.find(e => (e.url == url || e.url == url + '.html'));
if (find0) {
this.openPage(
{
id: find0.id,
label: arr[0],
value: find0.url,
}
);
}
else {
this.openPage(
{
id: url.replace(/\W/g, ''),
label: arr[0],
value: url,
}
);
}
}
}
},
tabDropdownAction(e) {
if (e == 'current') {
this.onDel(this.processList.findIndex(e => e.id == this.activeTabId));
this.toPath();
}
else if (e == 'other') {
this.processList = this.processList.filter(
e => e.id == this.activeTabId || e.value == "{$dashbord.url}"
);
this.toPath();
}
else if (e == 'all') {
this.processList = this.processList.filter(
e => e.value == "{$dashbord.url}"
);
this.toPath();
}
},
openTheme() {
that.drawer.visible = true;
},
setTheme({ name, color, label }) {
if (that.themeInfo.color == color) {
return false;
}
if (that.themeInfo.label) {
that.$message.success(`切换主题:${label}`);
}
var theme = document.getElementById("theme-style");
var style = theme || document.createElement("link");
style.href = `/assets/elementui/theme/${name}.css`;
if (!theme) {
style.type = "text/css";
style.rel = "stylesheet";
style.id = "theme-style";
document.getElementsByTagName("head").item(0).appendChild(style);
}
// 设置主题色和路径
that.themeInfo.color = color;
that.themeInfo.url = style.href;
that.themeInfo.name = name;
localStorage.setItem('index_theme', JSON.stringify(that.themeInfo));
// 设置 css 变量
document.getElementsByTagName("body")[0].style.setProperty("--color-primary", color);
},
/*tab操作*/
activeItem(item, index) {
if (!item || this.activeTabId == item.id) {
return;
}
this.activeTabId = item.id;
if (index === undefined) {
for (var i in this.processList) {
if (this.processList[i].id == item.id) {
index = i;
break;
}
}
}
var diff = 50 * (index - this.activeTabIndex);//判断是往左点还是往右点,加上惯性
this.activeTabIndex = index;
if (index == 0 || index == this.processList.length - 1) {
var diff = 0;
}
var el = this.$refs[`item-${item.id}`][0];
if (el) {
that.scrollToItem(el.offsetLeft + el.clientWidth - that.$refs["scroller"].clientWidth + diff);
}
},
onDel(index) {
if (index != 0) {
this.processList.splice(index, 1);
var find = this.processList.find(e => e.id == this.activeTabId);
if (!find) {
if (index > 1) {
this.activeItem(this.processList[index - 1], index - 1);
}
else {
this.toPath();
}
}
}
},
toPath() {
var find = this.processList.find(e => e.id == this.activeTabId);
if (!find) {
var next = last(this.processList);
if (next) {
this.activeTabId = next.id;
}
}
},
toScroll(isLeft) {
this.scrollToItem(this.$refs["scroller"].scrollLeft + (isLeft ? -400 : 400));
},
scrollToItem(leftPos) {
this.$refs["scroller"].scrollTo({
left: leftPos,
behavior: "smooth"
});
},
leftMenuSelect(id) {
var find = this.processList.find(e => e.id == id);
if (find) {
this.activeItem(find);
}
else {
var find0 = menuJson.find(e => e.id == id);
if (find0) {
this.openPage(
{
id: find0.id,
label: find0.name,
value: find0.url,
}
);
}
}
},
topMenuSelect(id) {
this.topActiveId = id;
if (!this.activeFirst) {
return;
}
var find = menuJson.find(e => e.pid == id);
if (find) {
var find0 = this.processList.find(e => e.id == find.id);
if (find0) {
this.activeItem(find0);
}
else {
this.openPage(
{
id: find.id,
label: find.name,
value: find.url,
}
);
}
}
},
openPage(item) {
this.processList.push(item);
Vue.nextTick(function () {
setTimeout(function () {
that.activeItem(item, that.processList.length - 1);
}, 100);
});
this.iframeLoading = true;
setTimeout(function () {
this.iframeLoading = false;
}, 3000);
},
reloadItem(item) {
var el = this.$refs[`iframe-${item.id}`][0];
if (el) {
el.contentWindow.location.reload(true);
this.iframeLoading = true;
setTimeout(function () {
this.iframeLoading = false;
}, 3000);
}
},
stopDefault(e) {
e.preventDefault();
e.stopPropagation();
}
},
});
$('a.open-tab').click(function () {
$.fn.multitabs().create(this, true);
return false;
});
((function ($) {
// 兼容 lightyear 的 MultiTabs js
var MultiTabs = function (element) {
var self = this;
self.$element = $(element);
};
MultiTabs.prototype = {
constructor: MultiTabs,
/**
* create tab and return this.
* @param obj the obj to trigger multitabs
* @param active if true, active tab after create
* @returns this Chain structure.
*/
create: function (obj, active) {
var url = $(obj).attr("href"),
text = $.trim($(obj).attr('title') || $(obj).data('title') || $(obj).text());
app.onCommand(text + '|' + url);
return this;
},
};
$.fn.multitabs = function () {
var self = $(this),
did = 'multitabs',
multitabs = $(document).data(did);
if (!multitabs) {
multitabs = new MultiTabs(this);
$(document).data(did, multitabs);
}
return $(document).data(did);
};
})(jQuery));
</script>
</body>
</html>