update
This commit is contained in:
11
module/Application/view/application/index/index.phtml
Normal file
11
module/Application/view/application/index/index.phtml
Normal file
@ -0,0 +1,11 @@
|
||||
<div class="hero-unit">
|
||||
<p align="center"><img src="/img/ag-hero.png" alt="Laminas API Tools <?= \ApiTools\VERSION ?>"></p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span8">
|
||||
<p><br /><br />In order to use the <strong>Laminas API Tools Admin UI</strong> you need to enable the <strong>development</strong> mode. Currently your application is running in <strong>production</strong> mode.</p>
|
||||
<p>To enable the development mode you can execute the following command from the terminal:</p>
|
||||
<p><pre>$ composer development-enable</pre></p>
|
||||
<p>Remember to set always the production mode if you want to deploy your API in a staging/production environment.</p>
|
||||
</div>
|
||||
</div>
|
134
module/Application/view/application/login/auth.phtml
Normal file
134
module/Application/view/application/login/auth.phtml
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
$info = \Application\Service\Extension\Laminas::$serviceManager->adminWebsitefiling->getCurrentWebsiteFiling();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>登录申请</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
|
||||
<link rel="stylesheet" type="text/css" href="/css/weui.min.css">
|
||||
<style>
|
||||
#login-btn {
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
.weui-btn_primary {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.weui-list-tips__item:before {
|
||||
content: "\2022";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -0.1em;
|
||||
}
|
||||
.weui-list-tips:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
border-top: 1px solid #000000;
|
||||
color: rgba(0,0,0,0.1);
|
||||
-webkit-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
.weui-msg__desc+.weui-msg__custom-area, .weui-msg__desc-primary+.weui-msg__custom-area {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.weui-msg__custom-area {
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.weui-list-tips:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.weui-list-tips {
|
||||
list-style: none;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 24px;
|
||||
line-height: 1.4;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.weui-list-tips__item:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.weui-list-tips__item {
|
||||
position: relative;
|
||||
padding-left: 15px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.weui-btn_primary:not(.weui-btn_disabled):active {
|
||||
color: hsla(0,0%,100%,.6);
|
||||
background-color: #166a9b;
|
||||
}
|
||||
|
||||
.weui-msg__icon-area img{
|
||||
width: 120px;
|
||||
width: 120px;
|
||||
}
|
||||
.weui-msg__icon-area {
|
||||
height: 120px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!--头像-->
|
||||
<div class="container">
|
||||
<div class="page msg_success js_show" tabindex="-1">
|
||||
<div class="weui-msg">
|
||||
<div class="weui-msg__icon-area">
|
||||
<!-- <i class="weui-icon-success weui-icon_msg"></i>-->
|
||||
<img src="<?= current(json_decode($info['website_logo'], true))['url'] ?? '' ?>"/>
|
||||
</div>
|
||||
<div class="weui-msg__text-area">
|
||||
<h2 class="weui-msg__title">申请获取以下权限</h2>
|
||||
<div class="weui-msg__custom-area">
|
||||
<ul class="weui-list-tips">
|
||||
<li role="option" class="weui-list-tips__item">获得您的公开信息(昵称,头像等)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="weui-msg__opr-area">
|
||||
<p class="weui-btn-area">
|
||||
<a href="javascript:" id="login-btn" role="button" class="weui-btn weui-btn_primary">微信一键授权登录</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="weui-footer weui-footer_fixed-bottom">
|
||||
<p class="weui-footer__text">技术支持 <?= $info['company_name'] ?? '' ?></p>
|
||||
<p class="weui-footer__text">Copyright © <?= $info['origin_year'] ?>-<?= $info['current_year'] ?></p>
|
||||
<a href="//beian.miit.gov.cn/" class="page_copyright">
|
||||
<?= $info['company_recordno'] ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div role="alert" id="loadingToast" style="opacity: 0; display: none;">
|
||||
<div class="weui-mask_transparent"></div>
|
||||
<div class="weui-toast">
|
||||
<span class="weui-primary-loading weui-icon_toast">
|
||||
<span class="weui-primary-loading__dot"></span>
|
||||
</span>
|
||||
<p class="weui-toast__content">加载中</p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
document.getElementById('login-btn').addEventListener('click', function () {
|
||||
window.location = '<?= $authUrl ?>'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</html>
|
298
module/Application/view/application/login/bind.phtml
Normal file
298
module/Application/view/application/login/bind.phtml
Normal file
File diff suppressed because one or more lines are too long
4
module/Application/view/application/login/index.phtml
Normal file
4
module/Application/view/application/login/index.phtml
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
$path = $_SERVER['DOCUMENT_ROOT'].'/static/index.html';
|
||||
$html = file_get_contents($path);
|
||||
echo $html;
|
298
module/Application/view/application/login/success.phtml
Normal file
298
module/Application/view/application/login/success.phtml
Normal file
File diff suppressed because one or more lines are too long
383
module/Application/view/application/wechat/bind.phtml
Normal file
383
module/Application/view/application/wechat/bind.phtml
Normal file
@ -0,0 +1,383 @@
|
||||
<style>
|
||||
.weui-form {
|
||||
padding: 56px 0 0;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
line-height: 1.4;
|
||||
min-height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.weui-cell {
|
||||
padding: 16px;
|
||||
position: relative;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
line-height: 1.41176471;
|
||||
font-size: 17px;
|
||||
color: rgba(0,0,0,0.9);
|
||||
}
|
||||
|
||||
.weui-form__text-area {
|
||||
padding: 0 32px;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.weui-form__control-area {
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-flex: 1;
|
||||
flex: 1;
|
||||
margin: 48px 0;
|
||||
}
|
||||
|
||||
.weui-cells__group_form .weui-cells {
|
||||
margin-left: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.weui-cells__group_form .weui-cell {
|
||||
padding: 16px 16px;
|
||||
}
|
||||
|
||||
[class*=" weui-icon-"] {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
font-size: 10px;
|
||||
width: 2.4em;
|
||||
height: 2.4em;
|
||||
-webkit-mask-position: 50% 50%;
|
||||
mask-position: 50% 50%;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-size: 100%;
|
||||
mask-size: 100%;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.weui-cells__group_form .weui-cell_vcode.weui-cell_wrap .weui-input {
|
||||
font-size: 17px;
|
||||
min-height: 1.88235294em;
|
||||
}
|
||||
|
||||
.weui-cells__group_form input, .weui-cells__group_form textarea, .weui-cells__group_form label[for] {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
.weui-input {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
-webkit-appearance: none;
|
||||
background-color: transparent;
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
height: 1.41176471em;
|
||||
line-height: 1.41176471;
|
||||
}
|
||||
|
||||
.weui-cells__group_form .weui-vcode-btn {
|
||||
font-size: 16px;
|
||||
padding: 0 12px;
|
||||
height: auto;
|
||||
width: auto;
|
||||
line-height: 2;
|
||||
border-radius: 6px;
|
||||
color: #06ae56;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
button.weui-vcode-btn {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
button.weui-btn, input.weui-btn {
|
||||
border-width: 0;
|
||||
outline: 0;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
.weui-vcode-btn {
|
||||
display: inline-block;
|
||||
height: 56px;
|
||||
margin-left: 5px;
|
||||
padding: 0 0.6em 0 0.7em;
|
||||
line-height: 56px;
|
||||
vertical-align: middle;
|
||||
font-size: 17px;
|
||||
color: #576b95;
|
||||
position: relative;
|
||||
}
|
||||
.weui-btn_default {
|
||||
color: #06ae56;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
.weui-btn {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 184px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 8px 24px;
|
||||
box-sizing: border-box;
|
||||
font-weight: 700;
|
||||
font-size: 17px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
line-height: 1.88235294;
|
||||
border-radius: 8px;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.form_vcode {
|
||||
height: 85vh;
|
||||
}
|
||||
|
||||
.weui-cells__group_form .weui-cell_vcode.weui-cell_wrap .weui-label {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.page.form_input_status .weui-label, .page.form_vcode .weui-label {
|
||||
width: 3.14em;
|
||||
}
|
||||
.weui-cells__group_form .weui-cell_wrap .weui-label {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.weui-cells__group_form input, .weui-cells__group_form textarea, .weui-cells__group_form label[for] {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
.weui-cells__group_form .weui-label {
|
||||
max-width: 5em;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.weui-cells__group_form .weui-cell__control {
|
||||
margin: 8px 0 8px 16px;
|
||||
}
|
||||
|
||||
.weui-btn {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 184px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 8px 24px;
|
||||
box-sizing: border-box;
|
||||
font-weight: 700;
|
||||
font-size: 17px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
line-height: 1.88235294;
|
||||
border-radius: 8px;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.weui-toast {
|
||||
position: fixed;
|
||||
z-index: 5500;
|
||||
font-size: 10px;
|
||||
width: 13.6em;
|
||||
height: 13.6em;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%,-50%);
|
||||
transform: translate(-50%,-50%);
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
color: rgba(255,255,255,0.9);
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
background-color: #4c4c4c;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.weui-toast_text {
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 152px;
|
||||
max-width: 216px;
|
||||
padding: 12px 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.weui-toast_text .weui-toast__content {
|
||||
font-size: 14px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.weui-btn[disabled] {
|
||||
color: rgba(0,0,0,0.2);
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div class="page form_vcode js_show" tabindex="-1">
|
||||
<input type="hidden" value="<?= $openid ?>" id="input-openid">
|
||||
<div class="weui-form">
|
||||
<div class="weui-form__text-area">
|
||||
<h2 class="weui-form__title">手机号绑定</h2>
|
||||
<!-- <div class="weui-form__desc" id="">--><?//= $openid ?><!--</div>-->
|
||||
</div>
|
||||
<div class="weui-form__control-area">
|
||||
<div class="weui-cells__group weui-cells__group_form">
|
||||
<div class="weui-cells">
|
||||
<div class="weui-cell weui-cell_active">
|
||||
<div class="weui-cell__hd"><label class="weui-label">手机号</label></div>
|
||||
<span class="weui-cell__control">+86</span>
|
||||
<div class="weui-cell__bd">
|
||||
<input id="input-mobile" class="weui-input weui-cell__control" type="number" placeholder="请输入手机号" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="weui-cell weui-cell_active">
|
||||
<div class="weui-cell__hd"><label for="js_input1" class="weui-label">验证码</label></div>
|
||||
<div class="weui-cell__bd">
|
||||
<input id="input-captcha" class="weui-input weui-cell__control" type="number" pattern="[0-9]*" placeholder="请输入验证码" value="">
|
||||
</div>
|
||||
<div class="weui-cell__ft">
|
||||
<button id="captchaBtn" role="button" onclick="getCaptcha()" class="js_target weui-cell__control weui-btn weui-btn_default weui-vcode-btn weui-btn_loading">获取验证码</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="weui-form__opr-area">
|
||||
<!-- <button class="weui-btn weui-btn_primary" type="button" style="width: 184px" id="submitBtn" onclick="submit()"><i class="weui_icon_msg weui_icon_success"></i>确定</button>-->
|
||||
<button disabled class="weui-btn weui-btn_primary" type="button" style="width: 184px" id="submitBtn" onclick="submit()"><i class="weui_icon_msg weui_icon_success"></i>确定</button>
|
||||
</div>
|
||||
</div>
|
||||
<div role="alert" id="textToast" style="opacity:0;display: none;">
|
||||
<div class="weui-mask_transparent"></div>
|
||||
<div class="weui-toast weui-toast_text">
|
||||
<p class="weui-toast__content">文字提示</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
//ajax post请求获取接口数据
|
||||
var ajaxPost = function (reqUrl, params, callback, async) {
|
||||
var xhr = null;
|
||||
if(window.XMLHttpRequest) {
|
||||
xhr = new XMLHttpRequest();
|
||||
} else if(window.ActiveXObject) {
|
||||
xhr = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
if(!xhr) { return false;}
|
||||
if (async && callback) {
|
||||
xhr.addEventListener('readystatechange', function () {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
callback(JSON.parse(xhr.responseText));
|
||||
}
|
||||
});
|
||||
}
|
||||
xhr.open('post', reqUrl, async);
|
||||
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var strArr = [];
|
||||
for(var k in params) {
|
||||
strArr.push(k + "=" + params[k]);
|
||||
}
|
||||
var data = strArr.join("&");
|
||||
xhr.send(data);
|
||||
if (!async) {
|
||||
return xhr.responseText;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取手机号验证码
|
||||
*/
|
||||
function getCaptcha() {
|
||||
let mobile = document.getElementById('input-mobile').value;
|
||||
|
||||
if (!mobile || !/^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/.test(mobile)) {
|
||||
topTips('请输入正确的手机号')
|
||||
return
|
||||
}
|
||||
|
||||
ajaxPost('<?= $host ?>' + '/wechat/bind-captcha', {
|
||||
'mobile': document.getElementById('input-mobile').value,
|
||||
'openid': document.getElementById('input-openid').value,
|
||||
}, (e) => {
|
||||
if (e.code === 200) {
|
||||
topTips('验证码发送成功', 'success')
|
||||
setTimer();
|
||||
// 让确定按键可以点
|
||||
document.getElementById('submitBtn').attributes.removeNamedItem('disabled')
|
||||
// 发验证码了就不让改手机号
|
||||
document.getElementById('input-mobile').attributes.setNamedItem(document.createAttribute('disabled'))
|
||||
} else {
|
||||
topTips(e.msg)
|
||||
}
|
||||
}, true)
|
||||
}
|
||||
|
||||
// 计时器句柄
|
||||
let timerHandler = 0;
|
||||
|
||||
// 发送验证码速率
|
||||
let totalTimer = 60;
|
||||
|
||||
function setTimer() {
|
||||
const el = document.getElementById('captchaBtn');
|
||||
let attr = document.createAttribute('disabled')
|
||||
el.attributes.setNamedItem(attr)
|
||||
|
||||
if (timerHandler) {
|
||||
clearInterval(timerHandler)
|
||||
totalTimer = 60
|
||||
}
|
||||
|
||||
el.textContent = `获取验证码(${totalTimer}S)`;
|
||||
timerHandler = setInterval(() => {
|
||||
totalTimer--;
|
||||
el.textContent = `获取验证码(${totalTimer}S)`;
|
||||
if (totalTimer === 0) {
|
||||
clearInterval(timerHandler)
|
||||
el.textContent = `获取验证码`;
|
||||
el.attributes.removeNamedItem('disabled')
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
function submit() {
|
||||
document.getElementById('submitBtn').attributes.setNamedItem(document.createAttribute('disabled'))
|
||||
ajaxPost('<?= $host ?>' + '/wechat/bind-submit', {
|
||||
'mobile': document.getElementById('input-mobile').value,
|
||||
'captcha': document.getElementById('input-captcha').value,
|
||||
'openid': document.getElementById('input-openid').value,
|
||||
}, (e) => {
|
||||
if (e.code === 200) {
|
||||
alert('绑定成功');
|
||||
WeixinJSBridge.call('closeWindow');
|
||||
} else {
|
||||
topTips(e.msg)
|
||||
}
|
||||
document.getElementById('submitBtn').attributes.removeNamedItem('disabled')
|
||||
}, true)
|
||||
}
|
||||
|
||||
</script>
|
71
module/Application/view/dashboard/analysis.phtml
Normal file
71
module/Application/view/dashboard/analysis.phtml
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div id="main" style="width: 100%;height:400px;"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const { createApp, reactive, onMounted } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
dataProvider: {},
|
||||
searchDataProvider: {
|
||||
params: '1'
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
var chartDom = document.getElementById('main');
|
||||
var myChart = echarts.init(chartDom);
|
||||
var option;
|
||||
option = {
|
||||
title: {
|
||||
text: '请求数量'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['00-01', '01-02', '02-03', '03-04', '04-05', '05-06', '06-07', '07-08', '08-09', '09-10', '10-11', '11-12', '12-13','13-14', '14-15', '15-16', '16-17', '17-18', '18-19', '19-20', '20-21', '21-22', '22-23']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
<?php foreach ($data as $item): ?>
|
||||
{
|
||||
name: '<?= $item['name'] ?>',
|
||||
data: [<?= implode(',', $item['data']) ?>],
|
||||
type: 'line'
|
||||
},
|
||||
<?php endforeach; ?>
|
||||
]
|
||||
};
|
||||
myChart.setOption(option);
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
fetch('/api/dashboard/form-log', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider = res.data
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
return {
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
105
module/Application/view/dashboard/analysisResponseTime.phtml
Normal file
105
module/Application/view/dashboard/analysisResponseTime.phtml
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div id="main" style="width: 100%;height:400px;"></div>
|
||||
<div class="panel panel-default">
|
||||
<!-- Table -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px">id</th>
|
||||
<th>请求参数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in state.dataProvider">
|
||||
<td>{{ index }}</td>
|
||||
<td>{{ item }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const { createApp, reactive, onMounted } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
dataProvider: {},
|
||||
searchDataProvider: {
|
||||
params: '1'
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
var chartDom = document.getElementById('main');
|
||||
var myChart = echarts.init(chartDom);
|
||||
var option;
|
||||
option = {
|
||||
color: ['#91cc75', '#ee6666'],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
// Use axis to trigger tooltip
|
||||
type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow'
|
||||
}
|
||||
},
|
||||
legend: {},
|
||||
xAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: ['<?= implode("','", $title) ?>']
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '正常请求',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
data: [<?= implode(',', \Application\Service\Extension\Helper\ArrayHelper::getColumn($data, 'normal')) ?>]
|
||||
},
|
||||
{
|
||||
name: '慢请求',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
data: [<?= implode(',', \Application\Service\Extension\Helper\ArrayHelper::getColumn($data, 'slow')) ?>]
|
||||
},
|
||||
]
|
||||
};
|
||||
myChart.setOption(option);
|
||||
myChart.on('click', function(event) {
|
||||
console.log(event.name)
|
||||
fetchData(event.name)
|
||||
});
|
||||
})
|
||||
|
||||
function fetchData(url) {
|
||||
fetch('/api/dashboard/analysisResponseTime?url=' + url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider = res.data
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
return {
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
95
module/Application/view/dashboard/exception.phtml
Normal file
95
module/Application/view/dashboard/exception.phtml
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div class="panel panel-default">
|
||||
<div class="navbar-form" role="search">
|
||||
<div class="form-group">
|
||||
<input v-model="state.searchDataProvider.date" type="text" class="form-control" placeholder="Search">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default" @click="fetchData()">Submit</button>
|
||||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>path</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in state.dataProvider.files">
|
||||
<td>
|
||||
<span class="detail" @click="detail(item, index)">{{ item }}</span>
|
||||
<div ref="detailWrapper" style="white-space: pre">
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<style scoped>
|
||||
.detail{
|
||||
cursor: pointer;
|
||||
}
|
||||
.detail:hover{
|
||||
color: #0000FF;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
const { createApp, reactive, ref } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const detailWrapper = ref(null)
|
||||
const state = reactive({
|
||||
dataProvider: {
|
||||
files: <?= json_encode($files) ?>,
|
||||
},
|
||||
searchDataProvider: {
|
||||
date: '<?= date('Y-m-d', time()) ?>'
|
||||
}
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
fetch('/api/dashboard/exception', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider.files = res.data
|
||||
this.detailWrapper.forEach(element => {
|
||||
element.innerHTML = '';
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function detail(path, index) {
|
||||
console.log('点了', index)
|
||||
fetch('/api/dashboard/exception/detail', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify({
|
||||
path: path
|
||||
})
|
||||
}).then(res => res.json()).then(res => {
|
||||
// state.dataProvider = res.data
|
||||
this.detailWrapper[index].innerHTML = res.data[0]
|
||||
})
|
||||
}
|
||||
return {
|
||||
detailWrapper,
|
||||
detail,
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
62
module/Application/view/dashboard/fileTimestamp.phtml
Normal file
62
module/Application/view/dashboard/fileTimestamp.phtml
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div class="navbar-form" role="search">
|
||||
<div class="form-group">
|
||||
<input v-model="state.searchDataProvider.path" type="text" class="form-control" placeholder="Search">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default" @click="fetchData">Submit</button>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<!-- Table -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>path</th>
|
||||
<th>updated_time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in state.dataProvider">
|
||||
<td>{{ item.path }}</td>
|
||||
<td>{{ item.timestamp }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const { createApp, reactive } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
dataProvider: {},
|
||||
searchDataProvider: {
|
||||
path: '/module/Application'
|
||||
}
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
fetch('/api/dashboard/file-timestamp', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider = res.data
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
return {
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
61
module/Application/view/dashboard/formLog.phtml
Normal file
61
module/Application/view/dashboard/formLog.phtml
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div class="navbar-form" role="search">
|
||||
<div class="form-group">
|
||||
主键ID:
|
||||
<input v-model="state.searchDataProvider.params" type="text" class="form-control" placeholder="Search">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default" @click="fetchData">Go!</button>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<!-- Table -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in state.dataProvider">
|
||||
<td>{{ item }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const { createApp, reactive } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
dataProvider: {},
|
||||
searchDataProvider: {
|
||||
params: '1'
|
||||
}
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
fetch('/api/dashboard/form-log', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider = res.data
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
return {
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
59
module/Application/view/dashboard/index.phtml
Normal file
59
module/Application/view/dashboard/index.phtml
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/exception"><h3>错误日志: <?= $filesCount ?? 0 ?></h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/form-log"><h3>表单日志</h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/file-timestamp"><h3>文件更新时间</h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/redis"><h3>redis</h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<h3>单元测试</h3>
|
||||
<!-- <a href="/dashboard/unit-test"><h3>单元测试</h3></a>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/analysis"><h3>访问统计</h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-4">
|
||||
<div class="thumbnail">
|
||||
<div class="caption">
|
||||
<a href="/dashboard/analysis-response-time"><h3>性能统计</h3></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
let token = sessionStorage.getItem('token');
|
||||
document.cookie = `token=${token}`;
|
||||
</script>
|
60
module/Application/view/dashboard/redis.phtml
Normal file
60
module/Application/view/dashboard/redis.phtml
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div class="navbar-form" role="search">
|
||||
<div class="form-group">
|
||||
<input v-model="state.searchDataProvider.params" type="text" class="form-control" placeholder="Search">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default" @click="fetchData">Submit</button>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<!-- Table -->
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in state.dataProvider">
|
||||
<td>{{ item }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const { createApp, reactive } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const state = reactive({
|
||||
dataProvider: {},
|
||||
searchDataProvider: {
|
||||
params: 'get key'
|
||||
}
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
fetch('/api/dashboard/redis', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.json()).then(res => {
|
||||
state.dataProvider = res.data
|
||||
console.log(res)
|
||||
})
|
||||
}
|
||||
return {
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
80
module/Application/view/dashboard/unitTest.phtml
Normal file
80
module/Application/view/dashboard/unitTest.phtml
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
$this->layout('layout/dashboardLayout');
|
||||
?>
|
||||
|
||||
<div id="app">
|
||||
<div class="panel panel-default">
|
||||
<div class="navbar-form" role="search">
|
||||
<button :disabled="state.isTesting" type="submit" class="btn btn-default" @click="fetchData()">测试</button>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div ref="response"style="white-space: pre">
|
||||
{{ state.dataProvider }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style scoped>
|
||||
.detail{
|
||||
cursor: pointer;
|
||||
}
|
||||
.detail:hover{
|
||||
color: #0000FF;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
const { createApp, reactive, ref } = Vue
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const response = ref(null)
|
||||
const state = reactive({
|
||||
isTesting: false,
|
||||
dataProvider: '',
|
||||
searchDataProvider: {
|
||||
date: '<?= date('Y-m-d', time()) ?>'
|
||||
}
|
||||
})
|
||||
|
||||
function fetchData() {
|
||||
state.isTesting = true;
|
||||
state.dataProvider = ''
|
||||
fetch('/api/dashboard/unitTest', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
},
|
||||
body: Qs.stringify(state.searchDataProvider)
|
||||
}).then(res => res.text()).then(res => {
|
||||
state.dataProvider = res
|
||||
}).finally(() => {
|
||||
state.isTesting = false
|
||||
})
|
||||
}
|
||||
|
||||
// function detail(path, index) {
|
||||
// console.log('点了', index)
|
||||
// fetch('/api/dashboard/exception/detail', {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
// },
|
||||
// body: Qs.stringify({
|
||||
// path: path
|
||||
// })
|
||||
// }).then(res => res.json()).then(res => {
|
||||
// // state.dataProvider = res.data
|
||||
// this.detailWrapper[index].innerHTML = res.data[0]
|
||||
// })
|
||||
// }
|
||||
return {
|
||||
response,
|
||||
fetchData,
|
||||
state
|
||||
}
|
||||
}
|
||||
}).mount('#app')
|
||||
</script>
|
105
module/Application/view/error/404.phtml
Normal file
105
module/Application/view/error/404.phtml
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
use Laminas\Mvc\Application;
|
||||
?>
|
||||
<h1>A 404 error occurred</h1>
|
||||
<h2><?= $this->message ?></h2>
|
||||
|
||||
<?php
|
||||
if (! empty($this->reason)) :
|
||||
$reasonMessage = '';
|
||||
switch ($this->reason) {
|
||||
case Application::ERROR_CONTROLLER_CANNOT_DISPATCH:
|
||||
$reasonMessage = 'The requested controller was unable to dispatch the request.';
|
||||
break;
|
||||
case Application::ERROR_MIDDLEWARE_CANNOT_DISPATCH:
|
||||
$reasonMessage = 'The requested middleware was unable to dispatch the request.';
|
||||
break;
|
||||
case Application::ERROR_CONTROLLER_NOT_FOUND:
|
||||
$reasonMessage = 'The requested controller could not be mapped to an existing controller class.';
|
||||
break;
|
||||
case Application::ERROR_CONTROLLER_INVALID:
|
||||
$reasonMessage = 'The requested controller was not dispatchable.';
|
||||
break;
|
||||
case Application::ERROR_ROUTER_NO_MATCH:
|
||||
$reasonMessage = 'The requested URL could not be matched by routing.';
|
||||
break;
|
||||
default:
|
||||
$reasonMessage = 'We cannot determine at this time why a 404 was generated.';
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
||||
<p><?= $reasonMessage ?></p>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (! empty($this->controller)) : ?>
|
||||
<dl>
|
||||
<dt>Controller:</dt>
|
||||
<dd><?= $this->escapeHtml($this->controller) ?>
|
||||
<?php
|
||||
if (! empty($this->controller_class)
|
||||
&& $this->controller_class != $this->controller
|
||||
) {
|
||||
echo sprintf('(resolves to %s)', $this->escapeHtml($this->controller_class));
|
||||
}
|
||||
?>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (! empty($this->display_exceptions)) : ?>
|
||||
<?php if (isset($this->exception)
|
||||
&& ($this->exception instanceof \Throwable || $this->exception instanceof \Exception)) : ?>
|
||||
<hr/>
|
||||
<h2>Additional information:</h2>
|
||||
<h3><?= get_class($this->exception) ?></h3>
|
||||
<dl>
|
||||
<dt>File:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->exception->getFile() ?>:<?= $this->exception->getLine() ?></pre>
|
||||
</dd>
|
||||
<dt>Message:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->escapeHtml($this->exception->getMessage()) ?></pre>
|
||||
</dd>
|
||||
<dt>Stack trace:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->exception->getTraceAsString() ?></pre>
|
||||
</dd>
|
||||
</dl>
|
||||
<?php $e = $this->exception->getPrevious() ?>
|
||||
<?php if ($e) : ?>
|
||||
<hr/>
|
||||
<h2>Previous exceptions:</h2>
|
||||
<ul class="unstyled">
|
||||
<?php while ($e) : ?>
|
||||
<li>
|
||||
<h3><?= get_class($e) ?></h3>
|
||||
<dl>
|
||||
<dt>File:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $e->getFile() ?>:<?= $e->getLine() ?></pre>
|
||||
</dd>
|
||||
<dt>Message:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->escapeHtml($e->getMessage()) ?></pre>
|
||||
</dd>
|
||||
<dt>Stack trace:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $e->getTraceAsString() ?></pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<?php $e = $e->getPrevious() ?>
|
||||
<?php endwhile ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
||||
<?php else : ?>
|
||||
<h3>No Exception available</h3>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<?php endif ?>
|
57
module/Application/view/error/index.phtml
Normal file
57
module/Application/view/error/index.phtml
Normal file
@ -0,0 +1,57 @@
|
||||
<h1>An error occurred</h1>
|
||||
<h2><?= $this->message ?></h2>
|
||||
|
||||
<?php if (! empty($this->display_exceptions)) : ?>
|
||||
<?php if (isset($this->exception)
|
||||
&& ($this->exception instanceof \Throwable || $this->exception instanceof \Exception)) : ?>
|
||||
<hr/>
|
||||
<h2>Additional information:</h2>
|
||||
<h3><?= get_class($this->exception) ?></h3>
|
||||
<dl>
|
||||
<dt>File:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->exception->getFile() ?>:<?= $this->exception->getLine() ?></pre>
|
||||
</dd>
|
||||
<dt>Message:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->escapeHtml($this->exception->getMessage()) ?></pre>
|
||||
</dd>
|
||||
<dt>Stack trace:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->exception->getTraceAsString() ?></pre>
|
||||
</dd>
|
||||
</dl>
|
||||
<?php $e = $this->exception->getPrevious() ?>
|
||||
<?php if ($e) : ?>
|
||||
<hr/>
|
||||
<h2>Previous exceptions:</h2>
|
||||
<ul class="unstyled">
|
||||
<?php while ($e) : ?>
|
||||
<li>
|
||||
<h3><?= get_class($e); ?></h3>
|
||||
<dl>
|
||||
<dt>File:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $e->getFile() ?>:<?= $e->getLine() ?></pre>
|
||||
</dd>
|
||||
<dt>Message:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $this->escapeHtml($e->getMessage()) ?></pre>
|
||||
</dd>
|
||||
<dt>Stack trace:</dt>
|
||||
<dd>
|
||||
<pre class="prettyprint linenums"><?= $e->getTraceAsString() ?></pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<?php $e = $e->getPrevious() ?>
|
||||
<?php endwhile ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
||||
<?php else : ?>
|
||||
<h3>No Exception available</h3>
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<?php endif ?>
|
45
module/Application/view/layout/dashboardLayout.phtml
Normal file
45
module/Application/view/layout/dashboardLayout.phtml
Normal file
@ -0,0 +1,45 @@
|
||||
<?= $this->doctype() ?>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<?php
|
||||
echo $this->headTitle('Laminas API Tools');
|
||||
|
||||
echo $this->headMeta()->appendName('viewport', 'width=device-width, initial-scale=1.0');
|
||||
|
||||
echo $this->headLink(['rel' => 'icon', 'type' => 'image/png', 'href' => $this->basePath('/img/favicon.png')])
|
||||
->prependStylesheet($this->basePath('/api-tools/css/main.min.css'))
|
||||
->prependStylesheet($this->basePath('/api-tools/css/bootstrap.min.css'));
|
||||
|
||||
echo $this->headScript()
|
||||
->appendFile('https://cdn.bootcdn.net/ajax/libs/vue/3.2.33/vue.global.js')
|
||||
->appendFile('https://cdn.bootcdn.net/ajax/libs/qs/6.13.0/qs.js')
|
||||
->appendFile('https://cdn.bootcdn.net/ajax/libs/echarts/5.5.0/echarts.common.min.js');
|
||||
?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="/dashboard">回首页</a></li>
|
||||
</ol>
|
||||
<?= $this->content ?>
|
||||
</div>
|
||||
<footer>
|
||||
<hr>
|
||||
<div class="container center-block"><div class="row">
|
||||
<div class="col-sm-4">
|
||||
© <?= date('Y') ?> <a href="https://getlaminas.org/">AAAAAAAA</a> a Series of LF Projects, LLC.
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4"><p class="center-block">
|
||||
Laminas API Tools version <strong><?= \ApiTools\VERSION ?></strong>
|
||||
</p></div>
|
||||
|
||||
<div class="col-sm-4"><p class="pull-right">
|
||||
For more information <a href="https://api-tools.getlaminas.org">api-tools.getlaminas.org</a>
|
||||
</p></div>
|
||||
</div></div>
|
||||
</footer>
|
||||
<?= $this->inlineScript() ?>
|
||||
</body>
|
||||
</html>
|
41
module/Application/view/layout/layout.phtml
Normal file
41
module/Application/view/layout/layout.phtml
Normal file
@ -0,0 +1,41 @@
|
||||
<?= $this->doctype() ?>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<?php
|
||||
echo $this->headTitle('Laminas API Tools');
|
||||
|
||||
echo $this->headMeta()->appendName('viewport', 'width=device-width, initial-scale=1.0');
|
||||
|
||||
echo $this->headLink(['rel' => 'icon', 'type' => 'image/png', 'href' => $this->basePath('/img/favicon.png')])
|
||||
->prependStylesheet($this->basePath('/api-tools/css/main.min.css'))
|
||||
->prependStylesheet($this->basePath('/api-tools/css/bootstrap.min.css'));
|
||||
|
||||
echo $this->headScript()
|
||||
->prependFile($this->basePath('/api-tools/js/bootstrap.min.js'))
|
||||
->prependFile($this->basePath('/api-tools/js/jquery.min.js'));
|
||||
?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<?= $this->content ?>
|
||||
</div>
|
||||
<footer>
|
||||
<hr>
|
||||
<div class="container center-block"><div class="row">
|
||||
<div class="col-sm-4">
|
||||
© <?= date('Y') ?> <a href="https://getlaminas.org/">Laminas Project</a> a Series of LF Projects, LLC.
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4"><p class="center-block">
|
||||
Laminas API Tools version <strong><?= \ApiTools\VERSION ?></strong>
|
||||
</p></div>
|
||||
|
||||
<div class="col-sm-4"><p class="pull-right">
|
||||
For more information <a href="https://api-tools.getlaminas.org">api-tools.getlaminas.org</a>
|
||||
</p></div>
|
||||
</div></div>
|
||||
</footer>
|
||||
<?= $this->inlineScript() ?>
|
||||
</body>
|
||||
</html>
|
52
module/Application/view/layout/wechat.phtml
Normal file
52
module/Application/view/layout/wechat.phtml
Normal file
@ -0,0 +1,52 @@
|
||||
<?= $this->doctype() ?>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<?php
|
||||
echo $this->headTitle($title);
|
||||
|
||||
echo $this->headMeta()->appendName('viewport', 'width=device-width, initial-scale=1.0');
|
||||
?>
|
||||
<link rel="stylesheet" type="text/css" href="/css/weui.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container" style="height: 100vh">
|
||||
<?= $this->content ?>
|
||||
</div>
|
||||
<!-- <div class="weui-footer weui-footer_fixed-bottom">-->
|
||||
<!-- <p class="weui-footer__text">技术支持 北京安捷讯科技有限公司</p>-->
|
||||
<!-- <p class="weui-footer__text">Copyright © 2008-2022</p>-->
|
||||
<!-- <a href="//beian.miit.gov.cn/" class="page_copyright">-->
|
||||
<!-- 京ICP备20021033号-4-->
|
||||
<!-- </a>-->
|
||||
<!-- </div>-->
|
||||
<?= $this->inlineScript() ?>
|
||||
</body>
|
||||
<script>
|
||||
let isTopTips = false;
|
||||
|
||||
function topTips(message, level = 'error') {
|
||||
if (isTopTips === true) {
|
||||
return
|
||||
}
|
||||
|
||||
// #06ae56
|
||||
// #fa5151
|
||||
let bgColor = level === 'error' ? '#fa5151' : '#06ae56'
|
||||
const tipsHtml = '<div role="alert" class="weui-toptips weui-toptips_warn" id="topTips" style="display: none; opacity: 0;transition: opacity 0.5s linear 0s;background-color: ' + bgColor + '">' + message + '</div>';
|
||||
document.querySelector('.container').insertAdjacentHTML('afterend', tipsHtml)
|
||||
let ele = document.getElementById('topTips');
|
||||
|
||||
isTopTips = true;
|
||||
ele.style.display = 'block';
|
||||
ele.style.opacity = '1';
|
||||
ele.textContent = message;
|
||||
setTimeout(() => {
|
||||
console.log('hide')
|
||||
ele.style.opacity = '0';
|
||||
ele.remove()
|
||||
isTopTips = false;
|
||||
}, 2000)
|
||||
}
|
||||
</script>
|
||||
</html>
|
Reference in New Issue
Block a user