This commit is contained in:
nanguaboss
2026-08-03 00:07:01 +08:00
commit 71c6e8d9c1
112 changed files with 7815 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
<?php
/**
* 文件删除接口(同时删除物理文件) POST /api/document/delete.php
* 入参:id(或 ids 逗号分隔批量)
*/
require_once __DIR__ . '/../common/db.php';
require_once __DIR__ . '/../common/response.php';
require_once __DIR__ . '/../common/auth.php';
require_once __DIR__ . '/../common/logger.php';
checkAjax();
checkPermission('document');
$id = (int)($_POST['id'] ?? 0);
$ids = trim($_POST['ids'] ?? '');
$idList = [];
if ($id > 0) $idList[] = $id;
if ($ids !== '') {
foreach (explode(',', $ids) as $v) {
$v = (int)trim($v);
if ($v > 0) $idList[] = $v;
}
}
$idList = array_unique($idList);
if (!$idList) {
Response::error('参数错误', 400);
}
$pdo = DB::getInstance()->getPdo();
$in = implode(',', array_fill(0, count($idList), '?'));
// 取出物理路径
$stmt = $pdo->prepare("SELECT id, storage_path FROM company_documents WHERE id IN ($in)");
$stmt->execute($idList);
$docs = $stmt->fetchAll();
// 删除物理文件(仅限本站上传目录内的文件)
foreach ($docs as $doc) {
$path = $doc['storage_path'];
if (strpos($path, 'static/uploads/documents/') === 0) {
$full = __DIR__ . '/../../' . $path;
if (is_file($full)) {
@unlink($full);
}
}
}
// 删除记录(document_links 级联删除)
$del = $pdo->prepare("DELETE FROM company_documents WHERE id IN ($in)");
$del->execute($idList);
$affected = $del->rowCount();
logCurrent('delete', 'document', 'company_documents', null, ['ids' => $idList]);
Response::success(['affected' => $affected], "已删除 $affected 个文件(含物理文件)");
+49
View File
@@ -0,0 +1,49 @@
<?php
/**
* 文件列表接口 GET/POST /api/document/list.php
* 参数:page / limit / keyword / file_type / is_active
* 数据源:company_documents 表
*/
require_once __DIR__ . '/../common/db.php';
require_once __DIR__ . '/../common/response.php';
require_once __DIR__ . '/../common/auth.php';
checkPermission('document');
[$page, $limit] = pageParams();
$keyword = trim($_REQUEST['keyword'] ?? '');
$fileType = trim($_REQUEST['file_type'] ?? '');
$active = isset($_REQUEST['is_active']) && $_REQUEST['is_active'] !== '' ? (int)$_REQUEST['is_active'] : null;
$where = ['is_active = 1'];
$params = [];
if ($active !== null) {
$where = ['is_active = ?'];
$params = [$active];
}
if ($keyword !== '') {
$where[] = '(doc_name LIKE ? OR document_source LIKE ?)';
$like = "%$keyword%";
array_push($params, $like, $like);
}
if ($fileType !== '') { $where[] = 'file_type = ?'; $params[] = $fileType; }
$whereSql = implode(' AND ', $where);
$pdo = DB::getInstance()->getPdo();
$stmt = $pdo->prepare("SELECT COUNT(*) FROM company_documents WHERE $whereSql");
$stmt->execute($params);
$total = (int)$stmt->fetchColumn();
$offset = ($page - 1) * $limit;
$stmt = $pdo->prepare(
"SELECT id, doc_name, storage_path, file_type, is_current, publish_date, document_source, tags, is_active, created_at
FROM company_documents
WHERE $whereSql
ORDER BY id DESC
LIMIT $limit OFFSET $offset"
);
$stmt->execute($params);
$list = $stmt->fetchAll();
Response::success(['list' => $list, 'total' => $total, 'page' => $page, 'limit' => $limit]);
+75
View File
@@ -0,0 +1,75 @@
<?php
/**
* 文件上传接口 POST /api/document/upload.php (multipart/form-data, 字段名 file)
* 可选:doc_name(默认取原文件名)/ tags(JSON)
* 存储:static/uploads/documents/年/月/随机文件名
* 返回:相对路径 storage_path
*/
require_once __DIR__ . '/../common/db.php';
require_once __DIR__ . '/../common/response.php';
require_once __DIR__ . '/../common/auth.php';
require_once __DIR__ . '/../common/logger.php';
checkAjax();
checkPermission('document');
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
Response::error('请选择要上传的文件', 400);
}
$file = $_FILES['file'];
$maxSize = 50 * 1024 * 1024; // 50MB
if ($file['size'] > $maxSize) {
Response::error('文件不能超过50MB', 400);
}
// 安全扩展名白名单
$extMap = [
'pdf' => 'application/pdf', 'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'ppt' => 'application/vnd.ms-powerpoint',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'txt' => 'text/plain', 'csv' => 'text/csv', 'png' => 'image/png',
'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif',
'zip' => 'application/zip', 'rar' => 'application/x-rar-compressed',
];
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!isset($extMap[$ext])) {
Response::error('不允许的文件类型:' . ($ext !== '' ? $ext : '无扩展名'), 400);
}
// 目录:static/uploads/documents/年/月
$baseDir = __DIR__ . '/../../static/uploads/documents';
$subDir = date('Y') . '/' . date('m');
$dir = $baseDir . '/' . $subDir;
if (!is_dir($dir) && !mkdir($dir, 0777, true)) {
Response::error('创建上传目录失败', 500);
}
$newName = date('YmdHis') . '_' . substr(uniqid(), -6) . '.' . $ext;
$dest = $dir . '/' . $newName;
if (!move_uploaded_file($file['tmp_name'], $dest)) {
Response::error('文件保存失败', 500);
}
$storagePath = 'static/uploads/documents/' . $subDir . '/' . $newName;
$docName = trim($_POST['doc_name'] ?? '') !== '' ? trim($_POST['doc_name']) : $file['name'];
$tags = $_POST['tags'] ?? null;
$tagsJson = null;
if ($tags !== null && $tags !== '') {
$decoded = json_decode($tags, true);
$tagsJson = is_array($decoded) ? json_encode($decoded, JSON_UNESCAPED_UNICODE) : null;
}
$pdo = DB::getInstance()->getPdo();
$stmt = $pdo->prepare(
"INSERT INTO company_documents (doc_name, storage_path, file_type, is_current, document_source, tags)
VALUES (?, ?, ?, 1, ?, ?)"
);
$stmt->execute([$docName, $storagePath, $extMap[$ext], '本地上传', $tagsJson]);
$newId = (int)$pdo->lastInsertId();
logCurrent('upload', 'document', 'company_documents', $newId, ['doc_name' => $docName, 'storage_path' => $storagePath]);
Response::success(['id' => $newId, 'storage_path' => $storagePath, 'doc_name' => $docName], '上传成功');