Merge branch 'import-solidjs' into 'dev'
add vue See merge request JJins/wuhu-torn-helper!1
This commit is contained in:
commit
f28dbce227
9
global.d.ts
vendored
9
global.d.ts
vendored
@ -116,6 +116,15 @@ declare module "*.css" {
|
||||
const value: string;
|
||||
export default value;
|
||||
}
|
||||
// declare module '*.vue' {
|
||||
// import type { DefineComponent } from 'vue'
|
||||
// const component: DefineComponent<{}, {}, any>
|
||||
//
|
||||
// export interface HTMLAttributes {
|
||||
// vModel?: any;
|
||||
// }
|
||||
// export default component
|
||||
// }
|
||||
|
||||
declare function GM_xmlhttpRequest(init: any): void;
|
||||
|
||||
|
||||
16538
misc/vue.js
Normal file
16538
misc/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
6432
package-lock.json
generated
6432
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -2,24 +2,27 @@
|
||||
"name": "wuhu-torn-helper",
|
||||
"version": "0.8.2",
|
||||
"description": "芜湖助手",
|
||||
"dependencies": {},
|
||||
"scripts": {
|
||||
"release": "rollup -c rollup-prod.config.js && node build.js",
|
||||
"watch": "rollup -c -w"
|
||||
"release": "cross-env NODE_ENV=production rollup -c rollup-prod.config.js && node build.js",
|
||||
"watch": "cross-env NODE_ENV=development rollup -c -w"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-alias": "^4.0.3",
|
||||
"@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": "^18.0.6",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"npm": "^8.19.2",
|
||||
"rollup": "^2.79.0",
|
||||
"rollup-plugin-html-literals": "^1.1.5",
|
||||
"rollup-plugin-serve": "^2.0.1",
|
||||
"rollup-plugin-string": "^3.0.0",
|
||||
"rollup-plugin-uglify": "^6.0.4",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string-html": "^1.0.0",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.8.3",
|
||||
"uglify-js": "^3.16.1"
|
||||
"vue": "^3.2.47"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,6 @@
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import json from "@rollup/plugin-json";
|
||||
import { string } from "rollup-plugin-string";
|
||||
import { uglify } from "rollup-plugin-uglify";
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import rollupConfig from "./rollup.config";
|
||||
|
||||
export default {
|
||||
input: 'src/ts/index.ts',
|
||||
output: {
|
||||
file: 'dist/bundle.min.js',
|
||||
format: 'iife',
|
||||
},
|
||||
plugins: [
|
||||
typescript(),
|
||||
json(),
|
||||
string({
|
||||
include: ["**/*.html", "**/*.css"]
|
||||
}),
|
||||
uglify(),
|
||||
],
|
||||
};
|
||||
rollupConfig.plugins.push(terser());
|
||||
rollupConfig.output.file = 'dist/bundle.min.js';
|
||||
export default rollupConfig;
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import json from "@rollup/plugin-json";
|
||||
// import template from "rollup-plugin-html-literals";
|
||||
import { string } from "rollup-plugin-string";
|
||||
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 postcss from 'rollup-plugin-postcss';
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
|
||||
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';
|
||||
export default {
|
||||
input: 'src/ts/index.ts',
|
||||
output: {
|
||||
@ -10,15 +17,40 @@ export default {
|
||||
format: 'iife',
|
||||
},
|
||||
plugins: [
|
||||
// template({
|
||||
// include: '*.html',
|
||||
// failOnError: true
|
||||
// }),
|
||||
typescript(),
|
||||
json(),
|
||||
string({
|
||||
include: ["**/*.html", "**/*.css"]
|
||||
alias({
|
||||
entries: [{ find: 'vue', replacement: vuePath }]
|
||||
}),
|
||||
replace({
|
||||
values: {
|
||||
'process.env.NODE_ENV': () => JSON.stringify(node_env),
|
||||
'__VUE_OPTIONS_API__': () => JSON.stringify(false),
|
||||
'__VUE_PROD_DEVTOOLS__': () => JSON.stringify(true),
|
||||
},
|
||||
preventAssignment: true,
|
||||
}),
|
||||
vue({ isProduction: node_env === 'production' }),
|
||||
postcss({ minimize: true }),
|
||||
resolve({
|
||||
browser: true,
|
||||
preferBuiltins: false,
|
||||
}),
|
||||
typescript(),
|
||||
html({
|
||||
// include: ["**/*.html", "**/*.css"],
|
||||
include: ["**/*.html"],
|
||||
minifier: {
|
||||
includeAutoGeneratedTags: true,
|
||||
removeAttributeQuotes: false,
|
||||
removeComments: true,
|
||||
removeRedundantAttributes: false,
|
||||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
sortClassName: true,
|
||||
useShortDoctype: true,
|
||||
collapseWhitespace: true,
|
||||
minifyCSS: true,
|
||||
}
|
||||
}),
|
||||
// uglify(),
|
||||
],
|
||||
};
|
||||
|
||||
6
src/shims-vue.d.ts
vendored
Normal file
6
src/shims-vue.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/* eslint-disable */
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
@ -13,7 +13,7 @@ import ZhongIcon from "./ZhongIcon";
|
||||
import Alert from "./utils/Alert";
|
||||
import FetchEventCallback from "./action/FetchEventCallback";
|
||||
import globVars from "../globVars";
|
||||
import Translate from "./action/Translate";
|
||||
import TranslateNew from "./action/TranslateNew";
|
||||
|
||||
/**
|
||||
* 脚本不区分页面的通用功能入口
|
||||
@ -66,9 +66,9 @@ export class Common extends WuhuBase {
|
||||
}
|
||||
|
||||
// fetch方法处理
|
||||
FetchEventCallback.getInstance();
|
||||
globVars.responseHandlers.push(FetchEventCallback.getInstance().responseHandler);
|
||||
// fetch方法处理-翻译
|
||||
globVars.responseHandlers.push(Translate.responseHandler);
|
||||
globVars.responseHandlers.push(TranslateNew.getInstance().responseHandler);
|
||||
|
||||
// 存钱相关
|
||||
depoHelper();
|
||||
|
||||
@ -4,28 +4,25 @@ export default class Log {
|
||||
|
||||
public static info(...o): void {
|
||||
Log.counter.info++;
|
||||
let time = this.getTime();
|
||||
let flag = '[WH] IFO';
|
||||
let flag = '%c WH %cIFO%c' + this.getTime() + '%c';
|
||||
if (this.debug()) {
|
||||
console.log(flag, time, ...o);
|
||||
console.log(flag, 'background:grey;color:white;', '', 'color:grey;', '', ...o);
|
||||
}
|
||||
this.saveLogs(flag, time, ...o);
|
||||
this.saveLogs(flag, ...o);
|
||||
}
|
||||
|
||||
public static error(...o): void {
|
||||
Log.counter.error++;
|
||||
let time = this.getTime();
|
||||
let flag = '[WH] ERR';
|
||||
console.error(flag, time, ...o);
|
||||
this.saveLogs(flag, time, ...o);
|
||||
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 time = this.getTime();
|
||||
let flag = '[WH] WRN';
|
||||
(this.debug()) && (console.warn(flag, time, ...o));
|
||||
this.saveLogs(flag, time, ...o);
|
||||
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 {
|
||||
@ -47,7 +44,7 @@ export default class Log {
|
||||
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 }]`;
|
||||
return `${ year }-${ month }-${ date } ${ hours }:${ minutes }:${ seconds }.${ ms }`;
|
||||
}
|
||||
|
||||
public static getLogs() {
|
||||
@ -56,7 +53,7 @@ export default class Log {
|
||||
|
||||
private static saveLogs(...o) {
|
||||
o.forEach(item => {
|
||||
if (typeof item === 'string') this.logs += 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;
|
||||
|
||||
@ -5,7 +5,6 @@ import WuhuBase from "./WuhuBase";
|
||||
import CommonUtils from "./utils/CommonUtils";
|
||||
import Log from "./Log";
|
||||
import WuhuConfig from "./WuhuConfig";
|
||||
import Alert from "./utils/Alert";
|
||||
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";
|
||||
@ -98,16 +97,7 @@ export default class UrlPattern extends WuhuBase {
|
||||
});
|
||||
|
||||
// 监听啤酒购买
|
||||
let buyBeerResultMonitor = (url, body, opt) => {
|
||||
if (url.includes('shops.php') && opt.method === 'POST') {
|
||||
let req = opt.requestBody;
|
||||
if (req && req.includes('step=buyShopItem') && req.includes('ID=180') && body.json && body.json['success']) {
|
||||
new Alert('检测到已成功购买啤酒');
|
||||
BuyBeerHelper.getInstance().skip_today();
|
||||
}
|
||||
}
|
||||
};
|
||||
globVars.responseHandlers.push(buyBeerResultMonitor);
|
||||
globVars.responseHandlers.push(BuyBeerHelper.getInstance().responseHandler);
|
||||
}
|
||||
|
||||
// 快速crime TODO 重构、与翻译解藕
|
||||
|
||||
@ -33,8 +33,8 @@ export default class WuhuBase extends Provider {
|
||||
if (condition) throw '芜湖';
|
||||
}
|
||||
|
||||
public getClassName() {
|
||||
return this.className;
|
||||
}
|
||||
// public getClassName() {
|
||||
// return this.className;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@ -7,8 +7,9 @@ import MathUtils from "../utils/MathUtils";
|
||||
import NOTIFY_HTML from "../../static/html/buyBeer/notify.html";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import Popup from "../utils/Popup";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
|
||||
export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop {
|
||||
export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop, ResponseInject {
|
||||
className = 'BuyBeerHelper';
|
||||
|
||||
private isNotifying = false;
|
||||
@ -119,6 +120,16 @@ export default class BuyBeerHelper extends WuhuBase implements BeerMonitorLoop {
|
||||
});
|
||||
popup.getElement().appendChild(confirm);
|
||||
}
|
||||
|
||||
public responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }, opt: { method: "GET" | "POST"; requestBody: string }) {
|
||||
if (url.includes('shops.php') && opt?.method === 'POST') {
|
||||
let req = opt.requestBody;
|
||||
if (req && req.includes('step=buyShopItem') && req.includes('ID=180') && body.json && body.json['success']) {
|
||||
new Alert('检测到已成功购买啤酒');
|
||||
BuyBeerHelper.getInstance().skip_today();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface BeerMonitorLoop {
|
||||
|
||||
0
src/ts/class/action/BuyBeerResult.ts
Normal file
0
src/ts/class/action/BuyBeerResult.ts
Normal file
@ -1,26 +1,21 @@
|
||||
import WuhuBase from "../WuhuBase";
|
||||
import { MiniProfile } from "../../interface/responseType/MiniProfile";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import globVars from "../../globVars";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import Provider from "../provider/Provider";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
|
||||
/**
|
||||
* fetch 事件监听回调
|
||||
*/
|
||||
export default class FetchEventCallback extends WuhuBase {
|
||||
export default class FetchEventCallback extends Provider implements ResponseInject {
|
||||
className = "FetchEventCallback";
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
globVars.responseHandlers.push((url, response) => this.handler(response, url))
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch 返回后处理
|
||||
* @param response
|
||||
* @param url
|
||||
* @param response
|
||||
*/
|
||||
public handler(response, url: string) {
|
||||
public responseHandler(url: string, response) {
|
||||
// mini profile 中添加上次动作
|
||||
if (url.includes('profiles.php?step=getUserNameContextMenu') && WuhuConfig.get('ShowMiniProfLastAct')) {
|
||||
window.setTimeout(async () => {
|
||||
|
||||
@ -4,11 +4,18 @@ import WuhuConfig from "../WuhuConfig";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import TornStyleBlock from "../utils/TornStyleBlock";
|
||||
import TornStyleSwitch from "../utils/TornStyleSwitch";
|
||||
import FetchUtils from "../utils/FetchUtils";
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
import globVars from "../../globVars";
|
||||
import IUserProfileData from "../../interface/IUserProfileData";
|
||||
|
||||
export default class ProfileHelper extends WuhuBase {
|
||||
export default class ProfileHelper extends WuhuBase implements ResponseInject {
|
||||
className = 'ProfileHelper';
|
||||
|
||||
private readonly block;
|
||||
|
||||
// 曾用名已检测过标记
|
||||
private task = true;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
CommonUtils.addStyle('body.wh-hide_profile_img .profile-image a.profile-image-wrapper .img-wrap img{display:none;}');
|
||||
@ -21,27 +28,33 @@ export default class ProfileHelper extends WuhuBase {
|
||||
Log.info('[ProfileHelper] 隐藏头像');
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
}
|
||||
let block = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
this.block = new TornStyleBlock('芜湖助手').insert2Dom();
|
||||
// 隐藏头像
|
||||
let hideImgSwitch = new TornStyleSwitch('隐藏头像', WuhuConfig.get('HideProfileImg'));
|
||||
block.append(hideImgSwitch.getBase());
|
||||
this.block.append(hideImgSwitch.getBase());
|
||||
hideImgSwitch.getInput().addEventListener('change', () => {
|
||||
document.body.classList.toggle('wh-hide_profile_img');
|
||||
WuhuConfig.set('HideProfileImg', hideImgSwitch.getInput().checked, true);
|
||||
});
|
||||
// 曾用名
|
||||
let nameHistoryNode;
|
||||
if (WuhuConfig.get('ShowNameHistory')) {
|
||||
globVars.responseHandlers.push((url, body) => this.responseHandler(url, body));
|
||||
}
|
||||
}
|
||||
|
||||
responseHandler(url: string, body: { json: unknown; text: string; isModified: boolean }) {
|
||||
if (url.includes('profiles.php?step=getProfileData') && this.task) {
|
||||
// 曾用名
|
||||
let nameHistoryNode;
|
||||
nameHistoryNode = document.createElement('p');
|
||||
nameHistoryNode.innerHTML = '曾用名:';
|
||||
block.append(nameHistoryNode);
|
||||
FetchUtils.getInstance().getProfile(id).then((res) => {
|
||||
if (res.userInformation.previousAliases.length > 0) {
|
||||
res.userInformation.previousAliases.forEach(item => nameHistoryNode.innerHTML += item + ' ');
|
||||
} else {
|
||||
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 += '暂无';
|
||||
}
|
||||
this.task = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,7 @@
|
||||
import WuhuBase from "../WuhuBase";
|
||||
import {
|
||||
chatDict,
|
||||
eventsDict,
|
||||
headerDict,
|
||||
itemNameDict,
|
||||
itemPageDict,
|
||||
propertyDict,
|
||||
sidebarDict
|
||||
} from "../../dictionary/translation";
|
||||
import { chatDict, eventsDict, headerDict, propertyDict, sidebarDict } from "../../dictionary/translation";
|
||||
import Log from "../Log";
|
||||
import Timer from "../utils/Timer";
|
||||
import { Button, MiniProfile } from "../../interface/responseType/MiniProfile";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import Sidebar from "../../interface/responseType/Sidebar";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import InventoryItemInfo from "../../interface/responseType/InventoryItemInfo";
|
||||
|
||||
export default class Translate extends WuhuBase {
|
||||
className = 'Translate';
|
||||
@ -303,369 +290,4 @@ export default class Translate extends WuhuBase {
|
||||
observer.observe(document.body, opt);
|
||||
}).observe(document.body, opt);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch xhr 返回数据的翻译处理
|
||||
* @param url
|
||||
* @param body
|
||||
* @param opt
|
||||
*/
|
||||
public static responseHandler(url: string, body: { json: unknown, text: string, isModified: boolean }, opt: { method: 'GET' | 'POST', requestBody: string }): void {
|
||||
if (!WuhuConfig.get('transNew')) return;
|
||||
// TODO 字典抽取
|
||||
let map = {
|
||||
iconMap: {
|
||||
'Online': { title: "在线" },
|
||||
'Level 100': { title: "100 级" },
|
||||
'Jail': {
|
||||
title: "坐牢", description: {
|
||||
map: {
|
||||
'Being questioned for suspicious online activity.': '因可疑的网上活动而被盘问。',
|
||||
'Suspect of a presidential assassination': '刺杀总统的嫌疑人',
|
||||
}
|
||||
}
|
||||
},
|
||||
'Federal jail': {
|
||||
title: "联邦监狱(FJ)", description: {
|
||||
map: {
|
||||
'Account marked for deletion': '账号标记删除',
|
||||
}
|
||||
}
|
||||
},
|
||||
'Idle': { title: "暂离" },
|
||||
'Offline': { title: "离线" },
|
||||
'Enby': { title: "中性" },
|
||||
'Male': { title: "男性" },
|
||||
'Female': { title: "女性" },
|
||||
'Donator': { title: "DP捐助者" },
|
||||
'Subscriber': { title: "蓝星订阅者" },
|
||||
'Traveling': { title: "旅行中" },
|
||||
'Hospital': {
|
||||
title: "已入院",
|
||||
description: {
|
||||
map: {
|
||||
'Fell from a two story building while on a hitman mission': '在执行刺杀任务时从二楼摔下',
|
||||
'Overdosed on Xanax': '吃 Xan 后 OD',
|
||||
'Mauled by a guard dog': '被看门狗咬',
|
||||
},
|
||||
replace: [/(Hospitalized|Mugged|Attacked|Defeated) by (someone|<a.+\/a>)(.+Early discharge available.+)?/, '被 $2 $1$3'],
|
||||
attachedMap: [
|
||||
{
|
||||
'Hospitalized': '强制住院',
|
||||
'Mugged': '抢劫',
|
||||
'Attacked': '攻击',
|
||||
'Defeated': '击败',
|
||||
},
|
||||
{ 'someone': '某人' },
|
||||
{ '<br><i>Early discharge available</i>': '<br><i>提前出院(ED)可用</i>' },
|
||||
],
|
||||
}
|
||||
},
|
||||
'Bounty': {
|
||||
title: "被悬赏",
|
||||
description: { replace: [/On this person's head for (\$[,0-9]+)( : .+)?/, '$1 悬赏此人$2'] }
|
||||
},
|
||||
'Married': {
|
||||
title: "已婚", description: { replace: [/To/, '和'] }
|
||||
},
|
||||
'Company': {
|
||||
title: "公司",
|
||||
description: {
|
||||
replace: [/([a-zA-Z ]+)( of )(.+) \(([aA-zZ ]+)\)$/, "【$3】$4的$1"],
|
||||
attachedMap: [
|
||||
{
|
||||
'Director': '老板',
|
||||
'Salesperson': '销售员',
|
||||
},
|
||||
{}, {},
|
||||
{
|
||||
'Private Security Firm': '安保公司 (PSF)',
|
||||
'Lingerie Store': '内衣店 (LS)',
|
||||
'Adult Novelties': '成人用品店 (AN)',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
'Job': {
|
||||
title: "系统公司",
|
||||
description: {
|
||||
replace: [/([a-zA-Z ]+) (in|at) (.+)$/, "$3的$1"],
|
||||
attachedMap: [
|
||||
{
|
||||
'Manager': '经理',
|
||||
},
|
||||
{},
|
||||
{
|
||||
'a Grocery Store': '杂货店',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
'Faction': {
|
||||
title: "帮派",
|
||||
description: { replace: [/([aA-zZ ]+)( of )(.+)/, "[$3] 帮派的 [$1]"] }
|
||||
},
|
||||
'Bazaar': {
|
||||
title: "摊位",
|
||||
description: {
|
||||
map: {
|
||||
'This person has items in their bazaar for sale':
|
||||
'此人在摊位上有物品出售'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
buttonMap: {
|
||||
message: {
|
||||
'Add $0 to your enemy list': '添加 $0 到敌人列表',
|
||||
'Add $0 to your friend list': '添加 $0 到好友列表',
|
||||
'You are currently traveling': '你在天上',
|
||||
'Initiate a chat with $0': '与 $0 私聊',
|
||||
'You are not in Torn': '你不在城内',
|
||||
"View $0's personal statistics": '查看 $0 的个人统计数据',
|
||||
"Place a bounty on $0": '对 $0 发起悬赏',
|
||||
"Report $0 to staff": '向工作人员举报 $0',
|
||||
"Send $0 a message": '发邮件给 $0',
|
||||
"View $0's display case": '查看 $0 的展柜',
|
||||
"$0 is currently in hospital": '$0 正在住院',
|
||||
"$0 has not been online in the last 6 hours": '$0 超 6 小时未在线',
|
||||
"Give some money to $0": '给 $0 一些钱',
|
||||
"$0's bazaar is closed": '$0 的摊位已关闭',
|
||||
"View $0's bazaar": '查看 $0 的摊位',
|
||||
"Initiate a trade with $0": '与 $0 交易',
|
||||
"$0 has no items in their bazaar": '$0 的摊位是空的',
|
||||
"$0 is currently in jail": '$0 目前在坐牢',
|
||||
"Pay $0's bail": '支付 $0 的保释金',
|
||||
"Bust $0 out of jail": '把 $0 从监狱里踢出来',
|
||||
"$0 is currently in federal jail": '$0 目前在联邦监狱(FJ)',
|
||||
"NPC's cannot be bountied": 'NPC 不能被悬赏',
|
||||
"$0 is hiding out abroad": '$0 正在海外躲藏',
|
||||
"$0 has no items in their display cabinet": '$0 的展柜是空的',
|
||||
"You do not have enough energy to attack $0": '你没有足够的能量攻击 $0',
|
||||
"You have not met this person recently or they have blocked you": '最近你没有遇见此人,或已被屏蔽',
|
||||
},
|
||||
},
|
||||
destinationMap: {
|
||||
'Mexico': '墨西哥',
|
||||
'Cayman Islands': '开曼群岛',
|
||||
'Canada': '加拿大',
|
||||
'Hawaii': '夏威夷',
|
||||
'United Kingdom': '英国',
|
||||
'Argentina': '阿根廷',
|
||||
'Switzerland': '瑞士',
|
||||
'Japan': '日本',
|
||||
'China': '中国',
|
||||
'UAE': '阿联酋(UAE)',
|
||||
'South Africa': '南非',
|
||||
},
|
||||
barMap: {
|
||||
'Chain': { name: '连击' },
|
||||
'Energy': { name: '能量' },
|
||||
'Happy': { name: '快乐' },
|
||||
'Life': { name: '血量' },
|
||||
'Nerve': { name: '犯罪' },
|
||||
},
|
||||
areaMap: {
|
||||
calendar: { name: '日历', shortName: '日历' },
|
||||
traveling: { name: '飞行中', shortName: '飞行' },
|
||||
casino: { name: '赌场' },
|
||||
city: { name: '城市' },
|
||||
crimes: { name: '犯罪' },
|
||||
education: { name: '教育', shortName: '教育' },
|
||||
forums: { name: '论坛' },
|
||||
gym: { name: '健身房' },
|
||||
hall_of_fame: { name: '名人堂', shortName: '排名' },
|
||||
home: { name: '主页', shortName: '主页' },
|
||||
hospital: { name: '医院' },
|
||||
items: { name: '物品' },
|
||||
jail: { name: '监狱' },
|
||||
job: { name: '工作', shortName: '工作' },
|
||||
missions: { name: '任务' },
|
||||
my_faction: { name: '帮派', shortName: '帮派' },
|
||||
newspaper: { name: '报纸', shortName: '报纸' },
|
||||
properties: { name: '住宅', shortName: '住宅' },
|
||||
recruit_citizens: { name: '招募玩家', shortName: '招募' },
|
||||
},
|
||||
accountMap: {
|
||||
awards: { name: '奖章' },
|
||||
events: { name: '通知' },
|
||||
messages: { name: '邮件' }
|
||||
}
|
||||
};
|
||||
try {
|
||||
// Mini Profile
|
||||
if (url.includes('profiles.php?step=getUserNameContextMenu')) {
|
||||
let jsonObj: MiniProfile = body.json as MiniProfile;
|
||||
Log.info('翻译mini profile返回内容');
|
||||
// 状态图标
|
||||
jsonObj.icons.forEach(icon => {
|
||||
let iconMap = map.iconMap;
|
||||
let oriTitle = icon.title;
|
||||
if (iconMap[oriTitle]) {
|
||||
icon.title = iconMap[oriTitle].title;
|
||||
let desc = iconMap[oriTitle].description;
|
||||
let oriDesc = icon.description;
|
||||
if (icon.description && desc) {
|
||||
if (desc.map && desc.map[oriDesc]) {
|
||||
icon.description = desc.map[oriDesc];
|
||||
} else if (desc.replace) {
|
||||
icon.description = oriDesc.replace(new RegExp(desc.replace[0]), desc.replace[1]);
|
||||
if (desc.attachedMap) {
|
||||
desc.attachedMap.forEach((item, index) => {
|
||||
let factor = oriDesc.replace(new RegExp(desc.replace[0]), '$' + (index + 1));
|
||||
Log.info({ factor });
|
||||
let cn = item[factor];
|
||||
cn && (icon.description = icon.description.replace(factor, cn));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 离线转钱警告
|
||||
if (jsonObj.user.sendMoneyWarning) {
|
||||
let daysMatch = jsonObj.user.sendMoneyWarning.match(/[0-9]+/);
|
||||
if (daysMatch.length !== 0)
|
||||
jsonObj.user.sendMoneyWarning = `警告:此人已离线 ${ daysMatch[0] } 天`;
|
||||
}
|
||||
// 按钮
|
||||
let buttons = jsonObj.profileButtons.buttons;
|
||||
let buttonKeyList = Object.keys(buttons);
|
||||
let username = jsonObj.user.playerName;
|
||||
let msgMap = map.buttonMap.message;
|
||||
buttonKeyList.forEach(buttonKey => {
|
||||
if (buttons[buttonKey].state === 'hidden') return;
|
||||
let button: Button = buttons[buttonKey];
|
||||
let oriMsg = button.message.replace(username, '$0');
|
||||
if (msgMap[oriMsg]) {
|
||||
button.message = msgMap[oriMsg].replace('$0', username);
|
||||
}
|
||||
});
|
||||
// TODO 称号
|
||||
// 用户状态
|
||||
let status = jsonObj.userStatus.status.type;
|
||||
switch (status) {
|
||||
case 'traveling-to': {
|
||||
let origin = jsonObj.userStatus.status.to.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.to.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'traveling-from': {
|
||||
let origin = jsonObj.userStatus.status.from.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.from.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'abroad': {
|
||||
let origin = jsonObj.userStatus.status.in.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.in.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'jail': {
|
||||
let origin = jsonObj.userStatus.status.description;
|
||||
let cn = map.iconMap.Jail.description.map[origin];
|
||||
cn && (jsonObj.userStatus.status.description = cn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
body.isModified = true;
|
||||
|
||||
Log.info({ 'localized': jsonObj });
|
||||
}
|
||||
// TODO 边栏
|
||||
else if (url.includes('sidebarAjaxAction.php?q=sync')) {
|
||||
let response = body.json as Sidebar;
|
||||
|
||||
type target = { [k: string]: { name: string, shortName?: string } };
|
||||
let nameMapReplace = (target: target, _map: target) => {
|
||||
Object.keys(target).forEach(key => {
|
||||
if (target[key] && _map[key]) {
|
||||
target[key].name = _map[key].name;
|
||||
if (target[key].shortName && _map[key].shortName) {
|
||||
target[key].shortName = _map[key].shortName;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
nameMapReplace(response.areas, map.areaMap);
|
||||
nameMapReplace(response.account, map.accountMap);
|
||||
body.isModified = true;
|
||||
}
|
||||
// 物品详情
|
||||
else if (url.includes('inventory.php') && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && opt?.requestBody.includes('step=info')) {
|
||||
let resp = body.json as InventoryItemInfo;
|
||||
// TODO 维护通用物品数据(对应名称、描述、类型)缓存
|
||||
let map: { [k: string]: Partial<InventoryItemInfo> } = {
|
||||
'Glass of Beer': {
|
||||
itemName: '一杯啤酒',
|
||||
itemInfo: '[译]Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you\'d get from a regular bottle of suds. Provides a moderate nerve increase when consumed.',
|
||||
itemInfoContent: "\n" +
|
||||
" <div class='m-bottom10'>\n" +
|
||||
" <span class=\"bold\">一杯啤酒</span> 是酒类物品\n" +
|
||||
" </div>\n" +
|
||||
" Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed.\n" +
|
||||
" <div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
},
|
||||
};
|
||||
let idMap = { 816: 'Glass of Beer' };
|
||||
let itemInfo = CommonUtils.getInstance().getItemByIdOrName(resp.itemName, idMap, map);
|
||||
if (itemInfo) {
|
||||
body.isModified = true;
|
||||
resp.itemInfo = itemInfo.itemInfo;
|
||||
resp.itemName = itemInfo.itemName;
|
||||
resp.itemInfoContent = itemInfo.itemInfoContent;
|
||||
}
|
||||
// TODO 老字典
|
||||
let itemName = itemNameDict[resp.itemName];
|
||||
if (itemName) {
|
||||
body.isModified = true;
|
||||
resp.itemInfoContent = resp.itemInfoContent
|
||||
.replace('The ', '')
|
||||
.replace(resp.itemName, `${ itemName }(${ resp.itemName })`);
|
||||
}
|
||||
}
|
||||
// 物品列表
|
||||
else if ((url.includes('item.php') || url.includes('inventory.php')) && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && (opt?.requestBody.includes('step=getCategoryList') || opt?.requestBody.includes('step=getList'))) {
|
||||
let resp = body.json as { html: string };
|
||||
if (resp.html) {
|
||||
let tmp = document.createElement('div');
|
||||
tmp.innerHTML = resp.html;
|
||||
Log.info(tmp);
|
||||
tmp.childNodes.forEach(li => {
|
||||
if (li.nodeType === 1) {
|
||||
let elem = li as Element;
|
||||
// 物品名
|
||||
let name = elem.querySelector('.name-wrap .name');
|
||||
let nameZh = itemNameDict[name.innerText.trim()];
|
||||
if (nameZh) {
|
||||
name.innerText = `${ name.innerText } ${ nameZh }`;
|
||||
}
|
||||
// 操作按钮
|
||||
let actions = elem.querySelectorAll('.icon-h');
|
||||
actions.forEach(action => {
|
||||
let attrTitle = action.getAttribute('title');
|
||||
// TODO
|
||||
let zh = itemPageDict[attrTitle];
|
||||
if (zh) {
|
||||
action.setAttribute('title', zh);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
resp.html = tmp.innerHTML;
|
||||
body.isModified = true;
|
||||
}
|
||||
}
|
||||
// TODO 物品列表json版
|
||||
else if (url.includes('inventory.php') && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && opt?.requestBody.includes('step=getList')) {
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error('responseHandler', e.stack || e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
382
src/ts/class/action/TranslateNew.ts
Normal file
382
src/ts/class/action/TranslateNew.ts
Normal file
@ -0,0 +1,382 @@
|
||||
import ResponseInject from "../../interface/ResponseInject";
|
||||
import WuhuConfig from "../WuhuConfig";
|
||||
import { Button, MiniProfile } from "../../interface/responseType/MiniProfile";
|
||||
import Log from "../Log";
|
||||
import Sidebar from "../../interface/responseType/Sidebar";
|
||||
import InventoryItemInfo from "../../interface/responseType/InventoryItemInfo";
|
||||
import CommonUtils from "../utils/CommonUtils";
|
||||
import { itemNameDict, itemPageDict } from "../../dictionary/translation";
|
||||
import Provider from "../provider/Provider";
|
||||
|
||||
/**
|
||||
* 翻译重构
|
||||
*/
|
||||
export default class TranslateNew extends Provider implements ResponseInject {
|
||||
className = 'TranslateNew';
|
||||
|
||||
/**
|
||||
* fetch xhr 返回数据的翻译处理
|
||||
* @param url
|
||||
* @param body
|
||||
* @param opt
|
||||
*/
|
||||
public responseHandler(url: string, body: { json: unknown, text: string, isModified: boolean }, opt: { method: 'GET' | 'POST', requestBody: string }): void {
|
||||
if (!WuhuConfig.get('transNew')) return;
|
||||
// TODO 字典抽取
|
||||
let map = {
|
||||
iconMap: {
|
||||
'Online': { title: "在线" },
|
||||
'Level 100': { title: "100 级" },
|
||||
'Jail': {
|
||||
title: "坐牢", description: {
|
||||
map: {
|
||||
'Being questioned for suspicious online activity.': '因可疑的网上活动而被盘问。',
|
||||
'Suspect of a presidential assassination': '刺杀总统的嫌疑人',
|
||||
}
|
||||
}
|
||||
},
|
||||
'Federal jail': {
|
||||
title: "联邦监狱(FJ)", description: {
|
||||
map: {
|
||||
'Account marked for deletion': '账号标记删除',
|
||||
}
|
||||
}
|
||||
},
|
||||
'Idle': { title: "暂离" },
|
||||
'Offline': { title: "离线" },
|
||||
'Enby': { title: "中性" },
|
||||
'Male': { title: "男性" },
|
||||
'Female': { title: "女性" },
|
||||
'Donator': { title: "DP捐助者" },
|
||||
'Subscriber': { title: "蓝星订阅者" },
|
||||
'Traveling': { title: "旅行中" },
|
||||
'Hospital': {
|
||||
title: "已入院",
|
||||
description: {
|
||||
map: {
|
||||
'Fell from a two story building while on a hitman mission': '在执行刺杀任务时从二楼摔下',
|
||||
'Overdosed on Xanax': '吃 Xan 后 OD',
|
||||
'Mauled by a guard dog': '被看门狗咬',
|
||||
},
|
||||
replace: [/(Hospitalized|Mugged|Attacked|Defeated) by (someone|<a.+\/a>)(.+Early discharge available.+)?/, '被 $2 $1$3'],
|
||||
attachedMap: [
|
||||
{
|
||||
'Hospitalized': '强制住院',
|
||||
'Mugged': '抢劫',
|
||||
'Attacked': '攻击',
|
||||
'Defeated': '击败',
|
||||
},
|
||||
{ 'someone': '某人' },
|
||||
{ '<br><i>Early discharge available</i>': '<br><i>提前出院(ED)可用</i>' },
|
||||
],
|
||||
}
|
||||
},
|
||||
'Bounty': {
|
||||
title: "被悬赏",
|
||||
description: { replace: [/On this person's head for (\$[,0-9]+)( : .+)?/, '$1 悬赏此人$2'] }
|
||||
},
|
||||
'Married': {
|
||||
title: "已婚", description: { replace: [/To/, '和'] }
|
||||
},
|
||||
'Company': {
|
||||
title: "公司",
|
||||
description: {
|
||||
replace: [/([a-zA-Z ]+)( of )(.+) \(([aA-zZ ]+)\)$/, "【$3】$4的$1"],
|
||||
attachedMap: [
|
||||
{
|
||||
'Director': '老板',
|
||||
'Salesperson': '销售员',
|
||||
},
|
||||
{}, {},
|
||||
{
|
||||
'Private Security Firm': '安保公司 (PSF)',
|
||||
'Lingerie Store': '内衣店 (LS)',
|
||||
'Adult Novelties': '成人用品店 (AN)',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
'Job': {
|
||||
title: "系统公司",
|
||||
description: {
|
||||
replace: [/([a-zA-Z ]+) (in|at) (.+)$/, "$3的$1"],
|
||||
attachedMap: [
|
||||
{
|
||||
'Manager': '经理',
|
||||
},
|
||||
{},
|
||||
{
|
||||
'a Grocery Store': '杂货店',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
'Faction': {
|
||||
title: "帮派",
|
||||
description: { replace: [/([aA-zZ ]+)( of )(.+)/, "[$3] 帮派的 [$1]"] }
|
||||
},
|
||||
'Bazaar': {
|
||||
title: "摊位",
|
||||
description: {
|
||||
map: {
|
||||
'This person has items in their bazaar for sale':
|
||||
'此人在摊位上有物品出售'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
buttonMap: {
|
||||
message: {
|
||||
'Add $0 to your enemy list': '添加 $0 到敌人列表',
|
||||
'Add $0 to your friend list': '添加 $0 到好友列表',
|
||||
'You are currently traveling': '你在天上',
|
||||
'Initiate a chat with $0': '与 $0 私聊',
|
||||
'You are not in Torn': '你不在城内',
|
||||
"View $0's personal statistics": '查看 $0 的个人统计数据',
|
||||
"Place a bounty on $0": '对 $0 发起悬赏',
|
||||
"Report $0 to staff": '向工作人员举报 $0',
|
||||
"Send $0 a message": '发邮件给 $0',
|
||||
"View $0's display case": '查看 $0 的展柜',
|
||||
"$0 is currently in hospital": '$0 正在住院',
|
||||
"$0 has not been online in the last 6 hours": '$0 超 6 小时未在线',
|
||||
"Give some money to $0": '给 $0 一些钱',
|
||||
"$0's bazaar is closed": '$0 的摊位已关闭',
|
||||
"View $0's bazaar": '查看 $0 的摊位',
|
||||
"Initiate a trade with $0": '与 $0 交易',
|
||||
"$0 has no items in their bazaar": '$0 的摊位是空的',
|
||||
"$0 is currently in jail": '$0 目前在坐牢',
|
||||
"Pay $0's bail": '支付 $0 的保释金',
|
||||
"Bust $0 out of jail": '把 $0 从监狱里踢出来',
|
||||
"$0 is currently in federal jail": '$0 目前在联邦监狱(FJ)',
|
||||
"NPC's cannot be bountied": 'NPC 不能被悬赏',
|
||||
"$0 is hiding out abroad": '$0 正在海外躲藏',
|
||||
"$0 has no items in their display cabinet": '$0 的展柜是空的',
|
||||
"You do not have enough energy to attack $0": '你没有足够的能量攻击 $0',
|
||||
"You have not met this person recently or they have blocked you": '最近你没有遇见此人,或已被屏蔽',
|
||||
},
|
||||
},
|
||||
destinationMap: {
|
||||
'Mexico': '墨西哥',
|
||||
'Cayman Islands': '开曼群岛',
|
||||
'Canada': '加拿大',
|
||||
'Hawaii': '夏威夷',
|
||||
'United Kingdom': '英国',
|
||||
'Argentina': '阿根廷',
|
||||
'Switzerland': '瑞士',
|
||||
'Japan': '日本',
|
||||
'China': '中国',
|
||||
'UAE': '阿联酋(UAE)',
|
||||
'South Africa': '南非',
|
||||
},
|
||||
barMap: {
|
||||
'Chain': { name: '连击' },
|
||||
'Energy': { name: '能量' },
|
||||
'Happy': { name: '快乐' },
|
||||
'Life': { name: '血量' },
|
||||
'Nerve': { name: '犯罪' },
|
||||
},
|
||||
areaMap: {
|
||||
calendar: { name: '日历', shortName: '日历' },
|
||||
traveling: { name: '飞行中', shortName: '飞行' },
|
||||
casino: { name: '赌场' },
|
||||
city: { name: '城市' },
|
||||
crimes: { name: '犯罪' },
|
||||
education: { name: '教育', shortName: '教育' },
|
||||
forums: { name: '论坛' },
|
||||
gym: { name: '健身房' },
|
||||
hall_of_fame: { name: '名人堂', shortName: '排名' },
|
||||
home: { name: '主页', shortName: '主页' },
|
||||
hospital: { name: '医院' },
|
||||
items: { name: '物品' },
|
||||
jail: { name: '监狱' },
|
||||
job: { name: '工作', shortName: '工作' },
|
||||
missions: { name: '任务' },
|
||||
my_faction: { name: '帮派', shortName: '帮派' },
|
||||
newspaper: { name: '报纸', shortName: '报纸' },
|
||||
properties: { name: '住宅', shortName: '住宅' },
|
||||
recruit_citizens: { name: '招募玩家', shortName: '招募' },
|
||||
},
|
||||
accountMap: {
|
||||
awards: { name: '奖章' },
|
||||
events: { name: '通知' },
|
||||
messages: { name: '邮件' }
|
||||
}
|
||||
};
|
||||
try {
|
||||
// Mini Profile
|
||||
if (url.includes('profiles.php?step=getUserNameContextMenu')) {
|
||||
let jsonObj: MiniProfile = body.json as MiniProfile;
|
||||
Log.info('翻译mini profile返回内容');
|
||||
// 状态图标
|
||||
jsonObj.icons.forEach(icon => {
|
||||
let iconMap = map.iconMap;
|
||||
let oriTitle = icon.title;
|
||||
if (iconMap[oriTitle]) {
|
||||
icon.title = iconMap[oriTitle].title;
|
||||
let desc = iconMap[oriTitle].description;
|
||||
let oriDesc = icon.description;
|
||||
if (icon.description && desc) {
|
||||
if (desc.map && desc.map[oriDesc]) {
|
||||
icon.description = desc.map[oriDesc];
|
||||
} else if (desc.replace) {
|
||||
icon.description = oriDesc.replace(new RegExp(desc.replace[0]), desc.replace[1]);
|
||||
if (desc.attachedMap) {
|
||||
desc.attachedMap.forEach((item, index) => {
|
||||
let factor = oriDesc.replace(new RegExp(desc.replace[0]), '$' + (index + 1));
|
||||
Log.info({ factor });
|
||||
let cn = item[factor];
|
||||
cn && (icon.description = icon.description.replace(factor, cn));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 离线转钱警告
|
||||
if (jsonObj.user.sendMoneyWarning) {
|
||||
let daysMatch = jsonObj.user.sendMoneyWarning.match(/[0-9]+/);
|
||||
if (daysMatch.length !== 0)
|
||||
jsonObj.user.sendMoneyWarning = `警告:此人已离线 ${ daysMatch[0] } 天`;
|
||||
}
|
||||
// 按钮
|
||||
let buttons = jsonObj.profileButtons.buttons;
|
||||
let buttonKeyList = Object.keys(buttons);
|
||||
let username = jsonObj.user.playerName;
|
||||
let msgMap = map.buttonMap.message;
|
||||
buttonKeyList.forEach(buttonKey => {
|
||||
if (buttons[buttonKey].state === 'hidden') return;
|
||||
let button: Button = buttons[buttonKey];
|
||||
let oriMsg = button.message.replace(username, '$0');
|
||||
if (msgMap[oriMsg]) {
|
||||
button.message = msgMap[oriMsg].replace('$0', username);
|
||||
}
|
||||
});
|
||||
// TODO 称号
|
||||
// 用户状态
|
||||
let status = jsonObj.userStatus.status.type;
|
||||
switch (status) {
|
||||
case 'traveling-to': {
|
||||
let origin = jsonObj.userStatus.status.to.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.to.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'traveling-from': {
|
||||
let origin = jsonObj.userStatus.status.from.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.from.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'abroad': {
|
||||
let origin = jsonObj.userStatus.status.in.simpleName;
|
||||
let cn = map.destinationMap[origin]
|
||||
cn && (jsonObj.userStatus.status.in.simpleName = cn);
|
||||
break;
|
||||
}
|
||||
case 'jail': {
|
||||
let origin = jsonObj.userStatus.status.description;
|
||||
let cn = map.iconMap.Jail.description.map[origin];
|
||||
cn && (jsonObj.userStatus.status.description = cn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
body.isModified = true;
|
||||
|
||||
Log.info({ 'localized': jsonObj });
|
||||
}
|
||||
// TODO 边栏
|
||||
else if (url.includes('sidebarAjaxAction.php?q=sync')) {
|
||||
let response = body.json as Sidebar;
|
||||
|
||||
type target = { [k: string]: { name: string, shortName?: string } };
|
||||
let nameMapReplace = (target: target, _map: target) => {
|
||||
Object.keys(target).forEach(key => {
|
||||
if (target[key] && _map[key]) {
|
||||
target[key].name = _map[key].name;
|
||||
if (target[key].shortName && _map[key].shortName) {
|
||||
target[key].shortName = _map[key].shortName;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
nameMapReplace(response.areas, map.areaMap);
|
||||
nameMapReplace(response.account, map.accountMap);
|
||||
body.isModified = true;
|
||||
}
|
||||
// 物品详情
|
||||
else if ((url.includes('inventory.php?step=info')) || (url.includes('inventory.php') && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && opt?.requestBody.includes('step=info'))) {
|
||||
Log.info('responseHandler');
|
||||
let resp = body.json as InventoryItemInfo;
|
||||
// TODO 维护通用物品数据(对应名称、描述、类型)缓存
|
||||
let map: { [k: string]: Partial<InventoryItemInfo> } = {
|
||||
'Glass of Beer': {
|
||||
itemName: '一杯啤酒',
|
||||
itemInfo: '[译]Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you\'d get from a regular bottle of suds. Provides a moderate nerve increase when consumed.',
|
||||
itemInfoContent: "\n" +
|
||||
" <div class='m-bottom10'>\n" +
|
||||
" <span class=\"bold\">一杯啤酒</span> 是酒类物品\n" +
|
||||
" </div>\n" +
|
||||
" Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed.\n" +
|
||||
" <div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
},
|
||||
};
|
||||
let idMap = { 816: 'Glass of Beer' };
|
||||
let itemInfo = CommonUtils.getInstance().getItemByIdOrName(resp.itemName, idMap, map);
|
||||
if (itemInfo) {
|
||||
body.isModified = true;
|
||||
resp.itemInfo = itemInfo.itemInfo;
|
||||
resp.itemName = itemInfo.itemName;
|
||||
resp.itemInfoContent = itemInfo.itemInfoContent;
|
||||
}
|
||||
// TODO 老字典
|
||||
let itemName = itemNameDict[resp.itemName];
|
||||
if (itemName) {
|
||||
body.isModified = true;
|
||||
resp.itemInfoContent = resp.itemInfoContent
|
||||
.replace('The ', '')
|
||||
.replace(resp.itemName, `${ itemName }(${ resp.itemName })`);
|
||||
}
|
||||
}
|
||||
// 物品列表
|
||||
else if ((url.includes('item.php') || url.includes('inventory.php')) && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && (opt?.requestBody.includes('step=getCategoryList') || opt?.requestBody.includes('step=getList'))) {
|
||||
let resp = body.json as { html: string };
|
||||
if (resp.html) {
|
||||
let tmp = document.createElement('div');
|
||||
tmp.innerHTML = resp.html;
|
||||
Log.info(tmp);
|
||||
tmp.childNodes.forEach(li => {
|
||||
if (li.nodeType === 1) {
|
||||
let elem = li as Element;
|
||||
// 物品名
|
||||
let name = elem.querySelector('.name-wrap .name');
|
||||
let nameZh = itemNameDict[name.innerText.trim()];
|
||||
if (nameZh) {
|
||||
name.innerText = `${ name.innerText } ${ nameZh }`;
|
||||
}
|
||||
// 操作按钮
|
||||
let actions = elem.querySelectorAll('.icon-h');
|
||||
actions.forEach(action => {
|
||||
let attrTitle = action.getAttribute('title');
|
||||
// TODO
|
||||
let zh = itemPageDict[attrTitle];
|
||||
if (zh) {
|
||||
action.setAttribute('title', zh);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
resp.html = tmp.innerHTML;
|
||||
body.isModified = true;
|
||||
}
|
||||
}
|
||||
// TODO 物品列表json版
|
||||
else if (url.includes('inventory.php') && opt?.method === 'POST' &&
|
||||
typeof opt?.requestBody === 'string' && opt?.requestBody.includes('step=getList')) {
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error('responseHandler', e.stack || e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/ts/class/handler/ItemValueQueryHandler.ts
Normal file
21
src/ts/class/handler/ItemValueQueryHandler.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import WuhuBase from "../WuhuBase";
|
||||
import Popup from "../utils/Popup";
|
||||
import Elem from "../provider/Elem";
|
||||
|
||||
/**
|
||||
* 快速查价
|
||||
*/
|
||||
export default class ItemValueQueryHandler extends WuhuBase {
|
||||
className = "ItemValueQueryHandler";
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public show() {
|
||||
let pop = new Popup('', '快速查价');
|
||||
pop.getElement().append(
|
||||
new Elem('div').html('<p>test</p>').class('wh-test').el()
|
||||
)
|
||||
}
|
||||
}
|
||||
26
src/ts/class/provider/Elem.ts
Normal file
26
src/ts/class/provider/Elem.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export default class Elem {
|
||||
private readonly elem: HTMLElement;
|
||||
|
||||
constructor(tagName) {
|
||||
this.elem = document.createElement(tagName);
|
||||
}
|
||||
|
||||
public html(htmlString): Elem {
|
||||
this.elem.innerHTML = htmlString;
|
||||
return this;
|
||||
}
|
||||
|
||||
public id(id): Elem {
|
||||
this.elem.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public class(className): Elem {
|
||||
this.elem.classList.add(className);
|
||||
return this;
|
||||
}
|
||||
|
||||
public el(): HTMLElement {
|
||||
return this.elem;
|
||||
}
|
||||
}
|
||||
@ -30,4 +30,8 @@ export default class Provider {
|
||||
pool: Provider.pool,
|
||||
}
|
||||
}
|
||||
|
||||
public getClassName() {
|
||||
return this.className;
|
||||
}
|
||||
}
|
||||
|
||||
116
src/ts/class/utils/ItemHelper.ts
Normal file
116
src/ts/class/utils/ItemHelper.ts
Normal file
@ -0,0 +1,116 @@
|
||||
import WuhuBase from "../WuhuBase";
|
||||
import InventoryItemInfo from "../../interface/responseType/InventoryItemInfo";
|
||||
import FetchUtils from "./FetchUtils";
|
||||
import CommonUtils from "./CommonUtils";
|
||||
import Log from "../Log";
|
||||
|
||||
export default class ItemHelper extends WuhuBase {
|
||||
className = "ItemHelper";
|
||||
itemValueMap: { [k: string]: Partial<InventoryItemInfo> } = {
|
||||
'Glass of Beer': {
|
||||
itemName: '一杯啤酒',
|
||||
itemInfo: '[译]Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you\'d get from a regular bottle of suds. Provides a moderate nerve increase when consumed.',
|
||||
itemInfoContent: "\n" +
|
||||
" <div class='m-bottom10'>\n" +
|
||||
" <span class=\"bold\">一杯啤酒</span> 是酒类物品\n" +
|
||||
" </div>\n" +
|
||||
" Only savages drink beer straight out of the bottle. This glass of beer is obtained fresh from the keg, and provides the same level of drunken joy as you'd get from a regular bottle of suds. Provides a moderate nerve increase when consumed.\n" +
|
||||
" <div class=\"t-green bold item-effect m-top10\">效果: 犯罪 + 2,增幅CD + 1h。</div>",
|
||||
},
|
||||
};
|
||||
itemPriceMap = {
|
||||
205: { name: 'Vicodin', price: 1300 },
|
||||
};
|
||||
// 缓存过期时间 分钟
|
||||
private readonly priceTimeout = 720;
|
||||
|
||||
// TODO 定时
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public async getItemData(idOrName: string): Promise<Partial<InventoryItemInfo>> {
|
||||
return await (await FetchUtils.getInstance().ajaxFetch({
|
||||
url: `/inventory.php?step=info&itemID=${ idOrName }&armouryID=0&asObject=true`,
|
||||
method: 'GET',
|
||||
referrer: 'bazaar.php',
|
||||
})).json();
|
||||
}
|
||||
|
||||
/**
|
||||
* 物品查价-缓存
|
||||
* @param idOrName
|
||||
*/
|
||||
public getItemPrice(idOrName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 物品查价-API
|
||||
* @param idOrName
|
||||
*/
|
||||
public getItemPriceApi(idOrName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 物品查价值
|
||||
*/
|
||||
public async getItemValue(idOrName) {
|
||||
return (await this.getItemData(idOrName)).itemValue.replaceAll(/[,$]/, '');
|
||||
}
|
||||
|
||||
public getLocalPriceData(): { priceData: PriceData, promise: Promise<PriceData> } {
|
||||
// 获取本地缓存
|
||||
let localStore = localStorage.getItem('WHItemPrice');
|
||||
let res = { priceData: null, promise: null };
|
||||
let data: PriceData = null;
|
||||
// 无缓存
|
||||
if (!localStore) {
|
||||
res.promise = this.fetchPriceData();
|
||||
return res;
|
||||
}
|
||||
// 解析缓存
|
||||
try {
|
||||
data = JSON.parse(localStore);
|
||||
} catch (e) {
|
||||
Log.error(e.stack || e.message || e);
|
||||
throw new Error('JSON解析错误');
|
||||
}
|
||||
// 缓存超时
|
||||
if (Date.now() - data.timestamp > this.priceTimeout * 60000) {
|
||||
res.priceData = null;
|
||||
res.promise = this.fetchPriceData();
|
||||
} else {
|
||||
res.priceData = data;
|
||||
res.promise = null;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private async fetchPriceData(): Promise<PriceData> {
|
||||
let res = null;
|
||||
// 获取在线价格
|
||||
try {
|
||||
res = JSON.parse(await CommonUtils.COFetch('https://jjins.github.io/item_price_raw.json'))
|
||||
} catch (err) {
|
||||
Log.error(err.stack || err.message || err);
|
||||
throw new Error('获取在线价格时出错');
|
||||
}
|
||||
// 更新缓存
|
||||
let localData: PriceData = {
|
||||
timestamp: Date.now(),
|
||||
data: res,
|
||||
};
|
||||
localStorage.setItem('WHItemPrice', JSON.stringify(localData));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
interface PriceData {
|
||||
timestamp: number
|
||||
data: {
|
||||
[k: number]: {
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,13 +2,25 @@ import WuhuBase from "../WuhuBase";
|
||||
import POPUP_HTML from "../../static/html/popup.html";
|
||||
import Log from "../Log";
|
||||
|
||||
/**
|
||||
* 弹窗
|
||||
*/
|
||||
export default class Popup extends WuhuBase {
|
||||
className = 'Popup';
|
||||
private readonly container: HTMLElement = null;
|
||||
private readonly node: HTMLElement = null;
|
||||
private onClosing: () => unknown;
|
||||
|
||||
constructor(innerHTML: string, title: string = '芜湖助手') {
|
||||
/**
|
||||
* 构造新弹窗
|
||||
* @param innerHTML
|
||||
* @param title
|
||||
* @param onClosing
|
||||
*/
|
||||
constructor(innerHTML: string, title: string = '芜湖助手', onClosing: () => unknown = () => {
|
||||
}) {
|
||||
super();
|
||||
this.onClosing = onClosing;
|
||||
if (Popup.glob.popup_node) {
|
||||
Log.info('关闭前一个弹窗');
|
||||
Popup.glob.popup_node.close();
|
||||
@ -29,6 +41,7 @@ export default class Popup extends WuhuBase {
|
||||
}
|
||||
|
||||
public close() {
|
||||
this.onClosing();
|
||||
this.container.remove();
|
||||
this.showChat();
|
||||
}
|
||||
@ -51,4 +64,16 @@ export default class Popup extends WuhuBase {
|
||||
// 禁止单例调用
|
||||
private getInstance() {
|
||||
}
|
||||
|
||||
public setOnClosing(onClosing): void {
|
||||
if (!onClosing) {
|
||||
throw new Error('无方法用于设置onClosing');
|
||||
}
|
||||
this.onClosing = onClosing;
|
||||
}
|
||||
|
||||
public closing(func: () => unknown): Popup {
|
||||
this.setOnClosing(func);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
5
src/ts/decs/TestDeco.ts
Normal file
5
src/ts/decs/TestDeco.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import Log from "../class/Log";
|
||||
|
||||
export default function (tar: unknown) {
|
||||
Log.info("TestDeco", tar);
|
||||
}
|
||||
@ -1,13 +1,22 @@
|
||||
import toThousands from "../utils/toThousands";
|
||||
import CommonUtils from "../../class/utils/CommonUtils";
|
||||
import Log from "../../class/Log";
|
||||
import CITY_FINDER_CSS from "../../static/css/city_finder.css";
|
||||
import TornStyleBlock from "../../class/utils/TornStyleBlock";
|
||||
import ItemHelper from "../../class/utils/ItemHelper";
|
||||
|
||||
/**
|
||||
* 2023-02-22 修改物品价格查询逻辑,缓存优先
|
||||
* @param _base
|
||||
*/
|
||||
export default function cityFinder(_base: TornStyleBlock): void {
|
||||
CommonUtils.addStyle(CITY_FINDER_CSS);
|
||||
// 物品名与价格
|
||||
let items = null;
|
||||
let items: {
|
||||
[k: number]: {
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
} = null;
|
||||
// const base = document.createElement('div');
|
||||
// base.id = 'wh-city-finder';
|
||||
// const container = document.createElement('div');
|
||||
@ -24,12 +33,13 @@ export default function cityFinder(_base: TornStyleBlock): void {
|
||||
_base.append(header, info);
|
||||
document.body.classList.add('wh-city-finds');
|
||||
|
||||
CommonUtils.COFetch('https://jjins.github.io/item_price_raw.json')
|
||||
.then(r => items = JSON.parse(r))
|
||||
.catch(err => {
|
||||
Log.error(err);
|
||||
items = undefined
|
||||
});
|
||||
// CommonUtils.COFetch('https://jjins.github.io/item_price_raw.json')
|
||||
// .then(r => items = JSON.parse(r))
|
||||
// .catch(err => {
|
||||
// Log.error(err);
|
||||
// items = undefined
|
||||
// });
|
||||
let itemHelper = ItemHelper.getInstance();
|
||||
CommonUtils.elementReady('div.leaflet-marker-pane').then(elem => {
|
||||
// document.querySelector('.content-wrapper').prepend(base);
|
||||
|
||||
@ -73,29 +83,40 @@ export default function cityFinder(_base: TornStyleBlock): void {
|
||||
header.innerHTML = `捡垃圾助手 - ${ founds.length } 个物品,总价值 $${ toThousands(total) }`;
|
||||
// _base.setTitle(`捡垃圾助手 - ${ founds.length } 个物品,总价值 $${ toThousands(total) }`);
|
||||
};
|
||||
// 未取到数据时添加循环来调用函数
|
||||
if (items === null) {
|
||||
// 15s超时
|
||||
let timeout = 30;
|
||||
const interval = window.setInterval(() => {
|
||||
timeout--;
|
||||
if (items !== null) {
|
||||
displayNamePrice();
|
||||
window.clearInterval(interval);
|
||||
}
|
||||
if (0 === timeout) {
|
||||
Log.info('获取物品名称与价格信息超时')
|
||||
window.clearInterval(interval)
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
// 无法跨域获取数据时
|
||||
else if (items === undefined) {
|
||||
info.innerHTML += '(当前平台暂不支持查询价格)';
|
||||
}
|
||||
// 调用函数
|
||||
else {
|
||||
// // 未取到数据时添加循环来调用函数
|
||||
// if (items === null) {
|
||||
// // 15s超时
|
||||
// let timeout = 30;
|
||||
// const interval = window.setInterval(() => {
|
||||
// timeout--;
|
||||
// if (items !== null) {
|
||||
// displayNamePrice();
|
||||
// window.clearInterval(interval);
|
||||
// }
|
||||
// if (0 === timeout) {
|
||||
// Log.info('获取物品名称与价格信息超时')
|
||||
// window.clearInterval(interval)
|
||||
// }
|
||||
// }, 500);
|
||||
// }
|
||||
// // 无法跨域获取数据时
|
||||
// else if (items === undefined) {
|
||||
// info.innerHTML += '(当前平台暂不支持查询价格)';
|
||||
// }
|
||||
// // 调用函数
|
||||
// else {
|
||||
// displayNamePrice();
|
||||
// }
|
||||
|
||||
let priceData = itemHelper.getLocalPriceData();
|
||||
if (priceData.priceData) {
|
||||
items = priceData.priceData.data;
|
||||
displayNamePrice();
|
||||
} else {
|
||||
window.setTimeout(async () => {
|
||||
items = (await priceData.promise).data;
|
||||
displayNamePrice();
|
||||
}, 0);
|
||||
}
|
||||
})
|
||||
}
|
||||
22
src/ts/interface/ResponseInject.ts
Normal file
22
src/ts/interface/ResponseInject.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 处理网络请求响应的类型
|
||||
*/
|
||||
export default interface ResponseInject {
|
||||
/**
|
||||
* @param url 请求url
|
||||
* @param body 响应体代理
|
||||
* @param opt 请求参数
|
||||
*/
|
||||
responseHandler(
|
||||
url: string,
|
||||
body: {
|
||||
json: unknown,
|
||||
text: string,
|
||||
isModified: boolean
|
||||
},
|
||||
opt: {
|
||||
method: 'GET' | 'POST',
|
||||
requestBody: string
|
||||
}
|
||||
): void
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
* 物品详情
|
||||
*/
|
||||
export default interface InventoryItemInfo {
|
||||
itemID: 816
|
||||
itemID: number
|
||||
itemInfo: string
|
||||
// html 格式
|
||||
itemInfoContent: string
|
||||
@ -10,4 +10,5 @@ export default interface InventoryItemInfo {
|
||||
// html 格式
|
||||
itemRareTitle: string
|
||||
itemType: "Item"
|
||||
itemValue: string
|
||||
}
|
||||
|
||||
@ -1,65 +1,69 @@
|
||||
<div class="acc-title">
|
||||
<span class="item-desc">
|
||||
<span aria-labelledby="180-name 180-price 180-stock" class="item Alcohol" itemid="180" loaded="0" tabindex="0">
|
||||
<img alt="Bottle of Beer" aria-hidden="true" class="torn-item item-plate" data-converted="1"
|
||||
data-size="large" id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f-old" src="/images/items/180/large.png"
|
||||
style="opacity: 0;">
|
||||
<span class="item-hover">
|
||||
<button aria-label="Show info: Bottle of Beer" class="view-h wai-btn" i-data="i_723_228_51_52" value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-h wai-btn" i-data="i_774_228_51_52" value="100"></button>
|
||||
</span>
|
||||
<canvas aria-label="Bottle of Beer" class="torn-item item-plate item-converted" height="50"
|
||||
id="item-1bea9f66-a6c4-475c-accb-41dcb67af64f"
|
||||
item-mode="light" role="img" style="opacity: 1;" width="100"></canvas></span>
|
||||
<span class="desc">
|
||||
<span class="name t-overflow bold" id="180-name">啤酒</span>
|
||||
<span class="price t-gray-6" data-sell="$5" id="180-price">$10</span>
|
||||
<span class="stock t-gray-6 t-overflow" id="180-stock">酒 (<span class="instock">1100</span>存货)</span>
|
||||
</span>
|
||||
<span class="buy-act-wrap">
|
||||
<label class="wai" for="180">Amount
|
||||
of Bottle of Beer</label>
|
||||
<input autocomplete="new-amount" id="180" maxlength="3" name="buyAmount[]" type="text" value="100">
|
||||
<span class="buy-act bold">
|
||||
<button class="wai-support t-blue h">买</button>
|
||||
<div class="tt-max-buy-overlay"></div>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<div class="confirm-wrap">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
点击确定购买
|
||||
</span>
|
||||
<span>
|
||||
<span class="count">100</span>
|
||||
瓶啤酒
|
||||
$<span class="total">1,000</span>
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#" i-data="i_819_263_23_16">
|
||||
确定
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#" i-data="i_852_263_18_16">
|
||||
不
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="item-desc tt-buy" style="display: inline-block;">
|
||||
<span aria-labelledby="180-name 180-price 180-stock" class="item Alcohol" itemid="180" loaded="0" tabindex="0">
|
||||
<span class="item-plate">
|
||||
<img alt="Bottle of Beer" class="torn-item large" src="/images/items/180/large.png">
|
||||
</span>
|
||||
<span class="item-hover">
|
||||
<button aria-label="Show info: Bottle of Beer" class="view-h wai-btn" value="100"></button>
|
||||
<button aria-label="Buy: Bottle of Beer" class="buy-h wai-btn" i-data="i_661_346_51_52" value="100"></button>
|
||||
</span>
|
||||
</span>
|
||||
<span class="desc">
|
||||
<span id="180-name" class="name t-overflow bold">一瓶啤酒</span>
|
||||
<span id="180-price" class="price t-gray-6" data-sell="$5">$10</span>
|
||||
<span id="180-stock" class="stock t-gray-6 t-overflow">Alcohol (<span class="instock">600</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" i-data="i_815_375_53_34" 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" style="display: none;">
|
||||
<span class="confirm">
|
||||
<span>
|
||||
确定购买
|
||||
</span>
|
||||
<span>
|
||||
<span class="count">100</span>
|
||||
x Bottle of Beer for
|
||||
$<span class="total">1,000</span>
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
<a class="wai-support yes m-right10 bold t-blue h" data-id="180" href="#" i-data="i_705_379_24_14">
|
||||
Yes
|
||||
</a>
|
||||
<span class="no bold">
|
||||
<a class="wai-support t-blue h" href="#" i-data="i_740_379_16_14">
|
||||
No
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="success-wrap">
|
||||
<span class="success">
|
||||
<span class="t-red bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
</span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" i-data="i_954_228_10_11" value="100"></button>
|
||||
<div class="success-wrap" style="display: none;">
|
||||
<span class="success"><span class="t-red bold">
|
||||
There is not enough stock left to buy <b>100</b> of this item.
|
||||
</span>
|
||||
<span class="confirm-act m-top5">
|
||||
|
||||
<a class="items m-right10 bold t-blue h" href="item.php">Your Items</a>
|
||||
|
||||
|
||||
</span></span>
|
||||
<button aria-label="Close" class="close-icon p0 wai-btn" i-data="i_840_344_10_11" value="100"></button>
|
||||
</div>
|
||||
<div class="msg-wrap">
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
<span class="t-green bold">
|
||||
<span class="ajax-preloader"></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view-item-info">
|
||||
|
||||
@ -1,47 +1,56 @@
|
||||
import WuhuBase from "../class/WuhuBase";
|
||||
import Log from "../class/Log";
|
||||
import CommonUtils from "../class/utils/CommonUtils";
|
||||
import Popup from "../class/utils/Popup";
|
||||
import CompanyHelper from "../class/action/CompanyHelper";
|
||||
import globVars from "../globVars";
|
||||
import { createApp } from "vue";
|
||||
import ItemPrice from "../vue/ItemPrice.vue"
|
||||
|
||||
export default class Test extends WuhuBase {
|
||||
className = 'Test';
|
||||
|
||||
public test(): void {
|
||||
let popup = new Popup(CommonUtils.getInstance().getTravelStage().toString());
|
||||
let popup = new Popup(
|
||||
// '<input v-model="itemNameInput" placeholder="输入物品名(英)" /><br/>' +
|
||||
// '<select v-if="itemNameInput" v-on:select=""><option v-for="item in filteredItems">{{ item }}</option></select>' +
|
||||
// '<p v-if="itemInfo"></p>' +
|
||||
''
|
||||
);
|
||||
popup.getElement()['__POOL__'] = Test.getPool();
|
||||
Log.info({ NET: globVars.WH_NET_LOG });
|
||||
|
||||
// this.case1()
|
||||
// this.case2()
|
||||
// this.case3().then();
|
||||
// let vueApp = createApp({
|
||||
// data() {
|
||||
// return {
|
||||
// itemNameInput: "",
|
||||
// itemInfo:{}
|
||||
// }
|
||||
// },
|
||||
// computed: {
|
||||
// filteredItems() {
|
||||
// let arr = ['123', '456', '789', '135', '246', '357', '579'];
|
||||
// let out = [];
|
||||
// if (this.itemNameInput) {
|
||||
// arr.forEach(v => {
|
||||
// v.includes(this.itemNameInput) && out.push(v);
|
||||
// })
|
||||
// }
|
||||
// return out;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
let vueApp = createApp(ItemPrice);
|
||||
vueApp.mount('#wh-popup-cont');
|
||||
popup.setOnClosing(() => vueApp.unmount());
|
||||
}
|
||||
|
||||
private case1() {
|
||||
const temp = document.createElement("DIV");
|
||||
const temp2 = document.createElement("DIV");
|
||||
|
||||
// @ts-ignore
|
||||
temp.append(...document.body.childNodes);
|
||||
// @ts-ignore
|
||||
temp2.append(...document.head.childNodes);
|
||||
temp2.querySelectorAll('script[src*="google"]').forEach(item => item.remove());
|
||||
temp2.querySelectorAll('#gtm_tag').forEach(item => item.remove());
|
||||
temp2.querySelectorAll('script[src*="chat/gonline"]').forEach(item => item.remove());
|
||||
temp2.querySelectorAll('script[nonce]').forEach(item => item.remove());
|
||||
|
||||
window.stop();
|
||||
|
||||
// document.body.outerHTML = document.body.outerHTML;
|
||||
Log.info(document.body.outerHTML);
|
||||
document.body.innerHTML = "";
|
||||
document.head.innerHTML = "";
|
||||
// @ts-ignore
|
||||
document.body.append(...temp.childNodes);
|
||||
// @ts-ignore
|
||||
// document.head.append(...temp2.childNodes);
|
||||
document.body.insertAdjacentHTML('afterbegin', temp2.innerHTML);
|
||||
// FetchUtils.getInstance().ajaxFetch({
|
||||
// url: '/inventory.php?step=info&itemID=205&armouryID=0&asObject=true',
|
||||
//
|
||||
// method: 'GET',
|
||||
// referrer: 'bazaar.php',
|
||||
// });
|
||||
// ItemValueQueryHandler.getInstance().show();
|
||||
}
|
||||
|
||||
private case2() {
|
||||
|
||||
13
src/ts/vue/Hello.vue
Normal file
13
src/ts/vue/Hello.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Hello"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
45
src/ts/vue/ItemPrice.vue
Normal file
45
src/ts/vue/ItemPrice.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<input v-model="itemNameInput" placeholder="输入物品名(英)"/><br/>
|
||||
<select v-if="itemNameInput" v-on:select="">
|
||||
<option v-for="item in filteredItems">{{ item }}</option>
|
||||
</select>
|
||||
<p v-if="itemInfo">
|
||||
{{ itemInfo.value }}
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Hello from "./Hello.vue";
|
||||
|
||||
export default {
|
||||
name: "ItemPrice",
|
||||
components: { Hello },
|
||||
data() {
|
||||
return {
|
||||
itemNameInput: "",
|
||||
itemInfo: {
|
||||
value: 100
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredItems() {
|
||||
let arr = ['123', '456', '789', '135', '246', '357', '579'];
|
||||
let out = [];
|
||||
if (this.itemNameInput) {
|
||||
arr.forEach(v => {
|
||||
v.includes(this.itemNameInput) && out.push(v);
|
||||
})
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
p {
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
@ -10,7 +10,10 @@
|
||||
"removeComments": true,
|
||||
"sourceMap": false,
|
||||
"resolveJsonModule": true,
|
||||
// "strict": true,
|
||||
"jsx": "react-native"
|
||||
"strict": false,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"strictNullChecks": false,
|
||||
"strictFunctionTypes": false
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user