587 lines
21 KiB
PHP
587 lines
21 KiB
PHP
<?php
|
||
// 如果未安装(没有install.lock),跳转到install.php
|
||
if (!file_exists(__DIR__ . '/install.lock') || !file_exists(__DIR__ . '/config/db_config.php')) {
|
||
header('Location: install.php');
|
||
exit;
|
||
}
|
||
|
||
require_once 'config/database.php';
|
||
require_once 'includes/utils.php';
|
||
|
||
$database = new Database();
|
||
$db = $database->getConnection();
|
||
$utils = new Utils($db);
|
||
|
||
// 初始化数据库
|
||
$database->initDatabase();
|
||
|
||
$message = '';
|
||
$message_type = '';
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$ip = Utils::getClientIP();
|
||
|
||
// 检查IP限制
|
||
if (!$utils->checkIPLimit($ip)) {
|
||
$message = '您今天的提交次数已达上限(3次),请明天再试。';
|
||
$message_type = 'error';
|
||
} else {
|
||
$submission_type = $_POST['submission_type'] ?? 'website';
|
||
|
||
if ($submission_type === 'website') {
|
||
// 网址投稿处理
|
||
$url = trim($_POST['url'] ?? '');
|
||
$title = trim($_POST['title'] ?? '');
|
||
$description = trim($_POST['description'] ?? '');
|
||
$keywords = trim($_POST['keywords'] ?? '');
|
||
$platforms = isset($_POST['platforms']) ? implode(',', $_POST['platforms']) : '';
|
||
$contact = trim($_POST['contact'] ?? '');
|
||
|
||
if (empty($url)) {
|
||
$message = '请输入网址URL。';
|
||
$message_type = 'error';
|
||
} elseif ($utils->checkWebsiteDuplicate($url)) {
|
||
$message = '该网址已存在,请勿重复提交。';
|
||
$message_type = 'error';
|
||
} else {
|
||
try {
|
||
$stmt = $db->prepare("
|
||
INSERT INTO website_submissions (url, title, description, keywords, platforms, contact, ip_address)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||
");
|
||
$stmt->execute([$url, $title, $description, $keywords, $platforms, $contact, $ip]);
|
||
|
||
$utils->recordIPSubmission($ip);
|
||
$message = '提交成功!我们会尽快审核您的内容。';
|
||
$message_type = 'success';
|
||
} catch (PDOException $e) {
|
||
$message = '提交失败,请稍后重试。';
|
||
$message_type = 'error';
|
||
}
|
||
}
|
||
} else {
|
||
// APP投稿处理
|
||
$name = trim($_POST['app_name'] ?? '');
|
||
$platform = trim($_POST['app_platform'] ?? '');
|
||
$version = trim($_POST['app_version'] ?? '');
|
||
$icon_url = trim($_POST['icon_url'] ?? '');
|
||
$download_url = trim($_POST['download_url'] ?? '');
|
||
$website_url = trim($_POST['website_url'] ?? '');
|
||
$description = trim($_POST['app_description'] ?? '');
|
||
$platforms = isset($_POST['platforms']) ? implode(',', $_POST['platforms']) : '';
|
||
$contact = trim($_POST['contact'] ?? '');
|
||
|
||
if (empty($name) || empty($platform)) {
|
||
$message = '请填写应用名称和系统平台。';
|
||
$message_type = 'error';
|
||
} elseif ($utils->checkAppDuplicate($name, $platform)) {
|
||
$message = '该应用已存在,请勿重复提交。';
|
||
$message_type = 'error';
|
||
} else {
|
||
try {
|
||
$stmt = $db->prepare("
|
||
INSERT INTO app_submissions (name, platform, version, icon_url, download_url, website_url, description, platforms, contact, ip_address)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||
");
|
||
$stmt->execute([$name, $platform, $version, $icon_url, $download_url, $website_url, $description, $platforms, $contact, $ip]);
|
||
|
||
$utils->recordIPSubmission($ip);
|
||
$message = '提交成功!我们会尽快审核您的内容。';
|
||
$message_type = 'success';
|
||
} catch (PDOException $e) {
|
||
$message = '提交失败,请稍后重试。';
|
||
$message_type = 'error';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
|
||
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>内容投稿系统</title>
|
||
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||
<link rel="stylesheet" href="mobile.css" media="only screen and (max-width: 768px)">
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
padding: 20px;
|
||
}
|
||
|
||
.container {
|
||
max-width: 800px;
|
||
margin: 0 auto;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
border-radius: 20px;
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||
overflow: hidden;
|
||
backdrop-filter: blur(10px);
|
||
}
|
||
|
||
.header {
|
||
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
|
||
color: white;
|
||
padding: 40px;
|
||
text-align: center;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 2.5rem;
|
||
font-weight: 700;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.header p {
|
||
font-size: 1.1rem;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.tab-container {
|
||
display: flex;
|
||
background: #f8fafc;
|
||
border-bottom: 1px solid #e2e8f0;
|
||
}
|
||
|
||
.tab {
|
||
flex: 1;
|
||
padding: 20px;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
font-weight: 600;
|
||
color: #64748b;
|
||
transition: all 0.3s ease;
|
||
border-bottom: 3px solid transparent;
|
||
}
|
||
|
||
.tab.active {
|
||
color: #4f46e5;
|
||
background: white;
|
||
border-bottom-color: #4f46e5;
|
||
}
|
||
|
||
.tab:hover {
|
||
background: #f1f5f9;
|
||
}
|
||
|
||
.form-container {
|
||
padding: 40px;
|
||
}
|
||
|
||
.form-section {
|
||
display: none;
|
||
}
|
||
|
||
.form-section.active {
|
||
display: block;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.form-group label {
|
||
display: block;
|
||
margin-bottom: 8px;
|
||
font-weight: 600;
|
||
color: #374151;
|
||
}
|
||
|
||
.form-group input,
|
||
.form-group textarea,
|
||
.form-group select {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
border: 2px solid #e5e7eb;
|
||
border-radius: 10px;
|
||
font-size: 16px;
|
||
transition: all 0.3s ease;
|
||
background: #fafafa;
|
||
}
|
||
|
||
.form-group input:focus,
|
||
.form-group textarea:focus,
|
||
.form-group select:focus {
|
||
outline: none;
|
||
border-color: #4f46e5;
|
||
background: white;
|
||
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
|
||
}
|
||
|
||
.form-group textarea {
|
||
resize: vertical;
|
||
min-height: 100px;
|
||
}
|
||
|
||
.checkbox-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 15px;
|
||
margin-top: 10px;
|
||
}
|
||
|
||
.checkbox-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.checkbox-item input[type="checkbox"] {
|
||
width: auto;
|
||
margin: 0;
|
||
}
|
||
|
||
.platform-warning {
|
||
margin-top: 10px;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
font-size: 14px;
|
||
display: none;
|
||
}
|
||
|
||
.platform-warning.compliance {
|
||
background: #fef3c7;
|
||
color: #92400e;
|
||
border: 1px solid #fbbf24;
|
||
}
|
||
|
||
.platform-warning.loose {
|
||
background: #dbeafe;
|
||
color: #1e40af;
|
||
border: 1px solid #60a5fa;
|
||
}
|
||
|
||
.btn-group {
|
||
display: flex;
|
||
gap: 15px;
|
||
margin-top: 30px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 12px 24px;
|
||
border: none;
|
||
border-radius: 10px;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.btn-primary {
|
||
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
|
||
color: white;
|
||
flex: 1;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 10px 20px rgba(79, 70, 229, 0.3);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #f1f5f9;
|
||
color: #64748b;
|
||
border: 2px solid #e2e8f0;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: #e2e8f0;
|
||
}
|
||
|
||
.message {
|
||
padding: 15px;
|
||
border-radius: 10px;
|
||
margin-bottom: 20px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.message.success {
|
||
background: #d1fae5;
|
||
color: #065f46;
|
||
border: 1px solid #10b981;
|
||
}
|
||
|
||
.message.error {
|
||
background: #fee2e2;
|
||
color: #991b1b;
|
||
border: 1px solid #ef4444;
|
||
}
|
||
|
||
.url-fetch {
|
||
display: flex;
|
||
gap: 10px;
|
||
align-items: end;
|
||
}
|
||
|
||
.url-fetch input {
|
||
flex: 1;
|
||
}
|
||
|
||
.url-fetch button {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.container {
|
||
margin: 10px;
|
||
border-radius: 15px;
|
||
}
|
||
|
||
.header {
|
||
padding: 30px 20px;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.form-container {
|
||
padding: 30px 20px;
|
||
}
|
||
|
||
.btn-group {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.url-fetch {
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1><i class="fas fa-paper-plane"></i> 内容投稿系统</h1>
|
||
<p>分享优质内容,共建互联网生态</p>
|
||
</div>
|
||
|
||
<div class="tab-container">
|
||
<div class="tab active" onclick="switchTab('website')">
|
||
<i class="fas fa-globe"></i> 网址投稿
|
||
</div>
|
||
<div class="tab" onclick="switchTab('app')">
|
||
<i class="fas fa-mobile-alt"></i> APP/软件投稿
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-container">
|
||
<?php if ($message): ?>
|
||
<div class="message <?php echo $message_type; ?>">
|
||
<?php echo htmlspecialchars($message); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form method="POST" id="submissionForm">
|
||
<input type="hidden" name="submission_type" id="submission_type" value="website">
|
||
|
||
<!-- 网址投稿表单 -->
|
||
<div class="form-section active" id="website-form">
|
||
<div class="form-group">
|
||
<label for="url">网址URL *</label>
|
||
<div class="url-fetch">
|
||
<input type="url" id="url" name="url" placeholder="https://example.com" required>
|
||
<button type="button" class="btn btn-secondary" onclick="fetchWebsiteInfo()">
|
||
<i class="fas fa-download"></i> 获取信息
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="title">网站名称</label>
|
||
<input type="text" id="title" name="title" placeholder="网站标题">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="description">网站描述</label>
|
||
<textarea id="description" name="description" placeholder="网站描述信息"></textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="keywords">关键词</label>
|
||
<input type="text" id="keywords" name="keywords" placeholder="关键词,用逗号分隔">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- APP投稿表单 -->
|
||
<div class="form-section" id="app-form">
|
||
<div class="form-group">
|
||
<label for="app_name">应用名称 *</label>
|
||
<input type="text" id="app_name" name="app_name" placeholder="应用名称">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="app_platform">系统平台 *</label>
|
||
<select id="app_platform" name="app_platform">
|
||
<option value="">请选择平台</option>
|
||
<option value="Windows">Windows</option>
|
||
<option value="macOS">macOS</option>
|
||
<option value="Linux">Linux</option>
|
||
<option value="Android">Android</option>
|
||
<option value="iOS">iOS</option>
|
||
<option value="Web">Web应用</option>
|
||
<option value="跨平台">跨平台</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="app_version">版本号</label>
|
||
<input type="text" id="app_version" name="app_version" placeholder="v1.0.0">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="icon_url">图标地址</label>
|
||
<input type="url" id="icon_url" name="icon_url" placeholder="https://example.com/icon.png">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="download_url">下载链接</label>
|
||
<input type="url" id="download_url" name="download_url" placeholder="https://example.com/download">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="website_url">官网/落地页</label>
|
||
<input type="url" id="website_url" name="website_url" placeholder="https://example.com">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="app_description">应用描述</label>
|
||
<textarea id="app_description" name="app_description" placeholder="应用功能描述"></textarea>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 公共字段 -->
|
||
<div class="form-group">
|
||
<label>收录平台</label>
|
||
<div class="checkbox-group">
|
||
<div class="checkbox-item">
|
||
<input type="checkbox" id="platform1" name="platforms[]" value="自媒体维基" onchange="checkPlatforms()">
|
||
<label for="platform1">自媒体维基</label>
|
||
</div>
|
||
<div class="checkbox-item">
|
||
<input type="checkbox" id="platform2" name="platforms[]" value="zTab" onchange="checkPlatforms()">
|
||
<label for="platform2">zTab</label>
|
||
</div>
|
||
<div class="checkbox-item">
|
||
<input type="checkbox" id="platform3" name="platforms[]" value="SOSO" onchange="checkPlatforms()">
|
||
<label for="platform3">SOSO</label>
|
||
</div>
|
||
</div>
|
||
<div class="platform-warning compliance" id="compliance-warning">
|
||
<i class="fas fa-exclamation-triangle"></i> 提醒:自媒体维基和zTab平台需要合法合规的内容,请确保您提交的内容符合相关法律法规。
|
||
</div>
|
||
<div class="platform-warning loose" id="loose-warning">
|
||
<i class="fas fa-info-circle"></i> 提醒:SOSO平台内容审查相对宽松,但仍需遵守基本的网络道德规范。
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="contact">联系方式(可选)</label>
|
||
<input type="text" id="contact" name="contact" placeholder="邮箱或其他联系方式">
|
||
</div>
|
||
|
||
<div class="btn-group">
|
||
<button type="submit" class="btn btn-primary">
|
||
<i class="fas fa-paper-plane"></i> 提交投稿
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function switchTab(type) {
|
||
// 切换标签
|
||
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
|
||
event.target.closest('.tab').classList.add('active');
|
||
|
||
// 切换表单
|
||
document.querySelectorAll('.form-section').forEach(section => section.classList.remove('active'));
|
||
document.getElementById(type + '-form').classList.add('active');
|
||
|
||
// 更新提交类型
|
||
document.getElementById('submission_type').value = type;
|
||
|
||
// 更新必填字段
|
||
updateRequiredFields(type);
|
||
}
|
||
|
||
function updateRequiredFields(type) {
|
||
// 清除所有必填
|
||
document.querySelectorAll('input[required], select[required]').forEach(field => {
|
||
field.removeAttribute('required');
|
||
});
|
||
|
||
if (type === 'website') {
|
||
document.getElementById('url').setAttribute('required', 'required');
|
||
} else {
|
||
document.getElementById('app_name').setAttribute('required', 'required');
|
||
document.getElementById('app_platform').setAttribute('required', 'required');
|
||
}
|
||
}
|
||
|
||
function checkPlatforms() {
|
||
const compliance = document.querySelectorAll('#platform1:checked, #platform2:checked').length > 0;
|
||
const loose = document.querySelector('#platform3:checked');
|
||
|
||
document.getElementById('compliance-warning').style.display = compliance ? 'block' : 'none';
|
||
document.getElementById('loose-warning').style.display = loose ? 'block' : 'none';
|
||
}
|
||
|
||
async function fetchWebsiteInfo() {
|
||
const url = document.getElementById('url').value;
|
||
if (!url) {
|
||
alert('请先输入网址');
|
||
return;
|
||
}
|
||
|
||
const button = event.target;
|
||
const originalText = button.innerHTML;
|
||
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 获取中...';
|
||
button.disabled = true;
|
||
|
||
try {
|
||
const response = await fetch('api/fetch_website_info.php', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ url: url })
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.success) {
|
||
document.getElementById('title').value = data.title || '';
|
||
document.getElementById('description').value = data.description || '';
|
||
document.getElementById('keywords').value = data.keywords || '';
|
||
} else {
|
||
alert('获取网站信息失败,请手动填写');
|
||
}
|
||
} catch (error) {
|
||
alert('获取网站信息失败,请手动填写');
|
||
} finally {
|
||
button.innerHTML = originalText;
|
||
button.disabled = false;
|
||
}
|
||
}
|
||
|
||
// 初始化
|
||
updateRequiredFields('website');
|
||
</script>
|
||
</body>
|
||
</html>
|