deotalandAi/.trae/documents/优化IPCard组件生成状态样式.md

202 lines
4.4 KiB
Markdown
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.

# 新建项目系列选择功能实现
## 需求分析
* 当用户点击"新建项目"卡片时,需要弹出系列选择弹窗
* 系列弹窗包含两个选项Done 和 Oone对应图片在 src/assets/xh 文件夹中
* 选中后将系列名称作为 type 参数传递给 createNewProject 函数
## 实现计划
### 1. 创建 SeriesSelector 组件
* **文件路径**`src/views/components/SeriesSelector.vue`
* **功能**
* 显示两个系列选项Done 和 Oone
* 每个选项显示对应的图片
* 支持选中状态切换
* 提供确认和取消按钮
* 通过 emit 事件返回选中的系列名称
### 2. 修改 CreationWorkspace.vue
* **引入组件**:在 CreationWorkspace.vue 中引入 SeriesSelector 组件
* **添加状态管理**
* `showSeriesSelector`:控制系列选择弹窗的显示/隐藏
* **修改新建项目逻辑**
* 点击"新建项目"卡片时,显示系列选择弹窗
* 监听 SeriesSelector 的确认事件,获取选中的系列名称
* 将系列名称作为 type 参数调用 createNewProject 函数
### 3. 样式设计
* 系列选择弹窗采用与现有删除确认弹窗一致的设计风格
* 系列选项卡片包含图片和名称,支持悬停和选中效果
* 确认和取消按钮使用现有按钮样式
## 代码结构
### SeriesSelector.vue
```vue
<template>
<!-- 系列选择弹窗 -->
<div v-if="show" class="modal-overlay" @click="onCancel">
<div class="modal-content" @click.stop>
<!-- 模态头部 -->
<div class="modal-header">
<h2 class="modal-title">{{ t('creationWorkspace.selectSeries') }}</h2>
</div>
<!-- 模态内容 -->
<div class="modal-body">
<div class="series-selector-content">
<!-- 系列选项列表 -->
<div class="series-list">
<!-- Done 系列 -->
<div
class="series-item"
:class="{ active: selectedSeries === 'Done' }"
@click="selectedSeries = 'Done'"
>
<div class="series-image">
<img src="@/assets/xh/Done.webp" alt="Done" />
</div>
<div class="series-name">Done</div>
</div>
<!-- Oone 系列 -->
<div
class="series-item"
:class="{ active: selectedSeries === 'Oone' }"
@click="selectedSeries = 'Oone'"
>
<div class="series-image">
<img src="@/assets/xh/Oone.webp" alt="Oone" />
</div>
<div class="series-name">Oone</div>
</div>
</div>
<!-- 操作按钮 -->
<div class="series-actions">
<button class="modal-action-btn cancel" @click="onCancel">
{{ t('creationWorkspace.cancel') }}
</button>
<button class="modal-action-btn primary" @click="onConfirm">
{{ t('creationWorkspace.confirm') }}
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, defineProps, defineEmits } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const props = defineProps({
show: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['confirm', 'cancel'])
const selectedSeries = ref('')
const onConfirm = () => {
if (selectedSeries.value) {
emit('confirm', selectedSeries.value)
}
}
const onCancel = () => {
emit('cancel')
}
</script>
<style scoped>
/* 系列选择弹窗样式 */
.series-selector-content {
text-align: center;
}
.series-list {
display: flex;
gap: 24px;
justify-content: center;
margin-bottom: 32px;
}
.series-item {
background: #f8fafc;
border: 2px solid #e2e8f0;
border-radius: 12px;
padding: 16px;
cursor: pointer;
transition: all 0.3s ease;
width: 200px;
}
.series-item:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}
.series-item.active {
border-color: #6B46C1;
background: rgba(107, 70, 193, 0.05);
box-shadow: 0 4px 16px rgba(107, 70, 193, 0.2);
}
.series-image {
width: 100%;
height: 120px;
overflow: hidden;
border-radius: 8px;
margin-bottom: 12px;
}
.series-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.series-name {
font-size: 16px;
font-weight: 600;
color: #1f2937;
}
.series-actions {
display: flex;
gap: 16px;
justify-content: center;
}
</style>
```