Files
Demo1/index.php
2025-11-15 17:37:48 +08:00

511 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Git文件上传工具
* 支持JS和CSS分离文件上传无限制
*/
// 设置上传限制
ini_set('upload_max_filesize', '0');
ini_set('post_max_size', '0');
ini_set('max_execution_time', '0');
ini_set('memory_limit', '-1');
// 获取当前目录
$currentDir = __DIR__;
$gitDir = $currentDir . '/.git';
$remoteConfigFile = $currentDir . '/.git_remote_config.json';
// 检查Git仓库是否存在
function checkGitRepo() {
global $gitDir;
return is_dir($gitDir);
}
// 初始化Git仓库
function initGitRepo() {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git init', $output, $returnCode);
return $returnCode === 0;
} catch (Exception $e) {
return false;
}
}
// 获取文件列表
function getFileList($dir = '.') {
$files = [];
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
if ($file->isFile() && !strpos($file->getPathname(), '.git')) {
$relativePath = str_replace('\\', '/', substr($file->getPathname(), strlen(__DIR__) + 1));
$files[] = $relativePath;
}
}
return $files;
}
// 处理文件上传
function handleFileUpload($files) {
$uploadedFiles = [];
if (!isset($files['files']) || empty($files['files']['name'][0])) {
return ['success' => false, 'message' => '没有选择文件'];
}
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
$fileCount = count($files['files']['name']);
for ($i = 0; $i < $fileCount; $i++) {
if ($files['files']['error'][$i] === UPLOAD_ERR_OK) {
$tmpName = $files['files']['tmp_name'][$i];
$fileName = basename($files['files']['name'][$i]);
$uploadPath = $uploadDir . $fileName;
// 移动上传的文件
if (move_uploaded_file($tmpName, $uploadPath)) {
$uploadedFiles[] = $fileName;
}
}
}
return ['success' => true, 'files' => $uploadedFiles];
}
// 获取远程仓库配置
function getRemoteConfig() {
global $remoteConfigFile;
if (file_exists($remoteConfigFile)) {
$config = json_decode(file_get_contents($remoteConfigFile), true);
return $config ?: ['remotes' => []];
}
return ['remotes' => []];
}
// 保存远程仓库配置
function saveRemoteConfig($config) {
global $remoteConfigFile;
return file_put_contents($remoteConfigFile, json_encode($config, JSON_PRETTY_PRINT));
}
// 添加远程仓库
function addRemote($name, $url) {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git remote add ' . escapeshellarg($name) . ' ' . escapeshellarg($url), $output, $returnCode);
if ($returnCode === 0) {
// 保存到配置文件
$config = getRemoteConfig();
$config['remotes'][$name] = $url;
saveRemoteConfig($config);
return ['success' => true, 'message' => '远程仓库添加成功'];
} else {
return ['success' => false, 'message' => '远程仓库添加失败'];
}
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 获取远程仓库列表
function getRemotes() {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git remote -v', $output, $returnCode);
$remotes = [];
foreach ($output as $line) {
if (preg_match('/^(\S+)\s+(\S+)\s+\((\w+)\)/', $line, $matches)) {
$remotes[$matches[1]] = [
'url' => $matches[2],
'type' => $matches[3]
];
}
}
return ['success' => true, 'remotes' => $remotes];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 推送代码到指定远程仓库
function pushToRemote($remote = 'origin', $branch = 'main') {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git push ' . escapeshellarg($remote) . ' ' . escapeshellarg($branch), $output, $returnCode);
return ['success' => $returnCode === 0, 'output' => $output];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 获取分支列表
function getBranches() {
global $currentDir;
try {
$output = [];
$returnCode = 0;
// 获取本地分支
exec('cd "' . $currentDir . '" && git branch -a', $output, $returnCode);
$branches = [];
$currentBranch = '';
foreach ($output as $line) {
$line = trim($line);
if (empty($line)) continue;
// 检查是否是当前分支
if (strpos($line, '*') === 0) {
$currentBranch = trim(substr($line, 1));
$branches[] = [
'name' => $currentBranch,
'current' => true,
'remote' => false
];
} else {
// 检查是否是远程分支
$isRemote = strpos($line, 'remotes/') !== false;
$branchName = $isRemote ? substr($line, strpos($line, 'remotes/') + 8) : $line;
$branches[] = [
'name' => trim($branchName),
'current' => false,
'remote' => $isRemote
];
}
}
return ['success' => true, 'branches' => $branches, 'current' => $currentBranch];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 创建新分支
function createBranch($branchName) {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git checkout -b ' . escapeshellarg($branchName), $output, $returnCode);
if ($returnCode === 0) {
return ['success' => true, 'message' => '分支创建成功', 'output' => $output];
} else {
return ['success' => false, 'message' => '分支创建失败', 'output' => $output];
}
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 删除分支
function deleteBranch($branchName, $force = false) {
global $currentDir;
try {
$forceFlag = $force ? '-D' : '-d';
exec('cd "' . $currentDir . '" && git branch ' . $forceFlag . ' ' . escapeshellarg($branchName), $output, $returnCode);
if ($returnCode === 0) {
return ['success' => true, 'message' => '分支删除成功', 'output' => $output];
} else {
return ['success' => false, 'message' => '分支删除失败', 'output' => $output];
}
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 切换分支
function switchBranch($branchName) {
global $currentDir;
try {
exec('cd "' . $currentDir . '" && git checkout ' . escapeshellarg($branchName), $output, $returnCode);
if ($returnCode === 0) {
return ['success' => true, 'message' => '分支切换成功', 'output' => $output];
} else {
return ['success' => false, 'message' => '分支切换失败', 'output' => $output];
}
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 处理Git操作
function handleGitOperation($operation, $message = '', $files = [], $remote = 'origin', $branch = 'main') {
global $currentDir;
try {
$output = [];
$returnCode = 0;
switch ($operation) {
case 'status':
exec('cd "' . $currentDir . '" && git status --porcelain', $output, $returnCode);
break;
case 'add':
if (!empty($files)) {
foreach ($files as $file) {
exec('cd "' . $currentDir . '" && git add "' . $file . '"', $output, $returnCode);
}
} else {
exec('cd "' . $currentDir . '" && git add .', $output, $returnCode);
}
break;
case 'commit':
if (empty($message)) {
$message = '自动提交';
}
exec('cd "' . $currentDir . '" && git commit -m "' . addslashes($message) . '"', $output, $returnCode);
break;
case 'push':
// 使用新的推送函数,支持指定远程仓库和分支
return pushToRemote($remote, $branch);
case 'log':
exec('cd "' . $currentDir . '" && git log --oneline -10', $output, $returnCode);
break;
}
return ['success' => $returnCode === 0, 'output' => $output];
} catch (Exception $e) {
return ['success' => false, 'message' => $e->getMessage()];
}
}
// 处理AJAX请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
header('Content-Type: application/json; charset=utf-8');
$action = $_POST['action'] ?? '';
switch ($action) {
case 'upload':
$result = handleFileUpload($_FILES);
echo json_encode($result);
break;
case 'git_operation':
$operation = $_POST['operation'] ?? '';
$message = $_POST['message'] ?? '';
$files = $_POST['files'] ?? [];
$remote = $_POST['remote'] ?? 'origin';
$branch = $_POST['branch'] ?? 'main';
$result = handleGitOperation($operation, $message, $files, $remote, $branch);
echo json_encode($result);
break;
case 'add_remote':
$name = $_POST['name'] ?? '';
$url = $_POST['url'] ?? '';
if (empty($name) || empty($url)) {
echo json_encode(['success' => false, 'message' => '远程仓库名称和地址不能为空']);
} else {
$result = addRemote($name, $url);
echo json_encode($result);
}
break;
case 'get_remotes':
$result = getRemotes();
echo json_encode($result);
break;
case 'get_branches':
$result = getBranches();
echo json_encode($result);
break;
case 'create_branch':
$branchName = $_POST['branch_name'] ?? '';
if (empty($branchName)) {
echo json_encode(['success' => false, 'message' => '分支名称不能为空']);
} else {
$result = createBranch($branchName);
echo json_encode($result);
}
break;
case 'delete_branch':
$branchName = $_POST['branch_name'] ?? '';
$force = isset($_POST['force']) && $_POST['force'] === 'true';
if (empty($branchName)) {
echo json_encode(['success' => false, 'message' => '分支名称不能为空']);
} else {
$result = deleteBranch($branchName, $force);
echo json_encode($result);
}
break;
case 'switch_branch':
$branchName = $_POST['branch_name'] ?? '';
if (empty($branchName)) {
echo json_encode(['success' => false, 'message' => '分支名称不能为空']);
} else {
$result = switchBranch($branchName);
echo json_encode($result);
}
break;
case 'get_files':
$files = getFileList();
echo json_encode(['success' => true, 'files' => $files]);
break;
case 'check_git':
echo json_encode(['success' => true, 'hasGit' => checkGitRepo()]);
break;
case 'init_git':
$success = initGitRepo();
echo json_encode(['success' => $success]);
break;
default:
echo json_encode(['success' => false, 'message' => '未知操作']);
}
exit;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Git文件上传工具</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>Git文件上传工具</h1>
<div class="git-status" id="gitStatus">
<span class="status-indicator" id="gitIndicator"></span>
<span id="gitStatusText">检查Git状态...</span>
</div>
</header>
<main>
<!-- 文件上传区域 -->
<section class="upload-section">
<h2>文件上传</h2>
<div class="upload-area" id="uploadArea">
<div class="upload-placeholder">
<svg class="upload-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
</svg>
<p>拖拽文件到此处或点击选择文件</p>
<p class="upload-hint">支持任意大小的文件,无数量限制</p>
</div>
<input type="file" id="fileInput" multiple style="display: none;">
</div>
<div class="uploaded-files" id="uploadedFiles"></div>
</section>
<!-- 文件列表 -->
<section class="files-section">
<h2>项目文件</h2>
<div class="file-controls">
<button id="refreshFiles" class="btn btn-secondary">刷新文件列表</button>
<button id="selectAllFiles" class="btn btn-secondary">全选</button>
<button id="deselectAllFiles" class="btn btn-secondary">取消全选</button>
</div>
<div class="file-list" id="fileList">
<div class="loading">加载文件中...</div>
</div>
</section>
<!-- Git操作区域 -->
<section class="git-section">
<h2>Git操作</h2>
<!-- 分支管理 -->
<div class="branch-config">
<h3>分支管理</h3>
<div class="form-group">
<label for="branchSelect">当前分支:</label>
<select id="branchSelect" class="form-control">
<option value="">加载分支中...</option>
</select>
</div>
<div class="form-group">
<label for="newBranchName">新分支名称:</label>
<input type="text" id="newBranchName" placeholder="输入新分支名称">
</div>
<div class="button-group">
<button id="createBranch" class="btn btn-success">创建分支</button>
<button id="switchBranch" class="btn btn-primary">切换分支</button>
<button id="deleteBranch" class="btn btn-danger">删除分支</button>
<button id="refreshBranches" class="btn btn-secondary">刷新分支</button>
</div>
</div>
<hr style="margin: 20px 0;">
<!-- 远程仓库配置 -->
<div class="remote-config">
<h3>远程仓库配置</h3>
<div class="form-group">
<label for="remoteName">远程仓库名称:</label>
<input type="text" id="remoteName" placeholder="例如: origin" value="origin">
</div>
<div class="form-group">
<label for="remoteUrl">仓库地址:</label>
<input type="text" id="remoteUrl" placeholder="例如: https://github.com/username/repo.git">
</div>
<button id="addRemote" class="btn btn-info">添加远程仓库</button>
<button id="showRemotes" class="btn btn-secondary">查看远程仓库</button>
<div class="remote-list" id="remoteList"></div>
</div>
<hr style="margin: 20px 0;">
<div class="git-controls">
<div class="form-group">
<label for="commitMessage">提交信息:</label>
<input type="text" id="commitMessage" placeholder="输入提交信息..." value="自动提交">
</div>
<div class="button-group">
<button id="gitAdd" class="btn btn-primary">添加到暂存区</button>
<button id="gitCommit" class="btn btn-success">提交更改</button>
<button id="gitPush" class="btn btn-warning">推送到远程</button>
<button id="gitStatusBtn" class="btn btn-info">查看状态</button>
<button id="gitLog" class="btn btn-secondary">查看日志</button>
</div>
</div>
<div class="git-output" id="gitOutput"></div>
</section>
</main>
</div>
<script src="js/main.js"></script>
</body>
</html>