10 changed files with 1297 additions and 3 deletions
@ -0,0 +1,343 @@ |
|||||
|
// pages/collection/index.js
|
||||
|
const API = require('../../utils/api.js'); |
||||
|
|
||||
|
Page({ |
||||
|
data: { |
||||
|
qrCodes: [], // 二维码数据
|
||||
|
invitees: [], // 邀请者列表
|
||||
|
isAdmin: false, // 是否为管理员
|
||||
|
activeFilter: 'all', // 当前激活的筛选条件
|
||||
|
sidebarVisible: false, // 侧边栏是否可见
|
||||
|
expandedIndex: -1, // 当前展开的二维码索引
|
||||
|
searchKeyword: '' // 搜索关键词
|
||||
|
}, |
||||
|
|
||||
|
onLoad: function (options) { |
||||
|
// 页面加载时的初始化逻辑
|
||||
|
console.log('二维码合集页面加载,options:', options); |
||||
|
|
||||
|
// 检查是否是通过内部按钮进入的
|
||||
|
if (!options.from || options.from !== 'internal') { |
||||
|
console.log('非内部进入,重定向到首页'); |
||||
|
wx.redirectTo({ |
||||
|
url: '/pages/index/index' |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 加载二维码合集
|
||||
|
this.loadQrCollection(); |
||||
|
}, |
||||
|
|
||||
|
onShow: function () { |
||||
|
// 页面显示时重新加载数据
|
||||
|
this.loadQrCollection(); |
||||
|
}, |
||||
|
|
||||
|
// 加载用户信息
|
||||
|
loadUserInfo: function () { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
// 从本地存储获取用户信息
|
||||
|
const userInfo = wx.getStorageSync('userInfo') || {}; |
||||
|
// 获取电话号码信息
|
||||
|
const phoneNumber = userInfo.phoneNumber || wx.getStorageSync('phoneNumber') || ''; |
||||
|
|
||||
|
// 如果有电话号码,查询personnel表获取详细信息
|
||||
|
if (phoneNumber) { |
||||
|
// 根据电话号码查询personnel表
|
||||
|
API.request('/api/personnel/get', 'POST', { phone: phoneNumber }).then(res => { |
||||
|
console.log('查询personnel表结果:', res); |
||||
|
if (res && res.success && res.data && res.data.length > 0) { |
||||
|
const personnelInfo = res.data[0]; |
||||
|
// 更新用户信息
|
||||
|
const updatedUserInfo = { |
||||
|
name: personnelInfo.name || userInfo.name || userInfo.userName || '微信用户', |
||||
|
phoneNumber: phoneNumber, |
||||
|
projectName: personnelInfo.projectName || '' |
||||
|
}; |
||||
|
// 存储到本地存储
|
||||
|
wx.setStorageSync('userInfo', updatedUserInfo); |
||||
|
resolve(updatedUserInfo); |
||||
|
} else { |
||||
|
// 如果查询失败,使用本地存储的用户信息
|
||||
|
const fallbackUserInfo = { |
||||
|
name: userInfo.name || userInfo.userName || '微信用户', |
||||
|
phoneNumber: phoneNumber, |
||||
|
projectName: userInfo.projectName || '' |
||||
|
}; |
||||
|
resolve(fallbackUserInfo); |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error('查询personnel表失败:', err); |
||||
|
// 如果查询失败,使用本地存储的用户信息
|
||||
|
const fallbackUserInfo = { |
||||
|
name: userInfo.name || userInfo.userName || '微信用户', |
||||
|
phoneNumber: phoneNumber, |
||||
|
projectName: userInfo.projectName || '' |
||||
|
}; |
||||
|
resolve(fallbackUserInfo); |
||||
|
}); |
||||
|
} else { |
||||
|
// 如果没有电话号码,使用本地存储的用户信息
|
||||
|
const fallbackUserInfo = { |
||||
|
name: userInfo.name || userInfo.userName || '微信用户', |
||||
|
phoneNumber: phoneNumber, |
||||
|
projectName: userInfo.projectName || '' |
||||
|
}; |
||||
|
resolve(fallbackUserInfo); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 将UTC时间转换为北京时间
|
||||
|
convertToBeijingTime: function (utcTime) { |
||||
|
if (!utcTime) return '未知'; |
||||
|
|
||||
|
// 创建Date对象
|
||||
|
const date = new Date(utcTime); |
||||
|
|
||||
|
// 转换为北京时间(UTC+8)
|
||||
|
const beijingTime = new Date(date.getTime() + 8 * 60 * 60 * 1000); |
||||
|
|
||||
|
// 格式化时间
|
||||
|
const year = beijingTime.getFullYear(); |
||||
|
const month = String(beijingTime.getMonth() + 1).padStart(2, '0'); |
||||
|
const day = String(beijingTime.getDate()).padStart(2, '0'); |
||||
|
const hours = String(beijingTime.getHours()).padStart(2, '0'); |
||||
|
const minutes = String(beijingTime.getMinutes()).padStart(2, '0'); |
||||
|
const seconds = String(beijingTime.getSeconds()).padStart(2, '0'); |
||||
|
|
||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
||||
|
}, |
||||
|
|
||||
|
// 处理二维码数据,转换时间为北京时间
|
||||
|
processQrCodes: function (qrCodes) { |
||||
|
return qrCodes.map(qrCode => { |
||||
|
const newQrCode = { ...qrCode }; |
||||
|
// 转换创建时间
|
||||
|
if (newQrCode.createdAt) { |
||||
|
newQrCode.createdAt = this.convertToBeijingTime(newQrCode.createdAt); |
||||
|
} |
||||
|
// 转换签发日期
|
||||
|
if (newQrCode.issueDate) { |
||||
|
newQrCode.issueDate = this.convertToBeijingTime(newQrCode.issueDate); |
||||
|
} |
||||
|
return newQrCode; |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 加载二维码合集
|
||||
|
loadQrCollection: function () { |
||||
|
this.loadUserInfo().then(user => { |
||||
|
try { |
||||
|
// 构建请求参数
|
||||
|
let params = {}; |
||||
|
if (user) { |
||||
|
params.userName = user.name; |
||||
|
params.phoneNumber = user.phoneNumber; |
||||
|
params.projectName = user.projectName; |
||||
|
} |
||||
|
|
||||
|
console.log('加载二维码合集,用户信息:', user); |
||||
|
|
||||
|
// 从服务器获取二维码合集
|
||||
|
API.getQrCollection(params).then(res => { |
||||
|
console.log('获取二维码合集结果:', res); |
||||
|
|
||||
|
if (res && res.success) { |
||||
|
// 动态生成筛选按钮
|
||||
|
if (res.isAdmin && res.invitees && res.invitees.length > 0) { |
||||
|
this.setData({ |
||||
|
isAdmin: res.isAdmin, |
||||
|
invitees: res.invitees |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
if (res.qrCodes && res.qrCodes.length > 0) { |
||||
|
// 处理二维码数据,转换时间为北京时间
|
||||
|
const processedQrCodes = this.processQrCodes(res.qrCodes); |
||||
|
|
||||
|
// 渲染二维码合集
|
||||
|
this.setData({ |
||||
|
qrCodes: processedQrCodes |
||||
|
}); |
||||
|
} else { |
||||
|
// 显示空状态
|
||||
|
this.setData({ |
||||
|
qrCodes: [] |
||||
|
}); |
||||
|
} |
||||
|
} else { |
||||
|
// 显示错误状态
|
||||
|
wx.showToast({ |
||||
|
title: '加载失败,请稍后重试', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
} |
||||
|
}).catch(err => { |
||||
|
console.error('获取二维码合集失败:', err); |
||||
|
wx.showToast({ |
||||
|
title: '加载失败,请稍后重试', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
console.error('获取二维码合集失败:', error); |
||||
|
wx.showToast({ |
||||
|
title: '加载失败,请稍后重试', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 打开筛选侧边栏
|
||||
|
openSidebar: function () { |
||||
|
this.setData({ |
||||
|
sidebarVisible: true |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 关闭筛选侧边栏
|
||||
|
closeSidebar: function () { |
||||
|
this.setData({ |
||||
|
sidebarVisible: false |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 切换展开/收起状态
|
||||
|
toggleSection: function (e) { |
||||
|
const index = e.currentTarget.dataset.index; |
||||
|
this.setData({ |
||||
|
expandedIndex: this.data.expandedIndex === index ? -1 : index |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 切换筛选条件
|
||||
|
switchFilter: function (e) { |
||||
|
const filter = e.currentTarget.dataset.filter; |
||||
|
this.setData({ |
||||
|
activeFilter: filter |
||||
|
}); |
||||
|
this.filterQrCodes(filter, null, this.data.searchKeyword); |
||||
|
}, |
||||
|
|
||||
|
// 按邀请者筛选
|
||||
|
filterByInviter: function (e) { |
||||
|
const filter = e.currentTarget.dataset.filter; |
||||
|
const inviterName = e.currentTarget.dataset.inviter; |
||||
|
this.setData({ |
||||
|
activeFilter: filter |
||||
|
}); |
||||
|
this.filterQrCodes(filter, inviterName, this.data.searchKeyword); |
||||
|
this.closeSidebar(); |
||||
|
}, |
||||
|
|
||||
|
// 搜索输入事件
|
||||
|
onSearchInput: function (e) { |
||||
|
const searchKeyword = e.detail.value; |
||||
|
this.setData({ |
||||
|
searchKeyword: searchKeyword |
||||
|
}); |
||||
|
this.filterQrCodes(this.data.activeFilter, null, searchKeyword); |
||||
|
}, |
||||
|
|
||||
|
// 筛选二维码
|
||||
|
filterQrCodes: function (filter, inviterName, searchKeyword = '') { |
||||
|
this.loadUserInfo().then(user => { |
||||
|
// 构建请求参数
|
||||
|
let params = {}; |
||||
|
if (user) { |
||||
|
params.userName = user.name; |
||||
|
params.phoneNumber = user.phoneNumber; |
||||
|
params.projectName = user.projectName; |
||||
|
} |
||||
|
|
||||
|
console.log('筛选二维码,用户信息:', user); |
||||
|
|
||||
|
// 重新加载并筛选二维码
|
||||
|
API.getQrCollection(params).then(res => { |
||||
|
if (res && res.success && res.qrCodes && res.qrCodes.length > 0) { |
||||
|
// 处理二维码数据,转换时间为北京时间
|
||||
|
let filteredQrCodes = this.processQrCodes(res.qrCodes); |
||||
|
|
||||
|
if (filter === 'me' && user) { |
||||
|
// 筛选当前用户自己的二维码
|
||||
|
filteredQrCodes = filteredQrCodes.filter(qrCode => |
||||
|
qrCode.inviter === user.name |
||||
|
); |
||||
|
} else if (filter.startsWith('invitee_') && inviterName) { |
||||
|
// 筛选特定邀请者的二维码
|
||||
|
filteredQrCodes = filteredQrCodes.filter(qrCode => |
||||
|
qrCode.inviter === inviterName |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
// 搜索功能
|
||||
|
if (searchKeyword) { |
||||
|
const keyword = searchKeyword.toLowerCase(); |
||||
|
filteredQrCodes = filteredQrCodes.filter(qrCode => { |
||||
|
return ( |
||||
|
(qrCode.phoneNumber && qrCode.phoneNumber.toLowerCase().includes(keyword)) || |
||||
|
(qrCode.company && qrCode.company.toLowerCase().includes(keyword)) |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
// 添加高亮效果
|
||||
|
filteredQrCodes = filteredQrCodes.map(qrCode => { |
||||
|
const newQrCode = { ...qrCode }; |
||||
|
if (newQrCode.company && newQrCode.company.toLowerCase().includes(keyword)) { |
||||
|
const regex = new RegExp(`(${keyword})`, 'gi'); |
||||
|
newQrCode.company = newQrCode.company.replace(regex, '<span class="highlight">$1</span>'); |
||||
|
} |
||||
|
if (newQrCode.phoneNumber && newQrCode.phoneNumber.toLowerCase().includes(keyword)) { |
||||
|
const regex = new RegExp(`(${keyword})`, 'gi'); |
||||
|
newQrCode.phoneNumber = newQrCode.phoneNumber.replace(regex, '<span class="highlight">$1</span>'); |
||||
|
} |
||||
|
return newQrCode; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
this.setData({ |
||||
|
qrCodes: filteredQrCodes |
||||
|
}); |
||||
|
} |
||||
|
}).catch(error => { |
||||
|
console.error('筛选二维码失败:', error); |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 返回上一页
|
||||
|
goBack: function () { |
||||
|
wx.navigateBack({ |
||||
|
delta: 1 |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 跳转到生成邀请二维码页面
|
||||
|
goToGenerate: function () { |
||||
|
wx.redirectTo({ |
||||
|
url: '/pages/qrcode/index?from=internal' |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
// 图片加载成功事件
|
||||
|
onImageLoad: function () { |
||||
|
console.log('二维码图片加载成功'); |
||||
|
}, |
||||
|
|
||||
|
// 图片加载失败事件
|
||||
|
onImageError: function (e) { |
||||
|
console.error('二维码图片加载失败:', e); |
||||
|
wx.showToast({ |
||||
|
title: '二维码图片加载失败', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"navigationBarTitleText": "二维码合集", |
||||
|
"navigationBarBackgroundColor": "#ffffff", |
||||
|
"navigationBarTextStyle": "black", |
||||
|
"enablePullDownRefresh": true |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
<!--pages/collection/index.wxml--> |
||||
|
<view class="page-container"> |
||||
|
<!-- 筛选和搜索栏 --> |
||||
|
<view class="filter-bar"> |
||||
|
<view class="filter-tabs"> |
||||
|
<view class="filter-tab {{activeFilter === 'all' ? 'active' : ''}}" data-filter="all" bindtap="switchFilter"> |
||||
|
<text>全部</text> |
||||
|
</view> |
||||
|
<view class="filter-tab {{activeFilter === 'me' ? 'active' : ''}}" data-filter="me" bindtap="switchFilter"> |
||||
|
<text>我的</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="search-container"> |
||||
|
<input |
||||
|
type="text" |
||||
|
placeholder="搜索电话号码/主体名称" |
||||
|
bindinput="onSearchInput" |
||||
|
value="{{searchKeyword}}" |
||||
|
class="search-input" |
||||
|
/> |
||||
|
</view> |
||||
|
<view wx:if="isAdmin && invitees.length > 0" class="filter-button" bindtap="openSidebar"> |
||||
|
<text class="filter-icon">🔍</text> |
||||
|
<text class="filter-text">筛选</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 二维码列表 --> |
||||
|
<view class="qr-list"> |
||||
|
<block wx:if="{{qrCodes.length === 0}}"> |
||||
|
<view class="empty-state"> |
||||
|
<image |
||||
|
src="https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=empty" |
||||
|
mode="aspectFit" |
||||
|
class="empty-image" |
||||
|
/> |
||||
|
<text class="empty-text">暂无二维码</text> |
||||
|
<text class="empty-subtext">请先生成邀请二维码</text> |
||||
|
</view> |
||||
|
</block> |
||||
|
<block wx:else> |
||||
|
<block wx:for="{{qrCodes}}" wx:key="sessionId" wx:for-index="index"> |
||||
|
<!-- 二维码项 --> |
||||
|
<view class="qr-item" bindtap="toggleSection" data-index="{{index}}"> |
||||
|
<view class="qr-item-header"> |
||||
|
<view class="qr-item-info"> |
||||
|
<rich-text nodes="{{item.company ? item.company : '未知'}}"></rich-text> |
||||
|
<view class="qr-item-details"> |
||||
|
<rich-text nodes="{{item.phoneNumber ? item.phoneNumber : '未知'}}"></rich-text> |
||||
|
<text> / {{item.createdAt || '未知'}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="qr-item-arrow"> |
||||
|
<text>{{expandedIndex === index ? '▲' : '▼'}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 二维码详情 --> |
||||
|
<view class="qr-item-content" wx:if="{{expandedIndex === index}}"> |
||||
|
<image |
||||
|
src="{{item.qrCodeUrl || 'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' + encodeURIComponent(item.url)}}" |
||||
|
mode="aspectFit" |
||||
|
class="qr-image" |
||||
|
bindload="onImageLoad" |
||||
|
binderror="onImageError" |
||||
|
/> |
||||
|
<view class="qr-info-center"> |
||||
|
<view class="qr-info-item"> |
||||
|
<text>{{item.inviter || '未知'}}</text> |
||||
|
</view> |
||||
|
<view class="qr-info-item"> |
||||
|
<text>{{item.inviterProjectName || '无职位'}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</block> |
||||
|
</block> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部按钮 --> |
||||
|
<view class="bottom-section"> |
||||
|
<button class="generate-button" bindtap="goToGenerate"> |
||||
|
<text class="generate-button-text">生成邀请二维码</text> |
||||
|
</button> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 筛选侧边栏 --> |
||||
|
<view class="sidebar" wx:if="{{sidebarVisible}}"> |
||||
|
<view class="sidebar-overlay" bindtap="closeSidebar"></view> |
||||
|
<view class="sidebar-content"> |
||||
|
<view class="sidebar-header"> |
||||
|
<text class="sidebar-title">筛选用户</text> |
||||
|
<view class="sidebar-close" bindtap="closeSidebar"> |
||||
|
<text>✕</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="sidebar-body"> |
||||
|
<view |
||||
|
wx:for="{{invitees}}" |
||||
|
wx:key="inviter" |
||||
|
class="sidebar-item" |
||||
|
data-filter="invitee_{{index}}" |
||||
|
data-inviter="{{item.inviter}}" |
||||
|
bindtap="filterByInviter" |
||||
|
> |
||||
|
<text class="sidebar-item-text">{{item.inviter}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
@ -0,0 +1,434 @@ |
|||||
|
/* pages/collection/index.wxss */ |
||||
|
|
||||
|
/* 页面容器 */ |
||||
|
.page-container { |
||||
|
width: 100%; |
||||
|
background-color: #f5f5f5; |
||||
|
min-height: 100vh; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
/* 筛选和搜索栏 */ |
||||
|
.filter-bar { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 16rpx; |
||||
|
background-color: #f0f9f0; |
||||
|
border-bottom: 1rpx solid #d4edda; |
||||
|
box-sizing: border-box; |
||||
|
position: sticky; |
||||
|
top: 0; |
||||
|
z-index: 900; |
||||
|
flex-wrap: wrap; |
||||
|
gap: 12rpx; |
||||
|
min-height: 100rpx; |
||||
|
overflow-x: hidden; |
||||
|
} |
||||
|
|
||||
|
.filter-tabs { |
||||
|
display: flex; |
||||
|
gap: 8rpx; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.filter-tab { |
||||
|
padding: 6rpx 12rpx; |
||||
|
border-radius: 16rpx; |
||||
|
background-color: #f0f0f0; |
||||
|
font-size: 22rpx; |
||||
|
color: #666; |
||||
|
transition: all 0.3s; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.filter-tab.active { |
||||
|
background-color: #4CAF50; |
||||
|
color: white; |
||||
|
} |
||||
|
|
||||
|
.search-container { |
||||
|
flex: 1; |
||||
|
min-width: 150rpx; |
||||
|
position: relative; |
||||
|
margin: 0 8rpx; |
||||
|
flex-basis: 0; |
||||
|
max-width: 400rpx; |
||||
|
} |
||||
|
|
||||
|
.search-input { |
||||
|
width: 100%; |
||||
|
flex: 1; |
||||
|
padding: 16rpx 20rpx; |
||||
|
border: 1rpx solid #e0e0e0; |
||||
|
border-radius: 12rpx; |
||||
|
font-size: 28rpx; |
||||
|
box-sizing: border-box; |
||||
|
background-color: #f9f9f9; |
||||
|
min-height: 70rpx; |
||||
|
} |
||||
|
|
||||
|
.search-input:focus { |
||||
|
border-color: #4CAF50; |
||||
|
background-color: #ffffff; |
||||
|
box-shadow: 0 0 0 2rpx rgba(76, 175, 80, 0.1); |
||||
|
} |
||||
|
|
||||
|
/* 高亮效果 */ |
||||
|
.highlight { |
||||
|
background-color: #FFF3CD; |
||||
|
color: #856404; |
||||
|
padding: 0 4rpx; |
||||
|
border-radius: 4rpx; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.filter-button { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 6rpx; |
||||
|
padding: 12rpx 16rpx; |
||||
|
background-color: #4CAF50; |
||||
|
color: white; |
||||
|
border-radius: 10rpx; |
||||
|
font-size: 24rpx; |
||||
|
flex-shrink: 0; |
||||
|
min-height: 60rpx; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.filter-icon { |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.filter-text { |
||||
|
font-size: 22rpx; |
||||
|
} |
||||
|
|
||||
|
/* 二维码列表 */ |
||||
|
.qr-list { |
||||
|
padding: 16rpx; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
/* 空状态 */ |
||||
|
.empty-state { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 100rpx 0; |
||||
|
color: #999; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.empty-image { |
||||
|
width: 120rpx; |
||||
|
height: 120rpx; |
||||
|
margin-bottom: 24rpx; |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
|
||||
|
.empty-text { |
||||
|
font-size: 28rpx; |
||||
|
margin-bottom: 8rpx; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
.empty-subtext { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
/* 二维码项 */ |
||||
|
.qr-item { |
||||
|
background-color: white; |
||||
|
border-radius: 12rpx; |
||||
|
margin-bottom: 16rpx; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06); |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.qr-item-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 16rpx; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.qr-item-info { |
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.qr-item-info rich-text { |
||||
|
display: block; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
color: #333; |
||||
|
margin-bottom: 8rpx; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.qr-item-details { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.qr-item-details rich-text { |
||||
|
display: inline; |
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.qr-item-details text { |
||||
|
margin-left: 8rpx; |
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.qr-item-arrow { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
margin-left: 16rpx; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
/* 二维码详情 */ |
||||
|
.qr-item-content { |
||||
|
padding: 0 16rpx 16rpx; |
||||
|
border-top: 1rpx solid #f0f0f0; |
||||
|
animation: slideDown 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideDown { |
||||
|
from { |
||||
|
opacity: 0; |
||||
|
transform: translateY(-10rpx); |
||||
|
} |
||||
|
to { |
||||
|
opacity: 1; |
||||
|
transform: translateY(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.qr-image { |
||||
|
width: 200rpx; |
||||
|
height: 200rpx; |
||||
|
margin: 16rpx auto; |
||||
|
display: block; |
||||
|
border-radius: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.qr-info-center { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
margin-top: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.qr-info-item { |
||||
|
margin-bottom: 8rpx; |
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
|
text-align: center; |
||||
|
width: 100%; |
||||
|
max-width: 200rpx; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
/* 底部按钮 */ |
||||
|
.bottom-section { |
||||
|
padding: 20rpx 16rpx; |
||||
|
background-color: white; |
||||
|
border-top: 1rpx solid #e0e0e0; |
||||
|
margin-top: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.generate-button { |
||||
|
width: 100%; |
||||
|
height: 80rpx; |
||||
|
background-color: #4CAF50; |
||||
|
color: white; |
||||
|
border: none; |
||||
|
border-radius: 12rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.generate-button-text { |
||||
|
color: white; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
/* 筛选侧边栏 */ |
||||
|
.sidebar { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
z-index: 2000; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.sidebar-overlay { |
||||
|
flex: 1; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
} |
||||
|
|
||||
|
.sidebar-content { |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
width: 70%; |
||||
|
max-width: 300rpx; |
||||
|
background-color: white; |
||||
|
box-shadow: -4rpx 0 10rpx rgba(0, 0, 0, 0.1); |
||||
|
animation: slideIn 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideIn { |
||||
|
from { |
||||
|
transform: translateX(100%); |
||||
|
} |
||||
|
to { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.sidebar-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 20rpx; |
||||
|
border-bottom: 1rpx solid #e0e0e0; |
||||
|
} |
||||
|
|
||||
|
.sidebar-title { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.sidebar-close { |
||||
|
font-size: 32rpx; |
||||
|
color: #999; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.sidebar-body { |
||||
|
padding: 20rpx; |
||||
|
max-height: calc(100% - 80rpx); |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.sidebar-item { |
||||
|
padding: 16rpx 0; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.sidebar-item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.sidebar-item-text { |
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
/* 响应式调整 */ |
||||
|
@media (max-width: 375px) { |
||||
|
.filter-bar { |
||||
|
flex-direction: column; |
||||
|
align-items: stretch; |
||||
|
} |
||||
|
|
||||
|
.filter-tabs { |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.search-container { |
||||
|
min-width: 100%; |
||||
|
margin: 8rpx 0; |
||||
|
} |
||||
|
|
||||
|
.filter-button { |
||||
|
align-self: center; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 针对中等屏幕的调整 */ |
||||
|
@media (min-width: 376px) and (max-width: 480px) { |
||||
|
.filter-bar { |
||||
|
flex-wrap: nowrap; |
||||
|
} |
||||
|
|
||||
|
.filter-tabs { |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.search-container { |
||||
|
flex: 1; |
||||
|
min-width: 150rpx; |
||||
|
max-width: 300rpx; |
||||
|
} |
||||
|
|
||||
|
.filter-button { |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 针对大屏幕的调整 */ |
||||
|
@media (min-width: 481px) { |
||||
|
.filter-bar { |
||||
|
flex-wrap: nowrap; |
||||
|
} |
||||
|
|
||||
|
.search-container { |
||||
|
flex: 1; |
||||
|
min-width: 200rpx; |
||||
|
max-width: 400rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 滚动条样式 */ |
||||
|
::-webkit-scrollbar { |
||||
|
width: 4rpx; |
||||
|
height: 4rpx; |
||||
|
} |
||||
|
|
||||
|
::-webkit-scrollbar-track { |
||||
|
background: #f1f1f1; |
||||
|
border-radius: 2rpx; |
||||
|
} |
||||
|
|
||||
|
::-webkit-scrollbar-thumb { |
||||
|
background: #c1c1c1; |
||||
|
border-radius: 2rpx; |
||||
|
} |
||||
|
|
||||
|
::-webkit-scrollbar-thumb:hover { |
||||
|
background: #a8a8a8; |
||||
|
} |
||||
Loading…
Reference in new issue