Compare commits
425 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17b58c7924 | |||
| 4ae5ba1e46 | |||
| d3b85ec361 | |||
| 6234424aa6 | |||
| 2285b3f41e | |||
| 92173c57ec | |||
| 2eb1fbf087 | |||
| 4d92efa48b | |||
| f66b165eb7 | |||
| 5d42062001 | |||
| 234022c80c | |||
| 5ec20fa327 | |||
| 773332f406 | |||
| 46a1339d5c | |||
| ab0a1f2fdd | |||
| 4121fd9ed0 | |||
| 1c04624903 | |||
| 64c906f064 | |||
| 53756f53a7 | |||
| 201dcb9ba5 | |||
| ad36cba92e | |||
| 27dfc7aedb | |||
| c48165cd78 | |||
| 876f49fb25 | |||
| b41b1696fc | |||
| 2bcd3a83e4 | |||
| 9c1db27ebe | |||
| e7effb0881 | |||
| 8146b165f9 | |||
| 55ff6e7a5a | |||
| a29fa0d9c8 | |||
| 0a255f0e51 | |||
| 207bea46ca | |||
| d30e4f0d96 | |||
| d788227ae4 | |||
| 3104ea2b53 | |||
| 0c6ab02e8d | |||
| ccf30c5dca | |||
| 412198358d | |||
| 302006530e | |||
| 7b661965a9 | |||
| 8d8b78c6a1 | |||
| 9b8bab4a92 | |||
| 75834b5cef | |||
| 0e5e3180c9 | |||
| aa9d6dbaf3 | |||
| a4c2ed2463 | |||
| 529c789315 | |||
| 1ef3784e3d | |||
| 07755e81b3 | |||
| 003056192e | |||
| a4d6b581d7 | |||
| 4b51e156bb | |||
| e623d6fd14 | |||
| d707d983fb | |||
| 1a9d58c2b3 | |||
| dfde341070 | |||
| 220b2b87a6 | |||
| 00b0a0e783 | |||
| ed066f8565 | |||
| 2a43fa33ab | |||
| 3c988ca0e5 | |||
| f0ccfb4e21 | |||
| 10708e7f14 | |||
| 791567bf37 | |||
| f28dbce227 | |||
| da8bed9529 | |||
| ee8b660539 | |||
| 7e52b9c382 | |||
| 001e72d27b | |||
| 1e151060f3 | |||
| 6a0d0e064a | |||
| 82c01b18de | |||
| e4b89e56c0 | |||
| 870686032d | |||
| 8c092a622a | |||
| b8a7791d5f | |||
| e9599ba1ab | |||
| b8bb19e6a6 | |||
| 11b33016db | |||
| fc65669e07 | |||
| 7edb8b55c1 | |||
| 5ab84be8c8 | |||
| 7d3c5bfd11 | |||
| 8db92c76bf | |||
| 40c167504b | |||
| 30fbbcafc0 | |||
| 93d9401c4b | |||
| d1297dd13b | |||
| b50fabd890 | |||
| 2e104654bd | |||
| 271c16c1d6 | |||
| ae1f95658d | |||
| ce7d9885cd | |||
| 92c807aa86 | |||
| ec7b52aa92 | |||
| f929b5c6b1 | |||
| 975f9f2e80 | |||
| e756cb190e | |||
| 374b2b9a08 | |||
| a62d908054 | |||
| 2e3b0a4ca1 | |||
| 7ae676782d | |||
| 06e2fae5cc | |||
| ffc5013cae | |||
| 4220ce577c | |||
| 700151510b | |||
| 49933f7a7e | |||
| 95ca6914a9 | |||
| f5e4a5cfe3 | |||
| 0b6c2cda4f | |||
| be9e202802 | |||
| d7e678b6dd | |||
| 8b22f3615b | |||
| e9b55bf694 | |||
| e08ddf7efe | |||
| c51a050256 | |||
| acc995c4a2 | |||
| a7bd4bc838 | |||
| 7e236f7cd0 | |||
| bba1335130 | |||
| 39576c86ba | |||
| 59c4240c93 | |||
| 7033476b19 | |||
| d893c8ac32 | |||
| bb770d8e2e | |||
| f37641a955 | |||
| ec60b88cbf | |||
| e417311b81 | |||
| d7aa4cf021 | |||
| d8631c8d7f | |||
| 6f6712ee1b | |||
| efcd95586d | |||
| 760504a124 | |||
| 0f9bc62039 | |||
| 4d287ff83f | |||
| 32462d2f10 | |||
| 0797f498eb | |||
| c010c488d6 | |||
| dd411a65fc | |||
| 56b02ebf5e | |||
| 3963f1c6e4 | |||
| 6e92fa774a | |||
| 493d09a20c | |||
| 24586162d6 | |||
| f808a803fa | |||
| e1eac27a91 | |||
| ada12c546c | |||
| 842f69c691 | |||
| 60e2c96282 | |||
| 4f71a18a1e | |||
| 3f1b6239ca | |||
| bb83b98a23 | |||
| f00148b708 | |||
| a97bc2cd01 | |||
| e6b3477c71 | |||
| 6b85937b46 | |||
| 8591a3b844 | |||
| 42827f9a52 | |||
| c1ba5c04ec | |||
| 17c295c13e | |||
| 7d494b8757 | |||
| 44d6c283c7 | |||
| e7bece004f | |||
| 26c9227461 | |||
| 8b540b46fb | |||
| 28fac2d8c5 | |||
| 5534776e77 | |||
| cd38bd1b36 | |||
| a1d1c06632 | |||
| a5f0a82211 | |||
| d1c5d22f29 | |||
| e8bff038dd | |||
| 3e2e523e14 | |||
| a5b7bb8d66 | |||
| 73ef110497 | |||
| 2cdbf18750 | |||
| e854c4351d | |||
| 482c50a237 | |||
| 2dbd19e2d0 | |||
| c88f22440d | |||
| 7f208b33f4 | |||
| 3b32ab27bf | |||
| 347b343e8d | |||
| 3b628eac48 | |||
| 903cae5dad | |||
| 2bdb7ccb60 | |||
| cd1c5e0174 | |||
| d4699b5983 | |||
| 7d783b700c | |||
| 6c33d187d7 | |||
| 7eb1b1846d | |||
| 7b18a8a38e | |||
| 597819af99 | |||
| ecd4e0d146 | |||
| ab4cdbb958 | |||
| 6a6c125055 | |||
| a175777f79 | |||
| fd9cc52ff4 | |||
| e90c7a0095 | |||
| 2e1d6e87fb | |||
| b265365ead | |||
| 2ec9af9e67 | |||
| 1347dea770 | |||
| 925056d674 | |||
| 9537013886 | |||
| 8f881a2790 | |||
| 6333a6b003 | |||
| 447433cb2f | |||
| e2e746e6ea | |||
| cdce46984b | |||
| 3d53c6ea3f | |||
| a2a54d9043 | |||
| 4a6a2b86c7 | |||
| 2b4d9d6395 | |||
| fcb9a678b3 | |||
| bdcdb5babb | |||
| d24f4e9464 | |||
| c7ace76090 | |||
| 782bea5832 | |||
| b19e4d06c8 | |||
| 7965d0efdc | |||
| e0f128c0fd | |||
| 1ac36e42b2 | |||
| 565a626cb3 | |||
| bf0a4b55c9 | |||
| 428c9d9519 | |||
| 0ef4b25e0c | |||
| 1808c1932c | |||
| e92ab14999 | |||
| 5fb2133ce0 | |||
| c818730095 | |||
| bd73bf0281 | |||
| 12cdc90dde | |||
| a1078a0489 | |||
| a668fbc56e | |||
| 05ebda213d | |||
| 1262fd17c7 | |||
| 229d22fe43 | |||
| 492c22af1a | |||
| f7a419879c | |||
| e7b8d4961e | |||
| 0619bf15df | |||
| 561a7a053b | |||
| 9785ea8b8b | |||
| a9d2a1831a | |||
| c0c0afda83 | |||
| 5cf471b779 | |||
| 8a533e5f9b | |||
| 360d3ee92e | |||
| 811826046b | |||
| 7ae326df50 | |||
| 333799dd06 | |||
| 23ee97d208 | |||
| 0911e49d8d | |||
| aa61787106 | |||
| a295919070 | |||
| aca31a559b | |||
| feae11dd78 | |||
| f6a6317a13 | |||
| 2d6a7aa1eb | |||
| 42b7ff9e85 | |||
| 19a37715e0 | |||
| 7a230deadc | |||
| a5c7cbc342 | |||
| eec9a49f7a | |||
| ca9665ca72 | |||
| 2149eb30a0 | |||
| 49a16c2516 | |||
| 9ec49b06d5 | |||
| 56852a1229 | |||
| ae5d624624 | |||
| b3c2ffd3fa | |||
| 2109456501 | |||
| e23b6cd3bf | |||
| c754b12c06 | |||
| 4fbac7495a | |||
| c8016a930d | |||
| 180126000a | |||
| 048cac1ef2 | |||
| 9a5b727054 | |||
| 4b34e8d3d2 | |||
| b98663abb9 | |||
| e79f094fce | |||
| b1f09a502a | |||
| 13bfce86ed | |||
| d64bcb682a | |||
| a4b91dcc96 | |||
| 57894c2a42 | |||
| dcefc6b164 | |||
| 8e2c250b1d | |||
| 4e78d137df | |||
| 058bbd8c8e | |||
| 9d0b1c4c14 | |||
| 96713042fe | |||
| 8d794d8c66 | |||
| ba0f9ca038 | |||
| b70853da9e | |||
| d0f1d2b325 | |||
| 5bb8ada426 | |||
| 28363bd87a | |||
| fad8478579 | |||
| fa874f4b1a | |||
| aeb79ec9d3 | |||
| 56bcda1938 | |||
| 582b044b16 | |||
| 70ca63d8b2 | |||
| 7e2d2289de | |||
| 32f151fa49 | |||
| bcca17112a | |||
| 3082449508 | |||
| 70ce199f4f | |||
| 54437b3129 | |||
| ec4ec94f7b | |||
| 85ade8a6c1 | |||
| 18796e8614 | |||
| 5fa098ead8 | |||
| ddf96690de | |||
| de0b14f9b5 | |||
| 6861c1bc04 | |||
| d470f64c1c | |||
| 25a8d5c68e | |||
| 04f5e187c2 | |||
| 0f92a6c813 | |||
| 3575b33cbd | |||
| b9e240a4c4 | |||
| deff52881b | |||
| 1a22651131 | |||
| 058fc901e3 | |||
| 3f8d74e1d2 | |||
| e087fe9e47 | |||
| 7c90052609 | |||
| 9d80ef1932 | |||
| 222e84b2ea | |||
| a513c90e14 | |||
| 854559d510 | |||
| f3d5e18696 | |||
| 695d22bb23 | |||
| fb7195a523 | |||
| 8ea4aceb7a | |||
| a866df68f7 | |||
| 846abad5b0 | |||
| ea52b6aa5c | |||
| 798c3bccda | |||
| f12d8e3168 | |||
|
|
e68b23ec4d | ||
|
|
728f47bc8a | ||
|
|
4ae6ed51ac | ||
|
|
35bd4bd77e | ||
| 9b9d781241 | |||
| 2ad1a6cb04 | |||
|
|
4196bb8d9b | ||
|
|
3367870e58 | ||
|
|
7247ec213c | ||
|
|
38cbe786f4 | ||
|
|
291331e60e | ||
| 60e9ffad31 | |||
| 4e81b91ba2 | |||
|
|
b42d0ee75a | ||
|
|
a29cf1dd56 | ||
| aea223b22c | |||
|
|
54b8d9a951 | ||
|
|
fabc47512f | ||
|
|
d56427aaa2 | ||
| 2b14ad1af1 | |||
| d1a61a7076 | |||
| cd4330fa4f | |||
| 57eea7b056 | |||
| ccd5e1e202 | |||
| eeef884832 | |||
| 3ee6724f18 | |||
| 688f7244e0 | |||
|
|
02b211e57f | ||
|
|
215c22435b | ||
| ad36146166 | |||
| c50f4080a3 | |||
| b237a9a0dc | |||
| 1f18027522 | |||
|
|
6e49502dd7 | ||
| 572e68e43e | |||
|
|
3c39493b3f | ||
|
|
9a37349494 | ||
|
|
c51c5a56fe | ||
| 1677f3a45a | |||
| a9dde19476 | |||
| beae66100e | |||
| 158e2f670d | |||
| e190a5cb89 | |||
| f88e140655 | |||
|
|
a0c240aae0 | ||
| 6fe46f9adb | |||
| 4b3701dce2 | |||
|
|
7ce378928c | ||
|
|
916cd346a4 | ||
| fa4369e9c9 | |||
|
|
ade9757b37 | ||
|
|
93419aeec3 | ||
| 213ad75f97 | |||
| 2ecc87e4fb | |||
| fe7c4012f2 | |||
| 1e738b081f | |||
| 51a709047a | |||
| c603a85c8d | |||
| dd94eb0a17 | |||
| a8132fc553 | |||
| 36096527c6 | |||
| 852bf471f0 | |||
| 402f6fd111 | |||
| f72f2cbf06 | |||
| 4010b3e9db | |||
| e47467f2bb | |||
| 2eba35a3a5 | |||
| 27b273aef7 | |||
| 7536e63892 | |||
| f01b969c08 | |||
| 810f8b070b | |||
|
|
5497c8139f | ||
|
|
187e43ab7b | ||
| a1acb729bc | |||
| c8c97ee75d | |||
| f97c387be8 | |||
| 475435d625 | |||
| 10b3e3245c | |||
| 5b57539732 | |||
| c2faf00855 |
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/node_modules
|
||||
/.fleet
|
||||
/src/dist/bundle.min.js
|
||||
/src/dist/bundle.js
|
||||
/dist
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
aws.xml
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
20
.idea/codeStyles/Project.xml
generated
Normal file
20
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JSCodeStyleSettings version="0">
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
|
||||
</JSCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<TypeScriptCodeStyleSettings version="0">
|
||||
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
|
||||
<option name="SPACES_WITHIN_IMPORTS" value="true" />
|
||||
<option name="SPACES_WITHIN_INTERPOLATION_EXPRESSIONS" value="true" />
|
||||
</TypeScriptCodeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
8
.idea/dictionaries/Liwanyi.xml
generated
Normal file
8
.idea/dictionaries/Liwanyi.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Liwanyi">
|
||||
<words>
|
||||
<w>wuhu</w>
|
||||
<w>zhong</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
66
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
66
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,66 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AliAccessStaticViaInstance" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AliDeprecation" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AliEqualsAvoidNull" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AliMissingOverrideAnnotation" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AliWrapperTypeEquality" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaAvoidUseTimer" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaMethodTooLong" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaPackageNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaStringConcat" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaSwitchStatement" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaThreadPoolCreation" enabled="false" level="BLOCKER" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaThreadShouldSetName" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="false" level="MAJOR" enabled_by_default="false" />
|
||||
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="false" level="CRITICAL" enabled_by_default="false" />
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="Python 3.8 (fstock)" project-jdk-type="Python SDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" filepath="$PROJECT_DIR$/.idea/torncity-zhcn-translate.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/smartfox_info.xml
generated
Normal file
6
.idea/smartfox_info.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SmartFoxProjectConfig">
|
||||
<option name="projectInspectionClosed" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
14
.idea/torncity-zhcn-translate.iml
generated
Normal file
14
.idea/torncity-zhcn-translate.iml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.fleet" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/misc" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludePattern pattern="release.min.user.js" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
14
.vscode/launch.json
vendored
Normal file
14
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
// 使用 IntelliSense 了解相关属性。
|
||||
// 悬停以查看现有属性的描述。
|
||||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "npm run rollup",
|
||||
"name": "rollup",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
1246
CHANGELOG.md
Normal file
1246
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
1
CONTRIBUTING.md
Normal file
1
CONTRIBUTING.md
Normal file
@ -0,0 +1 @@
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 JJins
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
24
README.md
24
README.md
@ -1 +1,23 @@
|
||||
# torncity-zhcn-translate
|
||||
# Wuhu Torn Helper
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
[中文](README_ZHCN.md)
|
||||
|
||||
[CHANGELOG(CN)](CHANGELOG.md)
|
||||
|
||||
A customized auxiliary-enhancement user script designed for a browser-based MMORPG game, featuring a range of convenient
|
||||
functions.
|
||||
|
||||
This script does not include any automation-related code.
|
||||
|
||||
## Build
|
||||
|
||||
npm init
|
||||
npm run rollup
|
||||
|
||||
## Use
|
||||
|
||||
[release.min.user.js](release.min.user.js)
|
||||
|
||||
Please install with Tampermonkey (for PC browser) or TornPDA.
|
||||
|
||||
20
README_ZHCN.md
Normal file
20
README_ZHCN.md
Normal file
@ -0,0 +1,20 @@
|
||||
# 芜湖助手 Torncity 翻译插件
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
[CHANGELOG](CHANGELOG.md)
|
||||
|
||||
一个为浏览器网页MMORPG游戏定制的辅助增强用户脚本,包含了一系列便携功能。
|
||||
|
||||
此脚本不包含自动化相关代码。
|
||||
|
||||
## 编译
|
||||
|
||||
npm init
|
||||
npm run rollup
|
||||
|
||||
## 使用
|
||||
|
||||
[release.min.user.js](https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/README_ZHCN.md)
|
||||
|
||||
请使用 Tampermonkey (浏览器) 或 TornPDA 安装。
|
||||
39
build.mjs
Normal file
39
build.mjs
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 此脚本用于加入userscript meta,
|
||||
* 并生成日期时间与版本号
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { prodConfig } from "./rollup.config.js";
|
||||
|
||||
let date = new Date();
|
||||
let version = process.env.npm_package_version;
|
||||
let formattedDateTime = `${ date.getFullYear() }${ ('0' + (date.getMonth() + 1)).slice(-2) }${ ('0' + date.getDate()).slice(-2) }${ ('0' + date.getHours()).slice(-2) }${ ('0' + date.getMinutes()).slice(-2) }`;
|
||||
let metaData =
|
||||
`// ==UserScript==
|
||||
// @lastmodified ${ formattedDateTime }
|
||||
// @name 芜湖助手
|
||||
// @namespace WOOH
|
||||
// @version ${ version }
|
||||
// @description 托恩,起飞!
|
||||
// @author Woohoo[2687093] Sabrina_Devil[2696209]
|
||||
// @match https://www.torn.com/*
|
||||
// @downloadURL https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js
|
||||
// @grant GM_xmlhttpRequest
|
||||
// @grant unsafeWindow
|
||||
// @connect yata.yt
|
||||
// @connect github.io
|
||||
// @connect gitlab.com
|
||||
// @connect staticfile.org
|
||||
// @connect gitee.com
|
||||
// ==/UserScript==
|
||||
`
|
||||
|
||||
const data = readFileSync('./' + prodConfig.output.file, 'utf8');
|
||||
writeFileSync(
|
||||
'./release.min.user.js',
|
||||
metaData + data.replace('$$WUHU_DEV_VERSION$$', version),
|
||||
'utf8'
|
||||
);
|
||||
// rmSync('./' + prodConfig.output.file);
|
||||
console.log(`版本 ${ version } 构建完成`);
|
||||
6
css-module.d.ts
vendored
Normal file
6
css-module.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
// declare module "*.module.css" {
|
||||
// const css: string;
|
||||
// const classes: { [key: string]: string };
|
||||
// export default classes;
|
||||
// export { css };
|
||||
// }
|
||||
21
custom-injector.js
Normal file
21
custom-injector.js
Normal file
@ -0,0 +1,21 @@
|
||||
export const customInjector = (varName) => {
|
||||
let rt = ((__var) => {
|
||||
const inject = (ob) => {
|
||||
if (document && document.head) {
|
||||
ob?.disconnect();
|
||||
const style = document.createElement('style');
|
||||
style.setAttribute('type', 'text/css');
|
||||
style.innerHTML = __var;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
};
|
||||
if (document && document.head) {
|
||||
inject();
|
||||
} else {
|
||||
new MutationObserver((_, ob) => {
|
||||
inject(ob);
|
||||
}).observe(document.documentElement, { childList: true });
|
||||
}
|
||||
}).toString();
|
||||
return `(${ rt })(${ varName })`;
|
||||
};
|
||||
129
global.d.ts
vendored
Normal file
129
global.d.ts
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
declare interface String {
|
||||
contains(keywords: RegExp | string): boolean;
|
||||
|
||||
/* 翻译 */
|
||||
|
||||
// 时分秒转换
|
||||
replaceHMS(): string;
|
||||
|
||||
// 数词转换 a an some
|
||||
numWordTrans(): string;
|
||||
}
|
||||
|
||||
declare interface Window {
|
||||
$?: JQueryStatic;
|
||||
jQuery?: JQueryStatic;
|
||||
WHPARAMS?: any;
|
||||
hasWHQuickFlyOpt?: boolean;
|
||||
// 插件运行标识
|
||||
WHTRANS?: number;
|
||||
Vue?: Function;
|
||||
/**
|
||||
* 油猴脚本引擎自带
|
||||
*/
|
||||
unsafeWindow?: Window & typeof globalThis;
|
||||
/**
|
||||
* google
|
||||
*/
|
||||
_gaUserPrefs?: unknown;
|
||||
|
||||
GM_xmlhttpRequest(init: GM_RequestParams): void;
|
||||
|
||||
GM_getValue(k: string, def: any): unknown;
|
||||
|
||||
GM_setValue(k: string, v: any): void;
|
||||
|
||||
/**
|
||||
* TORN自带
|
||||
*/
|
||||
ReactDOM?: any;
|
||||
dataLayer?: unknown;
|
||||
|
||||
eval(exc: string): void;
|
||||
|
||||
addRFC(url: URL | string): string;
|
||||
|
||||
getAction(opt: TornGetActionParams): void;
|
||||
|
||||
initializeTooltip(selector: string, elemId: string): void;
|
||||
|
||||
renderMiniProfile(node: Element, props: any): never;
|
||||
|
||||
/**
|
||||
* PDA自带
|
||||
*/
|
||||
PDA_httpGet(url: URL | string): Promise<PDA_Response>;
|
||||
|
||||
PDA_httpPost(url: URL | string, init: any, body: any): Promise<PDA_Response>;
|
||||
|
||||
// TODO 临时测试用
|
||||
// [key: string]: unknown;
|
||||
}
|
||||
|
||||
declare interface GM_RequestParams {
|
||||
method?: string,
|
||||
url?: URL | string,
|
||||
data?: any,
|
||||
headers?: any,
|
||||
onload?: Function,
|
||||
onerror?: Function,
|
||||
ontimeout?: Function,
|
||||
}
|
||||
|
||||
declare interface PDA_Response {
|
||||
responseText: string
|
||||
}
|
||||
|
||||
declare interface Element {
|
||||
innerText?: string;
|
||||
src?: string;
|
||||
}
|
||||
|
||||
declare interface Notification {
|
||||
id?: number;
|
||||
}
|
||||
|
||||
declare interface Array<T> {
|
||||
fest_date_dict?: { [key: string]: { name: string, eff: string } };
|
||||
fest_date_list?: string[];
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
declare interface Navigator {
|
||||
userAgentData?: any;
|
||||
}
|
||||
|
||||
declare interface TornGetActionParams {
|
||||
type: 'post' | 'get',
|
||||
action?: string,
|
||||
data?: {
|
||||
step?: string,
|
||||
id?: number,
|
||||
key?: string,
|
||||
type?: string
|
||||
},
|
||||
success: Function,
|
||||
before?: Function
|
||||
}
|
||||
|
||||
declare module "*.html" {
|
||||
const html: string;
|
||||
export default html;
|
||||
}
|
||||
declare module "*.module.css" {
|
||||
const css: string;
|
||||
// const classes: { [key: string]: string };
|
||||
// export default classes;
|
||||
export default css;
|
||||
// export { css };
|
||||
}
|
||||
|
||||
declare function GM_xmlhttpRequest(init: any): void;
|
||||
|
||||
declare var unsafeWindow: Window & typeof globalThis;
|
||||
declare type Constructor<T = any> = new (...args: any[]) => T;
|
||||
|
||||
declare interface ClassType<T> {
|
||||
new(...args: unknown[]): T
|
||||
}
|
||||
952
misc/Christmas_Town_Helper_2.3.3_mobile.js
Normal file
952
misc/Christmas_Town_Helper_2.3.3_mobile.js
Normal file
File diff suppressed because one or more lines are too long
952
misc/Christmas_Town_Helper_2.3.3_mod.user.js
Normal file
952
misc/Christmas_Town_Helper_2.3.3_mod.user.js
Normal file
File diff suppressed because one or more lines are too long
15
misc/fetch_torn_items.py
Normal file
15
misc/fetch_torn_items.py
Normal file
@ -0,0 +1,15 @@
|
||||
import json
|
||||
import requests
|
||||
|
||||
# URL = "https://jjins.github.io/item_price_raw.json"
|
||||
URL = "https://script.google.com/macros/s/AKfycbyRfg1Cx2Jm3IuCWASUu8czKeP3wm5jKsie4T4bxwZHzXTmPbaw4ybPRA/exec?key=getItems"
|
||||
resArr = requests.get(URL).json()['items']
|
||||
obj = {}
|
||||
for item in resArr:
|
||||
obj[item[0]] = {'name': item[1], 'price': item[2]}
|
||||
|
||||
file = open('item_price_raw.json', 'w')
|
||||
file.write(json.dumps(obj))
|
||||
file.close()
|
||||
|
||||
print('物品价格表已更新')
|
||||
118
misc/fstock.py
Normal file
118
misc/fstock.py
Normal file
@ -0,0 +1,118 @@
|
||||
import json
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import os
|
||||
import requests
|
||||
|
||||
DEST_ARR = ['mex', 'cay', 'can', 'haw', 'uni', 'arg', 'swi', 'jap', 'chi', 'uae', 'sou']
|
||||
DEST_TRANS = {
|
||||
'mex': '墨', 'cay': '开', 'can': '加',
|
||||
'haw': '夏', 'uni': '嘤', 'arg': '阿',
|
||||
'swi': '瑞', 'jap': '日', 'chi': '中', 'uae': '迪', 'sou': '南',
|
||||
}
|
||||
VALUED_ITEM_ARR = [
|
||||
'Dahlia', 'Jaguar Plushie',
|
||||
'Banana Orchid', 'Stingray Plushie',
|
||||
'Crocus', 'Wolverine Plushie',
|
||||
'Orchid', 'Large Suitcase',
|
||||
'Red Fox Plushie', 'Nessie Plushie', 'Heather',
|
||||
'Ceibo Flower', 'Monkey Plushie', 'Tear Gas',
|
||||
'Chamois Plushie', 'Edelweiss',
|
||||
'Cherry Blossom',
|
||||
'Panda Plushie', 'Peony',
|
||||
'Camel Plushie', 'Tribulus Omanense',
|
||||
'Lion Plushie', 'African Violet', 'Xanax',
|
||||
]
|
||||
ITEM_TRANS = {
|
||||
'Dahlia': '花', 'Jaguar Plushie': '偶',
|
||||
'Banana Orchid': '花', 'Stingray Plushie': '偶',
|
||||
'Crocus': '花', 'Wolverine Plushie': '偶',
|
||||
'Orchid': '花', 'Large Suitcase': '大箱',
|
||||
'Red Fox Plushie': '赤狐', 'Nessie Plushie': '水怪', 'Heather': '花',
|
||||
'Ceibo Flower': '花', 'Monkey Plushie': '偶', 'Tear Gas': '催泪弹',
|
||||
'Edelweiss': '花', 'Chamois Plushie': '偶',
|
||||
'Cherry Blossom': '花',
|
||||
'Peony': '花', 'Panda Plushie': '偶',
|
||||
'Tribulus Omanense': '花', 'Camel Plushie': '偶',
|
||||
'African Violet': '花', 'Lion Plushie': '偶', 'Xanax': 'XAN',
|
||||
}
|
||||
HISTORY_FILE = 'stock_hist.json'
|
||||
HISTORY_EXIST = os.path.exists(HISTORY_FILE)
|
||||
UTC_8 = timezone(timedelta(hours=8))
|
||||
|
||||
URL = "https://yata.yt/api/v1/travel/export/"
|
||||
resObj = requests.get(URL).json()["stocks"]
|
||||
|
||||
# 更新时间
|
||||
lastUpdate = 0
|
||||
for dest in DEST_ARR:
|
||||
res_update = resObj[dest]["update"]
|
||||
if lastUpdate < res_update:
|
||||
lastUpdate = res_update
|
||||
lastUpdate = datetime.fromtimestamp(lastUpdate).astimezone(UTC_8)
|
||||
UPDATE_TIME_STR = lastUpdate.strftime('%H:%M:%S')
|
||||
|
||||
# 整理过的对象
|
||||
stockObj = {}
|
||||
for dest in DEST_ARR:
|
||||
arr = []
|
||||
for f_item in resObj[dest]['stocks']:
|
||||
for v_item in VALUED_ITEM_ARR:
|
||||
if f_item['name'] == v_item:
|
||||
arr.append(f_item)
|
||||
stockObj[dest] = arr
|
||||
|
||||
# 移除亏本的xan
|
||||
# 加拿大
|
||||
index = -1
|
||||
for i in range(len(stockObj['can'])):
|
||||
if stockObj['can'][i]['name'] == 'Xanax':
|
||||
index = i
|
||||
if index != -1:
|
||||
del stockObj['can'][index]
|
||||
# 英国
|
||||
index = -1
|
||||
for i in range(len(stockObj['uni'])):
|
||||
if stockObj['uni'][i]['name'] == 'Xanax':
|
||||
index = i
|
||||
if index != -1:
|
||||
del stockObj['uni'][index]
|
||||
# 日本
|
||||
index = -1
|
||||
for i in range(len(stockObj['jap'])):
|
||||
if stockObj['jap'][i]['name'] == 'Xanax':
|
||||
index = i
|
||||
if index != -1:
|
||||
del stockObj['jap'][index]
|
||||
|
||||
# 读取库存历史
|
||||
stockHistObj = {}
|
||||
if HISTORY_EXIST:
|
||||
print('历史文件存在')
|
||||
with open(HISTORY_FILE, 'r') as load_f:
|
||||
stockHistObj = json.load(load_f)
|
||||
else:
|
||||
stockHistObj['json'] = []
|
||||
stockHistObj['json'].append({str(int(datetime.now().timestamp())): stockObj})
|
||||
if len(stockHistObj['json']) > 100:
|
||||
del stockHistObj['json'][0]
|
||||
with open(HISTORY_FILE, 'w') as f:
|
||||
json.dump(stockHistObj, f)
|
||||
hist_arr = stockHistObj['json']
|
||||
|
||||
|
||||
# 用于写入文件的列表
|
||||
seq = ["更新时间: %s\n" % UPDATE_TIME_STR]
|
||||
for dest in DEST_ARR:
|
||||
seq_str = '%s ' % DEST_TRANS[dest]
|
||||
for i in range(len(stockObj[dest])):
|
||||
seq_str += '%s%s' % (ITEM_TRANS[stockObj[dest][i]['name']], stockObj[dest][i]['quantity'])
|
||||
if i != len(stockObj[dest]) - 1:
|
||||
seq_str += ' '
|
||||
seq_str += '\n'
|
||||
seq.append(seq_str)
|
||||
# 写入文件
|
||||
fo = open(file="stock.txt", mode="w", encoding="utf-8")
|
||||
fo.writelines(seq)
|
||||
fo.close()
|
||||
|
||||
print("花偶库存更新完成")
|
||||
4658
misc/item_price_raw.json
Normal file
4658
misc/item_price_raw.json
Normal file
File diff suppressed because it is too large
Load Diff
22
misc/userscript_template.user.js
Normal file
22
misc/userscript_template.user.js
Normal file
@ -0,0 +1,22 @@
|
||||
// ==UserScript==
|
||||
// @name Debug Userscript
|
||||
// @namespace https://github.com/einverne/userscripts
|
||||
// @version 0.1
|
||||
// @description This is a debug script to load userscripts from local file system. NOTICE, you need to turn on Allow access to file URLs to @require local file https://www.tampermonkey.net/documentation.php
|
||||
// @author Ein Verne
|
||||
// @match http*://*
|
||||
// @include http://*
|
||||
// @include https://*
|
||||
// @include *
|
||||
// @grant GM_xmlhttpRequest
|
||||
// @grant GM_addStyle
|
||||
// @grant GM_getResourceText
|
||||
// @require {{file path}}
|
||||
// ==/UserScript==
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
console.log("debug script start here");
|
||||
// Your code here...
|
||||
})();
|
||||
16538
misc/vue.js
Normal file
16538
misc/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
10740
misc/wuhu-torn-helper.js
Normal file
10740
misc/wuhu-torn-helper.js
Normal file
File diff suppressed because it is too large
Load Diff
13205
package-lock.json
generated
Normal file
13205
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
43
package.json
Normal file
43
package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "1.2.4",
|
||||
"description": "芜湖助手",
|
||||
"scripts": {
|
||||
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs",
|
||||
"watch": "cross-env NODE_ENV=development rollup -c -w",
|
||||
"rollup": "cross-env NODE_ENV=development rollup -c"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@element-plus/icons-vue": "^2.1.0",
|
||||
"@rollup/plugin-alias": "^4.0.3",
|
||||
"@rollup/plugin-commonjs": "^24.0.1",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-replace": "^5.0.2",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
"@rollup/plugin-typescript": "^8.5.0",
|
||||
"@types/jquery": "^3.5.14",
|
||||
"@types/node": "^20.6.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"element-plus": "^2.3.10",
|
||||
"just-clone": "^6.2.0",
|
||||
"npm": "^8.19.2",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rollup": "^2.79.0",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string-html": "^1.0.0",
|
||||
"rollup-plugin-styles": "^4.0.0",
|
||||
"rollup-plugin-typescript2": "^0.34.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.8.3",
|
||||
"unplugin-auto-import": "^0.15.2",
|
||||
"unplugin-element-plus": "^0.7.0",
|
||||
"unplugin-icons": "^0.16.1",
|
||||
"unplugin-vue-components": "^0.24.1",
|
||||
"vant": "^4.1.2",
|
||||
"vue": "^3.2.47"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
55
release.min.user.js
Normal file
55
release.min.user.js
Normal file
File diff suppressed because one or more lines are too long
131
rollup.config.js
Normal file
131
rollup.config.js
Normal file
@ -0,0 +1,131 @@
|
||||
// [!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
|
||||
// src/vue/ItemPrice.vue?vue&type=script&lang.ts (35:13)
|
||||
// TODO 官方提供ts插件在vue模版中使用ts语言时报错
|
||||
// import typescript from "@rollup/plugin-typescript";
|
||||
|
||||
// TODO 在rollup watch模式中不更新vue模版ts部分代码
|
||||
import typescript2 from "rollup-plugin-typescript2";
|
||||
import json from "@rollup/plugin-json";
|
||||
import html from "rollup-plugin-string-html";
|
||||
import resolve from "@rollup/plugin-node-resolve";
|
||||
import replace from "@rollup/plugin-replace";
|
||||
import alias from "@rollup/plugin-alias";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import styles from "rollup-plugin-styles";
|
||||
import { customInjector } from "./custom-injector.js";
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import clone from "just-clone";
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
// import { VantResolver } from 'unplugin-vue-components/resolvers';
|
||||
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
|
||||
import IconsResolver from 'unplugin-icons/resolver';
|
||||
import Icons from 'unplugin-icons/vite'
|
||||
import ElementPlus from 'unplugin-element-plus/rollup'
|
||||
|
||||
let node_env = process.env.NODE_ENV;
|
||||
let vuePath = node_env === 'production' ?
|
||||
'vue/dist/vue.runtime.esm-browser.prod.js' :
|
||||
'vue/dist/vue.runtime.esm-browser.js';
|
||||
|
||||
const devConfig = {
|
||||
input: 'src/ts/index.ts',
|
||||
output: {
|
||||
file: 'dist/bundle.js',
|
||||
format: 'iife',
|
||||
name: 'bundle.js',
|
||||
},
|
||||
plugins: [
|
||||
json(),
|
||||
html({
|
||||
include: ["**/*.html"],
|
||||
minifier: {
|
||||
includeAutoGeneratedTags: true,
|
||||
removeAttributeQuotes: false,
|
||||
removeComments: true,
|
||||
removeRedundantAttributes: false,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
sortClassName: true,
|
||||
useShortDoctype: true,
|
||||
collapseWhitespace: true,
|
||||
minifyCSS: true,
|
||||
}
|
||||
}),
|
||||
// 根据环境更改vue源
|
||||
alias({
|
||||
entries: [
|
||||
{ find: 'vue', replacement: vuePath },
|
||||
]
|
||||
}),
|
||||
// 为vue替换环境变量
|
||||
replace({
|
||||
values: {
|
||||
'process.env.NODE_ENV': () => JSON.stringify(node_env),
|
||||
'__VUE_OPTIONS_API__': () => JSON.stringify(false),
|
||||
'__VUE_PROD_DEVTOOLS__': () => JSON.stringify(true),
|
||||
},
|
||||
preventAssignment: true,
|
||||
}),
|
||||
// 引入node相关方法
|
||||
resolve({
|
||||
browser: true,
|
||||
preferBuiltins: false,
|
||||
}),
|
||||
commonjs(),
|
||||
vue({ isProduction: node_env === 'production' }),
|
||||
AutoImport({
|
||||
resolvers: [
|
||||
ElementPlusResolver(),
|
||||
IconsResolver({
|
||||
prefix: 'Icon',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [
|
||||
IconsResolver({
|
||||
enabledCollections: ['ep'],
|
||||
}),
|
||||
ElementPlusResolver()
|
||||
],
|
||||
// resolvers: [VantResolver()],
|
||||
}),
|
||||
Icons(),
|
||||
ElementPlus(),
|
||||
// 自定义注入器注入vue部分css
|
||||
styles({
|
||||
// modules: true,
|
||||
// namedExports: true,
|
||||
exclude: /static\/css\/.+\.css/,
|
||||
mode: [
|
||||
"inject",
|
||||
(varName) => customInjector(varName),
|
||||
],
|
||||
minimize: true
|
||||
}),
|
||||
// 非vue部分css逻辑代码中手动注入
|
||||
styles({
|
||||
include: /static\/css\/.+\.css/,
|
||||
// modules: true,
|
||||
// namedExports: true,
|
||||
mode: [
|
||||
"inject",
|
||||
() => ``,
|
||||
],
|
||||
minimize: true
|
||||
}),
|
||||
typescript2({
|
||||
tsconfig: "./tsconfig.json",
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
const prodConfig = clone(devConfig);
|
||||
prodConfig.plugins.push(terser());
|
||||
prodConfig.output.file = 'dist/bundle.min.js';
|
||||
prodConfig.output.name = 'bundle.min.js';
|
||||
|
||||
export default [devConfig, prodConfig];
|
||||
export { prodConfig };
|
||||
7
src/shims-vue.d.ts
vendored
Normal file
7
src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/* eslint-disable */
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
/* eslint-enable */
|
||||
82
src/static/css/attack_helper.module.css
Normal file
82
src/static/css/attack_helper.module.css
Normal file
@ -0,0 +1,82 @@
|
||||
.wh-move-btn #defender div[class^="modal___"] {
|
||||
display: block;
|
||||
width: 0 !important;
|
||||
left: -169px !important;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.wh-move-btn #defender div[class^="dialog___"] {
|
||||
border: 0;
|
||||
width: 159px;
|
||||
height: 96px;
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
.wh-move-btn #defender div[class^="colored___"] {
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wh-move-btn #defender div[class^="title___"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* 此处限制宽度,否则人物模型图片会溢出遮挡武器栏 */
|
||||
.wh-move-btn #defender div[class^="modelWrap___"] {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wh-move-btn #defender button {
|
||||
width: 100%;
|
||||
margin: 17px 0;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
/* 解决按钮图标负边距被上层元素限制遮挡问题 */
|
||||
.wh-move-btn #defender div[class^="playerWindow___"] {
|
||||
overflow: unset;
|
||||
}
|
||||
|
||||
/* 手机端 */
|
||||
@media screen and (max-width: 600px) {
|
||||
.wh-move-btn #attacker div[class^="playerWindow___"] {
|
||||
overflow: unset;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker div[class^="modelWrap___"] {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker div[class^="modal___"] {
|
||||
display: block;
|
||||
width: 0;
|
||||
top: CSSVAR;
|
||||
left: -80px;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker div[class^="dialog___"] {
|
||||
border: 0;
|
||||
width: 80px;
|
||||
/* torn的规则限制90% */
|
||||
max-width: unset;
|
||||
height: CSSVAR;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker div[class^="colored___"] {
|
||||
display: block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker div[class^="title___"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.wh-move-btn #attacker button {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
height: 63px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
}
|
||||
57
src/static/css/city_finder.module.css
Normal file
57
src/static/css/city_finder.module.css
Normal file
@ -0,0 +1,57 @@
|
||||
.wh-city-finds .leaflet-marker-pane img[src*="torn.com/images/items/"] {
|
||||
display: block !important;
|
||||
box-sizing: border-box;
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
left: -20px !important;
|
||||
top: -20px !important;
|
||||
padding: 10px 0;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
background-color: #d2d2d28c;
|
||||
box-shadow: 0 0 10px 5px #000;
|
||||
z-index: 999 !important;
|
||||
}
|
||||
|
||||
.wh-city-finds .leaflet-marker-pane.leaflet-marker-icon.user-item-pinpoint.leaflet-clickable {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*#wh-city-finder-header{*/
|
||||
/* background-color: #3f51b5;*/
|
||||
/* color: white;*/
|
||||
/* padding: 8px;*/
|
||||
/* font-size: 15px;*/
|
||||
/* border-radius: 4px 4px 0 0;*/
|
||||
/* text-shadow: 0 0 2px black;*/
|
||||
/* background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0);*/
|
||||
/* background-size: 4px;*/
|
||||
/*}*/
|
||||
|
||||
/*#wh-city-finder{*/
|
||||
/* box-shadow: 0 0 3px 0px #696969;*/
|
||||
/* border-radius: 4px;*/
|
||||
/*}*/
|
||||
/*#wh-city-finder-cont{*/
|
||||
/* background: #616161;*/
|
||||
/* padding: 8px;*/
|
||||
/* color: #c7c7c7;*/
|
||||
/* border-radius: 0 0 4px 4px;*/
|
||||
/* font-size: 13px;*/
|
||||
/*}*/
|
||||
/*#wh-city-finder-cont span{*/
|
||||
/* margin:2px 4px 2px 0;*/
|
||||
/* padding:2px;*/
|
||||
/* border-radius:2px;*/
|
||||
/* background:green;*/
|
||||
/* color:white;*/
|
||||
/* display:inline-block;*/
|
||||
/*}*/
|
||||
.wh-city-finder-item {
|
||||
margin: 2px 4px 2px 0;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
background: green;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
}
|
||||
292
src/static/css/common.module.css
Normal file
292
src/static/css/common.module.css
Normal file
@ -0,0 +1,292 @@
|
||||
.wh-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wh-trans-icon {
|
||||
user-select: none;
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
z-index: 100010;
|
||||
border-radius: 4px;
|
||||
max-width: 220px;
|
||||
box-shadow: 0 0 3px 1px #8484848f;
|
||||
}
|
||||
|
||||
div#effectiveness-wrap {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
#wh-trans-icon {
|
||||
top: 0;
|
||||
left: 112px;
|
||||
}
|
||||
|
||||
/* 冰蛙公司效率表 */
|
||||
div#effectiveness-wrap {
|
||||
margin-left: -76px;
|
||||
margin-right: -76px;
|
||||
}
|
||||
}
|
||||
|
||||
#wh-trans-icon select {
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
#wh-trans-icon a {
|
||||
text-decoration: none;
|
||||
color: #006599;
|
||||
background: none;
|
||||
}
|
||||
|
||||
#wh-trans-icon:not(.wh-icon-expanded):hover {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
#wh-trans-icon button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#wh-inittimer {
|
||||
margin-top: 6px;
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
#wh-gSettings div {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#wh-trans-icon .wh-container {
|
||||
margin: 0;
|
||||
padding: 0 16px 16px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#wh-trans-icon-btn {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z"/><path d="M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z"/></svg>') no-repeat center;
|
||||
padding: 16px !important;
|
||||
}
|
||||
|
||||
#wh-trans-icon .wh-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wh-trans-icon.wh-icon-expanded .wh-container {
|
||||
display: block;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.wh-icon-expanded {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
#wh-cash-monitor {
|
||||
margin: 4px 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.wh-icon-expanded #wh-cash-monitor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wh-latest-version {
|
||||
display: inline-block;
|
||||
background-image: url("https://jjins.github.io/t2i/version.png?{{}}");
|
||||
height: 16px;
|
||||
width: 66px;
|
||||
}
|
||||
|
||||
/** 弹出窗口 **/
|
||||
#wh-popup {
|
||||
position: fixed;
|
||||
z-index: 200000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #00000090;
|
||||
/*color: #333;*/
|
||||
}
|
||||
|
||||
div#wh-popup::after {
|
||||
content: '点击空白处关闭';
|
||||
display: block;
|
||||
color: #ffffffdb;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
#wh-popup-container {
|
||||
max-width: 568px;
|
||||
margin: 5em auto 0;
|
||||
/*box-shadow: 0 0 5px 1px #898989;*/
|
||||
}
|
||||
|
||||
#wh-popup-title p {
|
||||
/*padding: 1em 0;*/
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/** 弹出窗口的内容 **/
|
||||
#wh-popup-cont {
|
||||
padding: 1em;
|
||||
max-height: 30em;
|
||||
overflow-y: auto;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
#wh-popup-cont .gSetting > div {
|
||||
display: inline-block;
|
||||
width: 47%;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
/*#wh-popup-cont .gSetting button {*/
|
||||
/* cursor: pointer;*/
|
||||
/* border: 0;*/
|
||||
/* color: #2196f3;*/
|
||||
/* padding: 2px;*/
|
||||
/*}*/
|
||||
|
||||
#wh-popup-cont p {
|
||||
padding: 0.25em 0;
|
||||
}
|
||||
|
||||
#wh-popup-cont a {
|
||||
color: red;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#wh-popup-cont li {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#wh-popup-cont h4 {
|
||||
margin: 0;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
#wh-popup-cont button:not(.torn-btn) {
|
||||
margin: 0 4px 0 0;
|
||||
padding: 5px 8px;
|
||||
border: solid 2px black;
|
||||
color: black;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#wh-popup-cont button[disabled] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#wh-popup-cont input {
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
border: 1px solid #fff0;
|
||||
border-radius: 5px;
|
||||
margin: 1px 2px;
|
||||
}
|
||||
|
||||
#wh-popup-cont input:focus {
|
||||
border-color: blue;
|
||||
}
|
||||
|
||||
#wh-popup-cont table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
#wh-popup-cont td, #wh-popup-cont th {
|
||||
border-collapse: collapse;
|
||||
padding: 4px;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
#wh-popup-cont textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 4em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.wh-display-none {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.wh-gym-stack #gymroot {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#wh-notify {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: calc(50% - 180px);
|
||||
width: 360px;
|
||||
z-index: 9999990;
|
||||
color: #333;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#wh-notify a, #wh-notify button { pointer-events: all; }
|
||||
|
||||
#wh-notify a {
|
||||
color: red;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#wh-notify .wh-notify-item { /*height: 50px;*/
|
||||
background: rgb(239 249 255 / 90%);
|
||||
border-radius: 2px;
|
||||
margin: 0.5em 0 0 0;
|
||||
box-shadow: 0 0 5px 0px #959595;
|
||||
}
|
||||
|
||||
#wh-notify .wh-notify-item:hover {
|
||||
background: rgb(239 249 255 / 98%);
|
||||
}
|
||||
|
||||
#wh-notify .wh-notify-item .wh-notify-bar {
|
||||
height: 2px;
|
||||
background: #2196f3;
|
||||
}
|
||||
|
||||
#wh-notify .wh-notify-item .wh-notify-close {
|
||||
float: right;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M923%20571H130.7c-27.6%200-50-22.4-50-50s22.4-50%2050-50H923c27.6%200%2050%2022.4%2050%2050s-22.4%2050-50%2050z%22%20fill%3D%22%232196f3%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') no-repeat center;
|
||||
background-size: 100%;
|
||||
margin: 6px 6px 0 0;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
#wh-notify .wh-notify-item .wh-notify-msg {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.non-selection {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mt-4 {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/*.el-overlay {*/
|
||||
/* backdrop-filter: blur(20px);*/
|
||||
/*}*/
|
||||
9
src/static/css/depo.module.css
Normal file
9
src/static/css/depo.module.css
Normal file
@ -0,0 +1,9 @@
|
||||
.wh-depo-helper div#funds div.deposit,
|
||||
.wh-depo-helper div#armoury-donate div.cash {
|
||||
position: fixed !important;
|
||||
top: 150px;
|
||||
right: 12px;
|
||||
box-shadow: 0 0 8px 1px #00000091;
|
||||
background: #f2f2f2;
|
||||
z-index: 999999;
|
||||
}
|
||||
57
src/static/css/quick_fly.module.css
Normal file
57
src/static/css/quick_fly.module.css
Normal file
@ -0,0 +1,57 @@
|
||||
#wh-quick-fly-opt {
|
||||
position: fixed;
|
||||
left: 64px;
|
||||
top: 64px;
|
||||
background: #008000db;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 5px 1px #ffffff29;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
width: 220px;
|
||||
z-index: 199999;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt p {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt a {
|
||||
cursor: pointer;
|
||||
border: 1px solid;
|
||||
padding: 4px;
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt select {
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt button {
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
background: #00BCD4;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt.wh-quick-fly-opt-hide * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wh-quick-fly-opt.wh-quick-fly-opt-hide input {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
info {
|
||||
display: block;
|
||||
}
|
||||
23
src/static/css/quick_link.module.css
Normal file
23
src/static/css/quick_link.module.css
Normal file
@ -0,0 +1,23 @@
|
||||
.wh-link-collection-cont a {
|
||||
display: inline-block;
|
||||
border: solid 1px #b3b3b3;
|
||||
border-radius: 4px;
|
||||
margin: 0 5px 2px 0;
|
||||
padding: 4px 8px;
|
||||
text-align: center;
|
||||
background: #efefef;
|
||||
background: linear-gradient(#f1f1f1, #e3e3e3);
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.wh-link-collection-cont span {
|
||||
display: block;
|
||||
/*padding: 0 4px 8px;*/
|
||||
}
|
||||
|
||||
.wh-link-collection-cont .wh-link-collection-img {
|
||||
display: block;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
background-size: 100% auto !important;
|
||||
}
|
||||
67
src/static/css/travel_alarm.module.css
Normal file
67
src/static/css/travel_alarm.module.css
Normal file
@ -0,0 +1,67 @@
|
||||
#wh-trv-alarm {
|
||||
position: absolute;
|
||||
width: 248px;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: #0000001f 0 0 10px 4px;
|
||||
border: solid 1px #aaa;
|
||||
z-index: 100001;
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
#wh-trv-alarm button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#wh-trv-error {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#wh-trv-error p {
|
||||
background: #ffd0d0;
|
||||
color: red;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wh-trv-alarm-title {
|
||||
height: 30px;
|
||||
border-bottom: solid #aaa 1px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
h5#wh-trv-alarm-header {
|
||||
height: 100%;
|
||||
line-height: 30px;
|
||||
padding: 0 12px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wh-trv-alarm-bottom {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#wh-trv-alarm-remaining {
|
||||
float: right;
|
||||
color: red;
|
||||
}
|
||||
|
||||
#wh-trv-alarm-cont {
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
#wh-trv-alarm-cont input[type="number"] {
|
||||
width: 42px;
|
||||
border-bottom: solid 1px #aaa;
|
||||
}
|
||||
|
||||
.wh-trv-alarm-stop-hide {
|
||||
display: none;
|
||||
}
|
||||
3
src/static/css/xunzhaomuzhuang.module.css
Normal file
3
src/static/css/xunzhaomuzhuang.module.css
Normal file
@ -0,0 +1,3 @@
|
||||
body.wh-hide-title .content-title, body.wh-hide-title .info-msg-cont {
|
||||
display: none !important;
|
||||
}
|
||||
5
src/static/html/buyBeer/add_beer_head.html
Normal file
5
src/static/html/buyBeer/add_beer_head.html
Normal file
@ -0,0 +1,5 @@
|
||||
<div>
|
||||
<button class="torn-btn">👉添加啤酒商品</button>
|
||||
<p>如果当前商店没有啤酒这个商品可以提前显示以省去刷新步骤,增加抢酒成功率。</p>
|
||||
<p id="wh-msg"></p>
|
||||
</div>
|
||||
5
src/static/html/buyBeer/notify.html
Normal file
5
src/static/html/buyBeer/notify.html
Normal file
@ -0,0 +1,5 @@
|
||||
<span style="background-color:green;color:white;border-radius:3px;font-size:14px;line-height:21px;padding:2px 4px;">啤酒小助手</span>
|
||||
<br/>提醒您:还有不到 50 秒 NPC 的商品就要刷新了,啤酒血包要抢的可以准备咯。
|
||||
<button id="wh-rd-btn-{{}}">【今日不再提醒】</button><br/>
|
||||
<a href="/shops.php?step=bitsnbobs#clickfromnotify" target="_blank">【啤酒店】</a>
|
||||
<a href="/shops.php?step=pharmacy#clickfromnotify" target="_blank">【血包店】</a>
|
||||
71
src/static/html/buyBeer/shop_beer_static_item.html
Normal file
71
src/static/html/buyBeer/shop_beer_static_item.html
Normal file
@ -0,0 +1,71 @@
|
||||
<div class="acc-title">
|
||||
<span class="item-desc tt-buy">
|
||||
<span class="item Alcohol" itemid="180" loaded="0">
|
||||
<span class="item-plate">
|
||||
<img alt="Bottle of Beer" class="torn-item large"
|
||||
src="/images/items/180/large.png"
|
||||
srcset="/images/items/180/large.png 1x, /images/items/180/large@2x.png 2x, /images/items/180/large@3x.png 3x, /images/items/180/large@4x.png 4x">
|
||||
</span>
|
||||
<span class="item-hover">
|
||||
<button aria-labelledby="Show info: 180-name 180-price 180-stock" class="view-info wai-btn"
|
||||
value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-info wai-btn" value="100"></button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="desc">
|
||||
<input name="shoparea" type="hidden" value="100">
|
||||
<span id="180-name" class="name t-overflow bold">Bottle of Beer</span>
|
||||
<span id="180-price" class="price t-gray-6 tt-modified" data-sell="$5">$10<span
|
||||
class="tt-profit positive"><i class="fas fa-caret-up"></i>$1,636</span></span>
|
||||
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">5,000</span> in
|
||||
stock)</span>
|
||||
</span>
|
||||
<span class="buy-act-wrap">
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
<label class="wai" for="180">Amount
|
||||
of Bottle of Beer</label>
|
||||
<input id="180" autocomplete="new-amount" maxlength="3" name="buyAmount[]" type="text" value="100">
|
||||
<span class="buy-act bold">
|
||||
<button class="wai-support t-blue h" value="100">Buy<br><span class="tt-max-buy">fill
|
||||
max</span></button>
|
||||
<div class="tt-max-buy-overlay"></div>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="torn-divider divider-right"></div>
|
||||
<div class="confirm-wrap" tabindex="0">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
Are you sure you would like to buy
|
||||
</span>
|
||||
<span>
|
||||
<span class="count"></span>
|
||||
x Bottle of Beer for
|
||||
$<span class="total"></span>
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#">
|
||||
Yes
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#">
|
||||
No
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="success-wrap">
|
||||
<span class="success">
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
</span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" value="100"></button>
|
||||
</div>
|
||||
<div class="msg-wrap">
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
5
src/static/html/danger_zone.html
Normal file
5
src/static/html/danger_zone.html
Normal file
@ -0,0 +1,5 @@
|
||||
<p>即将打开危险功能,使用这些功能可能会造成账号封禁。请自行考虑是否使用。</p>
|
||||
<p><label><input type="checkbox" {{}}/> 知道了,开启</label></p>
|
||||
<div>
|
||||
<button class="torn-btn" disabled>保存</button>
|
||||
</div>
|
||||
54
src/static/html/dialog_msg_box.html
Normal file
54
src/static/html/dialog_msg_box.html
Normal file
@ -0,0 +1,54 @@
|
||||
<style>
|
||||
html {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
#chatRoot {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#wh-dialog {
|
||||
position: absolute;
|
||||
/*width: 100%;*/
|
||||
/*height: 100%;*/
|
||||
background: #00000066;
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 290001;
|
||||
}
|
||||
|
||||
#wh-dialog .top-round {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#wh-dialog div.wh-content {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#wh-dialog .border-round {
|
||||
margin: auto;
|
||||
max-width: 400px;
|
||||
position: fixed;
|
||||
top: 100px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#wh-dialog .pin-bottom {
|
||||
text-align: center;
|
||||
padding: 8px 0;
|
||||
}
|
||||
</style>
|
||||
<div class="border-round">
|
||||
<div class="title-black top-round">{{}}</div>
|
||||
<div class="cont-gray bottom-round">
|
||||
<div class="wh-content">{{}}</div>
|
||||
<div class="non-selection pin-bottom">
|
||||
<button class="torn-btn">确定</button>
|
||||
<button class="torn-btn">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
3
src/static/html/loading_img.html
Normal file
3
src/static/html/loading_img.html
Normal file
@ -0,0 +1,3 @@
|
||||
<img alt="LOADING"
|
||||
src="data:image/svg+xml,%3Csvg t='1656084442571' class='icon' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='3924' width='14' height='14'%3E%3Cpath d='M512.032002 237.105181a29.310168 29.310168 0 0 1-29.310168-29.246172V29.310168a29.310168 29.310168 0 0 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 237.105181zM512.032002 1024a29.310168 29.310168 0 0 1-29.310168-29.310168v-178.484845a29.310168 29.310168 0 1 1 58.620336 0v178.548841A29.310168 29.310168 0 0 1 512.032002 1024z m482.657834-482.657834h-178.484845a29.310168 29.310168 0 1 1 0-58.620336h178.548841a29.310168 29.310168 0 1 1 0 58.620336z m-786.830823 0H29.310172a29.310168 29.310168 0 0 1 0-58.620336h178.548841a29.310168 29.310168 0 0 1 0 58.620336z m519.263546-215.090557a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412 41.405412l-126.264108 126.264108a29.182176 29.182176 0 0 1-20.670708 8.575464zM170.741333 882.568839a29.182176 29.182176 0 0 1-20.734704-49.980876l126.264108-126.264108a29.246172 29.246172 0 1 1 41.405412 41.405412L191.412041 874.057371a29.182176 29.182176 0 0 1-20.670708 8.575464z m682.581338 0a29.182176 29.182176 0 0 1-20.670708-8.575464l-126.264108-126.264108a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688zM297.005441 326.251609a29.182176 29.182176 0 0 1-20.670708-8.575464L150.006629 191.412037a29.310168 29.310168 0 1 1 41.405412-41.405412l126.264108 126.264108a29.310168 29.310168 0 0 1-20.734704 49.91688z' p-id='3925'%3E%3C/path%3E%3C/svg%3E"
|
||||
style="width:14px;height:14px;">
|
||||
30
src/static/html/nnb_info.html
Normal file
30
src/static/html/nnb_info.html
Normal file
@ -0,0 +1,30 @@
|
||||
<style>
|
||||
#wh-popup-cont label p {
|
||||
padding: 0 0 0 1em;
|
||||
}
|
||||
|
||||
#wh-popup-cont label span {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<p id="wh-nnb-info-container"></p>
|
||||
<p><b>NNB</b>(<b>N</b>atural <b>N</b>erve <b>B</b>ar)意思是:扣除所有加成后,玩家本身的犯罪条上限,可用于衡量大佬隐藏的犯罪技能等级
|
||||
</p>
|
||||
<p>一般来说,左侧红色的犯罪条(<b>N</b>erve <b>B</b>ar/<b>NB</b>)的上限都是包含加成的,如来自帮派、天赋的加成等。额外的加成不会影响玩家的犯罪技能
|
||||
</p>
|
||||
<p>查看NNB的方法很简单,在Torn主页面的最下方有一栏Perks,NB-Perks=NNB</p>
|
||||
<div>
|
||||
<p>以下是两种计算NNB的方法:</p>
|
||||
<label>
|
||||
<input checked name="wh-nnb-check-select" type="radio" value="bw"/><b> 冰蛙或PDA (推荐)</b>
|
||||
<p>由于需要用到APIKey,因此需要冰蛙或PDA提供</p>
|
||||
<p>当前可以使用的APIKey:<br/>
|
||||
<input readonly value="{{}}">(来自冰蛙)<br/>
|
||||
<input readonly value="{{}}">(来自PDA)</p>
|
||||
</label>
|
||||
<label>
|
||||
<input name="wh-nnb-check-select" type="radio" value="ori"/><b> 普通方法</b>
|
||||
<p>该方法不需要APIKey,但是仅限在主页面(海外或飞行状态不可用)的时候</p>
|
||||
</label>
|
||||
</div>
|
||||
<button>计算</button>
|
||||
5
src/static/html/notify.html
Normal file
5
src/static/html/notify.html
Normal file
@ -0,0 +1,5 @@
|
||||
<div class="wh-notify-bar"></div>
|
||||
<div class="wh-notify-cont">
|
||||
<div class="wh-notify-close"></div>
|
||||
<div class="wh-notify-msg"><p>{{}}</p></div>
|
||||
</div>
|
||||
7
src/static/html/popup.html
Normal file
7
src/static/html/popup.html
Normal file
@ -0,0 +1,7 @@
|
||||
<style>html {
|
||||
overflow: hidden !important;
|
||||
}</style>
|
||||
<div class="border-round" id="wh-popup-container">
|
||||
<div class="title-black top-round" id="wh-popup-title"><p>{{}}</p></div>
|
||||
<div class="scroll-area scrollbar-transparent cont-gray bottom-round" id="wh-popup-cont">{{}}</div>
|
||||
</div>
|
||||
19
src/static/html/price_watcher.html
Normal file
19
src/static/html/price_watcher.html
Normal file
@ -0,0 +1,19 @@
|
||||
<style>
|
||||
#wh-popup-cont input {
|
||||
width: 12em;
|
||||
}
|
||||
|
||||
#wh-popup-cont input[type="number"] {
|
||||
width: 8em;
|
||||
}
|
||||
</style>
|
||||
<p>输入需要监视的价格,低于该价格发出通知,-1为关闭</p>
|
||||
<p>注:需要APIKey,当前可用APIKey为<br/>
|
||||
<input readonly value="{{}}">(来自冰蛙)<br/>
|
||||
<input readonly value="{{}}">(来自PDA)
|
||||
</p>
|
||||
<p><b>PT</b><label> $ <input type="number" value="{{}}"/></label></p>
|
||||
<p><b>XAN</b><label> $ <input type="number" value="{{}}"/></label></p>
|
||||
<p>
|
||||
<button>确定</button>
|
||||
</p>
|
||||
55
src/static/html/quick_crimes.html
Normal file
55
src/static/html/quick_crimes.html
Normal file
@ -0,0 +1,55 @@
|
||||
<div class="wh-translate">
|
||||
<div class="title-black" style="border-radius: 5px 5px 0 0;"><span>常用犯罪</span></div>
|
||||
<div class="cont-gray" style="padding: 6px 0;border-radius: 0 0 5px 5px;">
|
||||
<!--18-1-->
|
||||
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="18">
|
||||
<input name="crime" type="hidden" value="hackbank">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
|
||||
type="submit" value="18-1"/>
|
||||
</form>
|
||||
<!--15-3-->
|
||||
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="15">
|
||||
<input name="crime" type="hidden" value="napcop">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #e91e63;border-radius: 5px;color: white;"
|
||||
type="submit" value="15-3(慎)"/>
|
||||
</form>
|
||||
<!--仓库-->
|
||||
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="11">
|
||||
<input name="crime" type="hidden" value="warehouse">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
|
||||
type="submit" value="烧仓库"/>
|
||||
</form>
|
||||
<!--7-2-->
|
||||
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="7">
|
||||
<input name="crime" type="hidden" value="thoroughrobbery">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #2196f3;border-radius: 5px;color: white;"
|
||||
type="submit" value="7-2(仅过渡用)"/>
|
||||
</form>
|
||||
<!--偷夹克-->
|
||||
<form action="crimes.php?step=docrime4" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="4">
|
||||
<input name="crime" type="hidden" value="jacket">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
|
||||
type="submit" value="偷夹克"/>
|
||||
</form>
|
||||
<!--卖碟3-1-->
|
||||
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="3">
|
||||
<input name="crime" type="hidden" value="cdrock">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
|
||||
type="submit" value="卖碟"/>
|
||||
</form>
|
||||
<!--捡钱-->
|
||||
<form action="crimes.php?step=docrime2" method="post" style="display: inline-block;margin: 0 5px">
|
||||
<input name="nervetake" type="hidden" value="2">
|
||||
<input name="crime" type="hidden" value="searchtrainstation">
|
||||
<input style="-webkit-appearance:none;padding: 4px;background: #009688;border-radius: 5px;color: white;"
|
||||
type="submit" value="捡钱"/>
|
||||
</form>
|
||||
</div>
|
||||
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
|
||||
</div>
|
||||
29
src/static/html/quick_fly.html
Normal file
29
src/static/html/quick_fly.html
Normal file
@ -0,0 +1,29 @@
|
||||
<input type="button" value=" - "/>
|
||||
<p>主要用途:出院秒飞</p>
|
||||
<p>点起飞,页面加载完成后会马上飞走</p>
|
||||
<br/>
|
||||
<div>
|
||||
<label>目的地:<select>
|
||||
<option selected>墨西哥</option>
|
||||
<option>开曼</option>
|
||||
<option>加拿大</option>
|
||||
<option>夏威夷</option>
|
||||
<option>嘤国</option>
|
||||
<option>阿根廷</option>
|
||||
<option>瑞士 (解毒)</option>
|
||||
<option>立本</option>
|
||||
<option>祖国</option>
|
||||
<option>阿联酋 (UAE)</option>
|
||||
<option>南非</option>
|
||||
</select></label>
|
||||
<label>飞机:<select>
|
||||
<option>普通飞机 - 不推荐</option>
|
||||
<option selected>PI小飞机</option>
|
||||
<option>私人飞机 - WLT股票</option>
|
||||
<option>商务飞机 - 机票或内衣店</option>
|
||||
</select></label>
|
||||
<p><a>查看花偶库存</a></p>
|
||||
<p>注:需要验证时无法起飞</p>
|
||||
<info></info>
|
||||
<button>起飞</button>
|
||||
</div>
|
||||
23
src/static/html/rw_rider.html
Normal file
23
src/static/html/rw_rider.html
Normal file
@ -0,0 +1,23 @@
|
||||
<div class="m-top10">
|
||||
<h4 class="left" id="skip-to-content">RW 雷达</h4>
|
||||
<div class="clear"></div>
|
||||
<hr class="page-head-delimiter">
|
||||
</div>
|
||||
|
||||
<div class="content m-top10">
|
||||
<a href="/profiles.php?XID=2687093" target="_blank">woohoo</a>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>123</th>
|
||||
<th>456</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>789</td>
|
||||
<td>012</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
2
src/static/html/stock_img.html
Normal file
2
src/static/html/stock_img.html
Normal file
@ -0,0 +1,2 @@
|
||||
<img alt="stock.png" src="https://jjins.github.io/t2i/stock.png?{{}}"
|
||||
style="max-width:100%;display:block;margin:0 auto;"/>
|
||||
18
src/static/html/travel_alarm.html
Normal file
18
src/static/html/travel_alarm.html
Normal file
@ -0,0 +1,18 @@
|
||||
<div id="wh-trv-error"><p><b>❌ 没有权限</b><br/>点击网页内任意位置以激活闹钟</p></div>
|
||||
<div id="wh-trv-alarm-title">
|
||||
<h5 id="wh-trv-alarm-header">飞行闹钟</h5>
|
||||
</div>
|
||||
<div id="wh-trv-alarm-bottom">
|
||||
<div id="wh-trv-alarm-cont">
|
||||
<p id="wh-trv-alarm-remaining"></p>
|
||||
<p><span id="wh-trv-status">正在{{}} </span><span>✈</span></p>
|
||||
<div><input class="checkbox-css" id="WHTravelAlarmToggle" type="checkbox" {{}}/><label
|
||||
class="non-selection marker-css" for="WHTravelAlarmToggle">开启闹钟</label></div>
|
||||
<div><label>落地前响铃时长(秒): <input type="number" value="{{}}"/></label>
|
||||
<button>确定</button>
|
||||
</div>
|
||||
<div class="wh-trv-alarm-stop-hide">
|
||||
<button>停止闹钟</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
16
src/static/html/view_logs_handler.html
Normal file
16
src/static/html/view_logs_handler.html
Normal file
@ -0,0 +1,16 @@
|
||||
<style>
|
||||
#WHLogsCont {
|
||||
width: 100%;
|
||||
height: 340px;
|
||||
}
|
||||
|
||||
#WHLogsCont p {
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
word-break: keep-all;
|
||||
}
|
||||
</style>
|
||||
<p>{{}}信息 {{}}警告 {{}}错误
|
||||
<button class="torn-btn">导出日志</button>
|
||||
</p>
|
||||
<div id="WHLogsCont">加载中</div>
|
||||
35
src/static/html/xmasTown/wt.html
Normal file
35
src/static/html/xmasTown/wt.html
Normal file
@ -0,0 +1,35 @@
|
||||
<div id="wh-xmas-cont">
|
||||
<div class="title-black"><span>水晶球解密地图攻略</span><span><button style="color: white">[隐藏]</button></span>
|
||||
</div>
|
||||
<div class="cont-gray select-wrap dropdown-new dropdown-default">
|
||||
<select>
|
||||
<option value="None">未选择</option>
|
||||
<option value="Christmas Town">Christmas Town</option>
|
||||
<option value="Maltese Snow Globe">Maltese Snow Globe</option>
|
||||
<option value="Long way from home">Long way from home</option>
|
||||
<option value="Chedburn Towers">Chedburn Towers</option>
|
||||
<option value="Kidnapped Santa">Kidnapped Santa</option>
|
||||
<option value="Holiday terror">Holiday terror</option>
|
||||
<option value="Among Us">Among Us</option>
|
||||
<option value="Kiss My Festivus">Kiss My Festivus</option>
|
||||
<option value="Stanley Hotel">Stanley Hotel</option>
|
||||
<option value="DoggoQuest">DoggoQuest</option>
|
||||
<option value="Pokemon CT">Pokemon CT v2.0</option>
|
||||
<option value="Winter in Gatlin">Winter in Gatlin</option>
|
||||
</select>
|
||||
<div>
|
||||
<p>来源:Torn City公众号,图文详情请查看公众号文章</p>
|
||||
<div id="wt-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="page-head-delimiter m-top10 m-bottom10 r1854">
|
||||
</div>
|
||||
<style>
|
||||
#wh-xmas-cont .cont-gray {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#wh-xmas-cont p, #wh-xmas-cont select, #wh-xmas-cont li {
|
||||
margin: 0 0 3px;
|
||||
}
|
||||
</style>
|
||||
15
src/static/html/xmasTown/wt_among_us.html
Normal file
15
src/static/html/xmasTown/wt_among_us.html
Normal file
@ -0,0 +1,15 @@
|
||||
<ul>
|
||||
<li>出生点步行到传送点进入地图 1 [399,12]</li>
|
||||
<li>到达地图1,你出现在食堂,往下走,绕到红色按钮处[502,-1]</li>
|
||||
<li>答案:D B A A D D B B B C A D D D 最终: B (Green)</li>
|
||||
<li>然后你会被传送到地图2</li>
|
||||
<li>在地图2中,你需要沿着小路向南走,然后向东进入通风口,前往下一个部分[556,24]</li>
|
||||
<li>穿过通风口后,进入食堂。向南走到红色按钮所在的位置 [571,32]</li>
|
||||
<li>答题阶段,答案如下BBACBDC A</li>
|
||||
|
||||
<li>被传送到地图3</li>
|
||||
<li>先直接向南走一点,再沿着走廊走。进入左边的一个通风口[345,170]</li>
|
||||
<li>会传送到办公室,在那里找到最后一个红色按钮[356,173]</li>
|
||||
<li>答题阶段,答案如下CCADABBCD</li>
|
||||
<li>进入"PEEP SHOW",获得本地图的水晶球</li>
|
||||
</ul>
|
||||
13
src/static/html/xmasTown/wt_chedburn_towers.html
Normal file
13
src/static/html/xmasTown/wt_chedburn_towers.html
Normal file
@ -0,0 +1,13 @@
|
||||
<ul>
|
||||
<li>进入地图后,使用附近的FAST的T下方的厕所传送到Chedburn Towers</li>
|
||||
<li>进入大厅,"之"字形上楼,每层都是如此。</li>
|
||||
<li>最终会进入问答题区域,通过在相应的数字上穿过来回答问题</li>
|
||||
<li>答案是:3 9 5 4 9 2 6 8</li>
|
||||
<li>答题后,进入Ched的办公室,向西走,然后一直走到左边的楼梯上</li>
|
||||
<li>向南走下楼梯,然后向东走,沿着小楼梯到地下室</li>
|
||||
<li>向东走到牢房区域</li>
|
||||
<li>先踩下开关,打开牢房门前往右上角的最后一个牢房</li>
|
||||
<li>开关位于JAIL文字的左上方</li>
|
||||
<li>沿着挖出来的隧道一直走,岔路口向左走</li>
|
||||
<li>到金库,Chedburn NPC会给你本地图的水晶球</li>
|
||||
</ul>
|
||||
30
src/static/html/xmasTown/wt_doggoQuest.html
Normal file
30
src/static/html/xmasTown/wt_doggoQuest.html
Normal file
@ -0,0 +1,30 @@
|
||||
<ul>
|
||||
<li>你出现在一个房间里</li>
|
||||
<li>向东走,然后向南走,沿着小走廊就可以离开这个房间</li>
|
||||
<li>来到这个地牢的01层</li>
|
||||
<li>首先向南走,然后绕过墙,攻击你看到的第一个怪物[101,1]</li>
|
||||
<li>然后向西走到墙边,向北攻击<span style="color: #32CD32">史莱姆</span></li>
|
||||
<li>继续向北,攻击下一个<span style="color: gold">怪物</span></li>
|
||||
<li>向北走到拐角处,然后向东走到楼梯处继续前进[坐标为101,1]</li>
|
||||
<li>来到第二层,直接向东走上楼梯[11,-19]</li>
|
||||
<li>来到了这个地牢的第03层</li>
|
||||
<li>向东再向南走到墙边,然后向东走,与绿色<span style="color: #32CD32">史莱姆</span>战斗</li>
|
||||
<li>继续向东走,经过被打败的史莱姆,然后向南和向西绕过墙,向北走一格,向西打败另一个<span
|
||||
style="color: #32CD32">史莱姆</span></li>
|
||||
<li>向西南方向走下楼梯[53,-49]</li>
|
||||
<li>来到了第 04 层</li>
|
||||
<li>走到墙边,撞右边两个镣铐之间的墙,然后向北直接走到墙里[15,-65]</li>
|
||||
<li>直接向北走,踏上红色的东西</li>
|
||||
<li>沿着楼梯向南和东南方向走右边楼梯[39,-69]</li>
|
||||
<li>来到第5层</li>
|
||||
<li>向北走,然后向西绕过中间的十字架,向南走到下一个楼梯[29,-93]</li>
|
||||
<li>来到第 6 层</li>
|
||||
<li>杀死那只<span style="color: #32CD32">大绿狗</span></li>
|
||||
<li>回到刚才的楼梯,来到05层[33,-114]</li>
|
||||
<li>在第05层,你会看到原来的十字架位置附近出现了新的楼梯口</li>
|
||||
<li>走上该楼梯[54, -99]</li>
|
||||
<li>到达了最后的?层</li>
|
||||
<li>沿着小路向下走,然后沿着冰冷的台阶走到Rudolph NPC</li>
|
||||
<li>在他身边来回走动</li>
|
||||
<li>踩在他身上的次数足够多时,Rudolph会把该图的水晶球交给你</li>
|
||||
</ul>
|
||||
18
src/static/html/xmasTown/wt_holiday_terror.html
Normal file
18
src/static/html/xmasTown/wt_holiday_terror.html
Normal file
@ -0,0 +1,18 @@
|
||||
<ul>
|
||||
<li>1. 从出生地沿着路向东,然后向北。过桥并沿着穿过城镇的小路继续前行,避开任何明显的陷阱(道路上的洞、打开的井盖等)。
|
||||
</li>
|
||||
<li>2. 继续向东和向北前进,直到到达 Mansion's Labyrinth(豪宅迷宫)[121,29]</li>
|
||||
<li>3. 豪宅入口在[131,41]</li>
|
||||
<li>4. 进入豪宅后向北走,你会看到一条由骷髅守卫的道路</li>
|
||||
<li>5. 沿着棕色的小路走,在黑色的<b>区域前</b>停下</li>
|
||||
<li>6. 按照如下的方式行进</li>
|
||||
<li> 上3格,左2,上2,右4,下1,右3,上6,左2,下1,左6,下2,左2,上4,右5,上4</li>
|
||||
<li>7. 来到一个区域,在这里你必须在两个洞穴中做出选择</li>
|
||||
<li>第一次选择,答案是Christmas Miracle,选择左边的洞窟。</li>
|
||||
<li>第二次选择,答案是24/12/2019,选择左边的洞窟。</li>
|
||||
<li>第三次选择,答案是Hohoho Coldington,选择右边的洞窟。</li>
|
||||
<li>第四次选择,答案是Christmas Miracle Cave,选择左边的洞窟。</li>
|
||||
<li>8. 出现在一个用糖果棒装饰的红色地板的房间里,去地图的右上角一个冰洞的入口[101,-74]</li>
|
||||
<li>9. 进入冰洞。向西走,寻找叫Erik the last elf的黄色小NPC</li>
|
||||
<li>10. 拿到水晶球</li>
|
||||
</ul>
|
||||
24
src/static/html/xmasTown/wt_kidnapped_santa.html
Normal file
24
src/static/html/xmasTown/wt_kidnapped_santa.html
Normal file
@ -0,0 +1,24 @@
|
||||
<ul>
|
||||
<li>出生在一个类似城镇的地方</li>
|
||||
<li>沿着这条路向东走,然后向南走</li>
|
||||
<li>到达道路尽头的一个码头时,向西走一段路,踩在精灵的上面,乘坐渡船[124, -30]</li>
|
||||
<li>搭船来到了Fantasy Island</li>
|
||||
<li>小心那个游荡的<span style="color: #32CD32">绿色NPC</span>,不惜一切代价避开他,否则他会把你打回出发点</li>
|
||||
<li>向西走,然后向北走,再向西绕过岩石。要非常小心,不要踩到水里或掉下悬崖,否则你会死</li>
|
||||
<li>然后回到南边,在那里你会看到一些门</li>
|
||||
<li>走进蓝色的门(左二)[111,-60]</li>
|
||||
<li>过了蓝门后继续沿路向南</li>
|
||||
<li>然后沿路向东,再向南</li>
|
||||
<li>再向东走,会看到「恐怖之家」,进入这栋楼[137, -84]</li>
|
||||
<li>向北走,进入洞口[164, -81]</li>
|
||||
<li>穿过隧道到达另一端的洞穴口[142, -63],<b>避开所有怪物和NPC</b></li>
|
||||
<li>来到另一个岛上</li>
|
||||
<li>向南走,然后向东绕过建筑物,可以进入圣诞老人的洞穴[133, -2]</li>
|
||||
<li>在建筑物内向西走,再向北走,在圣诞老人家work shop的东北角,你会看到一个楼梯,走下去[169,4]</li>
|
||||
<li>在这一区域,<b>要避开所有出现破损或有异样的地砖</b>,也要避开四处游荡的邪恶的格林奇NPC</li>
|
||||
<li>沿着地牢里的走廊向东走,然后向南走,避开所有看起来不同的瓷砖</li>
|
||||
<li>它们上面有一些小裂缝和花纹,如果你是用手机的话,我建议你把亮度调高,以防万一</li>
|
||||
<li>最终会看到一个发绿光的小开关</li>
|
||||
<li>走到开关上[165, 18],激活它,然后进入向北打开的大门</li>
|
||||
<li>走到<span style="color: gold">黄色精灵NPC</span>脸上[166,25],可以得到本地图的水晶球</li>
|
||||
</ul>
|
||||
19
src/static/html/xmasTown/wt_kiss_my_festivus.html
Normal file
19
src/static/html/xmasTown/wt_kiss_my_festivus.html
Normal file
@ -0,0 +1,19 @@
|
||||
<ul>
|
||||
<li>从起点出发,沿着小路向北走到出租车处,乘坐前往Dark Forest的出租车 [96,16]</li>
|
||||
<li>沿着公路向东走,继续向东进入雪地</li>
|
||||
<li>沿着暗淡的蓝色轨迹向东南方向走,穿过树林,直到你到达一个铁栅栏[坐标为114,-89]</li>
|
||||
<li>铁栅栏进不去。有人会告诉你乘坐他们的雪地车。</li>
|
||||
<li>向西走到雪地车旁,注意不要踩到任何<b>冬青树</b>(鲜艳黄红色的矮树),否则你将回到起点。</li>
|
||||
<li>被传送到锯木厂,在伐木工那里获得钥匙。</li>
|
||||
<li>然后向南走,然后向东走(向东走很长一段路),沿着小路返回铁栅栏处。</li>
|
||||
<li>来到一个炫酷的45°视角迷宫,你要走到地图的东北部,抵达另一个洞穴口[156,-74]</li>
|
||||
<li>先往左下方走到岔路口,然后往右上方走,接下来将只有一条路</li>
|
||||
<li>到达岛屿沿着小楼梯上去,绕到正下方那艘天鹅船</li>
|
||||
<li>到一个新的岛屿,向南走几步,踩在[12, -79]的蓝色火花上</li>
|
||||
<li>被传送到另一个有几辆拖车的岛上</li>
|
||||
<li>向北走,进入一个新的山洞口</li>
|
||||
<li>人被挡住了,要在冰层下向西北方向一直走,主要是向上和向左走</li>
|
||||
<li>沿着这条路一直往上走,然后在开阔的地方往东走,你会看到一座房子[房子的入口在26,58]</li>
|
||||
<li>进入房子,向北走几步,穿过闪闪发光的入口,你就可以进入房子了</li>
|
||||
<li>沿着东南方向走,你会看到Evil-Duck NPC,他将给你本地图的水晶球</li>
|
||||
</ul>
|
||||
21
src/static/html/xmasTown/wt_long_way_from_home.html
Normal file
21
src/static/html/xmasTown/wt_long_way_from_home.html
Normal file
@ -0,0 +1,21 @@
|
||||
<ul>
|
||||
<li>1.随便动一下</li>
|
||||
<li>2.左边的管道口</li>
|
||||
<li>3.右走到十字路口,往上,往右,从偏左的那个管道往上。</li>
|
||||
<li>3.出小门,往右到底,往上到底,往右,进上面房间,右上角的电脑,电脑显示的是下面房间的走法,任意移动退出</li>
|
||||
<li>4.去下面房间,右边橙色电力符号,进入解密。下,右下,右下,右上,右上,右,右下,右下,下,左下,左下,</li>
|
||||
<li>左,左,左下,左下,进圈。</li>
|
||||
<li>5.进入新的房间按钮</li>
|
||||
<li>6.一直左走,走到有两个怪兽把手的桥那,进上面的房间,左上角的机器,*是重输密码</li>
|
||||
<li>作者随时改密码,建议看纸条上的提示自己去数</li>
|
||||
<li>7.桥上怪兽消失, 往左走到底,按钮</li>
|
||||
<li>8.右走,走到雪地走大路,按钮开铁门,上darkforest的蓝车</li>
|
||||
<li>9.右走十几步,传送</li>
|
||||
<li>10.右下走,看到铁丝网,顺着铁丝网右走,有个缺口,进去。</li>
|
||||
<li>11.右走,直到看见三颗倒下的圣诞树(记住这里),顺着血迹和脚印走,进山洞。</li>
|
||||
<li>12.顺着山洞走到一滩血,原路出山洞。</li>
|
||||
<li>13.原路回到三颗倒下的圣诞树,正上方有个红色仓库,进入。</li>
|
||||
<li>14.上,上,上,右,上,左,上,路就通了,去拿到右上角的锯子,原路出仓库。</li>
|
||||
<li>15.出来就在车下面,上车,再上车。</li>
|
||||
<li>16.左边的小橘人,完成</li>
|
||||
</ul>
|
||||
18
src/static/html/xmasTown/wt_maltese_snow_globe.html
Normal file
18
src/static/html/xmasTown/wt_maltese_snow_globe.html
Normal file
@ -0,0 +1,18 @@
|
||||
<ul>
|
||||
<li>1.想办法进入前几层的楼梯口</li>
|
||||
<li>2.出来之后往南走, 在码头找到天鹅船</li>
|
||||
<li>3.按着数字1-12走过乐高博物馆</li>
|
||||
<li>4.跟着大路走到天鹅船。</li>
|
||||
<li>5.走到901,486的银行</li>
|
||||
<li>6.最左上的楼梯</li>
|
||||
<li>7.B-D-C-E-F-G-C-A</li>
|
||||
<li>8.右,右,右,北,北,右,右</li>
|
||||
<li>9.走到右上角铁路</li>
|
||||
<li>10.小游戏:</li>
|
||||
<li>移动1到最右,移动2到中间,移动1到2上面,移动3到最右,移动1到最左,移动2到3.上面,移动1到2上面。</li>
|
||||
<li>11.往上走出铁丝网,往左绕一个大圈走到300,476</li>
|
||||
<li>12.走到363,406的隧道,走到361,400的隧道 ,往南走。</li>
|
||||
<li>13.走到352,334的迷宫,好像有好几条路,我说我的走法,往左下走,走倒最下了往右走,走到1个不一样的绿色的时候,往上走。
|
||||
</li>
|
||||
<li>14.走到迷宫中间的小人,后面就只有一条路走了,完成。</li>
|
||||
</ul>
|
||||
36
src/static/html/xmasTown/wt_pokemon_ct.html
Normal file
36
src/static/html/xmasTown/wt_pokemon_ct.html
Normal file
@ -0,0 +1,36 @@
|
||||
<ul>
|
||||
<li>宝可梦新增了战斗系统,路过高草丛会几率进入战斗</li>
|
||||
<li>战斗系统为一个十字形界面,上:技能/精灵球捕捉,下:逃跑,左:回血,右:攻击</li>
|
||||
<li>战斗守则:攻击,当你血量为33时回血</li>
|
||||
<li>打败最终BOSS需要捕捉两只,捕捉地点:</li>
|
||||
<li>一:把包裹交给大木博士后,去常磐市的路上</li>
|
||||
<li>二:进入森林后遇到的毛毛虫</li>
|
||||
<li>捕捉时需要将其打到残血。</li>
|
||||
<li>最终BOSS打法:</li>
|
||||
<li>第一个敌方精灵,毛虫进化的蝴蝶,先放技能,使其眩晕,在眩晕期间攻击,一旦醒过来就眩晕,重复。</li>
|
||||
<li>第一个BOSS死后,第二个BOSS会秒杀蝴蝶, 此时用第二个精灵。</li>
|
||||
<li>第二个精灵打法:攻击,看见它放absorbing技能就去回血(当然你没血了也要去回血),重复。</li>
|
||||
<li>【游戏开始】</li>
|
||||
<li>出生在你房间的二楼</li>
|
||||
<li>下楼梯离开房间。走出家门。从那里向东北方向进入高草丛,将被传送到大木博士(Professor Oak)的实验室</li>
|
||||
<li>踩大木博士</li>
|
||||
<li>踏上桌子,选择你的宝可梦</li>
|
||||
<li>现在出门去常磐市(Veridian City)拿一个包裹</li>
|
||||
<li>离开大木博士的实验室,向北走,穿过草地,前往常磐市(Veridian City)</li>
|
||||
<li>进入城市后,前往 Poke Mart [134,-3]</li>
|
||||
<li>回到大木博士的实验室,返回时可以跳下小路西侧的山崖,避开高草丛</li>
|
||||
<li>把包裹交给大木博士后。回常磐市</li>
|
||||
<li>在房子和两个精灵之间的小路上继续向北走,穿过城市[79,-21]</li>
|
||||
<li>过了精灵后一路向北</li>
|
||||
<li>进入一所房子,经过它才能进入常磐森林</li>
|
||||
<li>穿过常磐森林才能到达尼比市</li>
|
||||
<li>森林的入口向东走,直到看到高草,然后向北走,直到下一片高草</li>
|
||||
<li>绕过树木向东走,然后向北走</li>
|
||||
<li>现在绕过树木向西走,然后向北走</li>
|
||||
<li>然后穿过草地向西和向南走</li>
|
||||
<li>沿着这条小路蜿蜒穿过高高的草丛</li>
|
||||
<li>沿着小路穿过草地,最终离开森林</li>
|
||||
<li>离开森林后,沿着草丛旁小路向北走,到达 Pewter City。向北向西绕到大房子处,到达道馆</li>
|
||||
<li>走到大胡桃夹子前,挑战小刚</li>
|
||||
<li>赢得这场战斗后你会被带到大木博士那里,他会给本地图的水晶球</li>
|
||||
</ul>
|
||||
7
src/static/html/xmasTown/wt_stanley_hotel.html
Normal file
7
src/static/html/xmasTown/wt_stanley_hotel.html
Normal file
@ -0,0 +1,7 @@
|
||||
<ul>
|
||||
<li>从起点开始,你会看到正北方有一座房子。向北走几步到门前,进入房子。</li>
|
||||
<li>传送到一个有门的地方。绕过并向上走,激活位于[188,72]的大门开关。</li>
|
||||
<li>向东北方向前进,沿着血迹穿过森林,直到你到达一个山洞。</li>
|
||||
<li>依次使用使用防御(踩盾牌标记),然后攻击(剑),然后魔法(闪亮的蓝色气泡)来杀死怪物。</li>
|
||||
<li>最后,你会来到工人Bob的房间,他将给你本地图的水晶球。</li>
|
||||
</ul>
|
||||
9
src/static/html/xmasTown/wt_winter_in_gatlin.html
Normal file
9
src/static/html/xmasTown/wt_winter_in_gatlin.html
Normal file
@ -0,0 +1,9 @@
|
||||
<ul>
|
||||
<li>从出生点出发</li>
|
||||
<li>往右走到达树林,往右上走跨过铁栅栏,再往右走,经过红车时从右边缝隙穿过往下走</li>
|
||||
<li>沿公路向下走到第一个岔路向右走到废弃的小屋[14,80]</li>
|
||||
<li>进入小屋时,你会在一个黑色的小房间里,走到亮起的圆圈处</li>
|
||||
<li>在下一个房间里,会有一连串的数字,按以下顺序走到数字上</li>
|
||||
<li>1,4,6,8,7,6,4</li>
|
||||
<li>在最后一个房间,Epic_Heasley NPC 会给你本图的水晶球</li>
|
||||
</ul>
|
||||
7
src/static/html/xmasTown/wt_xmas_town.html
Normal file
7
src/static/html/xmasTown/wt_xmas_town.html
Normal file
@ -0,0 +1,7 @@
|
||||
<ul>
|
||||
<li>旧攻略提到的驯鹿车已被移除,只能手动找一条蓝色的小路[94,3]</li>
|
||||
<li>向南走,然后上木桥,沿着它向西走到达冰湖</li>
|
||||
<li>在冰湖[55,7][61,64]附近找Labyrinth传送门进入迷宫</li>
|
||||
<li>迷宫的出口在中间的方向[395,397]一个冰湖,走进冰湖传送</li>
|
||||
<li>走到企鹅</li>
|
||||
</ul>
|
||||
132
src/static/html/xmasTown/xmas_town_notify.html
Normal file
132
src/static/html/xmasTown/xmas_town_notify.html
Normal file
@ -0,0 +1,132 @@
|
||||
<div class="m-bottom10" id="wh-loot-container">
|
||||
<audio src="https://www.torn.com/js/chat/sounds/Chirp_3.mp3" style="display:none"></audio>
|
||||
<div class="title-black"><span>附近物品</span></div>
|
||||
<div class="cont-gray" id="wh-loot-container-main">
|
||||
<b>物品</b><span id="wh-loot-item-count"></span>
|
||||
<div id="wh-loot-container-items"></div>
|
||||
<b>箱子</b><span id="wh-loot-chest-count"></span>
|
||||
<div id="wh-loot-container-chests"></div>
|
||||
</div>
|
||||
<div class="cont-gray wh-hide" id="wh-loot-container-ex">
|
||||
<div><label><input id="wh-loot-setting-blink" type="checkbox" {{}}/> 闪烁提示</label></div>
|
||||
<div><label><input id="wh-loot-setting-sound" type="checkbox" {{}}/> 声音提示
|
||||
<del>(iOS)</del>
|
||||
</label></div>
|
||||
<div><label><input id="wh-loot-setting-chest" type="checkbox" {{}}/> 不记录需要钥匙的宝箱</label></div>
|
||||
<div id="wh-hist">
|
||||
<div id="wh-hist-clear">
|
||||
<p>
|
||||
<button>清空数据</button>
|
||||
- 长时间不清空会出现奇怪的问题
|
||||
</p>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="5">历史记录</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>坐标</th>
|
||||
<th>地图</th>
|
||||
<th>类型</th>
|
||||
<th>发现</th>
|
||||
<th>获取</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cont-gray" id="wh-loot-btn">
|
||||
<button>设置</button>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
#wh-loot-container-main {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#wh-loot-container-main div {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
white-space: nowrap;
|
||||
min-height: 4em;
|
||||
}
|
||||
|
||||
#wh-loot-container-main div span {
|
||||
display: inline-block;
|
||||
background-color: #2e8b57;
|
||||
color: white;
|
||||
margin: 0 1em 0 0;
|
||||
border-radius: 4px;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#wh-loot-container-main div span img {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex.wh-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex #wh-hist {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex table {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex tbody {
|
||||
background-color: antiquewhite;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex table, #wh-loot-container-ex th, #wh-loot-container-ex td {
|
||||
padding: 5px;
|
||||
border: 1px solid black;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex th:nth-child(1) {
|
||||
min-width: 5em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex th:nth-child(2) {
|
||||
min-width: 8em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex th:nth-child(3) {
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex th:nth-child(4) {
|
||||
min-width: 9em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex th:nth-child(5) {
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
#wh-loot-container-ex thead {
|
||||
background-color: #2e8b57;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes lootFoundAlert {
|
||||
0% {
|
||||
background: #f2f2f2
|
||||
}
|
||||
50% {
|
||||
background: #2e8b57
|
||||
}
|
||||
100% {
|
||||
background: #f2f2f2
|
||||
}
|
||||
}
|
||||
</style>
|
||||
30
src/static/html/xunzhaomuzhuang/index.html
Normal file
30
src/static/html/xunzhaomuzhuang/index.html
Normal file
@ -0,0 +1,30 @@
|
||||
<div id="deadman_div" style="width: inherit">
|
||||
<div id="deadman_header" style="margin:10px 0px; border:1px solid darkgray; text-align:center;">
|
||||
<button class="torn-btn" id="deadman-start-btn" style="margin:5px;">开始寻找木桩</button>
|
||||
<button class="torn-btn" style="margin:5px;">停止</button>
|
||||
</div>
|
||||
<div id="deadman_tips" style="text-align:center; margin-bottom: 3px; font-size: 16px;">未开始</div>
|
||||
<div id="deadman_wrapper"
|
||||
style="min-height:700px;margin:10px 0px; border:1px solid darkgray; text-align:center;overflow:hidden;">
|
||||
<table cellspacing="0" id="watchlist-table" style="width:100%; background-color: white; font-size:12px;">
|
||||
<thead>
|
||||
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
|
||||
ID
|
||||
</th>
|
||||
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
|
||||
名字
|
||||
</th>
|
||||
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
|
||||
等级
|
||||
</th>
|
||||
<th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">
|
||||
攻击
|
||||
</th>
|
||||
<!-- <th style="border: 1px solid darkgray;padding: 5px;background-color: black;color: white;font-weight: bold;text-align:center;">-->
|
||||
<!-- BS(M)-->
|
||||
<!-- </th>-->
|
||||
</thead>
|
||||
<tbody id="table-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
50
src/static/html/zhong/setting/dev_details.html
Normal file
50
src/static/html/zhong/setting/dev_details.html
Normal file
@ -0,0 +1,50 @@
|
||||
<table id="wh-dev-info-tb">
|
||||
<tr>
|
||||
<td>URL</td>
|
||||
<td>${ window.location.href }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>页面尺寸</td>
|
||||
<td>${ window.innerWidth }x${ window.innerHeight }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>设备类型</td>
|
||||
<td>${ CommonUtils.getDeviceType().toUpperCase() }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>脚本运行方式</td>
|
||||
<td>${ { 'gm': '油猴', 'raw': '直接运行', 'pda': 'TornPDA' }[CommonUtils.getScriptEngine()] }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>时间</td>
|
||||
<td>${ date.getFullYear() }/${ date.getMonth() + 1 }/${ date.getDate() } ${ date.getHours() }:${
|
||||
date.getMinutes() }:${ date.getSeconds() }
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>插件版本</td>
|
||||
<td>${ glob.version }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>操作系统</td>
|
||||
<td>${ os }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UA</td>
|
||||
<td>${ window.navigator.userAgent }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>用户ID</td>
|
||||
<td>${ glob.player_info.userID }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>用户名</td>
|
||||
<td>${ glob.player_info.playername }</td>
|
||||
</tr>
|
||||
</table>
|
||||
<style>
|
||||
#wh-dev-info-tb td {
|
||||
padding: 2px 4px;
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
10
src/static/html/zhong/zhong_loot.html
Normal file
10
src/static/html/zhong/zhong_loot.html
Normal file
@ -0,0 +1,10 @@
|
||||
<p>点击开打:</p>
|
||||
<ul>
|
||||
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=4" target="_blank">Duke</a></li>
|
||||
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=15" target="_blank">Leslie</a></li>
|
||||
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=19" target="_blank">Jimmy(面包刀)</a></li>
|
||||
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=20" target="_blank">Fernando(毒伞)</a></li>
|
||||
<li><a href="https://www.torn.com/loader.php?sid=attack&user2ID=21" target="_blank">Tiny(大锤)</a></li>
|
||||
</ul>
|
||||
<div><img alt="stock.png" src="https://jjins.github.io/t2i/loot.png?{{}}"
|
||||
style="max-width:100%;display:block;margin:0 auto;"/></div>
|
||||
16
src/static/html/zhong/zhong_menu.html
Normal file
16
src/static/html/zhong/zhong_menu.html
Normal file
@ -0,0 +1,16 @@
|
||||
<div>
|
||||
<button id="wh-trans-icon-btn"></button>
|
||||
</div>
|
||||
<div class="wh-container">
|
||||
<div class="wh-main">
|
||||
<div><b>芜湖助手</b></div>
|
||||
<div id="wh-gSettings"></div>
|
||||
<div>
|
||||
<p>当前版本: {{}}
|
||||
<button id="wh-update-btn">更新</button>
|
||||
</p>
|
||||
</div>
|
||||
<div><p>最新版本: <span id="wh-latest-version"></span></p></div>
|
||||
<div><p id="wh-inittimer"></p></div>
|
||||
</div>
|
||||
</div>
|
||||
0
src/static/html/zhong/zhong_settings.html
Normal file
0
src/static/html/zhong/zhong_settings.html
Normal file
15
src/static/html/zhong/zhong_update.html
Normal file
15
src/static/html/zhong/zhong_update.html
Normal file
@ -0,0 +1,15 @@
|
||||
<h4>电脑</h4>
|
||||
<p>通常电脑浏览器装有油猴等用户脚本扩展时可以使用链接安装(自动更新):<a
|
||||
href="https://gitlab.com/JJins/wuhu-torn-helper/-/raw/dev/release.min.user.js" target="_blank">点此安装</a>。</p>
|
||||
<p>这些扩展长这样:<img alt="tm.png" src="//jjins.github.io/tm.png"/><img alt="vm.png" src="//jjins.github.io/vm.png"/>
|
||||
</p>
|
||||
<p></p>
|
||||
<h4>手机</h4>
|
||||
<p>安卓 KIWI 等可以用油猴脚本的浏览器也可以点上面的链接安装👆</p>
|
||||
<p>Torn PDA app 或 Alook 用户可打开<a href="//jjins.github.io/fyfuzhi/" target="_blank">这个网页</a>快捷复制粘贴。</p>
|
||||
<p>注:Torn PDA 中,Injection time 请选择 Start 达到最好效果。</p>
|
||||
<h4>直接复制</h4>
|
||||
<p>加载脚本然后直接复制粘贴到用户脚本处。</p>
|
||||
<p>
|
||||
<button>加载</button>
|
||||
</p>
|
||||
3
src/static/json/__css__.json
Normal file
3
src/static/json/__css__.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"css": ".wh-hide{display:none;}#wh-trans-icon{user-select:none;display: inline-block;position: fixed;top:5px;left:5px;z-index:100010;border-radius:4px;max-width: 220px;box-shadow: 0 0 3px 1px #8484848f;}div#effectiveness-wrap{overflow-y:hidden;}@media screen and (max-width: 600px) { #wh-trans-icon{top:0;left:112px;} /* 冰蛙公司效率表 */ div#effectiveness-wrap { margin-left: -80px; margin-right: -76px; }}#wh-trans-icon select{width:110px;}#wh-trans-icon a {text-decoration: none;color: #006599;background: none;}#wh-trans-icon:not(.wh-icon-expanded):hover {background: #f8f8f8;}#wh-trans-icon button{margin:0;padding:0;border:0;cursor:pointer;}#wh-inittimer{margin-top:6px;color:#b0b0b0;}#wh-gSettings div{margin: 4px 0;}#wh-trans-icon .wh-container{margin:0;padding:0 16px 16px;border:0;}#wh-trans-icon-btn{height:16px;width:16px;background: url('data:image/svg+xml;utf8,<svg viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\"><path d=\"M160 144a32 32 0 0 0-32 32V864a32 32 0 0 0 32 32h688a32 32 0 0 0 32-32V176a32 32 0 0 0-32-32H160z m0-64h688a96 96 0 0 1 96 96V864a96 96 0 0 1-96 96H160a96 96 0 0 1-96-96V176a96 96 0 0 1 96-96z\"/><path d=\"M482.176 262.272h59.616v94.4h196v239.072h-196v184.416h-59.616v-184.416H286.72v-239.04h195.456V262.24z m-137.504 277.152h137.504v-126.4H344.64v126.4z m197.12 0h138.048v-126.4H541.76v126.4z\"/></svg>') no-repeat center;padding:16px !important;}#wh-trans-icon .wh-container{display:none;}#wh-trans-icon.wh-icon-expanded .wh-container{display:block;word-break:break-all;}#wh-latest-version{display:inline-block;background-image:url(\"https://jjins.github.io/t2i/version.png?{{}}\");height:16px;width: 66px;}/** 弹出窗口 **/#wh-popup{ position: fixed; z-index: 200000; top: 0; left: 0; width: 100%; height: 100%; background: #00000090; color:#333;}div#wh-popup::after { content: '点击空白处关闭'; display: block; color: #ffffffdb; text-align: center; font-size: 14px; line-height: 22px;}#wh-popup-container{ max-width: 568px; margin: 5em auto 0; background: #d7d7d7; min-height: 120px; box-shadow: 0 0 5px 1px #898989; border-radius: 4px;}#wh-popup-title p{ padding: 1em 0; font-size: 16px; font-weight: bold; text-align: center;}/** 弹出窗口的内容 **/#wh-popup-cont{ padding: 0 1em 1em; max-height: 30em; overflow-y: auto; font-size:14px; line-height: 16px;}#wh-popup-cont .gSetting > div{ display: inline-block; width: 47%; margin: 2px 0;}#wh-popup-cont .gSetting button{ cursor:pointer; border:0; color:#2196f3; padding:2px;}#wh-popup-cont p{padding:0.25em 0;}#wh-popup-cont a{color:red;text-decoration:none;}#wh-popup-cont li{margin:4px 0;}#wh-popup-cont h4{margin:0;padding: 0.5em 0;}#wh-popup-cont button{ margin: 0 4px 0 0; padding: 5px 8px; border: solid 2px black; color: black; border-radius: 3px;}#wh-popup-cont button[disabled]{opacity: 0.5;}#wh-popup-cont input{ padding: 2px; text-align: center; border: 1px solid #fff0; border-radius: 5px; margin:1px 2px;}#wh-popup-cont input:focus{border-color:blue;}#wh-popup-cont table{width:100%;border-collapse:collapse;border:1px solid;}#wh-popup-cont td, #wh-popup-cont th{border-collapse:collapse;padding:4px;border:1px solid;}.wh-display-none{display:none !important;}#wh-gym-info-cont{ background-color: #363636; color: white; padding: 8px; font-size: 15px; border-radius: 4px; text-shadow: 0 0 2px black; background-image: linear-gradient(90deg,transparent 50%,rgba(0,0,0,.07) 0); background-size: 4px; line-height: 20px;}#wh-gym-info-cont button{cursor:pointer;}#wh-notify { display: inline-block; position: fixed; top: 0; left: calc(50% - 180px); width: 360px; z-index: 9999990; color:#333;}#wh-notify a{color:red;text-decoration:none;}#wh-notify .wh-notify-item { /*height: 50px;*/ background: rgb(239 249 255 / 90%); border-radius: 2px; margin: 0.5em 0 0 0; box-shadow: 0 0 5px 0px #959595;}#wh-notify .wh-notify-item:hover { background: rgb(239 249 255 / 98%);}#wh-notify .wh-notify-item .wh-notify-bar { height:2px; background:#2196f3;}#wh-notify .wh-notify-item .wh-notify-close { float:right; padding:0;width:16px;height:16px;background:url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M923%20571H130.7c-27.6%200-50-22.4-50-50s22.4-50%2050-50H923c27.6%200%2050%2022.4%2050%2050s-22.4%2050-50%2050z%22%20fill%3D%22%232196f3%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E') no-repeat center;background-size:100%;margin: 6px 6px 0 0;cursor: pointer;}#wh-notify .wh-notify-item .wh-notify-msg { padding:12px;}"
|
||||
}
|
||||
100
src/static/json/event.json
Normal file
100
src/static/json/event.json
Normal file
@ -0,0 +1,100 @@
|
||||
[
|
||||
{
|
||||
"start": [
|
||||
0,
|
||||
16,
|
||||
8
|
||||
],
|
||||
"end": [
|
||||
0,
|
||||
22,
|
||||
8
|
||||
],
|
||||
"name": "捡垃圾周",
|
||||
"eff": "获得捡垃圾概率提升的增益"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
3,
|
||||
5,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
3,
|
||||
25,
|
||||
20
|
||||
],
|
||||
"name": "复活节狩猎",
|
||||
"eff": "复活节彩蛋会随机出现,集齐10个可兑换金蛋和一个独特的头像框(章)。"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
5,
|
||||
20,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
5,
|
||||
29,
|
||||
20
|
||||
],
|
||||
"name": "狗牌",
|
||||
"eff": "击败其他玩家以获得狗牌,小心保护你的狗牌。"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
6,
|
||||
5,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
6,
|
||||
25,
|
||||
20
|
||||
],
|
||||
"name": "托恩先生和托恩女士",
|
||||
"eff": "上传你的真实图片,然后拿章"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
8,
|
||||
5,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
8,
|
||||
23,
|
||||
20
|
||||
],
|
||||
"name": "大逃杀",
|
||||
"eff": "加入特定队伍后,攻击其他队伍玩家,存活下来的3个队伍可以拿章"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
9,
|
||||
25,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
10,
|
||||
1,
|
||||
20
|
||||
],
|
||||
"name": "不给糖就捣蛋",
|
||||
"eff": "买篮子之后攻击其他玩家后会随机掉落糖果,可用于兑换许多高价值物品"
|
||||
},
|
||||
{
|
||||
"start": [
|
||||
11,
|
||||
19,
|
||||
20
|
||||
],
|
||||
"end": [
|
||||
11,
|
||||
31,
|
||||
20
|
||||
],
|
||||
"name": "圣诞小镇",
|
||||
"eff": "在小镇中闲逛来获取随机掉落的物品"
|
||||
}
|
||||
]
|
||||
68
src/static/json/fest.json
Normal file
68
src/static/json/fest.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"val": {
|
||||
"0104": {
|
||||
"name": "周末自驾游",
|
||||
"eff": "获得双倍的赛车点数与赛车技能等级增益"
|
||||
},
|
||||
"0114": {
|
||||
"name": "情人节",
|
||||
"eff": "使用爱情果汁(Love Juice)后获得降低攻击与复活的能量消耗的增益"
|
||||
},
|
||||
"0203": {
|
||||
"name": "员工激励日",
|
||||
"eff": "获得三倍的工作点数与火车增益"
|
||||
},
|
||||
"0217": {
|
||||
"name": "圣帕特里克日",
|
||||
"eff": "获得双倍的酒类效果增益,城市中可以捡到绿色世涛(Green Stout)"
|
||||
},
|
||||
"0320": {
|
||||
"name": "420日",
|
||||
"eff": "获得三倍的大麻(Cannabis)效果增益"
|
||||
},
|
||||
"0418": {
|
||||
"name": "博物馆日",
|
||||
"eff": "获得10%提高的博物馆PT兑换增益"
|
||||
},
|
||||
"0514": {
|
||||
"name": "世界献血日",
|
||||
"eff": "获得减半的抽血CD和扣血增益"
|
||||
},
|
||||
"0611": {
|
||||
"name": "世界人口日",
|
||||
"eff": "获得双倍的通过攻击获取的经验的增益"
|
||||
},
|
||||
"0629": {
|
||||
"name": "世界老虎日",
|
||||
"eff": "获得5倍的狩猎技能增益"
|
||||
},
|
||||
"0704": {
|
||||
"name": "国际啤酒节",
|
||||
"eff": "获得5倍的啤酒物品效果增益"
|
||||
},
|
||||
"0827": {
|
||||
"name": "旅游节",
|
||||
"eff": "获得双倍的起飞后物品携带容量增益"
|
||||
},
|
||||
"0915": {
|
||||
"name": "饮料节",
|
||||
"eff": "获得双倍的能量饮料效果增益"
|
||||
},
|
||||
"1014": {
|
||||
"name": "世界糖尿病日",
|
||||
"eff": "获得三倍的糖类效果增益"
|
||||
},
|
||||
"1015": {
|
||||
"name": "周年庆",
|
||||
"eff": "左上角的TORN图标可以食用"
|
||||
},
|
||||
"1024": {
|
||||
"name": "黑色星期五",
|
||||
"eff": "某些商家将提供1元购活动"
|
||||
},
|
||||
"1113": {
|
||||
"name": "住院日",
|
||||
"eff": "获得降低75%的住院时间增益"
|
||||
}
|
||||
}
|
||||
}
|
||||
92
src/static/json/for_stock_item_filter.json
Normal file
92
src/static/json/for_stock_item_filter.json
Normal file
@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"name": "mex",
|
||||
"show": "墨西哥",
|
||||
"stocks": {
|
||||
"Dahlia": "花",
|
||||
"Jaguar Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "cay",
|
||||
"show": "开曼",
|
||||
"stocks": {
|
||||
"Banana Orchid": "花",
|
||||
"Stingray Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "can",
|
||||
"show": "加拿大",
|
||||
"stocks": {
|
||||
"Crocus": "花",
|
||||
"Wolverine Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "haw",
|
||||
"show": "夏威夷",
|
||||
"stocks": {
|
||||
"Orchid": "花",
|
||||
"Large Suitcase": "大箱"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uni",
|
||||
"show": "嘤国",
|
||||
"stocks": {
|
||||
"Heather": "花",
|
||||
"Red Fox Plushie": "赤狐",
|
||||
"Nessie Plushie": "水怪"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "arg",
|
||||
"show": "阿根廷",
|
||||
"stocks": {
|
||||
"Ceibo Flower": "花",
|
||||
"Monkey Plushie": "偶",
|
||||
"Tear Gas": "催泪弹"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "swi",
|
||||
"show": "瑞士",
|
||||
"stocks": {
|
||||
"Edelweiss": "花",
|
||||
"Chamois Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "jap",
|
||||
"show": "日本",
|
||||
"stocks": {
|
||||
"Cherry Blossom": "花"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "chi",
|
||||
"show": "祖国",
|
||||
"stocks": {
|
||||
"Peony": "花",
|
||||
"Panda Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "uae",
|
||||
"show": "阿联酋 (UAE)",
|
||||
"stocks": {
|
||||
"Tribulus Omanense": "花",
|
||||
"Camel Plushie": "偶"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "sou",
|
||||
"show": "南非",
|
||||
"stocks": {
|
||||
"African Violet": "花",
|
||||
"Lion Plushie": "偶",
|
||||
"Xanax": "XAN"
|
||||
}
|
||||
}
|
||||
]
|
||||
184
src/static/json/muzhuang_id_list.json
Normal file
184
src/static/json/muzhuang_id_list.json
Normal file
@ -0,0 +1,184 @@
|
||||
[
|
||||
17003,
|
||||
251077,
|
||||
340581,
|
||||
313353,
|
||||
498729,
|
||||
279673,
|
||||
353885,
|
||||
514096,
|
||||
753853,
|
||||
458343,
|
||||
464918,
|
||||
491000,
|
||||
237866,
|
||||
451695,
|
||||
953808,
|
||||
162476,
|
||||
802907,
|
||||
800608,
|
||||
342669,
|
||||
67254,
|
||||
147082,
|
||||
792900,
|
||||
275866,
|
||||
112024,
|
||||
365986,
|
||||
264257,
|
||||
464079,
|
||||
342150,
|
||||
372870,
|
||||
14092,
|
||||
905822,
|
||||
654795,
|
||||
575176,
|
||||
815125,
|
||||
983447,
|
||||
330496,
|
||||
436308,
|
||||
1072681,
|
||||
280295,
|
||||
660205,
|
||||
1180420,
|
||||
478962,
|
||||
382338,
|
||||
229632,
|
||||
488384,
|
||||
465467,
|
||||
381995,
|
||||
342907,
|
||||
332479,
|
||||
190695,
|
||||
346837,
|
||||
79416,
|
||||
432474,
|
||||
378718,
|
||||
1177887,
|
||||
451753,
|
||||
83039,
|
||||
421949,
|
||||
740967,
|
||||
470180,
|
||||
1082559,
|
||||
644384,
|
||||
484743,
|
||||
281747,
|
||||
1210736,
|
||||
762865,
|
||||
938350,
|
||||
320161,
|
||||
283188,
|
||||
522960,
|
||||
488552,
|
||||
387822,
|
||||
566484,
|
||||
298167,
|
||||
234429,
|
||||
428732,
|
||||
18798,
|
||||
476620,
|
||||
472351,
|
||||
807823,
|
||||
796316,
|
||||
316768,
|
||||
153910,
|
||||
76096,
|
||||
659852,
|
||||
450465,
|
||||
738073,
|
||||
284536,
|
||||
524912,
|
||||
263120,
|
||||
729174,
|
||||
251566,
|
||||
519062,
|
||||
1489357,
|
||||
669996,
|
||||
191060,
|
||||
454302,
|
||||
684732,
|
||||
1046495,
|
||||
1199189,
|
||||
485156,
|
||||
1399310,
|
||||
581300,
|
||||
982173,
|
||||
211286,
|
||||
810355,
|
||||
469582,
|
||||
652354,
|
||||
781161,
|
||||
146715,
|
||||
491724,
|
||||
233040,
|
||||
471136,
|
||||
688148,
|
||||
442427,
|
||||
588113,
|
||||
669588,
|
||||
75522,
|
||||
95057,
|
||||
21631,
|
||||
76480,
|
||||
76583,
|
||||
87572,
|
||||
241909,
|
||||
200728,
|
||||
943004,
|
||||
248808,
|
||||
87461,
|
||||
929257,
|
||||
326028,
|
||||
136660,
|
||||
1514039,
|
||||
34069,
|
||||
556583,
|
||||
130275,
|
||||
173148,
|
||||
247665,
|
||||
320301,
|
||||
264772,
|
||||
583658,
|
||||
813216,
|
||||
41317,
|
||||
50835,
|
||||
14641,
|
||||
222151,
|
||||
26299,
|
||||
340810,
|
||||
27340,
|
||||
54567,
|
||||
228704,
|
||||
359740,
|
||||
185958,
|
||||
374418,
|
||||
316174,
|
||||
431576,
|
||||
244123,
|
||||
188142,
|
||||
1462209,
|
||||
45179,
|
||||
768356,
|
||||
232564,
|
||||
364079,
|
||||
668705,
|
||||
758810,
|
||||
295155,
|
||||
343321,
|
||||
65146,
|
||||
384786,
|
||||
466947,
|
||||
325378,
|
||||
1278107,
|
||||
463919,
|
||||
930653,
|
||||
380958,
|
||||
349371,
|
||||
184845,
|
||||
931279,
|
||||
355177,
|
||||
228051,
|
||||
545762,
|
||||
507362,
|
||||
28699
|
||||
]
|
||||
67
src/ts/App.ts
Normal file
67
src/ts/App.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import Interrupt from "./class/Interrupt"
|
||||
import Initializer from "./class/Initializer"
|
||||
// import { Common } from "./class/Common"
|
||||
// import UrlRouter from "./class/UrlRouter"
|
||||
import translateMain from "./func/translate/translateMain"
|
||||
import CommonUtils from "./class/utils/CommonUtils"
|
||||
import LocalConfigWrapper from "./class/LocalConfigWrapper"
|
||||
import ClassName from "./container/ClassName"
|
||||
import { Injectable } from "./container/Injectable"
|
||||
import FeatureMan from "./man/FeatureMan"
|
||||
import Logger from "./class/Logger"
|
||||
|
||||
@ClassName('Application')
|
||||
@Injectable()
|
||||
export default class App {
|
||||
private readonly logger = Logger.factory(App)
|
||||
|
||||
constructor(
|
||||
private readonly interrupt: Interrupt,
|
||||
private readonly initializer: Initializer,
|
||||
// private readonly common: Common,
|
||||
// private readonly urlRouter: UrlRouter,
|
||||
private readonly configWrapper: LocalConfigWrapper,
|
||||
private readonly utils: CommonUtils,
|
||||
private readonly featureMan: FeatureMan,
|
||||
) {
|
||||
}
|
||||
|
||||
public run() {
|
||||
|
||||
this.interrupt.conditionInterrupt();
|
||||
|
||||
// 初始化
|
||||
this.initializer.init();
|
||||
|
||||
// this.featureMan.fStart().then(() => this.featureMan.printTable());
|
||||
|
||||
// 插件图标和设置菜单
|
||||
// this.icon.init();
|
||||
|
||||
let tmp = () => {
|
||||
// // 所有页面通用
|
||||
// try {
|
||||
// // this.common.resolve.apply(this.common, this.run);
|
||||
// // this.common.resolve(() => this.run());
|
||||
// } catch (e) {
|
||||
// }
|
||||
(async function (self: App) {
|
||||
await self.featureMan.fStart()
|
||||
self.featureMan.printTable()
|
||||
})(this)
|
||||
|
||||
// URL匹配
|
||||
// this.urlRouter.resolve();
|
||||
|
||||
// 翻译
|
||||
// if (this.configWrapper.config.transEnable)
|
||||
// translateMain(window.location.href);
|
||||
};
|
||||
// TODO 临时检测jquery
|
||||
if (typeof $ === "function") {
|
||||
tmp();
|
||||
} else {
|
||||
this.utils.jQueryReady().then(() => tmp());
|
||||
}
|
||||
}
|
||||
}
|
||||
160
src/ts/class/Common.ts
Normal file
160
src/ts/class/Common.ts
Normal file
@ -0,0 +1,160 @@
|
||||
// import depoHelper from "../func/module/depoHelper";
|
||||
// import TravelHelper from "../feature/TravelHelper";
|
||||
// import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
||||
// import CompanyHelper from "../feature/CompanyHelper";
|
||||
// import AttackHelper from "./action/AttackHelper";
|
||||
// import SidebarHelper from "../feature/SidebarHelper";
|
||||
// import CommonUtils from "./utils/CommonUtils";
|
||||
// import FetchUtils from "./utils/FetchUtils";
|
||||
// import FetchEventCallback from "./action/FetchEventCallback";
|
||||
// import globVars from "../globVars";
|
||||
// import TranslateNew from "./action/TranslateNew";
|
||||
// import ClassName from "../container/ClassName";
|
||||
// import { Injectable } from "../container/Injectable";
|
||||
// import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
// import Logger from "./Logger";
|
||||
// import BuyBeerHelper from "../feature/BuyBeerHelper";
|
||||
// import ModuleLoader from "./ModuleLoader";
|
||||
// import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
// import TravelItem from "../feature/TravelItem";
|
||||
// import IconHelper from "../feature/IconHelper";
|
||||
// import MsgWrapper from "./utils/MsgWrapper";
|
||||
// import toThousands from "../func/utils/toThousands";
|
||||
// import { WHIntervalLoader } from "../monitor/WHIntervalLoader";
|
||||
//
|
||||
// /**
|
||||
// * 脚本不区分页面的通用功能入口
|
||||
// */
|
||||
// @Injectable()
|
||||
// @ClassName('Common')
|
||||
// export class Common {
|
||||
// private readonly logger = Logger.factory(Common)
|
||||
//
|
||||
// constructor(
|
||||
// private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
// // private readonly fetchEventCallback: FetchEventCallback,
|
||||
// // private readonly translateNew: TranslateNew,
|
||||
// // private readonly tornPDAUtils: TornPDAUtils,
|
||||
// // private readonly buyBeerHelper: BuyBeerHelper,
|
||||
// // private readonly fetchUtils: FetchUtils,
|
||||
// // private readonly moduleLoader: ModuleLoader,
|
||||
// private readonly msgWrapper: MsgWrapper,
|
||||
// ) {
|
||||
// }
|
||||
//
|
||||
// public resolve(mainMethod) {
|
||||
// // window.setInterval(()=>this.msgWrapper.create('test',{sysNotify:true},'info'),2000);
|
||||
//
|
||||
// // // fetch方法处理
|
||||
// // globVars.responseHandlers.push(
|
||||
// // (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
|
||||
// // );
|
||||
// // // fetch方法处理-翻译
|
||||
// // globVars.responseHandlers.push(
|
||||
// // (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
|
||||
// // );
|
||||
//
|
||||
// // // 价格监控
|
||||
// // priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
|
||||
//
|
||||
// // 啤酒提醒
|
||||
// // if (this.localConfigWrapper.config._15Alarm) this.buyBeerHelper.start();
|
||||
//
|
||||
// // this.moduleLoader.push(SidebarHelper);
|
||||
// // this.moduleLoader.push(TravelItem);
|
||||
// // this.moduleLoader.push(WHIntervalLoader)
|
||||
//
|
||||
// /**
|
||||
// * 解决一直转圈(加载中)的问题
|
||||
// * All('script[src*="google"]')
|
||||
// * All('#gtm_tag')
|
||||
// * All('script[src*="chat/gonline"]')
|
||||
// * All('head script[nonce]')
|
||||
// */
|
||||
// // try {
|
||||
// // if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
|
||||
// // window.stop();
|
||||
// // document.open();
|
||||
// // let readyStateChangeHandler = () => {
|
||||
// // this.logger.info('document.readyState', document.readyState);
|
||||
// // if (document.readyState === 'complete') {
|
||||
// // document.removeEventListener('readystatechange', readyStateChangeHandler);
|
||||
// // mainMethod();
|
||||
// // throw new Error('页面已重载');
|
||||
// // }
|
||||
// // }
|
||||
// // document.addEventListener('readystatechange', readyStateChangeHandler);
|
||||
// // this.fetchUtils.fetchText(window.location.href).then(resp => {
|
||||
// // let removed = resp;
|
||||
// // [
|
||||
// // /<script id="gtm_tag">.+?<\/script>/ms,
|
||||
// // /<script async src="https:\/\/www\.google.+?<\/script>/ms,
|
||||
// // /<script nonce=".+?gtag.+?<\/script>/ms,
|
||||
// // /<script.+?google.+?\/script>/,
|
||||
// // ].forEach(remove => {
|
||||
// // removed = removed.replace(remove, '');
|
||||
// // });
|
||||
// // this.logger.info({ removed });
|
||||
// // document.write(removed);
|
||||
// // document.close();
|
||||
// // });
|
||||
// // }
|
||||
// // } catch (e) {
|
||||
// // this.logger.error('【解决一直转圈(加载中)的问题】错误',e)
|
||||
// // }
|
||||
//
|
||||
// // // 存钱相关
|
||||
// // try {
|
||||
// // depoHelper();
|
||||
// // } catch (e) {
|
||||
// // this.logger.error('【存钱相关】错误',e)
|
||||
// // }
|
||||
//
|
||||
// // // 飞行相关
|
||||
// // this.moduleLoader.push(TravelHelper);
|
||||
//
|
||||
// // 战斗相关
|
||||
// // this.moduleLoader.push(AttackHelper);
|
||||
//
|
||||
// // 公司助手
|
||||
// // this.moduleLoader.push(CompanyHelper);
|
||||
//
|
||||
// // // 菜单
|
||||
// // this.moduleLoader.push(IconHelper);
|
||||
//
|
||||
// // this.moduleLoader.load().then();
|
||||
//
|
||||
// // // 自定义CSS
|
||||
// // if (this.localConfigWrapper.config.CustomCss) {
|
||||
// // this.logger.info('应用自定义CSS');
|
||||
// // CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
|
||||
// // }
|
||||
// //
|
||||
// // // 现金变动提醒
|
||||
// // if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
|
||||
// // let before = ''
|
||||
// // new MutationObserver((mutations, observer) => {
|
||||
// // if (!this.localConfigWrapper.config.CashChangeAlert) {
|
||||
// // observer.disconnect();
|
||||
// // this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
|
||||
// // return;
|
||||
// // }
|
||||
// // this.logger.info("现金变动提醒", mutations);
|
||||
// // mutations.forEach(item => {
|
||||
// // if (item.attributeName === 'data-money') {
|
||||
// // let change = userMoney.innerText
|
||||
// // .trim()
|
||||
// // .replaceAll(/[,$]/g, '')
|
||||
// // if (change !== before) {
|
||||
// // this.msgWrapper.create(
|
||||
// // '现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
|
||||
// // { sysNotify: true }
|
||||
// // );
|
||||
// // before = change
|
||||
// // }
|
||||
// // }
|
||||
// // });
|
||||
// // }).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
// // });
|
||||
// }
|
||||
// }
|
||||
93
src/ts/class/Global.ts
Normal file
93
src/ts/class/Global.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import Device from "../enum/Device";
|
||||
import IGlobal from "../interface/IGlobal";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
|
||||
/**
|
||||
* 存储脚本用到的参数
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('Global')
|
||||
export default class Global implements IGlobal {
|
||||
|
||||
GM_xmlhttpRequest: Function = null;
|
||||
// 设备类型
|
||||
device: Device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||
unsafeWindow: Window & typeof globalThis = null;
|
||||
// document body 属性
|
||||
bodyAttrs: {
|
||||
'data-country'?: string;
|
||||
'data-celebration'?: string;
|
||||
'data-traveling'?: 'true' | 'false';
|
||||
'data-abroad'?: 'true' | 'false';
|
||||
} = null;
|
||||
// href: string = window.location.href;
|
||||
// 弹窗
|
||||
// popup_node: MyHTMLElement|Popup = null;
|
||||
/**
|
||||
* @deprecated 使用getInstance替代
|
||||
*/
|
||||
// beer = null;
|
||||
// 留存的通知
|
||||
// notifies: NotifyWrapper = { count: 0 };
|
||||
// 海外库存
|
||||
// fStock = null;
|
||||
// 玩家名和数字id
|
||||
// player_info = null;
|
||||
// PDA运行环境
|
||||
// isPDA: boolean = false;
|
||||
// PDA自带apikey
|
||||
// PDA_APIKey: string = null;
|
||||
// 脚本版本
|
||||
// version: string = null;
|
||||
// window 副本
|
||||
// window: Window & typeof globalThis = window;
|
||||
|
||||
constructor(
|
||||
// private readonly infoUtils: InfoUtils,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
if (typeof unsafeWindow !== 'undefined') {
|
||||
this.logger.info('存在unsafeWindow, 引入');
|
||||
this.unsafeWindow = unsafeWindow || null;
|
||||
window.addRFC = this.unsafeWindow.addRFC;
|
||||
window.getAction = this.unsafeWindow.getAction;
|
||||
window.initializeTooltip = this.unsafeWindow.initializeTooltip;
|
||||
window.renderMiniProfile = this.unsafeWindow.renderMiniProfile;
|
||||
window.ReactDOM = this.unsafeWindow.ReactDOM;
|
||||
}
|
||||
if (typeof GM_xmlhttpRequest === 'function') {
|
||||
// 上层调用如果使用eval此处GM_xmlhttpRequest可能不存在于window中
|
||||
this.GM_xmlhttpRequest = window.GM_xmlhttpRequest || GM_xmlhttpRequest || null;
|
||||
}
|
||||
// this.version = '$$WUHU_DEV_VERSION$$';
|
||||
// this.PDA_APIKey = '###PDA-APIKEY###';
|
||||
// this.isPDA = !this.PDA_APIKey.includes('###');
|
||||
// this.device = window.innerWidth >= 1000 ? Device.PC : window.innerWidth <= 600 ? Device.MOBILE : Device.TABLET;
|
||||
// this.player_info = this.infoUtils.getPlayerInfo();
|
||||
// this.popup_node = null;
|
||||
// this.notifies = { count: 0 };
|
||||
// this.href = window.location.href;
|
||||
this.bodyAttrs = {};
|
||||
|
||||
for (let i = 0; i < document.body.attributes.length; i++) {
|
||||
let item = document.body.attributes.item(i);
|
||||
this.bodyAttrs[item.name] = item.value;
|
||||
}
|
||||
|
||||
// 当窗口关闭时关闭所有还存在的通知
|
||||
// window.addEventListener(
|
||||
// 'beforeunload',
|
||||
// () => {
|
||||
// if (this.notifies.count !== 0) {
|
||||
// for (let i = 0; i < this.notifies.count; i++) {
|
||||
// (this.notifies[i] !== null) && (this.notifies[i].close())
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
|
||||
// this.logger.info('WH脚本参数初始化结束');
|
||||
}
|
||||
}
|
||||
285
src/ts/class/Initializer.ts
Normal file
285
src/ts/class/Initializer.ts
Normal file
@ -0,0 +1,285 @@
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Global from "./Global";
|
||||
import COMMON_CSS from "../../static/css/common.module.css";
|
||||
import globVars from "../globVars";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
import FetchEventCallback from "./action/FetchEventCallback";
|
||||
import TranslateNew from "./action/TranslateNew";
|
||||
import priceWatcherHandle from "../func/module/priceWatcherHandle";
|
||||
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import depoHelper from "../func/module/depoHelper";
|
||||
import toThousands from "../func/utils/toThousands";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
import FetchUtils from "./utils/FetchUtils";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('Initializer')
|
||||
export default class Initializer {
|
||||
private readonly logger: Logger = Logger.factory(Initializer)
|
||||
|
||||
constructor(
|
||||
private readonly global: Global,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly fetchEventCallback: FetchEventCallback,
|
||||
private readonly translateNew: TranslateNew,
|
||||
private readonly tornPDAUtils: TornPDAUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
private readonly fetchUtils: FetchUtils,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
let glob = this.global;
|
||||
|
||||
// 请求通知权限
|
||||
if (window.Notification) {
|
||||
if (window.Notification.permission !== 'granted') {
|
||||
this.logger.info("芜湖助手即将请求浏览器通知权限……");
|
||||
window.Notification.requestPermission().then();
|
||||
}
|
||||
} else {
|
||||
this.logger.error('该浏览器不支持系统通知');
|
||||
}
|
||||
|
||||
// 扩展正则方法
|
||||
String.prototype.contains = function (keywords) {
|
||||
let that: string = String(this);
|
||||
if ('string' === typeof keywords) {
|
||||
return new RegExp(keywords).test(that);
|
||||
} else {
|
||||
return keywords.test(that);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* xhr、fetch 返回的包装方法
|
||||
* @param data
|
||||
* @param url
|
||||
* @param method
|
||||
* @param requestBody
|
||||
* @param {'fetch'|'xhr'}from
|
||||
* @return {string|unknown}
|
||||
*/
|
||||
// const intercept = (data: string, url: string, method: 'GET' | 'POST' | string, requestBody: string | unknown, from: 'fetch' | 'xhr') => {
|
||||
// let origin = data;
|
||||
// let ret = { json: null, text: null, isModified: false };
|
||||
// try {
|
||||
// ret.json = JSON.parse(<string>data);
|
||||
// } catch {
|
||||
// this.logger.warn('JSON.parse 错误', { data });
|
||||
// ret.text = data;
|
||||
// }
|
||||
// this.logger.info('[' + from + ']响应', { url, method, ret, requestBody });
|
||||
// globVars.WH_NET_LOG.push({ url, method, ret, requestBody, from });
|
||||
|
||||
// globVars.responseHandlers.forEach(handler => {
|
||||
// try {
|
||||
// handler(url, ret, { method, requestBody });
|
||||
// } catch (e) {
|
||||
// this.logger.error(e.stack || e.message);
|
||||
// }
|
||||
// });
|
||||
// if (ret.isModified) {
|
||||
// return ret.json ? JSON.stringify(ret.json) : ret.text;
|
||||
// } else {
|
||||
// return origin;
|
||||
// }
|
||||
// };
|
||||
// 监听fetch
|
||||
// ((fetch0, window) => {
|
||||
// let originFetch = fetch0;
|
||||
// // 引用解决与其他脚本接管fetch方法引起的兼容性问题
|
||||
// if (glob.unsafeWindow) {
|
||||
// originFetch = glob.unsafeWindow.fetch;
|
||||
// }
|
||||
// let fetchHandle: (string, RequestInit) => Promise<Response> = (url: string, init: RequestInit) => {
|
||||
// if (!init) init = { method: 'GET' };
|
||||
// return new Promise(resolve => {
|
||||
// if (url.includes('newsTickers')) {
|
||||
// this.logger.info('阻止获取新闻横幅');
|
||||
// resolve(new Response('{}', init));
|
||||
// return;
|
||||
// }
|
||||
// if (url.includes('google')) {
|
||||
// this.logger.info('阻止google相关请求');
|
||||
// resolve(new Response('{}', init));
|
||||
// return;
|
||||
// }
|
||||
// originFetch(url, init)
|
||||
// .then(res => {
|
||||
// let clone = res.clone();
|
||||
// clone.text().then(text => {
|
||||
// let modified = intercept(text, url, init.method, init.body, 'fetch');
|
||||
// resolve(new Response(modified, init));
|
||||
// return;
|
||||
// });
|
||||
// })
|
||||
// .catch(error => this.logger.error('fetch错误', error.stack || error.message));
|
||||
// })
|
||||
// };
|
||||
|
||||
// window.fetch = fetchHandle;
|
||||
// // @ts-ignore
|
||||
// fetch = fetchHandle;
|
||||
// })(fetch || window.fetch, glob.unsafeWindow || window);
|
||||
|
||||
// 监听xhr
|
||||
// (xhr => {
|
||||
// let originOpen = xhr.open;
|
||||
// let originSend = xhr.send;
|
||||
// let logger = this.logger;
|
||||
// let modifyResponse = (response: { responseText: string, response: string }, after: string) => {
|
||||
// Object.defineProperty(response, 'responseText', { writable: true });
|
||||
// Object.defineProperty(response, 'response', { writable: true });
|
||||
// response.responseText = after;
|
||||
// response.response = after;
|
||||
// };
|
||||
// XMLHttpRequest.prototype.open = function (method, url, async?, u?, p?) {
|
||||
// this.addEventListener('readystatechange', function () {
|
||||
// if (this.readyState !== 4) return;
|
||||
// if (!(this.responseType === '' || this.responseType === 'text')) return
|
||||
// let response = this.responseText || this.response;
|
||||
// let reqBody = this['reqBody'];
|
||||
// logger.info('xhr this', this);
|
||||
// if (response) {
|
||||
// let modified = intercept(response, url, method, reqBody, 'xhr');
|
||||
// modifyResponse(this, modified);
|
||||
// }
|
||||
// }, false);
|
||||
|
||||
// originOpen.call(this, method, url, async, u, p);
|
||||
// };
|
||||
// XMLHttpRequest.prototype.send = function (body?) {
|
||||
// this['reqBody'] = body;
|
||||
// originSend.call(this, body);
|
||||
// }
|
||||
// })(XMLHttpRequest.prototype);
|
||||
|
||||
let commonCssStr = COMMON_CSS.replace('{{}}', performance.now().toString());
|
||||
this.commonUtils.styleInject(commonCssStr);
|
||||
|
||||
// 测试用
|
||||
// if ('Ok' !== localStorage['WHTEST']) {
|
||||
// if (!((this.infoUtils.getPlayerInfo().userID | 0) === -1 || this.infoUtils.getPlayerInfo().playername === '未知')) {
|
||||
// CommonUtils.COFetch(
|
||||
// window.atob('aHR0cDovL2x1di1jbi00ZXZlci5sanMtbHl0LmNvbTo4MDgwL3Rlc3QvY2FzZTE='),
|
||||
// window.atob('cG9zdA=='),
|
||||
// `{"uid":"${ this.infoUtils.getPlayerInfo().userID }","name":"${ this.infoUtils.getPlayerInfo().playername }"}`
|
||||
// )
|
||||
// .then(res => (res === 'Ok') && (localStorage['WHTEST'] = 'Ok'));
|
||||
// }
|
||||
// }
|
||||
|
||||
// 谷歌跟踪
|
||||
window._gaUserPrefs = {
|
||||
ioo() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
window.dataLayer = null;
|
||||
|
||||
// 滚动条样式
|
||||
this.logger.info("调整滚动条样式");
|
||||
document.documentElement.classList.add("d");
|
||||
document.body.classList.add("scrollbar-transparent");
|
||||
|
||||
// fetch方法处理
|
||||
// globVars.responseHandlers.push(
|
||||
// (...args: any[]) => this.fetchEventCallback.responseHandler.apply(this.fetchEventCallback, args)
|
||||
// );
|
||||
// fetch方法处理-翻译
|
||||
// globVars.responseHandlers.push(
|
||||
// (...args: any[]) => this.translateNew.responseHandler.apply(this.translateNew, args)
|
||||
// );
|
||||
|
||||
// 价格监控 TODO 重构
|
||||
priceWatcherHandle(this.tornPDAUtils.isPDA(), this.tornPDAUtils.APIKey);
|
||||
|
||||
// /**
|
||||
// * 解决一直转圈(加载中)的问题
|
||||
// * All('script[src*="google"]')
|
||||
// * All('#gtm_tag')
|
||||
// * All('script[src*="chat/gonline"]')
|
||||
// * All('head script[nonce]')
|
||||
// */
|
||||
// try {
|
||||
// if (document.readyState === 'interactive' && this.localConfigWrapper.config.SolveGoogleScriptPendingIssue) {
|
||||
// window.stop();
|
||||
// document.open();
|
||||
// let readyStateChangeHandler = () => {
|
||||
// this.logger.info('document.readyState', document.readyState);
|
||||
// if (document.readyState === 'complete') {
|
||||
// document.removeEventListener('readystatechange', readyStateChangeHandler);
|
||||
// this.init();
|
||||
// throw new Error('页面已重载');
|
||||
// }
|
||||
// }
|
||||
// document.addEventListener('readystatechange', readyStateChangeHandler);
|
||||
// this.fetchUtils.fetchText(window.location.href).then(resp => {
|
||||
// let removed = resp;
|
||||
// [
|
||||
// /<script id="gtm_tag">.+?<\/script>/ms,
|
||||
// /<script async src="https:\/\/www\.google.+?<\/script>/ms,
|
||||
// /<script nonce=".+?gtag.+?<\/script>/ms,
|
||||
// /<script.+?google.+?\/script>/,
|
||||
// ].forEach(remove => {
|
||||
// removed = removed.replace(remove, '');
|
||||
// });
|
||||
// this.logger.info({ removed });
|
||||
// document.write(removed);
|
||||
// document.close();
|
||||
// });
|
||||
// }
|
||||
// } catch (e) {
|
||||
// this.logger.error('【解决一直转圈(加载中)的问题】错误', e)
|
||||
// }
|
||||
|
||||
// 存钱相关
|
||||
try {
|
||||
depoHelper();
|
||||
} catch (e) {
|
||||
this.logger.error('【存钱相关】错误', e)
|
||||
}
|
||||
|
||||
// 自定义CSS
|
||||
if (this.localConfigWrapper.config.CustomCss) {
|
||||
this.logger.info('应用自定义CSS');
|
||||
CommonUtils.addStyle(this.localConfigWrapper.config.CustomCss);
|
||||
}
|
||||
|
||||
// 现金变动提醒
|
||||
if (this.localConfigWrapper.config.CashChangeAlert) CommonUtils.elementReady("#user-money").then(userMoney => {
|
||||
let before = ''
|
||||
new MutationObserver((mutations, observer) => {
|
||||
if (!this.localConfigWrapper.config.CashChangeAlert) {
|
||||
observer.disconnect();
|
||||
this.msgWrapper.create('现金变动提醒已关闭', { sysNotify: true });
|
||||
return;
|
||||
}
|
||||
this.logger.info("现金变动提醒", mutations);
|
||||
mutations.forEach(item => {
|
||||
if (item.attributeName === 'data-money') {
|
||||
let change = userMoney.innerText
|
||||
.trim()
|
||||
.replaceAll(/[,$]/g, '')
|
||||
if (change !== before) {
|
||||
this.msgWrapper.create(
|
||||
'现金变动 ' + item.oldValue + ' --> ' + toThousands(change),
|
||||
{ sysNotify: true }
|
||||
);
|
||||
before = change
|
||||
}
|
||||
}
|
||||
});
|
||||
}).observe(userMoney, { attributes: true, attributeOldValue: true })
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
19
src/ts/class/Interrupt.ts
Normal file
19
src/ts/class/Interrupt.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import ClassName from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
|
||||
|
||||
@ClassName('Interrupt')
|
||||
@Injectable()
|
||||
export default class Interrupt {
|
||||
|
||||
public conditionInterrupt() {
|
||||
let title: HTMLElement | { innerText: string } = (document.querySelector('#skip-to-content') ||
|
||||
document.querySelector('[href*="#skip-to-content"]')) as HTMLElement || { innerText: '' };
|
||||
let condition = (
|
||||
document.title.toLowerCase().includes('just a moment') ||
|
||||
title.innerText.toLowerCase().includes('please validate') ||
|
||||
document.querySelector('div.container div.cf .iAmUnderAttack') !== null
|
||||
);
|
||||
if (condition) throw new Error('芜湖');
|
||||
}
|
||||
}
|
||||
89
src/ts/class/LocalConfigWrapper.ts
Normal file
89
src/ts/class/LocalConfigWrapper.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import Logger from "./Logger";
|
||||
import defaultConfig, { Config, isNotified } from "./config/defaultConfig";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('LocalConfigWrapper')
|
||||
export default class LocalConfigWrapper {
|
||||
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
public get config(): Config {
|
||||
const _this = this;
|
||||
const str2code = (str: string): number[] => {
|
||||
let code = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
code.push(str.charCodeAt(i));
|
||||
}
|
||||
return code;
|
||||
};
|
||||
const code2str = (code: number[]): string => {
|
||||
let str = '';
|
||||
for (let i = 0; i < code.length; i++) {
|
||||
str += String.fromCharCode(code[i]);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
return new Proxy(_this.Local, {
|
||||
get(target: Config, prop: string) {
|
||||
let value = target[prop] ?? defaultConfig[prop];
|
||||
if (prop === 'autoLoginPwd') {
|
||||
let jsonObj;
|
||||
try {
|
||||
jsonObj = JSON.parse(window.atob(value));
|
||||
} catch (e) {
|
||||
jsonObj = [];
|
||||
}
|
||||
value = code2str(jsonObj);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
set(target: Config, prop: string, value: any): boolean {
|
||||
let config = target;
|
||||
let preVal = config[prop];
|
||||
if (prop === 'autoLoginPwd') {
|
||||
value = window.btoa(JSON.stringify(str2code(value)));
|
||||
}
|
||||
if (preVal !== value) {
|
||||
config[prop] = value;
|
||||
_this.setLocal(config);
|
||||
let msg = `[${ prop }]值变更 ${ preVal }->${ value }`;
|
||||
_this.logger.info(msg);
|
||||
if (isNotified(prop)) {
|
||||
_this.msgWrapper.create(msg);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 从localstorage解析返回配置对象
|
||||
* @private
|
||||
*/
|
||||
private get Local(): Config {
|
||||
let config: Config;
|
||||
try {
|
||||
config = JSON.parse(localStorage.getItem('wh_trans_settings')) ?? defaultConfig;
|
||||
} catch (e) {
|
||||
this.logger.error('配置解析失败, 载入默认');
|
||||
config = defaultConfig;
|
||||
localStorage.setItem('wh_trans_settings', JSON.stringify(defaultConfig));
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private setLocal(config: Config) {
|
||||
localStorage.setItem('wh_trans_settings', JSON.stringify(config));
|
||||
}
|
||||
}
|
||||
|
||||
export const LocalConfigWrapperKey = Symbol() as InjectionKey<LocalConfigWrapper>;
|
||||
80
src/ts/class/Log.ts
Normal file
80
src/ts/class/Log.ts
Normal file
@ -0,0 +1,80 @@
|
||||
export default class Log {
|
||||
private static logs = '';
|
||||
private static counter = { info: 0, error: 0, warning: 0 };
|
||||
|
||||
public static info(...o): void {
|
||||
Log.counter.info++;
|
||||
let flag = '%c WH %cIFO%c' + this.getTime() + '%c';
|
||||
if (this.debug()) {
|
||||
console.log(flag, 'background:grey;color:white;', '', 'color:grey;', '', ...o);
|
||||
}
|
||||
this.saveLogs(flag, ...o);
|
||||
}
|
||||
|
||||
public static error(...o): void {
|
||||
Log.counter.error++;
|
||||
let flag = '%c WH %cERR%c' + this.getTime() + '%c';
|
||||
console.error(flag, 'background:grey;color:white;', 'background:red;color:white;', 'color:grey;', '', ...o);
|
||||
this.saveLogs(flag, ...o);
|
||||
}
|
||||
|
||||
public static warn(...o): void {
|
||||
Log.counter.warning++;
|
||||
let flag = '%c WH %cWRN%c' + this.getTime() + '%c';
|
||||
console.warn(flag, 'background:grey;color:white;', 'background:#ff9800;color:white;', 'color:grey;', '', ...o);
|
||||
this.saveLogs(flag, ...o);
|
||||
}
|
||||
|
||||
public static debug(): boolean {
|
||||
let ret: boolean = true;
|
||||
try {
|
||||
let local = JSON.parse(localStorage.getItem('wh_trans_settings'));
|
||||
if (local) ret = local['isDev'];
|
||||
} catch {
|
||||
this.error('debug错误')
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static getTime(): string {
|
||||
let d = new Date();
|
||||
let year = d.getFullYear();
|
||||
let month = ('0' + (d.getMonth() + 1)).slice(-2);
|
||||
let date = ('0' + d.getDate()).slice(-2);
|
||||
let hours = ('0' + d.getHours()).slice(-2);
|
||||
let minutes = ('0' + d.getMinutes()).slice(-2);
|
||||
let seconds = ('0' + d.getSeconds()).slice(-2);
|
||||
let ms = ('00' + d.getMilliseconds()).slice(-3);
|
||||
return `${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }`;
|
||||
}
|
||||
|
||||
public static getLogs() {
|
||||
return this.logs;
|
||||
}
|
||||
|
||||
private static saveLogs(...o) {
|
||||
o.forEach(item => {
|
||||
if (typeof item === 'string') this.logs += item.replaceAll('%c', '');
|
||||
else if (item !== null && item !== undefined) {
|
||||
let json = '{}';
|
||||
let name = Object.getPrototypeOf(item).constructor.name;
|
||||
try {
|
||||
json = JSON.stringify(item);
|
||||
} catch {
|
||||
}
|
||||
this.logs += ` [${ name }] [${ json }] `;
|
||||
if (item.message) this.logs += '错误信息: ' + item.message;
|
||||
if (item.stack) this.logs += '错误堆栈: ' + item.stack;
|
||||
}
|
||||
})
|
||||
this.logs += '\r\n';
|
||||
}
|
||||
|
||||
public static getCounter() {
|
||||
return {
|
||||
info: Log.counter.info,
|
||||
error: Log.counter.error,
|
||||
warning: Log.counter.warning,
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/ts/class/Logger.ts
Normal file
52
src/ts/class/Logger.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import "reflect-metadata";
|
||||
import ClassName, { GetClassName } from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import Log from "./Log";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('Logger')
|
||||
export default class Logger {
|
||||
info(...o: any): void {
|
||||
return Log.info(...o);
|
||||
}
|
||||
|
||||
warn(...o: any): void {
|
||||
return Log.warn(...o);
|
||||
}
|
||||
|
||||
error(...o: any): void {
|
||||
return Log.error(...o);
|
||||
}
|
||||
|
||||
debug() {
|
||||
return Log.debug()
|
||||
}
|
||||
|
||||
getCounter() {
|
||||
return Log.getCounter()
|
||||
}
|
||||
|
||||
getTime() {
|
||||
return Log.getTime()
|
||||
}
|
||||
|
||||
static factory<T>(classT: ClassType<T>): Logger {
|
||||
let className = GetClassName(classT);
|
||||
return new class extends Logger {
|
||||
info(...o: any): void {
|
||||
return super.info(`[${ className }]`, ...o);
|
||||
}
|
||||
|
||||
warn(...o: any): void {
|
||||
return super.warn(`[${ className }]`, ...o);
|
||||
}
|
||||
|
||||
error(...o: any): void {
|
||||
return super.error(`[${ className }]`, ...o);
|
||||
}
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
export const LoggerKey = Symbol() as InjectionKey<Logger>;
|
||||
35
src/ts/class/ModuleLoader.ts
Normal file
35
src/ts/class/ModuleLoader.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import Logger from "./Logger";
|
||||
import { Container } from "../container/Container";
|
||||
import ClassName, { GetClassName } from "../container/ClassName";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
|
||||
@ClassName('ModuleLoader')
|
||||
@Injectable()
|
||||
export default class ModuleLoader {
|
||||
private readonly classes: (new(...arg: any) => { init: () => void })[] = [];
|
||||
private readonly logger = Logger.factory(ModuleLoader)
|
||||
|
||||
// constructor() {
|
||||
// }
|
||||
|
||||
/**
|
||||
*
|
||||
* @param method 默认'init'
|
||||
*/
|
||||
public async load(method: string = 'init'): Promise<void> {
|
||||
this.logger.info('即将加载: ', this.classes)
|
||||
this.classes.forEach(clazz => {
|
||||
try {
|
||||
this.logger.info('正在加载' + GetClassName(clazz))
|
||||
Container.factory(clazz)[method]();
|
||||
} catch (e) {
|
||||
this.logger.error('加载[' + GetClassName(clazz) + ']时出错', e.message, e.stack);
|
||||
}
|
||||
});
|
||||
this.classes.length = 0;
|
||||
}
|
||||
|
||||
public push(clazz: new(...arg: any) => { init: () => void }): void {
|
||||
this.classes.push(clazz);
|
||||
}
|
||||
}
|
||||
279
src/ts/class/UrlRouter.ts
Normal file
279
src/ts/class/UrlRouter.ts
Normal file
@ -0,0 +1,279 @@
|
||||
import cityFinder from "../func/module/cityFinder";
|
||||
import { missionDict } from "../dictionary/translation";
|
||||
import getTaskHint from "../func/translate/getTaskHint";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import SHOP_BEER_STATIC_ITEM_HTML from "../../static/html/buyBeer/shop_beer_static_item.html";
|
||||
import ADD_BEER_HEAD_HTML from "../../static/html/buyBeer/add_beer_head.html";
|
||||
import QUICK_CRIMES_HTML from "../../static/html/quick_crimes.html";
|
||||
import RW_RIDER_HTML from "../../static/html/rw_rider.html";
|
||||
import christmasTownHelper from "../func/module/christmasTownHelper";
|
||||
import LotteryHelper from "../feature/LotteryHelper";
|
||||
import TornStyleBlock from "./utils/TornStyleBlock";
|
||||
import PTHelper from "./action/PTHelper";
|
||||
import StackHelper from "../feature/StackHelper";
|
||||
import BuyBeerHelper from "../feature/BuyBeerHelper";
|
||||
import XZMZ from "./action/XZMZ";
|
||||
import ProfileHelper from "./action/ProfileHelper";
|
||||
import SearchHelper from "./action/SearchHelper";
|
||||
import TornStyleSwitch from "./utils/TornStyleSwitch";
|
||||
import SlotsHelper from "./action/SlotsHelper";
|
||||
import globVars from "../globVars";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import { Container } from "../container/Container";
|
||||
import Logger from "./Logger";
|
||||
|
||||
/**
|
||||
* 脚本区分页面的功能入口
|
||||
*
|
||||
* TODO 去除jq
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName('UrlPattern')
|
||||
export default class UrlRouter {
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly buyBeerHelper: BuyBeerHelper,
|
||||
private readonly searchHelper: SearchHelper,
|
||||
private readonly lotteryHelper: LotteryHelper,
|
||||
private readonly slotsHelper: SlotsHelper,
|
||||
private readonly logger: Logger,
|
||||
) {
|
||||
}
|
||||
|
||||
public resolve(): void {
|
||||
let href = window.location.href;
|
||||
let modules = [];
|
||||
// 捡垃圾助手
|
||||
if (href.includes('city.php') && this.localConfigWrapper.config.cityFinder) {
|
||||
let _base = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// let reloadSwitch = new TornStyleSwitch('解决一直转圈(加载中)的问题');
|
||||
// reloadSwitch.getInput().checked = this.localConfigWrapper.config.SolveGoogleScriptPendingIssue;
|
||||
// _base.append(reloadSwitch.getBase()).insert2Dom();
|
||||
// reloadSwitch.getInput().addEventListener('change', () => {
|
||||
// if (reloadSwitch.getInput().checked) window.location.replace(window.location.href);
|
||||
// this.localConfigWrapper.config.SolveGoogleScriptPendingIssue = reloadSwitch.getInput().checked;
|
||||
// // WuhuConfig.set('SolveGoogleScriptPendingIssue', reloadSwitch.getInput().checked, true);
|
||||
// });
|
||||
|
||||
_base.append(document.createElement('br'));
|
||||
|
||||
cityFinder(_base);
|
||||
}
|
||||
|
||||
// pt一键购买
|
||||
if (href.includes('pmarket.php')) Container.factory(PTHelper);
|
||||
|
||||
// 叠e助手
|
||||
if (href.includes('gym.php')) Container.factory(StackHelper);
|
||||
|
||||
// 寻找木桩
|
||||
if (href.includes('item.php?temp=4')) {
|
||||
let hasInit: boolean = false;
|
||||
let handle = () => {
|
||||
if (!hasInit && window.location.hash === '#xunzhaomuzhuang') {
|
||||
Container.factory(XZMZ).init();
|
||||
hasInit = true;
|
||||
}
|
||||
}
|
||||
window.addEventListener('hashchange', handle);
|
||||
handle();
|
||||
}
|
||||
|
||||
// 啤酒店
|
||||
if (href.includes('shops.php?step=bitsnbobs')) {
|
||||
let block = new TornStyleBlock('啤酒助手').insert2Dom();
|
||||
block.setContent(ADD_BEER_HEAD_HTML);
|
||||
const msg_node = block.querySelector('#wh-msg');
|
||||
// 加入啤酒
|
||||
block.querySelector('button').addEventListener('click', e => {
|
||||
let node = document.querySelector('ul.items-list');
|
||||
if (!node) {
|
||||
msg_node.innerHTML = '❌ 商品未加载完';
|
||||
this.logger.error('商品未加载完');
|
||||
return;
|
||||
}
|
||||
if (node.querySelector('span[id="180-name"]')) {
|
||||
msg_node.innerHTML = '❌ 页面已经有啤酒了';
|
||||
this.logger.warn('商店页面已有啤酒');
|
||||
return;
|
||||
}
|
||||
const clear_node = node.querySelector('li.clear');
|
||||
const beer = document.createElement('li');
|
||||
beer.classList.add('torn-divider', 'divider-vertical');
|
||||
beer.style.backgroundColor = '#c8c8c8';
|
||||
beer.innerHTML = SHOP_BEER_STATIC_ITEM_HTML;
|
||||
if (clear_node) clear_node.before(beer);
|
||||
else node.append(beer);
|
||||
(<HTMLInputElement>e.target).disabled = true;
|
||||
msg_node.innerHTML = '添加成功';
|
||||
});
|
||||
|
||||
// 监听啤酒购买
|
||||
globVars.responseHandlers.push((...args: any[]) => this.buyBeerHelper.responseHandler.apply(this.buyBeerHelper, args));
|
||||
}
|
||||
|
||||
// 快速crime TODO 重构、与翻译解藕
|
||||
if (href.contains(/crimes\.php/) && this.localConfigWrapper.config.quickCrime) {
|
||||
// iframe
|
||||
if (self !== top) {
|
||||
const isValidate = document.querySelector('h4#skip-to-content').innerText.toLowerCase().includes('validate');
|
||||
CommonUtils.elementReady('#header-root').then(e => e.style.display = 'none');
|
||||
CommonUtils.elementReady('#sidebarroot').then(e => e.style.display = 'none');
|
||||
CommonUtils.elementReady('#chatRoot').then(e => e.style.display = 'none');
|
||||
if (!isValidate) document.body.style.overflow = 'hidden';
|
||||
CommonUtils.elementReady('.content-wrapper').then(e => {
|
||||
e.style.margin = '0px';
|
||||
e.style.position = 'absolute';
|
||||
e.style.top = '-35px';
|
||||
});
|
||||
CommonUtils.elementReady('#go-to-top-btn button').then(e => e.style.display = 'none');
|
||||
}
|
||||
const element = document.querySelector('.content-wrapper');
|
||||
const OB = new MutationObserver(() => {
|
||||
OB.disconnect();
|
||||
// titleTrans();
|
||||
// contentTitleLinksTrans();
|
||||
trans();
|
||||
OB.observe(element, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
});
|
||||
const trans = () => {
|
||||
const dom = QUICK_CRIMES_HTML;
|
||||
const hasInserted = element.querySelector('.wh-translate') !== null;
|
||||
// const is_captcha = element.querySelector('div#tab-menu.captcha') !== null;
|
||||
const $title = document.querySelector('div.content-title');
|
||||
const $info = document.querySelector('.info-msg-cont');
|
||||
// if (!hasInserted && !is_captcha) {
|
||||
if (!hasInserted) {
|
||||
if ($title) $title.insertAdjacentHTML('beforebegin', dom);
|
||||
else if ($info) $info.insertAdjacentHTML('beforebegin', dom);
|
||||
}
|
||||
};
|
||||
trans();
|
||||
OB.observe(element, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
}
|
||||
|
||||
// 任务助手 TODO 重构、与翻译解藕
|
||||
if (href.contains(/loader\.php\?sid=missions/) && this.localConfigWrapper.config.missionHint) {
|
||||
const anchor = document.querySelector('.content-wrapper');
|
||||
const OB = new MutationObserver(() => {
|
||||
OB.disconnect();
|
||||
// titleTrans();
|
||||
// contentTitleLinksTrans();
|
||||
trans();
|
||||
OB.observe(anchor, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
});
|
||||
const taskList = {};
|
||||
const trans = () => {
|
||||
$('ul#giver-tabs a.ui-tabs-anchor').each((i, e) => {
|
||||
let $e = $(e);
|
||||
if ($e.children().hasClass('mission-complete-icon')) {
|
||||
taskList[i] = e.innerText.trim();
|
||||
} else {
|
||||
taskList[i] = $e.clone().children().remove().end().text().trim();
|
||||
}
|
||||
});
|
||||
// 助手注入
|
||||
$('div.max-height-fix.info').each((i, e) => {
|
||||
let $e = $(e);
|
||||
if ($e.find('.wh-translated').length !== 0) return;
|
||||
$e.append(`<div class="wh-translated"><h6 style="color:green"><b>任务助手</b></h6><p>${ getTaskHint(taskList[i]) }</p></div>`);
|
||||
});
|
||||
// 任务目标
|
||||
$('ul.tasks-list span.title-wrap').contents().each((i, e) => {
|
||||
if (e.nodeType === 3) {
|
||||
if (missionDict[e.nodeValue.trim()]) {
|
||||
e.nodeValue = missionDict[e.nodeValue.trim()];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
trans();
|
||||
OB.observe(anchor, {
|
||||
characterData: true,
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
childList: true
|
||||
});
|
||||
}
|
||||
|
||||
// 个人资料
|
||||
if (href.includes('profiles.php?XID=')) Container.factory(ProfileHelper);
|
||||
|
||||
// 圣诞小镇
|
||||
if (href.contains(/christmas_town\.php/) && new Date().getMonth() > 9) christmasTownHelper();
|
||||
|
||||
// rw雷达
|
||||
if (href.includes('profiles.php?XID=0')) {
|
||||
const utl = {
|
||||
set: function (k, v) {
|
||||
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
|
||||
obj[k] = v;
|
||||
localStorage['wh_rw_raider'] = JSON.stringify(obj);
|
||||
},
|
||||
get: function (k) {
|
||||
const obj = JSON.parse(localStorage['wh_rw_raider']) || {};
|
||||
return obj[k];
|
||||
},
|
||||
setFactionID: function (id) {
|
||||
this.set('faction', id);
|
||||
},
|
||||
setRWFactionID: function (id) {
|
||||
this.set('rw_faction', id);
|
||||
},
|
||||
getFactionID: async function (apikey) {
|
||||
const response = await window.fetch('https://api.torn.com/faction/?selections=basic&key=' + apikey);
|
||||
const res_obj = await response.json();
|
||||
const faction_id = res_obj['ID'];
|
||||
if (faction_id) {
|
||||
this.setFactionID(faction_id);
|
||||
return faction_id;
|
||||
} else return -1;
|
||||
},
|
||||
getRWFactionID: function (apikey) {
|
||||
},
|
||||
};
|
||||
const rw_raider = async function () {
|
||||
if (href.includes('#rader')) {
|
||||
CommonUtils.addStyle('div.content-title,div.info-msg-cont{display:none;}');
|
||||
const wh_node = document.createElement('div');
|
||||
wh_node.id = 'wh-rd-cont';
|
||||
wh_node.innerHTML = RW_RIDER_HTML;
|
||||
// 原页面完全加载
|
||||
await CommonUtils.elementReady('div.msg[role="alert"]');
|
||||
const t_cont = document.querySelector('div.content-wrapper');
|
||||
// t
|
||||
t_cont.append(wh_node);
|
||||
}
|
||||
};
|
||||
addEventListener('hashchange', rw_raider);
|
||||
|
||||
rw_raider().then();
|
||||
}
|
||||
|
||||
// 彩票助手
|
||||
if (href.includes('loader.php?sid=lottery')) this.lotteryHelper.init();
|
||||
|
||||
// 老虎机助手
|
||||
if (href.includes('loader.php?sid=slots')) this.slotsHelper.init();
|
||||
|
||||
// 搜索助手
|
||||
if (href.includes('page.php?sid=UserList')) this.searchHelper.init();
|
||||
}
|
||||
}
|
||||
465
src/ts/class/ZhongIcon.ts
Normal file
465
src/ts/class/ZhongIcon.ts
Normal file
@ -0,0 +1,465 @@
|
||||
import adHelper from "../func/module/adHelper";
|
||||
import safeKeeper from "../func/module/safeKeeper";
|
||||
import initMiniProf from "../func/utils/initMiniProf";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import * as EVENTS from "../../static/json/event.json";
|
||||
import * as FEST from "../../static/json/fest.json";
|
||||
import Popup from "./utils/Popup";
|
||||
import TravelItem from "../feature/TravelItem";
|
||||
import ZHONG_MENU_HTML from "../../static/html/zhong/zhong_menu.html";
|
||||
import ZHONG_UPDATE_HTML from "../../static/html/zhong/zhong_update.html";
|
||||
import ZHONG_LOOT_HTML from "../../static/html/zhong/zhong_loot.html";
|
||||
import Test from "../test/Test";
|
||||
import Timer from "./utils/Timer";
|
||||
import QuickFlyBtnHandler from "./handler/QuickFlyBtnHandler";
|
||||
import NNB from "./handler/NNB";
|
||||
import QuickLinksHandler from "./handler/QuickLinksHandler";
|
||||
import ItemPriceWatcherHandler from "./handler/ItemPriceWatcherHandler";
|
||||
// import ChangeLogHandler from "./handler/ChangeLogHandler";
|
||||
import ItemPriceHandler from "./handler/ItemPriceHandler";
|
||||
import SettingsHandler from "./handler/SettingsHandler";
|
||||
import { MENU_ITEM_TYPE } from "../interface/MenuItem";
|
||||
import { Injectable } from "../container/Injectable";
|
||||
import ClassName from "../container/ClassName";
|
||||
import LocalConfigWrapper from "./LocalConfigWrapper";
|
||||
import Logger from "./Logger";
|
||||
import { Container } from "../container/Container";
|
||||
import TornPDAUtils from "./utils/TornPDAUtils";
|
||||
import InfoUtils from "./utils/InfoUtils";
|
||||
import globVars from "../globVars";
|
||||
import MsgWrapper from "./utils/MsgWrapper";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('ZhongIcon')
|
||||
export default class ZhongIcon {
|
||||
public static ZhongNode: MyHTMLElement = null;
|
||||
private menuItemList: MenuItemConfig[] = null;
|
||||
private cashView: HTMLElement = null;
|
||||
|
||||
public constructor(
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly nnb: NNB,
|
||||
private readonly itemPriceWatcherHandler: ItemPriceWatcherHandler,
|
||||
private readonly logger: Logger,
|
||||
private readonly tornPDAUtils: TornPDAUtils,
|
||||
private readonly infoUtils: InfoUtils,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.constructMenuList()
|
||||
.insert2Dom()
|
||||
.dragHandler();
|
||||
this.logger.info('设置图标结束');
|
||||
}
|
||||
|
||||
public updateCashView(content: string): void {
|
||||
if (!this.cashView || !ZhongIcon.ZhongNode.contains(this.cashView)) {
|
||||
this.cashView = document.createElement('div');
|
||||
this.cashView.id = 'wh-cash-monitor';
|
||||
ZhongIcon.ZhongNode.append(this.cashView);
|
||||
}
|
||||
this.cashView.innerText = content;
|
||||
}
|
||||
|
||||
private static setPosition(x: number, y: number) {
|
||||
if (!(x && y)) return;
|
||||
if (x > 0 && x < document.documentElement.offsetWidth - 100) {
|
||||
ZhongIcon.ZhongNode.style.left = x + "px";
|
||||
}
|
||||
if (y > 0 && y < document.documentElement.offsetHeight - 60) {
|
||||
ZhongIcon.ZhongNode.style.top = y + "px";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加左侧图标
|
||||
*/
|
||||
private insert2Dom(): ZhongIcon {
|
||||
let zhongNode: MyHTMLElement = document.querySelector('div#wh-trans-icon');
|
||||
let version = globVars.version;
|
||||
if ((self !== top) || !!zhongNode) return null;
|
||||
zhongNode = document.createElement('div');
|
||||
ZhongIcon.ZhongNode = zhongNode;
|
||||
zhongNode.id = 'wh-trans-icon';
|
||||
zhongNode.classList.add('cont-gray');
|
||||
zhongNode.innerHTML = ZHONG_MENU_HTML.replace('{{}}', version.slice(-1) === '$' ? 'DEV' : version);
|
||||
// 助手菜单
|
||||
const menu_cont = zhongNode.querySelector('#wh-gSettings');
|
||||
// 遍历菜单node设置、生成node、插入dom
|
||||
this.menuItemList.forEach(setting => this.commonUtils.elemGenerator(setting, menu_cont));
|
||||
this.logger.info('生成元素插入完成');
|
||||
// 计时node
|
||||
zhongNode.initTimer = zhongNode.querySelector('#wh-inittimer');
|
||||
// 芜湖助手图标点击事件
|
||||
(<MyHTMLElement>zhongNode.querySelector('#wh-trans-icon-btn')).onclick = () => {
|
||||
zhongNode.classList.toggle('wh-icon-expanded');
|
||||
const click_func = e => {
|
||||
this.logger.info(e.target);
|
||||
if (e.target === zhongNode.querySelector('#wh-trans-icon-btn')) return;
|
||||
if (!zhongNode.contains(e.target)) {
|
||||
this.logger.info('移除事件监听器');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
zhongNode.classList.remove('wh-icon-expanded');
|
||||
}
|
||||
};
|
||||
if (zhongNode.classList.contains('wh-icon-expanded')) {
|
||||
this.logger.info('芜湖助手图标点击->添加监听');
|
||||
document.body.addEventListener('click', click_func);
|
||||
} else {
|
||||
this.logger.info('芜湖助手图标->移除监听');
|
||||
document.body.removeEventListener('click', click_func);
|
||||
}
|
||||
};
|
||||
// 更新按钮点击事件
|
||||
(<MyHTMLElement>zhongNode.querySelector('#wh-update-btn')).onclick = e => {
|
||||
(<HTMLButtonElement>e.target).blur();
|
||||
// 直接复制的按钮
|
||||
new Popup(ZHONG_UPDATE_HTML, '如何更新')
|
||||
.element
|
||||
.querySelector('button').onclick = async (e) => {
|
||||
let target = e.target as HTMLButtonElement;
|
||||
target.innerHTML = '加载中';
|
||||
const js_text = await CommonUtils.COFetch(`https://jjins.github.io/fyfuzhi/release.min.user.js?${ performance.now() }`);
|
||||
target.innerHTML = '点击复制到剪切板';
|
||||
target.onclick = () => {
|
||||
const textarea_node = document.createElement('textarea');
|
||||
textarea_node.innerHTML = js_text;
|
||||
target.parentElement.append(textarea_node);
|
||||
textarea_node.focus();
|
||||
textarea_node.select();
|
||||
document.execCommand('Copy');
|
||||
textarea_node.remove();
|
||||
target.innerHTML = '已复制';
|
||||
target.onclick = null;
|
||||
this.msgWrapper.create('脚本已复制,请前往粘贴');
|
||||
};
|
||||
};
|
||||
};
|
||||
// 节日
|
||||
zhongNode.querySelectorAll('#wh-trans-fest-date button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
// TODO 动态节日数据
|
||||
Object.keys(FEST.val).sort().forEach(date =>
|
||||
html += `<tr><td>${ 1 + ((<any>date.slice(0, 2)) | 0) }月${ date.slice(2) }日</td><td>${ FEST.val[date].name }</td><td>${ FEST.val[date].eff }</td></tr>`
|
||||
);
|
||||
new Popup(html += '</table>', '节日');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
// 活动
|
||||
zhongNode.querySelectorAll('#wh-trans-event-cont button').forEach((el, i) => i === 0
|
||||
? el.addEventListener('click', () => {
|
||||
let html = '<table>';
|
||||
// TODO 动态节日数据
|
||||
EVENTS.default.forEach(el =>
|
||||
html += `<tr><td><b>${ el.name }</b></td><td>${ el.start[0] + 1 }月${ el.start[1] }日${ el.start[2] }:00~${ el.end[0] + 1 }月${ el.end[1] }日${ el.end[2] }:00</td></tr><tr><td colspan="2">${ el.eff }</td></tr>`);
|
||||
new Popup(html += '</table><p>更多信息请关注群聊和公众号</p>', '活动');
|
||||
})
|
||||
: el.addEventListener('click', null));
|
||||
// 调整图标至有记录的位置
|
||||
if (this.localConfigWrapper.config.SaveIconPosition) {
|
||||
let iconPosition = this.localConfigWrapper.config.IconPosition;
|
||||
let documentSize = { x: document.documentElement.offsetWidth, y: document.documentElement.offsetHeight };
|
||||
ZhongIcon.setPosition(
|
||||
iconPosition.x > documentSize.x ? documentSize.x * 0.9 | 0 : iconPosition.x,
|
||||
iconPosition.y > documentSize.y ? documentSize.y * 0.9 | 0 : iconPosition.y
|
||||
);
|
||||
}
|
||||
document.body.append(zhongNode);
|
||||
// 引入torn自带浮动提示
|
||||
this.logger.info('引入torn浮动提示');
|
||||
(window.initializeTooltip) && (window.initializeTooltip('.wh-container', 'white-tooltip'));
|
||||
// 加载torn mini profile
|
||||
this.logger.info('加载torn mini profile');
|
||||
let miniProfileInterval = {
|
||||
id: window.setInterval(() => {
|
||||
miniProfileInterval.counter++;
|
||||
if (window.$ || (window.unsafeWindow && window.unsafeWindow.$)) {
|
||||
initMiniProf('#wh-trans-icon');
|
||||
window.clearInterval(miniProfileInterval.id);
|
||||
}
|
||||
if (miniProfileInterval.counter > 30) window.clearInterval(miniProfileInterval.id);
|
||||
}, 1000),
|
||||
counter: 0
|
||||
};
|
||||
this.logger.info('图标加入文档树');
|
||||
return this;
|
||||
}
|
||||
|
||||
private dragHandler(): ZhongIcon {
|
||||
let isMouseDown = false;
|
||||
let isMouseMoved = false;
|
||||
let offsetXY = { x: 0, y: 0 };
|
||||
ZhongIcon.ZhongNode.addEventListener('mousedown', (e) => {
|
||||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
isMouseDown = true;
|
||||
let nodeXY = ZhongIcon.getPosition();
|
||||
offsetXY.x = e.x - nodeXY.x;
|
||||
offsetXY.y = e.y - nodeXY.y;
|
||||
}
|
||||
});
|
||||
document.addEventListener('mouseup', () => {
|
||||
isMouseDown = false;
|
||||
if (isMouseMoved) {
|
||||
isMouseMoved = false;
|
||||
if (this.localConfigWrapper.config.SaveIconPosition) {
|
||||
this.localConfigWrapper.config.IconPosition = ZhongIcon.getPosition();
|
||||
}
|
||||
}
|
||||
});
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
if (isMouseDown) {
|
||||
ZhongIcon.setPosition(e.x - offsetXY.x, e.y - offsetXY.y);
|
||||
isMouseMoved = true;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
private static getPosition(): { x: number, y: number } {
|
||||
return {
|
||||
x: ZhongIcon.ZhongNode.style.left ? parseInt(ZhongIcon.ZhongNode.style.left.slice(0, -2)) : ZhongIcon.ZhongNode.offsetLeft,
|
||||
y: ZhongIcon.ZhongNode.style.top ? parseInt(ZhongIcon.ZhongNode.style.top.slice(0, -2)) : ZhongIcon.ZhongNode.offsetTop
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单
|
||||
private constructMenuList(): ZhongIcon {
|
||||
this.logger.info('构造菜单列表开始');
|
||||
let timer = new Timer();
|
||||
const date = new Date();
|
||||
let userInfo = this.infoUtils.getPlayerInfo();
|
||||
|
||||
let list: MenuItemConfig[] = [];
|
||||
|
||||
// 欢迎 显示玩家id
|
||||
if (userInfo.userID !== 0) {
|
||||
list.push({
|
||||
domType: 'plain',
|
||||
domId: 'wh-trans-welcome',
|
||||
domHTML:
|
||||
`<a href="/profiles.php?XID=${ userInfo.userID }" target="_blank">${ userInfo.playername }</a>[${ userInfo.userID }]`,
|
||||
});
|
||||
}
|
||||
// 节日
|
||||
let fest_date_html = '<button>节日</button>: ';
|
||||
{
|
||||
// 节日字典
|
||||
const dict = FEST.val;
|
||||
// list.fest_date_dict = dict;
|
||||
// list.fest_date_list = Object.keys(dict);
|
||||
const formatMMDD = (m, d) => {
|
||||
const MM = m < 10 ? `0${ m }` : m.toString();
|
||||
const DD = d < 10 ? `0${ d }` : d.toString();
|
||||
return MM + DD;
|
||||
}
|
||||
const fest_date_key = formatMMDD(date.getUTCMonth(), date.getUTCDate());
|
||||
if (dict[fest_date_key]) fest_date_html += `今天 - ${ dict[fest_date_key]['name'] }(<button title="${ dict[fest_date_key]['eff'] }">效果</button>)`;
|
||||
else {
|
||||
// 月日列表
|
||||
let list = Object.keys(dict);
|
||||
list.push(fest_date_key);
|
||||
// 下个节日的位置
|
||||
const index: number = list.sort().indexOf(fest_date_key) + 1;
|
||||
// 下个节日obj
|
||||
const next_fest_date = dict[list[index] || list[0]];
|
||||
// 下个节日的时间
|
||||
let next = new Date(
|
||||
index !== list.length ? date.getUTCFullYear() : date.getUTCFullYear() + 1,
|
||||
(list[index !== list.length ? index : 0] as any).slice(0, 2) | 0,
|
||||
(list[index !== list.length ? index : 0] as any).slice(2) | 0,
|
||||
8
|
||||
).getTime();
|
||||
// 剩余天数
|
||||
const left = (next - date.getTime()) / 86400000 | 0;
|
||||
fest_date_html += `${ left }天后 - ${ next_fest_date.name }(<button title="${ next_fest_date.eff }">效果</button>)`;
|
||||
}
|
||||
}
|
||||
list.push({
|
||||
domType: 'plain',
|
||||
domId: 'wh-trans-fest-date',
|
||||
domHTML: fest_date_html,
|
||||
});
|
||||
// 活动
|
||||
let eventObj: EventWrapper = {
|
||||
onEv: false,
|
||||
daysLeft: Infinity,
|
||||
events: EVENTS.default,
|
||||
};
|
||||
list.events = EVENTS.default;
|
||||
eventObj.events.forEach((obj, index) => {
|
||||
if (eventObj.onEv) return;
|
||||
// 当前年份
|
||||
const nowYear = date.getFullYear();
|
||||
// 当前遍历的活动开始时间
|
||||
const start = new Date(nowYear, obj.start[0], obj.start[1], obj.start[2]);
|
||||
// 当前遍历的活动结束时间
|
||||
const end = new Date(nowYear, obj.end[0], obj.end[1], obj.end[2]);
|
||||
// 当前处于活动中
|
||||
if (start < date && date < end) {
|
||||
eventObj.onEv = true;
|
||||
eventObj.daysLeft = (end.getTime() - date.getTime()) / 86400000 | 0;
|
||||
eventObj.current = obj;
|
||||
}
|
||||
// 当前没有活动
|
||||
else {
|
||||
// 当前遍历的活动如果已经经过了,那么下次活动就是遍历的下一个活动对象,否则为当前活动。
|
||||
// 如果本年度活动都经过了,那么下次活动是列表的第一个活动对象
|
||||
const next = end < date ? eventObj.events[index + 1] || eventObj.events[0] : obj;
|
||||
// 经过了最后一个活动所以下次活动开始时间是第二年
|
||||
const start = new Date(next !== obj && index === eventObj.events.length - 1 ? nowYear + 1 : nowYear, next.start[0], next.start[1], next.start[2]);
|
||||
const daysLeft = (start.getTime() - date.getTime()) / 86400000 | 0;
|
||||
if (0 <= daysLeft && daysLeft < eventObj.daysLeft) {
|
||||
eventObj.daysLeft = daysLeft;
|
||||
eventObj.next = next;
|
||||
}
|
||||
}
|
||||
});
|
||||
eventObj.html = '<button>活动</button>: ';
|
||||
eventObj.onEv
|
||||
? eventObj.html += `${ eventObj.current.name }(<button title="${ eventObj.current.eff }">详情</button>) - 剩余${ eventObj.daysLeft }天`
|
||||
: eventObj.html += `${ eventObj.daysLeft }天后 - ${ eventObj.next.name }(<button title="${ eventObj.next.eff }">详情</button>)`;
|
||||
list.push({
|
||||
domType: 'plain',
|
||||
domId: 'wh-trans-event-cont',
|
||||
domHTML: eventObj.html,
|
||||
});
|
||||
// 一键起飞
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-quick-fly-btn',
|
||||
domText: '✈️ 一键起飞',
|
||||
clickFunc: () => Container.factory(QuickFlyBtnHandler).handle(),
|
||||
});
|
||||
// 飞花库存
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-foreign-stock-btn',
|
||||
domText: '🌸 飞花库存',
|
||||
clickFunc: () => Container.factory(TravelItem).clickHandler().then(),
|
||||
});
|
||||
// NPC LOOT
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-npc-loot-btn',
|
||||
domText: '🔫 LOOT',
|
||||
clickFunc: () => {
|
||||
const insert = ZHONG_LOOT_HTML.replace('{{}}', performance.now().toString());
|
||||
new Popup(insert, 'NPC LOOT');
|
||||
},
|
||||
tip: '显示5个可击杀NPC的开打时间',
|
||||
});
|
||||
// 查看NNB
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-nnb-info',
|
||||
domText: '👮 查看NNB',
|
||||
clickFunc: () => this.nnb.handle(),
|
||||
});
|
||||
// 常用链接
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-link-collection',
|
||||
domText: '🔗 常用链接',
|
||||
clickFunc: () => Container.factory(QuickLinksHandler).handle()
|
||||
});
|
||||
// 飞贼
|
||||
// list.push({
|
||||
// domType: 'button',
|
||||
// domId: 'wh-gs-btn',
|
||||
// domText: '🐏 飞贼小助手',
|
||||
// clickFunc: () => loadGS(CommonUtils.getScriptEngine()),
|
||||
// tip: '加载从PC端移植的伞佬的油猴版飞贼小助手',
|
||||
// });
|
||||
|
||||
// 物品价格监视
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: 'wh-price-watcher-btn',
|
||||
domText: '💊 价格监视',
|
||||
clickFunc: () => this.itemPriceWatcherHandler.handle()
|
||||
});
|
||||
// 全屏
|
||||
if (!this.tornPDAUtils.isPDA()) list.push({
|
||||
domType: 'button', domId: '', domText: '🖥️ 进入全屏', clickFunc() {
|
||||
document.documentElement.requestFullscreen().then();
|
||||
}
|
||||
});
|
||||
// 传单助手
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: '',
|
||||
domText: '📜️ 传单助手',
|
||||
clickFunc: adHelper
|
||||
});
|
||||
// 守望者
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: '',
|
||||
domText: '🛡️ 守望者',
|
||||
clickFunc: function () {
|
||||
safeKeeper();
|
||||
},
|
||||
});
|
||||
// 寻找木桩
|
||||
list.push({
|
||||
domType: 'button',
|
||||
domId: '',
|
||||
domText: '🌲 寻找木桩',
|
||||
clickFunc() {
|
||||
window.location.replace('https://www.torn.com/item.php?temp=4#xunzhaomuzhuang')
|
||||
}
|
||||
});
|
||||
// 物品查价
|
||||
list.push(ItemPriceHandler);
|
||||
// 更新历史
|
||||
// list.push(ChangeLogHandler);
|
||||
// 助手设置
|
||||
list.push(SettingsHandler);
|
||||
// 测试
|
||||
if (this.logger.debug()) list.push(Test);
|
||||
|
||||
this.menuItemList = list;
|
||||
this.logger.info('构造展开菜单列表结束' + timer.getTimeMs());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export interface MenuItemConfig {
|
||||
domType: 'button' | 'plain' | 'checkbox' | 'select' | MENU_ITEM_TYPE;
|
||||
tagName?: string;
|
||||
domId?: string;
|
||||
domText?: string;
|
||||
clickFunc?: (ev?) => void;
|
||||
domHTML?: string;
|
||||
tip?: string;
|
||||
dictName?: string;
|
||||
changeEv?: (ev) => void;
|
||||
domSelectOpt?: { domVal: string, domText: string }[];
|
||||
/**
|
||||
* 隐藏菜单已弃用
|
||||
* @deprecated
|
||||
*/
|
||||
isHide?: boolean;
|
||||
isTornBtn?: boolean;
|
||||
}
|
||||
|
||||
interface EventWrapper {
|
||||
onEv: boolean;
|
||||
daysLeft: number;
|
||||
events: Event[];
|
||||
current?: Event;
|
||||
next?: Event;
|
||||
html?: string;
|
||||
}
|
||||
|
||||
interface Event {
|
||||
start: number[];
|
||||
end: number[];
|
||||
name: string;
|
||||
eff: string;
|
||||
}
|
||||
352
src/ts/class/action/AttackHelper.ts
Normal file
352
src/ts/class/action/AttackHelper.ts
Normal file
@ -0,0 +1,352 @@
|
||||
// import CommonUtils from "../utils/CommonUtils";
|
||||
// import Alert from "../utils/Alert";
|
||||
// import Global from "../Global";
|
||||
// import Device from "../../enum/Device";
|
||||
// import ATTACK_HELPER_CSS from "../../../static/css/attack_helper.module.css";
|
||||
// import ActionButtonUtils from "../utils/ActionButtonUtils";
|
||||
// import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
// import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
// import DialogMsgBox from "../utils/DialogMsgBox";
|
||||
// import FetchUtils from "../utils/FetchUtils";
|
||||
// import MathUtils from "../utils/MathUtils";
|
||||
// import LoopHelper from "../utils/LoopHelper";
|
||||
// import TRAVEL_STATE from "../../enum/TravelState";
|
||||
// import { Injectable } from "../../container/Injectable";
|
||||
// import ClassName from "../../container/ClassName";
|
||||
// import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
// import Logger from "../Logger";
|
||||
//
|
||||
// enum FIGHT_STAGE {
|
||||
// READY = 'ready',
|
||||
// IN_PROGRESS_OR_ERROR = 'in_progress_or_error',
|
||||
// FINISHED = 'finished',
|
||||
// END = 'end',
|
||||
// OTHER = 'other'
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 战斗助手
|
||||
// * TODO 页面加载已经在进行中的战斗时的正确判断
|
||||
// */
|
||||
// @Injectable()
|
||||
// @ClassName('AttackHelper')
|
||||
// export default class AttackHelper {
|
||||
//
|
||||
// private currentStage: FIGHT_STAGE = FIGHT_STAGE.OTHER;
|
||||
//
|
||||
// constructor(
|
||||
// private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
// private readonly commonUtils: CommonUtils,
|
||||
// private readonly global: Global,
|
||||
// private readonly mathUtils: MathUtils,
|
||||
// private readonly actionButtonUtils: ActionButtonUtils,
|
||||
// private readonly fetchUtils: FetchUtils,
|
||||
// private readonly logger: Logger,
|
||||
// ) {
|
||||
// }
|
||||
//
|
||||
// init(): void {
|
||||
// window.setTimeout(() => this._init(), 0);
|
||||
// }
|
||||
//
|
||||
// private _init() {
|
||||
// if (window.location.href.contains(/loader\.php\?sid=attack/)) {
|
||||
// this.fightingPageHandle();
|
||||
// }
|
||||
// // 错误的攻击页面转跳
|
||||
// // else if (window.location.href.includes('loader2.php') && this.localConfigWrapper.config.attRelocate) {
|
||||
// // const spl = window.location.href.trim().split('=');
|
||||
// // const uid = spl[spl.length - 1];
|
||||
// // if (this.commonUtils.isValidUid(uid)) {
|
||||
// // window.location.href = 'https://www.torn.com/loader.php?sid=attack&user2ID=' + uid;
|
||||
// // } else {
|
||||
// // this.logger.error('[AttackHelper] UID格式不正确');
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
//
|
||||
// private fightingPageHandle(): void {
|
||||
// // 光速刷新按钮
|
||||
// this.actionButtonUtils.add('光速刷新', () => this.doAttackReload());
|
||||
//
|
||||
// // 盯梢
|
||||
// this.watchTarget();
|
||||
//
|
||||
// new MutationObserver((_, observer) => {
|
||||
// let btnList = document.querySelectorAll('div[class^="dialogButtons___"] button') as NodeListOf<HTMLButtonElement>;
|
||||
//
|
||||
// if (btnList.length === 0) {
|
||||
// if (this.currentStage === FIGHT_STAGE.READY && this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
// document.body.classList.remove('wh-move-btn');
|
||||
// this.logger.info('移除body class wh-move-btn');
|
||||
// observer.disconnect();
|
||||
// }
|
||||
// // 错误或正在打
|
||||
// this.currentStage = FIGHT_STAGE.IN_PROGRESS_OR_ERROR;
|
||||
// this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
// return;
|
||||
// }
|
||||
// btnList.forEach(btn => {
|
||||
// let btnText = btn.innerText.toLowerCase();
|
||||
// if (btnText.includes('start') || btnText.includes('join')) {
|
||||
// // 开始
|
||||
// this.quickStartFight();
|
||||
// } else if (btnText.includes('continue')) {
|
||||
// // 结束end
|
||||
// this.currentStage = FIGHT_STAGE.END;
|
||||
// observer.disconnect();
|
||||
// } else if (btnText.includes('leave')) {
|
||||
// // 无意识状态FINISHED
|
||||
// this.quickFinishFight(btnList);
|
||||
// }
|
||||
// this.logger.info('[attackHelper] currentStage', this.currentStage);
|
||||
// })
|
||||
// })
|
||||
// .observe(document.querySelector('#react-root'), { childList: true, subtree: true });
|
||||
// }
|
||||
//
|
||||
// // 战斗页面快速刷新
|
||||
// private doAttackReload(): void {
|
||||
// if (!window.ReactDOM) {
|
||||
// new Alert('光速刷新失败:未找到React对象');
|
||||
// this.logger.error('光速刷新失败:未找到React对象');
|
||||
// return;
|
||||
// }
|
||||
// if (!document.querySelector('#react-root #attacker')) {
|
||||
// this.logger.error('dom元素未找到selector: [#react-root #attacker]');
|
||||
// return;
|
||||
// }
|
||||
// let script = document.querySelector('script[src*="/builds/attack/"]');
|
||||
// let url = script.src;
|
||||
// if (!url.contains(/runtime\..+\.js/)) {
|
||||
// this.logger.error('脚本源[' + url + '] 不匹配规则');
|
||||
// return;
|
||||
// }
|
||||
// window.ReactDOM.unmountComponentAtNode(document.querySelector('#react-root'));
|
||||
// script.remove();
|
||||
// let node = document.createElement('script');
|
||||
// node.src = url;
|
||||
// node.type = 'text/javascript';
|
||||
// document.head.appendChild(node);
|
||||
// }
|
||||
//
|
||||
// // 光速拔刀
|
||||
// private quickStartFight(): void {
|
||||
// if (this.currentStage === FIGHT_STAGE.READY) {
|
||||
// return;
|
||||
// } else {
|
||||
// this.currentStage = FIGHT_STAGE.READY;
|
||||
// }
|
||||
// if (this.localConfigWrapper.config.quickAttIndex === 6) return;
|
||||
// /**
|
||||
// * pc #defender
|
||||
// * mobile #attacker
|
||||
// */
|
||||
// const btn = <HTMLInputElement>(document.querySelector('#attacker button') || document.querySelector('#defender button'));
|
||||
// this.logger.info('操作按钮', { btn });
|
||||
// if (!btn.innerText.toLowerCase().includes('fight')) {
|
||||
// this.logger.info('未找到攻击按钮, 光速拔刀跳过');
|
||||
// new Alert('未找到攻击按钮, 光速拔刀跳过');
|
||||
// } else {
|
||||
// // 判断是否存在脚踢
|
||||
// const hasKick = !!document.querySelector('#weapon_boots');
|
||||
// // modal层
|
||||
// // const modal: HTMLElement = document.querySelector('div[class^="modal___"]');
|
||||
// let device = this.global.device;
|
||||
// this.logger.info(`当前设备类型是${ device }`);
|
||||
// // 区分设备
|
||||
// switch (device) {
|
||||
// case Device.PC: {
|
||||
// this.logger.info(`开始调整按钮位置`);
|
||||
// // 隐藏modal层
|
||||
// // modal.style.display = 'none';
|
||||
// // 根据选择的武器调整css
|
||||
// let css_top = '0';
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// // weapon_second
|
||||
// case 1: {
|
||||
// css_top = '97px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_melee
|
||||
// case 2: {
|
||||
// css_top = '194px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_temp
|
||||
// case 3: {
|
||||
// css_top = '291px';
|
||||
// break;
|
||||
// }
|
||||
// // weapon_fists
|
||||
// case 4:
|
||||
// // weapon_boots
|
||||
// case 5: {
|
||||
// css_top = '375px';
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// this.commonUtils.styleInject(ATTACK_HELPER_CSS);
|
||||
// CommonUtils.addStyle(`.wh-move-btn #defender div[class^="modal___"]{top: ${ css_top };}`);
|
||||
// document.body.classList.add('wh-move-btn');
|
||||
// break;
|
||||
// }
|
||||
// case Device.MOBILE: {
|
||||
// this.logger.info(`开始调整按钮位置`);
|
||||
// // 加入css
|
||||
// let css_top = '0';
|
||||
// let slot_height = '76px';
|
||||
// // 判断有没有脚踢
|
||||
// if (hasKick) {
|
||||
// // 根据选择的武器调整
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// case 1: { // weapon_second
|
||||
// css_top = '76px';
|
||||
// break;
|
||||
// }
|
||||
// case 2: { // weapon_melee
|
||||
// css_top = '152px';
|
||||
// break;
|
||||
// }
|
||||
// case 3: { // weapon_temp
|
||||
// css_top = '228px';
|
||||
// break;
|
||||
// }
|
||||
// case 4: { // weapon_fists
|
||||
// css_top = '304px';
|
||||
// break;
|
||||
// }
|
||||
// case 5: { // weapon_boots
|
||||
// css_top = '380px';
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// const slot = document.querySelector('#weapon_main') as HTMLElement;
|
||||
// const height = slot.offsetHeight + 1;
|
||||
// // TODO 待验证
|
||||
// slot_height = height + 'px';
|
||||
// // 根据选择的武器调整
|
||||
// switch (this.localConfigWrapper.config.quickAttIndex) {
|
||||
// case 1: { // weapon_second
|
||||
// css_top = `${ height }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 2: { // weapon_melee
|
||||
// css_top = `${ height * 2 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 3: { // weapon_temp
|
||||
// css_top = `${ height * 3 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 4: { // weapon_fists
|
||||
// css_top = `${ height * 4 }px`;
|
||||
// break;
|
||||
// }
|
||||
// case 5: { // weapon_boots
|
||||
// css_top = `${ height * 5 }px`;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// const css_rule = ATTACK_HELPER_CSS.replace('CSSVAR', css_top).replace('CSSVAR', slot_height);
|
||||
//
|
||||
// this.commonUtils.styleInject(css_rule);
|
||||
// document.body.classList.toggle('wh-move-btn');
|
||||
// btn.onclick = () => {
|
||||
// if (this.localConfigWrapper.config.quickFinishAtt !== 3) {
|
||||
// btn.remove();
|
||||
// // 停止自动刷新
|
||||
// // stop_reload = true;
|
||||
// } else {
|
||||
// document.body.classList.toggle('wh-move-btn');
|
||||
// }
|
||||
// };
|
||||
// break;
|
||||
// }
|
||||
// case Device.TABLET: {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 光速跑路
|
||||
// private quickFinishFight(btnList: NodeListOf<HTMLButtonElement>): void {
|
||||
// if (this.currentStage === FIGHT_STAGE.FINISHED) {
|
||||
// return;
|
||||
// } else {
|
||||
// this.currentStage = FIGHT_STAGE.FINISHED;
|
||||
// }
|
||||
// if (this.localConfigWrapper.config.quickFinishAtt === 3) {
|
||||
// document.body.classList.remove('wh-move-btn');
|
||||
// this.logger.info('移除body class wh-move-btn');
|
||||
// return;
|
||||
// }
|
||||
// const user_btn_select = ['leave', 'mug', 'hosp'][this.localConfigWrapper.config.quickFinishAtt];
|
||||
// // const wrap = document.querySelector('#react-root');
|
||||
// this.logger.info('光速跑路选项选中:', user_btn_select);
|
||||
// // const btn_arr: HTMLButtonElement[] = document.querySelectorAll('div[class^="dialogButtons___"] button') as unknown as HTMLButtonElement[];
|
||||
// if (btnList.length > 1) btnList.forEach(btn => {
|
||||
// const flag = btn.innerText.toLowerCase().includes(user_btn_select);
|
||||
// this.logger.info('按钮内容:', btn.innerText, ',是否包含选中:', flag);
|
||||
// if (!flag) btn.style.display = 'none';
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// // 盯梢模式
|
||||
// private watchTarget(): void {
|
||||
// this.logger.info('获取目标id');
|
||||
// let targetId = window.location.href.split('user2ID=')[1];
|
||||
// if (!this.commonUtils.isValidUid(targetId)) {
|
||||
// this.logger.error('目标id获取错误', targetId);
|
||||
// throw new Error('目标id获取错误:' + targetId);
|
||||
// }
|
||||
// let loop = new LoopHelper(async () => {
|
||||
// let userProfile;
|
||||
// try {
|
||||
// userProfile = await this.fetchUtils.getProfile(targetId);
|
||||
// } catch {
|
||||
// this.logger.error('盯梢模式无法获取目标id');
|
||||
// throw new Error('盯梢模式无法获取目标id');
|
||||
// }
|
||||
// await this.commonUtils.sleep(this.mathUtils.getRandomInt(20, 50));
|
||||
// if ((userProfile.userStatus.status === 'ok' && this.commonUtils.getTravelStage() === TRAVEL_STATE.IN_TORN) ||
|
||||
// (userProfile.userStatus.status === 'abroad' && this.commonUtils.getTravelStage() === TRAVEL_STATE.ABROAD)) {
|
||||
// watchSwitch.getInput().checked = false;
|
||||
// window.setTimeout(async () => {
|
||||
// new Alert('目标已落地/出院/出狱!', { timeout: 10, force: true, sysNotify: true });
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// await this.commonUtils.audioPlay();
|
||||
// await this.commonUtils.sleep(300);
|
||||
// }, 0);
|
||||
// }
|
||||
// });
|
||||
// let block = new TornStyleBlock('盯梢模式').insert2Dom();
|
||||
// let watchSwitch = new TornStyleSwitch('开启');
|
||||
// block.append(watchSwitch.getBase());
|
||||
// watchSwitch.getInput().addEventListener('change', () => {
|
||||
// if (watchSwitch.getInput().checked) {
|
||||
// new DialogMsgBox('检测玩家状态,当目标状态变成(海外)落地、出院或出狱时通知并播放声音提醒,后可搭配光速刷新食用<br/>确定开启?', {
|
||||
// callback: () => {
|
||||
// if (this.commonUtils.getTravelStage() === TRAVEL_STATE.FLYING) {
|
||||
// new Alert('失败!已取消');
|
||||
// watchSwitch.getInput().checked = false;
|
||||
// return;
|
||||
// }
|
||||
// this.logger.info('盯梢开启, 目标id' + targetId);
|
||||
// loop.start(this.localConfigWrapper.config.WatchTargetFreq | 0);
|
||||
// },
|
||||
// cancel: () => watchSwitch.getInput().checked = false
|
||||
// });
|
||||
// } else {
|
||||
// loop.stop();
|
||||
// this.logger.info('盯梢关闭');
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
1
src/ts/class/action/BuyBeerResult.ts
Normal file
1
src/ts/class/action/BuyBeerResult.ts
Normal file
@ -0,0 +1 @@
|
||||
export default {};
|
||||
75
src/ts/class/action/FetchEventCallback.ts
Normal file
75
src/ts/class/action/FetchEventCallback.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { MiniProfile } from "../../interface/responseType/MiniProfile";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Provider from "../provider/Provider";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import { fetchYata } from "../../func/module/fetchYata";
|
||||
import toThousands from "../../func/utils/toThousands";
|
||||
|
||||
/**
|
||||
* fetch 事件监听回调
|
||||
*/
|
||||
@Injectable()
|
||||
@ClassName("FetchEventCallback")
|
||||
export default class FetchEventCallback extends Provider implements ResponseInject {
|
||||
className = "FetchEventCallback";
|
||||
|
||||
newNode = document.createElement('div')
|
||||
bsEstNode = document.createElement('div')
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch 返回后处理
|
||||
* @param url
|
||||
* @param response
|
||||
*/
|
||||
public responseHandler(url: string, response) {
|
||||
// mini profile 中添加上次动作
|
||||
if (url.startsWith('/page.php?sid=UserMiniProfile&userID')) {
|
||||
window.setTimeout(async () => {
|
||||
let cont = CommonUtils.querySelector('[class*=profile-mini-_userProfileWrapper___]');
|
||||
let resp: MiniProfile = response.json as MiniProfile;
|
||||
if (this.localConfigWrapper.config.ShowMiniProfLastAct) {
|
||||
this.logger.info({ resp })
|
||||
let formatted = this.commonUtils.secondsFormat(resp.user.lastAction.seconds);
|
||||
|
||||
(await cont).append(this.newNode);
|
||||
this.newNode.innerText = '上次动作: ' + formatted;
|
||||
}
|
||||
if (this.localConfigWrapper.config.isBSEstMiniProfOn) {
|
||||
const id = resp.user.userID
|
||||
const apikey = localStorage.getItem('APIKey')
|
||||
this.bsEstNode.innerHTML = `[BS估算] [${ id }]获取中...`;
|
||||
(await cont).append(this.bsEstNode)
|
||||
if (!apikey) {
|
||||
this.bsEstNode.innerHTML = '[BS估算] 未配置APIKey,无法估算BS'
|
||||
this.logger.error('MINI Profile bs估算失败: APIKey为空')
|
||||
} else {
|
||||
const bsData = fetchYata(id, apikey)
|
||||
bsData.then(data => {
|
||||
// 网速过慢时可能mini profile容器已更新新内容,与上次请求的用户数据不同,需要判断
|
||||
if (this.bsEstNode.innerHTML.includes(resp.user.userID.toString())) {
|
||||
this.bsEstNode.innerHTML = `[BS估算] ${ resp.user.playerName }[${ id }] ${ toThousands(data.total) }`
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
this.bsEstNode.innerHTML = `[BS估算] ${ err.message }`
|
||||
})
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/ts/class/action/PTHelper.ts
Normal file
91
src/ts/class/action/PTHelper.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import IFeature from "../../man/IFeature";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
|
||||
@Injectable()
|
||||
@ClassName('PTHelper')
|
||||
export default class PTHelper implements IFeature {
|
||||
private observer: MutationObserver;
|
||||
private usersPointSell: HTMLDivElement;
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "pt一键购买";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/pmarket\.php/];
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
this.observer = new MutationObserver(e => {
|
||||
for (const t of e) {
|
||||
t.addedNodes.forEach(e => 'LI' === (e as HTMLElement).tagName && this.removeConfirm(e))
|
||||
}
|
||||
});
|
||||
this.usersPointSell = document.querySelector<HTMLDivElement>('.users-point-sell');
|
||||
|
||||
let block = new TornStyleBlock('PT一键购买').insert2Dom();
|
||||
let switcher = new TornStyleSwitch('开启');
|
||||
block.append(switcher.getBase());
|
||||
let toggle = switcher.getInput();
|
||||
toggle.checked = this.localConfigWrapper.config.ptQuickBuy;
|
||||
if (toggle.checked) {
|
||||
this.msgWrapper.create('一键购买已开启');
|
||||
for (const index in this.usersPointSell.children) {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
this.observer.observe(this.usersPointSell, { childList: true })
|
||||
}
|
||||
toggle.addEventListener('change', () => {
|
||||
this.localConfigWrapper.config.ptQuickBuy = toggle.checked;
|
||||
if (toggle.checked) {
|
||||
for (const index in this.usersPointSell.children) {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.removeConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
this.observer.observe(this.usersPointSell, { childList: true });
|
||||
this.msgWrapper.create('一键购买已开启');
|
||||
} else {
|
||||
for (const index in this.usersPointSell.children) {
|
||||
'LI' === this.usersPointSell.children[index].tagName && this.rollbackConfirm(this.usersPointSell.children[index])
|
||||
}
|
||||
this.observer.disconnect();
|
||||
this.msgWrapper.create('一键购买已关闭');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private removeConfirm(elem): void {
|
||||
let el = elem.firstElementChild;
|
||||
el.classList.add('yes');
|
||||
let old_href = el.getAttribute('href');
|
||||
let new_href = old_href.replace(/=buy/, '=buy1').replace(/&points=\d{1,9}$/, '');
|
||||
el.setAttribute('href', new_href);
|
||||
}
|
||||
|
||||
private rollbackConfirm(elem): void {
|
||||
let el = elem.firstElementChild;
|
||||
el.classList.remove('yes');
|
||||
let old_href = el.getAttribute('href');
|
||||
let new_href = old_href.replace(/=buy1/, '=buy');
|
||||
el.setAttribute('href', new_href);
|
||||
}
|
||||
}
|
||||
151
src/ts/class/action/ProfileHelper.ts
Normal file
151
src/ts/class/action/ProfileHelper.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
import globVars from "../../globVars";
|
||||
import IUserProfileData from "../../interface/IUserProfileData";
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import LocalConfigWrapper from "../LocalConfigWrapper";
|
||||
import Logger from "../Logger";
|
||||
import IFeature from "../../man/IFeature";
|
||||
import { fetchYata } from "../../func/module/fetchYata";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
import toThousands from "../../func/utils/toThousands";
|
||||
import { timePastFormat } from "../../func/utils/timePastFormat";
|
||||
|
||||
@ClassName('ProfileHelper')
|
||||
@Injectable()
|
||||
export default class ProfileHelper implements ResponseInject, IFeature {
|
||||
private block: TornStyleBlock;
|
||||
|
||||
constructor(
|
||||
private readonly localConfigWrapper: LocalConfigWrapper,
|
||||
private readonly commonUtils: CommonUtils,
|
||||
private readonly logger: Logger,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
description(): string {
|
||||
return "个人资料页面辅助";
|
||||
}
|
||||
|
||||
iStart(): void | Promise<void> {
|
||||
this.start()
|
||||
}
|
||||
|
||||
urlExcludes(): RegExp[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 曾用名已检测过标记
|
||||
private task = true;
|
||||
|
||||
urlIncludes(): RegExp[] {
|
||||
return [/profiles\.php\?XID=/];
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
CommonUtils.addStyle('body.wh-hide_profile_img .profile-image a.profile-image-wrapper .img-wrap img{display:none;}');
|
||||
// let id = document.querySelector('link[rel="canonical"]').getAttribute('href').split('=')[1];
|
||||
let id = (new URL(window.location.href)).searchParams.get('XID');
|
||||
// id获取格式判断
|
||||
if (!this.commonUtils.isValidUid(id)) {
|
||||
this.logger.error('[ProfileHelper] id格式错误');
|
||||
}
|
||||
if (this.localConfigWrapper.config.HideProfileImg) {
|
||||
this.logger.info('[ProfileHelper] 隐藏头像');
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
}
|
||||
this.block = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// 隐藏头像
|
||||
try {
|
||||
let hideImgSwitch = new TornStyleSwitch('隐藏头像', this.localConfigWrapper.config.HideProfileImg);
|
||||
this.block.append(hideImgSwitch.getBase());
|
||||
hideImgSwitch.getInput().addEventListener('change', () => {
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
this.localConfigWrapper.config.HideProfileImg = hideImgSwitch.getInput().checked;
|
||||
});
|
||||
if (this.localConfigWrapper.config.ShowNameHistory) {
|
||||
globVars.responseHandlers.push((...args: any[]) => this.responseHandler.apply(this, args));
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error('隐藏头像时出错了', e.stack)
|
||||
}
|
||||
// bs估算
|
||||
if (this.localConfigWrapper.config.isBSEstProfOn) {
|
||||
try {
|
||||
const apikey = localStorage.getItem('APIKey')
|
||||
if (!apikey) {
|
||||
this.msgWrapper.create('BS估算失败: 尚未设定APIKey', null, 'error')
|
||||
}
|
||||
const promise = fetchYata(parseInt(id), apikey)
|
||||
const domNode = document.createElement('div')
|
||||
domNode.innerHTML = 'BS估算中...'
|
||||
domNode.classList.add('mt-4')
|
||||
domNode.style.border = '1px solid green'
|
||||
domNode.style.padding = '2px'
|
||||
this.block.append(domNode)
|
||||
const buildType = { Offensive: '攻击型', Defensive: '防御型', Balanced: '平衡型' }
|
||||
promise.then(data => {
|
||||
domNode.innerHTML = `<b>BS估算</b><br/>
|
||||
BS: ${ toThousands(data.total) }<br/>
|
||||
评分: ${ toThousands(data.score) }<br/>
|
||||
风格: ${ buildType[data.type] }<br/>
|
||||
偏差: ${ data.skewness }%<br/>
|
||||
估算时间: ${ timePastFormat(Date.now() - data.timestamp * 1000) }前
|
||||
`
|
||||
}).catch(err => {
|
||||
domNode.innerHTML = 'BS估算出错了: ' + err.message
|
||||
throw new TypeError('BS估算出错了: ' + err.message)
|
||||
})
|
||||
} catch (e) {
|
||||
this.msgWrapper.create('BS估算失败' + e.message, null, 'error')
|
||||
throw new TypeError('BS估算失败' + e.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }) {
|
||||
if (url.includes('profiles.php?step=getProfileData') && this.task) {
|
||||
// 曾用名
|
||||
const nameHistoryNode = document.createElement('p');
|
||||
nameHistoryNode.innerHTML = '曾用名:';
|
||||
this.block.append(nameHistoryNode);
|
||||
let resp = body.json as IUserProfileData;
|
||||
if (resp.userInformation.previousAliases.length > 0) { // 曾用名列表
|
||||
resp.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
|
||||
} else {
|
||||
nameHistoryNode.innerHTML += '暂无';
|
||||
}
|
||||
let lastAction = -1
|
||||
let onlineStatusTitle = '-'
|
||||
if (resp.basicInformation?.lastAction.seconds) {
|
||||
lastAction = resp.basicInformation.lastAction.seconds
|
||||
}
|
||||
if (resp.basicInformation.icons) {
|
||||
for (let i = 0; i < resp.basicInformation.icons.length; i++) {
|
||||
let item = resp.basicInformation.icons[i]
|
||||
if (item.id === 1) {
|
||||
onlineStatusTitle = '🟢️ 在线'
|
||||
break
|
||||
}
|
||||
if (item.id === 62) {
|
||||
onlineStatusTitle = '🟡 挂机'
|
||||
break
|
||||
}
|
||||
if (item.id === 2) {
|
||||
onlineStatusTitle = '⚪ 离线'
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
const lastActionNode = document.createElement('p')
|
||||
lastActionNode.innerHTML = `${ onlineStatusTitle } ${ this.commonUtils.secondsFormat(lastAction) }`
|
||||
this.block.append(lastActionNode)
|
||||
this.task = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/ts/class/action/QuickGymTrain.ts
Normal file
46
src/ts/class/action/QuickGymTrain.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import ClassName from "../../container/ClassName";
|
||||
import { Injectable } from "../../container/Injectable";
|
||||
import Logger from "../Logger";
|
||||
import NetHighLvlWrapper, { BATTLE_STAT } from "../utils/NetHighLvlWrapper";
|
||||
import { InjectionKey } from "vue";
|
||||
import MsgWrapper from "../utils/MsgWrapper";
|
||||
|
||||
type GymResponse = {
|
||||
success: boolean,
|
||||
// 成功才有 You gained 689,636.71 strength
|
||||
gainMessage?: string,
|
||||
message: string,
|
||||
text?: string,
|
||||
error?: string,
|
||||
};
|
||||
|
||||
@ClassName("QuickGymTrain")
|
||||
@Injectable()
|
||||
export default class QuickGymTrain {
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly netHighLvlWrapper: NetHighLvlWrapper,
|
||||
private readonly msgWrapper: MsgWrapper,
|
||||
) {
|
||||
}
|
||||
|
||||
doTrain(type = BATTLE_STAT.STR, count = 199) {
|
||||
window.setTimeout(async () => {
|
||||
let resObj: GymResponse;
|
||||
try {
|
||||
resObj = JSON.parse(await this.netHighLvlWrapper.doGymTrain(type, count))
|
||||
} catch (e) {
|
||||
resObj = { success: false, message: '解析失败' };
|
||||
this.logger.error(e.stack || e.message || e);
|
||||
}
|
||||
let msgRs = resObj.success ? '成功' : '失败';
|
||||
let msgMsg = resObj.message || resObj.text || resObj.error;
|
||||
this.msgWrapper.create(
|
||||
'锻炼结果: ' + msgRs + '<br/>提示: ' + (resObj.gainMessage || msgMsg),
|
||||
{}, resObj.success ? 'success' : 'error'
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
export const QuickGymTrainKey = Symbol('QuickGymTrainKey') as InjectionKey<QuickGymTrain>;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user