|                                                                                                                                                                                                                                  |  | <template>  <view class="desk-container">
        <!-- 顶部搜索栏 -->    <view class="header">      <view class="search-container">        <uv-search           placeholder="请输入要查询的内容"           :show-action="true"          :action-style="{color: '#fff', backgroundColor: '#06DADC', borderRadius:'8rpx', width:'100rpx', height: '64rpx', lineHeight: '64rpx', borderRadius: '198rpx', text:'white', fontSize:'26rpx'}"          shape="round"          bg-color="#F3F3F3"          color="#C6C6C6"          height="32"          margin="0"          v-model="searchKeyword"          searchIconColor="#8B8B8B"          placeholderColor="#c6c6c6"          @search="handleSearch"          @clear="handleSearch"          @custom="handleSearch"        ></uv-search>      </view>    </view>
    <!-- 书籍网格 -->    <view class="book-grid-container">      <view class="book-grid">        <view         v-for="(book, index) in list"         :key="index"         class="book-grid-item"        @click="goDetail(book)"        @longpress="showDeleteConfirm(book, index)"        >          <view class="book-grid-cover">            <image :src="book.book.booksImg" mode="aspectFill"></image>            <!-- 删除按钮 -->            <view class="delete-btn" @click.stop="showDeleteConfirm(book, index)">              <uv-icon name="close" size="16" color="#fff"></uv-icon>            </view>          </view>          <view class="book-grid-info">            <text class="book-grid-title">{{ book.book.booksName }}</text>            <view class="book-grid-meta">              <text class="book-grid-grade">{{ book.book.categoryName }}/</text>              <image src="/static/播放图标.png" class="book-grid-duration-icon" />              <text class="book-grid-duration">{{ book.book.duration }}</text>            </view>          </view>        </view>      </view>      <uv-loading-icon text="加载中" textSize="30rpx" v-if="isLoading"></uv-loading-icon>      <uv-empty v-else-if="!list.length" text="暂无数据"></uv-empty>    </view>  </view></template>
<script>import MixinList from '@/mixins/list'export default {  mixins: [MixinList],  data() {    return {      mixinListApi: 'book.stand',      mixinListConfig: {        customOnShow: true      },      searchKeyword: '',    }  },  methods: {    mixinSetParams(){      const params = {}      if(this.searchKeyword){        params.title = this.searchKeyword      }      return params    },    goDetail(book){      uni.navigateTo({        url: '/subPages/home/directory?id=' + book.bookId      })    },    handleSearch(){      this.list = []      this.initPage()      this.getList(true)    },        // 显示删除确认弹窗
    showDeleteConfirm(book, index) {      uni.showModal({        title: '确认删除',        content: `确定要从书桌中移除《${book.book.booksName}》吗?`,        confirmText: '删除',        confirmColor: '#ff4757',        success: (res) => {          if (res.confirm) {            this.deleteBook(book, index)          }        }      })    },        // 删除书本
    async deleteBook(book, index) {      try {        uni.showLoading({          title: '删除中...'        })                const res = await this.$api.book.delStand({          id: book.id        })                uni.hideLoading()                if (res.code === 200) {          // 从列表中移除该项
          this.list.splice(index, 1)                    uni.showToast({            title: '删除成功',            icon: 'success'          })        } else {          uni.showToast({            title: res.message || '删除失败',            icon: 'error'          })        }      } catch (error) {        uni.hideLoading()        console.error('删除书本失败:', error)        uni.showToast({          title: '删除失败',          icon: 'error'        })      }    }  },  onShow() {    // 只有登录才会获取书籍
    if (uni.getStorageSync('token')) {      this.initPage()      this.getList(true)    }  }}</script>
<style lang="scss" scoped>.desk-container {  background: #fff;  min-height: 100vh;  padding-bottom: 50rpx;}
// 顶部搜索栏
.header {  display: flex;  align-items: center;  padding: 20rpx 32rpx;  background: #fff;  position: sticky;  top: 0;  left: 0;  right: 0;  .search-container {    flex: 1;  }}
// 书籍网格容器
.book-grid-container {  padding: 20rpx 30rpx;}
// 书籍网格布局
.book-grid {  display: flex;  flex-wrap: wrap;  gap: 32rpx;    .book-grid-item {    width: 208rpx;    display: flex;    flex-direction: column;        .book-grid-cover {      box-shadow: 0px 4px 4px 0px #C0BCBA75;      width: 100%;      height: 278rpx;      border-radius: 16rpx;      overflow: hidden;      margin-bottom: 16rpx;      position: relative;            image {        width: 100%;        height: 100%;      }            .delete-btn {        position: absolute;        top: 8rpx;        right: 8rpx;        width: 32rpx;        height: 32rpx;        background: rgba(0, 0, 0, 0.6);        border-radius: 50%;        display: flex;        align-items: center;        justify-content: center;        z-index: 10;                &:active {          background: rgba(0, 0, 0, 0.8);        }      }    }        .book-grid-info {      padding: 6rpx;      box-sizing: border-box;            .book-grid-title {        font-size: 28rpx;        font-weight: 700;        color: $primary-text-color;                overflow: hidden;        text-overflow: ellipsis;        white-space: nowrap;      }            .book-grid-meta {        display: flex;        align-items: center;        margin-top: 8rpx;
        .book-grid-duration-icon {          width: 24rpx;          height: 24rpx;          margin-right: 12rpx;        }                .book-grid-grade {          font-size: 24rpx;          color: $secondary-text-color;          margin-right: 8rpx;        }                .book-grid-duration {          font-size: 24rpx;          color: $secondary-text-color;        }      }    }  }}</style>
 |