|

分享源码
界面截图: |
|
是否带模块: |
纯源码 |
备注说明: |
- |
批量管理数据的上传与下发
win版:HTTP服务器后端api接口上传与下发
https://bbs.125.la/forum.php?mod=viewthread&tid=14853568
(出处: 精易论坛)
111<?php
// ---------- index.php ----------
// 开启 session
session_start();
$max_age = 30 * 60; // 30 分钟(秒)
$password = '123123';
$now = time();
// 如果未登录或已过期
if (
!isset($_SESSION['authenticated'])
|| $_SESSION['authenticated'] !== true
|| !isset($_SESSION['login_time'])
|| ($now - $_SESSION['login_time'] > $max_age)
) {
$error = '';
// 如果提交了表单
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
if ($_POST['password'] === $password) {
// 登录成功,记录状态和时间戳
$_SESSION['authenticated'] = true;
$_SESSION['login_time'] = $now;
// 重定向到自己,避免表单重复提交
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
} else {
$error = '密码错误,请重试。';
}
}
// 显示登录表单
?>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>请输入密码</title>
<style>
body { font-family: Arial, sans-serif; background: #f5f6fa; color: #2f3640; display: flex; align-items: center; justify-content: center; height: 100vh; }
.login-box { background: #fff; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); width: 300px; }
input { width: 100%; padding: .5rem; margin-top: .5rem; border: 1px solid #ccc; border-radius: 4px; }
button { width: 100%; padding: .5rem; margin-top: 1rem; background: #0097e6; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
.error { color: #e84118; margin-top: .5rem; }
</style>
</head>
<body>
<div class="login-box">
<h2>请输入密码</h2>
<form method="post">
<input type="password" name="password" placeholder="密码" required autofocus>
<button type="submit">登录</button>
<?php if ($error): ?>
<div class="error"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
</form>
</div>
</body>
</html>
<?php
exit;
}
// ——————————————————————————————————————————
// ——————————————————————————————————————————
ini_set('display_errors', '0');
error_reporting(0);
// 数据库配置
$cfg = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'api',
'user' => 'api',
'pass' => 'TbYcJebZnr27JBw8',
];
// 连接 & 初始化数据库和表
try {
// 先连 root,确保库存在
$pdoRoot = new PDO(
"mysql:host={$cfg['host']};port={$cfg['port']}",
$cfg['user'], $cfg['pass'],
[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]
);
$pdoRoot->exec("CREATE DATABASE IF NOT EXISTS `{$cfg['dbname']}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci");
// 连接到业务库
$pdo = new PDO(
"mysql:host={$cfg['host']};port={$cfg['port']};dbname={$cfg['dbname']};charset=utf8mb4",
$cfg['user'], $cfg['pass'],
[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC]
);
// clients 表
$pdo->exec(<<<'SQL'
CREATE TABLE IF NOT EXISTS `clients` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`token` CHAR(32) NOT NULL UNIQUE,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`remark` VARCHAR(255) NOT NULL DEFAULT ''
) ENGINE=InnoDB CHARSET=utf8mb4;
SQL
);
// queue 表
$pdo->exec(<<<'SQL'
CREATE TABLE IF NOT EXISTS `queue` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`token` CHAR(32) NOT NULL,
`data` VARCHAR(255) NOT NULL,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`token`) REFERENCES `clients`(`token`) ON DELETE CASCADE,
INDEX (`token`)
) ENGINE=InnoDB CHARSET=utf8mb4;
SQL
);
} catch (Exception $e) {
http_response_code(500);
exit("DB init error");
}
// 解析 Method
$method = isset($_GET['Method']) ? strtolower($_GET['Method']) : '';
// Generate
if ($method === 'generate') {
$token = bin2hex(random_bytes(16));
$pdo->prepare("INSERT INTO clients (token) VALUES(?)")->execute([$token]);
$host = (isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']==='on'?'https':'http')
."://{$_SERVER['HTTP_HOST']}".dirname($_SERVER['SCRIPT_NAME']);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'token' => $token,
'upload_url' => "{$host}/index.php?Method=Upload&token={$token}&min=",
'download_url' => "{$host}/index.php?Method=Get&token={$token}&min=",
], JSON_UNESCAPED_UNICODE);
exit;
}
// List
if ($method === 'list') {
header('Content-Type: application/json; charset=utf-8');
$rows = $pdo->query("SELECT token, remark FROM clients ORDER BY ts DESC")->fetchAll();
$host = (isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']==='on'?'https':'http')
."://{$_SERVER['HTTP_HOST']}".dirname($_SERVER['SCRIPT_NAME']);
$out = [];
foreach ($rows as $r) {
$out[] = [
'token' => $r['token'],
'upload_url' => "{$host}/index.php?Method=Upload&token={$r['token']}&min=",
'download_url' => "{$host}/index.php?Method=Get&token={$r['token']}&min=",
'remark' => $r['remark']
];
}
echo json_encode($out, JSON_UNESCAPED_UNICODE);
exit;
}
// SaveRemark
if ($method === 'saveremark') {
$token = $_GET['token'] ?? '';
$remark = $_GET['remark'] ?? '';
if ($token === '') { http_response_code(400); exit('Missing token'); }
$pdo->prepare("UPDATE clients SET remark=? WHERE token=?")->execute([$remark, $token]);
header('Content-Type: text/plain; charset=utf-8');
exit("OK");
}
// Count
if ($method === 'count') {
$token = $_GET['token'] ?? '';
if ($token === '') { http_response_code(400); exit('Missing token'); }
$chk = $pdo->prepare("SELECT 1 FROM clients WHERE token=?"); $chk->execute([$token]);
if (!$chk->fetch()) { http_response_code(404); exit('Invalid token'); }
$cnt = $pdo->prepare("SELECT COUNT(*) FROM queue WHERE token=?");
$cnt->execute([$token]);
$num = (int)$cnt->fetchColumn();
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['count'=>$num], JSON_UNESCAPED_UNICODE);
exit;
}
// Clear
if ($method === 'clear') {
$token = $_GET['token'] ?? '';
if ($token === '') { http_response_code(400); exit('Missing token'); }
$chk = $pdo->prepare("SELECT 1 FROM clients WHERE token=?"); $chk->execute([$token]);
if (!$chk->fetch()) { http_response_code(404); exit('Invalid token'); }
$pdo->prepare("DELETE FROM queue WHERE token=?")->execute([$token]);
header('Content-Type: text/plain; charset=utf-8');
exit("OK");
}
// Upload
if ($method === 'upload') {
$token = $_GET['token'] ?? ''; $min = $_GET['min'] ?? '';
if ($token === '' || $min === '') { http_response_code(400); exit('Missing'); }
$chk = $pdo->prepare("SELECT 1 FROM clients WHERE token=?"); $chk->execute([$token]);
if (!$chk->fetch()) { http_response_code(404); exit('Invalid'); }
$pdo->prepare("INSERT INTO queue (token,data) VALUES(?,?)")->execute([$token,$min]);
header('Content-Type: text/plain; charset=utf-8');
exit("Uploaded: $min");
}
// Get
if ($method === 'get') {
$token = $_GET['token'] ?? ''; $min = $_GET['min'] ?? '';
if ($token === '' || !ctype_digit($min)) { http_response_code(400); exit('Invalid'); }
$chk = $pdo->prepare("SELECT 1 FROM clients WHERE token=?"); $chk->execute([$token]);
if (!$chk->fetch()) { http_response_code(404); exit('Invalid'); }
$limit = (int)$min;
$qry = $pdo->prepare("SELECT id,data FROM queue WHERE token=? ORDER BY id ASC LIMIT ?");
$qry->bindValue(1,$token); $qry->bindValue(2,$limit,PDO::PARAM_INT); $qry->execute();
$rows = $qry->fetchAll();
if ($rows) {
$ids = array_column($rows,'id');
$pls = implode(',',array_fill(0,count($ids),'?'));
$pdo->prepare("DELETE FROM queue WHERE id IN($pls)")->execute($ids);
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode(array_column($rows,'data'),JSON_UNESCAPED_UNICODE);
exit;
}
// Delete
if ($method === 'delete') {
$token = $_GET['token'] ?? '';
if ($token === '') { http_response_code(400); exit('Missing'); }
$pdo->prepare("DELETE FROM clients WHERE token=?")->execute([$token]);
header('Content-Type: text/plain; charset=utf-8');
exit("Deleted: $token");
}
// 前端界面
?><!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>接口管理面板</title>
<style>
body { font-family: Arial, sans-serif; background: #f5f6fa; color: #2f3640; padding: 2rem; }
h1 { margin-bottom: 1rem; }
#btnGen { background:#0097e6;color:#fff;border:none;padding:.6rem 1.2rem;border-radius:4px;cursor:pointer; }
#btnGen:hover{background:#40739e;}
table{width:100%;border-collapse:collapse;margin-top:1rem;background:#fff}
th,td{padding:.75rem;border:1px solid #dcdde1;text-align:left;}
th{background:#273c75;color:#f5f6fa;}
tr:nth-child(even){background:#f0f0f0;}
input,textarea{width:100%;padding:.4rem;border:1px solid #ccc;border-radius:4px;font-size:.95rem;}
textarea{resize:vertical;}
.btn-small{padding:.3rem .6rem;border:none;border-radius:4px;cursor:pointer;font-size:.85rem;}
.save-btn{background:#44bd32;color:#fff;margin-right:.3rem;}
.del-btn{background:#e84118;color:#fff;margin-right:.3rem;}
.count-btn{background:#e1b12c;color:#fff;margin-right:.3rem;}
.clear-btn{background:#c23616;color:#fff;}
</style>
</head>
<body>
<h1>接口管理面板</h1>
<button id="btnGen">生成接口</button>
<table id="tbl">
<thead>
<tr>
<th>Token</th>
<th>上传接口</th>
<th>下载接口</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
(function(){
const tblBody = document.querySelector('#tbl tbody');
const btnGen = document.getElementById('btnGen');
async function load(){
const res = await fetch('index.php?Method=List');
return await res.json();
}
function render(arr){
tblBody.innerHTML = '';
arr.forEach(item=>{
const tr = document.createElement('tr');
const tdTk = document.createElement('td');
tdTk.textContent = item.token;
const tdUp = document.createElement('td');
const inpUp = document.createElement('input');
inpUp.value = item.upload_url; inpUp.readOnly = true;
inpUp.onclick = ()=>navigator.clipboard.writeText(item.upload_url);
tdUp.appendChild(inpUp);
const tdDn = document.createElement('td');
const inpDn = document.createElement('input');
inpDn.value = item.download_url; inpDn.readOnly = true;
inpDn.onclick = ()=>navigator.clipboard.writeText(item.download_url);
tdDn.appendChild(inpDn);
const tdRk = document.createElement('td');
const txtRk = document.createElement('textarea');
txtRk.rows = 2; txtRk.value = item.remark;
tdRk.appendChild(txtRk);
const tdAc = document.createElement('td');
const btnSave = document.createElement('button');
btnSave.textContent = '保存'; btnSave.className = 'btn-small save-btn';
btnSave.onclick = async ()=>{
await fetch(`index.php?Method=SaveRemark&token=${item.token}&remark=${encodeURIComponent(txtRk.value)}`);
};
const btnCount = document.createElement('button');
btnCount.textContent = '查询数量'; btnCount.className = 'btn-small count-btn';
btnCount.onclick = async ()=>{
const res = await fetch(`index.php?Method=Count&token=${item.token}`);
const j = await res.json();
alert(`当前数据数量:${j.count}`);
};
const btnClear = document.createElement('button');
btnClear.textContent = '清空数据'; btnClear.className = 'btn-small clear-btn';
btnClear.onclick = async ()=>{
if (!confirm('确定要清空此 token 的所有数据吗?')) return;
await fetch(`index.php?Method=Clear&token=${item.token}`);
alert('已清空。');
};
const btnDel = document.createElement('button');
btnDel.textContent = '删除'; btnDel.className = 'btn-small del-btn';
btnDel.onclick = async ()=>{
if (!confirm('确定要删除此 token 及所有数据吗?')) return;
await fetch(`index.php?Method=Delete&token=${item.token}`);
render(await load());
};
tdAc.append(btnSave, btnCount, btnClear, btnDel);
tr.append(tdTk, tdUp, tdDn, tdRk, tdAc);
tblBody.appendChild(tr);
});
}
btnGen.onclick = async ()=>{
await fetch('index.php?Method=Generate');
render(await load());
};
load().then(render);
})();
</script>
</body>
</html>
|
|