4.4 KiB
4.4 KiB
新建项目系列选择功能实现
需求分析
-
当用户点击"新建项目"卡片时,需要弹出系列选择弹窗
-
系列弹窗包含两个选项: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
<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>