507 lines
11 KiB
Vue
507 lines
11 KiB
Vue
<template>
|
||
<view class="container">
|
||
<!-- Header: 极简大气,与详情页保持一致 -->
|
||
<view class="page-header">
|
||
<view class="header-content">
|
||
<view class="title-group">
|
||
<text class="header-title">我的清单</text>
|
||
<text class="header-subtitle">My COLLECTIONS</text>
|
||
</view>
|
||
<view class="header-badges">
|
||
<text class="count-badge">共计: {{ lists.length }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- List Content -->
|
||
<scroll-view class="list-content" scroll-y @scrolltolower="loadMore">
|
||
<view v-if="lists.length > 0" class="list-wrapper">
|
||
<view
|
||
v-for="(item, index) in lists"
|
||
:key="index"
|
||
class="list-card animate-slide-in"
|
||
:style="{ animationDelay: index * 0.05 + 's' }"
|
||
@tap="goToDetail(item)"
|
||
>
|
||
<!-- 1. 卡片顶部工具栏:日期 + 删除 -->
|
||
<!-- 彻底移除了 u-swipe-action,解决编译报错 -->
|
||
<view class="card-top-bar">
|
||
<view class="top-left">
|
||
<u-icon name="calendar" color="#999" size="14"></u-icon>
|
||
<text class="date-text">{{ item.created_at }}</text>
|
||
</view>
|
||
<!-- 显性删除按钮:更直观,防误触 -->
|
||
<view class="delete-btn" @tap.stop="handleDelete(index, item.id)">
|
||
<u-icon name="trash" color="#ccc" size="18"></u-icon>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 2. 卡片主体内容 -->
|
||
<view class="card-body">
|
||
<view class="body-left">
|
||
<text class="item-name">{{ item.name }}</text>
|
||
<view class="item-remark" v-if="item.remark">
|
||
<text class="remark-line"></text>
|
||
<text class="remark-text">{{ item.remark }}</text>
|
||
</view>
|
||
<view class="item-remark placeholder" v-else>
|
||
<text class="remark-text">暂无备注信息</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 右侧数量展示:更有设计感 -->
|
||
<view class="body-right">
|
||
<text class="count-label">商品数</text>
|
||
<text class="count-num">{{ item.count < 10 ? '0' + item.count : item.count }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 3. 底部装饰条 / 进入指引 -->
|
||
<view class="card-footer">
|
||
<text class="footer-status">查看详情</text>
|
||
<u-icon name="arrow-right" color="#B4854D" size="12"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="empty-state" v-else>
|
||
<image src="/static/images/empty.png" mode="widthFix" class="empty-img"></image>
|
||
<text class="empty-text">您还没有创建任何清单</text>
|
||
<text class="empty-sub">点击下方按钮开始创建</text>
|
||
</view>
|
||
|
||
<!-- 底部垫高 -->
|
||
<view style="height: 180rpx;"></view>
|
||
</scroll-view>
|
||
|
||
<!-- Create Button (Floating) -->
|
||
<view class="fab-container">
|
||
<view class="create-btn" @tap="showCreateModal" hover-class="btn-hover">
|
||
<u-icon name="plus" color="#fff" size="18"></u-icon>
|
||
<text>新建清单</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- Create List Modal -->
|
||
<u-modal
|
||
:show="showModal"
|
||
:title="false"
|
||
:showCancelButton="true"
|
||
cancelText="取消"
|
||
confirmText="创建"
|
||
confirmColor="#B4854D"
|
||
@confirm="createList"
|
||
@cancel="cancelCreate"
|
||
class="custom-modal"
|
||
>
|
||
<view class="modal-content">
|
||
<view class="modal-header-deco">
|
||
<text class="modal-title">新建清单</text>
|
||
<text class="modal-sub">创建新的选品组合</text>
|
||
</view>
|
||
|
||
<u-form :model="formData" ref="uForm" :errorType="['message']">
|
||
<u-form-item prop="name" class="modal-input-item">
|
||
<u-input
|
||
v-model="formData.name"
|
||
placeholder="清单名称"
|
||
border="bottom"
|
||
class="custom-input"
|
||
/>
|
||
</u-form-item>
|
||
<u-form-item prop="remark" class="modal-input-item">
|
||
<u-input
|
||
v-model="formData.remark"
|
||
placeholder="备注信息 (选填)"
|
||
border="bottom"
|
||
class="custom-input"
|
||
/>
|
||
</u-form-item>
|
||
</u-form>
|
||
</view>
|
||
</u-modal>
|
||
|
||
<!-- Loading -->
|
||
<u-loading-page :loading="isLoading" bgColor="rgba(255,255,255,0.9)" color="#B4854D" loadingText="加载中..."></u-loading-page>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {createCartApi, deleteCartApi, getCartListApi} from "@/api/page/cart";
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
isLoading: false,
|
||
showModal: false,
|
||
formData: {
|
||
name: '',
|
||
remark: ''
|
||
},
|
||
// swipeOptions 已移除,不再需要
|
||
lists: []
|
||
}
|
||
},
|
||
onShow() {
|
||
this.getList();
|
||
},
|
||
methods: {
|
||
navigateBack() {
|
||
uni.navigateBack()
|
||
},
|
||
showCreateModal() {
|
||
this.showModal = true
|
||
},
|
||
cancelCreate() {
|
||
this.showModal = false
|
||
this.formData = { name: '', remark: '' }
|
||
},
|
||
getList() {
|
||
getCartListApi().then((res) => {
|
||
this.lists = res
|
||
})
|
||
},
|
||
createList() {
|
||
if (!this.formData.name) {
|
||
uni.showToast({
|
||
title: '请输入清单名称',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
createCartApi(this.formData).then((res) => {
|
||
this.showModal = false
|
||
this.formData = { name: '', remark: '' }
|
||
uni.showToast({
|
||
title: '已创建',
|
||
icon: 'success'
|
||
})
|
||
this.getList();
|
||
})
|
||
},
|
||
goToDetail(item) {
|
||
uni.navigateTo({
|
||
url: `/pages/cart/detail?id=${item.id}`
|
||
})
|
||
},
|
||
loadMore() {
|
||
// 暂无更多逻辑
|
||
},
|
||
handleDelete(index, id) {
|
||
uni.showModal({
|
||
title: '删除确认',
|
||
content: '确定要删除这个清单吗?此操作不可恢复。',
|
||
confirmText: '删除',
|
||
confirmColor: '#B4854D',
|
||
cancelColor: '#999',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
deleteCartApi(id).then(() => {
|
||
this.lists.splice(index, 1)
|
||
uni.showToast({
|
||
title: '已删除',
|
||
icon: 'none'
|
||
})
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
/* 核心:Border-box 全局应用,防止布局错位 */
|
||
view, scroll-view, text, image {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.container {
|
||
min-height: 100vh;
|
||
width: 100%;
|
||
background-color: #F7F8FA; /* 高级灰背景 */
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 动画 */
|
||
@keyframes slideInUp {
|
||
from { opacity: 0; transform: translateY(30rpx); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
.animate-slide-in {
|
||
animation: slideInUp 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
|
||
}
|
||
|
||
/* Header */
|
||
.page-header {
|
||
width: 100%;
|
||
background: #fff;
|
||
padding: 50rpx 40rpx 30rpx;
|
||
position: relative;
|
||
z-index: 10;
|
||
border-bottom: 1rpx solid rgba(0,0,0,0.03);
|
||
}
|
||
|
||
.header-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.header-title {
|
||
font-size: 48rpx;
|
||
font-weight: 300;
|
||
color: #1A1A1A;
|
||
letter-spacing: 2rpx;
|
||
margin-bottom: 8rpx;
|
||
display: block;
|
||
font-family: serif;
|
||
}
|
||
|
||
.header-subtitle {
|
||
font-size: 18rpx;
|
||
color: #B4854D;
|
||
letter-spacing: 6rpx;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
display: block;
|
||
}
|
||
|
||
.count-badge {
|
||
font-size: 20rpx;
|
||
color: #999;
|
||
letter-spacing: 1rpx;
|
||
font-family: Arial, sans-serif;
|
||
}
|
||
|
||
/* List Content */
|
||
.list-content {
|
||
flex: 1;
|
||
width: 100%;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
/* --- 核心卡片样式 --- */
|
||
.list-card {
|
||
background: #fff;
|
||
margin-bottom: 30rpx;
|
||
border-radius: 12rpx;
|
||
box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.04);
|
||
overflow: hidden;
|
||
border: 1rpx solid rgba(0,0,0,0.02);
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* Top Bar */
|
||
.card-top-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 24rpx 30rpx;
|
||
border-bottom: 1rpx solid #F9F9F9;
|
||
}
|
||
|
||
.top-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.date-text {
|
||
font-size: 22rpx;
|
||
color: #999;
|
||
letter-spacing: 1rpx;
|
||
font-family: Arial, sans-serif;
|
||
}
|
||
|
||
.delete-btn {
|
||
padding: 10rpx;
|
||
margin-right: -10rpx; /* 增加点击热区修正视觉位置 */
|
||
}
|
||
|
||
/* Card Body */
|
||
.card-body {
|
||
padding: 30rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.body-left {
|
||
flex: 1;
|
||
padding-right: 30rpx;
|
||
}
|
||
|
||
.item-name {
|
||
font-size: 36rpx;
|
||
font-weight: 500;
|
||
color: #222;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
font-family: serif;
|
||
}
|
||
|
||
.item-remark {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.remark-line {
|
||
width: 20rpx;
|
||
height: 2rpx;
|
||
background-color: #B4854D;
|
||
}
|
||
|
||
.remark-text {
|
||
font-size: 24rpx;
|
||
color: #888;
|
||
font-style: italic;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 300rpx;
|
||
}
|
||
|
||
.placeholder .remark-text {
|
||
color: #ddd;
|
||
}
|
||
|
||
/* 右侧数量区 */
|
||
.body-right {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding-left: 30rpx;
|
||
border-left: 1rpx dashed #eee;
|
||
}
|
||
|
||
.count-label {
|
||
font-size: 18rpx; /* 微调字体大小 */
|
||
color: #ccc;
|
||
letter-spacing: 2rpx;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.count-num {
|
||
font-size: 48rpx;
|
||
font-weight: 400; /* 数字细一点更高级 */
|
||
color: #B4854D;
|
||
font-family: 'Times New Roman', serif;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* Card Footer */
|
||
.card-footer {
|
||
background: #FDFDFD;
|
||
padding: 16rpx 30rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
border-top: 1rpx solid #F9F9F9;
|
||
}
|
||
|
||
.footer-status {
|
||
font-size: 20rpx;
|
||
color: #B4854D;
|
||
letter-spacing: 2rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* FAB */
|
||
.fab-container {
|
||
position: fixed;
|
||
bottom: 60rpx;
|
||
left: 0;
|
||
right: 0;
|
||
display: flex;
|
||
justify-content: center;
|
||
pointer-events: none;
|
||
z-index: 20;
|
||
}
|
||
|
||
.create-btn {
|
||
pointer-events: auto;
|
||
background: #222; /* 纯黑背景更显奢华 */
|
||
color: #B4854D; /* 金色文字 */
|
||
padding: 28rpx 70rpx;
|
||
border-radius: 60rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
letter-spacing: 2rpx;
|
||
box-shadow: 0 20rpx 40rpx rgba(0,0,0,0.2);
|
||
transition: all 0.2s;
|
||
border: 1rpx solid #333;
|
||
}
|
||
|
||
.btn-hover {
|
||
transform: translateY(2rpx);
|
||
box-shadow: 0 10rpx 20rpx rgba(0,0,0,0.15);
|
||
}
|
||
|
||
/* Empty State */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding-top: 200rpx;
|
||
}
|
||
|
||
.empty-img {
|
||
width: 200rpx;
|
||
opacity: 0.8;
|
||
margin-bottom: 40rpx;
|
||
filter: grayscale(100%); /* 图片黑白化 */
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: 30rpx;
|
||
color: #666;
|
||
font-weight: 500;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.empty-sub {
|
||
font-size: 24rpx;
|
||
color: #ccc;
|
||
letter-spacing: 1rpx;
|
||
}
|
||
|
||
/* Modal Styling - 极简风 */
|
||
.modal-content {
|
||
padding: 50rpx 30rpx 30rpx;
|
||
}
|
||
|
||
.modal-header-deco {
|
||
text-align: center;
|
||
margin-bottom: 60rpx;
|
||
}
|
||
|
||
.modal-title {
|
||
display: block;
|
||
font-size: 40rpx;
|
||
font-weight: 300;
|
||
color: #333;
|
||
letter-spacing: 4rpx;
|
||
margin-bottom: 10rpx;
|
||
}
|
||
|
||
.modal-sub {
|
||
display: block;
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
|
||
.custom-input {
|
||
padding: 20rpx 0 !important;
|
||
}
|
||
</style> |