| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- <template>
- <div class="page-container">
- <div class="page-header">
- <PageTitle title="我的收藏" />
- <el-button type="danger" link @click="handleAddCategory"
- ><el-icon><Plus /></el-icon>添加分类</el-button
- >
- </div>
- <!-- 分类Tab -->
- <StatusTabs v-model="activeCategory" :tabs="categoryTabs" type="pill" />
- <!-- 操作栏 -->
- <div class="action-bar">
- <el-checkbox v-model="selectAll" @change="handleSelectAll">全选</el-checkbox>
- <el-button type="danger" link @click="handleBatchAddCart">加入购物车</el-button>
- <el-button type="danger" link @click="handleBatchCancel">取消收藏</el-button>
- </div>
- <!-- 商品列表 -->
- <div class="product-grid">
- <ProductCard
- v-for="(item, index) in productList"
- :key="index"
- :product="item"
- v-model="item.checked"
- show-checkbox
- show-action
- show-add-cart
- action-text="取消收藏"
- @action="handleCancelCollection(item)"
- @add-cart="handleAddCart(item)"
- />
- </div>
- <el-empty v-if="productList.length === 0" description="暂无收藏商品" />
- <TablePagination
- v-if="productList.length > 0"
- v-model:page="queryParams.pageNum"
- v-model:page-size="queryParams.pageSize"
- :total="total"
- @change="handleQuery"
- />
- <!-- 添加分类弹窗 -->
- <el-dialog v-model="categoryDialogVisible" title="添加分类" width="400px">
- <el-form ref="categoryFormRef" :model="categoryForm" :rules="categoryRules">
- <el-form-item prop="name"><el-input v-model="categoryForm.name" placeholder="请输入分类名称" /></el-form-item>
- </el-form>
- <template #footer>
- <el-button @click="categoryDialogVisible = false">取消</el-button>
- <el-button type="danger" @click="handleSaveCategory">确定</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, reactive, watch, onMounted } from 'vue';
- import { Plus } from '@element-plus/icons-vue';
- import { ElMessage, ElMessageBox, type CheckboxValueType } from 'element-plus';
- import { PageTitle, StatusTabs, ProductCard, TablePagination } from '@/components';
- import { favoritesList, favoritesProductList, cancelProductCollect, addProductShoppingCart } from '@/api/goods/index';
- const activeCategory = ref('all');
- const selectAll = ref(false);
- const categoryDialogVisible = ref(false);
- const categoryFormRef = ref();
- const loading = ref(false);
- const categoryTabs = ref<any[]>([{ key: 'all', label: '全部' }]);
- const categoryForm = reactive({ name: '' });
- const categoryRules = { name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }] };
- const queryParams = reactive({ pageNum: 1, pageSize: 15, favoritesId: '' as any });
- const total = ref(0);
- const productList = ref<any[]>([]);
- /** 获取收藏夹列表(分类Tab) */
- const getFavoritesTabs = () => {
- favoritesList({}).then((res: any) => {
- if (res.code == 200) {
- const tabs = [{ key: 'all', label: '全部' }];
- if (res.rows && res.rows.length > 0) {
- res.rows.forEach((item: any) => {
- tabs.push({ key: String(item.id), label: item.title || '未命名' });
- });
- }
- categoryTabs.value = tabs;
- }
- });
- };
- /** 获取收藏商品列表 */
- const getProductList = () => {
- loading.value = true;
- const params: any = { pageNum: queryParams.pageNum, pageSize: queryParams.pageSize };
- if (activeCategory.value !== 'all') {
- params.favoritesId = activeCategory.value;
- }
- favoritesProductList(params)
- .then((res: any) => {
- if (res.code == 200) {
- productList.value = (res.rows || []).map((item: any) => ({
- ...item,
- name: item.itemName || item.productName || item.name || '',
- image: item.productImage || item.image || '',
- price: item.price || item.memberPrice || item.minSellingPrice || '',
- originalPrice: item.marketPrice || item.originalPrice || '',
- tag: item.tag || '',
- checked: false
- }));
- total.value = res.total || 0;
- }
- })
- .finally(() => {
- loading.value = false;
- });
- };
- const handleQuery = () => {
- selectAll.value = false;
- getProductList();
- };
- watch(activeCategory, () => {
- queryParams.pageNum = 1;
- handleQuery();
- });
- onMounted(() => {
- getFavoritesTabs();
- getProductList();
- });
- const handleSelectAll = (val: CheckboxValueType) => {
- productList.value.forEach((item) => {
- item.checked = !!val;
- });
- };
- const handleAddCategory = () => {
- categoryForm.name = '';
- categoryDialogVisible.value = true;
- };
- const handleSaveCategory = async () => {
- const valid = await categoryFormRef.value?.validate();
- if (!valid) return;
- // TODO: 调用后端新增收藏夹接口
- categoryTabs.value.push({ key: categoryForm.name, label: categoryForm.name });
- ElMessage.success('添加成功');
- categoryDialogVisible.value = false;
- getFavoritesTabs();
- };
- /** 单个加入购物车 */
- const handleAddCart = (item: any) => {
- addProductShoppingCart({ productId: item.id, productNum: 1 }).then((res: any) => {
- if (res.code == 200) {
- ElMessage.success('已加入购物车');
- }
- });
- };
- /** 批量加入购物车 */
- const handleBatchAddCart = () => {
- const selected = productList.value.filter((item) => item.checked);
- if (selected.length === 0) {
- ElMessage.warning('请先选择商品');
- return;
- }
- const promises = selected.map((item) => addProductShoppingCart({ productId: item.id, productNum: 1 }));
- Promise.all(promises).then(() => {
- ElMessage.success(`已将${selected.length}件商品加入购物车`);
- });
- };
- /** 单个取消收藏 */
- const handleCancelCollection = (item: any) => {
- ElMessageBox.confirm('确定要取消收藏该商品吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
- const params: any = { productId: item.id || item.productId };
- if (activeCategory.value !== 'all') {
- params.favoritesId = activeCategory.value;
- }
- cancelProductCollect(params).then((res: any) => {
- if (res.code == 200) {
- ElMessage.success('已取消收藏');
- getProductList();
- }
- });
- });
- };
- /** 批量取消收藏 */
- const handleBatchCancel = () => {
- const selected = productList.value.filter((item) => item.checked);
- if (selected.length === 0) {
- ElMessage.warning('请先选择商品');
- return;
- }
- ElMessageBox.confirm(`确定要取消收藏选中的${selected.length}件商品吗?`, '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- const promises = selected.map((item) => {
- const params: any = { productId: item.id || item.productId };
- if (activeCategory.value !== 'all') {
- params.favoritesId = activeCategory.value;
- }
- return cancelProductCollect(params);
- });
- Promise.all(promises).then(() => {
- selectAll.value = false;
- ElMessage.success('已取消收藏');
- getProductList();
- });
- });
- };
- </script>
- <style scoped lang="scss">
- .page-container {
- width: 100%;
- }
- .page-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- :deep(.page-title) {
- margin-bottom: 0;
- }
- }
- .action-bar {
- display: flex;
- align-items: center;
- gap: 20px;
- padding: 10px 0;
- border-bottom: 1px solid #eee;
- margin-bottom: 15px;
- }
- .product-grid {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- gap: 15px;
- }
- </style>
|