文件
2026-08-16 17:03:10 +08:00

277 行
16 KiB
PHP

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
<?php
require __DIR__ . '/../includes/init.php';
requireStaff();
require '_common.php';
$isAdmin = isAdminStaff();
$db = db();
$msg = '';
$err = '';
if (!$isAdmin && $_SERVER['REQUEST_METHOD'] === 'POST') {
$err = '客服账号仅可查看,如需操作请联系管理员。';
}
$allowed = ['pending', 'paid', 'shipped', 'completed', 'cancelled'];
if (isset($_POST['update_status'])) {
verifyCsrf();
$id = (int) ($_POST['id'] ?? 0);
$status = $_POST['status'] ?? '';
if (!in_array($status, $allowed, true)) {
$err = '非法的订单状态';
} else {
$db->prepare('UPDATE ' . tn('orders') . ' SET status = ? WHERE id = ?')->execute([$status, $id]);
$msg = '订单
}
}
if (isset($_POST['ship'])) {
verifyCsrf();
$id = (int) ($_POST['id'] ?? 0);
$serverIp = trim($_POST['server_ip'] ?? '');
$connAddr = trim($_POST['conn_addr'] ?? '');
$loginUser = trim($_POST['login_user'] ?? '');
$loginPass = trim($_POST['login_pass'] ?? '');
$remark = trim($_POST['remark'] ?? '');
$activated = isset($_POST['activated']) ? 1 : 0;
$productInfo = trim($_POST['product_info'] ?? '');
$chk = $db->prepare('SELECT id, status FROM ' . tn('orders') . ' WHERE id = ?');
$chk->execute([$id]);
$ord = $chk->fetch();
if (!$ord) {
$err = '订单不存在';
} else {
$ex = $db->prepare('SELECT id FROM ' . tn('order_deliveries') . ' WHERE order_id = ? ORDER BY id DESC LIMIT 1');
$ex->execute([$id]);
$exId = $ex->fetchColumn();
if ($exId) {
$db->prepare('UPDATE ' . tn('order_deliveries') . ' SET server_ip=?, conn_addr=?, login_user=?, login_pass=?, remark=?, activated=?, product_info=? WHERE id=?')
->execute([$serverIp, $connAddr, $loginUser, $loginPass, $remark, $activated, $productInfo, $exId]);
} else {
$db->prepare('INSERT INTO ' . tn('order_deliveries') . ' (order_id, server_ip, conn_addr, login_user, login_pass, remark, activated, product_info, created_at) VALUES (?,?,?,?,?,?,?,?,NOW())')
->execute([$id, $serverIp, $connAddr, $loginUser, $loginPass, $remark, $activated, $productInfo]);
}
if ($ord['status'] === 'paid') {
$db->prepare('UPDATE ' . tn('orders') . ' SET status = ? WHERE id = ?')->execute(['shipped', $id]);
}
$msg = '发货信息已保存(订单
$u = $db->prepare('SELECT u.email, u.username FROM ' . tn('orders') . ' o LEFT JOIN ' . tn('users') . ' u ON u.id = o.user_id WHERE o.id = ?');
$u->execute([$id]);
$urow = $u->fetch();
if ($urow && !empty($urow['email'])) {
$subject = '[' . SITE_NAME . '] 你的订单
$body = '<div style="font-family:sans-serif;max-width:560px;margin:auto">'
. '<h2 style="color:
. '<p>你好 ' . h($urow['username']) . ',你购买的以下服务/商品已开通:</p>'
. '<div style="background:
. '<p style="margin:4px 0;">连接地址:' . h($connAddr) . '</p>'
. '<p style="margin:4px 0;">登录账户:' . h($loginUser) . '</p>'
. '<p style="margin:4px 0;">可在「我的订单 → 详情」中查看完整登录凭据。</p>'
. '</div>'
. '<p class="muted">如有问题请到「我的工单」联系客服。</p></div>';
fnwSendMail($urow['email'], $subject, $body);
}
}
}
if (isset($_POST['save_expire'])) {
verifyCsrf();
$id = (int) ($_POST['id'] ?? 0);
$clear = isset($_POST['clear_expire']);
$expRaw = trim($_POST['expires_at'] ?? '');
$newExp = null;
if (!$clear) {
if ($expRaw === '') {
$err = '请填写新的到期时间,或勾选「清除到期时间」';
} else {
$t = strtotime(str_replace('T', ' ', $expRaw));
if ($t === false) {
$err = '到期时间格式不正确';
} else {
$newExp = date('Y-m-d H:i:s', $t);
}
}
}
if ($err === '') {
$db->prepare('UPDATE ' . tn('orders') . ' SET expires_at = ?, expire_notify_sent = 0 WHERE id = ?')
->execute([$newExp, $id]);
$msg = '订单
}
}
if (isset($_POST['delete'])) {
verifyCsrf();
$id = (int) ($_POST['delete'] ?? 0);
$db->prepare('DELETE FROM ' . tn('order_deliveries') . ' WHERE order_id = ?')->execute([$id]);
$db->prepare('DELETE FROM ' . tn('order_items') . ' WHERE order_id = ?')->execute([$id]);
$db->prepare('DELETE FROM ' . tn('orders') . ' WHERE id = ?')->execute([$id]);
$msg = '订单
}
$filter = trim($_GET['status'] ?? '');
$where = $filter !== '' ? 'WHERE o.status = ?' : '';
$params = $filter !== '' ? [$filter] : [];
$stmt = $db->prepare(
'SELECT o.*, u.username, u.email AS u_email FROM ' . tn('orders') . ' o
LEFT JOIN ' . tn('users') . ' u ON u.id = o.user_id
' . $where . ' ORDER BY o.created_at DESC'
);
$stmt->execute($params);
$list = $stmt->fetchAll();
$itemsOf = [];
foreach ($list as $o) {
$it = $db->prepare('SELECT name, qty, period_days FROM ' . tn('order_items') . ' WHERE order_id = ?');
$it->execute([$o['id']]);
$itemsOf[$o['id']] = $it->fetchAll();
}
$view = isset($_GET['view']) ? (int) $_GET['view'] : 0;
$order = $delivery = null;
if ($view > 0) {
$ostmt = $db->prepare('SELECT o.*, u.username, u.email AS u_email FROM ' . tn('orders') . ' o LEFT JOIN ' . tn('users') . ' u ON u.id = o.user_id WHERE o.id = ?');
$ostmt->execute([$view]);
$order = $ostmt->fetch();
if ($order) {
$istmt = $db->prepare('SELECT * FROM ' . tn('order_items') . ' WHERE order_id = ?');
$istmt->execute([$order['id']]);
$order['items'] = $istmt->fetchAll();
$dstmt = $db->prepare('SELECT * FROM ' . tn('order_deliveries') . ' WHERE order_id = ? ORDER BY id DESC LIMIT 1');
$dstmt->execute([$order['id']]);
$delivery = $dstmt->fetch();
}
}
adminHeader('订单管理', 'orders');
?>
<h1 class="page-title"><i class="fas fa-receipt"></i> 订单管理</h1>
<?php if ($msg): ?><p class="banner-ok"><i class="fas fa-check-circle"></i> <?= h($msg) ?></p><?php endif; ?>
<?php if ($err): ?><p class="form-err"><?= h($err) ?></p><?php endif; ?>
<div class="cat-chips">
<a href="orders.php" class="chip <?= $filter===''?'active':'' ?>">全部</a>
<?php foreach ($allowed as $s): ?>
<a href="orders.php?status=<?= $s ?>" class="chip <?= $filter===$s?'active':'' ?>"><?= orderStatusLabel($s) ?></a>
<?php endforeach; ?>
</div>
<?php if ($order): ?>
<div class="panel">
<div class="od-head">
<div>
<div class="od-no">订单号:<?= h($order['order_no']) ?></div>
<div class="od-time"><?= date('Y-m-d H:i', strtotime($order['created_at'])) ?></div>
</div>
<span class="badge-status status-<?= h($order['status']) ?>"><?= orderStatusLabel($order['status']) ?></span>
</div>
<div class="od-info">
<div class="od-block">
<div class="od-label">订单发起人</div>
<div class="od-line"><?= h($order['username'] ?? '未知') ?></div>
<div class="od-line">账号邮箱:<?= h($order['u_email'] ?? '未填写') ?></div>
</div>
<div class="od-block">
<div class="od-label">联系信息</div>
<div class="od-line">联系人:<?= $order['contact'] !== '' ? h($order['contact']) : '—' ?></div>
<div class="od-line">联系邮箱:<?= $order['contact_email'] !== '' ? h($order['contact_email']) : '—' ?></div>
<div class="od-line">收货地址:<?= $order['address'] !== '' ? h($order['address']) : '(未填写)' ?></div>
</div>
<div class="od-block">
<div class="od-label">周期 / 到期</div>
<div class="od-line">周期:<?= periodLabel($order['period_days']) ?></div>
<div class="od-line">到期时间:<?= expiryBadge($order['expires_at']) ?></div>
<?php if (!empty($order['expire_notify_sent'])): ?><div class="od-line muted">已发送「到期前提醒」邮件</div><?php endif; ?>
<form method="post" action="" class="expire-edit">
<?= csrfField() ?>
<input type="hidden" name="id" value="<?= (int) $order['id'] ?>">
<label class="expire-field">修改到期时间
<input type="datetime-local" name="expires_at" value="<?= $order['expires_at'] ? date('Y-m-d\TH:i', strtotime($order['expires_at'])) : '' ?>">
</label>
<label class="expire-clear"><input type="checkbox" name="clear_expire" value="1"> 清除到期时间</label>
<button type="submit" name="save_expire" class="btn btn-primary btn-sm"><i class="fas fa-save"></i> 保存到期时间</button>
</form>
</div>
<div class="od-block">
<div class="od-label">备注</div>
<div class="od-line"><?= $order['note'] !== '' ? nl2br(h($order['note'])) : '(无)' ?></div>
</div>
<div class="od-block">
<div class="od-label">支付方式</div>
<div class="od-line"><?= payTypeLabel($order['pay_type']) ?><?= $order['pay_type']==='points' ? '(消耗 ' . (int)$order['points_used'] . ' 积分)' : '' ?></div>
</div>
</div>
<h3>商品明细</h3>
<table class="data-table">
<thead><tr><th>商品</th><th>单价</th><th>数量</th><th>小计</th><th>周期</th></tr></thead>
<tbody>
<?php foreach (($order['items'] ?? []) as $it): ?>
<tr>
<td><?= h($it['name']) ?></td>
<td><?= money($it['price']) ?></td>
<td><?= (int) $it['qty'] ?></td>
<td><?= money($it['subtotal']) ?></td>
<td><?= periodLabel($it['period_days']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<h3><i class="fas fa-truck"></i> 发货信息(连接地址 / 登录凭据 / 商品信息)</h3>
<?php if ($delivery): ?>
<div class="ship-existing">
<p class="muted">已填写,当前内容如下(可重新提交覆盖):</p>
<div class="od-line">激活状态:<span class="badge-<?= !empty($delivery['activated']) ? 'on' : 'off' ?>"><?= !empty($delivery['activated']) ? '已激活' : '未激活' ?></span></div>
<div class="od-line">服务器 IP<?= h($delivery['server_ip']) ?: '—' ?></div>
<div class="od-line">连接地址:<?= h($delivery['conn_addr']) ?: '—' ?></div>
<div class="od-line">登录账户:<?= h($delivery['login_user']) ?: '—' ?></div>
<div class="od-line">登录密码:<?= $delivery['login_pass'] !== '' ? h($delivery['login_pass']) : '—' ?></div>
<?php if ($delivery['product_info'] !== ''): ?><div class="od-line">商品信息:<?= nl2br(h($delivery['product_info'])) ?></div><?php endif; ?>
<?php if ($delivery['remark'] !== ''): ?><div class="od-line">备注:<?= nl2br(h($delivery['remark'])) ?></div><?php endif; ?>
</div>
<?php endif; ?>
<form method="post" action="" class="grid-form ship-form">
<?= csrfField() ?>
<input type="hidden" name="id" value="<?= (int) $order['id'] ?>">
<label>服务器 IP<input type="text" name="server_ip" value="<?= $delivery ? h($delivery['server_ip']) : '' ?>" placeholder="如 1.2.3.4"></label>
<label>连接地址 / 域名<input type="text" name="conn_addr" value="<?= $delivery ? h($delivery['conn_addr']) : '' ?>" placeholder="如 mc.example.com:25565"></label>
<label>登录账户<input type="text" name="login_user" value="<?= $delivery ? h($delivery['login_user']) : '' ?>" placeholder="如 player01"></label>
<label>登录密码<input type="text" name="login_pass" value="<?= $delivery ? h($delivery['login_pass']) : '' ?>" placeholder="如 ********"></label>
<label>激活状态
<select name="activated">
<option value="0" <?= $delivery && empty($delivery['activated']) ? 'selected' : '' ?>>未激活</option>
<option value="1" <?= $delivery && !empty($delivery['activated']) ? 'selected' : '' ?>>已激活</option>
</select>
</label>
<label class="span2">商品信息(展示给用户)<textarea name="product_info" rows="3" placeholder="选填,将展示给该用户,如开通说明、使用须知"><?= $delivery ? h($delivery['product_info']) : '' ?></textarea></label>
<label class="span2">备注<textarea name="remark" rows="2" placeholder="选填,仅内部可见"><?= $delivery ? h($delivery['remark']) : '' ?></textarea></label>
<div class="form-actions span2">
<button type="submit" name="ship" class="btn btn-primary"><i class="fas fa-paper-plane"></i> 保存发货信息<?= $delivery ? '(覆盖)' : '' ?></button>
<a href="orders.php" class="btn btn-ghost">返回列表</a>
</div>
</form>
</div>
<?php else: ?>
<div class="panel">
<?php if (empty($list)): ?>
<p class="empty">没有符合条件的订单。</p>
<?php else: ?>
<table class="data-table">
<thead><tr><th>订单号</th><th>用户</th><th>商品</th><th>金额</th><th>周期</th><th>支付</th><th>状态</th><th>时间</th><th>操作</th></tr></thead>
<tbody>
<?php foreach ($list as $o): ?>
<tr>
<td><?= h($o['order_no']) ?></td>
<td><?= h($o['username'] ?? '游客') ?></td>
<td class="cell-items">
<?php foreach (($itemsOf[$o['id']] ?? []) as $it): ?>
<div><?= h($it['name']) ?> ×<?= (int)$it['qty'] ?></div>
<?php endforeach; ?>
</td>
<td><?= money($o['total']) ?></td>
<td><?= periodLabel($o['period_days']) ?></td>
<td><span class="pay-<?= h($o['pay_type']) ?>"><?= payTypeLabel($o['pay_type']) ?><?= $o['pay_type']==='points' ? ' · ' . (int)$o['points_used'] . '分' : '' ?></span></td>
<td><span class="badge-status status-<?= h($o['status']) ?>"><?= orderStatusLabel($o['status']) ?></span></td>
<td><?= date('m-d H:i', strtotime($o['created_at'])) ?></td>
<td class="row-actions">
<a href="orders.php?view=<?= (int)$o['id'] ?>" class="mini-btn" title="查看 / 发货"><i class="fas fa-eye"></i></a>
<form method="post" action="" style="display:inline" onsubmit="return confirm('确定删除该订单?');">
<?= csrfField() ?>
<button type="submit" name="delete" value="<?= (int)$o['id'] ?>" class="mini-btn danger" title="删除订单"><i class="fas fa-trash"></i></button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
<?php endif; ?>
<?php adminFooter(); ?>