Files
medical-mall/pages/mall/admin/marketing/points/goods.uvue
2026-03-09 17:57:44 +08:00

399 lines
11 KiB
Plaintext

<template>
<view class="admin-marketing-integral-product">
<view class="content-body">
<!-- 搜索过滤栏 -->
<view class="filter-card border-shadow">
<view class="filter-row">
<view class="filter-item">
<text class="label-txt">创建时间:</text>
<view class="date-picker-mock">
<text class="calendar-ic">📅</text>
<text class="date-placeholder">开始日期 - 结束日期</text>
</view>
</view>
<view class="filter-item">
<text class="label-txt">上架状态:</text>
<view class="select-mock">
<text class="select-val">请选择</text>
<text class="arrow-down">▼</text>
</view>
</view>
<view class="filter-item">
<text class="label-txt">商品搜索:</text>
<input class="search-input" placeholder="请输入商品名称, ID" v-model="searchQuery" />
</view>
<view class="btn-query" @click="handleSearch">
<text class="query-txt">查询</text>
</view>
</view>
</view>
<!-- 主要内容区域 -->
<view class="table-card border-shadow">
<view class="card-header">
<view class="btn-primary-blue" @click="handleAdd">
<text class="btn-txt">+ 添加积分商品</text>
</view>
</view>
<!-- 表格 -->
<view class="table-container">
<view class="table-header-row">
<view class="th th-id">ID</view>
<view class="th th-img">商品图片</view>
<view class="th th-title">活动标题</view>
<view class="th th-integral">兑换积分</view>
<view class="th th-limit">限量</view>
<view class="th th-remain">限量剩余</view>
<view class="th th-time">创建时间</view>
<view class="th th-sort">排序</view>
<view class="th th-status">状态</view>
<view class="th th-ops">操作</view>
</view>
<view class="table-body">
<view v-for="(item, index) in productList" :key="item.id" class="table-row">
<view class="td td-id"><text class="td-txt">{{ item.id }}</text></view>
<view class="td td-img">
<image class="product-thumb" :src="item.image" mode="aspectFill"></image>
</view>
<view class="td td-title">
<text class="title-txt line-clamp-2">{{ item.title }}</text>
</view>
<view class="td td-integral"><text class="td-txt">{{ item.integral }}</text></view>
<view class="td td-limit"><text class="td-txt">{{ item.limit }}</text></view>
<view class="td td-remain"><text class="td-txt">{{ item.remain }}</text></view>
<view class="td td-time"><text class="td-txt-small">{{ item.createTime }}</text></view>
<view class="td td-sort"><text class="td-txt">{{ item.sort }}</text></view>
<view class="td td-status">
<view :class="['switch-box', item.status ? 'active' : '']" @click="toggleStatus(index)">
<view class="switch-dot"></view>
</view>
</view>
<view class="td td-ops">
<view class="op-links">
<text class="op-link">兑换记录</text>
<text class="op-split">|</text>
<text class="op-link" @click="handleEdit(item)">编辑</text>
<text class="op-split">|</text>
<text class="op-link">复制</text>
<text class="op-split">|</text>
<text class="op-link text-danger">删除</text>
</view>
</view>
</view>
</view>
</view>
<!-- 分页 -->
<view class="pagination-footer">
<view class="page-total">
<text class="total-txt">共 {{ total }} 条</text>
</view>
<view class="page-select">
<text class="page-val">15条/页 ▼</text>
</view>
<view class="page-btns">
<text class="p-btn"><</text>
<text class="p-btn active">1</text>
<text class="p-btn">></text>
</view>
<view class="page-jump">
<text class="jump-txt">前往</text>
<input class="jump-input" placeholder="1" />
<text class="jump-txt">页</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup lang="uts">
import { ref, reactive } from 'vue'
interface ProductItem {
id: number
image: string
title: string
integral: number
limit: number
remain: number
createTime: string
sort: number
status: boolean
}
const searchQuery = ref('')
const total = ref(3)
const productList = ref<ProductItem[]>([
{
id: 48,
image: 'https://img14.360buyimg.com/n1/jfs/t1/172605/32/17036/114175/609a473eE6997455c/df82c6168e36712b.jpg',
title: 'UR2024夏季新款女装复古纯欲氛围感一字肩短款T恤UWG440060',
integral: 0,
limit: 4,
remain: 0,
createTime: '2025-10-24 14:29:19',
sort: 9999,
status: true
},
{
id: 43,
image: 'https://img12.360buyimg.com/n1/jfs/t1/185449/19/11995/4379/60d96d27E6a877c8e/3c38d4e92a2a7a5a.jpg',
title: '阿迪达斯官网 adidas BBALL CAP COT 男女训练运动帽子FQ5270 传奇水蓝/传...',
integral: 100,
limit: 1,
remain: 0,
createTime: '2025-05-13 15:37:46',
sort: 9998,
status: true
},
{
id: 44,
image: 'https://img13.360buyimg.com/n1/jfs/t1/192173/5/11913/21447/60e57e95Ef82688f3/bc875f643e8c95a3.jpg',
title: '劳伦斯意式极简大平层设计师款直排真皮沙发简约客厅别墅大小户型',
integral: 6860,
limit: 1,
remain: 0,
createTime: '2025-05-13 15:38:02',
sort: 9996,
status: true
}
])
const handleSearch = () => { console.log('Searching...') }
const handleAdd = () => { console.log('Adding...') }
const handleEdit = (item: ProductItem) => { console.log('Editing...', item.id) }
const toggleStatus = (index: number) => {
productList.value[index].status = !productList.value[index].status
}
</script>
<style scoped lang="scss">
.admin-marketing-integral-product {
padding: 0;
background-color: transparent;
min-height: auto;
}
.border-shadow {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
.content-body {
display: flex;
flex-direction: column;
gap: 20px;
}
/* 过滤栏 */
.filter-card {
padding: 24px;
}
.filter-row {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
gap: 24px;
}
.filter-item {
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
}
.label-txt { font-size: 14px; color: #606266; white-space: nowrap; }
.date-picker-mock {
width: 280px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
flex-direction: row;
align-items: center;
padding: 0 12px;
gap: 8px;
}
.calendar-ic { font-size: 14px; color: #c0c4cc; }
.date-placeholder { font-size: 13px; color: #c0c4cc; }
.select-mock {
width: 180px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 0 12px;
}
.select-val { font-size: 14px; color: #c0c4cc; }
.arrow-down { font-size: 10px; color: #c0c4cc; }
.search-input {
width: 220px;
height: 32px;
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 0 12px;
font-size: 13px;
}
.btn-query {
background-color: #2d8cf0;
padding: 0 20px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
cursor: pointer;
}
.query-txt { color: #fff; font-size: 14px; }
/* 表格卡片 */
.table-card {
background-color: #fff;
}
.card-header { padding: 20px; }
.btn-primary-blue {
background-color: #2d8cf0;
padding: 8px 16px;
border-radius: 4px;
display: inline-flex;
}
.btn-txt { color: #fff; font-size: 14px; }
.table-container { padding: 0 20px 20px; }
.table-header-row {
display: flex;
flex-direction: row;
background-color: #f8f8f9;
border-bottom: 1px solid #e8eaec;
}
.th {
padding: 12px 10px;
font-size: 14px;
color: #515a6e;
font-weight: bold;
display: flex;
align-items: center;
}
.table-row {
display: flex;
flex-direction: row;
border-bottom: 1px solid #e8eaec;
align-items: center;
}
.td {
padding: 12px 10px;
display: flex;
align-items: center;
}
.td-txt { font-size: 14px; color: #515a6e; }
.td-txt-small { font-size: 13px; color: #515a6e; }
/* 列表各列宽度控制 */
.th-id, .td-id { width: 60px; }
.th-img, .td-img { width: 80px; }
.th-title, .td-title { flex: 1; min-width: 200px; }
.th-integral, .td-integral { width: 100px; }
.th-limit, .td-limit { width: 80px; }
.th-remain, .td-remain { width: 100px; }
.th-time, .td-time { width: 160px; }
.th-sort, .td-sort { width: 80px; }
.th-status, .td-status { width: 80px; }
.th-ops, .td-ops { width: 220px; justify-content: flex-end; }
.product-thumb {
width: 50px;
height: 50px;
border-radius: 4px;
background-color: #f5f5f5;
}
.title-txt { font-size: 13px; color: #333; line-height: 1.5; }
.line-clamp-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
/* Switch 开关 */
.switch-box {
width: 44px;
height: 22px;
background-color: #dcdfe6;
border-radius: 11px;
position: relative;
transition: background-color 0.3s;
cursor: pointer;
}
.switch-box.active { background-color: #2d8cf0; }
.switch-dot {
width: 18px;
height: 18px;
background-color: #fff;
border-radius: 9px;
position: absolute;
top: 2px;
left: 2px;
transition: transform 0.3s;
}
.switch-box.active .switch-dot { transform: translateX(22px); }
.op-links { display: flex; flex-direction: row; align-items: center; }
.op-link { color: #2d8cf0; font-size: 13px; cursor: pointer; margin: 0 5px; }
.op-split { color: #e8eaec; margin: 0 5px; }
.text-danger { color: #ed4014; }
/* 分页 */
.pagination-footer {
padding: 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
gap: 12px;
}
.total-txt { font-size: 13px; color: #606266; }
.page-val { font-size: 13px; color: #606266; border: 1px solid #dcdfe6; padding: 4px 10px; border-radius: 4px; }
.page-btns { display: flex; flex-direction: row; gap: 8px; }
.p-btn {
width: 32px;
height: 32px;
border: 1px solid #e8eaec;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
color: #666;
}
.p-btn.active { background-color: #2d8cf0; border-color: #2d8cf0; color: #fff; }
.page-jump { display: flex; flex-direction: row; align-items: center; gap: 8px; }
.jump-txt { font-size: 13px; color: #606266; }
.jump-input { width: 40px; height: 32px; border: 1px solid #dcdfe6; text-align: center; border-radius: 4px; font-size: 13px; }
</style>