初始提交

This commit is contained in:
2025-11-15 17:37:48 +08:00
commit ec563fc407
7 changed files with 2162 additions and 0 deletions

511
index.php Normal file
View File

@@ -0,0 +1,511 @@
<?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>