Initial commit

This commit is contained in:
net909
2023-09-28 16:21:06 +08:00
parent 498772eb04
commit ba7be004c0
640 changed files with 87745 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>温馨提示</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<meta name="renderer" content="webkit"/>
<style type="text/css">
*{box-sizing:border-box;margin:0;padding:0;font-family:Lantinghei SC,Open Sans,Arial,Hiragino Sans GB,Microsoft YaHei,"微软雅黑",STHeiti,WenQuanYi Micro Hei,SimSun,sans-serif;-webkit-font-smoothing:antialiased}
body{padding:70px 0;background:#edf1f4;font-weight:400;font-size:1pc;-webkit-text-size-adjust:none;color:#333}
a{outline:0;color:#3498db;text-decoration:none;cursor:pointer}
.system-message{margin:20px 5%;padding:40px 20px;background:#fff;box-shadow:1px 1px 1px hsla(0,0%,39%,.1);text-align:center}
.system-message h1{margin:0;margin-bottom:9pt;color:#444;font-weight:400;font-size:40px}
.system-message .jump,.system-message .image{margin:20px 0;padding:0;padding:10px 0;font-weight:400}
.system-message .jump{font-size:14px}
.system-message .jump a{color:#333}
.system-message p{font-size:9pt;line-height:20px}
.system-message .btn{display:inline-block;margin-right:10px;width:138px;height:2pc;border:1px solid #44a0e8;border-radius:30px;color:#44a0e8;text-align:center;font-size:1pc;line-height:2pc;margin-bottom:5px;}
.success .btn{border-color:#69bf4e;color:#69bf4e}
.error .btn{border-color:#ff8992;color:#ff8992}
.info .btn{border-color:#3498db;color:#3498db}
.copyright p{width:100%;color:#919191;text-align:center;font-size:10px}
.system-message .btn-grey{border-color:#bbb;color:#bbb}
.clearfix:after{clear:both;display:block;visibility:hidden;height:0;content:"."}
@media (max-width:768px){body {padding:20px 0;}}
@media (max-width:480px){.system-message h1{font-size:30px;}}
</style>
</head>
<body>
<div class="system-message {$code}">
<div class="image">
<img src="/static/images/{$code}.svg" alt="" width="150" />
</div>
<h1>{$msg}</h1>
{if $url}
<p class="jump">
页面将在 <span id="wait">{$wait}</span> 秒后自动跳转
</p>
{/if}
<p class="clearfix">
<a href="javascript:history.go(-1);" class="btn btn-grey">返回上一页</a>
{if $url}
<a href="{$url}" class="btn btn-primary">立即跳转</a>
{/if}
</p>
</div>
<script type="text/javascript">
(function () {
var wait = document.getElementById('wait');
var interval = setInterval(function () {
var time = --wait.innerHTML;
if (time <= 0) {
location.href = "{$url}";
clearInterval(interval);
}
}, 1000);
})();
</script>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
{extend name="common/layout" /}
{block name="title"}用户登录 - {:config_get('title')}{/block}
{block name="main"}
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="col-10 col-sm-8 col-md-6 col-xl-4 center-block">
<div class="nk-content-body" style="padding-top:50%">
<div class="card card-preview">
<div class="card-inner mt-3">
<div class="row g-2 text-center">
<div class="col-12">
<p>请选择登录方式</p>
<p>{if config_get('oauth_openqq')=='1'}<a href="javascript:connect('qq')"><img class="loginbtn" src="/static/images/qq.svg"></a>{/if}
{if config_get('oauth_openwx')=='1'}<a href="javascript:connect('wx')"><img class="loginbtn" src="/static/images/wechat.svg"></a>{/if}</p>
<p class="text-muted">新用户快捷登录后会自动注册账号</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
function connect(type){
httpPost("/oauth/login", {type: type}, function(data){
window.location.href = data;
})
}
</script>
{/block}
+42
View File
@@ -0,0 +1,42 @@
{extend name="common/layout" /}
{block name="title"}QQ统一扫码页面 - {:config_get('title')}{/block}
{block name="main"}
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="col-10 col-sm-8 col-md-6 col-xl-4 center-block">
<div class="nk-content-body">
<div class="card card-preview">
<div class="card-inner">
<div class="row g-2 text-center">
<div class="col-12">
<div class="list-group">
<div class="list-group-item list-group-item-info" style="font-weight: bold;" id="login">
<span id="loginmsg">使用QQ手机版扫描二维码</span><span id="loginload" style="padding-left: 10px;color: #790909;">.</span>
</div>
<div class="list-group-item" id="qrimg">
</div>
<div class="list-group-item" id="mobile" style="display:none;"><button type="button" id="mlogin" onclick="mloginurlnew()" class="btn btn-warning btn-block">跳转QQ快捷登录</button><button type="button" onclick="qrlogin()" class="btn btn-success btn-block">我已完成登录</button></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
const base64_decode = function (str) {
return decodeURIComponent(atob(str).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
const logintype = base64_decode('{$logintype}');
const loginname = base64_decode('{$loginname}');
const redirect = base64_decode('{$redirect}');
</script>
<script src="/static/js/qqlogin.js?v=1001"></script>
{/block}
+9
View File
@@ -0,0 +1,9 @@
<div class="nk-footer nk-footer-fluid bg-lighter">
<div class="container-xl">
<div class="nk-footer-wrap">
<div class="nk-footer-copyright"> &copy; {:date('Y')} {:config_get('title')} {:config_get('foot_code')}
</div>
</div>
</div>
</div>
<!-- footer @e -->
+112
View File
@@ -0,0 +1,112 @@
<!-- main header @s -->
<div class="nk-header nk-header-fluid nk-header-fixed is-light">
<div class="container-xl">
<div class="nk-header-wrap link-between">
<div class="nk-menu-trigger mr-sm-2 d-lg-none">
<a href="#" class="nk-nav-toggle nk-quick-nav-icon" data-target="headerNav"><em
class="icon ni ni-menu"></em></a>
</div>
<div class="nk-header-brand">
<a href="/" class="logo-link text-base"><img src="/static/images/logo.png" class="hide-mb-sm">{:config_get('title')}</a>
</div>
<!-- .nk-header-brand -->
<div class="nk-header-tools nk-header-menu" data-content="headerNav">
<div class="nk-header-mobile">
<div class="nk-header-brand">
<a href="/" class="logo-link text-base">
<span class="nio-version" style="font-size: 21px;position: inherit;">{:config_get('title')}</span>
</a>
</div>
<div class="nk-menu-trigger mr-n2">
<a href="#" class="nk-nav-toggle nk-quick-nav-icon" data-target="headerNav"><em class="icon ni ni-arrow-left"></em></a>
</div>
</div>
<!-- Menu -->
<ul class="nk-menu nk-menu-main">
<li class="nk-menu-item {if request()->action()=='index'}active{/if}">
<a href="/" class="nk-menu-link nk-ibx-action-item">
<em class="icon ni ni-home"></em>
<span class="nk-menu-text">首页</span>
</a>
</li>
<li class="nk-menu-item {if request()->action()=='stars'}active{/if}">
<a href="/stars" class="nk-menu-link nk-ibx-action-item">
<em class="icon ni ni-heart"></em>
<span class="nk-menu-text">我的收藏</span>
</a>
</li>
<li class="nk-menu-item {if request()->action()=='history'}active{/if}">
<a href="/history" class="nk-menu-link nk-ibx-action-item">
<em class="icon ni ni-history"></em>
<span class="nk-menu-text">最近使用</span>
</a>
</li>
<li class="nk-menu-item {if request()->action()=='comment'}active{/if}">
<a href="/comment" class="nk-menu-link nk-ibx-action-item">
<em class="icon ni ni-comments"></em>
<span class="nk-menu-text">留言反馈</span>
</a>
</li>
</ul>
</div>
<!-- .nk-header-menu -->
<div class="no-gutters">
<ul class="nk-quick-nav">
<li class="dropdown">
<a href="javascript:;" class="progress-rating dark-switch {if cookie('darkmode')=='1'}active{/if}">
<span class="nk-menu-icon">
<em class="icon ni ni-moon"></em>
<em class="icon ni ni-sun d-none"></em>
</span>
</a>
</li>
<li class="dropdown user-dropdown order-sm-first {if request()->action()=='login'}active{/if}">
{if $islogin}
<a href="#" class="dropdown-toggle nk-menu-link nk-ibx-action-item" data-toggle="dropdown">
<em class="icon ni ni-user-circle mr-1"></em>
<div class="dropdown-indicator">
{$user.username}
</div>
</a>
<div class="dropdown-menu dropdown-menu-md dropdown-menu-right dropdown-menu-s1 is-light">
<div class="dropdown-inner user-card-wrap bg-lighter d-none d-md-block">
<div class="user-card">
<div class="user-avatar">
<img src="{$user.avatar_url}">
</div>
<div class="user-info">
<span class="lead-text">{$user.username}</span>
<span class="sub-text">VIP{$user.level}</span>
</div>
<div class="user-action">
<a class="btn btn-icon mr-n2" href="#"><em class="icon ni ni-setting"></em></a>
</div>
</div>
</div>
<div class="dropdown-inner">
<ul class="link-list">
<li><a href="/logout"><em class="icon ni ni-signout"></em><span>退出登录</span></a>
</li>
</ul>
</div>
</div>
{else}
<a href="/login" class="dropdown-toggle nk-menu-link nk-ibx-action-item">
<em class="icon ni ni-user-circle mr-1"></em>
<div class="">
未登录
</div>
</a>
{/if}
</li>
<!-- .dropdown -->
</ul>
<!-- .nk-quick-nav -->
</div>
<!-- .nk-header-tools -->
</div>
<!-- .nk-header-wrap -->
</div>
<!-- .container-fliud -->
</div>
<!-- main header @e -->
+31
View File
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="zh" class="js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{block name="title"}标题{/block}</title>
<meta name="keywords" content="{:config_get('keywords')}">
<meta name="description" content="{:config_get('description')}">
<link rel="stylesheet" href="/static/css/dashlite.css">
<link rel="stylesheet" href="/static/css/style.css?v=1002">
{block name="head"}{/block}
</head>
<body class="nk-body npc-invest bg-lighter {if cookie('darkmode')=='1'}dark-mode{/if}">
<!-- wrap @s -->
<div class="nk-wrap ">
{include file="common/header" /}
<!-- content @s -->
{block name="main"}主内容{/block}
<!-- content @d -->
{include file="common/footer" /}
</div>
<!-- wrap @e -->
<script src="{$cdn_cdnjs}jquery/3.6.0/jquery.min.js"></script>
<script src="{$cdn_cdnjs}bootstrap/4.6.1/js/bootstrap.bundle.min.js"></script>
<script src="{$cdn_cdnjs}layer/3.5.1/layer.js"></script>
<script src="/static/js/nioapp.min.js"></script>
<script src="/static/js/script.js?v=1001"></script>
<script src="/static/js/common.js?v=1002"></script>
{block name="script"}{/block}
</body>
</html>
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="zh" class="js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>{block name="title"}标题{/block}</title>
<meta name="keywords" content="{:config_get('keywords')}">
<meta name="description" content="{:config_get('description')}">
<link rel="stylesheet" href="/static/css/dashlite.css">
<link rel="stylesheet" href="/static/css/style.css?v=1002">
{block name="head"}{/block}
</head>
<body class="nk-body npc-invest bg-lighter {if cookie('darkmode')=='1'}dark-mode{/if}">
<!-- wrap @s -->
<div class="nk-wrap ">
{include file="common/header" /}
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
{:config_get('head_banner')}
{block name="main"}主内容{/block}
<div class="mt-5 text-center">
<a href="javascript:star_plugin()" class="btn btn-sm btn-outline-danger mr-3">
<em class="icon ni ni-heart"></em>
<span class="nk-menu-text" id="star-btn-text">收藏工具</span>
</a>
<a href="./" class="btn btn-sm btn-outline-light">
<em class="icon ni ni-reply-all"></em>
<span class="nk-menu-text">返回首页</span>
</a>
</div>
{:config_get('foot_banner')}
</div>
<!-- content @d -->
{include file="common/footer" /}
</div>
<!-- wrap @e -->
<script src="{$cdn_cdnjs}jquery/3.6.0/jquery.min.js"></script>
<script src="{$cdn_cdnjs}bootstrap/4.6.1/js/bootstrap.bundle.min.js"></script>
<script src="{$cdn_cdnjs}layer/3.5.1/layer.js"></script>
<script src="/static/js/nioapp.min.js"></script>
<script src="/static/js/script.js"></script>
<script src="/static/js/common.js"></script>
<script>
var plugin_id = {$plugin.id};
var plugin_is_star = {$plugin.is_star};
$("#star-btn-text").text(plugin_is_star?'取消收藏':'添加收藏');
$(document).ready(function(){
$('.dark-switch').on("click", function(e) {
if ($("body.dark-mode").length <= 0) {
document.cookie='darkmode=1';
} else {
document.cookie='darkmode=0';
}
});
})
</script>
{block name="script"}{/block}
</body>
</html>
+186
View File
@@ -0,0 +1,186 @@
{extend name="common/layout" /}
{block name="title"}{:config_get('title')} - {:config_get('subtitle')}{/block}
{block name="main"}
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="nk-content-body">
<div class="card card-preview">
<div class="card-header border-bottom bg-white">
<div class="d-flex">
<div class="user-avatar bg-info mr-3">
<img src="{if $islogin}{$user.avatar_url}{else}/static/images/user.png{/if}">
</div>
<div class="fake-class">
<h6 class="mt-0 d-flex align-center"><span>{if $islogin}{$user.username}{else}<a href="/login">登录</a>后才能发表留言{/if}</span></h6>
<p class="text-soft">在使用工具遇到任何问题都可以在这里反馈哟!</p>
</div>
</div>
</div>
<div class="card-inner">
<form action="#" class="form is-alter" id="comment_form">
<div class="row gy-3">
<div class="col-md-12">
<div class="form-group">
<label class="form-label" for="content">留言内容</label>
<div class="form-control-wrap">
<textarea class="form-control" id="content" name="content" placeholder="请输入留言内容" rows="3" required=""></textarea>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-group">
<label class="form-label" for="email">电子邮箱</label>
<div class="form-control-wrap">
<input type="text" class="form-control" id="email" name="email" placeholder="请输入你的电子邮箱" required="">
</div>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<button type="submit" id="submit_comment" class="btn btn-lg btn-primary" {if !$islogin}disabled{/if}>提交</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="card card-preview">
<div class="card-header border-bottom bg-white">
<h6>留言列表</h6>
</div>
<div class="card-inner">
<div class="simplebar-content" style="padding: 0px;">
<div id="commentlist"></div>
</div>
<div class="paging mt-3 mb-3">
<nav>
<ul class="pagination nk-header-right" id="page">
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="script"}
<script src="https://static.geetest.com/v4/gt4.js"></script>
<script>
var captchaObj = null;
function get_page_html(page, pagenum, linum, func){
var html = '';
if(page<=1){
html += '<li class="page-item disabled"><a class="page-link">上一页</a></li>';
}else{
html += '<li class="page-item"><a class="page-link" href="javascript:'+func+'('+(page-1)+')">上一页</a></li>';
}
var num = Math.floor(linum/2);
var start=page-num>1?page-num:1;
var end=page+num<pagenum?page+num:pagenum;
for (var i=start;i<page;i++){
html += '<li class="page-item"><a class="page-link" href="javascript:'+func+'('+i+')">'+i+'</a></li>';
}
html += '<li class="page-item active"><a class="page-link">'+page+'</a></li>';
for (var i=page+1;i<=end;i++){
html += '<li class="page-item"><a class="page-link" href="javascript:'+func+'('+i+')">'+i+'</a></li>';
}
if(page>=pagenum){
html += '<li class="page-item disabled"><a class="page-link">下一页</a></li>';
}else{
html += '<li class="page-item"><a class="page-link" href="javascript:'+func+'('+(page+1)+')">下一页</a></li>';
}
return html;
}
function show_comment_list(page){
page = page || 1;
httpGet('/comment/do/list?page='+page, function(data){
var html = '';
if(data.items.length > 0){
$.each(data.items, function(index,value){
var reply = '';
if(value.reply!=null && value.reply!=''){
reply = `<div class="nk-reply-entry entry note p-2">
<p>管理员回复:${value.reply}</p>
</div>`
}
if(!value.enable) value.content += ` <font color="orange">(待审核)</font>`;
html += `<div class="nk-reply-item">
<div class="nk-reply-header">
<div class="user-card">
<div class="user-avatar sm bg-purple">
<img src="${value.avatar_url}">
</div>
<div class="user-name">${value.username}</div>
</div>
<div class="date-time">${value.time}</div>
</div>
<div class="nk-reply-body">
<p>${value.content}</p>
${reply}
</div>
</div>`
})
}else{
html += `<p class="search-placeholder">暂无留言</p>`
}
$("#commentlist").html(html);
var page = get_page_html(data.page, data.pagenum, 7, 'show_comment_list');
$("#page").html(page);
})
}
$(document).ready(function(){
show_comment_list();
});
</script>
{if $islogin}<script>
$(document).ready(function(){
initGeetest4({
captchaId: "54088bb07d2df3c46b79f80300b0abbe",
product: 'bind',
protocol: 'https://',
riskType: 'slide',
hideSuccess: true
},function (captcha) {
captcha.onReady(function(){
captchaObj = captcha;
}).onSuccess(function(){
var result = captcha.getValidate();
if (!result) {
layer.closeAll();
return alert('请先完成验证');
}
var data = {content:content,email:email}
httpPost("/comment/do/add", Object.assign(data, result), function(data){
if(data.status == 'ok'){
layer.alert('发表留言成功!', {icon:1}, function(){ show_comment_list();layer.closeAll(); });
captcha.reset();
}else{
layer.alert(data.message, {icon:7});
captcha.reset();
}
}, true)
}).onError(function(){
alert('验证码加载失败,请刷新页面重试');
})
});
$('#comment_form').submit(function () {
content = $("#content").val().trim();
email = $("#email").val().trim();
if(content == '' || email == ''){
layer.alert('请确保各项不能为空');return false;
}
if(content.length < 3){
layer.alert('留言内容太短,请修改后提交');return false;
}
var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
if(!reg.test(email)){
layer.alert('邮箱格式不正确!');return false;
}
captchaObj.showCaptcha();
return false;
});
})
</script>{/if}
{/block}
+168
View File
@@ -0,0 +1,168 @@
{extend name="common/layout" /}
{block name="title"}最近使用 - {:config_get('title')}{/block}
{block name="main"}
<div class="nk-content nk-content-lg nk-content-fluid pt-5 pb-5 bannerbg" style="background: url(/static/images/back.png);">
<div class="container-xl">
<div class="form-control-wrap circle">
<div class="form-text-hint-lx">
<span class="overline-title"><em class="icon ni ni-search"></em></span>
</div>
<input type="text" class="form-control form-control-lx btn-round" id="searchkw" placeholder="搜索工具(Ctrl+F)" autocomplete="off">
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-fluid p-0">
<div class="nk-block">
<div class="card">
<div class="card-inner p-2">
<div class="container-xl">
<nav>
<ul class="breadcrumb breadcrumb-pipe">
<li class="breadcrumb-item fs-16px category-all active"><a href="javascript:show_tool_list(0)">全部</a></li>
{foreach $category as $v}
<li class="breadcrumb-item fs-16px category-item" data-id="{$v.id}"><a href="javascript:show_tool_list({$v.id})">{$v.title}</a></li>
{/foreach}
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="nk-content-body">
<div class="card card-preview category-card">
<div class="card-inner mt-3">
<div class="nya-title nk-ibx-action-item progress-rating">
<em class="icon ni ni-history"></em>
<span class="nk-menu-text font-weight-bold">最近使用</span>
</div>
<div class="row g-2" id="toollist">
</div>
<div class="mt-5 pt-3 text-center border-top" id="clear-btn" style="display:none">
<a href="javascript:clear_all()" class="btn btn-sm btn-dim btn-danger">
<em class="icon ni ni-trash"></em>
<span class="nk-menu-text" id="star-btn-text">清空</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
var tool_list = {:json_encode($tool)};
var searchkw = '';
function show_category_btn(catid){
if(catid == 0){
$(".category-all").addClass("active");
$(".category-item").removeClass("active");
}else{
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
$.each($(".category-item"), function(index,value){
if($(value).attr('data-id') == catid){
$(value).addClass("active");
}
})
}
}
function show_tool_list(catid){
searchkw = '';$("#searchkw").val('');
show_category_btn(catid);
var html = '';
if(tool_list.length>0){
$.each(tool_list, function(index, value){
if(catid!=0 && value.category_id!=catid) return;
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
});
$("#clear-btn").show();
}else{
html += `<p class="search-placeholder">没有最近使用的工具~</p>`;
$("#clear-btn").hide();
}
$("#toollist").html(html);
bind_statistics();
}
function show_search_list(){
var list = tool_list.filter(v => {
return v.title.indexOf(searchkw) !== -1 || v.keyword!=null && v.keyword.indexOf(searchkw) !== -1
})
var html = '';
if(list.length>0){
$.each(list, function(index, value){
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
});
}else{
html += `<p class="search-placeholder">暂无搜索结果</p>`
}
$("#toollist").html(html);
bind_statistics();
$("#clear-btn").hide();
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
}
function watch_searchkw(kw){
if(kw != searchkw){
searchkw = kw;
if(searchkw == ''){
show_tool_list(0)
}else{
show_search_list()
}
}
}
function clear_all(){
var confirmobj = layer.confirm('你确定要清空所有最近使用的工具吗?', {
btn: ['确定','取消']
}, function(){
httpPost("/history/login", {do: 'clear'}, function(data){
layer.alert('清空成功!', {icon:1}, function(){ window.location.reload(); });
})
}, function(){
layer.close(confirmobj);
});
}
function bind_statistics(){
$(".tool-link").click(function(){
var id = $(this).attr('data-id');
$.ajax({
type : "POST",
url : "/clitool",
data : {id: id},
dataType : 'json',
async: true,
success : function(data) {
console.log('statistics ok '+id)
}
});
});
}
$(document).ready(function(){
show_tool_list(0);
$("#searchkw").on('input', function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$("#searchkw").change(function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$(document).keydown(function(event){
if(event.ctrlKey && event.keyCode==70){
$("#searchkw").focus();
return false;
}
});
})
</script>
{/block}
+188
View File
@@ -0,0 +1,188 @@
{extend name="common/layout" /}
{block name="title"}{:config_get('title')} - {:config_get('subtitle')}{/block}
{block name="main"}
<div class="nk-content nk-content-lg nk-content-fluid pt-5 pb-5 bannerbg" style="background: url(/static/images/back.png);">
<div class="container-xl">
<div class="form-control-wrap circle">
<div class="form-text-hint-lx">
<span class="overline-title"><em class="icon ni ni-search"></em></span>
</div>
<input type="text" class="form-control form-control-lx btn-round" id="searchkw" placeholder="搜索工具(Ctrl+F)" autocomplete="off">
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-fluid p-0">
<div class="nk-block">
<div class="card">
<div class="card-inner p-2">
<div class="container-xl">
<nav>
<ul class="breadcrumb breadcrumb-pipe">
<li class="breadcrumb-item fs-16px category-all active"><a href="javascript:show_tool_list(0)">全部</a></li>
{foreach $category as $v}
<li class="breadcrumb-item fs-16px category-item" data-id="{$v.id}"><a href="javascript:show_tool_list({$v.id})">{$v.title}</a></li>
{/foreach}
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="nk-content-body">
{:config_get('head_banner')}
<div id="toollist"></div>
<div class="card card-preview" id="link_content" style="display:none">
<div class="card-inner mt-3">
<div class="nya-title nk-ibx-action-item progress-rating">
<em class="icon ni ni-link"></em>
<span class="nk-menu-text font-weight-bold">友情链接</span>
</div>
<div class="row g-2">
<div class="col-12">
<ul class="preview-list">
{foreach $link as $v}
<li class="preview-item">
<a href="{$v.url}" class="btn btn-wider btn-outline-info btn-sm" target="_blank">{$v.name}</a>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
</div>
{:config_get('foot_banner')}
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
var tool_list = {:json_encode($tool)};
var tools = [];
var searchkw = '';
function show_category_btn(catid){
if(catid == 0){
$("#link_content").show();
$(".category-all").addClass("active");
$(".category-item").removeClass("active");
}else{
$("#link_content").hide();
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
$.each($(".category-item"), function(index,value){
if($(value).attr('data-id') == catid){
$(value).addClass("active");
}
})
}
}
function show_tool_list(catid){
searchkw = '';$("#searchkw").val('');
show_category_btn(catid);
tools = [];
var html = '';
$.each(tool_list, function(index, value){
if(catid!=0 && value.id!=catid) return;
html += `
<div class="card card-preview category-card" data-category-id="${value.id}">
<div class="card-inner mt-3">
<div class="nya-title nk-ibx-action-item progress-rating">
<em class="${value.icon}"></em>
<span class="nk-menu-text font-weight-bold">${value.title}</span>
</div>
<div class="row g-2">`;
$.each(value.items, function(index, value){
tools.push(value);
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
})
html += `
</div>
</div>
</div>`;
});
$("#toollist").html(html);
bind_statistics();
}
function show_search_list(){
var list = tools.filter(v => {
return v.title.indexOf(searchkw) !== -1 || v.keyword!=null && v.keyword.indexOf(searchkw) !== -1
})
var html = '';
html += `
<div class="card card-preview category-card">
<div class="card-inner mt-3">
<div class="nya-title nk-ibx-action-item progress-rating">
<em class="icon ni ni-search"></em>
<span class="nk-menu-text font-weight-bold">搜索结果</span>
</div>
<div class="row g-2">`;
if(list.length>0){
$.each(list, function(index, value){
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
})
}else{
html += `<p class="search-placeholder">暂无搜索结果</p>`
}
html += `
</div>
</div>
</div>`;
$("#toollist").html(html);
bind_statistics();
$("#link_content").hide();
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
}
function watch_searchkw(kw){
if(kw != searchkw){
searchkw = kw;
if(searchkw == ''){
show_tool_list(0)
}else{
show_search_list()
}
}
}
function bind_statistics(){
$(".tool-link").click(function(){
var id = $(this).attr('data-id');
$.ajax({
type : "POST",
url : "/clitool",
data : {id: id},
dataType : 'json',
async: true,
success : function(data) {
console.log('statistics ok '+id)
}
});
});
}
$(document).ready(function(){
show_tool_list(0);
$("#searchkw").on('input', function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$("#searchkw").change(function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$(document).keydown(function(event){
if(event.ctrlKey && event.keyCode==70){
$("#searchkw").focus();
return false;
}
});
})
</script>
{/block}
+168
View File
@@ -0,0 +1,168 @@
{extend name="common/layout" /}
{block name="title"}我的收藏 - {:config_get('title')}{/block}
{block name="main"}
<div class="nk-content nk-content-lg nk-content-fluid pt-5 pb-5 bannerbg" style="background: url(/static/images/back.png);">
<div class="container-xl">
<div class="form-control-wrap circle">
<div class="form-text-hint-lx">
<span class="overline-title"><em class="icon ni ni-search"></em></span>
</div>
<input type="text" class="form-control form-control-lx btn-round" id="searchkw" placeholder="搜索工具(Ctrl+F)" autocomplete="off">
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-fluid p-0">
<div class="nk-block">
<div class="card">
<div class="card-inner p-2">
<div class="container-xl">
<nav>
<ul class="breadcrumb breadcrumb-pipe">
<li class="breadcrumb-item fs-16px category-all active"><a href="javascript:show_tool_list(0)">全部</a></li>
{foreach $category as $v}
<li class="breadcrumb-item fs-16px category-item" data-id="{$v.id}"><a href="javascript:show_tool_list({$v.id})">{$v.title}</a></li>
{/foreach}
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
<!-- content @s -->
<div class="nk-content nk-content-lg nk-content-fluid">
<div class="container-xl">
<div class="nk-content-body">
<div class="card card-preview category-card">
<div class="card-inner mt-3">
<div class="nya-title nk-ibx-action-item progress-rating">
<em class="icon ni ni-heart"></em>
<span class="nk-menu-text font-weight-bold">我的收藏</span>
</div>
<div class="row g-2" id="toollist">
</div>
<div class="mt-5 pt-3 text-center border-top" id="clear-btn" style="display:none">
<a href="javascript:clear_all()" class="btn btn-sm btn-dim btn-danger">
<em class="icon ni ni-trash"></em>
<span class="nk-menu-text" id="star-btn-text">清空</span>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
var tool_list = {:json_encode($tool)};
var searchkw = '';
function show_category_btn(catid){
if(catid == 0){
$(".category-all").addClass("active");
$(".category-item").removeClass("active");
}else{
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
$.each($(".category-item"), function(index,value){
if($(value).attr('data-id') == catid){
$(value).addClass("active");
}
})
}
}
function show_tool_list(catid){
searchkw = '';$("#searchkw").val('');
show_category_btn(catid);
var html = '';
if(tool_list.length>0){
$.each(tool_list, function(index, value){
if(catid!=0 && value.category_id!=catid) return;
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
});
$("#clear-btn").show();
}else{
html += `<p class="search-placeholder">没有已收藏的工具~</p>`;
$("#clear-btn").hide();
}
$("#toollist").html(html);
bind_statistics();
}
function show_search_list(){
var list = tool_list.filter(v => {
return v.title.indexOf(searchkw) !== -1 || v.keyword!=null && v.keyword.indexOf(searchkw) !== -1
})
var html = '';
if(list.length>0){
$.each(list, function(index, value){
html += `
<div class="col-lg-3 col-md-4 col-6">
<a href="${value.url}" data-id="${value.id}" class="btn btn-wider btn-block btn-xl btn-outline-light tool-link" ${value.out?'target="_blank"':''}>${value.title}</a>
</div>`
});
}else{
html += `<p class="search-placeholder">暂无搜索结果</p>`
}
$("#toollist").html(html);
bind_statistics();
$("#clear-btn").hide();
$(".category-all").removeClass("active");
$(".category-item").removeClass("active");
}
function watch_searchkw(kw){
if(kw != searchkw){
searchkw = kw;
if(searchkw == ''){
show_tool_list(0)
}else{
show_search_list()
}
}
}
function clear_all(){
var confirmobj = layer.confirm('你确定要清空所有收藏的工具吗?', {
btn: ['确定','取消']
}, function(){
httpPost("/stars/login", {do: 'clear'}, function(data){
layer.alert('清空成功!', {icon:1}, function(){ window.location.reload(); });
})
}, function(){
layer.close(confirmobj);
});
}
function bind_statistics(){
$(".tool-link").click(function(){
var id = $(this).attr('data-id');
$.ajax({
type : "POST",
url : "/clitool",
data : {id: id},
dataType : 'json',
async: true,
success : function(data) {
console.log('statistics ok '+id)
}
});
});
}
$(document).ready(function(){
show_tool_list(0);
$("#searchkw").on('input', function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$("#searchkw").change(function(){
watch_searchkw($(this).val().trim().toLowerCase())
});
$(document).keydown(function(event){
if(event.ctrlKey && event.keyCode==70){
$("#searchkw").focus();
return false;
}
});
})
</script>
{/block}
+20
View File
@@ -0,0 +1,20 @@
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{$plugin.title} - {:config_get('title')}</title>
<link rel="icon" href="/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="keywords" content="{:config_get('keywords')}">
<meta name="description" content="{:config_get('description')}">
<meta name="author" content="Pluto" />
<style>
*{
margin: 0;
}
</style>
</head>
<body>
<iframe src="{$plugin.config->url}" frameborder="0" width="100%" height="100%"></iframe>
</body>
</html>
+34
View File
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="refresh" content="3;url='{$plugin.config->url}';">
<meta charset="utf-8">
<title>页面加载中,请稍候...</title>
<link rel="icon" href="/favicon.ico"/>
<meta name="keywords" content="{:config_get('keywords')}">
<meta name="description" content="{:config_get('description')}">
<meta name="author" content="Pluto" />
<script type="text/javascript">
var msg = document.title;
msg = "" + msg;pos = 0;
function scrollMSG() {
document.title = msg.substring(pos, msg.length) + msg.substring(0, pos);
pos++;
if (pos > msg.length) pos = 0
window.setTimeout("scrollMSG()",200);
}
scrollMSG();
</script>
<style>body{overflow:hidden;background:#666}.container{display:flex;justify-content:center;align-items:center;height:100vh;overflow:hidden;animation-delay:1s}.item-1{width:20px;height:20px;background:#f583a1;border-radius:50%;background-color:#eed968;margin:7px;display:flex;justify-content:center;align-items:center}@keyframes scale{0%{transform:scale(1)}50%,75%{transform:scale(3.5)}78%,100%{opacity:0}}.item-1:before{content:'';width:20px;height:20px;border-radius:50%;background-color:#eed968;opacity:.7;animation:scale 2s infinite cubic-bezier(0,0,0.49,1.02);animation-delay:200ms;transition:.5s all ease;transform:scale(1)}.item-2{width:20px;height:20px;background:#f583a1;border-radius:50%;background-color:#eece68;margin:7px;display:flex;justify-content:center;align-items:center}@keyframes scale{0%{transform:scale(1)}50%,75%{transform:scale(3.5)}78%,100%{opacity:0}}.item-2:before{content:'';width:20px;height:20px;border-radius:50%;background-color:#eece68;opacity:.7;animation:scale 2s infinite cubic-bezier(0,0,0.49,1.02);animation-delay:400ms;transition:.5s all ease;transform:scale(1)}.item-3{width:20px;height:20px;background:#f583a1;border-radius:50%;background-color:#eec368;margin:7px;display:flex;justify-content:center;align-items:center}@keyframes scale{0%{transform:scale(1)}50%,75%{transform:scale(3.5)}78%,100%{opacity:0}}.item-3:before{content:'';width:20px;height:20px;border-radius:50%;background-color:#eec368;opacity:.7;animation:scale 2s infinite cubic-bezier(0,0,0.49,1.02);animation-delay:600ms;transition:.5s all ease;transform:scale(1)}.item-4{width:20px;height:20px;background:#f583a1;border-radius:50%;background-color:#eead68;margin:7px;display:flex;justify-content:center;align-items:center}@keyframes scale{0%{transform:scale(1)}50%,75%{transform:scale(3.5)}78%,100%{opacity:0}}.item-4:before{content:'';width:20px;height:20px;border-radius:50%;background-color:#eead68;opacity:.7;animation:scale 2s infinite cubic-bezier(0,0,0.49,1.02);animation-delay:800ms;transition:.5s all ease;transform:scale(1)}.item-5{width:20px;height:20px;background:#f583a1;border-radius:50%;background-color:#ee8c68;margin:7px;display:flex;justify-content:center;align-items:center}@keyframes scale{0%{transform:scale(1)}50%,75%{transform:scale(3.5)}78%,100%{opacity:0}}.item-5:before{content:'';width:20px;height:20px;border-radius:50%;background-color:#ee8c68;opacity:.7;animation:scale 2s infinite cubic-bezier(0,0,0.49,1.02);animation-delay:1000ms;transition:.5s all ease;transform:scale(1)}</style>
</head>
<body>
<div class="container">
<div class="item-1"></div>
<div class="item-2"></div>
<div class="item-3"></div>
<div class="item-4"></div>
<div class="item-5"></div>
</div>
</body>
</html>
+311
View File
@@ -0,0 +1,311 @@
<html data-theme="light">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>安装向导 - 彩虹工具网</title>
<link rel="icon" href="/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://cdn.staticfile.org/daisyui/2.2.2/full.min.css" rel="stylesheet" type="text/css"/>
<link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet" type="text/css"/>
<script src="https://cdn.staticfile.org/limonte-sweetalert2/11.4.4/sweetalert2.all.min.js"></script>
<script src="https://cdn.staticfile.org/vue/2.6.14/vue.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.26.0/axios.min.js"></script>
<style>
body {
background-image: url("static/images/install_background.jpg");
background-repeat: no-repeat;
background-size: cover;
}
.panel {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(255, 255, 255, 0.67);
overflow: hidden;
animation: panel 1s ease-in-out;
}
@keyframes panel {
0% {
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
opacity: 0;
-webkit-transform: translate(-50%, -50%) perspective(400px) rotateX(90deg);
transform: translate(-50%, -50%) perspective(400px) rotateX(90deg)
}
40% {
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in;
-webkit-transform: translate(-50%, -50%) perspective(400px) rotateX(-20deg);
transform: translate(-50%, -50%) perspective(400px) rotateX(-20deg)
}
60% {
opacity: 1;
-webkit-transform: translate(-50%, -50%) perspective(400px) rotateX(10deg);
transform: translate(-50%, -50%) perspective(400px) rotateX(10deg)
}
80% {
-webkit-transform: translate(-50%, -50%) perspective(400px) rotateX(-5deg);
transform: translate(-50%, -50%) perspective(400px) rotateX(-5deg)
}
to {
-webkit-transform: translate(-50%, -50%) perspective(400px);
transform: translate(-50%, -50%) perspective(400px)
}
}
.table td, .table th {
background-color: transparent !important;
}
.v-enter-active {
transition: all .8s ease;
}
.v-leave-active {
transition: all .8s ease;
}
.v-enter {
transform: translateX(100%);
opacity: 0;
}
.v-leave-to {
transform: translateX(-100%);
opacity: 0;
position: absolute;
}
</style>
</head>
<body>
<div class="container mx-auto" id="app">
<div class="panel w-11/12 sm:w-3/4 md:w-2/3 2xl:w-1/2">
<div class="card text-center ">
<div class="card-body pt-8 pb-0">
<ul class="steps steps-horizontal">
<li class="step step-accent">开始安装</li>
<li class="step" :class="{'step-accent':step>0}">检测安装环境</li>
<li class="step" :class="{'step-accent':step>1}">配置数据库</li>
<li class="step" :class="{'step-accent':step>2}">配置管理员账号</li>
<li class="step" :class="{'step-accent':step>3}">完成安装</li>
</ul>
</div>
</div>
<div class="card text-center shadow-2xl main">
<transition>
<div class="card-body" v-show="step===0">
<h2 class="card-title m-auto">欢迎安装彩虹工具箱</h2>
<p>Welcome to install Caihong Toolbox.</p>
<div class="justify-center card-actions">
<button class="btn btn-outline btn-accent" @click="step++">开始安装吧~</button>
</div>
</div>
</transition>
<transition>
<div class="card-body" v-show="step===1">
<h2 class="card-title m-auto">检测安装环境</h2>
<div class="overflow-x-auto">
<table class="table w-full">
<thead>
<tr>
<th>检测项</th>
<th>检测结果</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in requirements" :key="index">
<td>{{index}}</td>
<td>
<div class="badge badge-success" v-if="item">
Yes
</div>
<div class="badge badge-error" v-else>
No
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="justify-center card-actions">
<button class="btn btn-outline btn-accent" @click="step++">下一步</button>
</div>
</div>
</transition>
<transition>
<div class="card-body" v-show="step===2">
<h2 class="card-title m-auto">配置数据库信息</h2>
<div>
<div class="form-control">
<label class="label">
<span class="label-text">数据库地址</span>
</label>
<input type="text" v-model="database.hostname" placeholder="请输入数据库地址"
class="input input-accent input-bordered">
</div>
<div class="form-control">
<label class="label">
<span class="label-text">数据库端口</span>
</label>
<input type="text" v-model="database.hostport" placeholder="请输入数据库端口"
class="input input-accent input-bordered">
</div>
<div class="form-control">
<label class="label">
<span class="label-text">数据库用户名</span>
</label>
<input type="text" v-model="database.username" placeholder="请输入数据库用户名"
class="input input-accent input-bordered">
</div>
<div class="form-control">
<label class="label">
<span class="label-text">数据库密码</span>
</label>
<input type="text" v-model="database.password" placeholder="请输入数据库密码"
class="input input-accent input-bordered">
</div>
<div class="form-control">
<label class="label">
<span class="label-text">数据库名</span>
</label>
<input type="text" v-model="database.database" placeholder="请输入数据库名"
class="input input-accent input-bordered">
</div>
</div>
<div class="justify-center card-actions">
<button class="btn btn-outline btn-accent" @click="step++">下一步</button>
</div>
</div>
</transition>
<transition>
<div class="card-body" v-show="step===3">
<h2 class="card-title m-auto">配置管理员账号</h2>
<div>
<div class="form-control">
<label class="label">
<span class="label-text">用户名</span>
</label>
<input type="text" v-model="admin.username" placeholder="请输入用户名"
class="input input-accent input-bordered">
</div>
<div class="form-control">
<label class="label">
<span class="label-text">密码</span>
</label>
<input type="text" v-model="admin.password" placeholder="请输入密码"
class="input input-accent input-bordered">
</div>
</div>
<div class="justify-center card-actions">
<button class="btn btn-outline btn-accent" @click="step++">下一步</button>
</div>
</div>
</transition>
<transition>
<div class="card-body" v-show="step===4">
<h2 class="card-title m-auto">完成安装</h2>
<p>恭喜你,已经成功安装了彩虹工具箱~</p>
<div class="justify-center card-actions">
<button class="btn btn-outline btn-accent" @click="window.location.href='/'">网站首页</button>
<button class="btn btn-outline btn-accent" @click="window.location.href='/admin/'">管理后台</button>
</div>
</div>
</transition>
</div>
</div>
</div>
<script>
const instance = axios.create({
baseURL: '/',
// timeout: 1000,
// headers: {'X-Custom-Header': 'foobar'}
});
const httpPost = (url, params) => {
return instance.post(url, params)
.then(res => {
return res.data
}).then(res => {
if (res.status !== "ok") {
Swal.fire({icon: 'error',title: res.message})
}
return res
})
}
new Vue({
el: '#app',
data: {
step: 0,
status: {},
requirements: JSON.parse(`{:json_encode($requirements)}`),
database: {
hostname: 'localhost',
hostport: '3306',
database: '',
username: '',
password: '',
},
admin: {
username: 'admin',
password: '',
},
},
watch: {
step(newVal, oldVal) {
let loading = null
if (this.status[newVal]) {
return
}
this.status[newVal] = true
switch (newVal) {
case 2:
let values = Object.values(this.requirements);
if (values.includes(false)) {
this.step = oldVal;
Swal.fire({icon: 'error',title: '环境不通过'})
this.status[newVal] = false
return
}
break
case 3:
loading = Swal.fire({title: '正在完成数据库安装', allowOutsideClick: false})
Swal.showLoading()
httpPost('/install/database', this.database).then(res => {
if (res.status === 'ok') {
httpPost('/install/init_data', {}).then(res2 => {
if (res2.status !== 'ok') {
this.step = oldVal
this.status[newVal] = false
}
})
} else {
this.step = oldVal
this.status[newVal] = false
}
}).finally(() => loading.close())
break
case 4:
loading = Swal.fire({title: '正在完成管理员账号配置', allowOutsideClick: false})
Swal.showLoading()
httpPost('/install/admin', this.admin).then(res => {
if (res.status !== 'ok') {
this.step = oldVal
this.status[newVal] = false
}
}).finally(() => loading.close())
break
}
}
},
methods: {}
})
</script>
</body>
</html>