diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b92f0ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# 依赖目录 +node_modules/ +miniprogram_npm/ + +# 构建输出目录 +dist/ +unpackage/ + +# 环境变量文件 +.env.* +!.env.example + +# 日志文件 +logs/ +*.log + +# 操作系统文件 +.DS_Store +Thumbs.db +desktop.ini + +# 编辑器目录和设置 +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# 微信开发者工具生成文件 +project.private.config.json +sitemap.json +typings/ + +# 临时文件 +*.tmp +*.temp +*.bak + +# 调试文件 +debug.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# 本地配置 +config/local.js +settings/private.json + +# 云开发相关(如使用) +cloudfunctions/**/node_modules/ +cloudfunctions/**/*.log + +# 其他 +*.zip +*.rar +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +[Tt]humbs.db \ No newline at end of file diff --git a/miniprogram/app.json b/miniprogram/app.json new file mode 100644 index 0000000..15f2879 --- /dev/null +++ b/miniprogram/app.json @@ -0,0 +1,66 @@ +{ + "pages": [ + "pages/index/index", + "pages/main/journal/index", + "pages/main/journal-creater/index", + "pages/main/portfolio/index", + "pages/main/travel/index", + "pages/main/about/index", + "pages/main/travel/luggage/index", + "pages/main/moment/index", + "pages/main/journal-list/index" + ], + "window": { + "navigationStyle": "custom", + "navigationBarTextStyle": "black", + "navigationBarBackgroundColor": "#FFFFFF" + }, + "lazyCodeLoading": "requiredComponents", + "tabBar": { + "color": "#8a8a8a", + "selectedColor": "#07C160", + "backgroundColor": "#ffffff", + "borderStyle": "white", + "list": [ + { + "text": "归档", + "pagePath": "pages/main/journal/index", + "iconPath": "assets/icon/journal.png", + "selectedIconPath": "assets/icon/journal_active.png" + }, + { + "text": "专拍", + "pagePath": "pages/main/portfolio/index", + "iconPath": "assets/icon/portfolio.png", + "selectedIconPath": "assets/icon/portfolio_active.png" + }, + { + "text": "瞬间", + "pagePath": "pages/main/moment/index", + "iconPath": "assets/icon/moment.png", + "selectedIconPath": "assets/icon/moment_active.png" + }, + { + "text": "旅行", + "pagePath": "pages/main/travel/index", + "iconPath": "assets/icon/travel.png", + "selectedIconPath": "assets/icon/travel_active.png" + }, + { + "text": "关于", + "pagePath": "pages/main/about/index", + "iconPath": "assets/icon/info.png", + "selectedIconPath": "assets/icon/info_active.png" + } + ] + }, + "permission": { + "scope.userLocation": { + "desc": "您的位置信息将用于发布新的日记记录定位" + } + }, + "requiredPrivateInfos": [ + "getLocation", + "chooseLocation" + ] +} \ No newline at end of file diff --git a/miniprogram/app.ts b/miniprogram/app.ts new file mode 100644 index 0000000..db4f490 --- /dev/null +++ b/miniprogram/app.ts @@ -0,0 +1,7 @@ +// app.ts +App({ + globalData: { + }, + onLaunch() { + }, +}) \ No newline at end of file diff --git a/miniprogram/app.wxss b/miniprogram/app.wxss new file mode 100644 index 0000000..099cf50 --- /dev/null +++ b/miniprogram/app.wxss @@ -0,0 +1,2 @@ +/**app.wxss**/ +@import "./tdesign.wxss"; \ No newline at end of file diff --git a/miniprogram/assets/icon/delete.png b/miniprogram/assets/icon/delete.png new file mode 100644 index 0000000..2b45119 Binary files /dev/null and b/miniprogram/assets/icon/delete.png differ diff --git a/miniprogram/assets/icon/info.png b/miniprogram/assets/icon/info.png new file mode 100644 index 0000000..a59e6c1 Binary files /dev/null and b/miniprogram/assets/icon/info.png differ diff --git a/miniprogram/assets/icon/info_active.png b/miniprogram/assets/icon/info_active.png new file mode 100644 index 0000000..ec32cf2 Binary files /dev/null and b/miniprogram/assets/icon/info_active.png differ diff --git a/miniprogram/assets/icon/journal.png b/miniprogram/assets/icon/journal.png new file mode 100644 index 0000000..27296fd Binary files /dev/null and b/miniprogram/assets/icon/journal.png differ diff --git a/miniprogram/assets/icon/journal_active.png b/miniprogram/assets/icon/journal_active.png new file mode 100644 index 0000000..ac96558 Binary files /dev/null and b/miniprogram/assets/icon/journal_active.png differ diff --git a/miniprogram/assets/icon/moment.png b/miniprogram/assets/icon/moment.png new file mode 100644 index 0000000..98eb0f2 Binary files /dev/null and b/miniprogram/assets/icon/moment.png differ diff --git a/miniprogram/assets/icon/moment_active.png b/miniprogram/assets/icon/moment_active.png new file mode 100644 index 0000000..d412d72 Binary files /dev/null and b/miniprogram/assets/icon/moment_active.png differ diff --git a/miniprogram/assets/icon/play.png b/miniprogram/assets/icon/play.png new file mode 100644 index 0000000..ee52254 Binary files /dev/null and b/miniprogram/assets/icon/play.png differ diff --git a/miniprogram/assets/icon/portfolio.png b/miniprogram/assets/icon/portfolio.png new file mode 100644 index 0000000..bd61702 Binary files /dev/null and b/miniprogram/assets/icon/portfolio.png differ diff --git a/miniprogram/assets/icon/portfolio_active.png b/miniprogram/assets/icon/portfolio_active.png new file mode 100644 index 0000000..f59e360 Binary files /dev/null and b/miniprogram/assets/icon/portfolio_active.png differ diff --git a/miniprogram/assets/icon/travel.png b/miniprogram/assets/icon/travel.png new file mode 100644 index 0000000..114198a Binary files /dev/null and b/miniprogram/assets/icon/travel.png differ diff --git a/miniprogram/assets/icon/travel_active.png b/miniprogram/assets/icon/travel_active.png new file mode 100644 index 0000000..9ff0c8a Binary files /dev/null and b/miniprogram/assets/icon/travel_active.png differ diff --git a/miniprogram/assets/image/logo.png b/miniprogram/assets/image/logo.png new file mode 100644 index 0000000..149d600 Binary files /dev/null and b/miniprogram/assets/image/logo.png differ diff --git a/miniprogram/components/background/snowflake/index.json b/miniprogram/components/background/snowflake/index.json new file mode 100644 index 0000000..7efff18 --- /dev/null +++ b/miniprogram/components/background/snowflake/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/components/background/snowflake/index.less b/miniprogram/components/background/snowflake/index.less new file mode 100644 index 0000000..4e3e09d --- /dev/null +++ b/miniprogram/components/background/snowflake/index.less @@ -0,0 +1,52 @@ +/* components/background/snow/index.wxss */ +@keyframes fall { + from { + transform: translateY(-10px) rotate(0); + } + + to { + transform: translateY(100vh) rotate(1800deg); + } +} + +page { + width: 100%; + height: 100%; + position: fixed; +} + +.snowflakes { + width: 100%; + height: 100%; + z-index: -1; + overflow: hidden; + position: absolute; + + .snowflake { + width: 10px; + height: 10px; + display: block; + position: absolute; + animation: fall linear infinite; + + &::before, + &::after { + content: ''; + position: absolute; + background: rgba(255, 122, 155, .8); + } + + &::before { + top: 45%; + left: 0; + width: 100%; + height: 10%; + } + + &::after { + left: 45%; + width: 10%; + height: 100%; + } + } +} diff --git a/miniprogram/components/background/snowflake/index.ts b/miniprogram/components/background/snowflake/index.ts new file mode 100644 index 0000000..9f1d0bf --- /dev/null +++ b/miniprogram/components/background/snowflake/index.ts @@ -0,0 +1,61 @@ +// components/background/snow/index.ts +import Toolkit from "../../../utils/Toolkit"; + +interface Snowflake { + x: number; + s: number; + speed: number; +} + +Component({ + + data: { + snowflakes: [] as Snowflake[], + timer: undefined as number | undefined, + docWidth: 375, + docHeight: 667, + }, + + methods: { + createSnowflake() { + const snowflake = { + x: Toolkit.random(0, this.data.docWidth), + s: Toolkit.random(6, 20), + speed: Toolkit.random(14, 26) + }; + this.setData({ + snowflakes: [...this.data.snowflakes, snowflake] + }); + } + }, + lifetimes: { + attached() { + const systemInfo = wx.getWindowInfo(); + this.setData({ + docWidth: systemInfo.windowWidth, + docHeight: systemInfo.windowHeight, + timer: setInterval(() => { + this.createSnowflake(); + console.log(this.data.snowflakes); + + if (40 < this.data.snowflakes.length) { + if (this.data.timer) { + clearInterval(this.data.timer); + } + this.setData({ + timer: undefined + }) + } + }, 2000) + }); + }, + detached() { + if (this.data.timer) { + clearInterval(this.data.timer); + this.setData({ + timer: undefined + }) + } + } + } +}) \ No newline at end of file diff --git a/miniprogram/components/background/snowflake/index.wxml b/miniprogram/components/background/snowflake/index.wxml new file mode 100644 index 0000000..96ba115 --- /dev/null +++ b/miniprogram/components/background/snowflake/index.wxml @@ -0,0 +1,9 @@ + + + + diff --git a/miniprogram/components/search-list/index.json b/miniprogram/components/search-list/index.json new file mode 100644 index 0000000..7efff18 --- /dev/null +++ b/miniprogram/components/search-list/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/components/search-list/index.less b/miniprogram/components/search-list/index.less new file mode 100644 index 0000000..94c579a --- /dev/null +++ b/miniprogram/components/search-list/index.less @@ -0,0 +1 @@ +/* components/search-list/index.wxss */ \ No newline at end of file diff --git a/miniprogram/components/search-list/index.ts b/miniprogram/components/search-list/index.ts new file mode 100644 index 0000000..feada99 --- /dev/null +++ b/miniprogram/components/search-list/index.ts @@ -0,0 +1,24 @@ +// components/search-list/index.ts +Component({ + + /** + * 组件的属性列表 + */ + properties: { + + }, + + /** + * 组件的初始数据 + */ + data: { + + }, + + /** + * 组件的方法列表 + */ + methods: { + + } +}) \ No newline at end of file diff --git a/miniprogram/components/search-list/index.wxml b/miniprogram/components/search-list/index.wxml new file mode 100644 index 0000000..e6a7fc2 --- /dev/null +++ b/miniprogram/components/search-list/index.wxml @@ -0,0 +1,2 @@ + +components/search-list/index.wxml \ No newline at end of file diff --git a/miniprogram/config/index.ts b/miniprogram/config/index.ts new file mode 100644 index 0000000..1c64fb6 --- /dev/null +++ b/miniprogram/config/index.ts @@ -0,0 +1,17 @@ +const envArgs = { + develop: { + url: "http://localhost:8091" + }, + trial: { + url: "https://api.imyeyu.com" + }, + release: { + url: "https://api.imyeyu.com" + } +} + +const env = wx.getAccountInfoSync().miniProgram.envVersion; + +export default { + ...envArgs[env] +} diff --git a/miniprogram/package-lock.json b/miniprogram/package-lock.json new file mode 100644 index 0000000..33180fa --- /dev/null +++ b/miniprogram/package-lock.json @@ -0,0 +1,30 @@ +{ + "name": "miniprogram", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "miniprogram", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "tdesign-miniprogram": "^1.11.2" + }, + "devDependencies": { + "miniprogram-api-typings": "^4.1.0" + } + }, + "node_modules/miniprogram-api-typings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-4.1.0.tgz", + "integrity": "sha512-4RBsz27nBKyRkVGoNkRaPx24/KeJBw3zaaIlXDR8s/WBh2PbcUAc+q7wLLbp7Qsmb3bLzzUu7tqAti+B06kmjg==", + "dev": true + }, + "node_modules/tdesign-miniprogram": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/tdesign-miniprogram/-/tdesign-miniprogram-1.11.2.tgz", + "integrity": "sha512-lXcry3vRa9jHzjpOdIxuIAh7F85kImym82VwLbCqr/TkMhycOsOepx+r1S9fum7u2nsWiYRTV+HuvDHN3KlIuA==" + } + } +} diff --git a/miniprogram/package.json b/miniprogram/package.json new file mode 100644 index 0000000..685a6fd --- /dev/null +++ b/miniprogram/package.json @@ -0,0 +1,18 @@ +{ + "name": "miniprogram", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "tdesign-miniprogram": "^1.11.2" + }, + "devDependencies": { + "miniprogram-api-typings": "^4.1.0" + } +} \ No newline at end of file diff --git a/miniprogram/pages/index/index.json b/miniprogram/pages/index/index.json new file mode 100644 index 0000000..1839b2c --- /dev/null +++ b/miniprogram/pages/index/index.json @@ -0,0 +1,6 @@ +{ + "usingComponents": { + "t-button": "tdesign-miniprogram/button/button", + "t-input": "tdesign-miniprogram/input/input" + } +} \ No newline at end of file diff --git a/miniprogram/pages/index/index.less b/miniprogram/pages/index/index.less new file mode 100644 index 0000000..7f7fdc2 --- /dev/null +++ b/miniprogram/pages/index/index.less @@ -0,0 +1,60 @@ +/**index.wxss**/ +page { + height: 100vh; + display: flex; + flex-direction: column; +} + +.index { + flex: 1; + overflow-y: hidden; + + .container { + height: 100%; + display: flex; + padding: 200rpx 0; + box-sizing: border-box; + align-items: center; + flex-direction: column; + justify-content: space-between; + + .header { + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + + .logo { + width: 128px; + height: 128px; + display: block; + border-radius: 4px; + box-shadow: 2px 2px 8px rgba(0, 0, 0, .2); + margin-bottom: 1rem; + } + + .name { + margin: 0 .5rem; + display: inline-block; + + &.gao { + color: #FF7A9B; + } + + &.yeyu { + color: #7A9BFF; + } + } + } + + .password { + width: 20rem; + border-top: 1px solid rgba(0, 0, 0, .1); + border-bottom: 1px solid rgba(0, 0, 0, .1); + } + + .enter { + width: 10rem; + } + } +} \ No newline at end of file diff --git a/miniprogram/pages/index/index.ts b/miniprogram/pages/index/index.ts new file mode 100644 index 0000000..4fa6d4f --- /dev/null +++ b/miniprogram/pages/index/index.ts @@ -0,0 +1,46 @@ +// index.ts + +import config from "../../config/index" + +interface IndexData { + key: string; +} + +Page({ + data: { + key: "" + }, + onShow() { + const key = wx.getStorageSync("key"); + if (key) { + this.setData({ + key + }); + } + }, + navigateToMain() { + wx.request({ + url: `${config.url}/journal/list`, + method: "POST", + header: { + Key: this.data.key + }, + data: { + index: 0, + size: 1 + }, + success: (resp) => { + const data = resp.data as any; + if (data.code === 20000) { + wx.setStorageSync("key", this.data.key); + wx.switchTab({ + url: "/pages/main/journal/index", + }) + } else { + wx.showToast({ title: "密码错误", icon: "error" }); + } + }, + fail: () => wx.showToast({ title: "验证失败", icon: "error" }) + }); + } +}) diff --git a/miniprogram/pages/index/index.wxml b/miniprogram/pages/index/index.wxml new file mode 100644 index 0000000..6235c47 --- /dev/null +++ b/miniprogram/pages/index/index.wxml @@ -0,0 +1,18 @@ + + + + + + + 小糕 + + 夜雨 + 的美好记录 + + + + + + 进入 + + diff --git a/miniprogram/pages/main/about/index.json b/miniprogram/pages/main/about/index.json new file mode 100644 index 0000000..0be651a --- /dev/null +++ b/miniprogram/pages/main/about/index.json @@ -0,0 +1,9 @@ +{ + "component": true, + "usingComponents": { + "t-icon": "tdesign-miniprogram/icon/icon", + "t-button": "tdesign-miniprogram/button/button", + "t-navbar": "tdesign-miniprogram/navbar/navbar", + "snowflake": "../../../components/background/snowflake" + } +} \ No newline at end of file diff --git a/miniprogram/pages/main/about/index.less b/miniprogram/pages/main/about/index.less new file mode 100644 index 0000000..543101b --- /dev/null +++ b/miniprogram/pages/main/about/index.less @@ -0,0 +1,107 @@ +/* pages/info/info.less */ +page { + height: 100vh; + display: flex; + flex-direction: column; +} + +.info { + height: 100%; + display: flex; + padding: 100rpx 0; + box-sizing: border-box; + flex-direction: column; + + .cotainer { + height: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + + .header { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + + .logo { + width: 128px; + height: 128px; + display: block; + border-radius: 4px; + box-shadow: 2px 2px 8px rgba(0, 0, 0, .2); + margin-bottom: 1rem; + } + + .name { + margin: 0 .5rem; + display: inline-block; + + &.gao { + color: #FF7A9B; + } + + &.yeyu { + color: #7A9BFF; + } + } + } + + .text { + color: #777; + font-size: 12px; + text-align: center; + + .love { + color: transparent; + font-size: 1rem; + animation: loveGradient 1500ms linear infinite; + text-align: center; + background: linear-gradient(90deg, #FFB5C7, #FF7A9B, #FF3A6B, #FF7A9B, #FFB5C7); + font-weight: bold; + font-family: "Arial", sans-serif; + margin-bottom: 1rem; + background-size: 200% 100%; + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + @keyframes loveGradient { + 0% { + background-position: 0% 50%; + } + 100% { + background-position: 200% 50%; + } + } + } + + .footer { + display: flex; + align-items: center; + flex-direction: column; + + .exit { + color: #E64340; + width: 10rem; + margin-bottom: 1rem; + } + + .item { + font-size: 14px; + text-align: center; + + .label { + color: #777; + } + + &.copyright { + display: flex; + font-size: 12px; + flex-direction: column; + } + } + } + } +} \ No newline at end of file diff --git a/miniprogram/pages/main/about/index.ts b/miniprogram/pages/main/about/index.ts new file mode 100644 index 0000000..b6fa09d --- /dev/null +++ b/miniprogram/pages/main/about/index.ts @@ -0,0 +1,64 @@ +// pages/info/info.ts + +import Time from "../../../utils/Time"; +import config from "../../../config/index" + +interface IAboutData { + timer?: number; + total?: number; + beginFriendText: string; +} + +Page({ + data: { + copyright: `Copyright © 2017 - ${new Date().getFullYear()} imyeyu.com`, + timer: undefined, + total: undefined, + beginFriendText: "相识 -- 天 -- 小时 -- 分钟 -- 秒", + beginLoveText: "相恋 -- 天 -- 小时 -- 分钟 -- 秒" + }, + onShow() { + const beginLove = new Date("2025/11/10 00:10:00"); + const beginFriend = new Date("2025/06/28 16:00:00"); + + const timer = setInterval(() => { + { + const r = Time.between(beginLove) + this.setData({ + beginLoveText: `相恋 ${r.d} 天 ${r.h} 小时 ${r.m.toString().padStart(2, "0")} 分钟 ${r.s.toString().padStart(2, "0")} 秒` + }) + } + { + const r = Time.between(beginFriend) + this.setData({ + beginFriendText: `相识 ${r.d} 天 ${r.h} 小时 ${r.m.toString().padStart(2, "0")} 分钟 ${r.s.toString().padStart(2, "0")} 秒` + }) + } + }, 1000) + this.setData({ + timer + }); + + + wx.request({ + url: `${config.url}/journal/total`, + method: "GET", + header: { + Key: wx.getStorageSync("key") + }, + success: (resp: any) => { + this.setData({ + total: resp.data.data + }); + } + }); + }, + onHide() { + this.data.timer && clearInterval(this.data.timer); + }, + exit() { + wx.redirectTo({ + "url": "/pages/index/index?from=info" + }) + } +}) \ No newline at end of file diff --git a/miniprogram/pages/main/about/index.wxml b/miniprogram/pages/main/about/index.wxml new file mode 100644 index 0000000..593657f --- /dev/null +++ b/miniprogram/pages/main/about/index.wxml @@ -0,0 +1,37 @@ + + + + + + + + + 记录 + 小糕 + + 夜雨 + 的美好回忆 + + + + {{beginLoveText}} + {{beginFriendText}} + 已留住 {{total}} 个我们的瞬间 + + + 退出 + + 开发者: + 夜雨 + + + 版本: + 1.2.2 + + + {{copyright}} + All Rights Reserved 夜雨 版权所有 + + + + \ No newline at end of file diff --git a/miniprogram/pages/main/journal-creater/index.json b/miniprogram/pages/main/journal-creater/index.json new file mode 100644 index 0000000..022469d --- /dev/null +++ b/miniprogram/pages/main/journal-creater/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "t-button": "tdesign-miniprogram/button/button", + "t-navbar": "tdesign-miniprogram/navbar/navbar" + } +} \ No newline at end of file diff --git a/miniprogram/pages/main/journal-creater/index.less b/miniprogram/pages/main/journal-creater/index.less new file mode 100644 index 0000000..a4c399e --- /dev/null +++ b/miniprogram/pages/main/journal-creater/index.less @@ -0,0 +1,101 @@ +/* pages/main/journal-creater/index.wxss */ +.container { + height: 100vh; + + .content { + width: calc(100% - 64px); + padding: 0 32px 32px 32px; + display: flex; + align-items: center; + flex-direction: column; + + .label { + color: #777; + } + + .section { + width: 100%; + margin-top: 1.5rem; + + &.time { + display: flex; + + .picker { + margin-right: .25rem; + } + } + + &.media { + + .ctrl { + display: flex; + + .clear { + width: 100px; + padding-left: 0; + padding-right: 0; + } + } + + .gallery { + gap: 10rpx; + display: grid; + margin-top: 1rem; + grid-template-columns: repeat(3, 1fr); + + .item { + height: 200rpx; + position: relative; + overflow: hidden; + background: #FFF; + box-shadow: 1px 1px 6px rgba(0, 0, 0, .1); + border-radius: 2rpx; + + .thumbnail { + height: 200rpx; + display: block; + } + + .video-container { + position: relative; + + + .play-icon { + top: 50%; + left: 50%; + width: 60rpx; + height: 60rpx; + z-index: 2; + position: absolute; + transform: translate(-50%, -50%); + pointer-events: none; + } + } + + + .delete { + top: 10rpx; + right: 10rpx; + width: 40rpx; + height: 40rpx; + z-index: 3; + padding: 5rpx; + position: absolute; + background: rgba(0, 0, 0, 0.5); + border-radius: 50%; + } + } + } + } + } + + .progress { + width: 100%; + } + + .submit { + width: 10rem; + margin-top: 1rem; + } + } +} \ No newline at end of file diff --git a/miniprogram/pages/main/journal-creater/index.ts b/miniprogram/pages/main/journal-creater/index.ts new file mode 100644 index 0000000..31a7cdd --- /dev/null +++ b/miniprogram/pages/main/journal-creater/index.ts @@ -0,0 +1,306 @@ +// pages/main/journal-creater/index.ts +import Events from "../../../utils/Events"; +import Time from "../../../utils/Time"; +import Toolkit from "../../../utils/Toolkit"; +import config from "../../../config/index"; + +enum MediaItemType { + IMAGE, + VIDEO +} + +type MediaItem = { + type: MediaItemType; + path: string; + thumbPath: string; + size: number; + duration: number | undefined; + raw: any; +} + +export type Location = { + lat: number; + lng: number; + text?: string; +} + +interface JournalEditorData { + idea: string; + date: string; + time: string; + mediaList: MediaItem[]; + location?: Location; + qqMapSDK?: any; + isAuthLocation: boolean; +} + +Page({ + data: { + idea: "", + date: "2025-06-28", + time: "16:00", + mediaList: [], + location: undefined, + submitText: "提交", + isSubmitting: false, + submitProgress: 0, + mediaItemTypeEnum: { + ...MediaItemType + }, + isAuthLocation: false + }, + async onLoad() { + // 授权定位 + const setting = await wx.getSetting(); + wx.setStorageSync("isAuthLocation", setting.authSetting["scope.userLocation"]); + let isAuthLocation = JSON.parse(wx.getStorageSync("isAuthLocation")); + this.setData({ isAuthLocation }); + if (!isAuthLocation) { + wx.authorize({ + scope: "scope.userLocation" + }).then(() => { + isAuthLocation = true; + this.setData({ isAuthLocation }); + }); + } + + const unixTime = new Date().getTime(); + this.setData({ + date: Time.toDate(unixTime), + time: Time.toTime(unixTime) + }); + // 获取默认定位 + wx.getLocation({ + type: "gcj02" + }).then(resp => { + this.setData({ + location: { + lat: resp.latitude, + lng: resp.longitude + }, + }); + const argLoc = `location=${this.data.location!.lat},${this.data.location!.lng}`; + const argKey = "key=WW5BZ-J4LCM-UIT6I-65MXY-Z5HDT-VRFFU"; + wx.request({ + url: `https://apis.map.qq.com/ws/geocoder/v1/?${argLoc}&${argKey}`, + success: res => { + if (res.statusCode === 200) { + this.setData({ + location: { + lat: this.data.location!.lat, + lng: this.data.location!.lng, + text: (res.data as any).result?.formatted_addresses?.recommend + } + }); + } + } + }); + }); + }, + async chooseLocation() { + const location = await wx.chooseLocation({}); + this.setData({ + location: { + lat: location.latitude, + lng: location.longitude, + text: location.name + } + }); + }, + addMedia() { + const that = this; + wx.chooseMedia({ + mediaType: ["mix"], + sourceType: ["album", "camera"], + camera: "back", + success(res) { + wx.showLoading({ + title: "加载中..", + mask: true + }) + const tempFiles = res.tempFiles; + const mediaList = tempFiles.map(item => { + return { + type: (MediaItemType)[item.fileType.toUpperCase()], + path: item.tempFilePath, + thumbPath: item.thumbTempFilePath, + size: item.size, + duration: item.duration, + raw: item + } as MediaItem; + }); + that.setData({ + mediaList: [...that.data.mediaList, ...mediaList] + }); + wx.hideLoading(); + } + }) + }, + clearMedia() { + wx.showModal({ + title: "提示", + content: "确认清空已选照片或视频吗?", + confirmText: "清空", + confirmColor: "#E64340", + cancelText: "取消", + success: res => { + if (res.confirm) { + this.setData({ + mediaList: [] + }); + } + } + }) + }, + preview(e: WechatMiniprogram.BaseEvent) { + wx.previewMedia({ + current: e.currentTarget.dataset.index, + sources: this.data.mediaList.map(item => { + return { + url: item.path, + type: MediaItemType[item.type].toLowerCase() + } as WechatMiniprogram.MediaSource; + }) + }); + }, + deleteMedia(e: WechatMiniprogram.BaseEvent) { + const index = e.currentTarget.dataset.index; + const mediaList = [...this.data.mediaList]; + mediaList.splice(index, 1); + this.setData({ + mediaList + }); + }, + cancel() { + wx.switchTab({ + url: "/pages/main/journal/index", + }) + }, + submit() { + const handleFail = () => { + wx.showToast({ title: "上传失败", icon: "error" }); + this.setData({ + submitText: "提交", + isSubmitting: false + }) + }; + + this.setData({ + submitText: "正在提交..", + isSubmitting: true + }) + + // 获取 openId + const getOpenId = new Promise((resolve, reject) => { + wx.login({ + success: (res) => { + if (res.code) { + wx.request({ + url: `${config.url}/journal/openid`, + method: "POST", + header: { + Key: wx.getStorageSync("key") + }, + data: { + code: res.code + }, + success: (resp) => { + const data = resp.data as any; + if (data.code === 20000) { + resolve(data.data); + } else { + reject(new Error("获取 openId 失败")); + } + }, + fail: () => reject(new Error("获取 openId 请求失败")) + }); + } else { + reject(new Error("获取登录凭证失败")); + } + }, + fail: () => reject(new Error("登录失败")) + }); + }); + // 文件上传 + const uploadFiles = new Promise((resolve, reject) => { + const mediaList = this.data.mediaList || []; + const total = mediaList.length; + let completed = 0; + + if (total === 0) { + resolve([]); + return; + } + // 更新进度初始状态 + this.setData({ + submitProgress: 0, + }); + + const uploadPromises = mediaList.map((item) => { + return new Promise((uploadResolve, uploadReject) => { + wx.uploadFile({ + url: `${config.url}/temp/file/upload`, + filePath: item.path, + name: "file", + success: (resp) => { + const result = JSON.parse(resp.data); + if (result && result.code === 20000) { + completed++; + // 更新进度 + this.setData({ + submitProgress: (completed / total), + }); + uploadResolve(result.data[0].id); + } else { + uploadReject(new Error(`文件上传失败: ${result?.message || '未知错误'}`)); + } + }, + fail: (err) => uploadReject(new Error(`文件上传失败: ${err.errMsg}`)) + }); + }); + }); + // 并行执行所有文件上传 + Promise.all(uploadPromises).then((tempFileIds) => { + this.setData({ + submitProgress: 1, + }); + resolve(tempFileIds); + }).catch(reject); + }); + // 并行执行获取 openId 和文件上传 + Promise.all([getOpenId, uploadFiles]).then(([openId, tempFileIds]) => { + wx.request({ + url: `${config.url}/journal/create`, + method: "POST", + header: { + Key: wx.getStorageSync("key") + }, + data: { + type: "NORMAL", + idea: this.data.idea, + createdAt: Date.parse(`${this.data.date} ${this.data.time}`), + lat: this.data.location?.lat, + lng: this.data.location?.lng, + location: this.data.location?.text, + pusher: openId, + tempFileIds + }, + success: async (resp: any) => { + Events.emit("JOURNAL_REFRESH"); + wx.showToast({ title: "提交成功", icon: "success" }); + this.setData({ + idea: "", + mediaList: [], + submitText: "提交", + isSubmitting: false, + }); + await Toolkit.sleep(1000); + wx.switchTab({ + url: "/pages/main/journal/index", + }) + }, + fail: handleFail + }); + }).catch(handleFail); + } +}); \ No newline at end of file diff --git a/miniprogram/pages/main/journal-creater/index.wxml b/miniprogram/pages/main/journal-creater/index.wxml new file mode 100644 index 0000000..a9e2957 --- /dev/null +++ b/miniprogram/pages/main/journal-creater/index.wxml @@ -0,0 +1,104 @@ + + + 取消 + + + + +