commit aff4457858976ec93818caed12ddf26c54ef1223 Author: 陈佳慧 <2488672761@qq.com> Date: Fri Oct 11 01:43:38 2024 +0800 Initial commit on main branch diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..115cc02 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,31 @@ +/* + * Eslint config file + * Documentation: https://eslint.org/docs/user-guide/configuring/ + * Install the Eslint extension before using this feature. + */ +module.exports = { + env: { + es6: true, + browser: true, + node: true, + }, + ecmaFeatures: { + modules: true, + }, + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + globals: { + wx: true, + App: true, + Page: true, + getCurrentPages: true, + getApp: true, + Component: true, + requirePlugin: true, + requireMiniProgram: true, + }, + // extends: 'eslint:recommended', + rules: {}, +} diff --git a/app.js b/app.js new file mode 100644 index 0000000..639f081 --- /dev/null +++ b/app.js @@ -0,0 +1,80 @@ +// app.js +App({ + onLaunch() { + // 监听页面不存在的情况 + wx.onPageNotFound(function(res) { + console.error('Page not found:', res); + wx.redirectTo({ + url: 'pages/participated/participated' + }) + }) + + // 获取本地存储的用户信息 + const userInfo = wx.getStorageSync('userInfo') + if (userInfo) { + this.globalData.userInfo = userInfo + this.globalData.isLoggedIn = true + } + + // 获取本地存储的积分 + const score = wx.getStorageSync('score') + if (score) { + this.globalData.score = score + } + }, + + onShow(options) { + // 小程序从后台进入前台时触发 + console.log('小程序显示', options) + }, + + onHide() { + // 小程序从前台进入后台时触发 + console.log('小程序隐藏') + }, + + globalData: { + userInfo: null, + isLoggedIn: false, + token: '', + score: 0, + activities: [], + participatedActivities: [] + }, + + // 全局方法 + setUserInfo(userInfo) { + this.globalData.userInfo = userInfo + this.globalData.isLoggedIn = true + wx.setStorageSync('userInfo', userInfo) + }, + + clearUserInfo() { + this.globalData.userInfo = null + this.globalData.isLoggedIn = false + this.globalData.token = '' + wx.removeStorageSync('userInfo') + }, + + updateScore(delta) { + this.globalData.score += delta + wx.setStorageSync('score', this.globalData.score) + }, + + addActivity(activity) { + this.globalData.activities.push(activity) + }, + + addParticipatedActivity(activity) { + this.globalData.participatedActivities.push(activity) + }, + + // 模拟随机点名 + randomNameCall(activityId) { + // 这里应该根据 activityId 获取对应活动的参与者列表 + // 为了演示,我们使用一个固定的名单 + const participants = ['张三', '李四', '王五', '赵六', '钱七'] + const randomIndex = Math.floor(Math.random() * participants.length) + return participants[randomIndex] + } +}) diff --git a/app.json b/app.json new file mode 100644 index 0000000..09573a8 --- /dev/null +++ b/app.json @@ -0,0 +1,52 @@ +{ + "pages": [ + "pages/login/login", + "pages/created/created", + "pages/participated/participated", + "pages/store/store", + "pages/createActivity/createActivity", + "pages/participatedDetail/participatedDetail", + "pages/test/test" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "点名小程序", + "navigationBarTextStyle": "black" + }, + "tabBar": { + "color": "#999999", + "selectedColor": "#0d94ff", + "backgroundColor": "#ffffff", + "list": [ + { + "pagePath": "pages/created/created", + "text": "我创建的", + "iconPath": "assets/icon-created.png", + "selectedIconPath": "assets/icon-created-active.png" + }, + { + "pagePath": "pages/participated/participated", + "text": "我参与的", + "iconPath": "assets/icon-participated.png", + "selectedIconPath": "assets/icon-participated-active.png" + }, + { + "pagePath": "pages/store/store", + "text": "商店", + "iconPath": "assets/icon-store.png", + "selectedIconPath": "assets/icon-store-active.png" + } + ] + }, + "style": "v2", + "sitemapLocation": "sitemap.json", + "networkTimeout": { + "request": 10000 + }, + "permission": { + "scope.userLocation": { + "desc": "你的位置信息将用于小程序位置接口的效果展示" + } + } +} \ No newline at end of file diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..06c6fc9 --- /dev/null +++ b/app.wxss @@ -0,0 +1,10 @@ +/**app.wxss**/ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} diff --git a/assets/icon-created-active.png b/assets/icon-created-active.png new file mode 100644 index 0000000..0669448 Binary files /dev/null and b/assets/icon-created-active.png differ diff --git a/assets/icon-created.png b/assets/icon-created.png new file mode 100644 index 0000000..11cf8d1 Binary files /dev/null and b/assets/icon-created.png differ diff --git a/assets/icon-participated-active.png b/assets/icon-participated-active.png new file mode 100644 index 0000000..d0e2f08 Binary files /dev/null and b/assets/icon-participated-active.png differ diff --git a/assets/icon-participated.png b/assets/icon-participated.png new file mode 100644 index 0000000..ea54a89 Binary files /dev/null and b/assets/icon-participated.png differ diff --git a/assets/icon-store-active.png b/assets/icon-store-active.png new file mode 100644 index 0000000..474dc85 Binary files /dev/null and b/assets/icon-store-active.png differ diff --git a/assets/icon-store.png b/assets/icon-store.png new file mode 100644 index 0000000..a65435b Binary files /dev/null and b/assets/icon-store.png differ diff --git a/instruction.md b/instruction.md new file mode 100644 index 0000000..dda8268 --- /dev/null +++ b/instruction.md @@ -0,0 +1,12 @@ +一个微信小程序 +1.你是一个经验丰富的ui设计师,风格简洁 +2.你现在已经在一个微信小程序的项目中,因此不需要生成目录结构 +3.做一个点名小程序 +4.首先需要一个登录页面,用户输入账号和密码,登陆成功后进入“我创建的”页面 +5.导航栏位于页面的底部,分别是我创建的,我参与的,商店 +6.“我创建的”页面上方有一个搜索框,下方有一个创建自定义按钮,点击“创建自定义”按钮可以进入创建活动页面,创建活动页面有活动名称,活动描述和上传xlsx文件,创建成功后返回“我创建的”页面,“我创建的”页面会出现一个活动组件,活动组件有活动名称和参与人数,点击活动组件可以进入活动详情页 +7.活动详情页有随机点名和回答问题两个按钮,点击随机点名按钮后,会随机抽取1个用户并显示在页面中,点击回答问题按钮会随机抽取1个用户并显示在页面中,按钮下方有加1分和减1分按钮,点击加一分按钮后,用户积分加一,点击减一分按钮后,用户积分减一 +8.点击“我参与的”可以找到我参与的活动,假设已经存在一个活动,活动名称是2024软件工程K班,活动人数为104人,点击此活动可以进入活动参与详情页,活动参与详情页有签到和“使用卡牌”两个按钮,点击“签到”按钮即可签到,“使用卡牌”按钮上方有一个显示框,会显示需要回答问题的用户 +9.点击商店按钮可以进入商店页面,商店页面有4个卡牌和需要积分的数量,点击购买按钮后积分减少,商店页面下方有一个猜题赢积分按钮,点击后会弹出一个弹窗,弹窗中有一个问题,用户输入答案后点击提交按钮,如果答案正确则积分加一 +10.背景颜色为#f4f3f3,按钮颜色为#0d94ff,按钮全部为圆角矩形 +11.主标题字号20px,副标题字号为16px,正文字号为14px,按钮标题为14px \ No newline at end of file diff --git a/pages/activityDetail/activityDetail.js b/pages/activityDetail/activityDetail.js new file mode 100644 index 0000000..78cc939 --- /dev/null +++ b/pages/activityDetail/activityDetail.js @@ -0,0 +1,39 @@ +Page({ + data: { + activity: null, + selectedUser: null + }, + + onLoad(options) { + const activityId = options.id; + this.fetchActivityDetails(activityId); + }, + + fetchActivityDetails(id) { + // 这里应该从后端 API 获取活动详情 + const mockActivity = { id: 1, name: '软件工程课程', participants: 50 }; + this.setData({ activity: mockActivity }); + }, + + randomNameCall() { + // 这里应该从后端 API 获取随机用户 + const randomUser = '张三'; + this.setData({ selectedUser: randomUser }); + }, + + randomQuestion() { + // 这里应该从后端 API 获取随机用户 + const randomUser = '李四'; + this.setData({ selectedUser: randomUser }); + }, + + addScore() { + // 这里应该调用后端 API 增加用户积分 + wx.showToast({ title: '积分已增加', icon: 'success' }); + }, + + minusScore() { + // 这里应该调用后端 API 减少用户积分 + wx.showToast({ title: '积分已减少', icon: 'success' }); + } +}); \ No newline at end of file diff --git a/pages/activityDetail/activityDetail.wxml b/pages/activityDetail/activityDetail.wxml new file mode 100644 index 0000000..9dc0b6d --- /dev/null +++ b/pages/activityDetail/activityDetail.wxml @@ -0,0 +1,17 @@ + + + 活动名称 + 参与人数: 50 + + + + + + + {{selectedUser}} + + + + + + \ No newline at end of file diff --git a/pages/activityDetail/activityDetail.wxss b/pages/activityDetail/activityDetail.wxss new file mode 100644 index 0000000..ca4fd56 --- /dev/null +++ b/pages/activityDetail/activityDetail.wxss @@ -0,0 +1,63 @@ +.container { + padding: 20px; + background-color: #f4f3f3; +} + +.activity-info { + background-color: white; + padding: 15px; + border-radius: 10px; + margin-bottom: 20px; +} + +.activity-name { + font-size: 20px; + font-weight: bold; +} + +.activity-participants { + font-size: 14px; + color: #666; +} + +.action-buttons { + display: flex; + justify-content: space-between; + margin-bottom: 20px; +} + +.btn-action { + width: 48%; + height: 40px; + background-color: #0d94ff; + color: white; + border-radius: 20px; + font-size: 14px; +} + +.selected-user { + background-color: white; + padding: 15px; + border-radius: 10px; + text-align: center; +} + +.selected-user-name { + font-size: 18px; + margin-bottom: 10px; +} + +.score-buttons { + display: flex; + justify-content: center; +} + +.btn-score { + width: 80px; + height: 30px; + background-color: #0d94ff; + color: white; + border-radius: 15px; + font-size: 14px; + margin: 0 10px; +} \ No newline at end of file diff --git a/pages/createActivity/createActivity.js b/pages/createActivity/createActivity.js new file mode 100644 index 0000000..748eb20 --- /dev/null +++ b/pages/createActivity/createActivity.js @@ -0,0 +1,51 @@ +Page({ + data: { + fileName: '' + }, + + onUpload() { + wx.chooseMessageFile({ + count: 1, + type: 'file', + extension: ['xlsx'], + success: (res) => { + const file = res.tempFiles[0]; + this.setData({ + fileName: file.name + }); + // 这里可以处理文件上传逻辑 + console.log('选择的文件:', file); + } + }); + }, + + onSubmit(e) { + const { activityName, activityDescription } = e.detail.value; + if (activityName && activityDescription) { + if (!this.data.fileName) { + wx.showToast({ + title: '请上传 XLSX 文件', + icon: 'none', + duration: 2000 + }); + return; + } + // 这里应该添加创建活动的逻辑,比如调用后端 API + console.log('创建活动:', activityName, activityDescription, this.data.fileName); + wx.showToast({ + title: '创建成功', + icon: 'success', + duration: 2000 + }); + setTimeout(() => { + wx.navigateBack(); + }, 2000); + } else { + wx.showToast({ + title: '请填写完整信息', + icon: 'none', + duration: 2000 + }); + } + } +}); \ No newline at end of file diff --git a/pages/createActivity/createActivity.wxml b/pages/createActivity/createActivity.wxml new file mode 100644 index 0000000..a4b48d4 --- /dev/null +++ b/pages/createActivity/createActivity.wxml @@ -0,0 +1,27 @@ + +
+ + 活动名称 + + + + + + + 活动描述 + + + + + + + 上传文件 + + {{fileName}} + + + + + +
+
\ No newline at end of file diff --git a/pages/createActivity/createActivity.wxss b/pages/createActivity/createActivity.wxss new file mode 100644 index 0000000..bc9c2d8 --- /dev/null +++ b/pages/createActivity/createActivity.wxss @@ -0,0 +1,70 @@ +.container { + padding: 20px; + background-color: #f4f3f3; + min-height: 100vh; + box-sizing: border-box; + display: flex; + flex-direction: column; +} + +.form-group { + margin-bottom: 20px; +} + +.label { + display: block; + font-size: 14px; + color: #333; + margin-bottom: 5px; +} + +.input-container { + background-color: #fff; + border-radius: 5px; + padding: 5px; +} + +input, textarea { + width: 100%; + padding: 10px; + border: none; + font-size: 14px; + background-color: transparent; +} + +textarea { + height: 100px; +} + +.upload-btn { + background-color: #f0f0f0; + color: #333; + font-size: 12px; + padding: 8px 15px; + border-radius: 5px; + margin-bottom: 10px; + width: auto; + display: inline-block; +} + +.file-name { + font-size: 12px; + color: #666; + margin-left: 10px; +} + +.submit-container { + flex-grow: 1; + display: flex; + align-items: flex-end; + margin-top: 20px; +} + +.submit-btn { + background-color: #0d94ff; + color: white; + font-size: 16px; + padding: 10px 20px; + border-radius: 5px; + width: 100%; +} \ No newline at end of file diff --git a/pages/created/created.js b/pages/created/created.js new file mode 100644 index 0000000..668c6ea --- /dev/null +++ b/pages/created/created.js @@ -0,0 +1,27 @@ +Page({ + data: { + activities: [ + { id: 1, name: "活动1", participants: 10 }, + { id: 2, name: "活动2", participants: 20 }, + { id: 3, name: "活动3", participants: 15 } + ] + }, + + onSearchInput(e) { + // 实现搜索功能 + console.log("搜索:", e.detail.value); + }, + + onActivityTap(e) { + const activityId = e.currentTarget.dataset.id; + wx.navigateTo({ + url: `/pages/activityDetail/activityDetail?id=${activityId}` + }); + }, + + onCreateActivity() { + wx.navigateTo({ + url: '/pages/createActivity/createActivity' + }); + } +}); \ No newline at end of file diff --git a/pages/created/created.json b/pages/created/created.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/created/created.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/created/created.wxml b/pages/created/created.wxml new file mode 100644 index 0000000..f19a4da --- /dev/null +++ b/pages/created/created.wxml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/created/created.wxss b/pages/created/created.wxss new file mode 100644 index 0000000..f18ba31 --- /dev/null +++ b/pages/created/created.wxss @@ -0,0 +1,64 @@ +.container { + padding: 20px; + background-color: #f4f3f3; + min-height: 100vh; + box-sizing: border-box; +} + +.search-bar { + position: sticky; + top: 0; + z-index: 1000; + background-color: #f4f3f3; + padding: 10px 0; +} + +.search-bar input { + width: 100%; + height: 40px; + padding: 0 15px; + border: 1px solid #ccc; + border-radius: 20px; + background-color: #fff; +} + +.activity-list { + margin-top: 20px; + margin-bottom: 20px; +} + +.activity-item { + width: 100%; + background-color: #fff; + padding: 15px; + margin-bottom: 10px; + border-radius: 5px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); + text-align: left; +} + +.activity-info { + display: flex; + flex-direction: column; +} + +.activity-name { + font-size: 16px; + font-weight: bold; + color: #333; +} + +.activity-participants { + font-size: 14px; + color: #666; + margin-top: 5px; +} + +.create-btn { + background-color: #0d94ff; + color: white; + border-radius: 5px; + padding: 10px 20px; + font-size: 16px; + width: 100%; +} \ No newline at end of file diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..a8d6aa5 --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,49 @@ +// index.js +const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0' + +Page({ + data: { + motto: 'Hello World', + userInfo: { + avatarUrl: defaultAvatarUrl, + nickName: '', + }, + hasUserInfo: false, + canIUseGetUserProfile: wx.canIUse('getUserProfile'), + canIUseNicknameComp: wx.canIUse('input.type.nickname'), + }, + bindViewTap() { + wx.navigateTo({ + url: '../logs/logs' + }) + }, + onChooseAvatar(e) { + const { avatarUrl } = e.detail + const { nickName } = this.data.userInfo + this.setData({ + "userInfo.avatarUrl": avatarUrl, + hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl, + }) + }, + onInputChange(e) { + const nickName = e.detail.value + const { avatarUrl } = this.data.userInfo + this.setData({ + "userInfo.nickName": nickName, + hasUserInfo: nickName && avatarUrl && avatarUrl !== defaultAvatarUrl, + }) + }, + getUserProfile(e) { + // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 + wx.getUserProfile({ + desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 + success: (res) => { + console.log(res) + this.setData({ + userInfo: res.userInfo, + hasUserInfo: true + }) + } + }) + }, +}) diff --git a/pages/index/index.json b/pages/index/index.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/index/index.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..0721ba0 --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,27 @@ + + + + + + + + 昵称 + + + + + + 请使用2.10.4及以上版本基础库 + + + + {{userInfo.nickName}} + + + + {{motto}} + + + diff --git a/pages/index/index.wxss b/pages/index/index.wxss new file mode 100644 index 0000000..1ebed4b --- /dev/null +++ b/pages/index/index.wxss @@ -0,0 +1,62 @@ +/**index.wxss**/ +page { + height: 100vh; + display: flex; + flex-direction: column; +} +.scrollarea { + flex: 1; + overflow-y: hidden; +} + +.userinfo { + display: flex; + flex-direction: column; + align-items: center; + color: #aaa; + width: 80%; +} + +.userinfo-avatar { + overflow: hidden; + width: 128rpx; + height: 128rpx; + margin: 20rpx; + border-radius: 50%; +} + +.usermotto { + margin-top: 200px; +} + +.avatar-wrapper { + padding: 0; + width: 56px !important; + border-radius: 8px; + margin-top: 40px; + margin-bottom: 40px; +} + +.avatar { + display: block; + width: 56px; + height: 56px; +} + +.nickname-wrapper { + display: flex; + width: 100%; + padding: 16px; + box-sizing: border-box; + border-top: .5px solid rgba(0, 0, 0, 0.1); + border-bottom: .5px solid rgba(0, 0, 0, 0.1); + color: black; +} + +.nickname-label { + width: 105px; +} + +.nickname-input { + flex: 1; +} diff --git a/pages/login/login.js b/pages/login/login.js new file mode 100644 index 0000000..85407d2 --- /dev/null +++ b/pages/login/login.js @@ -0,0 +1,41 @@ +Page({ + data: { + account: '', + password: '' + }, + + onAccountInput(e) { + this.setData({ + account: e.detail.value + }) + }, + + onPasswordInput(e) { + this.setData({ + password: e.detail.value + }) + }, + + onLogin() { + const { account, password } = this.data + if (account && password) { + // 这里应该添加实际的登录逻辑,比如调用后端 API + // 现在我们只是模拟登录成功 + wx.showToast({ + title: '登录成功', + icon: 'success', + duration: 2000 + }) + // 登录成功后跳转到"我创建的"页面 + wx.switchTab({ + url: '/pages/created/created' + }) + } else { + wx.showToast({ + title: '请输入账号和密码', + icon: 'none', + duration: 2000 + }) + } + } +}) \ No newline at end of file diff --git a/pages/login/login.wxml b/pages/login/login.wxml new file mode 100644 index 0000000..7eae0f0 --- /dev/null +++ b/pages/login/login.wxml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pages/login/login.wxss b/pages/login/login.wxss new file mode 100644 index 0000000..a42a0f8 --- /dev/null +++ b/pages/login/login.wxss @@ -0,0 +1,30 @@ +.container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + background-color: #f4f3f3; +} + +.login-form { + width: 80%; + max-width: 300px; +} + +input { + width: 100%; + height: 40px; + margin-bottom: 20px; + padding: 0 10px; + border: 1px solid #ccc; + border-radius: 5px; +} + +button { + width: 100%; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; +} \ No newline at end of file diff --git a/pages/logs/logs.js b/pages/logs/logs.js new file mode 100644 index 0000000..85f6aac --- /dev/null +++ b/pages/logs/logs.js @@ -0,0 +1,18 @@ +// logs.js +const util = require('../../utils/util.js') + +Page({ + data: { + logs: [] + }, + onLoad() { + this.setData({ + logs: (wx.getStorageSync('logs') || []).map(log => { + return { + date: util.formatTime(new Date(log)), + timeStamp: log + } + }) + }) + } +}) diff --git a/pages/logs/logs.json b/pages/logs/logs.json new file mode 100644 index 0000000..b55b5a2 --- /dev/null +++ b/pages/logs/logs.json @@ -0,0 +1,4 @@ +{ + "usingComponents": { + } +} \ No newline at end of file diff --git a/pages/logs/logs.wxml b/pages/logs/logs.wxml new file mode 100644 index 0000000..85cf1bf --- /dev/null +++ b/pages/logs/logs.wxml @@ -0,0 +1,6 @@ + + + + {{index + 1}}. {{log.date}} + + diff --git a/pages/logs/logs.wxss b/pages/logs/logs.wxss new file mode 100644 index 0000000..33f9d9e --- /dev/null +++ b/pages/logs/logs.wxss @@ -0,0 +1,16 @@ +page { + height: 100vh; + display: flex; + flex-direction: column; +} +.scrollarea { + flex: 1; + overflow-y: hidden; +} +.log-item { + margin-top: 20rpx; + text-align: center; +} +.log-item:last-child { + padding-bottom: env(safe-area-inset-bottom); +} diff --git a/pages/myCreated/myCreated.js b/pages/myCreated/myCreated.js new file mode 100644 index 0000000..38bce58 --- /dev/null +++ b/pages/myCreated/myCreated.js @@ -0,0 +1,32 @@ +Page({ + data: { + activities: [] + }, + + onLoad() { + this.fetchActivities(); + }, + + fetchActivities() { + // 这里应该从后端 API 获取活动列表 + const mockActivities = [ + { id: 1, name: '软件工程课程', participants: 50 }, + { id: 2, name: '数据结构讨论', participants: 30 } + ]; + this.setData({ activities: mockActivities }); + }, + + onSearch(e) { + const keyword = e.detail.value; + // 实现搜索逻辑 + }, + + goToCreateActivity() { + wx.navigateTo({ url: '/pages/createActivity/createActivity' }); + }, + + goToActivityDetail(e) { + const activityId = e.currentTarget.dataset.id; + wx.navigateTo({ url: `/pages/activityDetail/activityDetail?id=${activityId}` }); + } +}); \ No newline at end of file diff --git a/pages/myCreated/myCreated.wxml b/pages/myCreated/myCreated.wxml new file mode 100644 index 0000000..667c3c6 --- /dev/null +++ b/pages/myCreated/myCreated.wxml @@ -0,0 +1,12 @@ + + + + + + + + 活动名称 + 参与人数: 50 + + + \ No newline at end of file diff --git a/pages/myCreated/myCreated.wxss b/pages/myCreated/myCreated.wxss new file mode 100644 index 0000000..272d0b0 --- /dev/null +++ b/pages/myCreated/myCreated.wxss @@ -0,0 +1,40 @@ +.container { + padding: 20px; + background-color: #f4f3f3; +} + +.search-bar { + width: 100%; + height: 40px; + background-color: white; + border-radius: 20px; + padding: 0 10px; + margin-bottom: 20px; +} + +.btn-create { + width: 100%; + height: 40px; + background-color: #0d94ff; + color: white; + border-radius: 20px; + font-size: 14px; + margin-bottom: 20px; +} + +.activity-item { + background-color: white; + padding: 15px; + border-radius: 10px; + margin-bottom: 10px; +} + +.activity-name { + font-size: 16px; + font-weight: bold; +} + +.activity-participants { + font-size: 14px; + color: #666; +} \ No newline at end of file diff --git a/pages/myParticipated/myParticipated.js b/pages/myParticipated/myParticipated.js new file mode 100644 index 0000000..260b038 --- /dev/null +++ b/pages/myParticipated/myParticipated.js @@ -0,0 +1,22 @@ +Page({ + data: { + activities: [] + }, + + onLoad() { + this.fetchParticipatedActivities(); + }, + + fetchParticipatedActivities() { + // 这里应该从后端 API 获取参与的活动列表 + const mockActivities = [ + { id: 1, name: '2024软件工程K班', participants: 104 } + ]; + this.setData({ activities: mockActivities }); + }, + + goToParticipatedDetail(e) { + const activityId = e.currentTarget.dataset.id; + wx.navigateTo({ url: `/pages/participatedDetail/participatedDetail?id=${activityId}` }); + } +}); \ No newline at end of file diff --git a/pages/myParticipated/myParticipated.wxml b/pages/myParticipated/myParticipated.wxml new file mode 100644 index 0000000..c5a0deb --- /dev/null +++ b/pages/myParticipated/myParticipated.wxml @@ -0,0 +1,8 @@ + + + + 2024软件工程K班 + 参与人数: 104 + + + \ No newline at end of file diff --git a/pages/myParticipated/myParticipated.wxss b/pages/myParticipated/myParticipated.wxss new file mode 100644 index 0000000..397a584 --- /dev/null +++ b/pages/myParticipated/myParticipated.wxss @@ -0,0 +1,21 @@ +.container { + padding: 20px; + background-color: #f4f3f3; +} + +.activity-item { + background-color: white; + padding: 15px; + border-radius: 10px; + margin-bottom: 10px; +} + +.activity-name { + font-size: 16px; + font-weight: bold; +} + +.activity-participants { + font-size: 14px; + color: #666; +} \ No newline at end of file diff --git a/pages/participated/participated.js b/pages/participated/participated.js new file mode 100644 index 0000000..37052d7 --- /dev/null +++ b/pages/participated/participated.js @@ -0,0 +1,52 @@ +Page({ + data: { + activities: [ + { id: 1, name: "2024软件工程K班", participants: 104 } + // 可以添加更多活动 + ], + filteredActivities: [] + }, + + onLoad: function() { + this.setData({ + filteredActivities: this.data.activities.slice(1) // 除了第一个活动外的所有活动 + }); + }, + + onSearchInput(e) { + const searchText = e.detail.value.toLowerCase(); + const filtered = this.data.activities.filter(activity => + activity.name.toLowerCase().includes(searchText) + ); + this.setData({ + filteredActivities: filtered + }); + }, + + onActivitySummaryTap() { + wx.navigateTo({ + url: '/pages/participatedDetail/participatedDetail?id=1', + fail: (err) => { + console.error('Navigation failed:', err); + wx.showToast({ + title: '页面跳转失败', + icon: 'none' + }); + } + }); + }, + + onActivityTap(e) { + const activityId = e.currentTarget.dataset.id; + wx.navigateTo({ + url: `/pages/participatedDetail/participatedDetail?id=${activityId}`, + fail: (err) => { + console.error('Navigation failed:', err); + wx.showToast({ + title: '页面跳转失败', + icon: 'none' + }); + } + }); + } +}); \ No newline at end of file diff --git a/pages/participated/participated.json b/pages/participated/participated.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/participated/participated.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/participated/participated.wxml b/pages/participated/participated.wxml new file mode 100644 index 0000000..d4b285d --- /dev/null +++ b/pages/participated/participated.wxml @@ -0,0 +1,9 @@ + + + + 2024软件工程K班 + 参与人数:104人 + + + + \ No newline at end of file diff --git a/pages/participated/participated.wxss b/pages/participated/participated.wxss new file mode 100644 index 0000000..6c313d1 --- /dev/null +++ b/pages/participated/participated.wxss @@ -0,0 +1,92 @@ +.container { + background-color: #f4f3f3; + min-height: 100vh; + box-sizing: border-box; + display: flex; + flex-direction: column; +} + +.top-section { + padding: 20px; +} + +.search-container { + margin-bottom: 15px; +} + +.search-bar { + display: flex; + align-items: center; + background-color: #fff; + border-radius: 20px; + padding: 5px 15px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.search-bar icon { + margin-right: 5px; +} + +.search-bar input { + flex: 1; + border: none; + background: transparent; + height: 30px; + font-size: 14px; +} + +.activity-summary { + background-color: #0d94ff; + color: white; + padding: 15px; + border-radius: 5px; + display: flex; + flex-direction: column; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.summary-title { + font-size: 18px; + font-weight: bold; + margin-bottom: 5px; +} + +.summary-participants { + font-size: 14px; +} + +.activity-list { + padding: 20px; +} + +.activity-item { + background-color: #fff; + padding: 15px; + margin-bottom: 10px; + border-radius: 5px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.activity-info { + display: flex; + flex-direction: column; +} + +.activity-name { + font-size: 16px; + font-weight: bold; + color: #333; +} + +.activity-participants { + font-size: 14px; + color: #666; + margin-top: 5px; +} + +.no-activities { + text-align: center; + color: #999; + margin-top: 50px; + padding: 0 20px; +} \ No newline at end of file diff --git a/pages/participatedDetail/participatedDetail.js b/pages/participatedDetail/participatedDetail.js new file mode 100644 index 0000000..d5d592f --- /dev/null +++ b/pages/participatedDetail/participatedDetail.js @@ -0,0 +1,147 @@ +const app = getApp() + +Page({ + data: { + activity: null, + luckyStudent: null, + isLoading: false, + studentId: null, + showAnswerModal: false + }, + + onLoad: function(options) { + const activityId = options.id; + // 这里应该根据 activityId 从服务器或本地存储加载活动详情 + // 现在我们只是模拟一下 + this.setData({ + activity: { id: activityId, name: "2024软件工程K班", participants: 104 } + }); + // 这里应该从全局状态或本地存储获取当前用户的 student_id + this.setData({ + studentId: app.globalData.studentId || '12345' // 假设的学生ID + }); + }, + + onSignIn: function() { + wx.request({ + url: 'http://10.133.7.205:3000/update_attendance_score', + method: 'POST', + data: { + student_id: this.data.studentId + }, + success: (res) => { + if (res.statusCode === 200) { + wx.showToast({ + title: '签到成功', + icon: 'success' + }); + } else { + wx.showToast({ + title: '签到失败', + icon: 'none' + }); + } + }, + fail: (err) => { + console.error('API request failed:', err); + wx.showToast({ + title: '网络错误', + icon: 'none' + }); + } + }); + }, + + onDrawLuckyStudent: function() { + if (this.data.isLoading) return; // 防止重复点击 + + this.setData({ isLoading: true }); + + this.drawLuckyStudentWithRetry(3); // 最多重试3次 + }, + + drawLuckyStudentWithRetry: function(retryCount) { + wx.request({ + url: 'http://10.133.7.205:3000/get_random_student', + method: 'GET', + timeout: 15000, // 增加超时时间到15秒 + success: (res) => { + if (res.statusCode === 200) { + this.setData({ + luckyStudent: res.data.name, + studentId: res.data.id, + isLoading: false, + showAnswerModal: true + }); + wx.showToast({ + title: '已抽取幸运儿', + icon: 'success' + }); + } else { + this.handleDrawError('服务器返回错误', retryCount); + } + }, + fail: (err) => { + console.error('API request failed:', err); + this.handleDrawError('网络请求失败', retryCount); + } + }); + }, + + handleDrawError: function(errorMsg, retryCount) { + if (retryCount > 0) { + setTimeout(() => { + this.drawLuckyStudentWithRetry(retryCount - 1); + }, 1000); // 1秒后重试 + } else { + this.setData({ isLoading: false }); + wx.showModal({ + title: '抽取失败', + content: `${errorMsg},请稍后再试。`, + showCancel: false + }); + } + }, + + onAnswerCorrect: function() { + this.updateAnswerScore(true, 1); + }, + + onAnswerIncorrect: function() { + this.updateAnswerScore(false, 0); + }, + + updateAnswerScore: function(repeatedCorrectly, answerScore) { + wx.request({ + url: 'http://10.133.7.205:3000/update_answer_score', + method: 'POST', + data: { + student_id: this.data.studentId, + repeated_correctly: repeatedCorrectly, + answer_score: answerScore + }, + success: (res) => { + if (res.statusCode === 200) { + wx.showToast({ + title: '回答已记录', + icon: 'success' + }); + } else { + wx.showToast({ + title: '记录失败', + icon: 'none' + }); + } + this.setData({ showAnswerModal: false }); + }, + fail: (err) => { + console.error('API request failed:', err); + wx.showToast({ + title: '网络错误', + icon: 'none' + }); + this.setData({ showAnswerModal: false }); + } + }); + } +}); \ No newline at end of file diff --git a/pages/participatedDetail/participatedDetail.json b/pages/participatedDetail/participatedDetail.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/participatedDetail/participatedDetail.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/participatedDetail/participatedDetail.wxml b/pages/participatedDetail/participatedDetail.wxml new file mode 100644 index 0000000..be82fc4 --- /dev/null +++ b/pages/participatedDetail/participatedDetail.wxml @@ -0,0 +1,27 @@ + + + {{activity.name}} + 参与人数:{{activity.participants}}人 + + + + 幸运儿:{{luckyStudent}} + + + + + + + + + + {{luckyStudent}} 回答问题: + + + + + + + \ No newline at end of file diff --git a/pages/participatedDetail/participatedDetail.wxss b/pages/participatedDetail/participatedDetail.wxss new file mode 100644 index 0000000..1ede768 --- /dev/null +++ b/pages/participatedDetail/participatedDetail.wxss @@ -0,0 +1,95 @@ +.container { + padding: 20rpx; + background-color: #f4f3f3; + min-height: 100vh; +} + +.activity-info { + background-color: #ffffff; + border-radius: 10rpx; + padding: 20rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1); +} + +.activity-name { + font-size: 20px; + font-weight: bold; + display: block; + margin-bottom: 10rpx; +} + +.activity-participants { + font-size: 16px; + color: #666; +} + +.lucky-student { + background-color: #ffffff; + border-radius: 10rpx; + padding: 20rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1); + text-align: center; + font-size: 18px; + font-weight: bold; + color: #0d94ff; +} + +.action-buttons { + display: flex; + justify-content: space-between; + margin-bottom: 20rpx; +} + +.action-btn { + background-color: #0d94ff; + color: #ffffff; + border-radius: 20rpx; + font-size: 14px; + padding: 10rpx 20rpx; + width: 45%; +} + +.answer-modal { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; +} + +.modal-content { + background-color: #ffffff; + border-radius: 10rpx; + padding: 20rpx; + width: 80%; + text-align: center; +} + +.answer-buttons { + display: flex; + justify-content: space-around; + margin-top: 20rpx; +} + +.answer-btn { + border-radius: 20rpx; + font-size: 14px; + padding: 10rpx 20rpx; + width: 45%; +} + +.correct { + background-color: #4CAF50; + color: white; +} + +.incorrect { + background-color: #F44336; + color: white; +} \ No newline at end of file diff --git a/pages/store/store.js b/pages/store/store.js new file mode 100644 index 0000000..9f90816 --- /dev/null +++ b/pages/store/store.js @@ -0,0 +1,60 @@ +Page({ + data: { + cards: [ + { id: 1, name: "卡牌1", price: 100, image: "/assets/card1.png" }, + { id: 2, name: "卡牌2", price: 200, image: "/assets/card2.png" }, + { id: 3, name: "卡牌3", price: 300, image: "/assets/card3.png" }, + { id: 4, name: "卡牌4", price: 400, image: "/assets/card4.png" } + ], + userPoints: 1000 // 假设用户初始有1000积分 + }, + + onBuy: function(e) { + const cardId = e.currentTarget.dataset.id; + const card = this.data.cards.find(c => c.id === cardId); + if (this.data.userPoints >= card.price) { + this.setData({ + userPoints: this.data.userPoints - card.price + }); + wx.showToast({ + title: '购买成功', + icon: 'success' + }); + } else { + wx.showToast({ + title: '积分不足', + icon: 'none' + }); + } + }, + + onGuess: function() { + wx.showModal({ + title: '猜题', + content: '1 + 1 = ?', + editable: true, + placeholderText: '请输入答案', + confirmText: '提交', + cancelText: '取消', + success: (res) => { + if (res.confirm) { + const answer = res.content; + if (answer === '2') { + this.setData({ + userPoints: this.data.userPoints + 1 + }); + wx.showToast({ + title: '答对了,获得1积分', + icon: 'success' + }); + } else { + wx.showToast({ + title: '答错了,再接再厉', + icon: 'none' + }); + } + } + } + }); + } +}); \ No newline at end of file diff --git a/pages/store/store.wxml b/pages/store/store.wxml new file mode 100644 index 0000000..63ad446 --- /dev/null +++ b/pages/store/store.wxml @@ -0,0 +1,24 @@ + + + 当前积分:{{userPoints}} + + + + + {{item.name}} + + + {{item.price}} 积分 + + + + + + + + + \ No newline at end of file diff --git a/pages/store/store.wxss b/pages/store/store.wxss new file mode 100644 index 0000000..fdcb173 --- /dev/null +++ b/pages/store/store.wxss @@ -0,0 +1,71 @@ +.container { + padding: 20rpx; + background-color: #f4f3f3; + min-height: 100vh; + box-sizing: border-box; +} + +.user-points { + font-size: 16px; + margin-bottom: 20rpx; +} + +.card-list { + display: flex; + flex-direction: column; +} + +.card-item { + background-color: #ffffff; + border-radius: 10rpx; + padding: 20rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1); + display: flex; + flex-direction: column; + align-items: center; +} + +.card-name { + font-size: 20px; + font-weight: bold; + margin-bottom: 10rpx; +} + +.card-image { + width: 300rpx; + height: 300rpx; + object-fit: cover; + margin: 20rpx 0; +} + +.card-info { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.card-price { + font-size: 16px; + color: #666; + margin-bottom: 20rpx; +} + +.buy-btn, .guess-btn { + background-color: #0d94ff; + color: #ffffff; + border-radius: 20rpx; + font-size: 14px; + padding: 10rpx 20rpx; + width: 80%; +} + +.bottom-section { + margin-top: 20rpx; + width: 100%; +} + +.guess-btn { + width: 100%; +} \ No newline at end of file diff --git a/pages/test/test.js b/pages/test/test.js new file mode 100644 index 0000000..210d34b --- /dev/null +++ b/pages/test/test.js @@ -0,0 +1,6 @@ +Page({ + data: {} , + onLoad: function() { + console.log('Test page loaded'); + } +}) \ No newline at end of file diff --git a/pages/test/test.json b/pages/test/test.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/test/test.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/test/test.wxml b/pages/test/test.wxml new file mode 100644 index 0000000..c9bb97a --- /dev/null +++ b/pages/test/test.wxml @@ -0,0 +1 @@ +This is a test page \ No newline at end of file diff --git a/pages/test/test.wxss b/pages/test/test.wxss new file mode 100644 index 0000000..584a528 --- /dev/null +++ b/pages/test/test.wxss @@ -0,0 +1,3 @@ +view { + padding: 20px; +} \ No newline at end of file diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..0884f77 --- /dev/null +++ b/project.config.json @@ -0,0 +1,29 @@ +{ + "compileType": "miniprogram", + "libVersion": "trial", + "packOptions": { + "ignore": [], + "include": [] + }, + "setting": { + "coverView": true, + "es6": true, + "postcss": true, + "minified": true, + "enhance": true, + "showShadowRootInWxmlPanel": true, + "packNpmRelationList": [], + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "urlCheck": false + }, + "condition": {}, + "editorSetting": { + "tabIndent": "auto", + "tabSize": 2 + }, + "appid": "wxcbc61201213ab639" +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..236961d --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,7 @@ +{ + "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html", + "projectname": "K%E7%82%B9%E5%90%8D", + "setting": { + "compileHotReLoad": true + } +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..764bc2c --- /dev/null +++ b/utils/util.js @@ -0,0 +1,19 @@ +const formatTime = date => { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}` +} + +const formatNumber = n => { + n = n.toString() + return n[1] ? n : `0${n}` +} + +module.exports = { + formatTime +}