From 225a2d7fce8ca321ce361fbdd5535690693ffe1c Mon Sep 17 00:00:00 2001 From: ldeyun Date: Sun, 23 Nov 2025 22:30:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 2 +- common/appInit.js | 14 +- env.js | 33 + jest.config.js | 11 + pages-config/pages-all.json | 39 +- pages-config/tabBar.json | 24 +- pages.json | 60 +- pages/cal/cal.vue | 370 ++++++ pages/grid/grid.vue | 399 ------- pages/grid/login.vue | 21 - pages/index/index.vue | 52 + pages/info/info.vue | 9 + pages/list/detail.vue | 373 ------ pages/list/list.nvue | 206 ---- pages/ucenter.vue | 505 -------- pages/ucenter/ucenter.vue | 508 ++++++++ static/logo.png | Bin 0 -> 4023 bytes static/tabbar/cal.png | Bin 0 -> 10277 bytes static/tabbar/cal_active.png | Bin 0 -> 11435 bytes static/tabbar/grid.png | Bin 2695 -> 0 bytes static/tabbar/grid_active.png | Bin 2556 -> 0 bytes static/tabbar/info.png | Bin 0 -> 7959 bytes static/tabbar/info_active.png | Bin 0 -> 8600 bytes .../database/ngTools_Dict.schema.json | 64 +- .../database/ngTools_DictItem.schema.json | 83 +- .../database/ngTools_MeterPar.schema.json | 352 +++++- .../database/uni-id-users.schema.json | 443 ++++++- .../database/uni-stat-error-logs.schema.json | 103 +- .../uni-stat-error-result.schema.json | 97 +- .../components/next-tree/next-tree.vue | 1034 +++++++++++++++++ .../next-tree/components/next-tree/style.css | 269 +++++ uni_modules/next-tree/package.json | 84 ++ .../uni-config-center/uni-id/config.json | 44 +- .../uni-config-center/uni-id/package.json | 4 + .../common/uni-id-common/index.js | 577 ++++++++- .../uni-id-pages-fab-login.vue | 975 ++++++++-------- uni_modules/uni-id-pages/config.js | 2 +- uni_modules/uts-openSchema/changelog.md | 2 - uni_modules/uts-openSchema/package.json | 82 -- uni_modules/uts-openSchema/readme.md | 6 - .../utssdk/app-android/config.json | 3 - .../utssdk/app-android/index.uts | 15 - .../uts-openSchema/utssdk/app-ios/config.json | 3 - .../uts-openSchema/utssdk/app-ios/index.uts | 14 - .../uts-openSchema/utssdk/interface.uts | 1 - 45 files changed, 4667 insertions(+), 2216 deletions(-) create mode 100644 env.js create mode 100644 jest.config.js create mode 100644 pages/cal/cal.vue delete mode 100644 pages/grid/grid.vue delete mode 100644 pages/grid/login.vue create mode 100644 pages/index/index.vue create mode 100644 pages/info/info.vue delete mode 100644 pages/list/detail.vue delete mode 100644 pages/list/list.nvue delete mode 100644 pages/ucenter.vue create mode 100644 pages/ucenter/ucenter.vue create mode 100644 static/logo.png create mode 100644 static/tabbar/cal.png create mode 100644 static/tabbar/cal_active.png delete mode 100644 static/tabbar/grid.png delete mode 100644 static/tabbar/grid_active.png create mode 100644 static/tabbar/info.png create mode 100644 static/tabbar/info_active.png create mode 100644 uni_modules/next-tree/components/next-tree/next-tree.vue create mode 100644 uni_modules/next-tree/components/next-tree/style.css create mode 100644 uni_modules/next-tree/package.json create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/package.json delete mode 100644 uni_modules/uts-openSchema/changelog.md delete mode 100644 uni_modules/uts-openSchema/package.json delete mode 100644 uni_modules/uts-openSchema/readme.md delete mode 100644 uni_modules/uts-openSchema/utssdk/app-android/config.json delete mode 100644 uni_modules/uts-openSchema/utssdk/app-android/index.uts delete mode 100644 uni_modules/uts-openSchema/utssdk/app-ios/config.json delete mode 100644 uni_modules/uts-openSchema/utssdk/app-ios/index.uts delete mode 100644 uni_modules/uts-openSchema/utssdk/interface.uts diff --git a/App.vue b/App.vue index 07e285c..768bbd2 100644 --- a/App.vue +++ b/App.vue @@ -19,7 +19,7 @@ this.globalData.$i18n = this.$i18n this.globalData.$t = str => this.$t(str) initApp(); - uniIdPageInit() + uniIdPageInit() // #ifdef APP-PLUS //checkIsAgree(); APP端暂时先用原生默认生成的。目前,自定义方式启动vue界面时,原生层已经请求了部分权限这并不符合国家的法规 diff --git a/common/appInit.js b/common/appInit.js index b62d38c..4a0f3e0 100644 --- a/common/appInit.js +++ b/common/appInit.js @@ -47,17 +47,17 @@ export default async function() { methodName, // 云对象的方法名称 params // 参数列表 }) { - // console.log('interceptObject',{ - // objectName, // 云对象名称 - // methodName, // 云对象的方法名称 - // params // 参数列表 - // }); + console.log('interceptObject',{ + objectName, // 云对象名称 + methodName, // 云对象的方法名称 + params // 参数列表 + }); if(objectName == "uni-id-co" && (methodName.includes('loginBy') || ['login','registerUser'].includes(methodName) )){ console.log('执行登录相关云对象'); - params[0].inviteCode = await new Promise((callBack) => { + params[0].inviteCode = await new Promise((callBack) => { uni.getClipboardData({ success: function(res) { - console.log('剪切板内容:'+res.data); + console.log('剪切板内容:'+JSON.stringify(res)); if (res.data.slice(0, 18) == 'uniInvitationCode:') { let uniInvitationCode = res.data.slice(18, 38) console.log('当前用户是其他用户推荐下载的,推荐者的code是:' + uniInvitationCode); diff --git a/env.js b/env.js new file mode 100644 index 0000000..3e966c3 --- /dev/null +++ b/env.js @@ -0,0 +1,33 @@ +// 参考文档: https://uniapp.dcloud.net.cn/worktile/auto/hbuilderx-extension/#envjs +module.exports = { + "is-custom-runtime": false, + "UNI_TEST_CUSTOM_ENV": {}, + "compile": true, + "h5": { + "options": { + "headless": true + }, + "executablePath": "" + }, + "mp-weixin": { + "port": 9420, + "account": "", + "args": "", + "cwd": "", + "launch": true, + "teardown": "disconnect", + "remote": false, + "executablePath": "" + }, + "app-plus": { + "android": { + "id": "", + "executablePath": "" + }, + "version": "", + "ios": { + "id": "", + "executablePath": "" + } + } +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..a54d98a --- /dev/null +++ b/jest.config.js @@ -0,0 +1,11 @@ +module.exports = { + testTimeout: 10000, + reporters: [ + 'default' + ], + watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'], + moduleFileExtensions: ['js', 'json'], + rootDir: __dirname, + testMatch: ["/pages/**/*test.[jt]s?(x)"], + testPathIgnorePatterns: ['/node_modules/'] +} diff --git a/pages-config/pages-all.json b/pages-config/pages-all.json index 39620ad..240d441 100644 --- a/pages-config/pages-all.json +++ b/pages-config/pages-all.json @@ -1,43 +1,36 @@ /* /// Pages-Tool: 该文件是pages-tool插件的配置文件,根据pages-config.json的配置,本文件的内容可能合并到pages.json*/ { - "pages": [ - // { - // "path": "pages/grid/login", - // "style": { - // "navigationStyle": "custom" - // } - // } - // , - - { - "path": "pages/grid/grid", + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", "style": { - "navigationStyle": "custom" - } - },{ - "path": "pages/ucenter", - "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "主页" } }, { - "path": "pages/list/list", + "path": "pages/cal/cal", "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "计算" } }, { - "path": "pages/list/detail", + "path": "pages/info/info", "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "资料" + } + }, + { + "path": "pages/ucenter/ucenter", + "style": { + "navigationBarTitleText": "我的" } } - // #ifdef APP-PLUS - ,{ + , + { "path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup", "style": { "disableScroll": true, diff --git a/pages-config/tabBar.json b/pages-config/tabBar.json index bd786b9..56091a0 100644 --- a/pages-config/tabBar.json +++ b/pages-config/tabBar.json @@ -1,4 +1,3 @@ -/* /// Pages-Tool: 该文件是pages-tool插件的配置文件,根据pages-config.json的配置,本文件的内容可能合并到pages.json*/ { "tabBar": { "color": "#7A7E83", @@ -6,23 +5,28 @@ "borderStyle": "black", "backgroundColor": "#FFFFFF", "list": [{ - "pagePath": "pages/grid/grid", + "pagePath": "pages/index/index", "iconPath": "static/tabbar/list.png", "selectedIconPath": "static/tabbar/list_active.png", "text": "首页" + }, { + "pagePath": "pages/cal/cal", + "iconPath": "static/tabbar/cal.png", + "selectedIconPath": "static/tabbar/cal_active.png", + "text": "计算" + }, { + "pagePath": "pages/info/info", + "iconPath": "static/tabbar/info.png", + "selectedIconPath": "static/tabbar/info_active.png", + "text": "资料" } - // , { - // "pagePath": "pages/list/list", - // "iconPath": "static/tabbar/grid.png", - // "selectedIconPath": "static/tabbar/grid_active.png", - // "text": "常用资料" - // } + , { - "pagePath": "pages/ucenter", + "pagePath": "pages/ucenter/ucenter", "iconPath": "static/tabbar/me.png", "selectedIconPath": "static/tabbar/me_active.png", "text": "我的" } ] } -} \ No newline at end of file +}s \ No newline at end of file diff --git a/pages.json b/pages.json index c8a00fd..888b49d 100644 --- a/pages.json +++ b/pages.json @@ -1,42 +1,35 @@ { - "pages": [ - // { - // "path": "pages/grid/login", - // "style": { - // "navigationStyle": "custom" - // } - // } - // , - - { - "path": "pages/grid/grid", + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", "style": { - "navigationStyle": "custom" - } - },{ - "path": "pages/ucenter", - "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "主页" } }, { - "path": "pages/list/list", + "path": "pages/cal/cal", "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "计算" } }, { - "path": "pages/list/detail", + "path": "pages/info/info", "style": { - "navigationStyle": "custom" + "navigationBarTitleText": "资料" + } + }, + { + "path": "pages/ucenter/ucenter", + "style": { + "navigationBarTitleText": "我的" } } - // #ifdef APP-PLUS - ,{ + , + { "path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup", "style": { "disableScroll": true, @@ -648,19 +641,24 @@ "borderStyle": "black", "backgroundColor": "#FFFFFF", "list": [{ - "pagePath": "pages/grid/grid", + "pagePath": "pages/index/index", "iconPath": "static/tabbar/list.png", "selectedIconPath": "static/tabbar/list_active.png", "text": "首页" + }, { + "pagePath": "pages/cal/cal", + "iconPath": "static/tabbar/cal.png", + "selectedIconPath": "static/tabbar/cal_active.png", + "text": "计算" + }, { + "pagePath": "pages/info/info", + "iconPath": "static/tabbar/info.png", + "selectedIconPath": "static/tabbar/info_active.png", + "text": "资料" } - // , { - // "pagePath": "pages/list/list", - // "iconPath": "static/tabbar/grid.png", - // "selectedIconPath": "static/tabbar/grid_active.png", - // "text": "常用资料" - // } + , { - "pagePath": "pages/ucenter", + "pagePath": "pages/ucenter/ucenter", "iconPath": "static/tabbar/me.png", "selectedIconPath": "static/tabbar/me_active.png", "text": "我的" diff --git a/pages/cal/cal.vue b/pages/cal/cal.vue new file mode 100644 index 0000000..cfd5ffd --- /dev/null +++ b/pages/cal/cal.vue @@ -0,0 +1,370 @@ + + + + + diff --git a/pages/grid/grid.vue b/pages/grid/grid.vue deleted file mode 100644 index f9de758..0000000 --- a/pages/grid/grid.vue +++ /dev/null @@ -1,399 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/grid/login.vue b/pages/grid/login.vue deleted file mode 100644 index 629e443..0000000 --- a/pages/grid/login.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue new file mode 100644 index 0000000..ec0ec26 --- /dev/null +++ b/pages/index/index.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/pages/info/info.vue b/pages/info/info.vue new file mode 100644 index 0000000..96689d5 --- /dev/null +++ b/pages/info/info.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/pages/list/detail.vue b/pages/list/detail.vue deleted file mode 100644 index 5bbef34..0000000 --- a/pages/list/detail.vue +++ /dev/null @@ -1,373 +0,0 @@ - - - - - diff --git a/pages/list/list.nvue b/pages/list/list.nvue deleted file mode 100644 index a4a0e46..0000000 --- a/pages/list/list.nvue +++ /dev/null @@ -1,206 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/ucenter.vue b/pages/ucenter.vue deleted file mode 100644 index 8512bc1..0000000 --- a/pages/ucenter.vue +++ /dev/null @@ -1,505 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/ucenter/ucenter.vue b/pages/ucenter/ucenter.vue new file mode 100644 index 0000000..1e52aa4 --- /dev/null +++ b/pages/ucenter/ucenter.vue @@ -0,0 +1,508 @@ + + + + + diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a GIT binary patch literal 4023 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 SYs}WS&%*SCNx89m_5aR%71d$ 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 literal 0 HcmV?d00001 diff --git a/static/tabbar/grid.png b/static/tabbar/grid.png deleted file mode 100644 index 938b8212107cec8b8ac8b458f620afed4def22ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2695 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 K#QtG=HuAqSbgTpb diff --git a/static/tabbar/info.png b/static/tabbar/info.png new file mode 100644 index 0000000000000000000000000000000000000000..982c1602fb60faf5db4ea9df50e0301c60efd0c8 GIT binary patch literal 7959 zcmYj$1yEFP*geex(o0E)2-4lnN-0V#EJ()^Qc_Ebz>?D4Dd7^bfOJYPDcvC5(jbU@ z`}@y)^ZoDKd*7KmbL)AZ_dMr0C+e-X8ZqHhLJSNHVhwdwUGzBk-vPiwpQ|9%dFX+_ zP2I=?1A{T*zXLOV`^**tgK0=ZRY~7x@z~Vg4LFebcr|iVy-IqCbE!;$r2$x?B@^$b z4NZ(a+e|W{$lug*AKHF#Q{JMvGV}1^W?*J!`#{%FW9A{bwL(%nj#1`%A?~=2@d@n+ z{mA{ZgoJv(PYH^&IO;qOc77-ED@N2`4G$I;21XD;;Lr(2yOy&1`uQz-hzkjIdwt^_)|1x*hE$uKbsS+KC`NTS1HJx>_l7|u{35=$?cO|74g8ksUIjOdkBwED^SU%|4vCB7U+xgWiq+jq!GbHY;ryy*#>50X zhV%mQb>|APSuhmU_ioe$JJdo9MYRz|yQz-BAY6?k#V?BV7&wWJj-pxjHoewf~y0p{n>9uBAgMheld%zdfoXMHvhp ztc@9m9rv$3M8I*RG4MNOqbpQYAdT1LDe0-fx`d5Oj5qGS_#-I`_^fb6FqlEkTbV1O zXJTO{_BcN%xVyqIlT~0y6~#4pdn-x8@Rx%5(K0(h62GYIhN8h`DXOsWP+4gsIBtyp zXceZYo)!9Y`?xSN~3;7{u&A0!W}ZHb2q{~y|; z$Y3wns!}lgVVKmrnTb+Ur3p3t`|Gn-lZxB*NBO=$t#o+Wo{@510$uMu;pFTp!PJ7P#V^*IP~2VPW*_0zto+ykaC@bgnULa$0!_@*tzX6F8Qd zn9luPP#hi{%s{9o@5ytQq}j{HQmJ;Xk>-y_{No9g^r)tCK4wh2^InR}wfD7>6Maod zNRjJqqG||xGmSbMDW%pIC|C9K^DD=;F(M(zsy;-&Hf{T@8zZTWQF!&?O)uRuw);^o z7^h{{Usy$U`7a@GbdiOQx47eb>h;A5uN+w~yaDZ;=!0f_Qs%xMQZaS`2?^Ho-lsJT zRV)K#et=@hOEvYiy!8LRMBZd7lvB zVc&KBT?)!zdN8OmiL=Z5D2xE%bf1j5q+ecoRtuYb+!pikzk4-PVfleE&vBtkl*(6S z*2sbwQt8hq7Yd}J?%LL6+tD^TVQ$*J>AwT%rKqrcus3U7t`Dg0n8lL^0UgLmxy{oNfu0Xp~oepCR0f`_*Wt27BXNK$PCxI$_JTq=>u3#As6hgP%ub? z$Aa4tD8i$qAb?+p%_ypi%RUH)BCft(bZcivvZxx3fE01j=fXBNUx?5k=qAm;{MqYr zp1`CffDU#NqYR$Gz^5XBuk5!ltvgL(vL$vgTgU_6&S9ELsHwjuTh3;MqJEbBtHw^i zQiAIjV-Os{X-04HY51S%Bc?nKyv`{{D6ERv~HWXddj)y}iqg^k7Q|bHNY8gYB>U-s_iY#$;ruE zwMZbTsO0D8kMtk^SP%1zTFt^lr(ypYWf?MHArSI-YwgAz;wM!?wKad1e7l!iRg^w* zXFKr5@^;qQ$)uCSV>fNF)a+$kY_hnMa|O%e{VKkF`vm6~IZczJy&rvX{D1fG*FYfO zOumCJh!>)-Lk|p{7ofcI{9#l(BSZ$*^uM)t1_uEbtKT~A2p_L1_&zw{ZFKn;55$dk zcJ&h4r+lRs9YGOFIJ1M0X- z;qsu$NYgYL9on6$VHslF)u zP3aBg=iIZ>e!Q*ST{Zy;H>*VCsx|;Kkz+3<1n*m>lewHvcmc0Q;qMj`{wZH7IGKGG zwRH0MUcx>qorAjo*g_&TNM_~cL9RTpx*FW07C-RiA*g+u`0skFfYr(JBzy}YNu}|g zPLtbZr6r7?=%bq6rWJ3H8yyf%WUS6=?NzM~1e;o{N?0&zJZ{V? z&2P9gqd!x+b4Hvhy^5=$k!hJ&q0gPV?fKmaFUxmSa?l{C)ys+L&LDrL5x4KrzS8dV zXGUTo$X3xlWChr}ORut4GOV+5ztPwk{O4ll$FVoNh={d;r+$}OfPBnNqSn!C*A1xbK!z+S6SQAbvDAY^o1JPN-irM z&Ubm?eO{1`qhKScq&}I5;;E(3c=?5Bbj8GuvimSUD6*=QWc#i`i1^)zQ1ut?!M-@{ zsTR za3f05U+wwFE0pWR$`mCtZsO5b76d}O893{wAmBsSUBxzvPQXn9@_6Jm&?hWH0unD~ zd?Ea;ZiI4HK9nx0&PGtBcd! zb2f}N4(q9NA9;YiF@b67CavPY779!Mem}8ZRC^(@xJJl8?s96|+*$yAdtkb9*=?3X z=cz1_%yo8#5@Rjep+1!5<)+FvJ zS8`p-&>H>BjYdjpLE{GW#Oc8apa14Y?a*jpaxOc70QUp!3)BufkH{3Y*Z#?I&q+J} z`teB|w9UKsNfE?o2^wp2mhn&Eh7`>(fK*f=x~Ny=w#W6g-t|Vm=?|TxR~g+`d3#QG z!G;2g4h}*tuw`V}TQ6^~;<^g@pqs{^u$-KngjY3-Qha>GS*5=Yz87ZHv|KcNP5tLJ z^2F+hZ7JfG*B9dbsJk??Kg>Q*fNrdlF^j-&SXc}A7kTdvnkiOHjR{;^`S?g~OnxJ8aD|$4C7$}o>hTY7MOqp! z*y284;Ns)%hIL+qR2@wJ-0u5BR*%tVM6r|s!xU9G=^B4yZ%8^~%qv>xo8%I(6t zA}9w^scAA%T6S{r=|7^b0*e@ z5S`8`{PRGQ0_f*ERh2wlro@gW#!b*e?md<6Ol7xL&YZcjYMI2 z0S0=)67%!zDq2P}Dc$}K3_KTnmpDmS3wy*2Xb4QNI`rAFS--`1g^?O4EXSPJ3NKBM z7BG7?Lx1l$q3&2(Z;rmVyTdoF%4pu1J?6H@d6~|RJ=8_1DZLC4r zvuy`^H;7j(q~a^Xt))I0^r+zBeZ#`g)Y4jaZ-#o>H2$8CO4P|`@6m0O3*0+6FA^WL zAU#zRtYdJd?vXq6O++;f^SYWfbM_2|Gte@`(6`D6u*)5a%wFWMD=9%q^J-G-c8wY7 z>%`FXL@WK?S%(Isqdd^rhbq$n&opq-i&&zB^h^^>Cknc93_`Gjnj@6FEkjurR<<^R%|XXL8#pKW0OQ@PlWJUrR)f7?u!o1{h_ zm@3I0g1cLN_mCE_UE9>%K=YlhBb-8^_rh}5d+dW_V{ppEBgLM5hWUlalofoVcEm#B zmD$B$4_QrO)OJjCcIR$4KC|LWDBkMhDW#g{*n<{5^5cpzYl-&-f!?3(tTa)pe{Ic@ zbAFiEp`jC^(FC2$6p8EZtt_AkSum06Iw}c=5um!Ni9@)1FuZcVJ(0vo;3z#KdK;=W z6V2PRtvfMaLn}5jb3>*~G_R^uDLD~kk_fQ#8Xp?UJBQ6qvX%gSeSIMhr!S`Ba#KMB z)RigOk@8tlHT=}*MIP0x0d#%T;CMywza9KK3t7aG4ndZ3a03#>5fNFgA_=t{>cEH&GD_LB3WHdjPV6R)JA)PV)QK3Otc>iv`b zd;ZdKc&S5^xF~%10lPHM?paE{mw*6yt~Hd5{lP;##>QKT%TlvUC@?Q~Z4OCj#TCKw zO`9QROB56}D)b(KP@ckiCE$(o{@Q!`Ns)swmyI#YKSBHCE!t=K4q4Pq<!9=SG8TnkrYQKSXfBGR#nRXlQ zi1fZU6b7pd@sV|KYc?5yyeRYhl#8PzEY))$1faO`ku6C1k-USnZI#SwTYTb9SFeb5 zQ`FS-R`iFH*W}@WBM9=hUIfrLS@ODw)hFi?vgC9&$eN+>4cKLRE=m2t#3$pS<$L_b zQS(KURKUASLF`m2TYEEPK+>Cy&;I7dmM|I-^%(LFWp+1#*{VQ&QDrtLnT)l=6a|{f zE}YnJ+Z44Ru;S(J0FI6bkoAZ+E3J+WZ$cYO^) zMql6N!ZqKhX-I`)rG=USgz#|1XD$8vLEnqeD>>>LLDy!=9G#KMj+{7fN5$~_mT|VQ zv>_~!p zqhI;M0%j=onoHe@N)_NBtkb=&tldXqON?bjrDgH*^4c^y(F_Nu0waq`_%RF_bFVkj zqqxYC_#Cl%I&xw_yJ)m#E!EaGCOq7~Lrib^o$8yf_4c4t8l_WBtCmiNVWqU5rV=0u zg&%cgbk;WRp3#NdUIB#6YJaM_e`0J|G7-oma;c+iU4R^;M(r?jVf z61k+hvfWjtm#Ubik{Gey#H;D6!Jlm}FKf=^KxwQzn(H(owujRF{R4%E(m>ElV`FJ* zeehz@gV<{#kRA~(l0aHo2Km@!`DCpn_AH9P9)X9@YcO>jgq%M1kJ}%c%W>6=jF$;< zURh-Re45tsagN-;hAz5@MTQ4kp#3(44@%bA7rU9FM^?e!-?a{Y^5jW)@9JfP#tRAGR{ZXi$fn|IhFcs|OOA3CKpZv3u1Nf{vPxo(_ z12|GbgH_C#dafB|l6A#PfM^b6<{IxdxhV#^$dGY9rune5>|01o?sk5;@Fk@J@xqhw zzt;Qfy@A4XPQqQ7oq2fDaL(k{l!K{KRQTrfzDUMtg)${umxOrS@zNi=M2Is`GYMX` z=^O^aXwyUSfCuW|t8)-guUsk0cb63M%A7WXj3N@c3%CP|mMl zDyD6{y%po(l`>)F4cZrAUs<8uV-4=R?QD z)J(dpC<<2dIIqc3i@tMPF8&u}S!9^t|InqGt=bj>Cc!{2{Wnh|3||4^-(46;;dQN~ zq-z^3y8@3J5nS9aa0+BzTtA-`TwM`lM(vFECDTj5q1LPIC8}(EqoLpA8l_a>=_A0E zl(@dd+g|A$=|JjTfqLtJANiL*xs0IPB|xS|A~c6P+aOx2fB1xS|066a&f5So)iqW^ zyx>8z*(i_~(TB|)!SINP54&Tz7N2-C`$^hiFQ>g2r)?s|OGHy1EmZO7e|8@g5kE$U zqeQSsM#K3iuXx4 zXc&2x3&2TKbux)pg}@qzU>B7;#zBY-!g*oYV$!%o{2HAjuU)MTr}YgBx1+8a5L1;X zd?C0Ur@x#mpZ=UzIl^&KmT1eG>n+e0g?h(Bz(&fEpa^Otl7}E8``sTJU#0}#nOcR~m+%FSf)a69m0vuHD=VW8R zqdZRU6wqeC&>0cUY*C4=Ty0&glj$4u6@vdHTMHdiJ_LSeXWr!Ti5{*DELNR%ciZ zdWBqN>QLLU+@HUPDhLT-Y9vi8%|&GAkUzmQsDgw?pS$y#nMjlqhk`Wd)!v1C*zVWWnbwJDt@`+Cn%{y#tJZBp)CD3$Yvv=|b z1aLJmfetod{D5^-RW{7gmQUflU+io)4Bh=$FI2YCSC|+;J}X^%+geQMXA->_&fGRm z#9o!(sZ98zwiQD2ZIs#p zkr!ZV^Q9PpU_)p=PANPB(W-a`dK0%p3!mKSsW;nZe*o^vbY7?T4?+Sx(WavzKjX4W z3#;0(J6F$_%25@(0xD1_XWe+!Ah^;t>Be7U32jCc)V9eU+?xkoI6E!Zkf4>w42d8n z8>E620lFC3OERKU6TH&!F2oar+|g=t5w`@* z>IoBrl((`ZHc77vPkOO~hPA%C#WR}~LMdD=Z==MG1_FZs?+ZOzIyxn^F*vGYUv3UB zllcCnw{>2gd23` zAHPANIDsrg>d&9sv-pnq#e)~D!Q%b-|Ar*c{c8I8(0kR!8hhuyZYw^LSJkN5aqso5 zeUYX>J5>(Ng+5kSv$z3f|I55_VcuS|KI3q<(I?5>(jl?9@9co`3$>URJEFeD1I^Psg13z z@REG09T{4!2&R1gX7e($?)3VSU?}!5MkknRIK8m8hyjfnDU*?Eg#@_B#1L8miGV|D zv^TJcO2vFt{-V4e;GCc?coL$RgbgRfxl@5XnAR?EU zb^J&0^yJGs*4$0LbZ(v;q(a*|qn8iN$Jb-hH(qHyHdZUGz}P{L8WK3f6V#Sc7UHL` zXz>(8@x%!W%LA^fYVq@6*|PssCynl5AC%~3E?x0=cuw%YrQ zN2}C;!FkpW4Pj~?7lZ%+rIunB^nX2AmTv79-r={vXIt~CC?WtX0Ki&+b_8e2DgO41 z^Gcv%Ja=xlq-kxly!JRWLWZ}6b8pB1IzQ23pCRM(^xxjC#nPnzQRG}`=qW$=K81`z r`l9#P+hYd&pFjKmyT0li|Cpo6aqxf5lntSsZVU~OwraJqMacgEK#?WJ literal 0 HcmV?d00001 diff --git a/static/tabbar/info_active.png b/static/tabbar/info_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a79b406fd11755dfd20759e1de9c3143013ecd GIT binary patch literal 8600 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 THPn9jYJsGxsHM;#XBqK75@U|L literal 0 HcmV?d00001 diff --git a/uniCloud-aliyun/database/ngTools_Dict.schema.json b/uniCloud-aliyun/database/ngTools_Dict.schema.json index db31dca..54614fd 100644 --- a/uniCloud-aliyun/database/ngTools_Dict.schema.json +++ b/uniCloud-aliyun/database/ngTools_Dict.schema.json @@ -1 +1,63 @@ -{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"description":"ID,系统自动生成"},"dictName":{"description":"字典名称","bsonType":"string","title":"字典名称","trim":"both"},"dictCode":{"description":"字典编码","bsonType":"string","title":"字典编码","trim":"both"},"description":{"description":"描述","bsonType":"string","title":"描述","trim":"both"},"delFlag":{"description":"删除状态","bsonType":"int","title":"删除状态","trim":"both"},"createTime":{"description":"创建时间","bsonType":"string","title":"创建时间","trim":"both"},"createBy":{"description":"创建人","bsonType":"string","title":"创建人","trim":"both"},"updateTime":{"description":"更新时间","bsonType":"datetime","title":"更新时间","trim":"both"},"updateBy":{"description":"更新人","bsonType":"string","title":"更新人","trim":"both"}}} \ No newline at end of file +{ + "bsonType": "object", + "required": [], + "permission": { + "read": true, + "create": true, + "update": true, + "delete": true + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "dictName": { + "description": "字典名称", + "bsonType": "string", + "title": "字典名称", + "trim": "both" + }, + "dictCode": { + "description": "字典编码", + "bsonType": "string", + "title": "字典编码", + "trim": "both" + }, + "description": { + "description": "描述", + "bsonType": "string", + "title": "描述", + "trim": "both" + }, + "delFlag": { + "description": "删除状态", + "bsonType": "int", + "title": "删除状态", + "trim": "both" + }, + "createTime": { + "description": "创建时间", + "bsonType": "string", + "title": "创建时间", + "trim": "both" + }, + "createBy": { + "description": "创建人", + "bsonType": "string", + "title": "创建人", + "trim": "both" + }, + "updateTime": { + "description": "更新时间", + "bsonType": "datetime", + "title": "更新时间", + "trim": "both" + }, + "updateBy": { + "description": "更新人", + "bsonType": "string", + "title": "更新人", + "trim": "both" + } + } +} \ No newline at end of file diff --git a/uniCloud-aliyun/database/ngTools_DictItem.schema.json b/uniCloud-aliyun/database/ngTools_DictItem.schema.json index b3e2069..2ad4b1b 100644 --- a/uniCloud-aliyun/database/ngTools_DictItem.schema.json +++ b/uniCloud-aliyun/database/ngTools_DictItem.schema.json @@ -1 +1,82 @@ -{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"description":"ID,系统自动生成"},"dictID":{"description":"字典ID","bsonType":"string","title":"字典ID","trim":"both"},"itemValue":{"description":"字典项值","bsonType":"string","title":"字典项值","trim":"both","length":"1024"},"itemText":{"description":"字典项文本","bsonType":"string","title":"字典项文本","trim":"both"},"itemColor":{"description":"字典项颜色","bsonType":"string","title":"字典项颜色","trim":"both"},"description":{"description":"描述","bsonType":"string","title":"描述","trim":"both"},"sortOrder":{"description":"排序","bsonType":"string","title":"排序","trim":"both"},"status":{"description":"状态","bsonType":"int","title":"状态","trim":"both"},"createTime":{"description":"创建时间","bsonType":"datetime","title":"创建时间","trim":"both"},"createBy":{"description":"创建人","bsonType":"string","title":"创建人","trim":"both"},"updateTime":{"description":"更新时间","bsonType":"datetime","title":"更新时间","trim":"both"},"updateBy":{"description":"更新人","bsonType":"string","title":"更新人","trim":"both"}}} \ No newline at end of file +{ + "bsonType": "object", + "required": [], + "permission": { + "read": true, + "create": true, + "update": true, + "delete": true + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "dictID": { + "description": "字典ID", + "bsonType": "string", + "title": "字典ID", + "trim": "both" + }, + "itemValue": { + "description": "字典项值", + "bsonType": "string", + "title": "字典项值", + "trim": "both", + "length": "1024" + }, + "itemText": { + "description": "字典项文本", + "bsonType": "string", + "title": "字典项文本", + "trim": "both" + }, + "itemColor": { + "description": "字典项颜色", + "bsonType": "string", + "title": "字典项颜色", + "trim": "both" + }, + "description": { + "description": "描述", + "bsonType": "string", + "title": "描述", + "trim": "both" + }, + "sortOrder": { + "description": "排序", + "bsonType": "string", + "title": "排序", + "trim": "both" + }, + "status": { + "description": "状态", + "bsonType": "int", + "title": "状态", + "trim": "both" + }, + "createTime": { + "description": "创建时间", + "bsonType": "datetime", + "title": "创建时间", + "trim": "both" + }, + "createBy": { + "description": "创建人", + "bsonType": "string", + "title": "创建人", + "trim": "both" + }, + "updateTime": { + "description": "更新时间", + "bsonType": "datetime", + "title": "更新时间", + "trim": "both" + }, + "updateBy": { + "description": "更新人", + "bsonType": "string", + "title": "更新人", + "trim": "both" + } + } +} \ No newline at end of file diff --git a/uniCloud-aliyun/database/ngTools_MeterPar.schema.json b/uniCloud-aliyun/database/ngTools_MeterPar.schema.json index faebca6..1b4ea2e 100644 --- a/uniCloud-aliyun/database/ngTools_MeterPar.schema.json +++ b/uniCloud-aliyun/database/ngTools_MeterPar.schema.json @@ -1 +1,351 @@ -{"bsonType":"object","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"description":"ID,系统自动生成"},"createTime":{"description":"创建时间","bsonType":"datetime","title":"创建时间","trim":"both"},"createBy":{"description":"创建人","bsonType":"string","title":"创建人","trim":"both"},"updateTime":{"description":"更新时间","bsonType":"datetime","title":"更新时间","trim":"both"},"updateBy":{"description":"更新人","bsonType":"string","title":"更新人","trim":"both"},"meterID":{"description":"计量点编号","bsonType":"string","title":"计量点编号","trim":"both"},"dFlowCalbz":{"description":"流量计算标准","bsonType":"string","title":"流量计算标准","trim":"both"},"dZcalbz":{"description":"压缩因子计算标准","bsonType":"string","title":"压缩因子计算标准","trim":"both"},"dCbtj":{"description":"计量参比条件","bsonType":"string","title":"计量参比条件","trim":"both"},"dRsCbtj":{"description":"燃烧参比条件","bsonType":"string","title":"燃烧参比条件","trim":"both"},"dPb_M":{"description":"计量参比条件压力","bsonType":"string","title":"计量参比条件压力","trim":"both"},"dTb_M":{"description":"计量参比条件温度","bsonType":"string","title":"计量参比条件温度","trim":"both"},"dPb_E":{"description":"燃烧参比条件压力","bsonType":"string","title":"燃烧参比条件压力","trim":"both"},"dTb_E":{"description":"燃烧参比条件温度","bsonType":"string","title":"燃烧参比条件温度","trim":"both"},"dPatm":{"description":"当地大气压","bsonType":"string","title":"当地大气压","trim":"both"},"dPatmUnit":{"description":"当地大气压单位","bsonType":"string","title":"当地大气压单位","trim":"both"},"dNG_Compents":{"description":"天然气组分","bsonType":"string","title":"天然气组分","trim":"both"},"dMeterType":{"description":"流量计类别","bsonType":"string","title":"流量计类别","trim":"both"},"dCoreType":{"description":"节流装置类型","bsonType":"string","title":"节流装置类型","trim":"both"},"dPtmode":{"description":"取压方式","bsonType":"string","title":"取压方式","trim":"both"},"dPipeType":{"description":"管道类型","bsonType":"string","title":"管道类型","trim":"both"},"dPipeD":{"description":"管道内径","bsonType":"string","title":"管道内径","trim":"both"},"dLenUnit":{"description":"长度单位","bsonType":"string","title":"长度单位","trim":"both"},"dPipeDtemp":{"description":"管道内径参考温度","bsonType":"string","title":"管道内径参考温度","trim":"both"},"dPileDtempU":{"description":"温度单位","bsonType":"string","title":"温度单位","trim":"both"},"dPipeMaterial":{"description":"管道材料","bsonType":"string","title":"管道材料","trim":"both"},"dOrificeD":{"description":"孔板孔径","bsonType":"string","title":"孔板孔径","trim":"both"},"dOrificeUnit":{"description":"长度单位","bsonType":"string","title":"长度单位","trim":"both"},"dOrificeDtemp":{"description":"孔板内径参考温度","bsonType":"string","title":"孔板内径参考温度","trim":"both"},"dOrificeDtempUnit":{"description":"温度单位","bsonType":"string","title":"温度单位","trim":"both"},"dOrificeMaterial":{"description":"孔板材料","bsonType":"string","title":"孔板材料","trim":"both"},"dOrificeSharpness":{"description":"锐利度系数计算方法","bsonType":"string","title":"锐利度系数计算方法","trim":"both"},"dOrificeRk":{"description":"孔板入口圆弧半径","bsonType":"string","title":"孔板入口圆弧半径","trim":"both"},"dOrificeRkLenU":{"description":"长度单位","bsonType":"string","title":"长度单位","trim":"both"},"dPf":{"description":"输入压力","bsonType":"string","title":"输入压力","trim":"both"},"dPfUnit":{"description":"压力单位","bsonType":"string","title":"压力单位","trim":"both"},"dPfType":{"description":"压力类型","bsonType":"string","title":"压力类型","trim":"both"},"dTf":{"description":"输入温度","bsonType":"string","title":"输入温度","trim":"both"},"dTfUnit":{"description":"温度单位","bsonType":"string","title":"温度单位","trim":"both"},"dDp":{"description":"输入差压","bsonType":"string","title":"输入差压","trim":"both"},"dDpUnit":{"description":"压力单位","bsonType":"string","title":"压力单位","trim":"both"},"dVFlowUnit":{"description":"体积流量单位","bsonType":"string","title":"体积流量单位","trim":"both"},"dMFlowUnit":{"description":"质量流量单位","bsonType":"string","title":"质量流量单位","trim":"both"},"dEFlowUnit":{"description":"能量流量单位","bsonType":"string","title":"能量流量单位","trim":"both"},"dCdCalMethod":{"description":"流出系数计算方法","bsonType":"string","title":"流出系数计算方法","trim":"both"},"dMeterFactor":{"description":"仪表系数","bsonType":"string","title":"仪表系数","trim":"both"},"dPulseNum":{"description":"脉冲数","bsonType":"string","title":"脉冲数","trim":"both"},"dVFlowMax":{"description":"最大体积流量","bsonType":"string","title":"最大体积流量","trim":"both"},"dVFlowMin":{"description":"最小体积流量","bsonType":"string","title":"最小体积流量","trim":"both"},"dVFlowCon":{"description":"常用流量","bsonType":"string","title":"常用流量","trim":"both"},"dPfRangeMin":{"description":"压力量程","bsonType":"string","title":"压力量程","trim":"both"},"dPfRangeMax":{"description":"压力量程","bsonType":"string","title":"压力量程","trim":"both"},"dDpRangeMin":{"description":"差压量程","bsonType":"string","title":"差压量程","trim":"both"},"dDpRangeMax":{"description":"差压量程","bsonType":"string","title":"差压量程","trim":"both"},"dTfRangeMin":{"description":"温度计量程","bsonType":"string","title":"温度计量程","trim":"both"},"dTfRangeMax":{"description":"温度计量程","bsonType":"string","title":"温度计量程","trim":"both"},"dVGsc":{"description":"管束车水容积","bsonType":"string","title":"管束车水容积","trim":"both"}}} \ No newline at end of file +{ + "bsonType": "object", + "required": [], + "permission": { + "read": false, + "create": false, + "update": false, + "delete": false + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "createTime": { + "description": "创建时间", + "bsonType": "datetime", + "title": "创建时间", + "trim": "both" + }, + "createBy": { + "description": "创建人", + "bsonType": "string", + "title": "创建人", + "trim": "both" + }, + "updateTime": { + "description": "更新时间", + "bsonType": "datetime", + "title": "更新时间", + "trim": "both" + }, + "updateBy": { + "description": "更新人", + "bsonType": "string", + "title": "更新人", + "trim": "both" + }, + "meterID": { + "description": "计量点编号", + "bsonType": "string", + "title": "计量点编号", + "trim": "both" + }, + "dFlowCalbz": { + "description": "流量计算标准", + "bsonType": "string", + "title": "流量计算标准", + "trim": "both" + }, + "dZcalbz": { + "description": "压缩因子计算标准", + "bsonType": "string", + "title": "压缩因子计算标准", + "trim": "both" + }, + "dCbtj": { + "description": "计量参比条件", + "bsonType": "string", + "title": "计量参比条件", + "trim": "both" + }, + "dRsCbtj": { + "description": "燃烧参比条件", + "bsonType": "string", + "title": "燃烧参比条件", + "trim": "both" + }, + "dPb_M": { + "description": "计量参比条件压力", + "bsonType": "string", + "title": "计量参比条件压力", + "trim": "both" + }, + "dTb_M": { + "description": "计量参比条件温度", + "bsonType": "string", + "title": "计量参比条件温度", + "trim": "both" + }, + "dPb_E": { + "description": "燃烧参比条件压力", + "bsonType": "string", + "title": "燃烧参比条件压力", + "trim": "both" + }, + "dTb_E": { + "description": "燃烧参比条件温度", + "bsonType": "string", + "title": "燃烧参比条件温度", + "trim": "both" + }, + "dPatm": { + "description": "当地大气压", + "bsonType": "string", + "title": "当地大气压", + "trim": "both" + }, + "dPatmUnit": { + "description": "当地大气压单位", + "bsonType": "string", + "title": "当地大气压单位", + "trim": "both" + }, + "dNG_Compents": { + "description": "天然气组分", + "bsonType": "string", + "title": "天然气组分", + "trim": "both" + }, + "dMeterType": { + "description": "流量计类别", + "bsonType": "string", + "title": "流量计类别", + "trim": "both" + }, + "dCoreType": { + "description": "节流装置类型", + "bsonType": "string", + "title": "节流装置类型", + "trim": "both" + }, + "dPtmode": { + "description": "取压方式", + "bsonType": "string", + "title": "取压方式", + "trim": "both" + }, + "dPipeType": { + "description": "管道类型", + "bsonType": "string", + "title": "管道类型", + "trim": "both" + }, + "dPipeD": { + "description": "管道内径", + "bsonType": "string", + "title": "管道内径", + "trim": "both" + }, + "dLenUnit": { + "description": "长度单位", + "bsonType": "string", + "title": "长度单位", + "trim": "both" + }, + "dPipeDtemp": { + "description": "管道内径参考温度", + "bsonType": "string", + "title": "管道内径参考温度", + "trim": "both" + }, + "dPileDtempU": { + "description": "温度单位", + "bsonType": "string", + "title": "温度单位", + "trim": "both" + }, + "dPipeMaterial": { + "description": "管道材料", + "bsonType": "string", + "title": "管道材料", + "trim": "both" + }, + "dOrificeD": { + "description": "孔板孔径", + "bsonType": "string", + "title": "孔板孔径", + "trim": "both" + }, + "dOrificeUnit": { + "description": "长度单位", + "bsonType": "string", + "title": "长度单位", + "trim": "both" + }, + "dOrificeDtemp": { + "description": "孔板内径参考温度", + "bsonType": "string", + "title": "孔板内径参考温度", + "trim": "both" + }, + "dOrificeDtempUnit": { + "description": "温度单位", + "bsonType": "string", + "title": "温度单位", + "trim": "both" + }, + "dOrificeMaterial": { + "description": "孔板材料", + "bsonType": "string", + "title": "孔板材料", + "trim": "both" + }, + "dOrificeSharpness": { + "description": "锐利度系数计算方法", + "bsonType": "string", + "title": "锐利度系数计算方法", + "trim": "both" + }, + "dOrificeRk": { + "description": "孔板入口圆弧半径", + "bsonType": "string", + "title": "孔板入口圆弧半径", + "trim": "both" + }, + "dOrificeRkLenU": { + "description": "长度单位", + "bsonType": "string", + "title": "长度单位", + "trim": "both" + }, + "dPf": { + "description": "输入压力", + "bsonType": "string", + "title": "输入压力", + "trim": "both" + }, + "dPfUnit": { + "description": "压力单位", + "bsonType": "string", + "title": "压力单位", + "trim": "both" + }, + "dPfType": { + "description": "压力类型", + "bsonType": "string", + "title": "压力类型", + "trim": "both" + }, + "dTf": { + "description": "输入温度", + "bsonType": "string", + "title": "输入温度", + "trim": "both" + }, + "dTfUnit": { + "description": "温度单位", + "bsonType": "string", + "title": "温度单位", + "trim": "both" + }, + "dDp": { + "description": "输入差压", + "bsonType": "string", + "title": "输入差压", + "trim": "both" + }, + "dDpUnit": { + "description": "压力单位", + "bsonType": "string", + "title": "压力单位", + "trim": "both" + }, + "dVFlowUnit": { + "description": "体积流量单位", + "bsonType": "string", + "title": "体积流量单位", + "trim": "both" + }, + "dMFlowUnit": { + "description": "质量流量单位", + "bsonType": "string", + "title": "质量流量单位", + "trim": "both" + }, + "dEFlowUnit": { + "description": "能量流量单位", + "bsonType": "string", + "title": "能量流量单位", + "trim": "both" + }, + "dCdCalMethod": { + "description": "流出系数计算方法", + "bsonType": "string", + "title": "流出系数计算方法", + "trim": "both" + }, + "dMeterFactor": { + "description": "仪表系数", + "bsonType": "string", + "title": "仪表系数", + "trim": "both" + }, + "dPulseNum": { + "description": "脉冲数", + "bsonType": "string", + "title": "脉冲数", + "trim": "both" + }, + "dVFlowMax": { + "description": "最大体积流量", + "bsonType": "string", + "title": "最大体积流量", + "trim": "both" + }, + "dVFlowMin": { + "description": "最小体积流量", + "bsonType": "string", + "title": "最小体积流量", + "trim": "both" + }, + "dVFlowCon": { + "description": "常用流量", + "bsonType": "string", + "title": "常用流量", + "trim": "both" + }, + "dPfRangeMin": { + "description": "压力量程", + "bsonType": "string", + "title": "压力量程", + "trim": "both" + }, + "dPfRangeMax": { + "description": "压力量程", + "bsonType": "string", + "title": "压力量程", + "trim": "both" + }, + "dDpRangeMin": { + "description": "差压量程", + "bsonType": "string", + "title": "差压量程", + "trim": "both" + }, + "dDpRangeMax": { + "description": "差压量程", + "bsonType": "string", + "title": "差压量程", + "trim": "both" + }, + "dTfRangeMin": { + "description": "温度计量程", + "bsonType": "string", + "title": "温度计量程", + "trim": "both" + }, + "dTfRangeMax": { + "description": "温度计量程", + "bsonType": "string", + "title": "温度计量程", + "trim": "both" + }, + "dVGsc": { + "description": "管束车水容积", + "bsonType": "string", + "title": "管束车水容积", + "trim": "both" + } + } +} \ No newline at end of file diff --git a/uniCloud-aliyun/database/uni-id-users.schema.json b/uniCloud-aliyun/database/uni-id-users.schema.json index 9c848e1..cae65e9 100644 --- a/uniCloud-aliyun/database/uni-id-users.schema.json +++ b/uniCloud-aliyun/database/uni-id-users.schema.json @@ -1 +1,442 @@ -{"bsonType":"object","required":[],"permission":{"read":true,"create":true,"update":true,"delete":true},"properties":{"_id":{"description":"存储文档 ID(用户 ID),系统自动生成"},"username":{"bsonType":"string","title":"用户名","description":"用户名,不允许重复","trim":"both"},"password":{"bsonType":"password","title":"密码","description":"密码,加密存储","trim":"both"},"password_secret_version":{"bsonType":"int","title":"passwordSecret","description":"密码使用的passwordSecret版本"},"nickname":{"bsonType":"string","title":"昵称","description":"用户昵称","trim":"both"},"gender":{"bsonType":"int","title":"性别","description":"用户性别:0 未知 1 男性 2 女性","defaultValue":0,"enum":[{"text":"未知","value":0},{"text":"男","value":1},{"text":"女","value":2}]},"status":{"bsonType":"int","description":"用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝","title":"用户状态","defaultValue":0,"enum":[{"text":"正常","value":0},{"text":"禁用","value":1},{"text":"审核中","value":2},{"text":"审核拒绝","value":3}]},"mobile":{"bsonType":"string","title":"手机号码","description":"手机号码","pattern":"^\\+?[0-9-]{3,20}$","trim":"both"},"mobile_confirmed":{"bsonType":"int","description":"手机号验证状态:0 未验证 1 已验证","title":"手机号验证状态","defaultValue":0,"enum":[{"text":"未验证","value":0},{"text":"已验证","value":1}]},"email":{"bsonType":"string","format":"email","title":"邮箱","description":"邮箱地址","trim":"both"},"email_confirmed":{"bsonType":"int","description":"邮箱验证状态:0 未验证 1 已验证","title":"邮箱验证状态","defaultValue":0,"enum":[{"text":"未验证","value":0},{"text":"已验证","value":1}]},"avatar":{"bsonType":"string","title":"头像地址","description":"头像地址","trim":"both"},"avatar_file":{"bsonType":"file","title":"头像文件","description":"用file类型方便使用uni-file-picker组件"},"d_ids":{"bsonType":"array","description":"部门ID","title":"部门","foreignKey":"opendb-department._id","enumType":"tree","enum":{"collection":"opendb-department","orderby":"name asc","field":"_id as value, name as text"}},"e_ids":{"bsonType":"array","description":"企业ID","title":"企业"},"role":{"bsonType":"array","title":"角色","description":"用户角色","enum":{"collection":"uni-id-roles","field":"role_id as value, role_name as text"},"foreignKey":"uni-id-roles.role_id","permission":{"write":false}},"wx_unionid":{"bsonType":"string","description":"微信unionid"},"wx_openid":{"bsonType":"object","description":"微信各个平台openid","properties":{"app":{"bsonType":"string","description":"app平台微信openid"},"mp":{"bsonType":"string","description":"微信小程序平台openid"},"h5":{"bsonType":"string","description":"微信公众号平台openid"},"web":{"bsonType":"string","description":"微信网页登录openid"}}},"ali_openid":{"bsonType":"string","description":"支付宝平台openid"},"apple_openid":{"bsonType":"string","description":"苹果登录openid"},"dcloud_appid":{"bsonType":"array","description":"允许登录的客户端的appid列表","foreignKey":"opendb-app-list.appid"},"comment":{"bsonType":"string","title":"备注","description":"备注","trim":"both"},"third_party":{"bsonType":"object","description":"缓存用户在三方平台的token等信息","properties":{"mp_weixin":{"bsonType":"object","description":"微信小程序相关信息","properties":{"session_key":{"bsonType":"string","description":"微信小程序session key"}}},"app_weixin":{"bsonType":"object","description":"app平台微信相关信息","properties":{"access_token":{"bsonType":"string","description":"app平台微信access token"},"access_token_expired":{"bsonType":"string","description":"app平台微信access token过期时间"},"refresh_token":{"bsonType":"string","description":"app平台微信refresh token"}}},"h5_weixin":{"bsonType":"object","description":"微信公众号平台微信相关信息","properties":{"access_token":{"bsonType":"string","description":"微信公众号平台access token"},"access_token_expired":{"bsonType":"string","description":"微信公众号平台access token过期时间"},"refresh_token":{"bsonType":"string","description":"微信公众号平台refresh token"}}},"web_weixin":{"bsonType":"object","description":"web平台微信相关信息","properties":{"access_token":{"bsonType":"string","description":"web平台微信access token"},"access_token_expired":{"bsonType":"string","description":"web平台微信access token过期时间"},"refresh_token":{"bsonType":"string","description":"web平台微信refresh token"}}},"mp_qq":{"bsonType":"object","description":"QQ小程序相关信息","properties":{"session_key":{"bsonType":"string","description":"QQ小程序session key"}}},"app_qq":{"bsonType":"object","description":"app平台QQ相关信息","properties":{"access_token":{"bsonType":"string","description":"app平台QQ access token"},"access_token_expired":{"bsonType":"string","description":"app平台QQ access token过期时间"}}}}},"register_env":{"bsonType":"object","description":"注册环境信息","properties":{"appid":{"bsonType":"string","description":"注册时的应用AppId"},"uni_platform":{"bsonType":"string","description":"注册时的应用平台,app、h5等"},"os_name":{"bsonType":"string","description":"注册时的客户端系统类型,ios、android、windows、mac、linux"},"app_name":{"bsonType":"string","description":"注册时的应用名称"},"app_version":{"bsonType":"string","description":"注册时的应用版本名称"},"app_version_code":{"bsonType":"string","description":"注册时的应用版本号码"},"channel":{"bsonType":"string","description":"注册时的应用渠道或小程序启动场景"},"client_ip":{"bsonType":"string","description":"注册时的客户端ip"}}},"realname_auth":{"bsonType":"object","description":"实名认证信息","required":["type","auth_status"],"properties":{"type":{"bsonType":"int","minimum":0,"maximum":1,"description":"用户类型:0 个人用户 1 企业用户"},"auth_status":{"bsonType":"int","minimum":0,"maximum":3,"description":"认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败"},"auth_date":{"bsonType":"timestamp","description":"认证通过时间"},"real_name":{"bsonType":"string","description":"真实姓名\/企业名称"},"identity":{"bsonType":"string","description":"身份证号码\/营业执照号码"},"id_card_front":{"bsonType":"string","description":"身份证正面照 URL"},"id_card_back":{"bsonType":"string","description":"身份证反面照 URL"},"in_hand":{"bsonType":"string","description":"手持身份证照片 URL"},"license":{"bsonType":"string","description":"营业执照 URL"},"contact_person":{"bsonType":"string","description":"联系人姓名"},"contact_mobile":{"bsonType":"string","description":"联系人手机号码"},"contact_email":{"bsonType":"string","description":"联系人邮箱"}}},"score":{"bsonType":"int","description":"用户积分,积分变更记录可参考:uni-id-scores表定义"},"register_date":{"bsonType":"timestamp","description":"注册时间","forceDefaultValue":{"$env":"now"}},"register_ip":{"bsonType":"string","description":"注册时 IP 地址","forceDefaultValue":{"$env":"clientIP"}},"last_login_date":{"bsonType":"timestamp","description":"最后登录时间"},"last_login_ip":{"bsonType":"string","description":"最后登录时 IP 地址"},"token":{"bsonType":"array","description":"用户token"},"inviter_uid":{"bsonType":"array","description":"用户全部上级邀请者","trim":"both"},"invite_time":{"bsonType":"timestamp","description":"受邀时间"},"my_invite_code":{"bsonType":"string","description":"用户自身邀请码"},"identities":{"bsonType":"array","description":"三方平台身份信息;一个对象代表一个身份,参数支持: provider 身份源, userInfo 三方用户信息, openid 三方openid, unionid 三方unionid, uid 三方uid","permission":{"read":"'READ_UNI_ID_USERS' in auth.permission","write":"'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission"}}},"version":"1.0.3"} \ No newline at end of file +{ + "bsonType": "object", + "required": [], + "permission": { + "read": true, + "create": true, + "update": true, + "delete": true + }, + "properties": { + "_id": { + "description": "存储文档 ID(用户 ID),系统自动生成" + }, + "username": { + "bsonType": "string", + "title": "用户名", + "description": "用户名,不允许重复", + "trim": "both" + }, + "password": { + "bsonType": "password", + "title": "密码", + "description": "密码,加密存储", + "trim": "both" + }, + "password_secret_version": { + "bsonType": "int", + "title": "passwordSecret", + "description": "密码使用的passwordSecret版本" + }, + "nickname": { + "bsonType": "string", + "title": "昵称", + "description": "用户昵称", + "trim": "both" + }, + "gender": { + "bsonType": "int", + "title": "性别", + "description": "用户性别:0 未知 1 男性 2 女性", + "defaultValue": 0, + "enum": [{ + "text": "未知", + "value": 0 + }, { + "text": "男", + "value": 1 + }, { + "text": "女", + "value": 2 + }] + }, + "status": { + "bsonType": "int", + "description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝", + "title": "用户状态", + "defaultValue": 0, + "enum": [{ + "text": "正常", + "value": 0 + }, { + "text": "禁用", + "value": 1 + }, { + "text": "审核中", + "value": 2 + }, { + "text": "审核拒绝", + "value": 3 + }] + }, + "mobile": { + "bsonType": "string", + "title": "手机号码", + "description": "手机号码", + "pattern": "^\\+?[0-9-]{3,20}$", + "trim": "both" + }, + "mobile_confirmed": { + "bsonType": "int", + "description": "手机号验证状态:0 未验证 1 已验证", + "title": "手机号验证状态", + "defaultValue": 0, + "enum": [{ + "text": "未验证", + "value": 0 + }, { + "text": "已验证", + "value": 1 + }] + }, + "email": { + "bsonType": "string", + "format": "email", + "title": "邮箱", + "description": "邮箱地址", + "trim": "both" + }, + "email_confirmed": { + "bsonType": "int", + "description": "邮箱验证状态:0 未验证 1 已验证", + "title": "邮箱验证状态", + "defaultValue": 0, + "enum": [{ + "text": "未验证", + "value": 0 + }, { + "text": "已验证", + "value": 1 + }] + }, + "avatar": { + "bsonType": "string", + "title": "头像地址", + "description": "头像地址", + "trim": "both" + }, + "avatar_file": { + "bsonType": "file", + "title": "头像文件", + "description": "用file类型方便使用uni-file-picker组件" + }, + "d_ids": { + "bsonType": "array", + "description": "部门ID", + "title": "部门", + "foreignKey": "opendb-department._id", + "enumType": "tree", + "enum": { + "collection": "opendb-department", + "orderby": "name asc", + "field": "_id as value, name as text" + } + }, + "e_ids": { + "bsonType": "array", + "description": "企业ID", + "title": "企业" + }, + "role": { + "bsonType": "array", + "title": "角色", + "description": "用户角色", + "enum": { + "collection": "uni-id-roles", + "field": "role_id as value, role_name as text" + }, + "foreignKey": "uni-id-roles.role_id", + "permission": { + "write": false + } + }, + "wx_unionid": { + "bsonType": "string", + "description": "微信unionid" + }, + "wx_openid": { + "bsonType": "object", + "description": "微信各个平台openid", + "properties": { + "app": { + "bsonType": "string", + "description": "app平台微信openid" + }, + "mp": { + "bsonType": "string", + "description": "微信小程序平台openid" + }, + "h5": { + "bsonType": "string", + "description": "微信公众号平台openid" + }, + "web": { + "bsonType": "string", + "description": "微信网页登录openid" + } + } + }, + "ali_openid": { + "bsonType": "string", + "description": "支付宝平台openid" + }, + "apple_openid": { + "bsonType": "string", + "description": "苹果登录openid" + }, + "dcloud_appid": { + "bsonType": "array", + "description": "允许登录的客户端的appid列表", + "foreignKey": "opendb-app-list.appid" + }, + "comment": { + "bsonType": "string", + "title": "备注", + "description": "备注", + "trim": "both" + }, + "third_party": { + "bsonType": "object", + "description": "缓存用户在三方平台的token等信息", + "properties": { + "mp_weixin": { + "bsonType": "object", + "description": "微信小程序相关信息", + "properties": { + "session_key": { + "bsonType": "string", + "description": "微信小程序session key" + } + } + }, + "app_weixin": { + "bsonType": "object", + "description": "app平台微信相关信息", + "properties": { + "access_token": { + "bsonType": "string", + "description": "app平台微信access token" + }, + "access_token_expired": { + "bsonType": "string", + "description": "app平台微信access token过期时间" + }, + "refresh_token": { + "bsonType": "string", + "description": "app平台微信refresh token" + } + } + }, + "h5_weixin": { + "bsonType": "object", + "description": "微信公众号平台微信相关信息", + "properties": { + "access_token": { + "bsonType": "string", + "description": "微信公众号平台access token" + }, + "access_token_expired": { + "bsonType": "string", + "description": "微信公众号平台access token过期时间" + }, + "refresh_token": { + "bsonType": "string", + "description": "微信公众号平台refresh token" + } + } + }, + "web_weixin": { + "bsonType": "object", + "description": "web平台微信相关信息", + "properties": { + "access_token": { + "bsonType": "string", + "description": "web平台微信access token" + }, + "access_token_expired": { + "bsonType": "string", + "description": "web平台微信access token过期时间" + }, + "refresh_token": { + "bsonType": "string", + "description": "web平台微信refresh token" + } + } + }, + "mp_qq": { + "bsonType": "object", + "description": "QQ小程序相关信息", + "properties": { + "session_key": { + "bsonType": "string", + "description": "QQ小程序session key" + } + } + }, + "app_qq": { + "bsonType": "object", + "description": "app平台QQ相关信息", + "properties": { + "access_token": { + "bsonType": "string", + "description": "app平台QQ access token" + }, + "access_token_expired": { + "bsonType": "string", + "description": "app平台QQ access token过期时间" + } + } + } + } + }, + "register_env": { + "bsonType": "object", + "description": "注册环境信息", + "properties": { + "appid": { + "bsonType": "string", + "description": "注册时的应用AppId" + }, + "uni_platform": { + "bsonType": "string", + "description": "注册时的应用平台,app、h5等" + }, + "os_name": { + "bsonType": "string", + "description": "注册时的客户端系统类型,ios、android、windows、mac、linux" + }, + "app_name": { + "bsonType": "string", + "description": "注册时的应用名称" + }, + "app_version": { + "bsonType": "string", + "description": "注册时的应用版本名称" + }, + "app_version_code": { + "bsonType": "string", + "description": "注册时的应用版本号码" + }, + "channel": { + "bsonType": "string", + "description": "注册时的应用渠道或小程序启动场景" + }, + "client_ip": { + "bsonType": "string", + "description": "注册时的客户端ip" + } + } + }, + "realname_auth": { + "bsonType": "object", + "description": "实名认证信息", + "required": ["type", "auth_status"], + "properties": { + "type": { + "bsonType": "int", + "minimum": 0, + "maximum": 1, + "description": "用户类型:0 个人用户 1 企业用户" + }, + "auth_status": { + "bsonType": "int", + "minimum": 0, + "maximum": 3, + "description": "认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败" + }, + "auth_date": { + "bsonType": "timestamp", + "description": "认证通过时间" + }, + "real_name": { + "bsonType": "string", + "description": "真实姓名\/企业名称" + }, + "identity": { + "bsonType": "string", + "description": "身份证号码\/营业执照号码" + }, + "id_card_front": { + "bsonType": "string", + "description": "身份证正面照 URL" + }, + "id_card_back": { + "bsonType": "string", + "description": "身份证反面照 URL" + }, + "in_hand": { + "bsonType": "string", + "description": "手持身份证照片 URL" + }, + "license": { + "bsonType": "string", + "description": "营业执照 URL" + }, + "contact_person": { + "bsonType": "string", + "description": "联系人姓名" + }, + "contact_mobile": { + "bsonType": "string", + "description": "联系人手机号码" + }, + "contact_email": { + "bsonType": "string", + "description": "联系人邮箱" + } + } + }, + "score": { + "bsonType": "int", + "description": "用户积分,积分变更记录可参考:uni-id-scores表定义" + }, + "register_date": { + "bsonType": "timestamp", + "description": "注册时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "register_ip": { + "bsonType": "string", + "description": "注册时 IP 地址", + "forceDefaultValue": { + "$env": "clientIP" + } + }, + "last_login_date": { + "bsonType": "timestamp", + "description": "最后登录时间" + }, + "last_login_ip": { + "bsonType": "string", + "description": "最后登录时 IP 地址" + }, + "token": { + "bsonType": "array", + "description": "用户token" + }, + "inviter_uid": { + "bsonType": "array", + "description": "用户全部上级邀请者", + "trim": "both" + }, + "invite_time": { + "bsonType": "timestamp", + "description": "受邀时间" + }, + "my_invite_code": { + "bsonType": "string", + "description": "用户自身邀请码" + }, + "identities": { + "bsonType": "array", + "description": "三方平台身份信息;一个对象代表一个身份,参数支持: provider 身份源, userInfo 三方用户信息, openid 三方openid, unionid 三方unionid, uid 三方uid", + "permission": { + "read": "'READ_UNI_ID_USERS' in auth.permission", + "write": "'CREATE_UNI_ID_USERS' in auth.permission || 'UPDATE_UNI_ID_USERS' in auth.permission" + } + } + }, + "version": "1.0.3" +} \ No newline at end of file diff --git a/uniCloud-aliyun/database/uni-stat-error-logs.schema.json b/uniCloud-aliyun/database/uni-stat-error-logs.schema.json index 2a22612..61ae1f6 100644 --- a/uniCloud-aliyun/database/uni-stat-error-logs.schema.json +++ b/uniCloud-aliyun/database/uni-stat-error-logs.schema.json @@ -1 +1,102 @@ -{"bsonType":"object","description":"记录上报的应用运行错误日志","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"description":"ID,系统自动生成"},"appid":{"bsonType":"string","description":"用户端上报的应用ID"},"version":{"bsonType":"string","description":"用户端上报的应用版本号"},"platform":{"bsonType":"string","description":"用户端上报的平台code"},"channel":{"bsonType":"string","description":"用户端上报的渠道code\/场景值"},"error_type":{"bsonType":"int","description":"错误类型","defaultValue":0,"enum":[{"text":"未知","value":0},{"text":"表示webview页面js异常(uni-app项目对应vue页面)","value":2},{"text":"表示uni框架js异常(仅uni-app项目)","value":4},{"text":"表示控制页js异常(仅uni-app项目)","value":5},{"text":"表示nvue页面js异常(仅uni-app项目)","value":6}]},"device_id":{"bsonType":"string","description":"客户端携带的设备标识"},"uid":{"bsonType":"string","description":"用户编号, 对应uni-id-users._id"},"os":{"bsonType":"string","description":"客户端操作系统"},"ua":{"bsonType":"string","description":"客户端user-agent信息"},"space_id":{"bsonType":"string","description":"服务空间编号"},"space_provider":{"bsonType":"string","description":"服务空间提供商"},"sdk_version":{"bsonType":"string","description":"小程序基础库版本号"},"platform_version":{"bsonType":"string","description":"微信、支付宝宿主App的版本号"},"error_msg":{"bsonType":"string","description":"错误信息"},"error_hash":{"bsonType":"string","description":"错误hash码"},"page_url":{"bsonType":"string","description":"页面url"},"create_time":{"bsonType":"timestamp","description":"创建时间"}},"version":"0.0.2"} \ No newline at end of file +{ + "bsonType": "object", + "description": "记录上报的应用运行错误日志", + "required": [], + "permission": { + "read": false, + "create": false, + "update": false, + "delete": false + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "appid": { + "bsonType": "string", + "description": "用户端上报的应用ID" + }, + "version": { + "bsonType": "string", + "description": "用户端上报的应用版本号" + }, + "platform": { + "bsonType": "string", + "description": "用户端上报的平台code" + }, + "channel": { + "bsonType": "string", + "description": "用户端上报的渠道code\/场景值" + }, + "error_type": { + "bsonType": "int", + "description": "错误类型", + "defaultValue": 0, + "enum": [{ + "text": "未知", + "value": 0 + }, { + "text": "表示webview页面js异常(uni-app项目对应vue页面)", + "value": 2 + }, { + "text": "表示uni框架js异常(仅uni-app项目)", + "value": 4 + }, { + "text": "表示控制页js异常(仅uni-app项目)", + "value": 5 + }, { + "text": "表示nvue页面js异常(仅uni-app项目)", + "value": 6 + }] + }, + "device_id": { + "bsonType": "string", + "description": "客户端携带的设备标识" + }, + "uid": { + "bsonType": "string", + "description": "用户编号, 对应uni-id-users._id" + }, + "os": { + "bsonType": "string", + "description": "客户端操作系统" + }, + "ua": { + "bsonType": "string", + "description": "客户端user-agent信息" + }, + "space_id": { + "bsonType": "string", + "description": "服务空间编号" + }, + "space_provider": { + "bsonType": "string", + "description": "服务空间提供商" + }, + "sdk_version": { + "bsonType": "string", + "description": "小程序基础库版本号" + }, + "platform_version": { + "bsonType": "string", + "description": "微信、支付宝宿主App的版本号" + }, + "error_msg": { + "bsonType": "string", + "description": "错误信息" + }, + "error_hash": { + "bsonType": "string", + "description": "错误hash码" + }, + "page_url": { + "bsonType": "string", + "description": "页面url" + }, + "create_time": { + "bsonType": "timestamp", + "description": "创建时间" + } + }, + "version": "0.0.2" +} \ No newline at end of file diff --git a/uniCloud-aliyun/database/uni-stat-error-result.schema.json b/uniCloud-aliyun/database/uni-stat-error-result.schema.json index d13451d..ea9a2ea 100644 --- a/uniCloud-aliyun/database/uni-stat-error-result.schema.json +++ b/uniCloud-aliyun/database/uni-stat-error-result.schema.json @@ -1 +1,96 @@ -{"bsonType":"object","description":"存储汇总的错误日志的数据","required":[],"permission":{"read":false,"create":false,"update":false,"delete":false},"properties":{"_id":{"description":"ID,系统自动生成"},"appid":{"bsonType":"string","description":"应用ID"},"platform_id":{"bsonType":"string","description":"应用平台ID,对应uni-stat-app-platforms._id","foreignKey":"uni-stat-app-platforms._id"},"channel_id":{"bsonType":"string","description":"渠道\/场景值ID,对应uni-stat-app-channels._id","foreignKey":"uni-stat-app-channels._id"},"version_id":{"bsonType":"string","description":"应用版本ID,对应opendb-app-versions._id","foreignKey":"opendb-app-versions._id"},"type":{"bsonType":"string","description":"错误类型","enum":[{"text":"前端js错误","value":"js"},{"text":"原生应用崩溃错误","value":"crash"}]},"hash":{"bsonType":"string","description":"错误hash码"},"msg":{"bsonType":"string","description":"错误信息"},"count":{"bsonType":"int","description":"报错次数"},"app_launch_count":{"bsonType":"int","description":"本时间段App启动或从后台切到前台的次数"},"last_time":{"bsonType":"timestamp","description":"最近一次报错事件"},"dimension":{"bsonType":"string","description":"统计范围 day:按天统计,hour:按小时统计","enum":[{"text":"月","value":"month"},{"text":"周","value":"week"},{"text":"天","value":"day"},{"text":"小时","value":"hour"}]},"stat_date":{"bsonType":"int","description":"统计日期,格式yyyymmdd,例:20211201"},"start_time":{"bsonType":"timestamp","description":"开始时间"},"end_time":{"bsonType":"timestamp","description":"结束时间"}},"version":"0.0.2"} \ No newline at end of file +{ + "bsonType": "object", + "description": "存储汇总的错误日志的数据", + "required": [], + "permission": { + "read": false, + "create": false, + "update": false, + "delete": false + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "appid": { + "bsonType": "string", + "description": "应用ID" + }, + "platform_id": { + "bsonType": "string", + "description": "应用平台ID,对应uni-stat-app-platforms._id", + "foreignKey": "uni-stat-app-platforms._id" + }, + "channel_id": { + "bsonType": "string", + "description": "渠道\/场景值ID,对应uni-stat-app-channels._id", + "foreignKey": "uni-stat-app-channels._id" + }, + "version_id": { + "bsonType": "string", + "description": "应用版本ID,对应opendb-app-versions._id", + "foreignKey": "opendb-app-versions._id" + }, + "type": { + "bsonType": "string", + "description": "错误类型", + "enum": [{ + "text": "前端js错误", + "value": "js" + }, { + "text": "原生应用崩溃错误", + "value": "crash" + }] + }, + "hash": { + "bsonType": "string", + "description": "错误hash码" + }, + "msg": { + "bsonType": "string", + "description": "错误信息" + }, + "count": { + "bsonType": "int", + "description": "报错次数" + }, + "app_launch_count": { + "bsonType": "int", + "description": "本时间段App启动或从后台切到前台的次数" + }, + "last_time": { + "bsonType": "timestamp", + "description": "最近一次报错事件" + }, + "dimension": { + "bsonType": "string", + "description": "统计范围 day:按天统计,hour:按小时统计", + "enum": [{ + "text": "月", + "value": "month" + }, { + "text": "周", + "value": "week" + }, { + "text": "天", + "value": "day" + }, { + "text": "小时", + "value": "hour" + }] + }, + "stat_date": { + "bsonType": "int", + "description": "统计日期,格式yyyymmdd,例:20211201" + }, + "start_time": { + "bsonType": "timestamp", + "description": "开始时间" + }, + "end_time": { + "bsonType": "timestamp", + "description": "结束时间" + } + }, + "version": "0.0.2" +} \ No newline at end of file diff --git a/uni_modules/next-tree/components/next-tree/next-tree.vue b/uni_modules/next-tree/components/next-tree/next-tree.vue new file mode 100644 index 0000000..5e47118 --- /dev/null +++ b/uni_modules/next-tree/components/next-tree/next-tree.vue @@ -0,0 +1,1034 @@ + + + + + diff --git a/uni_modules/next-tree/components/next-tree/style.css b/uni_modules/next-tree/components/next-tree/style.css new file mode 100644 index 0000000..76c987f --- /dev/null +++ b/uni_modules/next-tree/components/next-tree/style.css @@ -0,0 +1,269 @@ +@font-face { + font-family: 'iconfont'; + src: url('//at.alicdn.com/t/c/font_4110624_qs48wckazsh.ttf?t=1712479573821') format('truetype'); +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.iconfont { + font-family: iconfont; + font-style: normal; +} +.iconfont-loading { + font-family: iconfont; + display: inline-block; + font-style: normal; + animation: spin 1s linear infinite; +} +.next-tree-mask { + position: fixed; + top: 0rpx; + right: 0rpx; + bottom: 0rpx; + left: 0rpx; + z-index: 997; + background-color: rgba(0, 0, 0, 0.6); + opacity: 0; + transition: all 0.3s ease; + visibility: hidden; +} +.next-tree-mask.show { + visibility: visible; + opacity: 1; +} +.next-tree-cnt { + position: fixed; + top: 0rpx; + right: 0rpx; + bottom: 0rpx; + left: 0rpx; + z-index: 997; + top: 360rpx; + transition: all 0.3s ease; + transform: translateY(100%); +} +.next-tree-cnt.next-tree-cnt-page { + transition: none; +} +.next-tree-cnt.show { + transform: translateY(0); +} +.next-tree-bar { + background-color: #fff; + height: 72rpx; + padding-left: 20rpx; + padding-right: 20rpx; + display: flex; + justify-content: space-between; + align-items: center; + box-sizing: border-box; + border-bottom-width: 1rpx !important; + border-bottom-style: solid; + border-bottom-color: #f5f5f5; + font-size: 32rpx; + color: #757575; + line-height: 1; +} +.next-tree-bar-btns { + display: inline-block; + display: flex; + flex-direction: row; +} +.btn-divid { + display: inline-block; + width: 1px; + margin: 0 10px; + background-color: #ccc; +} +.next-tree-bar-confirm { + color: #f9ae3d; +} +.next-tree-view { + position: absolute; + top: 0rpx; + right: 0rpx; + bottom: 0rpx; + left: 0rpx; + top: 72rpx; + background-color: #fff; + padding-top: 20rpx; + padding-right: 20rpx; + padding-bottom: 20rpx; + padding-left: 20rpx; +} +.next-tree-view-sc { + height: 100%; + overflow: hidden; +} +.next-tree-view-sc .empty { + text-align: center; + color: #757575; + padding: 30rpx; +} +.next-tree-item-block { + +} +.next-tree-item { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 26rpx; + color: #757575; + line-height: 1; + height: 0; + opacity: 0; + transition: 0.2s; + position: relative; + overflow: hidden; +} +.next-tree-item .icon-btn { + font-size: 30rpx; + margin-right: 20rpx; +} +.next-tree-item .left-line { + position: relative; + width: 1rpx; + height: 100%; + box-sizing: border-box; +} +.next-tree-item .left-line::before { + position: absolute; + content: ""; + width: 1rpx; + height: 100%; + background-color: rgba(204,204,204,0.9); + box-sizing: border-box; + + left: -18rpx; +} +.next-tree-item .parent-horizontal-line { + width: 1rpx; + height: 100%; + position: absolute; + top: 0; + left: 0rpx; + box-sizing: border-box; + background-color: rgba(204,204,204,0.9); +} +.next-tree-item .left-line .horizontal-line { + width: 20rpx; + height: 1rpx; + position: absolute; + top: 40rpx; + left: 0rpx; + background-color: rgba(204,204,204,0.9); + box-sizing: border-box; +} + +.next-tree-item.show { + height: 80rpx; + opacity: 1; +} +.next-tree-item.showchild:before { + transform: rotate(90deg); +} +.next-tree-item.border { + border-bottom: 1rpx solid rgba(204,204,204,0.2); +} +.next-tree-item.last:before { + opacity: 0; +} +.next-tree-item.disabled { + color: #ccc!important; +} + +.next-tree-icon { + width: 26rpx; + height: 26rpx; + margin-right: 8rpx; +} +.next-tree-label { + flex: 1; + display: flex; + align-items: center; + height: 100%; + line-height: 1.2; +} +.next-tree-label .label-input { + border: 1rpx solid #f0f0f0; + border-radius: 10rpx; + width: 100%; + padding: 12rpx 18rpx; + margin-right: 30rpx; +} +.next-tree-check { + width: 40px; + height: 40px; + display: flex; + justify-content: center; + align-items: center; +} +.next-tree-check-yes, +.next-tree-check-no { + width: 20px; + height: 20px; + border-top-left-radius: 20%; + border-top-right-radius: 20%; + border-bottom-right-radius: 20%; + border-bottom-left-radius: 20%; + border-top-width: 1rpx; + border-left-width: 1rpx; + border-bottom-width: 1rpx; + border-right-width: 1rpx; + border-style: solid; + border-color: #f9ae3d; + display: flex; + justify-content: center; + align-items: center; + box-sizing: border-box; +} +.next-tree-check-yes-b { + border-top-left-radius: 20%; + border-top-right-radius: 20%; + border-bottom-right-radius: 20%; + border-bottom-left-radius: 20%; + background-color: #f9ae3d; + color: #fff; +} +.next-tree-check-yes-b .icon-text { + font-size: 14px; + font-weight: normal; + font-family: uicon-iconfont; + display: flex; + flex-direction: row; + align-items: center; +} +.next-tree-check .radio { + border-top-left-radius: 50%; + border-top-right-radius: 50%; + border-bottom-right-radius: 50%; + border-bottom-left-radius: 50%; +} +.next-tree-check .radio .next-tree-check-yes-b { + border-top-left-radius: 50%; + border-top-right-radius: 50%; + border-bottom-right-radius: 50%; + border-bottom-left-radius: 50%; +} + +.next-tree-item.disabled .next-tree-check-no { + color: #ccc!important; +} +.next-tree-item.disabled .next-tree-check-yes-b { + background-color: #ccc!important; +} +.hover-c { + opacity: 0.6; +} + +.fixed-bottom-bar { + position: fixed; + bottom: 0rpx; + left: 0rpx; + right: 0rpx; + z-index: 998; +} + + diff --git a/uni_modules/next-tree/package.json b/uni_modules/next-tree/package.json new file mode 100644 index 0000000..6eb8ba2 --- /dev/null +++ b/uni_modules/next-tree/package.json @@ -0,0 +1,84 @@ +{ + "id": "next-tree", + "displayName": "next-tree(超强树选择器、树组件、树插件、无限级联树、单选树、多选树、自定义样式树、树形选择器)", + "version": "1.8.7", + "description": "next-tree 弹窗树形选择器,支持多选,支持大数据, 无限级联,单选,父子级级联,远程/ajax加载,子节点增量/异步渲染,自定义样式定制,具名插槽等;支持h5/小程序/APP,全端通用", + "keywords": [ + "树选择", + "tree", + "弹窗树选择器", + "多选树", + "单选树" +], +"engines": { + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "修改版本说明", + "permissions": "无" + }, + "npmurl": "", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["next-search-more"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "n", + "Edge": "y", + "Firefox": "y", + "Safari": "u" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "u", + "QQ": "y", + "钉钉": "y", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json index d0d7282..6dd37a7 100644 --- a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json +++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/config.json @@ -1,15 +1,17 @@ { - "passwordSecret": "passwordSecret-demo", - "tokenSecret": "tokenSecret-demo", + "passwordSecret": "test-passwordSecret", + "tokenSecret": "test-tokenSecret", "tokenExpiresIn": 7200, "tokenExpiresThreshold": 600, "passwordErrorLimit": 6, "bindTokenToDevice": false, "passwordErrorRetryTime": 3600, - "autoSetInviteCode": false, + "autoSetInviteCode": true, "forceInviteCode": false, + "preferedAppPlatform": "app", + "requestAuthSecret": "testSecret", "app": { - "tokenExpiresIn": 2592000, + "tokenExpiresIn": 2592000, "oauth": { "weixin": { "appid": "wx97a8f7019d175ced", @@ -20,6 +22,18 @@ } } }, + "web": { + "oauth": { + "weixin-h5": { + "appid": "微信浏览器内微信登录,所用的微信公众号appid", + "appsecret": "微信公众号后台获取的appsecret" + }, + "weixin-web": { + "appid": "手机微信扫码登录,所用的微信开放平台(https://open.weixin.qq.com/)-网站应用的appid", + "appsecret": "微信开放平台-网站应用的appsecret" + } + } + }, "mp-weixin": { "oauth": { "weixin": { @@ -31,26 +45,22 @@ "mp-alipay": { "oauth": { "alipay": { - "appid": "alipay appid", - "privateKey": "alipay privateKey" + "appid": "支付宝小程序登录用到的appid、privateKey请参考支付宝小程序的文档进行设置或者获取,https://opendocs.alipay.com/open/291/105971#LDsXr", + "privateKey": "支付宝小程序登录用到的appid、privateKey请参考支付宝小程序的文档进行设置或者获取,https://opendocs.alipay.com/open/291/105971#LDsXr" } } }, "service": { "sms": { "name": "应用名称,对应短信模版的name", - "codeExpiresIn": 180, - "smsKey": "短信密钥key,开通短信服务处可以看到", - "smsSecret": "短信密钥secret,开通短信服务处可以看到", - "scene": { - "bind-mobile-by-sms": { - "templateId": "绑定手机号使用的短信验证码模板", - "codeExpiresIn": 240 - } - } + "codeExpiresIn": 300, + "smsKey": "ec5fba39363dc30af7f21bbb5ac6e857", + "smsSecret": "09abff426ab62fd2e104c3be794b84c7" }, "univerify": { - "appid": "当前应用的appid,使用云函数URL化,此项必须配置" + "appid": "当前应用的appid,使用云函数URL化,此项必须配置", + "apiKey": "apiKey 和 apiSecret 在开发者中心获取,开发者中心:https://dev.dcloud.net.cn/uniLogin/index?type=0,文档:https://ask.dcloud.net.cn/article/37965", + "apiSecret": "" } } -} +} \ No newline at end of file diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/package.json b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/package.json new file mode 100644 index 0000000..2b8132e --- /dev/null +++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-id/package.json @@ -0,0 +1,4 @@ +{ + "name": "uni-id", + "dependencies": {} +} \ No newline at end of file diff --git a/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js index a8b99d0..6fcc68c 100644 --- a/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js +++ b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js @@ -1 +1,576 @@ -"use strict";var e,t=(e=require("crypto"))&&"object"==typeof e&&"default"in e?e.default:e;const n={TOKEN_EXPIRED:"uni-id-token-expired",CHECK_TOKEN_FAILED:"uni-id-check-token-failed",PARAM_REQUIRED:"uni-id-param-required",ACCOUNT_EXISTS:"uni-id-account-exists",ACCOUNT_NOT_EXISTS:"uni-id-account-not-exists",ACCOUNT_CONFLICT:"uni-id-account-conflict",ACCOUNT_BANNED:"uni-id-account-banned",ACCOUNT_AUDITING:"uni-id-account-auditing",ACCOUNT_AUDIT_FAILED:"uni-id-account-audit-failed",ACCOUNT_CLOSED:"uni-id-account-closed"};function i(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}function r(e){if(!e)return;const t=e.match(/^(\d+).(\d+).(\d+)/);return t?t.slice(1,4).map(e=>parseInt(e)):void 0}function o(e,t){const n=r(e),i=r(t);return n?i?function(e,t){const n=Math.max(e.length,t.length);for(let i=0;ir)return 1;if(n=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");t>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:n.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:n.ACCOUNT_BANNED};case 2:throw{errCode:n.ACCOUNT_AUDITING};case 3:throw{errCode:n.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:n.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:n.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:n.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const t=await T.where({role_id:I.in(e)}).get(),n=(i=t.data.reduce((e,t)=>(t.permission&&e.push(...t.permission),e),[]),Array.from(new Set(i)));var i;return this.userPermission={role:e,permission:n},this.userPermission}async _createToken({uid:e,role:t,permission:i}={}){if(!t||!i){const e=await this.getUserPermission();t=e.role,i=e.permission}let r={uid:e,role:t,permission:i};if(this.uniId.interceptorMap.has("customToken")){const n=this.uniId.interceptorMap.get("customToken");if("function"!=typeof n)throw new Error("Invalid custom token file");r=await n({uid:e,role:t,permission:i})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.18"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const t=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*t.iat)return!1}catch(e){if(e.errCode===n.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:t,permission:i}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:t,permission:i});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{uid:i}=t,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:i,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:t}=this.config;let i;try{i=k(e,t)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:n.TOKEN_EXPIRED};throw{errCode:n.CHECK_TOKEN_FAILED}}return i}async checkToken(e,{autoRefresh:t=!0}={}){if(!e)throw{errCode:n.CHECK_TOKEN_FAILED};this.oldToken=e;const i=this._checkToken(e);this.uid=i.uid,this.oldTokenPayload=i;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=i,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:t}=await this.getUserPermission();a.role=e,a.permission=t}if(!r||!t){const e={code:0,errCode:0,...i,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*i.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...i,...a,...d};return delete l.uniIdVersion,l}}var m=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:t=!0}={}){return new E({uniId:this}).checkToken(e,{autoRefresh:t})},createToken:async function({uid:e,role:t,permission:n}={}){return new E({uniId:this}).createToken({uid:e,role:t,permission:n})},refreshToken:async function({token:e}={}){return new E({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:t,config:n}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):t,this._config=n,this.config=this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,t){this.interceptorMap.set(e,t)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(this._config)return this._config;if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let t;switch(["app-plus","app-android","app-ios"].indexOf(this._clientInfo.platform)>-1&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":t="h5";break;case"app":t="app-plus"}const n=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];t&&e[t]&&n.push(e[t]),n.push(e[this._clientInfo.platform]);const i=Object.assign(...n);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!i||!i[e])throw new Error(`Config parameter missing, ${e} is required`)}),i}_getConfig(){return this._getPlatformConfig()}}for(const e in m)x.prototype[e]=m[e];function y(e){const t=new x(e);return new Proxy(t,{get(e,t){if(t in e&&0!==t.indexOf("_")){if("function"==typeof e[t])return(n=e[t],function(){let e;try{e=n.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return i(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==t&&"config"!==t)return e[t]}var n}})}x.prototype.createInstance=y;const O={createInstance:y};module.exports=O; +"use strict"; +var e, t = (e = require("crypto")) && "object" == typeof e && "default" in e ? e.default : e; +const n = { + TOKEN_EXPIRED: "uni-id-token-expired", + CHECK_TOKEN_FAILED: "uni-id-check-token-failed", + PARAM_REQUIRED: "uni-id-param-required", + ACCOUNT_EXISTS: "uni-id-account-exists", + ACCOUNT_NOT_EXISTS: "uni-id-account-not-exists", + ACCOUNT_CONFLICT: "uni-id-account-conflict", + ACCOUNT_BANNED: "uni-id-account-banned", + ACCOUNT_AUDITING: "uni-id-account-auditing", + ACCOUNT_AUDIT_FAILED: "uni-id-account-audit-failed", + ACCOUNT_CLOSED: "uni-id-account-closed" +}; + +function i(e) { + return !!e && ("object" == typeof e || "function" == typeof e) && "function" == typeof e.then +} + +function r(e) { + if (!e) return; + const t = e.match(/^(\d+).(\d+).(\d+)/); + return t ? t.slice(1, 4).map(e => parseInt(e)) : void 0 +} + +function o(e, t) { + const n = r(e), + i = r(t); + return n ? i ? function(e, t) { + const n = Math.max(e.length, t.length); + for (let i = 0; i < n; i++) { + const n = e[i], + r = t[i]; + if (n > r) return 1; + if (n < r) return -1 + } + return 0 + }(n, i) : 1 : i ? -1 : 0 +} +const s = { + "uni-id-token-expired": 30203, + "uni-id-check-token-failed": 30202 +}; + +function c(e) { + const { + errCode: t, + errMsgValue: n + } = e; + e.errMsg = this._t(t, n), t in s && (e.code = s[t]), delete e.errMsgValue +} + +function a(e) { + return "object" === (i = e, Object.prototype.toString.call(i).slice(8, -1).toLowerCase()) && e.errCode && (t = e + .errCode, Object.values(n).includes(t)) && !!e.errCode; + var t, i +} +let u = { + "zh-Hans": { + "uni-id-token-expired": "登录状态失效,token已过期", + "uni-id-check-token-failed": "token校验未通过", + "uni-id-param-required": "缺少参数: {param}", + "uni-id-account-exists": "此账号已注册", + "uni-id-account-not-exists": "此账号未注册", + "uni-id-account-conflict": "用户账号冲突", + "uni-id-account-banned": "从账号已封禁", + "uni-id-account-auditing": "此账号正在审核中", + "uni-id-account-audit-failed": "此账号审核失败", + "uni-id-account-closed": "此账号已注销" + }, + en: { + "uni-id-token-expired": "The login status is invalid, token has expired", + "uni-id-check-token-failed": "Check token failed", + "uni-id-param-required": "Parameter required: {param}", + "uni-id-account-exists": "Account exists", + "uni-id-account-not-exists": "Account does not exists", + "uni-id-account-conflict": "User account conflict", + "uni-id-account-banned": "Account has been banned", + "uni-id-account-auditing": "Account audit in progress", + "uni-id-account-audit-failed": "Account audit failed", + "uni-id-account-closed": "Account has been closed" + } +}; +try { + const e = require.resolve("uni-config-center/uni-id/lang/index.js"); + u = function(e, t) { + const n = Object.keys(e); + n.push(...Object.keys(t)); + const i = {}; + for (let r = 0; r < n.length; r++) { + const o = n[r]; + i[o] = Object.assign({}, e[o], t[o]) + } + return i + }(u, require(e)) +} catch (e) {} +var d = u; + +function l(e) { + return e.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") +} + +function h(e) { + return JSON.parse((t = function(e) { + var t = 4 - (e = e.toString()).length % 4; + if (4 !== t) + for (var n = 0; n < t; ++n) e += "="; + return e.replace(/-/g, "+").replace(/_/g, "/") + }(e), Buffer.from(t, "base64").toString("utf-8"))); + var t +} + +function f(e) { + return l((t = JSON.stringify(e), Buffer.from(t, "utf-8").toString("base64"))); + var t +} + +function p(e, n) { + return l(t.createHmac("sha256", n).update(e).digest("base64")) +} +const k = function(e, t) { + if ("string" != typeof e) throw new Error("Invalid token"); + const n = e.split("."); + if (3 !== n.length) throw new Error("Invalid token"); + const [i, r, o] = n; + if (p(i + "." + r, t) !== o) throw new Error("Invalid token"); + const s = h(i); + if ("HS256" !== s.alg || "JWT" !== s.typ) throw new Error("Invalid token"); + const c = h(r); + if (1e3 * c.exp < Date.now()) { + const e = new Error("Token expired"); + throw e.name = "TokenExpiredError", e + } + return c + }, + g = function(e, t, n = {}) { + const { + expiresIn: i + } = n; + if (!i) throw new Error("expiresIn is required"); + const r = parseInt(Date.now() / 1e3), + o = { + ...e, + iat: r, + exp: r + n.expiresIn + }, + s = f({ + alg: "HS256", + typ: "JWT" + }) + "." + f(o); + return s + "." + p(s, t) + }, + _ = uniCloud.database(), + I = _.command, + C = _.collection("uni-id-users"), + T = _.collection("uni-id-roles"); +class E { + constructor({ + uniId: e + } = {}) { + this.uid = null, this.userRecord = null, this.userPermission = null, this.oldToken = null, this + .oldTokenPayload = null, this.uniId = e, this.config = this.uniId._getConfig(), this.clientInfo = this + .uniId._clientInfo, this.checkConfig() + } + checkConfig() { + const { + tokenExpiresIn: e, + tokenExpiresThreshold: t + } = this.config; + if (t >= e) throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn"); + t > e / 2 && console.warn( + `Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}` + ) + } + get customToken() { + return this.uniId.interceptorMap.get("customToken") + } + isTokenInDb(e) { + return o(e, "1.0.10") >= 0 + } + async getUserRecord() { + if (this.userRecord) return this.userRecord; + const e = await C.doc(this.uid).get(); + if (this.userRecord = e.data[0], !this.userRecord) throw { + errCode: n.ACCOUNT_NOT_EXISTS + }; + switch (this.userRecord.status) { + case void 0: + case 0: + break; + case 1: + throw { + errCode: n.ACCOUNT_BANNED + }; + case 2: + throw { + errCode: n.ACCOUNT_AUDITING + }; + case 3: + throw { + errCode: n.ACCOUNT_AUDIT_FAILED + }; + case 4: + throw { + errCode: n.ACCOUNT_CLOSED + } + } + if (this.oldTokenPayload) { + if (this.isTokenInDb(this.oldTokenPayload.uniIdVersion)) { + if (-1 === (this.userRecord.token || []).indexOf(this.oldToken)) throw { + errCode: n.CHECK_TOKEN_FAILED + } + } + if (this.userRecord.valid_token_date && this.userRecord.valid_token_date > 1e3 * this.oldTokenPayload + .iat) throw { + errCode: n.TOKEN_EXPIRED + } + } + return this.userRecord + } + async updateUserRecord(e) { + await C.doc(this.uid).update(e) + } + async getUserPermission() { + if (this.userPermission) return this.userPermission; + const e = (await this.getUserRecord()).role || []; + if (0 === e.length) return this.userPermission = { + role: [], + permission: [] + }, this.userPermission; + if (e.includes("admin")) return this.userPermission = { + role: e, + permission: [] + }, this.userPermission; + const t = await T.where({ + role_id: I.in(e) + }).get(), + n = (i = t.data.reduce((e, t) => (t.permission && e.push(...t.permission), e), []), Array.from(new Set( + i))); + var i; + return this.userPermission = { + role: e, + permission: n + }, this.userPermission + } + async _createToken({ + uid: e, + role: t, + permission: i + } = {}) { + if (!t || !i) { + const e = await this.getUserPermission(); + t = e.role, i = e.permission + } + let r = { + uid: e, + role: t, + permission: i + }; + if (this.uniId.interceptorMap.has("customToken")) { + const n = this.uniId.interceptorMap.get("customToken"); + if ("function" != typeof n) throw new Error("Invalid custom token file"); + r = await n({ + uid: e, + role: t, + permission: i + }) + } + const o = Date.now(), + { + tokenSecret: s, + tokenExpiresIn: c, + maxTokenLength: a = 10 + } = this.config, + u = g({ + ...r, + uniIdVersion: "1.0.18" + }, s, { + expiresIn: c + }), + d = await this.getUserRecord(), + l = (d.token || []).filter(e => { + try { + const t = this._checkToken(e); + if (d.valid_token_date && d.valid_token_date > 1e3 * t.iat) return !1 + } catch (e) { + if (e.errCode === n.TOKEN_EXPIRED) return !1 + } + return !0 + }); + return l.push(u), l.length > a && l.splice(0, l.length - a), await this.updateUserRecord({ + last_login_ip: this.clientInfo.clientIP, + last_login_date: o, + token: l + }), { + token: u, + tokenExpired: o + 1e3 * c + } + } + async createToken({ + uid: e, + role: t, + permission: i + } = {}) { + if (!e) throw { + errCode: n.PARAM_REQUIRED, + errMsgValue: { + param: "uid" + } + }; + this.uid = e; + const { + token: r, + tokenExpired: o + } = await this._createToken({ + uid: e, + role: t, + permission: i + }); + return { + errCode: 0, + token: r, + tokenExpired: o + } + } + async refreshToken({ + token: e + } = {}) { + if (!e) throw { + errCode: n.PARAM_REQUIRED, + errMsgValue: { + param: "token" + } + }; + this.oldToken = e; + const t = this._checkToken(e); + this.uid = t.uid, this.oldTokenPayload = t; + const { + uid: i + } = t, { + role: r, + permission: o + } = await this.getUserPermission(), { + token: s, + tokenExpired: c + } = await this._createToken({ + uid: i, + role: r, + permission: o + }); + return { + errCode: 0, + token: s, + tokenExpired: c + } + } + _checkToken(e) { + const { + tokenSecret: t + } = this.config; + let i; + try { + i = k(e, t) + } catch (e) { + if ("TokenExpiredError" === e.name) throw { + errCode: n.TOKEN_EXPIRED + }; + throw { + errCode: n.CHECK_TOKEN_FAILED + } + } + return i + } + async checkToken(e, { + autoRefresh: t = !0 + } = {}) { + if (!e) throw { + errCode: n.CHECK_TOKEN_FAILED + }; + this.oldToken = e; + const i = this._checkToken(e); + this.uid = i.uid, this.oldTokenPayload = i; + const { + tokenExpiresThreshold: r + } = this.config, { + uid: o, + role: s, + permission: c + } = i, a = { + role: s, + permission: c + }; + if (!s && !c) { + const { + role: e, + permission: t + } = await this.getUserPermission(); + a.role = e, a.permission = t + } + if (!r || !t) { + const e = { + code: 0, + errCode: 0, + ...i, + ...a + }; + return delete e.uniIdVersion, e + } + const u = Date.now(); + let d = {}; + 1e3 * i.exp - u < 1e3 * r && (d = await this._createToken({ + uid: o + })); + const l = { + code: 0, + errCode: 0, + ...i, + ...a, + ...d + }; + return delete l.uniIdVersion, l + } +} +var m = Object.freeze({ + __proto__: null, + checkToken: async function(e, { + autoRefresh: t = !0 + } = {}) { + return new E({ + uniId: this + }).checkToken(e, { + autoRefresh: t + }) + }, + createToken: async function({ + uid: e, + role: t, + permission: n + } = {}) { + return new E({ + uniId: this + }).createToken({ + uid: e, + role: t, + permission: n + }) + }, + refreshToken: async function({ + token: e + } = {}) { + return new E({ + uniId: this + }).refreshToken({ + token: e + }) + } +}); +const w = require("uni-config-center")({ + pluginId: "uni-id" +}); +class x { + constructor({ + context: e, + clientInfo: t, + config: n + } = {}) { + this._clientInfo = e ? function(e) { + return { + appId: e.APPID, + platform: e.PLATFORM, + locale: e.LOCALE, + clientIP: e.CLIENTIP, + deviceId: e.DEVICEID + } + }(e) : t, this._config = n, this.config = this._getOriginConfig(), this.interceptorMap = new Map, w + .hasFile("custom-token.js") && this.setInterceptor("customToken", require(w.resolve( + "custom-token.js"))); + this._i18n = uniCloud.initI18n({ + locale: this._clientInfo.locale, + fallbackLocale: "zh-Hans", + messages: JSON.parse(JSON.stringify(d)) + }), d[this._i18n.locale] || this._i18n.setLocale("zh-Hans") + } + setInterceptor(e, t) { + this.interceptorMap.set(e, t) + } + _t(...e) { + return this._i18n.t(...e) + } + _parseOriginConfig(e) { + return Array.isArray(e) ? e : e[0] ? Object.values(e) : e + } + _getOriginConfig() { + if (this._config) return this._config; + if (w.hasFile("config.json")) { + let e; + try { + e = w.config() + } catch (e) { + throw new Error("Invalid uni-id config file\n" + e.message) + } + return this._parseOriginConfig(e) + } + try { + return this._parseOriginConfig(require("uni-id/config.json")) + } catch (e) { + throw new Error("Invalid uni-id config file") + } + } + _getAppConfig() { + const e = this._getOriginConfig(); + return Array.isArray(e) ? e.find(e => e.dcloudAppid === this._clientInfo.appId) || e.find(e => e + .isDefaultConfig) : e + } + _getPlatformConfig() { + const e = this._getAppConfig(); + if (!e) throw new Error( + `Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId` + ); + let t; + switch (["app-plus", "app-android", "app-ios"].indexOf(this._clientInfo.platform) > -1 && (this._clientInfo + .platform = "app"), "h5" === this._clientInfo.platform && (this._clientInfo.platform = "web"), this + ._clientInfo.platform) { + case "web": + t = "h5"; + break; + case "app": + t = "app-plus" + } + const n = [{ + tokenExpiresIn: 7200, + tokenExpiresThreshold: 1200, + passwordErrorLimit: 6, + passwordErrorRetryTime: 3600 + }, e]; + t && e[t] && n.push(e[t]), n.push(e[this._clientInfo.platform]); + const i = Object.assign(...n); + return ["tokenSecret", "tokenExpiresIn"].forEach(e => { + if (!i || !i[e]) throw new Error(`Config parameter missing, ${e} is required`) + }), i + } + _getConfig() { + return this._getPlatformConfig() + } +} +for (const e in m) x.prototype[e] = m[e]; + +function y(e) { + const t = new x(e); + return new Proxy(t, { + get(e, t) { + if (t in e && 0 !== t.indexOf("_")) { + if ("function" == typeof e[t]) return (n = e[t], function() { + let e; + try { + e = n.apply(this, arguments) + } catch (e) { + if (a(e)) return c.call(this, e), e; + throw e + } + return i(e) ? e.then(e => (a(e) && c.call(this, e), e), e => { + if (a(e)) return c.call(this, e), e; + throw e + }) : (a(e) && c.call(this, e), e) + }).bind(e); + if ("context" !== t && "config" !== t) return e[t] + } + var n + } + }) +} +x.prototype.createInstance = y; +const O = { + createInstance: y +}; +module.exports = O; \ No newline at end of file diff --git a/uni_modules/uni-id-pages/components/uni-id-pages-fab-login/uni-id-pages-fab-login.vue b/uni_modules/uni-id-pages/components/uni-id-pages-fab-login/uni-id-pages-fab-login.vue index 9688abf..d456953 100644 --- a/uni_modules/uni-id-pages/components/uni-id-pages-fab-login/uni-id-pages-fab-login.vue +++ b/uni_modules/uni-id-pages/components/uni-id-pages-fab-login/uni-id-pages-fab-login.vue @@ -1,568 +1,565 @@ diff --git a/uni_modules/uni-id-pages/config.js b/uni_modules/uni-id-pages/config.js index 618bcf7..f5ab36a 100644 --- a/uni_modules/uni-id-pages/config.js +++ b/uni_modules/uni-id-pages/config.js @@ -39,7 +39,7 @@ export default { appid: { weixin: { // 微信公众号的appid,来源:登录微信公众号(https://mp.weixin.qq.com)-> 设置与开发 -> 基本配置 -> 公众号开发信息 -> AppID - h5: 'xxxxxx', + h5: 'wx9f9b7d747d261686', // 微信开放平台的appid,来源:登录微信开放平台(https://open.weixin.qq.com) -> 管理中心 -> 网站应用 -> 选择对应的应用名称,点击查看 -> AppID web: 'xxxxxx' } diff --git a/uni_modules/uts-openSchema/changelog.md b/uni_modules/uts-openSchema/changelog.md deleted file mode 100644 index cb0bf4d..0000000 --- a/uni_modules/uts-openSchema/changelog.md +++ /dev/null @@ -1,2 +0,0 @@ -## 1.0.0(2024-04-25) -- 更新 在 Android 和 iOS 上打开链接的 UTS API diff --git a/uni_modules/uts-openSchema/package.json b/uni_modules/uts-openSchema/package.json deleted file mode 100644 index 78c3ee3..0000000 --- a/uni_modules/uts-openSchema/package.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "id": "uts-openSchema", - "displayName": "uts-openSchema", - "version": "1.0.0", - "description": "在 Android 和 iOS 上打开链接的 UTS API", - "keywords": [ - "uts-openSchema" -], - "repository": "", - "engines": { - "HBuilderX": "^4.0" - }, - "dcloudext": { - "type": "uts", - "sale": { - "regular": { - "price": "0.00" - }, - "sourcecode": { - "price": "0.00" - } - }, - "contact": { - "qq": "" - }, - "declaration": { - "ads": "无", - "data": "无", - "permissions": "无" - }, - "npmurl": "" - }, - "uni_modules": { - "dependencies": [], - "encrypt": [], - "platforms": { - "cloud": { - "tcb": "y", - "aliyun": "y", - "alipay": "y" - }, - "client": { - "Vue": { - "vue2": "n", - "vue3": "y" - }, - "App": { - "app-android": "y", - "app-ios": "y" - }, - "H5-mobile": { - "Safari": "n", - "Android Browser": "n", - "微信浏览器(Android)": "n", - "QQ浏览器(Android)": "n" - }, - "H5-pc": { - "Chrome": "n", - "IE": "n", - "Edge": "n", - "Firefox": "n", - "Safari": "n" - }, - "小程序": { - "微信": "n", - "阿里": "n", - "百度": "n", - "字节跳动": "n", - "QQ": "n", - "钉钉": "n", - "快手": "n", - "飞书": "n", - "京东": "n" - }, - "快应用": { - "华为": "n", - "联盟": "n" - } - } - } - } -} \ No newline at end of file diff --git a/uni_modules/uts-openSchema/readme.md b/uni_modules/uts-openSchema/readme.md deleted file mode 100644 index 7bda602..0000000 --- a/uni_modules/uts-openSchema/readme.md +++ /dev/null @@ -1,6 +0,0 @@ -# uts-openSchema -### 开发文档 -[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html) -[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html) -[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html) -[Hello UTS](https://gitcode.net/dcloud/hello-uts) \ No newline at end of file diff --git a/uni_modules/uts-openSchema/utssdk/app-android/config.json b/uni_modules/uts-openSchema/utssdk/app-android/config.json deleted file mode 100644 index bf95925..0000000 --- a/uni_modules/uts-openSchema/utssdk/app-android/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "minSdkVersion": "21" -} \ No newline at end of file diff --git a/uni_modules/uts-openSchema/utssdk/app-android/index.uts b/uni_modules/uts-openSchema/utssdk/app-android/index.uts deleted file mode 100644 index 660c99e..0000000 --- a/uni_modules/uts-openSchema/utssdk/app-android/index.uts +++ /dev/null @@ -1,15 +0,0 @@ -import Intent from 'android.content.Intent' -import Uri from 'android.net.Uri' -import { OpenSchema } from '../interface.uts' - -export const openSchema: OpenSchema = function (url: string) { - if (typeof url === 'string' && url.length > 0) { - const context = UTSAndroid.getUniActivity()! - const uri = Uri.parse(url) - const intent = new Intent(Intent.ACTION_VIEW, uri) - intent.setData(uri) - context.startActivity(intent) - } else { - console.error('url param ERROR:', JSON.stringify(url)) - } -} diff --git a/uni_modules/uts-openSchema/utssdk/app-ios/config.json b/uni_modules/uts-openSchema/utssdk/app-ios/config.json deleted file mode 100644 index f272043..0000000 --- a/uni_modules/uts-openSchema/utssdk/app-ios/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "deploymentTarget": "12.0" -} \ No newline at end of file diff --git a/uni_modules/uts-openSchema/utssdk/app-ios/index.uts b/uni_modules/uts-openSchema/utssdk/app-ios/index.uts deleted file mode 100644 index 6483e4f..0000000 --- a/uni_modules/uts-openSchema/utssdk/app-ios/index.uts +++ /dev/null @@ -1,14 +0,0 @@ -import { OpenSchema } from '../interface.uts' - -export const openSchema: OpenSchema = function(url: string): void { - if (typeof url == 'string' && url.length > 0) { - let uri = new URL(string = url) - if (uri != null && UIApplication.shared.canOpenURL(uri!)) { - UIApplication.shared.open(uri!, options = new Map(), completionHandler = null) - }else { - console.error('url param Error: ', url) - } - }else { - console.error('url param Error: ', url) - } -} \ No newline at end of file diff --git a/uni_modules/uts-openSchema/utssdk/interface.uts b/uni_modules/uts-openSchema/utssdk/interface.uts deleted file mode 100644 index e790e61..0000000 --- a/uni_modules/uts-openSchema/utssdk/interface.uts +++ /dev/null @@ -1 +0,0 @@ -export type OpenSchema = (url: string) => void