This commit is contained in:
Liwanyi 2023-06-05 15:36:06 +08:00
parent 302006530e
commit 412198358d
4 changed files with 145 additions and 31 deletions

View File

@ -5,6 +5,19 @@
# CHANGE # CHANGE
## 0.9.7
2023年06月05日
### 添加
- bazaar快速开关店
- 购物助手
### 修改
- 部分样式修改
## 0.9.6 ## 0.9.6
2023年06月01日 2023年06月01日

View File

@ -1,6 +1,6 @@
{ {
"name": "wuhu-torn-helper", "name": "wuhu-torn-helper",
"version": "0.9.6", "version": "0.9.7",
"description": "芜湖助手", "description": "芜湖助手",
"scripts": { "scripts": {
"release": "cross-env NODE_ENV=production rollup -c && node build.mjs", "release": "cross-env NODE_ENV=production rollup -c && node build.mjs",

File diff suppressed because one or more lines are too long

View File

@ -15,13 +15,39 @@
</el-button> </el-button>
</el-col> </el-col>
</el-row> </el-row>
<div v-if="itemOnList"> <div v-if="itemOnList.length > 0">
<div v-for="item in itemOnList"> <span :style="{backgroundImage: 'url(/images/items/' + itemName2IdMap[itemName] + '/small.png)'}"
<div>{{ item.playerName }}[{{ item.playerId }}] ${{ toThousands(item.price) }} x {{ item.amount }}</div> style="display:inline-block;width:38px;height:19px;"/>
<el-input :model-value="item.amount"/> <el-table :data="itemOnList" style="width: 100%" table-layout="auto">
<el-button @click="buy(item.playerId)">购买</el-button> <el-table-column label="卖家">
</div> <template #default="scope">
<!-- <div style="display: flex; align-items: center"-->
<!-- v-text="scope.row.playerName + `[${scope.row.playerId}]`"></div>-->
<el-link
:href="'/bazaar.php?userId=' + scope.row.playerId" :underline="false"
target="_blank"
type="primary"
v-text="scope.row.playerName + `[${scope.row.playerId}]`"
/>
</template>
</el-table-column>
<el-table-column label="单价">
<template #default="scope">
<div style="display: flex; align-items: center" v-text="'$' + toThousands(scope.row.price)"></div>
</template>
</el-table-column>
<el-table-column label="在售" prop="amount"/>
<el-table-column label="批量购买">
<template #default="scope">
<el-input v-model="scope.row.inputAmount" style="width: 60px;"/>
<el-button :loading="scope.row.onBuying"
type="primary" @click="buy(itemName, itemName2IdMap[itemName], scope.row)">购买
</el-button>
</template>
</el-table-column>
</el-table>
</div> </div>
<el-skeleton v-if="listLoading" animated count="5" style="margin-top: 1em"/>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -37,17 +63,30 @@ import { LoggerKey } from "../ts/class/Logger";
import { ItemHelperKey } from "../ts/class/utils/ItemHelper"; import { ItemHelperKey } from "../ts/class/utils/ItemHelper";
import { itemNameDict } from "../ts/dictionary/translation"; import { itemNameDict } from "../ts/dictionary/translation";
import toThousands from "../ts/func/utils/toThousands"; import toThousands from "../ts/func/utils/toThousands";
import { ElMessage } from "element-plus";
const logger = inject(LoggerKey); const logger = inject(LoggerKey);
const itemHelper = inject(ItemHelperKey); const itemHelper = inject(ItemHelperKey);
let itemName2IdMap: { [p: string]: number } = null; let itemName2IdMap: { [p: string]: number } = null;
const itemName = ref(''); const itemName = ref<string>('');
const itemNameList = ref([]); const itemNameList = ref<{ value: string, label: string }[]>([]);
const html = ref(''); const html = ref<string>('');
const itemOnList = ref<{ playerId: string, playerName: string, price: string, amount: number }[]>([]); type ItemInfo = {
playerId: string,
playerName: string,
price: number,
amount: number,
inputAmount: number,
// index: number,
onBuying: boolean,
};
const itemOnList = ref<ItemInfo[]>([]);
const listLoading = ref<boolean>(false);
const doGetIMarketList = async (id) => { const doGetIMarketList = async (id) => {
itemOnList.value = [];
listLoading.value = true;
const queryItemListHtml = await (await fetch(window.addRFC("https://www.torn.com/imarket.php"), { const queryItemListHtml = await (await fetch(window.addRFC("https://www.torn.com/imarket.php"), {
"headers": { "headers": {
"accept": "*/*", "accept": "*/*",
@ -65,23 +104,38 @@ const doGetIMarketList = async (id) => {
"mode": "cors", "mode": "cors",
"credentials": "include" "credentials": "include"
})).text(); })).text();
itemOnList.value = []; listLoading.value = false;
const container = document.createElement('div');
let container = document.createElement('div');
container.innerHTML = queryItemListHtml; container.innerHTML = queryItemListHtml;
const list = container.querySelectorAll('ul.items>li'); const list = container.querySelectorAll('ul.items li.private-bazaar');
logger.info({ list }); logger.info({ list });
list.forEach(li => { list.forEach((li, index) => {
let item = { playerId: null, playerName: null, price: null, amount: null }; let item = {
playerId: null,
playerName: null,
price: null,
amount: null,
inputAmount: null,
index,
onBuying: false
};
item.playerId = li.querySelector("a.user.name").getAttribute('href').trim().split('XID=')[1]; item.playerId = li.querySelector("a.user.name").getAttribute('href').trim().split('XID=')[1];
item.playerName = li.querySelector("a.user.name span").innerText.trim(); item.playerName = li.querySelector("a.user.name span").innerText.trim();
item.price = Number(li.querySelector("span.cost-price").innerText.trim().replace('$', '').replaceAll(',', '')); item.price = Number(li.querySelector("span.cost-price").innerText.trim().replace('$', '').replaceAll(',', ''));
item.amount = Number(li.querySelector("span.cost-amount").innerText.trim().split(' ')[0].replace('(', "")) item.amount = Number(li.querySelector("span.cost-amount").innerText.trim().split(' ')[0].replace('(', ""))
item.inputAmount = item.amount;
itemOnList.value.push(item); itemOnList.value.push(item);
}); });
container = null;
}; };
const buy = async (userId) => { const buy = async (itemName: string, itemId: number, itemInfo: ItemInfo) => {
const bazaarItemList = await (await fetch( itemInfo.onBuying = true;
`https://www.torn.com/bazaar.php?sid=bazaarData&step=getBazaarItems&start=0&ID=${ userId }&order=default&by=asc&categorised=0&limit=1000&searchname=`, try {
// id bazaar
let bazaarId;
const bazaarItemList: { list: { bazaarID: string, itemID: string }[] } = await (await fetch(
`https://www.torn.com/bazaar.php?sid=bazaarData&step=getBazaarItems&start=0&ID=${ itemInfo.playerId }&order=default&by=asc&categorised=0&limit=1000&searchname=`,
{ {
"headers": { "headers": {
"accept": "*/*", "accept": "*/*",
@ -91,14 +145,61 @@ const buy = async (userId) => {
"sec-fetch-site": "same-origin", "sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest" "x-requested-with": "XMLHttpRequest"
}, },
"referrer": "https://www.torn.com/bazaar.php?userId=" + userId, "referrer": "https://www.torn.com/bazaar.php?userId=" + itemInfo.playerId,
"referrerPolicy": "strict-origin-when-cross-origin", "referrerPolicy": "strict-origin-when-cross-origin",
"body": null, "body": null,
"method": "GET", "method": "GET",
"mode": "cors", "mode": "cors",
"credentials": "include" "credentials": "include"
})).json(); })).json();
let bazaarId; for (let i = 0; i < bazaarItemList.list.length; i++) {
if (bazaarItemList.list[i].itemID === itemId.toString()) {
bazaarId = bazaarItemList.list[i].bazaarID;
break;
}
}
if (!bazaarId) {
ElMessage.error('上架商品未找到');
logger.error('物品id未找到对应bazaar项目', bazaarItemList, itemId);
(() => {
throw new Error('bazaarId为空')
})();
}
// baz
let buyResponse = await (await fetch("https://www.torn.com/bazaar.php?sid=bazaarData&step=buyItem", {
"headers": {
"accept": "*/*",
"sec-ch-ua-mobile": "?0",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest"
},
"referrer": "https://www.torn.com/bazaar.php?userId=" + itemInfo.playerId,
"referrerPolicy": "strict-origin-when-cross-origin",
"body": (() => {
const data = new FormData();
data.append('userID', itemInfo.playerId);
data.append('id', bazaarId);
data.append('itemID', itemId.toString());
data.append('amount', itemInfo.inputAmount.toString());
data.append('price', itemInfo.price.toString());
data.append('beforeval', (itemInfo.price * itemInfo.inputAmount).toString());
return data;
})(),
"method": "POST",
"mode": "cors",
"credentials": "include"
})).json();
if (!buyResponse.success) {
ElMessage.error('购买失败 ' + buyResponse.text);
}
} catch (e) {
logger.error(e.stack);
ElMessage.error('出错了 ' + e.message);
}
itemInfo.onBuying = false;
}; };
onMounted(async () => { onMounted(async () => {