From 1a6280c998326b4a33e2a557d2687a889b1dd27f Mon Sep 17 00:00:00 2001 From: wangsai <1534599297@qq.com> Date: Wed, 24 Sep 2025 10:23:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 43 +++++ app.json | 49 +++++ images/app-logo.png | Bin 0 -> 2177 bytes images/icon/add-selected.png | Bin 0 -> 4813 bytes images/icon/add-selected2.png | Bin 0 -> 4680 bytes images/icon/add.png | Bin 0 -> 4813 bytes images/icon/add1.png | Bin 0 -> 4680 bytes images/icon/char1t.png | Bin 0 -> 2177 bytes images/icon/chart-selected.png | Bin 0 -> 4654 bytes images/icon/chart-selected11.png | Bin 0 -> 2177 bytes images/icon/chart.png | Bin 0 -> 4654 bytes images/icon/home-selected.png | Bin 0 -> 4791 bytes images/icon/home-selected2.png | Bin 0 -> 2177 bytes images/icon/home.png | Bin 0 -> 4791 bytes images/icon/home1.png | Bin 0 -> 2177 bytes images/icon/user-selected.png | Bin 0 -> 4754 bytes images/icon/user-selected1.png | Bin 0 -> 2177 bytes images/icon/user.png | Bin 0 -> 4754 bytes images/icon/user1.png | Bin 0 -> 2177 bytes images/wechat.png | Bin 0 -> 2177 bytes pages/add/add.js | 215 +++++++++++++++++++++ pages/add/add.wxml | 142 ++++++++++++++ pages/add/add.wxss | 313 +++++++++++++++++++++++++++++++ pages/category/category.js | 157 ++++++++++++++++ pages/category/category.wxml | 75 ++++++++ pages/category/category.wxss | 230 +++++++++++++++++++++++ pages/index/index.js | 69 +++++++ pages/index/index.wxml | 50 +++++ pages/index/index.wxss | 165 ++++++++++++++++ pages/launch/launch.js | 9 + pages/launch/launch.json | 3 + pages/launch/launch.wxml | 7 + pages/launch/launch.wxss | 18 ++ pages/login/login.js | 213 +++++++++++++++++++++ pages/login/login.json | 7 + pages/login/login.wxml | 83 ++++++++ pages/login/login.wxss | 180 ++++++++++++++++++ pages/profile/profile.js | 146 ++++++++++++++ pages/profile/profile.wxml | 75 ++++++++ pages/profile/profile.wxss | 128 +++++++++++++ pages/statistics/statistics.js | 209 +++++++++++++++++++++ pages/statistics/statistics.wxml | 88 +++++++++ pages/statistics/statistics.wxss | 234 +++++++++++++++++++++++ pages/utils/request.js | 111 +++++++++++ project.config.json | 25 +++ project.private.config.json | 14 ++ 46 files changed, 3058 insertions(+) create mode 100644 app.js create mode 100644 app.json create mode 100644 images/app-logo.png create mode 100644 images/icon/add-selected.png create mode 100644 images/icon/add-selected2.png create mode 100644 images/icon/add.png create mode 100644 images/icon/add1.png create mode 100644 images/icon/char1t.png create mode 100644 images/icon/chart-selected.png create mode 100644 images/icon/chart-selected11.png create mode 100644 images/icon/chart.png create mode 100644 images/icon/home-selected.png create mode 100644 images/icon/home-selected2.png create mode 100644 images/icon/home.png create mode 100644 images/icon/home1.png create mode 100644 images/icon/user-selected.png create mode 100644 images/icon/user-selected1.png create mode 100644 images/icon/user.png create mode 100644 images/icon/user1.png create mode 100644 images/wechat.png create mode 100644 pages/add/add.js create mode 100644 pages/add/add.wxml create mode 100644 pages/add/add.wxss create mode 100644 pages/category/category.js create mode 100644 pages/category/category.wxml create mode 100644 pages/category/category.wxss create mode 100644 pages/index/index.js create mode 100644 pages/index/index.wxml create mode 100644 pages/index/index.wxss create mode 100644 pages/launch/launch.js create mode 100644 pages/launch/launch.json create mode 100644 pages/launch/launch.wxml create mode 100644 pages/launch/launch.wxss create mode 100644 pages/login/login.js create mode 100644 pages/login/login.json create mode 100644 pages/login/login.wxml create mode 100644 pages/login/login.wxss create mode 100644 pages/profile/profile.js create mode 100644 pages/profile/profile.wxml create mode 100644 pages/profile/profile.wxss create mode 100644 pages/statistics/statistics.js create mode 100644 pages/statistics/statistics.wxml create mode 100644 pages/statistics/statistics.wxss create mode 100644 pages/utils/request.js create mode 100644 project.config.json create mode 100644 project.private.config.json diff --git a/app.js b/app.js new file mode 100644 index 0000000..7c72f39 --- /dev/null +++ b/app.js @@ -0,0 +1,43 @@ +App({ + onLaunch() { + this.checkLoginStatus() + // 初始化本地存储 + if (!wx.getStorageSync('records')) { + wx.setStorageSync('records', []); + } + + const defaultCategories = [ + { id: 1, name: '餐饮', type: 'out', icon: 'cutlery' }, + { id: 2, name: '交通', type: 'out', icon: 'car' }, + { id: 3, name: '购物', type: 'out', icon: 'shopping-cart' }, + { id: 4, name: '娱乐', type: 'out', icon: 'film' }, + { id: 5, name: '工资', type: 'in', icon: 'money' }, + { id: 6, name: '奖金', type: 'in', icon: 'gift' } + ]; + wx.setStorageSync('categories', defaultCategories); + }, + // 检查登录状态 + checkLoginStatus() { + // 从本地存储获取token + const token = wx.getStorageSync('token') + // const tokenExpire = wx.getStorageSync('tokenExpire') // 过期时间(可选) + + // // 检查token是否存在且未过期 + // const isLogin = token && (!tokenExpire || Date.now() < tokenExpire) + + if (token) { + // 已登录,跳转首页 + wx.switchTab({ + url: '/pages/index/index' // 首页路径 + }) + } else { + // 未登录或token过期,跳转登录页 + wx.redirectTo({ + url: '/pages/login/login' // 登录页路径 + }) + } + }, + globalData: { + userInfo: null + } +}) diff --git a/app.json b/app.json new file mode 100644 index 0000000..fdca928 --- /dev/null +++ b/app.json @@ -0,0 +1,49 @@ +{ + "pages": [ + "pages/login/login", + "pages/index/index", + "pages/add/add", + "pages/statistics/statistics", + "pages/category/category", + "pages/profile/profile" + ], + "window": { + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#4CAF50", + "navigationBarTitleText": "记账账啊", + "navigationBarTextStyle": "white" + }, + "tabBar": { + "color": "#7A7E83", + "selectedColor": "#4CAF50", + "borderStyle": "black", + "backgroundColor": "#ffffff", + "list": [ + { + "pagePath": "pages/index/index", + "text": "首页", + "iconPath": "/images/icon/home.png", + "selectedIconPath": "/images/icon/home-selected.png" + }, + { + "pagePath": "pages/add/add", + "text": "记账", + "iconPath": "/images/icon/add.png", + "selectedIconPath": "/images/icon/add-selected.png" + }, + { + "pagePath": "pages/statistics/statistics", + "text": "统计", + "iconPath": "/images/icon/chart.png", + "selectedIconPath": "/images/icon/chart-selected.png" + }, + { + "pagePath": "pages/profile/profile", + "text": "我的", + "iconPath": "/images/icon/user.png", + "selectedIconPath": "/images/icon/user-selected.png" + } + ] + }, + "sitemapLocation": "sitemap.json" +} diff --git a/images/app-logo.png b/images/app-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/add-selected.png b/images/icon/add-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..72882119be36ea688f50d37d8f4b305b333b025c GIT binary patch literal 4813 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 literal 0 HcmV?d00001 diff --git a/images/icon/add.png b/images/icon/add.png new file mode 100644 index 0000000000000000000000000000000000000000..72882119be36ea688f50d37d8f4b305b333b025c GIT binary patch literal 4813 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 literal 0 HcmV?d00001 diff --git a/images/icon/char1t.png b/images/icon/char1t.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/chart-selected.png b/images/icon/chart-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..9e89c5edc61a70a59d73009ed6350da614f61244 GIT binary patch literal 4654 zcmV+}64C96P)>3y@VJY8O&w`kPsuW0}=^yH`5uAFe@ZNL<&N>ISE0E2$9h2B|tVkyS)hl zc9DolxPWXIGET%KciQ58ZF|=9E{-oxp6ULD?n9eC zk?^9MM8dOf3KA~b)cw3$rmYKm)Q_acXzN0cwcU5$gDps~4K_x&xcH(3WKRenzz}H1 zP4FLg0w00f1~LL$q&i2cM9xIyf$k3_;fDH=vj^yn}fmwShpY% z9#yR8i-2^50u09;5RNZT0s;(yCQ_Z(Ngh-pNdsRJY>myZ{VXUz@Cm*FoF-kg;3R0i z*eVwbNDafOt^wZFY0=5EH!xJ^B1rN;7O+(cdy`&+17K7S)dbp{E<%U9x_VK7)KH+) zPoClIiL4^WCO^tUZv7A$=Rs=!NxLFpuQ8Ii(!)k zg3En?Lj~bgDiwh*5j{~J>TKc#VnZh0CI>_>;p((X2#0X%Dga1uDY*OD6vvYS!jWT& zE-$A|K+?p>WJXU0NaHw1j>)=y`i6U2@Ia?qm}T_L?wf5AK#uk9xVk|&R0O{EE1)CE zSraq+Gdt%P9gzC2X?5=G2dkUC0@GXq9u<%p4*X|nv+qqhm_UIbm5wCi{-+V60um%l zHkVA$U#xOu1uBulv14d7Krn}dgClFo=4PeW8DG7kM1WUB*we0`{J%s)th zpzD#83-)AyaP%0|&&+I8Ku^NBH}ZXB@x8^80iuR;^w=vuGdL-b>>^MSK*qSb;3O=o znSla&GR6@&!Jn{;1&vTmP28inCI<#qhd{F_b z0&cPB0tly9)_#0b?weouhWz-eKa%f$={xe3&wW|m{_NXtzU0v$1w5x&E`V@)HK_ky zX9ftr{nl^f$?19v2O#;L0`iNm{ao75@!9JFJQ$$BE0-&(E`X@jZbO>ZmDwweIe-9Z z-$;Q`1!-TtG**^dtJmXBE`VT2D_6>KEk~eZ#K7p$w`GhXztm9$W&4&{dOok1j0Obj zkEM6U5dRVEL-MzI0f)70TgTG&9(UEF0SWTzi%S#U>MuqOtTC+RQI?PlQSVjsI>Z5x z>Trn3OU{ccRI&aOkRb|I(QD&qKq?Xb_Cxk>m?B{Wxt7!L26dn=L(#<*2@XHIhyui8 zj<>j8b8z_cyhqYYMLl^R#>QwAATXeprOYIrQzMQbLjo#p9TEiyZx9aYD8IY}WQdkk z)H);z5H&NZaV^gm6-cT;>^dY0kjh~ZlvJGsS5DV`6o>-E#{||w1=1;ilQ{mDPiqTi zKzIk;DmlxIt-vP{GaWM^V>`+AsDNDo`;{y+AiRQQ?=F@sM*%Y+<+w;oofRmsy2^aD zH3krKqd6*!dkaW8+D4n=6o|RhYX+o>Sop-b>r)zcw(&!x_LqCuBjHC(c&L!D_~@KN zEitib0wm_L+0=p|@Bsnf03>+dwFwUc;<0kTg73TE@wi+CtTAf>B<8Z&loBK05%_?h zj~##rFx`ZxPg&;4O95-lngEFzvZj&^L5_eQ+CE?cSVPM(zeR!k%9sGj&yD>SS>R}E z#gq%6wC}kuPXX&m-2_N!KeNT6J2t=p7)GJ;LW34V0c*?}0jY}mnQbf_5SVa4h2@Dq zJH&z}1*|b^0>oq?3sHdr6)*u((iE$}KB3786tKpu36KQ#vq~zEr2+&b%Wk1jDHO0g zkJSf|YqnY%xmE$+P=SIJ7z{{3zR^@F5Ul_KiI#AF72x4a-1FgOZIQu%SRWgnUl`5D zBfx-X&G1tI{Ba)~<1v4{#~$zJ0E;Dd2Lm#nu%IVU0KpFkFlyWe0pP)R_zPD!Mwun0 zi2+%X)Oq;|7%)O0`1@Ff`~V40M)%1-mpp?3sS0`yYc8FX!Viob2>PLQ#rTj$g zdY<_`e~dPf9DAD`49GpMLH3Hu40$SGiQU0~tTZO`o)uGpJqlQ3)ξfmgEjbO^tmhXN)*=HWWM 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 literal 0 HcmV?d00001 diff --git a/images/icon/chart-selected11.png b/images/icon/chart-selected11.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/chart.png b/images/icon/chart.png new file mode 100644 index 0000000000000000000000000000000000000000..9e89c5edc61a70a59d73009ed6350da614f61244 GIT binary patch literal 4654 zcmV+}64C96P)>3y@VJY8O&w`kPsuW0}=^yH`5uAFe@ZNL<&N>ISE0E2$9h2B|tVkyS)hl zc9DolxPWXIGET%KciQ58ZF|=9E{-oxp6ULD?n9eC zk?^9MM8dOf3KA~b)cw3$rmYKm)Q_acXzN0cwcU5$gDps~4K_x&xcH(3WKRenzz}H1 zP4FLg0w00f1~LL$q&i2cM9xIyf$k3_;fDH=vj^yn}fmwShpY% z9#yR8i-2^50u09;5RNZT0s;(yCQ_Z(Ngh-pNdsRJY>myZ{VXUz@Cm*FoF-kg;3R0i z*eVwbNDafOt^wZFY0=5EH!xJ^B1rN;7O+(cdy`&+17K7S)dbp{E<%U9x_VK7)KH+) zPoClIiL4^WCO^tUZv7A$=Rs=!NxLFpuQ8Ii(!)k zg3En?Lj~bgDiwh*5j{~J>TKc#VnZh0CI>_>;p((X2#0X%Dga1uDY*OD6vvYS!jWT& zE-$A|K+?p>WJXU0NaHw1j>)=y`i6U2@Ia?qm}T_L?wf5AK#uk9xVk|&R0O{EE1)CE zSraq+Gdt%P9gzC2X?5=G2dkUC0@GXq9u<%p4*X|nv+qqhm_UIbm5wCi{-+V60um%l zHkVA$U#xOu1uBulv14d7Krn}dgClFo=4PeW8DG7kM1WUB*we0`{J%s)th zpzD#83-)AyaP%0|&&+I8Ku^NBH}ZXB@x8^80iuR;^w=vuGdL-b>>^MSK*qSb;3O=o znSla&GR6@&!Jn{;1&vTmP28inCI<#qhd{F_b z0&cPB0tly9)_#0b?weouhWz-eKa%f$={xe3&wW|m{_NXtzU0v$1w5x&E`V@)HK_ky zX9ftr{nl^f$?19v2O#;L0`iNm{ao75@!9JFJQ$$BE0-&(E`X@jZbO>ZmDwweIe-9Z z-$;Q`1!-TtG**^dtJmXBE`VT2D_6>KEk~eZ#K7p$w`GhXztm9$W&4&{dOok1j0Obj zkEM6U5dRVEL-MzI0f)70TgTG&9(UEF0SWTzi%S#U>MuqOtTC+RQI?PlQSVjsI>Z5x z>Trn3OU{ccRI&aOkRb|I(QD&qKq?Xb_Cxk>m?B{Wxt7!L26dn=L(#<*2@XHIhyui8 zj<>j8b8z_cyhqYYMLl^R#>QwAATXeprOYIrQzMQbLjo#p9TEiyZx9aYD8IY}WQdkk z)H);z5H&NZaV^gm6-cT;>^dY0kjh~ZlvJGsS5DV`6o>-E#{||w1=1;ilQ{mDPiqTi zKzIk;DmlxIt-vP{GaWM^V>`+AsDNDo`;{y+AiRQQ?=F@sM*%Y+<+w;oofRmsy2^aD zH3krKqd6*!dkaW8+D4n=6o|RhYX+o>Sop-b>r)zcw(&!x_LqCuBjHC(c&L!D_~@KN zEitib0wm_L+0=p|@Bsnf03>+dwFwUc;<0kTg73TE@wi+CtTAf>B<8Z&loBK05%_?h zj~##rFx`ZxPg&;4O95-lngEFzvZj&^L5_eQ+CE?cSVPM(zeR!k%9sGj&yD>SS>R}E z#gq%6wC}kuPXX&m-2_N!KeNT6J2t=p7)GJ;LW34V0c*?}0jY}mnQbf_5SVa4h2@Dq zJH&z}1*|b^0>oq?3sHdr6)*u((iE$}KB3786tKpu36KQ#vq~zEr2+&b%Wk1jDHO0g zkJSf|YqnY%xmE$+P=SIJ7z{{3zR^@F5Ul_KiI#AF72x4a-1FgOZIQu%SRWgnUl`5D zBfx-X&G1tI{Ba)~<1v4{#~$zJ0E;Dd2Lm#nu%IVU0KpFkFlyWe0pP)R_zPD!Mwun0 zi2+%X)Oq;|7%)O0`1@Ff`~V40M)%1-mpp?3sS0`yYc8FX!Viob2>PLQ#rTj$g zdY<_`e~dPf9DAD`49GpMLH3Hu40$SGiQU0~tTZO`o)uGpJqlQ3)ξfmgEjbO^tmhXN)*=HWWM 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 literal 0 HcmV?d00001 diff --git a/images/icon/home-selected.png b/images/icon/home-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..0bfb67db4f3a550113b96cdda45563d9147f4855 GIT binary patch literal 4791 zcmYkAXH*ky*M%p6P=d4=I!FQmLKP`eL`^~q)lj9QbfgGKuOV~+4aFz|8WE5pqSBj! zqLhFSB2@)7^eWP%318lS-;bGDYi7=#+3W0kt#jQO1am`9s4x@&08S&ko+abj$2fY~ zSQuyA!w*yd-~o*Eu-1{F)ndo!LSz1vh`9^iXZlR(3*|G)q|w@V2R{pTMR@AjlnCi zbsBCDP|9kHGJ-m(eRg=wZB3FTZ5NmPzU zTB61^fP~mIYrXkcA9Qe8*>$HWD6_Ov0+~_jyx=ng?d*&p1uMluN=GPj2cVzDx4O5& zp**k)ia%097j6IX2SB>x4^M6Iq{R)L`eO&eg*;FF^_THwVQ-(6b4#5f&P`b}eD8B( z#No)O+P+2A0&q#9PZR#cU_Uv#QSS2OzlR3?IJXMt&E~o*710Q#RXpS%qma5yLxJZ42r2?iwmEpNE$|;JHq2xe6C*kc|E{J z;J>9QAYXfM>5EDaoG15D8D*(kOnM_a+GJhSR~r5Pb|QIuh?4{E`A|w4<}QhTZ!L`y z3!{bdJO38mv2XcyZnpUon{h%1yAkUkkgjcV-l!tDFdi^2pECG@5fBwbwh)>N8WGE= zi-?D8->yt}Fqh?(CYS1$`@bTp6-cAAVF8A?5S-Y6^;vPU^bB*E1^s&tx!r<=xY+*g z%EgXOCCdErY#OyFe=aDOESlW;3&0QGYsVWtET$HHDJF~NYk_Bjyb98Gop|%D4tQWT zkd>G9nJN5w2{r$$l1RqxYsPB(t`|{2H?0m~_N4T3>R{c`KLKo|iQ6cdhy0bz{6q?! ztyG-!xv8nwXOwTxB&1|2ubKOi5}e`jZ7+ zKe8I)X+s`}tBi5$x8>-+fdC;)?3T?5borN1{Oh(A)>>k|M3cmvG`^Xa{VF4{a|U{6 zOmbxYG}Nq1MP{Zk6DzV?9MZ~C6F7Ko#|rH3ub21!PB`jsYSMob*X@$<_QYbgtvc?_ zAsmj_nPH(IHb2ixMLMXc?kNbv(ug{@8~JbSX}sO6X+#YBCOPiRKq)UJ2>k5qUbj0y zuzGb2jo{<=IV0=z9bvnAo263|8P^8PQ|=L8YvO_4y8J*&Yc8{9SeaU!VX|v?K8j81ZOQc557DY)7=W$v|7}Z_F2&*nD@I!hnyn=JOS8v z)-~`0IW-++vE<*|fukFM(mr!+!m^EV|GU$LkhD4JWBafr)g$SBFaxO>4=P+ z|8Xe_44ETBSNuudk=J(_O2L~qxe3SEHq0XQSIqON)9Bu}o%wKUqofV9IZe-SC?}^hf?_%GGe>@-7~-Ck6KQB&~c3jhy@MLx?)>CZ}a9Gka>IT zv0x0TS0ngkCFoMh4f30~P;yb8(FTh#qx*+_$=a8-MDQwx@=>64;h(6yU0M&*ReNOo;8eYnW*BP(GBa}ZI(3cc{T zf=@LZ8JF=2V8^?Tew{je-@`k^(npb z%(+`Q$Kt}!>l^z)X7ZVv zpjJRZ-VQ1@z$$xF{Vwwyj<+?DnZ{q1O$H1BARwo`I(!hS9$GMlu)ON zLh|^V+t7TXk)Z|^Q$1d3dLqw>y1BW=NhX-VrcWaC2C$cNH0r_2QOcsrf9Fou&w&&Q z%m?fRt#fXQC(VzWWNxl*=uh<_6M4mMObF=W4?nD1I0|ltMsXB+2iUXqZ;$1|b6dX= zmal~!WQAvT1&UF)T6fl+CPFhKUdq=+TzjJbXLEzXCI?(TIY0`bDm+bU*gp(*i(%z|Wb_Ae`>sHkOd`rs@f*|S3z*l;eghPa+s%`ej9z5ZyOQ3%14s>E%ipyuR(VmjKkFv)J|rS7*V!_qx-h>HXoZqnnvsI;}1- zm+vyk1Xz?{>0Rl6(BJU;ZcfmXPU|k@1@XXjZuAGwOOo0v zvCGa1!JoDJKc^N-e56K3_MbD#RFOq-WmiN$rROMe9!K{U7OHzaQvnlHibHk6YJO|g z*eR?22E(6g6OZGzlt=z~kP)XHXwfPqx8$Q@{LavwwF5f}RKvNOwBiNGj|M z!Cp8|@U}{O;Ls?QN?)EoZkH#P?Eff=;9W2_B@7@z2)U9%`%tl@2Z~{TDNXV7g6ID; zSSh(Jy7IMul;{S{(2$hVAE303CtbT@;&XtsY-2&6ubc1#e>erZNn|c&niNqC>-pIf z+K^m+em^l`aGi%w-q*qu@yC`1=BbX@40pw;4tacuRAtq7Tr2&rlv!-xvWc%s&OsyI zK$l)iX>eMO|3{^_MG8%SBdP8MG?Vs@4TCoGXW-Nc;HvAXi>O# zl&O!;JaghEF&mW9TNhJD)bEQS95`B>yh5rro`3SSSAxO6`@aIpG#Cq+qeown14BCh z$CiVSkGw6D-zRv|=~nbu!VY327z;l$kR#d0;-!V73` zq!zfe&u{su5TZGblL=q^M0Tc$BPLQ~PLmUWxZ}B#qLwCiwAtAYmcD+#aY&pw&o>q% z^?N7R`?HMP3t_l*k-MZOk^b{njrJAi%`Gk%K=(uV{WYH+7#~binw#l0Q+B*jOVy0( zeG-~TOr|9ktUKIYQr-Z+rDx~lrGnEjsa<%d;*5RX*rX+3(Z02StwemrYR_ZoWzW>5 ztuR4bT_0c%#}xkCa8q{vNKy)0;?L){j}!l%ft&atKkl^NdA+FUlSzWI^L?4f;@|JcOlvZZio1nF3Kcd4AA|4} z>uv$!Jt-(l0l4?)o@LE}w}V?EXE5x1dkH6_i)1(qc&*{kNAr|6%PGH5!t#RlD?s?* zpHdaS)KC84cQ39^jA+z*97KScdfgjy@6${jtnb9KQ$;_vJazl1DvON~tiT&W)ZT3+ z=vTcms-krJi`kafEq0B%cfYF0A2;RH+q%KM3D_JeBxOjMjn z7(PUvfO4u7(-#@g2-YWcdr6%Ix@b^q4{(XZz@q!>X%6b@PN0u_JMX5enMv#e?RV4& zG_<2k4wi@oic%cjv_OSqS3YeRb3;e;VGR z>xm5UOxHvZH`UaqO#*xA$T9Sg;G^hj{@Nv#W@_ykKaIY23Mwrs1A>?`<{F!c(FYzk zCt{I7pF#YAQ+>TPk2>a5@^VyKx6ahlvR>3#WQIKL$TE9u8Xlb4=9}FHg&k=YJ!g^I zyXe7+VCw;sSJ!EOEsYIL_R`R}%K=azzg5EjR@lD7lMbXKp`SAlrgrWvhLorOrVSPV zxwbm&o^(iM+U{t?vpq{2&oh5Dpcgu3+pOpUvQDN@JNbLk%a6mV=*OdyGiS+aAc6he zm*rL8E7D|E2OF9UJHo$pe%}5u-MVymVMZnIP43`yT;;`7(-!W4@7uezcmLf1iGqZx z>9C`3M6lGgXHc5VYDwovOiR}Ugg`Cnaq;owZlh4vPN5VpWt|1_h;?2ke&X-8`xeD= zH3{7I(m3IXqF%?36LftVGrDnqmp$gbW-bnlg!AZRnqyk?$8LO2&NkPMPm7D}4N<`> zXT}5FNnEB$su0E;)NuFl8H^E_F_gSPx{m!EP!^N!@wh%a5v!k;Ow3YzJ-V;qD5z!K z;){&RtBM}3@Zi`q5IFX~ifMBZ56jvlSFP}I!Ujt2Yx|BUvDR89eu0)UOF>Z&m_D1v zUnq`yR0f`c6GRRwlJg{Om)J<@M%*U2$Ts%{q+h?M|Hp%USL&y7L2;kIT!?y}w*d<#1)P-h+Q zXkTV=X2-5$&%T+{l1SdBC_3@&zlbij+_Fq`-QOMicBg)AYbv{ZM-JV~To!?S8;L-j zwG7<{V;b)|J4J_B&F*lpviHBVL^7BuDY0upTRUP&0bl8?ci-q%F&a1gDw1;TntuGr z)1uiQ{-N;T@=t6=3#7x1+E3lwmmX`zN$;|-|A8s9(m#wvQ)jM#CSWe(!m6Hmx}oBSQ`bpXOM3*$rH$BPs;JN46pSjBMn1FCF6W@=jju3xDLBMW7 zkX(>GV~@dJvemAI(abrP&Q(`iBH3vyUCH(ZBke69<-_}YL6E+=*~*lLoFM6UZky4E~exdk$+V;}=G>H_q~DRs%>a zdCs$hL00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/home.png b/images/icon/home.png new file mode 100644 index 0000000000000000000000000000000000000000..0bfb67db4f3a550113b96cdda45563d9147f4855 GIT binary patch literal 4791 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 DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/user-selected.png b/images/icon/user-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..3d40a39f259a4385da9f79088cedbcec0207d61d GIT binary patch literal 4754 zcmV;D5^e2?P)70_9ze$kUgdH z6cwmM0RmD?4wheL%8euaQK|YD`AtQij*|_j&huT!ZV8mxA=D#|J%L zj}W13;TBW@0y05P800eyiyj0RFbr7+BNve~iLfb1r<(1V9xnkB%0$@;%;S)HaP%|W zCn!KbUWvEwr zpWXy!fJMWzPgiJL{{cSiRDgi&kfzgtvl`R2gTfT!A$C;v;J3}-VMM(i+NN!M#27}n zZB>APY{-H;D!}M;P%UaeYD_v{mZmptzZ!D42t55Z<9!j=Zl7LYC8;&h8XA>XPdFTf(|LDi%5pg=2`={7q+(An@9 zh`&XRK)CHxU(M^H=mGsmzGzPfFK0W&b!7cx9iN( zWDi}RJo!0o&8oXuJV5h2wTN44bAWU@Ws7l!cAidI#ubmb|5o6v)v&7>KyU}^^iC!W zrzFRwH>8cQtDVKhCIG=#CEzvGFt`e=BIMiwiq)0*PCa?fdW0&wdO$k$8t9Nvf-s-y z3IGyOPmaEUXP1h%Y5{@pIuO?xDxueqh}*QRhp|b$Ay<`vj3Je~Q%&nZUL98f^btIK zS82#q9UvV;s<;*%A$LF`L&znSZB+pRI8~%Bp`qTUo=eHT`Vn!0uB<>|H5RB^4}}7I6x3q5svq| zt*!HbIaX~;gQN&R2uCb)t25sbk`ij49T37%f*F)o2SD=2%_4iqofVK_)`BbK z<=JNuHBv|}yUgDLehWwFVv7xbGwdgyW95 zo!NTsImRPN0pYl#brX);KJ_BW$0NxA!4EB{d>nVE2;BV@03=<)so!LP;MqrEf=mozZdIS5}o{?gah-~-8b+2)r*|Q9Ooq2FT=siMr5%W7#ff%+I6c7*$k`HYVKSu>Z zDgfJq4Tj7!C?LA-@n^`&HJ=w77+itSUL+_W+S(`sCC!&R6*x!%c#)9b(Fz7gXxDa- z8vGCy*rGtlNG2E{pp9a?*Sjtaz70JaF53{gf9Ktj5- z5RGCUBGe$vA5;YaL^~sxOVhl#Q-R3}Sdmi+uuTR8gLAmF0Ciy&R3MlFuu0hF)C?yB zqJ#5)Ppt&6rvfn)2od^E21Fai@JdDCUY-IW!mP=Fz?GFJ4QmupfoigbZBCudngmFQ z7_S<&SNsQ)ASTdUb5wpu?h2882}Se?my!z*CChXUS!Xd}D})oZy^fn*9y z8HY>(Bv}Jl5EYoBfSE8>_6B51p;H>mYpH;b0=@%vFFpp2(VhwzuSq2@Ks;;6%cwwg3itxzMPqg9u)@tK;5*gp3rI7< zu_5zNz<5se9sq0r8=57D}>_O)79SAYoNtZd9Ob1&#)UGgxJJC~LP{0Uz5v z8j#(^mw84Ph@O}vng(U|dbnC04G4@aT=6k;va9v-&fG8WJ~GAA;DeZtB6bzCCv)a~ zG$1)EduZ84%;)v;+m}N>&(HZQaJ#&Ha$1{n|6IzwvN=Gk$kX@b?N=#R^CoMyUf%xD zh9T*po&9J)KBxf}-u&h|sc^kFs%MMV-g?;X(SU5IQRGwOv07SWLs+RI6le|*y-OVZ zg|s4iqJc_SF-2?d6a5?w2nJ;h^d*}RM}g-4PUvVr;^-PKSEC_T>>rf~SKGF7g7zi1 z$mizn1&H++?4%T~^o~lYMXIt|{V7^6K-2)AQVH)p$+GUP8#Lehfy^gQ#CX~4iBG+K=97KOnR3nlM4G&#Nr79d19V931qd!IJ!wpQ zReBv;sh?_H^!Nih|3k!USl|T+=96s&Q@vadktCajSC>f¬OA*5`6BKv0m1QuI_W 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 literal 0 HcmV?d00001 diff --git a/images/icon/user-selected1.png b/images/icon/user-selected1.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/icon/user.png b/images/icon/user.png new file mode 100644 index 0000000000000000000000000000000000000000..3d40a39f259a4385da9f79088cedbcec0207d61d GIT binary patch literal 4754 zcmV;D5^e2?P)70_9ze$kUgdH z6cwmM0RmD?4wheL%8euaQK|YD`AtQij*|_j&huT!ZV8mxA=D#|J%L zj}W13;TBW@0y05P800eyiyj0RFbr7+BNve~iLfb1r<(1V9xnkB%0$@;%;S)HaP%|W zCn!KbUWvEwr zpWXy!fJMWzPgiJL{{cSiRDgi&kfzgtvl`R2gTfT!A$C;v;J3}-VMM(i+NN!M#27}n zZB>APY{-H;D!}M;P%UaeYD_v{mZmptzZ!D42t55Z<9!j=Zl7LYC8;&h8XA>XPdFTf(|LDi%5pg=2`={7q+(An@9 zh`&XRK)CHxU(M^H=mGsmzGzPfFK0W&b!7cx9iN( zWDi}RJo!0o&8oXuJV5h2wTN44bAWU@Ws7l!cAidI#ubmb|5o6v)v&7>KyU}^^iC!W zrzFRwH>8cQtDVKhCIG=#CEzvGFt`e=BIMiwiq)0*PCa?fdW0&wdO$k$8t9Nvf-s-y z3IGyOPmaEUXP1h%Y5{@pIuO?xDxueqh}*QRhp|b$Ay<`vj3Je~Q%&nZUL98f^btIK zS82#q9UvV;s<;*%A$LF`L&znSZB+pRI8~%Bp`qTUo=eHT`Vn!0uB<>|H5RB^4}}7I6x3q5svq| zt*!HbIaX~;gQN&R2uCb)t25sbk`ij49T37%f*F)o2SD=2%_4iqofVK_)`BbK z<=JNuHBv|}yUgDLehWwFVv7xbGwdgyW95 zo!NTsImRPN0pYl#brX);KJ_BW$0NxA!4EB{d>nVE2;BV@03=<)so!LP;MqrEf=mozZdIS5}o{?gah-~-8b+2)r*|Q9Ooq2FT=siMr5%W7#ff%+I6c7*$k`HYVKSu>Z zDgfJq4Tj7!C?LA-@n^`&HJ=w77+itSUL+_W+S(`sCC!&R6*x!%c#)9b(Fz7gXxDa- z8vGCy*rGtlNG2E{pp9a?*Sjtaz70JaF53{gf9Ktj5- z5RGCUBGe$vA5;YaL^~sxOVhl#Q-R3}Sdmi+uuTR8gLAmF0Ciy&R3MlFuu0hF)C?yB zqJ#5)Ppt&6rvfn)2od^E21Fai@JdDCUY-IW!mP=Fz?GFJ4QmupfoigbZBCudngmFQ z7_S<&SNsQ)ASTdUb5wpu?h2882}Se?my!z*CChXUS!Xd}D})oZy^fn*9y z8HY>(Bv}Jl5EYoBfSE8>_6B51p;H>mYpH;b0=@%vFFpp2(VhwzuSq2@Ks;;6%cwwg3itxzMPqg9u)@tK;5*gp3rI7< zu_5zNz<5se9sq0r8=57D}>_O)79SAYoNtZd9Ob1&#)UGgxJJC~LP{0Uz5v z8j#(^mw84Ph@O}vng(U|dbnC04G4@aT=6k;va9v-&fG8WJ~GAA;DeZtB6bzCCv)a~ zG$1)EduZ84%;)v;+m}N>&(HZQaJ#&Ha$1{n|6IzwvN=Gk$kX@b?N=#R^CoMyUf%xD zh9T*po&9J)KBxf}-u&h|sc^kFs%MMV-g?;X(SU5IQRGwOv07SWLs+RI6le|*y-OVZ zg|s4iqJc_SF-2?d6a5?w2nJ;h^d*}RM}g-4PUvVr;^-PKSEC_T>>rf~SKGF7g7zi1 z$mizn1&H++?4%T~^o~lYMXIt|{V7^6K-2)AQVH)p$+GUP8#Lehfy^gQ#CX~4iBG+K=97KOnR3nlM4G&#Nr79d19V931qd!IJ!wpQ zReBv;sh?_H^!Nih|3k!USl|T+=96s&Q@vadktCajSC>f¬OA*5`6BKv0m1QuI_W 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 literal 0 HcmV?d00001 diff --git a/images/icon/user1.png b/images/icon/user1.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/images/wechat.png b/images/wechat.png new file mode 100644 index 0000000000000000000000000000000000000000..bacb4bd7d33d9b49479b66b03b4229aefed48c87 GIT binary patch literal 2177 zcmV-{2!8j8P)00009a7bBm000ie z000ie0hKEb8vp8P z0f-L~;t-L0#J_-qIOT|xOQb{y0Vjw!MR0%vpvZy{u(B6$2oRQt5ZQ6O@vc2PJ2U-J zT^!zSZ@Z^wdS-TdW_N#wQFnDucm4W()T>vo&=>>z20g^=BH2auDgYp2?l0MP#u#G^ z5$T}&FXIC4lQS_i#%QgxJogEr%{iy9FkbQ_awd5aPx>8KhjJk1DfzK5ABD5lI%PW+ z(h{l-I+X*40 zl%uKoKyubvhhaD|O&$cK?UrSYAn+2-B;GI#r=rZIV2oLoC4@*-U=Z}=OrALif;f)H z+Rrfq5v7z$sWEU)lBC^kA58J)K)%g!oB@aNV$NFYcDqfYuBM-3M%KJbY3Dgpq|xbg z4uyns;GEmGT{?i@=k&;91wn9F#G8ZGItT)-b^qH$_Jjyi{9JMOssedjrIZk&*FAd| z(m{Aq-Kzwos;Pw+-m|0INs=4^!US?jaUA#Z!8@GeIF6#|@TznUB*I>ig&@KeMOp^H zfI$F+@lXBxgZvriynEtW(gc|-k*R;Oy2t-AVb!zLO~En zDYK#$mByGBlZ$c|gbh&>Onj^L$;<6q%kJqHXTI>PzjWT7x3FjA&<8i8d;jWu3V@JN z85`9l?~KIz)EE&-)LG8Bv9Yl~Ui}c5_`~4N)#lponrm0LKLXtWlK>)c`$^~2bG7Bm zGs};t2NiNYjLd&^_xg9&-^#WmU{>SD~P$ok;E?X$RfyLB_y__h^9rZ{R& zk|d5}DJ7kbqFTekLh-0Qx1eS(c?RvmlXJ+<2U_$QmIe{OyVCWf%_N8MTr9(&9= zAz&cRBWPw6MQQSE^o;3f;K1fY?Q!?i)6QuS?oO+L$Rw3UEm@tf)}D9X2VlS?CJBvh zB%L?!UVnM>-8i@dMguTF228prap3$hra!sn9+L`c)LN6AC!yPkNg7G#Ms)8tjeq=L za}}ZnfB|Cw5rlimKJn56Pkeo5WpHD5QG)VwjZ4Do@Qd1rn!e;) zO6|Fs1go7J5N?7ofDE|(Rd?aC_wci|rL*doM7}3mlElDI#{3~d*?Q81c?TY0+n@UnVvsHkgvb`h^)-3DZXjk*-K z400#Jh_;cg+D;-SDTM(On`Ao)lQP;8n9bx+gE=9a?miftjrn`$lb>$B+ctZt$im@z zo_jCUFMiSf+^`h}w023ylZdzb!vJVwJ`V5xqVXQ+pyX~f`;@bI-kQf@TmuO?{Y+CB zCwrsH?1fV4@$_|@KE8zlxCdqFvD4hKhR-WdEkb&_^N#6iI0Lv~&;NMtYccF4BnwMK zJXGiHc{WUkiEwr;UQC@Z4L>JE{p3u&qUSq~ll^=wEA%4?DP@i$v+aW9=#c>;x~`kE z5kZAUm9Az?3uMXNip)6YIdwlWK*UFSRtA z&1SQCSOOJ9^nKs+ywPi!sj<~+ZEbBG{EBAASiN4iZF@l7?6)_8YK< zrDkSkhT4x(z8@nD!$zY~T@Bd?AbM1-?Rnm?`!PyluXMM=fvN^2@w%>?mJST%aR-ez zb5>2eow~b1joGWcj(h!udSCc(GF_#VWm!~@Kic3@&N;0M&NlY(e7UQ=j(h#3k2YDm z7&8mZmVgh2=)gxG(WSi(75|J}c5W6Z13_f6GUDMcGZ#}y`(aHit# z?l?4+fa5qcGod>Pg_ExrIb>NiZrw9592~V&a@G>yDpYM1EXbGY1e56 zmljS_S$G`B*^QPthP1brl$P>16ggHJ`S#jV2+Oi+wc1d- zF|#;06SWfEmQqsePU(arkVPqvw`p*up<;r)suuqTn%j6`s|Qec00000NkvXXu0mjf DADKYB literal 0 HcmV?d00001 diff --git a/pages/add/add.js b/pages/add/add.js new file mode 100644 index 0000000..6b83d36 --- /dev/null +++ b/pages/add/add.js @@ -0,0 +1,215 @@ +const request = require('../utils/request') +Page({ + data: { + type: 'out', // 默认为支出 + amount: '', + selectedCategoryId: null, + categories: [], + filteredCategories: [], + note: '', + useDate: '', + maxDate: '', +// 控制弹窗显示 +showPopup: false, + +// 一级分类数据 +firstLevelCategories: [ + +], + +// 二级分类数据 +secondLevelCategories: [ + +], + +// 选中状态 +selectedFirstLevelId: null, +selectedSecondLevelId: null, +selectedCategoryName: '', +filteredSecondLevelCategories: [] + }, +// 显示分类选择弹窗 +showCategoryPopup() { + this.setData({ + showPopup: true + }); +}, + +// 隐藏分类选择弹窗 +hideCategoryPopup() { + this.setData({ + showPopup: false + }); +}, + +// 选择一级分类 +selectFirstLevel(e) { + const parentId = e.currentTarget.dataset.id; + + // 筛选对应的二级分类 + const filteredSeconds = this.data.secondLevelCategories.filter( + item => item.parentId == parentId + ); + + this.setData({ + selectedFirstLevelId: parentId, + filteredSecondLevelCategories: filteredSeconds, + // 重置二级分类选中状态 + selectedSecondLevelId: null + }); +}, + +// 选择二级分类 +selectSecondLevel(e) { + const secondLevelId = e.currentTarget.dataset.id; + const secondLevelName = e.currentTarget.dataset.name; + + // 如果点击的是已选中的,则取消选中 + if (this.data.selectedSecondLevelId === secondLevelId) { + this.setData({ + selectedSecondLevelId: null + }); + } else { + this.setData({ + selectedSecondLevelId: secondLevelId, + selectedCategoryName: secondLevelName + }); + } +}, + +// 确认选择 +confirmSelection() { + if (this.data.selectedSecondLevelId) { + // 这里可以处理选中后的逻辑 + console.log('选中的二级分类ID:', this.data.selectedSecondLevelId); + console.log('选中的二级分类名称:', this.data.selectedCategoryName); + + // 关闭弹窗 + this.hideCategoryPopup(); + } +}, +async getClassification() { + const res=await request.get('/admin-api/book/classification/oneTwoLevelList',{}) + console.log('resss:',res) + if(res.code==0){ + this.setData( + { + firstLevelCategories:res.data.outOne, + secondLevelCategories:res.data.outTwo, + categories:res.data.inOne, + filteredCategories: res.data.inOne + } + ) + } +}, +onShow(){ + this.getClassification() +}, + onLoad() { + // 获取当前日期 + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + const currentDate = `${year}-${month}-${day}`; + + this.setData({ + useDate: currentDate, + maxDate: currentDate + }); + + + }, + + setType(e) { + const type = e.currentTarget.dataset.type; + this.setData({ + type, + selectedCategoryId: null + }); + console.log('type:',type) + }, + + onAmountChange(e) { + let amount = e.detail.value; + + // 处理金额输入格式 + if (amount) { + // 只保留数字和一个小数点 + amount = amount.replace(/[^\d.]/g, ''); + // 确保只有一个小数点 + const dotIndex = amount.indexOf('.'); + if (dotIndex !== -1) { + amount = amount.substring(0, dotIndex + 3); // 限制两位小数 + } + } + + this.setData({ amount }); + }, + + selectCategory(e) { + const categoryId = e.currentTarget.dataset.id; + this.setData({ selectedCategoryId: categoryId }); + }, + + onNoteChange(e) { + this.setData({ note: e.detail.value }); + }, + + onDateChange(e) { + this.setData({ useDate: e.detail.value }); + }, + + async saveRecord() { + if (!this.data.amount ) { + wx.showToast({ + title: '请填写金额和选择分类', + icon: 'none', + duration: 2000 + }); + return; + } + + + + // 创建新记录 + const newRecord = { + type: this.data.type, + money: parseFloat(parseFloat(this.data.amount).toFixed(2)), + classId: this.data.type=='out'?this.data.selectedSecondLevelId:this.data.selectedCategoryId, + + remark: this.data.note, + useDate: this.data.useDate + }; + // 自动携带token + const res = await request.post('/admin-api/book/inout/create',newRecord) + console.log("新增结果:",res) + if(res.code==0){ + // 显示成功提示 + wx.showToast({ + title: '记录保存成功', + icon: 'success', + duration: 1500 + }); + this.setData({ + amount: '', + selectedCategoryId: '', + note: '', + selectedSecondLevelId: null, + }); + console.log('this.data:',this.data) + }else{ + wx.showToast({ + title: '记录保存失败', + icon: 'none', + duration: 2000 + }); + } + // 返回首页 + setTimeout(() => { + wx.navigateBack({ + delta: 1 + }); + }, 1500); + } +}) diff --git a/pages/add/add.wxml b/pages/add/add.wxml new file mode 100644 index 0000000..03bd807 --- /dev/null +++ b/pages/add/add.wxml @@ -0,0 +1,142 @@ + + + + + + 支出 + + + + 收入 + + + + + + ¥ + + + + + + 选择分类 + + + + {{item.classificationName}} + + + + + + + + 选择分类 + + {{selectedCategoryName || '请选择分类'}} + + + + + + + + + + + 选择分类 + + + + + + + + + {{item.classificationName}} + + + + + + + 请先选择一级分类 + + + + {{item.classificationName}} + + + + + + + + + + + + + + + + + + 备注 (可选) + + + + + + 日期 + + + + {{useDate}} + + + + + + + diff --git a/pages/add/add.wxss b/pages/add/add.wxss new file mode 100644 index 0000000..cb19886 --- /dev/null +++ b/pages/add/add.wxss @@ -0,0 +1,313 @@ +.container { + padding: 20px 15px; + background-color: #f5f5f5; + min-height: 100vh; +} + +.type-selector { + display: flex; + justify-content: center; + margin-bottom: 30px; +} + +.type-btn { + width: 120px; + height: 50px; + border-radius: 25px; + display: flex; + align-items: center; + justify-content: center; + margin: 0 10px; + font-size: 18px; + font-weight: 500; + border: 2px solid #ddd; + transition: all 0.3s; +} + +.type-btn.active { + border-color: #4CAF50; + color: #4CAF50; +} + +.type-btn .iconfont { + margin-right: 8px; + font-size: 20px; +} + +.amount-input { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 40px; +} + +.currency-symbol { + font-size: 36px; + color: #333; + margin-right: 10px; +} + +.amount-input input { + font-size: 48px; + text-align: left; + color: #333; + width: 250px; + padding: 0; + height: auto; +} + +.section-title { + display: block; + font-size: 16px; + color: #666; + margin-bottom: 15px; +} + +.category-grid { + display: flex; + flex-wrap: wrap; + gap: 15px; + margin-bottom: 30px; +} + +.category-item { + width: 70px; + height: 70px; + border-radius: 10px; + background-color: white; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 14px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); + transition: all 0.2s; +} + +.category-item .iconfont { + font-size: 24px; + margin-bottom: 5px; + color: #666; +} + +.category-item.selected { + background-color: #e8f5e9; + color: #4CAF50; +} + +.category-item.selected .iconfont { + color: #4CAF50; +} + +.note-section, .date-section { + margin-bottom: 30px; +} + +.note-section input, .date-picker { + width: 100%; + height: 50px; + background-color: white; + border-radius: 10px; + padding: 0 15px; + font-size: 16px; + box-sizing: border-box; +} + +.date-picker { + display: flex; + align-items: center; + color: #333; +} + +.date-picker .iconfont { + margin-right: 10px; + color: #999; +} + +.save-btn { + width: 100%; + height: 55px; + background-color: #4CAF50; + color: white; + border-radius: 27.5px; + font-size: 18px; + font-weight: 500; + line-height: 55px; + margin-top: 20px; +} + +.save-btn[disabled] { + background-color: #a5d6a7; + color: #e8f5e9; +} + +/************************/ +/* 触发区域样式 */ +.category-trigger { + margin-bottom: 30px; + + +} + +.note-section, .date-section { + margin-bottom: 30px; +} + +.section-title { + font-size: 34rpx; + font-weight: 600; + color: #333; + display: block; + margin-bottom: 20rpx; + padding-bottom: 15rpx; + border-bottom: 1px solid #f5f5f5; +} + +.selected-value { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20rpx; + background-color: #f9f9f9; + border-radius: 12rpx; + font-size: 28rpx; + color: #666; +} + +/* 遮罩层样式 */ +.category-mask { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 998; +} + +/* 弹窗样式 */ +.category-popup { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background-color: #fff; + border-top-left-radius: 24rpx; + border-top-right-radius: 24rpx; + z-index: 999; + max-height: 80vh; + display: flex; + flex-direction: column; +} + +/* 弹窗头部 */ +.popup-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 24rpx 30rpx; + border-bottom: 1px solid #f5f5f5; +} + +.popup-title { + font-size: 32rpx; + font-weight: 600; + color: #333; +} + +/* 弹窗内容区 */ +.popup-content { + display: flex; + flex: 1; + overflow: hidden; +} + +/* 一级分类列表 */ +.first-level-list { + width: 35%; + background-color: #f9f9f9; + overflow-y: auto; +} + +.first-level-item { + display: flex; + align-items: center; + padding: 28rpx 20rpx; + font-size: 28rpx; + color: #555; + border-left: 6rpx solid transparent; +} + +.first-level-item.selected { + background-color: #fff; + color: #387ef5; + border-left-color: #387ef5; + font-weight: 500; +} + +.first-level-item .iconfont { + font-size: 36rpx; + margin-right: 16rpx; + width: 40rpx; + text-align: center; +} + +/* 二级分类列表 */ +.second-level-list { + width: 65%; + padding: 20rpx; + overflow-y: auto; +} + +.no-selection { + height: 100%; + display: flex; + align-items: center; + justify-content: center; + color: #999; + font-size: 28rpx; +} + +.second-level-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 22rpx 20rpx; + margin-bottom: 8rpx; + background-color: #f5f5f5; + border-radius: 12rpx; + font-size: 26rpx; + color: #555; +} + +.second-level-item.selected { + background-color: #edf4ff; + color: #387ef5; +} + +.second-level-item .icon-check { + font-size: 28rpx; +} + +/* 弹窗底部 */ +.popup-footer { + padding: 20rpx 30rpx; + border-top: 1px solid #f5f5f5; +} + +.confirm-btn { + width: 100%; + padding: 20rpx 0; + background-color: #387ef5; + color: #fff; + font-size: 30rpx; + border-radius: 12rpx; + line-height: normal; +} + +.confirm-btn:disabled { + background-color: #b3d1ff; + color: #e6f0ff; +} + + \ No newline at end of file diff --git a/pages/category/category.js b/pages/category/category.js new file mode 100644 index 0000000..f6fa8ed --- /dev/null +++ b/pages/category/category.js @@ -0,0 +1,157 @@ +Page({ + data: { + activeType: 'expense', + categories: [], + filteredCategories: [], + showModal: false, + isEditing: false, + editingId: null, + categoryName: '', + selectedIcon: '', + icons: [ + 'cutlery', 'car', 'shopping-cart', 'home', 'gift', 'money', + 'book', 'film', 'plane', 'medkit', 'coffee', 'shirt', + 'graduation-cap', 'briefcase', 'gamepad', 'heart', 'pet' + ] + }, + + onLoad() { + this.loadCategories(); + }, + + loadCategories() { + const categories = wx.getStorageSync('categories') || []; + this.setData({ + categories, + filteredCategories: categories.filter(cat => cat.type === this.data.activeType) + }); + }, + + setActiveType(e) { + const type = e.currentTarget.dataset.type; + this.setData({ + activeType: type, + filteredCategories: this.data.categories.filter(cat => cat.type === type) + }); + }, + + addCategory() { + this.setData({ + showModal: true, + isEditing: false, + editingId: null, + categoryName: '', + selectedIcon: this.data.icons[0] + }); + }, + + editCategory(e) { + const categoryId = e.currentTarget.dataset.id; + const category = this.data.categories.find(cat => cat.id === categoryId); + + if (category) { + this.setData({ + showModal: true, + isEditing: true, + editingId: categoryId, + categoryName: category.name, + selectedIcon: category.icon + }); + } + }, + + deleteCategory(e) { + const categoryId = e.currentTarget.dataset.id; + + wx.showModal({ + title: '确认删除', + content: '删除分类后,该分类下的记录将不受影响,是否继续?', + cancelText: '取消', + confirmText: '删除', + success: (res) => { + if (res.confirm) { + let categories = this.data.categories; + categories = categories.filter(cat => cat.id !== categoryId); + + wx.setStorageSync('categories', categories); + this.loadCategories(); + + wx.showToast({ + title: '分类已删除', + icon: 'success', + duration: 1500 + }); + } + } + }); + }, + + hideModal() { + this.setData({ showModal: false }); + }, + + onNameChange(e) { + this.setData({ categoryName: e.detail.value }); + }, + + selectIcon(e) { + const icon = e.currentTarget.dataset.icon; + this.setData({ selectedIcon: icon }); + }, + + saveCategory() { + const { categoryName, selectedIcon, isEditing, editingId, activeType, categories } = this.data; + + if (!categoryName.trim()) { + wx.showToast({ + title: '请输入分类名称', + icon: 'none', + duration: 2000 + }); + return; + } + + if (!selectedIcon) { + wx.showToast({ + title: '请选择图标', + icon: 'none', + duration: 2000 + }); + return; + } + + let updatedCategories = [...categories]; + + if (isEditing) { + // 编辑现有分类 + const index = updatedCategories.findIndex(cat => cat.id === editingId); + if (index !== -1) { + updatedCategories[index] = { + ...updatedCategories[index], + name: categoryName, + icon: selectedIcon + }; + } + } else { + // 添加新分类 + const newId = Date.now(); + updatedCategories.push({ + id: newId, + name: categoryName, + type: activeType, + icon: selectedIcon + }); + } + + // 保存分类 + wx.setStorageSync('categories', updatedCategories); + this.loadCategories(); + this.hideModal(); + + wx.showToast({ + title: isEditing ? '分类已更新' : '分类已添加', + icon: 'success', + duration: 1500 + }); + } +}) diff --git a/pages/category/category.wxml b/pages/category/category.wxml new file mode 100644 index 0000000..6ef32e3 --- /dev/null +++ b/pages/category/category.wxml @@ -0,0 +1,75 @@ + + + 支出分类 + 收入分类 + + + + + + + + + + {{item.name}} + + + + + + + + + 暂无分类,请添加 + + + + + + + + + {{isEditing ? '编辑分类' : '添加分类'}} + + + + 分类名称 + + + + + 选择图标 + + + + + + + + + + + + + diff --git a/pages/category/category.wxss b/pages/category/category.wxss new file mode 100644 index 0000000..bc5ab0e --- /dev/null +++ b/pages/category/category.wxss @@ -0,0 +1,230 @@ +.container { + background-color: #f5f5f5; + min-height: 100vh; + padding-bottom: 80px; +} + +.type-tabs { + display: flex; + background-color: white; + border-bottom: 1px solid #f5f5f5; +} + +.tab { + flex: 1; + text-align: center; + padding: 15px 0; + font-size: 16px; + color: #666; + position: relative; +} + +.tab.active { + color: #4CAF50; +} + +.tab.active::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + background-color: #4CAF50; +} + +.category-list { + margin: 15px; +} + +.category-item { + display: flex; + justify-content: space-between; + align-items: center; + background-color: white; + border-radius: 10px; + padding: 15px; + margin-bottom: 10px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); +} + +.category-info { + display: flex; + align-items: center; +} + +.category-icon { + width: 40px; + height: 40px; + border-radius: 50%; + background-color: #e8f5e9; + color: #4CAF50; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; +} + +.category-icon .iconfont { + font-size: 20px; +} + +.category-name { + font-size: 16px; + color: #333; +} + +.category-actions { + display: flex; +} + +.edit-btn, .delete-btn { + padding: 5px 12px; + font-size: 14px; + border-radius: 4px; + margin-left: 10px; + height: auto; + line-height: normal; +} + +.edit-btn { + color: #4CAF50; + background-color: #e8f5e9; +} + +.delete-btn { + color: #f44336; + background-color: #ffebee; +} + +.no-categories { + text-align: center; + padding: 40px 0; + color: #999; + font-size: 14px; + background-color: white; + border-radius: 10px; +} + +.add-btn { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + width: 90%; + height: 50px; + background-color: #4CAF50; + color: white; + border-radius: 25px; + font-size: 16px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); +} + +.add-btn .iconfont { + margin-right: 8px; +} + +/* 弹窗样式 */ +.modal-mask { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +.modal-dialog { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background-color: white; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + padding: 20px; + z-index: 1001; +} + +.modal-title { + font-size: 18px; + font-weight: 600; + color: #333; + margin-bottom: 20px; + text-align: center; +} + +.form-item { + margin-bottom: 20px; +} + +.form-label { + display: block; + font-size: 14px; + color: #666; + margin-bottom: 10px; +} + +.form-item input { + width: 100%; + height: 45px; + border: 1px solid #ddd; + border-radius: 8px; + padding: 0 15px; + font-size: 16px; + box-sizing: border-box; +} + +.icon-selector { + display: flex; + flex-wrap: wrap; + gap: 15px; + max-height: 200px; + overflow-y: auto; +} + +.icon-item { + width: 50px; + height: 50px; + border-radius: 8px; + background-color: #f5f5f5; + display: flex; + align-items: center; + justify-content: center; +} + +.icon-item.selected { + background-color: #e8f5e9; + color: #4CAF50; +} + +.icon-item .iconfont { + font-size: 24px; +} + +.modal-footer { + display: flex; + margin-top: 10px; +} + +.cancel-btn, .confirm-btn { + flex: 1; + height: 45px; + border-radius: 8px; + font-size: 16px; + margin: 0 5px; +} + +.cancel-btn { + background-color: #f5f5f5; + color: #666; +} + +.confirm-btn { + background-color: #4CAF50; + color: white; +} diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..99c7f11 --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,69 @@ +const request = require('../utils/request') +Page({ + data: { + currentMonth: '', + totalBalance: '0.00', + totalIncome: '0.00', + totalExpense: '0.00', + recentRecords: [] + }, + + onShow() { + this.updateData(); + }, + + async updateData() { + // 更新当前月份 + const date = new Date(); + const year = date.getFullYear(); + const month = date.getMonth() + 1; + this.setData({ + currentMonth: `${year}年${month}月` + }); + + // 获取所有记录 + let records = []; + + // 筛选本月记录 + const currentMonthRecords = records.filter(record => { + const recordDate = new Date(record.date); + return recordDate.getFullYear() === year && recordDate.getMonth() + 1 === month; + }); + + // 计算收支和余额 + let totalIncome = 0; + let totalExpense = 0; + + currentMonthRecords.forEach(record => { + if (record.type === 'income') { + totalIncome += parseFloat(record.amount); + } else { + totalExpense += parseFloat(record.amount); + } + }); + + const totalBalance = totalIncome - totalExpense; + + try { + // 自动携带token + const res = await request.get('/admin-api/book/inout/myList?pageNo=1&pageSize=10') + console.log('获取数据成功:', res) + if(res.code==0){ + records=res.data.list + } + // 处理数据... + } catch (error) { + console.error('加载失败:', error) + } + console.log('records:',records) + this.setData({ + totalBalance: totalBalance.toFixed(2), + totalIncome: totalIncome.toFixed(2), + totalExpense: totalExpense.toFixed(2), + // 按日期排序,取最近10条 + recentRecords: [...records] + // .sort((a, b) => new Date(b.date) - new Date(a.date)) + .slice(0, 10) + }); + } +}) diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..9a679dd --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,50 @@ + + + + + + 本月收支 + {{currentMonth}} + + + + + + 收入 + ¥ {{totalIncome}} + + + + 支出 + ¥ {{totalExpense}} + + + + + + + + 近期记录 + 查看全部 + + + + + + + + + {{item.categoryName}} + {{item.useDate}} + + + {{item.type === 'in' ? '+' : '-'}}¥ {{item.money}} + + + + + 暂无记录,开始添加吧~ + + + + diff --git a/pages/index/index.wxss b/pages/index/index.wxss new file mode 100644 index 0000000..50860d4 --- /dev/null +++ b/pages/index/index.wxss @@ -0,0 +1,165 @@ +.container { + background-color: #f5f5f5; + min-height: 100vh; + padding-bottom: 60px; +} + +.balance-card { + background: linear-gradient(135deg, #4CAF50 0%, #8BC34A 100%); + color: white; + padding: 20px 15px; + border-radius: 15px; + margin: 15px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +} + +.balance-header { + display: flex; + justify-content: space-between; + margin-bottom: 15px; +} + +.balance-title { + font-size: 16px; + opacity: 0.9; +} + +.balance-date { + font-size: 14px; + opacity: 0.8; +} + +.balance-amount { + font-size: 32px; + font-weight: bold; + margin-bottom: 20px; +} + +.balance-stats { + display: flex; + justify-content: space-around; + border-top: 1px solid rgba(255, 255, 255, 0.2); + padding-top: 15px; +} + +.balance-item { + text-align: center; +} + +.income-label, .expense-label { + font-size: 14px; + opacity: 0.8; + display: block; + margin-bottom: 5px; +} + +.income-amount, .expense-amount { + font-size: 18px; + font-weight: 500; +} + +.balance-divider { + width: 1px; + background-color: rgba(255, 255, 255, 0.2); +} + +.records-section { + margin: 15px; + background-color: white; + border-radius: 15px; + padding: 15px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; +} + +.section-title { + font-size: 18px; + font-weight: 600; + color: #333; +} + +.see-all { + font-size: 14px; + color: #4CAF50; +} + +.records-list { + max-height: 400px; + overflow-y: auto; +} + +.record-item { + display: flex; + align-items: center; + padding: 12px 0; + border-bottom: 1px solid #f5f5f5; +} + +.record-item:last-child { + border-bottom: none; +} + +.record-icon { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; +} + +.income-icon { + background-color: #e8f5e9; + color: #4CAF50; +} + +.expense-icon { + background-color: #ffebee; + color: #f44336; +} + +.iconfont { + font-size: 20px; +} + +.record-details { + flex: 1; +} + +.record-title { + font-size: 16px; + color: #333; + margin-bottom: 3px; +} + +.record-date { + font-size: 12px; + color: #999; +} + +.record-amount { + font-size: 16px; + font-weight: 500; +} + +.income { + color: #4CAF50; +} + +.expense { + color: #f44336; +} + +.no-records { + text-align: center; + padding: 40px 0; + color: #999; + font-size: 14px; +} diff --git a/pages/launch/launch.js b/pages/launch/launch.js new file mode 100644 index 0000000..cb157a6 --- /dev/null +++ b/pages/launch/launch.js @@ -0,0 +1,9 @@ +{ + onLoad() { + // 延迟500ms跳转(可选,可用于显示小程序logo/slogan) + setTimeout(() => { + // 调用app.js中的登录检查方法 + getApp().checkLoginStatus() + }, 500) + } +} diff --git a/pages/launch/launch.json b/pages/launch/launch.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/launch/launch.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/launch/launch.wxml b/pages/launch/launch.wxml new file mode 100644 index 0000000..1cfc408 --- /dev/null +++ b/pages/launch/launch.wxml @@ -0,0 +1,7 @@ + + + + 智能记账本 + diff --git a/pages/launch/launch.wxss b/pages/launch/launch.wxss new file mode 100644 index 0000000..203d60b --- /dev/null +++ b/pages/launch/launch.wxss @@ -0,0 +1,18 @@ +.launch-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + background-color: #f5f7fa; +} + +.logo { + margin-bottom: 20rpx; +} + +.slogan { + font-size: 36rpx; + color: #3B82F6; + font-weight: bold; +} diff --git a/pages/login/login.js b/pages/login/login.js new file mode 100644 index 0000000..dc5fa51 --- /dev/null +++ b/pages/login/login.js @@ -0,0 +1,213 @@ +const request = require('../utils/request') +Page({ + data: { + // 账号密码 + account: '', + password: '', + // 显示密码切换 + showPassword: false, + // 错误状态 + accountError: false, + accountErrorMsg: '', + passwordError: false, + passwordErrorMsg: '', + // 加载状态 + isLoading: false + }, + + // 处理账号输入 + handleAccountInput(e) { + const account = e.detail.value.trim(); + this.setData({ + account, + accountError: false, + accountErrorMsg: '' + }); + }, + + // 处理密码输入 + handlePasswordInput(e) { + const password = e.detail.value; + this.setData({ + password, + passwordError: false, + passwordErrorMsg: '' + }); + }, + + // 切换密码显示状态 + togglePassword() { + this.setData({ + showPassword: !this.data.showPassword + }); + }, + + // 表单验证 + validateForm() { + let isValid = true; + const { account, password } = this.data; + + // 验证账号 + if (!account) { + this.setData({ + accountError: true, + accountErrorMsg: '请输入账号' + }); + isValid = false; + } else if (account.length < 4) { + this.setData({ + accountError: true, + accountErrorMsg: '账号长度不能少于4位' + }); + isValid = false; + } + + // 验证密码 + if (!password) { + this.setData({ + passwordError: true, + passwordErrorMsg: '请输入密码' + }); + isValid = false; + } else if (password.length < 6) { + this.setData({ + passwordError: true, + passwordErrorMsg: '密码长度不能少于6位' + }); + isValid = false; + } + + return isValid; + }, + + // 处理登录 + handleLogin() { + // 表单验证 + if (!this.validateForm()) { + return; + } + + const { account, password } = this.data; + + // 显示加载状态 + this.setData({ + isLoading: true + }); + + wx.request({ + url: 'http://localhost:48080/admin-api/system/auth/login', // 仅为示例,并非真实的接口地址 + method: 'POST', // 请求方法,可以是 GET, POST, PUT, DELETE 等 + data: { + "tenantName": "芋道源码", + "username": account, + "password": password, + "rememberMe": true + }, + header: { + 'Tenant-Id':1, + 'content-type': 'application/json' // 默认值,也可以根据后端要求设置其他值,如 'application/x-www-form-urlencoded' + }, + success :(res)=> { + console.log(res.data) + // 处理返回数据 + if(res.data.code==0){ + + wx.setStorageSync('token', res.data.data.accessToken); + console.log(wx.getStorageSync('token')) + // 跳转到主界面 + wx.switchTab({ + url: '/pages/index/index', + success: () => { + console.log('执行成功') + this.setData({ + isLoading: false + }); + } + }); + }else{ + this.setData({ + passwordError: true, + passwordErrorMsg: res.data.msg, + isLoading: false + }); + // 震动反馈 + wx.vibrateShort(); + } + }, + fail (err) { + console.error(err) + + }, + complete () { + // 请求完成时执行,无论成功或失败 + } + }) + }, + + // 微信快捷登录 + wxLogin(e) { + // 检查用户是否授权 + if (e.detail.userInfo) { + // 用户同意授权 + this.setData({ + isLoading: true + }); + + // 模拟微信登录过程 + setTimeout(() => { + // 保存用户信息 + wx.setStorageSync('userInfo', { + nickname: e.detail.userInfo.nickName, + avatar: e.detail.userInfo.avatarUrl, + loginTime: new Date().getTime(), + isWechatLogin: true + }); + + // 跳转到主界面 + wx.redirectTo({ + url: '/pages/index/index', + success: () => { + this.setData({ + isLoading: false + }); + } + }); + }, 1500); + } else { + // 用户拒绝授权 + wx.showToast({ + title: '授权失败,无法登录', + icon: 'none', + duration: 2000 + }); + } + }, + + // 跳转到忘记密码页面 + navigateToForgot() { + wx.navigateTo({ + url: '/pages/forgot-password/forgot-password' + }); + }, + + // 跳转到注册页面 + navigateToRegister() { + wx.navigateTo({ + url: '/pages/register/register' + }); + }, + + onLoad() { + // 检查是否已登录 + const userInfo = wx.getStorageSync('userInfo'); + if (userInfo && userInfo.loginTime) { + // 如果30天内登录过,自动跳转 + const now = new Date().getTime(); + if (now - userInfo.loginTime < 30 * 24 * 60 * 60 * 1000) { + wx.redirectTo({ + url: '/pages/index/index' + }); + } + } + } +}); diff --git a/pages/login/login.json b/pages/login/login.json new file mode 100644 index 0000000..ca1ac3b --- /dev/null +++ b/pages/login/login.json @@ -0,0 +1,7 @@ +{ + "navigationBarTitleText": "登录", + "navigationBarBackgroundColor": "#f5f7fa", + "navigationBarTextStyle": "black", + "backgroundColor": "#f5f7fa", + "usingComponents": {} +} diff --git a/pages/login/login.wxml b/pages/login/login.wxml new file mode 100644 index 0000000..f731f5c --- /dev/null +++ b/pages/login/login.wxml @@ -0,0 +1,83 @@ + diff --git a/pages/login/login.wxss b/pages/login/login.wxss new file mode 100644 index 0000000..b1d4313 --- /dev/null +++ b/pages/login/login.wxss @@ -0,0 +1,180 @@ +.login-container { + display: flex; + flex-direction: column; + min-height: 100vh; + background: linear-gradient(135deg, #f5f7fa 0%, #e4eaf1 100%); + padding: 0 30rpx; + box-sizing: border-box; +} + +/* 应用图标区域 */ +.app-icon { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 120rpx; + margin-bottom: 80rpx; +} + +.logo-img { + width: 160rpx; + height: 160rpx; + border-radius: 24rpx; + box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1); + margin-bottom: 30rpx; +} + +.app-name { + font-size: 36rpx; + font-weight: 600; + color: #333; + letter-spacing: 2rpx; +} + +/* 登录卡片 */ +.login-card { + background-color: #fff; + border-radius: 24rpx; + padding: 60rpx 40rpx; + box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.08); + margin-bottom: 50rpx; +} + +/* 输入框样式 */ +.input-group { + display: flex; + align-items: center; + border-bottom: 2rpx solid #eee; + padding: 25rpx 0; + position: relative; + transition: all 0.3s ease; +} + +.input-group.error { + border-bottom-color: #ff4d4f; +} + +.input-icon { + margin-right: 20rpx; +} + +.input-field { + flex: 1; + font-size: 30rpx; + color: #333; + height: 40rpx; +} + +.placeholder { + color: #c9c9c9; +} + +.toggle-password { + margin-left: 20rpx; +} + +.error-icon { + margin-left: 20rpx; +} + +.error-message { + color: #ff4d4f; + font-size: 24rpx; + margin-top: 10rpx; + margin-bottom: 10rpx; + height: 28rpx; + line-height: 28rpx; +} + +/* 忘记密码 */ +.forgot-password { + display: flex; + justify-content: flex-end; + margin: 15rpx 0 40rpx 0; +} + +.forgot-password text { + font-size: 26rpx; + color: #5a89e7; +} + +/* 登录按钮 */ +.login-button { + width: 100%; + height: 90rpx; + line-height: 90rpx; + background: linear-gradient(90deg, #5a89e7 0%, #3b6fe4 100%); + color: #fff; + font-size: 32rpx; + border-radius: 45rpx; + margin: 20rpx 0; + box-shadow: 0 6rpx 16rpx rgba(90, 137, 231, 0.4); + letter-spacing: 4rpx; +} + +.login-button::after { + border: none; +} + +/* 注册区域 */ +.register-section { + display: flex; + justify-content: center; + margin-top: 40rpx; + font-size: 26rpx; + color: #666; +} + +.register-link { + color: #5a89e7; + margin-left: 10rpx; + font-weight: 500; +} + +/* 其他登录方式 */ +.other-login { + display: flex; + align-items: center; + margin: 30rpx 0; +} + +.line { + flex: 1; + height: 1rpx; + background-color: #ddd; +} + +.other-login-text { + padding: 0 20rpx; + font-size: 24rpx; + color: #999; +} + +/* 社交登录 */ +.social-login { + display: flex; + justify-content: center; + margin-top: 20rpx; +} + +.social-btn { + display: flex; + align-items: center; + justify-content: center; + background-color: #f0f7ff; + color: #52c41a; + font-size: 28rpx; + padding: 0 30rpx; + height: 80rpx; + border-radius: 40rpx; +} + +.social-btn::after { + border: none; +} + +.social-icon { + width: 36rpx; + height: 36rpx; + margin-right: 15rpx; +} diff --git a/pages/profile/profile.js b/pages/profile/profile.js new file mode 100644 index 0000000..ac2f5f9 --- /dev/null +++ b/pages/profile/profile.js @@ -0,0 +1,146 @@ +Page({ + data: { + totalRecords: 0, + firstRecordDate: '', + consecutiveDays: 0 + }, + + onShow() { + this.updateStats(); + }, + + updateStats() { + const records = wx.getStorageSync('records') || []; + const totalRecords = records.length; + + let firstRecordDate = ''; + let consecutiveDays = 0; + + if (totalRecords > 0) { + // 计算首次记账日期 + const sortedRecords = [...records].sort((a, b) => new Date(a.date) - new Date(b.date)); + const firstDate = new Date(sortedRecords[0].date); + firstRecordDate = `${firstDate.getFullYear()}-${(firstDate.getMonth() + 1).toString().padStart(2, '0')}-${firstDate.getDate().toString().padStart(2, '0')}`; + + // 计算连续记账天数 + consecutiveDays = this.calculateConsecutiveDays(records); + } + + this.setData({ + totalRecords, + firstRecordDate, + consecutiveDays + }); + }, + + calculateConsecutiveDays(records) { + // 获取去重的日期列表 + const dateSet = new Set(); + records.forEach(record => { + dateSet.add(record.date); + }); + + const dateList = Array.from(dateSet).sort((a, b) => new Date(b) - new Date(a)); + + if (dateList.length === 0) { + return 0; + } + + // 检查是否包含今天 + const today = new Date(); + today.setHours(0, 0, 0, 0); + const lastDate = new Date(dateList[0]); + lastDate.setHours(0, 0, 0, 0); + + if (lastDate.getTime() !== today.getTime()) { + return 0; + } + + // 计算连续天数 + let consecutiveDays = 1; + for (let i = 0; i < dateList.length - 1; i++) { + const currentDate = new Date(dateList[i]); + currentDate.setHours(0, 0, 0, 0); + + const nextDate = new Date(dateList[i + 1]); + nextDate.setHours(0, 0, 0, 0); + + // 检查是否连续(相差一天) + const diffTime = currentDate.getTime() - nextDate.getTime(); + const diffDays = diffTime / (1000 * 60 * 60 * 24); + + if (diffDays === 1) { + consecutiveDays++; + } else { + break; + } + } + + return consecutiveDays; + }, + + exportData() { + const records = wx.getStorageSync('records') || []; + if (records.length === 0) { + wx.showToast({ + title: '暂无数据可导出', + icon: 'none', + duration: 2000 + }); + return; + } + + // 转换为CSV格式 + let csvContent = "日期,类型,分类,金额,备注\n"; + records.forEach(record => { + const type = record.type === 'income' ? '收入' : '支出'; + csvContent += `${record.date},${type},${record.categoryName},${record.amount},${record.note || ''}\n`; + }); + + // 这里仅做演示,实际导出功能需要后端支持或使用微信的文件系统API + wx.showModal({ + title: '导出成功', + content: '数据已导出为CSV格式', + showCancel: false + }); + }, + + clearData() { + wx.showModal({ + title: '确认清空', + content: '确定要清空所有记账数据吗?此操作不可恢复。', + cancelText: '取消', + confirmText: '确认', + success: (res) => { + if (res.confirm) { + wx.setStorageSync('records', []); + wx.showToast({ + title: '数据已清空', + icon: 'success', + duration: 2000 + }); + this.updateStats(); + } + } + }); + }, + + showAbout() { + wx.showModal({ + title: '关于简易记账', + content: '简易记账是一款简单实用的记账工具,帮助你记录和管理个人财务。', + showCancel: false, + confirmText: '我知道了' + }); + }, + + outLogin() { + wx.showModal({ + title: '关于简易记账', + content: '简易记账是一款简单实用的记账工具,帮助你记录和管理个人财务。', + showCancel: false, + confirmText: '我知道了' + }); + } + +}) diff --git a/pages/profile/profile.wxml b/pages/profile/profile.wxml new file mode 100644 index 0000000..4caa26c --- /dev/null +++ b/pages/profile/profile.wxml @@ -0,0 +1,75 @@ + + + + + + + + + + + 分类管理 + + + + + + + + 导出数据 + + + + + + + + 清空数据 + + + + + + + + 关于我们 + + + + + + + + 退出登录 + + + + + + + + 记账统计 + + + {{totalRecords}} + 总记录数 + + + {{firstRecordDate || '-'}} + 首次记账 + + + {{consecutiveDays}} + 连续记账(天) + + + + diff --git a/pages/profile/profile.wxss b/pages/profile/profile.wxss new file mode 100644 index 0000000..fa65c79 --- /dev/null +++ b/pages/profile/profile.wxss @@ -0,0 +1,128 @@ +.container { + background-color: #f5f5f5; + min-height: 100vh; + padding-bottom: 15px; +} + +.user-info { + background: linear-gradient(135deg, #4CAF50 0%, #8BC34A 100%); + padding: 30px 20px; + display: flex; + align-items: center; +} + +.avatar { + width: 80px; + height: 80px; + border-radius: 50%; + background-color: white; + padding: 5px; + margin-right: 15px; +} + +.avatar image { + width: 100%; + height: 100%; + border-radius: 50%; +} + +.user-details { + color: white; +} + +.username { + font-size: 20px; + font-weight: 600; + display: block; + margin-bottom: 5px; +} + +.user-desc { + font-size: 14px; + opacity: 0.9; +} + +.function-list { + background-color: white; + margin: 15px; + border-radius: 15px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.function-item { + display: flex; + align-items: center; + padding: 15px 20px; + border-bottom: 1px solid #f5f5f5; + color: #333; +} + +.function-item:last-child { + border-bottom: none; +} + +.function-icon { + width: 30px; + height: 30px; + border-radius: 50%; + background-color: #e8f5e9; + color: #4CAF50; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; +} + +.function-icon .iconfont { + font-size: 18px; +} + +.function-name { + flex: 1; + font-size: 16px; +} + +.function-item .icon-arrow-right { + color: #ccc; + font-size: 16px; +} + +.stats-card { + background-color: white; + margin: 0 15px; + border-radius: 15px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.stats-title { + font-size: 18px; + font-weight: 600; + color: #333; + display: block; + margin-bottom: 15px; +} + +.stats-grid { + display: flex; + justify-content: space-around; +} + +.stats-item { + text-align: center; + flex: 1; +} + +.stats-value { + font-size: 22px; + font-weight: 600; + color: #333; + display: block; + margin-bottom: 5px; +} + +.stats-label { + font-size: 14px; + color: #666; +} diff --git a/pages/statistics/statistics.js b/pages/statistics/statistics.js new file mode 100644 index 0000000..6cce705 --- /dev/null +++ b/pages/statistics/statistics.js @@ -0,0 +1,209 @@ +Page({ + data: { + selectedMonth: '', + selectedMonthText: '', + summary: { + income: '0.00', + expense: '0.00', + balance: '0.00' + }, + activeType: 'expense', + categoryStats: [], + monthRecords: [] + }, + + onLoad() { + // 初始化当前月份 + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const selectedMonth = `${year}-${month}`; + + this.setData({ + selectedMonth, + selectedMonthText: `${year}年${month}月` + }); + + this.updateStatistics(); + }, + + onMonthChange(e) { + const selectedMonth = e.detail.value; + const [year, month] = selectedMonth.split('-'); + this.setData({ + selectedMonth, + selectedMonthText: `${year}年${month}月` + }); + + this.updateStatistics(); + }, + + setActiveType(e) { + const type = e.currentTarget.dataset.type; + this.setData({ activeType: type }, () => { + this.calculateCategoryStats(); + this.drawPieChart(); + }); + }, + + updateStatistics() { + // 获取所有记录 + const records = wx.getStorageSync('records') || []; + const [year, month] = this.data.selectedMonth.split('-'); + + // 筛选当月记录 + const monthRecords = records.filter(record => { + const recordDate = new Date(record.date); + return recordDate.getFullYear() === parseInt(year) && + (recordDate.getMonth() + 1) === parseInt(month); + }); + + // 按日期倒序排列 + monthRecords.sort((a, b) => new Date(b.date) - new Date(a.date)); + + // 计算收支汇总 + let income = 0; + let expense = 0; + + monthRecords.forEach(record => { + if (record.type === 'income') { + income += parseFloat(record.amount); + } else { + expense += parseFloat(record.amount); + } + }); + + const balance = income - expense; + + this.setData({ + monthRecords, + summary: { + income: income.toFixed(2), + expense: expense.toFixed(2), + balance: balance.toFixed(2) + } + }, () => { + this.calculateCategoryStats(); + this.drawPieChart(); + }); + }, + + calculateCategoryStats() { + const { monthRecords, activeType } = this.data; + const typeRecords = monthRecords.filter(record => record.type === activeType); + + // 按分类汇总 + const categoryMap = {}; + + typeRecords.forEach(record => { + if (!categoryMap[record.categoryId]) { + categoryMap[record.categoryId] = { + categoryId: record.categoryId, + categoryName: record.categoryName, + amount: 0, + count: 0 + }; + } + + categoryMap[record.categoryId].amount += parseFloat(record.amount); + categoryMap[record.categoryId].count += 1; + }); + + // 转换为数组并排序 + let categoryStats = Object.values(categoryMap); + categoryStats.sort((a, b) => b.amount - a.amount); + + // 计算百分比 + const total = activeType === 'income' + ? parseFloat(this.data.summary.income) + : parseFloat(this.data.summary.expense); + + if (total > 0) { + categoryStats.forEach(item => { + item.percentage = Math.round((item.amount / total) * 100); + item.amount = item.amount.toFixed(2); + }); + } + + // 分配颜色 + const colors = ['#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3', '#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39']; + categoryStats.forEach((item, index) => { + item.color = colors[index % colors.length]; + }); + + this.setData({ categoryStats }); + }, + + drawPieChart() { + const { categoryStats } = this.data; + + if (categoryStats.length === 0) { + return; + } + + const ctx = wx.createCanvasContext('pieChart', this); + const centerX = 120; // 饼图中心X坐标 + const centerY = 120; // 饼图中心Y坐标 + const radius = 90; // 饼图半径 + + let startAngle = 0; + + categoryStats.forEach(item => { + const percentage = parseFloat(item.percentage); + const endAngle = startAngle + 2 * Math.PI * (percentage / 100); + + // 绘制扇形 + ctx.beginPath(); + ctx.setFillStyle(item.color); + ctx.moveTo(centerX, centerY); + ctx.arc(centerX, centerY, radius, startAngle, endAngle, false); + ctx.closePath(); + ctx.fill(); + + // 计算文本位置 + const midAngle = startAngle + (endAngle - startAngle) / 2; + const textRadius = radius * 0.6; // 文本距离中心的距离 + const textX = centerX + Math.cos(midAngle) * textRadius; + const textY = centerY + Math.sin(midAngle) * textRadius; + + // 绘制百分比文本 + ctx.setFontSize(14); + ctx.setFillStyle('#333'); + ctx.setTextAlign('center'); + ctx.setTextBaseline('middle'); + ctx.fillText(`${percentage}%`, textX, textY); + + startAngle = endAngle; + }); + + // 绘制中心空白区域 + ctx.beginPath(); + ctx.setFillStyle('#ffffff'); + ctx.arc(centerX, centerY, radius * 0.4, 0, 2 * Math.PI, false); + ctx.fill(); + + // 绘制中心文本 + const total = this.data.activeType === 'income' + ? this.data.summary.income + : this.data.summary.expense; + + ctx.setFontSize(16); + ctx.setFillStyle('#333'); + ctx.setTextAlign('center'); + ctx.setTextBaseline('middle'); + ctx.fillText(`总计`, centerX, centerY - 10); + + ctx.setFontSize(18); + ctx.setFillStyle(this.data.activeType === 'income' ? '#4CAF50' : '#f44336'); + ctx.fillText(`¥${total}`, centerX, centerY + 15); + + ctx.draw(); + }, + + formatDate(dateStr) { + const date = new Date(dateStr); + const month = date.getMonth() + 1; + const day = date.getDate(); + return `${month}月${day}日`; + } +}) diff --git a/pages/statistics/statistics.wxml b/pages/statistics/statistics.wxml new file mode 100644 index 0000000..0f43ccb --- /dev/null +++ b/pages/statistics/statistics.wxml @@ -0,0 +1,88 @@ + + + + + + + {{selectedMonthText}} + + + + + + + + + 收入 + ¥ {{summary.income}} + + + 支出 + ¥ {{summary.expense}} + + + 结余 + ¥ {{summary.balance}} + + + + + + + 分类统计 + + 支出 + 收入 + + + + + + + + + + + + + + {{item.categoryName}} + + + ¥ {{item.amount}} + {{item.percentage}}% + + + + + 本月暂无{{activeType === 'expense' ? '支出' : '收入'}}记录 + + + + + + + + 明细记录 + + + + + + + + + {{item.categoryName}} + {{item.note || '无备注'}} + {{formatDate(item.date)}} + + + {{item.type === 'income' ? '+' : '-'}}¥ {{item.amount}} + + + + + 本月暂无记录 + + + diff --git a/pages/statistics/statistics.wxss b/pages/statistics/statistics.wxss new file mode 100644 index 0000000..4c7695a --- /dev/null +++ b/pages/statistics/statistics.wxss @@ -0,0 +1,234 @@ +.container { + background-color: #f5f5f5; + min-height: 100vh; + padding-bottom: 60px; +} + +.month-picker { + padding: 15px; + background-color: white; +} + +.picker-view { + display: flex; + align-items: center; + justify-content: center; + height: 40px; + background-color: #f5f5f5; + border-radius: 20px; + color: #333; + font-size: 16px; +} + +.picker-view .iconfont { + margin: 0 8px; + color: #666; +} + +.summary-card { + display: flex; + justify-content: space-around; + background-color: white; + margin: 15px; + border-radius: 15px; + padding: 20px 10px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.summary-item { + text-align: center; + flex: 1; +} + +.summary-label { + display: block; + font-size: 14px; + color: #666; + margin-bottom: 5px; +} + +.summary-amount { + font-size: 22px; + font-weight: 600; +} + +.income { + color: #4CAF50; +} + +.expense { + color: #f44336; +} + +.balance { + color: #2196F3; +} + +.category-stats, .records-section { + background-color: white; + margin: 15px; + border-radius: 15px; + padding: 15px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; +} + +.section-title { + font-size: 18px; + font-weight: 600; + color: #333; +} + +.type-tabs { + display: flex; +} + +.tab { + padding: 5px 12px; + font-size: 14px; + border-radius: 15px; + margin-left: 10px; +} + +.tab.active { + background-color: #e8f5e9; + color: #4CAF50; +} + +.chart-container { + display: flex; + justify-content: center; + margin-bottom: 20px; +} + +.pie-chart { + width: 240px; + height: 240px; +} + +.category-details { + margin-bottom: 10px; +} + +.category-detail-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 0; + border-bottom: 1px solid #f5f5f5; +} + +.category-detail-item:last-child { + border-bottom: none; +} + +.category-info { + display: flex; + align-items: center; +} + +.category-color { + width: 12px; + height: 12px; + border-radius: 50%; + margin-right: 10px; +} + +.category-name { + font-size: 16px; + color: #333; +} + +.category-amount { + text-align: right; +} + +.category-amount text:first-child { + font-size: 16px; + font-weight: 500; + margin-right: 10px; +} + +.category-percentage { + font-size: 14px; + color: #999; +} + +.records-list { + max-height: 300px; + overflow-y: auto; +} + +.record-item { + display: flex; + align-items: center; + padding: 12px 0; + border-bottom: 1px solid #f5f5f5; +} + +.record-item:last-child { + border-bottom: none; +} + +.record-icon { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; +} + +.income-icon { + background-color: #e8f5e9; + color: #4CAF50; +} + +.expense-icon { + background-color: #ffebee; + color: #f44336; +} + +.iconfont { + font-size: 20px; +} + +.record-details { + flex: 1; +} + +.record-title { + font-size: 16px; + color: #333; + margin-bottom: 3px; +} + +.record-note { + font-size: 12px; + color: #999; + margin-bottom: 2px; +} + +.record-date { + font-size: 12px; + color: #ccc; +} + +.record-amount { + font-size: 16px; + font-weight: 500; +} + +.no-data, .no-records { + text-align: center; + padding: 30px 0; + color: #999; + font-size: 14px; +} diff --git a/pages/utils/request.js b/pages/utils/request.js new file mode 100644 index 0000000..80de07a --- /dev/null +++ b/pages/utils/request.js @@ -0,0 +1,111 @@ +/** + * 封装微信小程序请求,自动处理token + */ +const baseUrl='http://localhost:48080' + +const request = (url, options = {}) => { + // 返回Promise,方便使用async/await + return new Promise((resolve, reject) => { + // 默认请求头 + const header = { + 'Content-Type': 'application/json', + ...options.header + } + + // 从本地存储获取token并添加到请求头 + const token = wx.getStorageSync('token') + if (token) { + header['Authorization'] = `Bearer ${token}` + } + // 合并请求配置 + const config = { + url:baseUrl+url, + method: options.method || 'GET', + data: options.data || {}, + header, + // 成功回调 + success: (res) => { + if (res.statusCode === 200) { + // 业务成功,返回数据 + if(res.data&&res.data.code==401){ + console.log("登录已过期,请重新登录") + // token失效或未登录,清除token并跳转登录页 + wx.removeStorageSync('token') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + + // 记录当前页面,登录后返回 + const pages = getCurrentPages() + const currentPage = pages[pages.length - 1] + wx.redirectTo({ + url: `/pages/login/login?redirect=${currentPage.route}` + }) + + reject(new Error('未授权或token已过期')) + }else{ + console.log("111") + resolve(res.data) + } + } else if (res.statusCode === 401) { + console.log("登录已过期,请重新登录") + // token失效或未登录,清除token并跳转登录页 + wx.removeStorageSync('token') + wx.showToast({ + title: '登录已过期,请重新登录', + icon: 'none' + }) + + // 记录当前页面,登录后返回 + const pages = getCurrentPages() + const currentPage = pages[pages.length - 1] + wx.redirectTo({ + url: `/pages/login/login?redirect=${currentPage.route}` + }) + + reject(new Error('未授权或token已过期')) + } else { + // 其他错误(如400、500等) + wx.showToast({ + title: res.data?.message || '请求失败', + icon: 'none' + }) + reject(new Error(`请求错误: ${res.statusCode}`)) + } + }, + // 失败回调(如网络错误) + fail: (err) => { + wx.showToast({ + title: '网络异常,请稍后再试', + icon: 'none' + }) + reject(err) + }, + ...options + } + console.log('config.url',config.url) + // 发起原生请求 + wx.request(config) + }) +} + +// 快捷方法 +request.get = (url, data, options = {}) => { + return request(url, { ...options, method: 'GET', data }) +} + +request.post = (url, data, options = {}) => { + return request(url, { ...options, method: 'POST', data }) +} + +request.put = (url, data, options = {}) => { + return request(url, { ...options, method: 'PUT', data }) +} + +request.delete = (url, data, options = {}) => { + return request(url, { ...options, method: 'DELETE', data }) +} + +module.exports = request + diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..39e75ee --- /dev/null +++ b/project.config.json @@ -0,0 +1,25 @@ +{ + "setting": { + "es6": true, + "postcss": true, + "minified": true, + "uglifyFileName": false, + "enhance": true, + "packNpmRelationList": [], + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "useCompilerPlugins": false, + "minifyWXML": true + }, + "compileType": "miniprogram", + "simulatorPluginLibVersion": {}, + "packOptions": { + "ignore": [], + "include": [] + }, + "appid": "wx8002cc7a350eb380", + "editorSetting": {} +} \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json new file mode 100644 index 0000000..8d2d774 --- /dev/null +++ b/project.private.config.json @@ -0,0 +1,14 @@ +{ + "libVersion": "3.10.1", + "projectname": "accounting-wechat-miniprogram%20(1)", + "setting": { + "urlCheck": false, + "coverView": true, + "lazyloadPlaceholderEnable": false, + "skylineRenderEnable": false, + "preloadBackgroundData": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "compileHotReLoad": true + } +} \ No newline at end of file