feat: 新增商品类型选择组件

This commit is contained in:
yangmf_0726 committed 2025-08-24 17:52:49 +08:00
1 parent 638e0c4fad
commit 96c950084f
2 files changed
+249 -3

No files matched your search

@@ -0,0 +1,206 @@
<template>
<el-dialog
v-model="visible"
title="选择商品类型"
width="600px"
:before-close="handleDialogClose"
>
<div class="product-type-container">
<div class="type-card-list">
<div
class="type-card"
:class="{ 'selected': selectedType === 'mall' }"
@click="selectProductType('mall')"
>
<div class="card-content">
<div class="card-icon">
<Icon icon="ep:shopping-cart-full" :size="48" />
</div>
<div class="card-title">商城商品</div>
<div class="card-description">适用于线上商城销售的商品</div>
</div>
<div class="card-check" v-if="selectedType === 'mall'">
<Icon icon="ep:check" :size="20" />
</div>
</div>
<div
class="type-card"
:class="{ 'selected': selectedType === 'pickup' }"
@click="selectProductType('pickup')"
>
<div class="card-content">
<div class="card-icon">
<Icon icon="ep:box" :size="48" />
</div>
<div class="card-title">提货柜商品</div>
<div class="card-description">适用于自助提货柜销售的商品</div>
</div>
<div class="card-check" v-if="selectedType === 'pickup'">
<Icon icon="ep:check" :size="20" />
</div>
</div>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleDialogClose">取消</el-button>
<el-button type="primary" @click="handleConfirmSelection" :disabled="!selectedType">
确定
</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
defineOptions({ name: 'ProductTypeSelector' })
interface Props {
modelValue: boolean
}
interface Emits {
(e: 'update:modelValue', value: boolean): void
(e: 'confirm', type: 'mall' | 'pickup'): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const message = useMessage() // 消息弹窗
const selectedType = ref('') // 选中的商品类型
// 双向绑定显示状态
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
/** 选择商品类型 */
const selectProductType = (type: string) => {
selectedType.value = type
}
/** 确认选择 */
const handleConfirmSelection = () => {
if (!selectedType.value) {
message.warning('请选择商品类型')
return
}
// 发送确认事件
emit('confirm', selectedType.value as 'mall' | 'pickup')
// 清除选择状态
selectedType.value = ''
}
/** 处理弹窗关闭事件 */
const handleDialogClose = (done?: Function) => {
// 清除选择状态
selectedType.value = ''
// 关闭弹窗
if (done && typeof done === 'function') {
done()
} else {
visible.value = false
}
}
/** 处理取消按钮点击 */
const handleCancelClick = () => {
handleDialogClose()
}
/** 监听弹窗显示状态变化 */
watch(visible, (newVal) => {
if (newVal) {
// 每次打开弹窗时清除选择状态
selectedType.value = ''
}
})
</script>
<style scoped>
.product-type-container {
padding: 20px 0;
}
.type-card-list {
display: flex;
gap: 20px;
justify-content: center;
}
.type-card {
position: relative;
width: 200px;
height: 160px;
border: 2px solid #e4e7ed;
border-radius: 8px;
padding: 20px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #fff;
}
.type-card:hover {
border-color: #409eff;
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
}
.type-card.selected {
border-color: #409eff;
background: rgba(64, 158, 255, 0.05);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
}
.card-content {
text-align: center;
}
.card-icon {
color: #606266;
margin-bottom: 12px;
transition: color 0.3s ease;
}
.type-card.selected .card-icon {
color: #409eff;
}
.card-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin-bottom: 8px;
}
.card-description {
font-size: 12px;
color: #909399;
line-height: 1.4;
}
.card-check {
position: absolute;
top: 8px;
right: 8px;
width: 24px;
height: 24px;
background: #409eff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
</style>
+43 -3
View File
@@ -146,7 +146,7 @@
<el-button
type="primary"
plain
@click="openForm('create')"
@click="showProductTypeDialog = true"
v-hasPermi="['product:summary:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
@@ -225,6 +225,13 @@
/> -->
</ContentWrap>
<!-- 商品类型选择组件 -->
<ProductTypeSelector
:key="productTypeSelectorKey"
v-model="showProductTypeDialog"
@confirm="handleProductTypeConfirm"
/>
<!-- 表单弹窗:添加/修改 -->
<SummaryForm ref="formRef" @success="getList" />
</template>
@@ -234,19 +241,23 @@ import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { SummaryApi, SummaryVO } from '@/api/product/summary'
import SummaryForm from './SummaryForm.vue'
import ProductTypeSelector from './ProductTypeSelector.vue'
/** 商品汇总 列表 */
defineOptions({ name: 'Summary' })
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const { push } = useRouter() // 路由跳转
const loading = ref(true) // 列表的加载中
const list = ref<SummaryVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const showProductTypeDialog = ref(false) // 商品类型选择弹窗显示状态
const queryParams = reactive({
pageNo:1,
pageSize:10,
pageNo: 1,
pageSize: 10,
/*商品编号,自增 */
id: undefined,
@@ -328,6 +339,21 @@ const resetQuery = () => {
handleQuery()
}
/** 处理商品类型确认选择 */
const handleProductTypeConfirm = (type: 'mall' | 'pickup') => {
// 立即关闭弹窗
showProductTypeDialog.value = false
// 根据选择的类型跳转到对应的添加页面
if (type === 'mall') {
// 跳转到商城商品添加页面
push({ name: 'ProductSpuAdd' })
} else if (type === 'pickup') {
// 跳转到提货柜商品添加页面
push({ name: 'ProductPickupAdd' })
}
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
@@ -362,6 +388,20 @@ const handleExport = async () => {
}
}
const productTypeSelectorKey = ref(0) // 添加 key 控制组件重新渲染
/** 页面激活时清除弹窗状态 */
onActivated(() => {
// 确保从其他页面返回时弹窗是关闭的
showProductTypeDialog.value = false
// 强制重新渲染组件
productTypeSelectorKey.value++
// 重新获取数据
getList()
})
/** 初始化 **/
onMounted(() => {
getList()