美化packages.php界面:1)添加了套餐卡片网格布局;2)优化了表单样式和按钮设计;3)增强了套餐卡片的视觉层次;4)改进了空状态显示;5)添加了响应式设计支持
This commit is contained in:
+123
-115
@@ -82,19 +82,19 @@ $packages = $stmt->fetchAll();
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="package-form-container">
|
||||
<div class="package-form-container card">
|
||||
<h2>添加新套餐</h2>
|
||||
<form method="POST" class="form">
|
||||
<input type="hidden" name="action" value="add">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="package_name">套餐名称:</label>
|
||||
<input type="text" id="package_name" name="package_name" required>
|
||||
<input type="text" id="package_name" name="package_name" required placeholder="请输入套餐名称">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">套餐描述:</label>
|
||||
<textarea id="description" name="description" rows="3"></textarea>
|
||||
<textarea id="description" name="description" rows="3" placeholder="请输入套餐描述"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
@@ -105,7 +105,7 @@ $packages = $stmt->fetchAll();
|
||||
|
||||
<div class="form-group">
|
||||
<label for="price">价格(元):</label>
|
||||
<input type="number" id="price" name="price" min="0" step="0.01" required>
|
||||
<input type="number" id="price" name="price" min="0" step="0.01" required placeholder="请输入套餐价格">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -114,18 +114,18 @@ $packages = $stmt->fetchAll();
|
||||
<div class="services-container">
|
||||
<div class="service-item">
|
||||
<input type="text" name="services[]" placeholder="服务项目1" value="外观清洗">
|
||||
<button type="button" class="btn-remove" onclick="removeService(this)">删除</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" onclick="removeService(this)">删除</button>
|
||||
</div>
|
||||
<div class="service-item">
|
||||
<input type="text" name="services[]" placeholder="服务项目2" value="内饰清洁">
|
||||
<button type="button" class="btn-remove" onclick="removeService(this)">删除</button>
|
||||
<button type="button" class="btn btn-danger btn-sm" onclick="removeService(this)">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-add" onclick="addService()">+ 添加服务项目</button>
|
||||
<button type="button" class="btn btn-outline btn-sm" onclick="addService()">+ 添加服务项目</button>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">添加套餐</button>
|
||||
<button type="submit" class="btn btn-primary btn-lg">添加套餐</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -133,120 +133,128 @@ $packages = $stmt->fetchAll();
|
||||
<div class="packages-list">
|
||||
<h2>套餐列表</h2>
|
||||
<?php if (empty($packages)): ?>
|
||||
<p class="empty-message">暂无套餐数据</p>
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">📦</div>
|
||||
<p class="empty-message">暂无套餐数据</p>
|
||||
<p class="empty-submessage">点击上方"添加套餐"按钮创建第一个套餐吧!</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($packages as $package): ?>
|
||||
<div class="package-card <?= $package['is_active'] ? '' : 'inactive' ?>">
|
||||
<div class="package-header">
|
||||
<h3><?= htmlspecialchars($package['package_name']) ?></h3>
|
||||
<div class="package-status">
|
||||
<span class="status-badge <?= $package['is_active'] ? 'active' : 'inactive' ?>">
|
||||
<?= $package['is_active'] ? '启用' : '禁用' ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($package['description']): ?>
|
||||
<p class="package-description"><?= htmlspecialchars($package['description']) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="package-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">基础时长:</span>
|
||||
<span class="detail-value"><?= $package['base_duration'] ?>分钟</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">价格:</span>
|
||||
<span class="detail-value">¥<?= number_format($package['price'], 2) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$services = explode(',', $package['services']);
|
||||
if ($services && !empty(trim($services[0]))):
|
||||
?>
|
||||
<div class="package-services">
|
||||
<span class="detail-label">包含服务:</span>
|
||||
<div class="services-tags">
|
||||
<?php foreach ($services as $service): ?>
|
||||
<?php if (trim($service)): ?>
|
||||
<span class="service-tag"><?= htmlspecialchars(trim($service)) ?></span>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<div class="packages-grid">
|
||||
<?php foreach ($packages as $package): ?>
|
||||
<div class="package-card card <?= $package['is_active'] ? '' : 'inactive' ?>">
|
||||
<div class="package-header">
|
||||
<h3 class="package-title"><?= htmlspecialchars($package['package_name']) ?></h3>
|
||||
<div class="package-status">
|
||||
<span class="status-badge <?= $package['is_active'] ? 'active' : 'inactive' ?>">
|
||||
<?= $package['is_active'] ? '启用' : '禁用' ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($package['description']): ?>
|
||||
<p class="package-description"><?= htmlspecialchars($package['description']) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="package-actions">
|
||||
<button class="btn btn-sm" onclick="editPackage(<?= $package['id'] ?>)">编辑</button>
|
||||
<form method="POST" style="display: inline;" onsubmit="return confirmDelete()">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<div class="package-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">基础时长:</span>
|
||||
<span class="detail-value"><strong><?= $package['base_duration'] ?></strong>分钟</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">价格:</span>
|
||||
<span class="detail-value price"><strong>¥<?= number_format($package['price'], 2) ?></strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$services = explode(',', $package['services']);
|
||||
if ($services && !empty(trim($services[0]))):
|
||||
?>
|
||||
<div class="package-services">
|
||||
<span class="detail-label">包含服务:</span>
|
||||
<div class="services-tags">
|
||||
<?php foreach ($services as $service): ?>
|
||||
<?php if (trim($service)): ?>
|
||||
<span class="service-tag"><?= htmlspecialchars(trim($service)) ?></span>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="package-actions">
|
||||
<button class="btn btn-primary btn-sm" onclick="editPackage(<?= $package['id'] ?>">编辑</button>
|
||||
<form method="POST" style="display: inline;" onsubmit="return confirmDelete()">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="id" value="<?= $package['id'] ?>">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 编辑表单 -->
|
||||
<form method="POST" class="edit-form card" id="edit-form-<?= $package['id'] ?>" style="display: none;">
|
||||
<input type="hidden" name="action" value="update">
|
||||
<input type="hidden" name="id" value="<?= $package['id'] ?>">
|
||||
<button type="submit" class="btn btn-danger btn-sm">删除</button>
|
||||
|
||||
<h4>编辑套餐</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label>套餐名称:</label>
|
||||
<input type="text" name="package_name" value="<?= htmlspecialchars($package['package_name']) ?>" required placeholder="请输入套餐名称">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>套餐描述:</label>
|
||||
<textarea name="description" rows="2" placeholder="请输入套餐描述"><?= htmlspecialchars($package['description']) ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>基础时长(分钟):</label>
|
||||
<input type="number" name="base_duration" min="15" step="15" value="<?= $package['base_duration'] ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>价格(元):</label>
|
||||
<input type="number" name="price" min="0" step="0.01" value="<?= $package['price'] ?>" required placeholder="请输入套餐价格">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>服务项目:</label>
|
||||
<div class="services-container">
|
||||
<?php
|
||||
$services = explode(',', $package['services']);
|
||||
foreach ($services as $service):
|
||||
if (trim($service)):
|
||||
?>
|
||||
<div class="service-item">
|
||||
<input type="text" name="services[]" value="<?= htmlspecialchars(trim($service)) ?>">
|
||||
<button type="button" class="btn btn-danger btn-sm" onclick="removeService(this)">删除</button>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
endforeach;
|
||||
?>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline btn-sm" onclick="addService()">+ 添加服务项目</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" name="is_active" <?= $package['is_active'] ? 'checked' : '' ?>>
|
||||
<span class="checkbox-text">启用此套餐</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">保存更改</button>
|
||||
<button type="button" class="btn btn-outline" onclick="cancelEdit(<?= $package['id'] ?>)">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 编辑表单 -->
|
||||
<form method="POST" class="edit-form" id="edit-form-<?= $package['id'] ?>" style="display: none;">
|
||||
<input type="hidden" name="action" value="update">
|
||||
<input type="hidden" name="id" value="<?= $package['id'] ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>套餐名称:</label>
|
||||
<input type="text" name="package_name" value="<?= htmlspecialchars($package['package_name']) ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>套餐描述:</label>
|
||||
<textarea name="description" rows="2"><?= htmlspecialchars($package['description']) ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>基础时长(分钟):</label>
|
||||
<input type="number" name="base_duration" min="15" step="15" value="<?= $package['base_duration'] ?>" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>价格(元):</label>
|
||||
<input type="number" name="price" min="0" step="0.01" value="<?= $package['price'] ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>服务项目:</label>
|
||||
<div class="services-container">
|
||||
<?php
|
||||
$services = explode(',', $package['services']);
|
||||
foreach ($services as $service):
|
||||
if (trim($service)):
|
||||
?>
|
||||
<div class="service-item">
|
||||
<input type="text" name="services[]" value="<?= htmlspecialchars(trim($service)) ?>">
|
||||
<button type="button" class="btn-remove" onclick="removeService(this)">删除</button>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
endforeach;
|
||||
?>
|
||||
</div>
|
||||
<button type="button" class="btn-add" onclick="addService()">+ 添加服务项目</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" name="is_active" <?= $package['is_active'] ? 'checked' : '' ?>>
|
||||
启用此套餐
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">保存更改</button>
|
||||
<button type="button" class="btn" onclick="cancelEdit(<?= $package['id'] ?>)">取消</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1124,4 +1124,290 @@ label {
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--el-text-secondary);
|
||||
}
|
||||
|
||||
/* 套餐管理页面样式 */
|
||||
.package-form-container {
|
||||
margin-bottom: var(--el-spacing-extra-large);
|
||||
}
|
||||
|
||||
.package-form-container h2,
|
||||
.packages-list h2 {
|
||||
margin: 0 0 var(--el-spacing-large) 0;
|
||||
font-size: var(--el-font-size-large);
|
||||
font-weight: 600;
|
||||
color: var(--el-text-primary);
|
||||
padding-bottom: var(--el-spacing-base);
|
||||
border-bottom: 1px solid var(--el-border-lighter);
|
||||
}
|
||||
|
||||
/* 套餐卡片网格布局 */
|
||||
.packages-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: var(--el-spacing-large);
|
||||
margin-top: var(--el-spacing-large);
|
||||
}
|
||||
|
||||
/* 套餐卡片样式 */
|
||||
.package-card {
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.package-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--el-shadow-dark);
|
||||
}
|
||||
|
||||
.package-card.inactive {
|
||||
opacity: 0.7;
|
||||
border: 1px dashed var(--el-border-color);
|
||||
}
|
||||
|
||||
.package-card.inactive::before {
|
||||
content: '已禁用';
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: -30px;
|
||||
background: var(--el-danger-color);
|
||||
color: white;
|
||||
padding: 4px 32px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
transform: rotate(45deg);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.package-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: var(--el-spacing-base);
|
||||
}
|
||||
|
||||
.package-title {
|
||||
margin: 0;
|
||||
font-size: var(--el-font-size-large);
|
||||
font-weight: 600;
|
||||
color: var(--el-text-primary);
|
||||
flex: 1;
|
||||
margin-right: var(--el-spacing-base);
|
||||
}
|
||||
|
||||
.package-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 8px;
|
||||
border-radius: var(--el-border-radius-round);
|
||||
font-size: var(--el-font-size-extra-small);
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.status-badge.active {
|
||||
background: rgba(103, 194, 58, 0.1);
|
||||
color: var(--el-success-color);
|
||||
}
|
||||
|
||||
.status-badge.inactive {
|
||||
background: rgba(245, 108, 108, 0.1);
|
||||
color: var(--el-danger-color);
|
||||
}
|
||||
|
||||
.package-description {
|
||||
margin: 0 0 var(--el-spacing-base) 0;
|
||||
color: var(--el-text-secondary);
|
||||
font-size: var(--el-font-size-small);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.package-details {
|
||||
margin: var(--el-spacing-base) 0;
|
||||
padding: var(--el-spacing-base);
|
||||
background: var(--el-bg-color-page);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--el-spacing-small);
|
||||
font-size: var(--el-font-size-small);
|
||||
}
|
||||
|
||||
.detail-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: var(--el-text-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
color: var(--el-text-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.detail-value.price {
|
||||
color: var(--el-danger-color);
|
||||
font-size: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
/* 服务项目标签 */
|
||||
.package-services {
|
||||
margin: var(--el-spacing-base) 0;
|
||||
}
|
||||
|
||||
.package-services .detail-label {
|
||||
display: block;
|
||||
margin-bottom: var(--el-spacing-small);
|
||||
font-size: var(--el-font-size-small);
|
||||
}
|
||||
|
||||
.services-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--el-spacing-small);
|
||||
}
|
||||
|
||||
.service-tag {
|
||||
background: var(--el-border-extra-light);
|
||||
color: var(--el-text-regular);
|
||||
padding: 4px 12px;
|
||||
border-radius: var(--el-border-radius-round);
|
||||
font-size: var(--el-font-size-extra-small);
|
||||
font-weight: 500;
|
||||
border: 1px solid var(--el-border-lighter);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.service-tag:hover {
|
||||
background: var(--el-primary-light);
|
||||
color: var(--el-primary-color);
|
||||
border-color: var(--el-primary-light);
|
||||
}
|
||||
|
||||
/* 套餐操作按钮 */
|
||||
.package-actions {
|
||||
margin-top: var(--el-spacing-base);
|
||||
display: flex;
|
||||
gap: var(--el-spacing-small);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: var(--el-spacing-extra-large) 0;
|
||||
background: var(--el-bg-color);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
box-shadow: var(--el-shadow-light);
|
||||
margin-top: var(--el-spacing-large);
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: var(--el-spacing-base);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-message {
|
||||
font-size: var(--el-font-size-large);
|
||||
font-weight: 600;
|
||||
color: var(--el-text-secondary);
|
||||
margin: 0 0 var(--el-spacing-small) 0;
|
||||
}
|
||||
|
||||
.empty-submessage {
|
||||
font-size: var(--el-font-size-base);
|
||||
color: var(--el-text-placeholder);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 编辑表单样式 */
|
||||
.edit-form {
|
||||
margin-top: var(--el-spacing-base);
|
||||
border-top: 2px solid var(--el-border-lighter);
|
||||
padding-top: var(--el-spacing-large);
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
.edit-form h4 {
|
||||
margin: 0 0 var(--el-spacing-base) 0;
|
||||
font-size: var(--el-font-size-base);
|
||||
font-weight: 600;
|
||||
color: var(--el-text-primary);
|
||||
}
|
||||
|
||||
/* 服务项目样式 */
|
||||
.services-container {
|
||||
margin-bottom: var(--el-spacing-small);
|
||||
}
|
||||
|
||||
.service-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--el-spacing-small);
|
||||
margin-bottom: var(--el-spacing-small);
|
||||
}
|
||||
|
||||
.service-item input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 复选框标签样式 */
|
||||
.checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox-text {
|
||||
margin-left: var(--el-spacing-small);
|
||||
color: var(--el-text-primary);
|
||||
}
|
||||
|
||||
/* 动画效果 */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.packages-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.package-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.package-status {
|
||||
margin-top: var(--el-spacing-small);
|
||||
}
|
||||
|
||||
.form-row {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.form-row .form-group {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user