diff --git a/batch-upload/batch-upload.js b/batch-upload/batch-upload.js index b485ca6..9702b18 100644 --- a/batch-upload/batch-upload.js +++ b/batch-upload/batch-upload.js @@ -7,10 +7,28 @@ Page({ loading: false, error: '', }, + downloadTemplate() { + wx.downloadFile({ + url: `${app.globalData.baseUrl}/api/v1/entries/template`, + success: (res) => { + if (res.statusCode !== 200) { + this.setData({ error: '模板下载失败' }) + return + } + wx.openDocument({ + filePath: res.tempFilePath, + fileType: 'xlsx', + fail: () => this.setData({ error: '模板打开失败,请先保存到本地再上传' }), + }) + }, + fail: () => this.setData({ error: '模板下载失败' }), + }) + }, chooseFile() { wx.chooseMessageFile({ count: 1, type: 'file', + extension: ['xlsx'], success: (res) => { const file = res.tempFiles[0] this.setData({ fileName: file.name, loading: true, error: '' }) diff --git a/batch-upload/batch-upload.wxml b/batch-upload/batch-upload.wxml index b75bf50..83e2505 100644 --- a/batch-upload/batch-upload.wxml +++ b/batch-upload/batch-upload.wxml @@ -8,10 +8,14 @@ 批量上传 - 上传 Excel 文件导入单词或句子。 + 先下载模板,按模板填写后直接上传单词或句子。 + + + + - 已选择:{{fileName}} + {{error}} 总数:{{result.total}} 成功:{{result.success}} diff --git a/batch-upload/batch-upload.wxss b/batch-upload/batch-upload.wxss index 88904dd..813983c 100644 --- a/batch-upload/batch-upload.wxss +++ b/batch-upload/batch-upload.wxss @@ -1 +1 @@ -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:24rpx}.layout{display:grid;grid-template-columns:1fr;gap:24rpx}.instruction-card,.upload-card,.feedback-card,.step-card,.dropzone{background:rgba(29,32,37,.56);border:1rpx solid rgba(255,255,255,.08);border-radius:28rpx;box-sizing:border-box}.instruction-card{padding:24rpx}.section-title{display:block;font-size:28rpx;font-weight:700;margin-bottom:18rpx}.steps{display:flex;flex-direction:column;gap:18rpx}.step{display:flex;align-items:stretch;gap:16rpx}.step-dot{width:44rpx;height:44rpx;border-radius:9999rpx;background:#23262c;color:#aaabb0;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20rpx;font-weight:700;margin-top:10rpx}.active-dot{background:#c19cff;color:#000}.step-card{flex:1;padding:18rpx;background:#171a1f}.low{background:#111318}.step-title{display:block;font-size:24rpx;font-weight:700;margin-bottom:6rpx}.step-desc{display:block;font-size:20rpx;color:#aaabb0}.download{display:block;margin-top:12rpx;font-size:20rpx;color:#00e5ff}.upload-card{display:flex;flex-direction:column;gap:18rpx}.dropzone{padding:40rpx 28rpx;min-height:360rpx;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;background:rgba(29,32,37,.4)}.upload-icon{width:112rpx;height:112rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font-size:48rpx;color:#c19cff;margin-bottom:18rpx}.drop-title{display:block;font-size:34rpx;font-weight:800;margin-bottom:10rpx}.drop-desc{display:block;font-size:22rpx;color:#aaabb0;line-height:1.6;margin-bottom:24rpx}.choose-btn{border-radius:9999rpx;padding:20rpx 30rpx;background:linear-gradient(90deg,#c19cff,#9146ff);color:#fff;font-weight:700}.feedback-card{padding:24rpx;display:flex;flex-direction:column;gap:16rpx}.feedback-left{display:flex;align-items:center;gap:16rpx}.status-icon{width:56rpx;height:56rpx;border-radius:9999rpx;background:#111318;display:flex;align-items:center;justify-content:center;color:#00e5ff}.feedback-title{display:block;font-size:24rpx;font-weight:700}.feedback-file{display:block;font-size:20rpx;color:#aaabb0}.feedback-stats{display:flex;align-items:center;gap:24rpx;justify-content:flex-end}.stat{text-align:center}.stat-num{display:block;font-size:34rpx;font-weight:800}.good{color:#00e5ff}.bad{color:#aaabb0}.stat-label{display:block;font-size:18rpx;color:#aaabb0}.divider{width:1rpx;height:34rpx;background:rgba(255,255,255,.08)} +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:24rpx}.layout{display:grid;grid-template-columns:1fr;gap:24rpx}.instruction-card,.upload-card,.feedback-card,.step-card,.dropzone{background:rgba(29,32,37,.56);border:1rpx solid rgba(255,255,255,.08);border-radius:28rpx;box-sizing:border-box}.instruction-card{padding:24rpx}.section-title{display:block;font-size:28rpx;font-weight:700;margin-bottom:18rpx}.steps{display:flex;flex-direction:column;gap:18rpx}.step{display:flex;align-items:stretch;gap:16rpx}.step-dot{width:44rpx;height:44rpx;border-radius:9999rpx;background:#23262c;color:#aaabb0;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20rpx;font-weight:700;margin-top:10rpx}.active-dot{background:#c19cff;color:#000}.step-card{flex:1;padding:18rpx;background:#171a1f}.low{background:#111318}.step-title{display:block;font-size:24rpx;font-weight:700;margin-bottom:6rpx}.step-desc{display:block;font-size:20rpx;color:#aaabb0}.download{display:block;margin-top:12rpx;font-size:20rpx;color:#00e5ff}.upload-card{display:flex;flex-direction:column;gap:18rpx}.dropzone{padding:40rpx 28rpx;min-height:360rpx;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;background:rgba(29,32,37,.4)}.upload-icon{width:112rpx;height:112rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center;font-size:48rpx;color:#c19cff;margin-bottom:18rpx}.drop-title{display:block;font-size:34rpx;font-weight:800;margin-bottom:10rpx}.drop-desc{display:block;font-size:22rpx;color:#aaabb0;line-height:1.6;margin-bottom:24rpx}.action-row{display:flex;gap:20rpx}.action-btn{flex:1;border-radius:9999rpx;padding:22rpx 24rpx;font-size:28rpx;font-weight:700;line-height:1;text-align:center;box-sizing:border-box;border:1rpx solid transparent}.primary-btn{background:linear-gradient(90deg,#c19cff,#9146ff);color:#fff;box-shadow:0 16rpx 32rpx rgba(145,70,255,.22)}.ghost-btn{background:rgba(255,255,255,.04);color:#f6f6fc;border-color:rgba(255,255,255,.1)}.action-btn::after{border:none}.primary-btn:active{opacity:.92;transform:translateY(1rpx)}.ghost-btn:active{background:rgba(255,255,255,.08)}.info{margin-top:18rpx;padding:16rpx 20rpx;border-radius:20rpx;background:rgba(255,255,255,.04);color:#d7d7de;font-size:22rpx}.feedback-card{padding:24rpx;display:flex;flex-direction:column;gap:16rpx}.feedback-left{display:flex;align-items:center;gap:16rpx}.status-icon{width:56rpx;height:56rpx;border-radius:9999rpx;background:#111318;display:flex;align-items:center;justify-content:center;color:#00e5ff}.feedback-title{display:block;font-size:24rpx;font-weight:700}.feedback-file{display:block;font-size:20rpx;color:#aaabb0}.feedback-stats{display:flex;align-items:center;gap:24rpx;justify-content:flex-end}.stat{text-align:center}.stat-num{display:block;font-size:34rpx;font-weight:800}.good{color:#00e5ff}.bad{color:#aaabb0}.stat-label{display:block;font-size:18rpx;color:#aaabb0}.divider{width:1rpx;height:34rpx;background:rgba(255,255,255,.08)} diff --git a/entry-detail/entry-detail.js b/entry-detail/entry-detail.js new file mode 100644 index 0000000..704d528 --- /dev/null +++ b/entry-detail/entry-detail.js @@ -0,0 +1,70 @@ +const app = getApp() + +Page({ + data: { + entry: null, + loading: false, + error: '', + }, + onLoad(options) { + this.entryId = options.id + this.loadEntry() + }, + loadEntry() { + if (!app.globalData.openid) { + this.setData({ error: '请先登录' }) + return + } + if (!this.entryId) { + this.setData({ error: '缺少词条ID' }) + return + } + this.setData({ loading: true, error: '' }) + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/entries/${this.entryId}`, + header: { 'X-OpenID': app.globalData.openid }, + success: (res) => { + const entry = res.data?.data || null + this.setData({ entry, error: entry ? '' : '未找到词条' }) + }, + fail: () => this.setData({ error: '词条加载失败' }), + complete: () => this.setData({ loading: false }), + }) + }, + editEntry() { + if (!this.data.entry?.id) return + wx.navigateTo({ url: `/pages/entry-edit/entry-edit?id=${this.data.entry.id}` }) + }, + deleteEntry() { + if (!this.data.entry?.id) return + wx.showModal({ + title: '确认删除', + content: '删除后无法恢复,是否继续?', + success: (res) => { + if (!res.confirm) return + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/entries/${this.data.entry.id}`, + method: 'DELETE', + header: { 'X-OpenID': app.globalData.openid }, + success: () => { + wx.showToast({ title: '已删除', icon: 'success' }) + const pages = getCurrentPages() + const prevPage = pages[pages.length - 2] + if (prevPage && typeof prevPage.loadList === 'function') { + prevPage.loadList() + } + wx.navigateBack({ delta: 1 }) + }, + }) + }, + }) + }, + goBack() { + const pages = getCurrentPages() + const prevPage = pages[pages.length - 2] + if (prevPage && typeof prevPage.loadList === 'function') { + prevPage.loadList() + } + wx.navigateBack() + }, +}) diff --git a/entry-detail/entry-detail.json b/entry-detail/entry-detail.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/entry-detail/entry-detail.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/entry-detail/entry-detail.wxml b/entry-detail/entry-detail.wxml new file mode 100644 index 0000000..a2f3670 --- /dev/null +++ b/entry-detail/entry-detail.wxml @@ -0,0 +1,60 @@ + + + + + + + + + {{entry.entry_type === 'sentence' ? '句子' : '单词'}} + + + 🗑 + + + + {{entry.en_text}} + {{entry.entry_type === 'sentence' ? '翻译:' : '释义:'}}{{entry.zh_text}} + + 来源:{{entry.source_type}} + 状态:{{entry.status}} + + + + + 词条详情 + 查看单词或句子的完整信息 + + + + 加载中... + + + + {{error}} + + + + + 类型 + {{entry.entry_type === 'sentence' ? '句子' : '单词'}} + + + 内容 + {{entry.en_text}} + + + {{entry.entry_type === 'sentence' ? '翻译' : '释义'}} + {{entry.zh_text}} + + + {{entry.entry_type === 'word' ? '例句' : '补充说明'}} + {{entry.example_text}} + + + 来源 + {{entry.source_type}} + + + + diff --git a/entry-detail/entry-detail.wxss b/entry-detail/entry-detail.wxss new file mode 100644 index 0000000..96222db --- /dev/null +++ b/entry-detail/entry-detail.wxss @@ -0,0 +1,241 @@ +page { + background: #0c0e12; + color: #f6f6fc; +} + +.page { + min-height: 100vh; + background: #0c0e12; + position: relative; + overflow: hidden; + box-sizing: border-box; +} + +.bg-orb { + position: absolute; + border-radius: 9999rpx; + filter: blur(110rpx); + pointer-events: none; + z-index: 0; +} + +.orb1 { + width: 46vw; + height: 46vw; + top: -14vw; + right: -14vw; + background: rgba(193, 156, 255, 0.12); +} + +.orb2 { + width: 54vw; + height: 54vw; + left: -18vw; + bottom: -16vw; + background: rgba(0, 227, 253, 0.08); +} + +.content { + position: relative; + z-index: 1; + height: 100vh; + padding: 26rpx 32rpx 40rpx; + box-sizing: border-box; +} + +.hero-card { + position: relative; + overflow: hidden; + border-radius: 34rpx; + padding: 34rpx; + border: 1rpx solid rgba(255, 255, 255, 0.08); + background: rgba(29, 32, 37, 0.72); + box-shadow: 0 18rpx 60rpx rgba(0, 0, 0, 0.18); + margin-bottom: 28rpx; +} + +.hero-card::after { + content: ''; + position: absolute; + inset: auto -40rpx -40rpx auto; + width: 180rpx; + height: 180rpx; + border-radius: 9999rpx; + filter: blur(24rpx); + opacity: 0.4; +} + +.hero-card.cyan::after { + background: rgba(0, 227, 253, 0.45); +} + +.hero-card.pink::after { + background: rgba(255, 108, 149, 0.45); +} + +.hero-top { + position: relative; + z-index: 1; + display: flex; + justify-content: flex-end; + margin-bottom: 24rpx; +} + +.hero-title-group { + display: flex; + align-items: flex-start; + gap: 16rpx; +} + +.type-chip { + display: inline-flex; + align-items: center; + justify-content: center; + height: 60rpx; + padding: 0 22rpx; + border-radius: 9999rpx; + font-size: 22rpx; + font-weight: 700; + color: #00e3fd; + border: 1rpx solid rgba(255, 255, 255, 0.08); + background: rgba(255, 255, 255, 0.04); +} + +.hero-actions-vertical { + display: flex; + flex-direction: column; + gap: 12rpx; +} + +.mini-action { + width: 52rpx; + height: 52rpx; + border-radius: 16rpx; + display: flex; + align-items: center; + justify-content: center; + font-size: 26rpx; + background: rgba(255, 255, 255, 0.06); + border: 1rpx solid rgba(255, 255, 255, 0.08); + color: #f6f6fc; +} + +.mini-action.danger { + color: #ff7b9b; +} + +.main-text { + position: relative; + z-index: 1; + display: block; + font-size: 46rpx; + line-height: 1.25; + font-weight: 800; + letter-spacing: -0.5rpx; +} + +.translate { + position: relative; + z-index: 1; + display: block; + margin-top: 16rpx; + color: #f6f6fc; + font-size: 28rpx; + line-height: 1.7; +} + +.detail-badges { + position: relative; + z-index: 1; + display: flex; + flex-wrap: wrap; + gap: 12rpx; + margin-top: 20rpx; +} + +.badge-pill { + padding: 12rpx 18rpx; + border-radius: 9999rpx; + font-size: 22rpx; + color: #aaabb0; + border: 1rpx solid rgba(255, 255, 255, 0.06); + background: rgba(255, 255, 255, 0.03); +} + +.header { + margin-bottom: 24rpx; +} + +.title { + display: block; + font-size: 52rpx; + line-height: 1.1; + font-weight: 800; +} + +.subtitle { + display: block; + margin-top: 10rpx; + color: #aaabb0; + font-size: 24rpx; +} + +.info-card { + padding: 28rpx; + border-radius: 30rpx; + background: rgba(255, 255, 255, 0.04); + border: 1rpx solid rgba(255, 255, 255, 0.08); + margin-bottom: 26rpx; +} + +.info-row { + display: flex; + gap: 18rpx; + padding: 18rpx 0; + border-bottom: 1rpx solid rgba(255, 255, 255, 0.06); +} + +.info-row:last-child { + border-bottom: 0; + padding-bottom: 0; +} + +.info-label { + width: 120rpx; + flex-shrink: 0; + font-size: 24rpx; + color: #aaabb0; + font-weight: 700; +} + +.info-value { + flex: 1; + font-size: 26rpx; + color: #f6f6fc; + line-height: 1.6; +} + +.empty-state { + padding: 60rpx 20rpx; + text-align: center; + color: #aaabb0; +} + +.empty-title { + display: block; + font-size: 28rpx; + font-weight: 700; + color: #f6f6fc; +} + +.error-banner { + padding: 24rpx 28rpx; + border-radius: 20rpx; + background: rgba(167, 1, 56, 0.2); + border: 1rpx solid rgba(255, 110, 132, 0.35); +} + +.error-text { + color: #ffb2b9; + font-size: 24rpx; +} diff --git a/index/index.wxml b/index/index.wxml index 74653b4..4b7d3ce 100644 --- a/index/index.wxml +++ b/index/index.wxml @@ -1,7 +1,7 @@ - 学习驾驶舱 + 你好,同学! 专注高频复习,持续积累词库