修复上线第一版
This commit is contained in:
parent
ad510a1be6
commit
c92f4069a7
@ -1,32 +1,36 @@
|
||||
const app = getApp()
|
||||
|
||||
function staticIcon(path) {
|
||||
return `${app.globalData.staticBaseUrl}/${path.replace(/^\/+/, '')}`
|
||||
}
|
||||
|
||||
const ACHIEVEMENT_ICON_MAP = {
|
||||
MASTERED_100: '/assets/icons/achievements/core/100.svg',
|
||||
MASTERED_1000: '/assets/icons/achievements/core/1000.svg',
|
||||
MASTERED_3000: '/assets/icons/achievements/core/3000.svg',
|
||||
MASTERED_5000: '/assets/icons/achievements/core/5000.svg',
|
||||
MASTERED_7000: '/assets/icons/achievements/core/7000.svg',
|
||||
MASTERED_10000: '/assets/icons/achievements/core/10000.svg',
|
||||
TOTAL_100: '/assets/icons/achievements/core/total-100.svg',
|
||||
CHECKIN_7: '/assets/icons/achievements/core/checkin-30.svg',
|
||||
CHECKIN_30: '/assets/icons/achievements/core/checkin-30.svg',
|
||||
CHECKIN_100: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_180: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_360: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_STREAK_7: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_STREAK_30: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_STREAK_100: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_STREAK_180: '/assets/icons/achievements/core/streak.svg',
|
||||
CHECKIN_STREAK_360: '/assets/icons/achievements/core/streak.svg',
|
||||
ACCURACY_80: '/assets/icons/achievements/core/accuracy.svg',
|
||||
ACCURACY_90: '/assets/icons/achievements/core/accuracy.svg',
|
||||
DAILY_REVIEW_20: '/assets/icons/achievements/core/review-volume.svg',
|
||||
DAILY_REVIEW_50: '/assets/icons/achievements/core/review-volume.svg',
|
||||
MASTERED_100: staticIcon('icons/achievements/core/100.svg'),
|
||||
MASTERED_1000: staticIcon('icons/achievements/core/1000.svg'),
|
||||
MASTERED_3000: staticIcon('icons/achievements/core/3000.svg'),
|
||||
MASTERED_5000: staticIcon('icons/achievements/core/5000.svg'),
|
||||
MASTERED_7000: staticIcon('icons/achievements/core/7000.svg'),
|
||||
MASTERED_10000: staticIcon('icons/achievements/core/10000.svg'),
|
||||
TOTAL_100: staticIcon('icons/achievements/core/total-100.svg'),
|
||||
CHECKIN_7: staticIcon('icons/achievements/core/checkin-30.svg'),
|
||||
CHECKIN_30: staticIcon('icons/achievements/core/checkin-30.svg'),
|
||||
CHECKIN_100: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_180: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_360: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_STREAK_7: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_STREAK_30: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_STREAK_100: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_STREAK_180: staticIcon('icons/achievements/core/streak.svg'),
|
||||
CHECKIN_STREAK_360: staticIcon('icons/achievements/core/streak.svg'),
|
||||
ACCURACY_80: staticIcon('icons/achievements/core/accuracy.svg'),
|
||||
ACCURACY_90: staticIcon('icons/achievements/core/accuracy.svg'),
|
||||
DAILY_REVIEW_20: staticIcon('icons/achievements/core/review-volume.svg'),
|
||||
DAILY_REVIEW_50: staticIcon('icons/achievements/core/review-volume.svg'),
|
||||
}
|
||||
|
||||
const STATUS_ICON_MAP = {
|
||||
1: '/assets/icons/achievements/state/achievement-unlocked.svg',
|
||||
0: '/assets/icons/achievements/state/achievement-locked.svg',
|
||||
1: staticIcon('icons/achievements/state/achievement-unlocked.svg'),
|
||||
0: staticIcon('icons/achievements/state/achievement-locked.svg'),
|
||||
}
|
||||
|
||||
const GROUP_ORDER = {
|
||||
@ -39,12 +43,12 @@ const GROUP_ORDER = {
|
||||
}
|
||||
|
||||
const GROUP_META = {
|
||||
mastery: { title: '掌握进阶', subtitle: '从入门到精通', icon: '/assets/icons/achievements/core/mastery-advanced.svg' },
|
||||
checkin: { title: '打卡里程', subtitle: '记录坚持的脚步', icon: '/assets/icons/achievements/core/checkin-30.svg' },
|
||||
streak: { title: '连续坚持', subtitle: '不断线的努力', icon: '/assets/icons/achievements/core/streak.svg' },
|
||||
accuracy: { title: '准确率', subtitle: '复习质量提升', icon: '/assets/icons/achievements/core/accuracy.svg' },
|
||||
review: { title: '复习数量', subtitle: '积累复习量', icon: '/assets/icons/achievements/core/review-volume.svg' },
|
||||
other: { title: '其他', subtitle: '更多成就', icon: '/assets/icons/achievements/core/total-100.svg' },
|
||||
mastery: { title: '掌握进阶', subtitle: '从入门到精通', icon: staticIcon('icons/achievements/core/mastery-advanced.svg') },
|
||||
checkin: { title: '打卡里程', subtitle: '记录坚持的脚步', icon: staticIcon('icons/achievements/core/checkin-30.svg') },
|
||||
streak: { title: '连续坚持', subtitle: '不断线的努力', icon: staticIcon('icons/achievements/core/streak.svg') },
|
||||
accuracy: { title: '准确率', subtitle: '复习质量提升', icon: staticIcon('icons/achievements/core/accuracy.svg') },
|
||||
review: { title: '复习数量', subtitle: '积累复习量', icon: staticIcon('icons/achievements/core/review-volume.svg') },
|
||||
other: { title: '其他', subtitle: '更多成就', icon: staticIcon('icons/achievements/core/total-100.svg') },
|
||||
}
|
||||
|
||||
const GROUP_PROGRESS = {
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
list: [],
|
||||
loading: false,
|
||||
error: '',
|
||||
},
|
||||
onShow() {
|
||||
this.loadList()
|
||||
},
|
||||
loadList() {
|
||||
if (!app.globalData.openid) {
|
||||
this.setData({ error: '请先登录' })
|
||||
return
|
||||
}
|
||||
this.setData({ loading: true, error: '' })
|
||||
wx.request({
|
||||
url: `${app.globalData.baseUrl}/api/v1/entries`,
|
||||
header: { 'X-OpenID': app.globalData.openid },
|
||||
success: (res) => {
|
||||
const payload = res.data?.data || []
|
||||
this.setData({ list: payload })
|
||||
},
|
||||
fail: () => this.setData({ error: '词库加载失败' }),
|
||||
complete: () => this.setData({ loading: false }),
|
||||
})
|
||||
},
|
||||
goAdd() {
|
||||
wx.navigateTo({ url: '/pages/manage/entry-edit/entry-edit' })
|
||||
},
|
||||
goDetail(e) {
|
||||
const { id } = e.currentTarget.dataset
|
||||
wx.navigateTo({ url: `/pages/manage/entry-detail/entry-detail?id=${id}` })
|
||||
},
|
||||
goBatch() {
|
||||
wx.navigateTo({ url: '/pages/manage/batch-upload/batch-upload' })
|
||||
},
|
||||
goProgress() {
|
||||
wx.navigateTo({ url: '/pages/progress/progress-list/progress-list' })
|
||||
},
|
||||
goSettings() {
|
||||
wx.navigateTo({ url: '/pages/settings/settings' })
|
||||
},
|
||||
})
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
<view class="page">
|
||||
<scroll-view scroll-y class="content">
|
||||
<view class="header">
|
||||
<text class="title">词库管理</text>
|
||||
<text class="subtitle">管理并策划你的个人词汇集合。</text>
|
||||
</view>
|
||||
|
||||
<!-- <view class="toolbar">
|
||||
<button class="primary-btn" bindtap="goAdd">新增</button>
|
||||
<button class="secondary-btn" bindtap="goBatch">批量上传</button>
|
||||
<button class="secondary-btn" bindtap="goProgress">进度</button>
|
||||
<button class="secondary-btn" bindtap="goSettings">设置</button>
|
||||
</view> -->
|
||||
|
||||
<view class="search-row">
|
||||
<view class="search-box">
|
||||
<text class="search-icon">🔎</text>
|
||||
<text class="search-placeholder">搜索单词、短语或标签...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{loading}}" class="empty-state">
|
||||
<text class="empty-title">加载中...</text>
|
||||
<text class="empty-subtitle">正在同步词库数据</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{error}}" class="error-banner">
|
||||
<text class="error-text">{{error}}</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{!list.length}}" class="empty-state">
|
||||
<text class="empty-title">暂无词条</text>
|
||||
<text class="empty-subtitle">点击“新增”或“批量上传”开始构建词库</text>
|
||||
</view>
|
||||
|
||||
<view wx:else class="card-grid">
|
||||
<block wx:for="{{list}}" wx:key="id">
|
||||
<view class="word-card {{item.entry_type === 'sentence' ? 'pink' : 'cyan'}}" data-id="{{item.id}}" bindtap="goDetail">
|
||||
<view class="card-top">
|
||||
<view>
|
||||
<text class="word-title">{{item.en_text}}</text>
|
||||
<text class="phonetic">{{item.entry_type === 'sentence' ? '句子' : '单词'}}</text>
|
||||
</view>
|
||||
<view class="status-dot done">{{item.status}}</view>
|
||||
</view>
|
||||
<text class="meaning">{{item.entry_type === 'sentence' ? item.zh_text : item.zh_text}}</text>
|
||||
<text class="example" wx:if="{{item.entry_type === 'word' && item.example_text}}">例句:{{item.example_text}}</text>
|
||||
<text class="example" wx:elif="{{item.entry_type === 'sentence' && item.example_text}}">说明:{{item.example_text}}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="fab" bindtap="goAdd">+</view>
|
||||
</view>
|
||||
@ -1 +0,0 @@
|
||||
page{background:#0c0e12;color:#f6f6fc}.page{min-height:100vh;background:#0c0e12;box-sizing:border-box}.topbar{display:flex;justify-content:space-between;align-items:center;padding:24rpx 32rpx;background:rgba(12,14,18,.8);backdrop-filter:blur(24px);border-bottom:1rpx solid rgba(255,255,255,.08);box-shadow:0 1rpx 20rpx rgba(0,0,0,.08)}.brand{display:flex;align-items:center;gap:18rpx}.avatar-wrap{width:64rpx;height:64rpx;border-radius:9999rpx;overflow:hidden;border:1rpx solid rgba(255,255,255,.1);flex-shrink:0}.avatar{width:100%;height:100%}.brand-text{font-size:38rpx;font-weight:800;color:#c19cff}.icon-btn{width:72rpx;height:72rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center}.content{height:calc(100vh - 120rpx);padding:40rpx 32rpx 32rpx;box-sizing:border-box}.header{margin-bottom:28rpx}.title{display:block;font-size:52rpx;font-weight:800}.subtitle{display:block;margin-top:10rpx;color:#aaabb0;font-size:26rpx}.search-row{display:flex;flex-direction:column;gap:18rpx;margin-bottom:28rpx}.search-box{display:flex;align-items:center;gap:12rpx;padding:22rpx 26rpx;border-radius:9999rpx;background:#000;border:1rpx solid rgba(255,255,255,.1);color:#aaabb0}.search-placeholder{font-size:24rpx}.filters{display:flex;gap:14rpx;overflow-x:auto}.filter-btn{padding:18rpx 22rpx;border-radius:9999rpx;background:#23262c;color:#f6f6fc;font-size:22rpx;white-space:nowrap}.dim{color:#aaabb0;margin:0 4rpx}.card-grid{display:grid;grid-template-columns:1fr;gap:18rpx}.word-card{position:relative;overflow:hidden;padding:28rpx;border-radius:28rpx;background:rgba(29,32,37,.56);backdrop-filter:blur(24rpx);border:1rpx solid rgba(255,255,255,.06);box-shadow:0 20rpx 40rpx rgba(0,0,0,.06)}.cyan{box-shadow:0 20rpx 40rpx rgba(0,229,255,.05)}.purple{box-shadow:0 20rpx 40rpx rgba(127,0,255,.05)}.pink{box-shadow:0 20rpx 40rpx rgba(255,64,129,.05)}.wide{min-height:280rpx}.card-top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:18rpx}.word-title{display:block;font-size:38rpx;font-weight:800}.phonetic{display:block;margin-top:8rpx;font-size:22rpx;color:#aaabb0}.status-dot{width:56rpx;height:56rpx;border-radius:9999rpx;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06)}.done{color:#00e5ff}.learn{color:#c19cff}.review{color:#ff4081}.meaning{display:block;font-size:26rpx;color:#f6f6fc;line-height:1.6}.split{display:grid;grid-template-columns:1fr 1fr;gap:18rpx;align-items:start}.example{font-size:22rpx;color:#aaabb0;font-style:italic;border-left:4rpx solid rgba(193,156,255,.3);padding-left:14rpx;line-height:1.6}.progress-block{margin-top:22rpx;padding-top:18rpx;border-top:1rpx solid rgba(255,255,255,.05)}.progress-meta{display:flex;justify-content:space-between;font-size:20rpx;color:#aaabb0;margin-bottom:10rpx}.accent-cyan{color:#00e5ff}.accent-purple{color:#c19cff}.accent-pink{color:#ff4081}.progress-bar{height:10rpx;border-radius:9999rpx;background:#111318;overflow:hidden}.fill{height:100%;border-radius:9999rpx}.cyan-fill{width:95%;background:#00e5ff}.purple-fill{width:60%;background:#c19cff}.pink-fill{width:30%;background:#ff4081}.fab{position:fixed;right:28rpx;bottom:130rpx;width:96rpx;height:96rpx;border-radius:9999rpx;background:linear-gradient(135deg,#c19cff,#00e5ff);display:flex;align-items:center;justify-content:center;color:#fff;font-size:48rpx;box-shadow:0 0 20rpx rgba(193,156,255,.2)}
|
||||
36
me/me.js
36
me/me.js
@ -20,7 +20,7 @@ Page({
|
||||
this.setData({ loading: true, error: '' })
|
||||
await app.ensureLogin()
|
||||
if (!app.globalData.openid) {
|
||||
this.setData({ loading: false, error: '登录失败,请重试' })
|
||||
this.setData({ loading: false, error: '????????' })
|
||||
return
|
||||
}
|
||||
wx.request({
|
||||
@ -30,7 +30,7 @@ Page({
|
||||
success: (res) => {
|
||||
const profile = res.data?.data || {}
|
||||
const avatarUrl = profile.avatar_url || wx.getStorageSync(`avatarUrl:${app.globalData.openid}`) || ''
|
||||
const nickname = profile.nickname || '考研搭子'
|
||||
const nickname = profile.nickname || '????'
|
||||
const normalizedAvatar = avatarUrl.startsWith('http') ? avatarUrl : avatarUrl ? `${app.globalData.baseUrl}${avatarUrl}` : ''
|
||||
this.setData({
|
||||
openid: app.globalData.openid,
|
||||
@ -43,7 +43,7 @@ Page({
|
||||
fail: () => {
|
||||
const storedAvatarUrl = wx.getStorageSync(`avatarUrl:${app.globalData.openid}`) || ''
|
||||
const normalizedAvatar = storedAvatarUrl.startsWith('http') ? storedAvatarUrl : storedAvatarUrl ? `${app.globalData.baseUrl}${storedAvatarUrl}` : ''
|
||||
this.setData({ openid: app.globalData.openid, name: '考研搭子', nickname: '考研搭子', avatarUrl: normalizedAvatar, nicknameDraft: '考研搭子' })
|
||||
this.setData({ openid: app.globalData.openid, name: '????', nickname: '????', avatarUrl: normalizedAvatar, nicknameDraft: '????' })
|
||||
},
|
||||
complete: () => {
|
||||
this.loadAchievements()
|
||||
@ -52,13 +52,13 @@ Page({
|
||||
})
|
||||
},
|
||||
openNicknameModal() {
|
||||
this.setData({ showNicknameModal: true, nicknameDraft: this.data.nickname || this.data.name || '考研搭子' })
|
||||
this.setData({ showNicknameModal: true, nicknameDraft: this.data.nickname || this.data.name || '????' })
|
||||
},
|
||||
onAvatarError() {
|
||||
this.setData({ avatarUrl: '' })
|
||||
},
|
||||
closeNicknameModal() {
|
||||
this.setData({ showNicknameModal: false, nicknameDraft: this.data.nickname || this.data.name || '考研搭子' })
|
||||
this.setData({ showNicknameModal: false, nicknameDraft: this.data.nickname || this.data.name || '????' })
|
||||
},
|
||||
onNicknameInput(e) {
|
||||
this.setData({ nicknameDraft: e.detail.value })
|
||||
@ -67,7 +67,7 @@ Page({
|
||||
if (!app.globalData.openid) return
|
||||
const nickname = (this.data.nicknameDraft || '').trim()
|
||||
if (!nickname) {
|
||||
wx.showToast({ title: '昵称不能为空', icon: 'none' })
|
||||
wx.showToast({ title: '??????', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.request({
|
||||
@ -79,14 +79,14 @@ Page({
|
||||
const profile = res.data?.data || {}
|
||||
const nextNickname = profile.nickname || nickname
|
||||
this.setData({ nickname: nextNickname, name: nextNickname, nicknameDraft: nextNickname, showNicknameModal: false })
|
||||
wx.showToast({ title: '昵称已保存', icon: 'success' })
|
||||
wx.showToast({ title: '?????', icon: 'success' })
|
||||
},
|
||||
fail: () => wx.showToast({ title: '保存失败', icon: 'none' }),
|
||||
fail: () => wx.showToast({ title: '????', icon: 'none' }),
|
||||
})
|
||||
},
|
||||
chooseAvatar() {
|
||||
if (!app.globalData.openid) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
wx.showToast({ title: '????', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.chooseImage({
|
||||
@ -138,30 +138,30 @@ Page({
|
||||
data: { openid: app.globalData.openid },
|
||||
success: (profileRes) => {
|
||||
const profile = profileRes.data?.data || {}
|
||||
const nextNickname = profile.nickname || '考研搭子'
|
||||
const nextNickname = profile.nickname || '????'
|
||||
this.setData({ name: nextNickname, avatarUrl: fullUrl })
|
||||
},
|
||||
})
|
||||
wx.showToast({ title: '头像已上传', icon: 'success' })
|
||||
wx.showToast({ title: '?????', icon: 'success' })
|
||||
} catch (err) {
|
||||
wx.showToast({ title: '头像上传失败', icon: 'none' })
|
||||
wx.showToast({ title: '??????', icon: 'none' })
|
||||
}
|
||||
},
|
||||
fail: () => wx.showToast({ title: '头像上传失败', icon: 'none' }),
|
||||
fail: () => wx.showToast({ title: '??????', icon: 'none' }),
|
||||
})
|
||||
},
|
||||
fail: () => wx.showToast({ title: '头像处理失败', icon: 'none' }),
|
||||
fail: () => wx.showToast({ title: '??????', icon: 'none' }),
|
||||
}, this)
|
||||
})
|
||||
},
|
||||
fail: () => wx.showToast({ title: '头像处理失败', icon: 'none' }),
|
||||
fail: () => wx.showToast({ title: '??????', icon: 'none' }),
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
loadAchievements() {
|
||||
if (!app.globalData.openid) {
|
||||
this.setData({ error: '未获取到登录态' })
|
||||
this.setData({ error: '???????' })
|
||||
return
|
||||
}
|
||||
wx.request({
|
||||
@ -172,13 +172,13 @@ Page({
|
||||
const badges = Array.isArray(list) ? list.filter((i) => i.is_unlocked).length : 0
|
||||
this.setData({ badges })
|
||||
},
|
||||
fail: () => this.setData({ error: '成就数据加载失败' }),
|
||||
fail: () => this.setData({ error: '????????' }),
|
||||
})
|
||||
},
|
||||
goTo(e) {
|
||||
const { url } = e.currentTarget.dataset
|
||||
if (!app.globalData.openid) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
wx.showToast({ title: '????', icon: 'none' })
|
||||
return
|
||||
}
|
||||
wx.navigateTo({ url })
|
||||
|
||||
38
me/me.wxml
38
me/me.wxml
@ -1,14 +1,14 @@
|
||||
<view class="page">
|
||||
<view class="page">
|
||||
<scroll-view scroll-y class="content">
|
||||
<canvas canvas-id="avatar-canvas" class="avatar-canvas"></canvas>
|
||||
<view wx:if="{{loading}}" class="empty-state">
|
||||
<text class="empty-title">登录中...</text>
|
||||
<text class="empty-subtitle">正在获取你的登录态</text>
|
||||
<text class="empty-title">加载中...</text>
|
||||
<text class="empty-subtitle">正在获取个人信息</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{error}}" class="error-banner">
|
||||
<text class="error-text">{{error}}</text>
|
||||
<button class="secondary-btn error-btn" bindtap="loadProfile">重试登录</button>
|
||||
<button class="secondary-btn error-btn" bindtap="loadProfile">重试</button>
|
||||
</view>
|
||||
|
||||
<view wx:else class="hero-section">
|
||||
@ -16,7 +16,7 @@
|
||||
<view class="hero-avatar-border">
|
||||
<image class="hero-avatar" src="{{avatarUrl || '/assets/images/default-avatar.png'}}" mode="aspectFill" binderror="onAvatarError" />
|
||||
<view class="avatar-mask">
|
||||
<text class="avatar-mask-text">点击更换</text>
|
||||
<text class="avatar-mask-text">更换头像</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -24,24 +24,24 @@
|
||||
<text class="hero-name" bindtap="openNicknameModal">{{name}}</text>
|
||||
<view class="hero-badge">
|
||||
<view class="pulse-dot"></view>
|
||||
<text class="badge-text">累计学习 {{days}} 天</text>
|
||||
<text class="badge-text">坚持了 {{days}} 天</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{openid && badges === 0}}" class="empty-state small">
|
||||
<text class="empty-title">还没有勋章</text>
|
||||
<text class="empty-subtitle">完成复习和打卡后就会逐渐点亮</text>
|
||||
<text class="empty-title">还没有解锁成就</text>
|
||||
<text class="empty-subtitle">继续复习和打卡,成就会逐渐点亮</text>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{openid}}" class="grid-2">
|
||||
<view class="glass-card accent-tertiary" bindtap="goTo" data-url="/pages/achievements/achievements">
|
||||
<view class="glass-card accent-tertiary" bindtap="goTo" data-url="/package-stats/pages/achievements/achievements">
|
||||
<view class="card-glow"></view>
|
||||
<view class="card-icon icon-tertiary">🏅</view>
|
||||
<text class="card-title">成就墙</text>
|
||||
<text class="card-subtitle">已点亮 {{badges}} 枚勋章</text>
|
||||
<text class="card-subtitle">已解锁 {{badges}} 枚勋章</text>
|
||||
</view>
|
||||
<view class="glass-card accent-secondary" bindtap="goTo" data-url="/pages/checkin-detail/checkin-detail">
|
||||
<view class="glass-card accent-secondary" bindtap="goTo" data-url="/package-stats/pages/checkin-detail/checkin-detail">
|
||||
<view class="card-glow"></view>
|
||||
<view class="card-icon icon-secondary">📅</view>
|
||||
<text class="card-title">打卡详情</text>
|
||||
@ -56,27 +56,27 @@
|
||||
</view>
|
||||
|
||||
<view class="grid-2 management-grid">
|
||||
<view class="small-action" bindtap="goTo" data-url="/pages/vocab-manage/vocab-manage">
|
||||
<view class="small-action" bindtap="goTo" data-url="/package-vocab/pages/vocab-manage/vocab-manage">
|
||||
<view class="small-icon primary">📚</view>
|
||||
<text class="small-text">词库管理</text>
|
||||
</view>
|
||||
<view class="small-action" bindtap="goTo" data-url="/pages/entry-edit/entry-edit">
|
||||
<view class="small-action" bindtap="goTo" data-url="/package-vocab/pages/entry-edit/entry-edit">
|
||||
<view class="small-icon secondary">+</view>
|
||||
<text class="small-text">手动新增</text>
|
||||
</view>
|
||||
<view class="small-action" bindtap="goTo" data-url="/pages/batch-upload/batch-upload">
|
||||
<view class="small-action" bindtap="goTo" data-url="/package-vocab/pages/batch-upload/batch-upload">
|
||||
<view class="small-icon tertiary">☁</view>
|
||||
<text class="small-text">批量上传</text>
|
||||
</view>
|
||||
<view class="small-action" bindtap="goTo" data-url="/pages/progress-list/progress-list">
|
||||
<view class="small-action" bindtap="goTo" data-url="/package-stats/pages/progress-list/progress-list">
|
||||
<view class="small-icon primary-fixed">≡</view>
|
||||
<text class="small-text">进度列表</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="settings-card" bindtap="goTo" data-url="/pages/settings/settings">
|
||||
<view class="settings-card" bindtap="goTo" data-url="/package-stats/pages/settings/settings">
|
||||
<view class="settings-icon">⚙</view>
|
||||
<text class="settings-text">个性化设置</text>
|
||||
<text class="settings-text">设置中心</text>
|
||||
<view class="chevron">›</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@ -97,7 +97,7 @@
|
||||
|
||||
<view class="bottom-nav">
|
||||
<view class="nav-item" bindtap="goHome"><text class="nav-icon">⌂</text><text class="nav-label">首页</text></view>
|
||||
<view class="nav-item" bindtap="goToReview"><text class="nav-icon">📖</text><text class="nav-label">复习</text></view>
|
||||
<view class="nav-item" bindtap="goToReview"><text class="nav-icon">↻</text><text class="nav-label">复习</text></view>
|
||||
<view class="nav-item active"><text class="nav-icon">☺</text><text class="nav-label">我的</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -1,45 +0,0 @@
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
list: [],
|
||||
loading: false,
|
||||
error: '',
|
||||
},
|
||||
onShow() {
|
||||
this.loadList()
|
||||
},
|
||||
loadList() {
|
||||
if (!app.globalData.openid) {
|
||||
this.setData({ error: '请先登录' })
|
||||
return
|
||||
}
|
||||
this.setData({ loading: true, error: '' })
|
||||
wx.request({
|
||||
url: `${app.globalData.baseUrl}/api/v1/entries`,
|
||||
header: { 'X-OpenID': app.globalData.openid },
|
||||
success: (res) => {
|
||||
const payload = res.data?.data || []
|
||||
this.setData({ list: payload })
|
||||
},
|
||||
fail: () => this.setData({ error: '词库加载失败' }),
|
||||
complete: () => this.setData({ loading: false }),
|
||||
})
|
||||
},
|
||||
goAdd() {
|
||||
wx.navigateTo({ url: '/pages/entry-edit/entry-edit' })
|
||||
},
|
||||
goDetail(e) {
|
||||
const { id } = e.currentTarget.dataset
|
||||
wx.navigateTo({ url: `/pages/entry-detail/entry-detail?id=${id}` })
|
||||
},
|
||||
goBatch() {
|
||||
wx.navigateTo({ url: '/pages/batch-upload/batch-upload' })
|
||||
},
|
||||
goProgress() {
|
||||
wx.navigateTo({ url: '/pages/progress-list/progress-list' })
|
||||
},
|
||||
goSettings() {
|
||||
wx.navigateTo({ url: '/pages/settings/settings' })
|
||||
},
|
||||
})
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"usingComponents": {}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
<view class="page">
|
||||
<scroll-view scroll-y class="content">
|
||||
<view class="header">
|
||||
<text class="title">词库管理</text>
|
||||
<text class="subtitle">管理并策划你的个人词汇集合。</text>
|
||||
</view>
|
||||
|
||||
<!-- <view class="toolbar">
|
||||
<button class="primary-btn" bindtap="goAdd">新增</button>
|
||||
<button class="secondary-btn" bindtap="goBatch">批量上传</button>
|
||||
<button class="secondary-btn" bindtap="goProgress">进度</button>
|
||||
<button class="secondary-btn" bindtap="goSettings">设置</button>
|
||||
</view> -->
|
||||
|
||||
<view class="search-row">
|
||||
<view class="search-box">
|
||||
<text class="search-icon">🔎</text>
|
||||
<text class="search-placeholder">搜索单词、短语或标签...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{loading}}" class="empty-state">
|
||||
<text class="empty-title">加载中...</text>
|
||||
<text class="empty-subtitle">正在同步词库数据</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{error}}" class="error-banner">
|
||||
<text class="error-text">{{error}}</text>
|
||||
</view>
|
||||
|
||||
<view wx:elif="{{!list.length}}" class="empty-state">
|
||||
<text class="empty-title">暂无词条</text>
|
||||
<text class="empty-subtitle">点击“新增”或“批量上传”开始构建词库</text>
|
||||
</view>
|
||||
|
||||
<view wx:else class="card-grid">
|
||||
<block wx:for="{{list}}" wx:key="id">
|
||||
<view class="word-card {{item.entry_type === 'sentence' ? 'pink' : 'cyan'}}" data-id="{{item.id}}" bindtap="goDetail">
|
||||
<view class="card-top">
|
||||
<view>
|
||||
<text class="word-title">{{item.en_text}}</text>
|
||||
<text class="phonetic">{{item.entry_type === 'sentence' ? '句子' : '单词'}}</text>
|
||||
</view>
|
||||
<view class="status-dot done">{{item.status}}</view>
|
||||
</view>
|
||||
<text class="meaning">{{item.entry_type === 'sentence' ? item.zh_text : item.zh_text}}</text>
|
||||
<text class="example" wx:if="{{item.entry_type === 'word' && item.example_text}}">例句:{{item.example_text}}</text>
|
||||
<text class="example" wx:elif="{{item.entry_type === 'sentence' && item.example_text}}">说明:{{item.example_text}}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="fab" bindtap="goAdd">+</view>
|
||||
</view>
|
||||
@ -1 +0,0 @@
|
||||
page{background:#0c0e12;color:#f6f6fc}.page{min-height:100vh;background:#0c0e12;box-sizing:border-box}.topbar{display:flex;justify-content:space-between;align-items:center;padding:24rpx 32rpx;background:rgba(12,14,18,.8);backdrop-filter:blur(24px);border-bottom:1rpx solid rgba(255,255,255,.08);box-shadow:0 1rpx 20rpx rgba(0,0,0,.08)}.brand{display:flex;align-items:center;gap:18rpx}.avatar-wrap{width:64rpx;height:64rpx;border-radius:9999rpx;overflow:hidden;border:1rpx solid rgba(255,255,255,.1);flex-shrink:0}.avatar{width:100%;height:100%}.brand-text{font-size:38rpx;font-weight:800;color:#c19cff}.icon-btn{width:72rpx;height:72rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center}.content{height:calc(100vh - 120rpx);padding:40rpx 32rpx 32rpx;box-sizing:border-box}.header{margin-bottom:28rpx}.title{display:block;font-size:52rpx;font-weight:800}.subtitle{display:block;margin-top:10rpx;color:#aaabb0;font-size:26rpx}.search-row{display:flex;flex-direction:column;gap:18rpx;margin-bottom:28rpx}.search-box{display:flex;align-items:center;gap:12rpx;padding:22rpx 26rpx;border-radius:9999rpx;background:#000;border:1rpx solid rgba(255,255,255,.1);color:#aaabb0}.search-placeholder{font-size:24rpx}.filters{display:flex;gap:14rpx;overflow-x:auto}.filter-btn{padding:18rpx 22rpx;border-radius:9999rpx;background:#23262c;color:#f6f6fc;font-size:22rpx;white-space:nowrap}.dim{color:#aaabb0;margin:0 4rpx}.card-grid{display:grid;grid-template-columns:1fr;gap:18rpx}.word-card{position:relative;overflow:hidden;padding:28rpx;border-radius:28rpx;background:rgba(29,32,37,.56);backdrop-filter:blur(24rpx);border:1rpx solid rgba(255,255,255,.06);box-shadow:0 20rpx 40rpx rgba(0,0,0,.06)}.cyan{box-shadow:0 20rpx 40rpx rgba(0,229,255,.05)}.purple{box-shadow:0 20rpx 40rpx rgba(127,0,255,.05)}.pink{box-shadow:0 20rpx 40rpx rgba(255,64,129,.05)}.wide{min-height:280rpx}.card-top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:18rpx}.word-title{display:block;font-size:38rpx;font-weight:800}.phonetic{display:block;margin-top:8rpx;font-size:22rpx;color:#aaabb0}.status-dot{width:56rpx;height:56rpx;border-radius:9999rpx;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06)}.done{color:#00e5ff}.learn{color:#c19cff}.review{color:#ff4081}.meaning{display:block;font-size:26rpx;color:#f6f6fc;line-height:1.6}.split{display:grid;grid-template-columns:1fr 1fr;gap:18rpx;align-items:start}.example{font-size:22rpx;color:#aaabb0;font-style:italic;border-left:4rpx solid rgba(193,156,255,.3);padding-left:14rpx;line-height:1.6}.progress-block{margin-top:22rpx;padding-top:18rpx;border-top:1rpx solid rgba(255,255,255,.05)}.progress-meta{display:flex;justify-content:space-between;font-size:20rpx;color:#aaabb0;margin-bottom:10rpx}.accent-cyan{color:#00e5ff}.accent-purple{color:#c19cff}.accent-pink{color:#ff4081}.progress-bar{height:10rpx;border-radius:9999rpx;background:#111318;overflow:hidden}.fill{height:100%;border-radius:9999rpx}.cyan-fill{width:95%;background:#00e5ff}.purple-fill{width:60%;background:#c19cff}.pink-fill{width:30%;background:#ff4081}.fab{position:fixed;right:28rpx;bottom:130rpx;width:96rpx;height:96rpx;border-radius:9999rpx;background:linear-gradient(135deg,#c19cff,#00e5ff);display:flex;align-items:center;justify-content:center;color:#fff;font-size:48rpx;box-shadow:0 0 20rpx rgba(193,156,255,.2)}
|
||||
Loading…
Reference in New Issue
Block a user