代码修改

This commit is contained in:
qiuyuan 2025-11-20 18:42:27 +08:00
parent 8d345598cf
commit 1b6239b4bc

View File

@ -1,10 +1,761 @@
<!-- src/views/controlPanel/fileStore/index.vue -->
<template>
<div>
<h1>文件存储管理</h1>
<p>这个页面显示在Layout中包含侧边栏</p>
<router-link to="/" style="color: blue; text-decoration: underline;">
返回首页无侧边栏
</router-link>
<div class="container">
<header>
<h1>文件存储</h1>
</header>
<div class="storage-grid">
<div
v-for="storage in storageOptions"
:key="storage.id"
:class="['storage-card', storage.class, { selected: selectedStorage === storage.id }]"
@click="selectStorage(storage.id)"
>
<div class="card-header">
<div class="card-icon">
<i :class="storage.icon"></i>
</div>
<div class="card-title">{{ storage.name }}</div>
</div>
<div class="card-description">
{{ storage.description }}
</div>
<div class="card-stats">
<div class="stat">
<div class="stat-value">{{ storage.capacity }}</div>
<div class="stat-label">存储容量</div>
</div>
<div class="stat">
<div class="stat-value">{{ storage.speed }}</div>
<div class="stat-label">传输速度</div>
</div>
<div class="stat">
<div class="stat-value">{{ storage.price }}</div>
<div class="stat-label">价格/</div>
</div>
</div>
</div>
</div>
<div class="divider"></div>
<section class="init-section">
<h2>初始化文件存储</h2>
<div class="init-content">
<div class="init-form" v-if="!isInitialized">
<div class="form-group">
<label for="storageName">存储名称</label>
<input
id="storageName"
v-model="initForm.name"
type="text"
placeholder="请输入存储名称"
:class="{ error: formErrors.name }"
>
<span class="error-message" v-if="formErrors.name">{{ formErrors.name }}</span>
</div>
<div class="form-group">
<label for="storageSize">存储容量</label>
<div class="size-input">
<input
id="storageSize"
v-model.number="initForm.size"
type="number"
placeholder="请输入存储容量"
:class="{ error: formErrors.size }"
>
<select v-model="initForm.sizeUnit">
<option value="GB">GB</option>
<option value="TB">TB</option>
<option value="PB">PB</option>
</select>
</div>
<span class="error-message" v-if="formErrors.size">{{ formErrors.size }}</span>
</div>
<div class="form-group">
<label>存储类型</label>
<div class="radio-group">
<label class="radio-option">
<input
type="radio"
v-model="initForm.storageType"
value="standard"
>
<span class="radio-label">标准存储</span>
</label>
<label class="radio-option">
<input
type="radio"
v-model="initForm.storageType"
value="archive"
>
<span class="radio-label">归档存储</span>
</label>
<label class="radio-option">
<input
type="radio"
v-model="initForm.storageType"
value="performance"
>
<span class="radio-label">性能存储</span>
</label>
</div>
</div>
<div class="form-group">
<label class="checkbox-option">
<input
type="checkbox"
v-model="initForm.enableEncryption"
>
<span class="checkmark"></span>
启用数据加密
</label>
</div>
<div class="form-actions">
<button class="btn btn-outline" @click="resetForm">重置</button>
<button
class="btn btn-primary"
@click="initializeStorage"
:disabled="!canInitialize"
>
{{ isInitializing ? '初始化中...' : '开始初始化' }}
</button>
</div>
</div>
<div class="init-success" v-else>
<div class="success-icon">
<i class="fas fa-check-circle"></i>
</div>
<h3>初始化成功</h3>
<p>文件存储已成功创建您现在可以开始使用了</p>
<div class="storage-info">
<div class="info-item">
<span class="info-label">存储名称</span>
<span class="info-value">{{ initializedStorage.name }}</span>
</div>
<div class="info-item">
<span class="info-label">存储区域</span>
<span class="info-value">{{ getSelectedStorageName() }}</span>
</div>
<div class="info-item">
<span class="info-label">存储容量</span>
<span class="info-value">{{ initializedStorage.size }} {{ initializedStorage.sizeUnit }}</span>
</div>
<div class="info-item">
<span class="info-label">存储类型</span>
<span class="info-value">{{ getStorageTypeText(initializedStorage.storageType) }}</span>
</div>
</div>
<div class="success-actions">
<button class="btn btn-outline" @click="createNewStorage">创建新的存储</button>
<button class="btn btn-primary" @click="goToStorage">进入文件存储</button>
</div>
</div>
<div class="init-help">
<h3>文件存储使用介绍</h3>
<p>选择适合您需求的存储区域配置存储参数并开始使用</p>
<div v-if="selectedStorage" class="selected-info">
当前选择: <strong>{{ getSelectedStorageName() }}</strong>
</div>
<div class="help-actions">
<button class="btn btn-outline">查看文档</button>
<button class="btn btn-primary" @click="viewPricingRules">查看计费规则</button>
</div>
</div>
</div>
</section>
</div>
</template>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
//
interface StorageOption {
id: number
name: string
class: string
icon: string
description: string
capacity: string
speed: string
price: string
}
//
interface InitForm {
name: string
size: number | null
sizeUnit: string
storageType: string
enableEncryption: boolean
}
interface FormErrors {
name?: string
size?: string
}
interface InitializedStorage {
name: string
size: number
sizeUnit: string
storageType: string
enableEncryption: boolean
}
//
const selectedStorage = ref<number | null>(null)
const isInitializing = ref(false)
const isInitialized = ref(false)
//
const initForm = reactive<InitForm>({
name: '',
size: null,
sizeUnit: 'GB',
storageType: 'standard',
enableEncryption: true
})
const formErrors = reactive<FormErrors>({})
const initializedStorage = ref<InitializedStorage | null>(null)
//
const storageOptions = ref<StorageOption[]>([
{
id: 1,
name: 'A100专区',
class: 'a100',
icon: 'fas fa-microchip',
description: '高性能计算存储适用于AI训练和大数据分析',
capacity: '10TB',
speed: '10Gbps',
price: '¥299'
},
{
id: 2,
name: 'V100专区',
class: 'v100',
icon: 'fas fa-server',
description: '企业级存储解决方案,提供高可靠性和稳定性',
capacity: '20TB',
speed: '8Gbps',
price: '¥499'
},
{
id: 3,
name: '佛山区',
class: 'foshan',
icon: 'fas fa-map-marker-alt',
description: '华南地区存储节点,低延迟访问',
capacity: '15TB',
speed: '6Gbps',
price: '¥199'
},
{
id: 4,
name: '北京B区',
class: 'beijing',
icon: 'fas fa-cloud',
description: '华北地区存储节点,高可用性架构',
capacity: '25TB',
speed: '12Gbps',
price: '¥399'
}
])
//
const canInitialize = computed(() => {
return selectedStorage.value !== null &&
initForm.name.trim() !== '' &&
initForm.size !== null &&
initForm.size > 0
})
//
const selectStorage = (id: number): void => {
selectedStorage.value = id
}
//
const getSelectedStorageName = (): string => {
const selected = storageOptions.value.find(storage => storage.id === selectedStorage.value)
return selected ? selected.name : ''
}
//
const validateForm = (): boolean => {
//
formErrors.name = ''
formErrors.size = ''
let isValid = true
if (!initForm.name.trim()) {
formErrors.name = '请输入存储名称'
isValid = false
}
if (initForm.size === null || initForm.size <= 0) {
formErrors.size = '请输入有效的存储容量'
isValid = false
}
return isValid
}
//
const initializeStorage = async (): Promise<void> => {
if (!validateForm()) {
return
}
if (!selectedStorage.value) {
alert('请先选择存储区域')
return
}
isInitializing.value = true
try {
// API
await new Promise(resolve => setTimeout(resolve, 2000))
//
initializedStorage.value = {
name: initForm.name,
size: initForm.size!,
sizeUnit: initForm.sizeUnit,
storageType: initForm.storageType,
enableEncryption: initForm.enableEncryption
}
isInitialized.value = true
} catch (error) {
console.error('初始化失败:', error)
alert('初始化失败,请重试')
} finally {
isInitializing.value = false
}
}
//
const resetForm = (): void => {
initForm.name = ''
initForm.size = null
initForm.sizeUnit = 'GB'
initForm.storageType = 'standard'
initForm.enableEncryption = true
//
formErrors.name = ''
formErrors.size = ''
}
//
const createNewStorage = (): void => {
isInitialized.value = false
resetForm()
}
//
const goToStorage = (): void => {
alert('正在跳转到文件存储管理页面...')
//
}
//
const getStorageTypeText = (type: string): string => {
const typeMap: { [key: string]: string } = {
standard: '标准存储',
archive: '归档存储',
performance: '性能存储'
}
return typeMap[type] || type
}
//
const viewPricingRules = (): void => {
alert('计费规则页面即将打开')
}
</script>
<style scoped>
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
margin-bottom: 30px;
}
h1 {
font-size: 2.2rem;
color: #2c3e50;
margin-bottom: 10px;
}
.divider {
height: 1px;
background: linear-gradient(to right, transparent, #ddd, transparent);
margin: 25px 0;
}
h2 {
font-size: 1.6rem;
color: #34495e;
margin-bottom: 15px;
}
.storage-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
margin-bottom: 40px;
}
.storage-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
border: 2px solid transparent;
}
.storage-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12);
}
.storage-card.selected {
border-color: #3498db;
background-color: #f8fafd;
}
.card-header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.card-icon {
width: 50px;
height: 50px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 15px;
font-size: 1.5rem;
}
.a100 .card-icon {
background-color: #e8f4fd;
color: #3498db;
}
.v100 .card-icon {
background-color: #e8f6f3;
color: #1abc9c;
}
.foshan .card-icon {
background-color: #fef9e7;
color: #f39c12;
}
.beijing .card-icon {
background-color: #fdedec;
color: #e74c3c;
}
.card-title {
font-size: 1.2rem;
font-weight: 600;
}
.card-description {
color: #7f8c8d;
font-size: 0.9rem;
margin-bottom: 15px;
}
.card-stats {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.stat {
text-align: center;
}
.stat-value {
font-weight: 700;
font-size: 1.1rem;
}
.stat-label {
font-size: 0.8rem;
color: #7f8c8d;
}
.init-section {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}
.init-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
}
.init-form {
grid-column: 1;
}
.init-help {
grid-column: 2;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #2c3e50;
}
.form-group input[type="text"],
.form-group input[type="number"] {
width: 100%;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
.form-group input:focus {
outline: none;
border-color: #3498db;
}
.form-group input.error {
border-color: #e74c3c;
}
.error-message {
color: #e74c3c;
font-size: 12px;
margin-top: 5px;
display: block;
}
.size-input {
display: flex;
gap: 10px;
}
.size-input input {
flex: 1;
}
.size-input select {
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
background: white;
}
.radio-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.radio-option {
display: flex;
align-items: center;
cursor: pointer;
}
.radio-option input {
margin-right: 8px;
}
.checkbox-option {
display: flex;
align-items: center;
cursor: pointer;
}
.checkbox-option input {
margin-right: 8px;
}
.form-actions {
display: flex;
gap: 10px;
margin-top: 30px;
}
.btn {
padding: 10px 20px;
border-radius: 6px;
border: none;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.btn-primary {
background-color: #3498db;
color: white;
}
.btn-primary:hover:not(:disabled) {
background-color: #2980b9;
}
.btn-outline {
background-color: transparent;
border: 1px solid #3498db;
color: #3498db;
}
.btn-outline:hover {
background-color: #e8f4fd;
}
.init-success {
grid-column: 1 / -1;
text-align: center;
padding: 40px 20px;
}
.success-icon {
font-size: 4rem;
color: #27ae60;
margin-bottom: 20px;
}
.success-icon i {
animation: scaleIn 0.5s ease;
}
@keyframes scaleIn {
0% { transform: scale(0); }
70% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.storage-info {
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin: 30px 0;
text-align: left;
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.info-item {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px solid #e9ecef;
}
.info-item:last-child {
margin-bottom: 0;
border-bottom: none;
}
.info-label {
font-weight: 600;
color: #495057;
}
.info-value {
color: #6c757d;
}
.success-actions {
display: flex;
gap: 10px;
justify-content: center;
margin-top: 30px;
}
.selected-info {
margin-top: 20px;
padding: 15px;
background-color: #e8f4fd;
border-radius: 8px;
border-left: 4px solid #3498db;
}
.help-actions {
margin-top: 20px;
}
.init-help h3 {
font-size: 1.4rem;
margin-bottom: 8px;
color: #2c3e50;
}
.init-help p {
color: #7f8c8d;
margin-bottom: 15px;
}
@media (max-width: 768px) {
.storage-grid {
grid-template-columns: 1fr;
}
.init-content {
grid-template-columns: 1fr;
gap: 20px;
}
.init-form,
.init-help {
grid-column: 1;
}
.success-actions {
flex-direction: column;
}
.form-actions {
flex-direction: column;
}
}
</style>