更新
This commit is contained in:
parent
0c6ab02e8d
commit
3104ea2b53
@ -5,6 +5,14 @@
|
|||||||
|
|
||||||
# CHANGE
|
# CHANGE
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
2023年06月12日
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- PT购买
|
||||||
|
|
||||||
## 0.9.9
|
## 0.9.9
|
||||||
|
|
||||||
2023年06月07日
|
2023年06月07日
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -66,41 +66,37 @@
|
|||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<el-dialog
|
<el-dialog v-model="drawer" :destroy-on-close="true" :fullscreen="isMobilePhone" :lock-scroll="true"
|
||||||
v-model="drawer"
|
:title="drawerTitle" width="65%">
|
||||||
:destroy-on-close="true"
|
|
||||||
:title="drawerTitle"
|
|
||||||
:fullscreen="isMobilePhone"
|
|
||||||
:lock-scroll="true"
|
|
||||||
width="65%"
|
|
||||||
>
|
|
||||||
<component :is="drawerContent"/>
|
<component :is="drawerContent"/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</el-config-provider>
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { MoonNight } from "@element-plus/icons-vue";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { inject, onMounted, ref, shallowRef } from 'vue';
|
import { inject, onMounted, ref, shallowRef } from 'vue';
|
||||||
import { LoggerKey } from "../ts/class/Logger";
|
import { LoggerKey } from "../ts/class/Logger";
|
||||||
import ForeignStock from "./ForeignStock.vue";
|
|
||||||
import { MoonNight } from "@element-plus/icons-vue";
|
|
||||||
import Config from "./Config.vue";
|
|
||||||
import { QuickGymTrainKey } from "../ts/class/action/QuickGymTrain";
|
import { QuickGymTrainKey } from "../ts/class/action/QuickGymTrain";
|
||||||
import { BATTLE_STAT } from "../ts/class/utils/NetHighLvlWrapper";
|
|
||||||
import { QuickFlyBtnHandlerKey } from "../ts/class/handler/QuickFlyBtnHandler";
|
import { QuickFlyBtnHandlerKey } from "../ts/class/handler/QuickFlyBtnHandler";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { BATTLE_STAT } from "../ts/class/utils/NetHighLvlWrapper";
|
||||||
import QuickCrime from "./QuickCrime.vue";
|
|
||||||
import EventsViewer from "./EventsViewer.vue";
|
|
||||||
import CityUItems from "./CityUItems.vue";
|
|
||||||
import AutoLoginForm from "./AutoLoginForm.vue";
|
import AutoLoginForm from "./AutoLoginForm.vue";
|
||||||
import VirusProgramming from "./VirusProgramming.vue";
|
import CityUItems from "./CityUItems.vue";
|
||||||
|
import Config from "./Config.vue";
|
||||||
|
import EventsViewer from "./EventsViewer.vue";
|
||||||
|
import ForeignStock from "./ForeignStock.vue";
|
||||||
import MarketHelper from "./MarketHelper.vue";
|
import MarketHelper from "./MarketHelper.vue";
|
||||||
|
import PTMarketView from "./PTMarketView.vue";
|
||||||
|
import QuickCrime from "./QuickCrime.vue";
|
||||||
|
import VirusProgramming from "./VirusProgramming.vue";
|
||||||
|
|
||||||
const logger = inject(LoggerKey);
|
const logger = inject(LoggerKey);
|
||||||
const quickGymTrain = inject(QuickGymTrainKey);
|
const quickGymTrain = inject(QuickGymTrainKey);
|
||||||
const quickFlyBtnHandler = inject(QuickFlyBtnHandlerKey);
|
const quickFlyBtnHandler = inject(QuickFlyBtnHandlerKey);
|
||||||
|
|
||||||
const useItem = (itemId) => {
|
const useItem = (itemId: string) => {
|
||||||
fetch(window.addRFC("https://www.torn.com/item.php"), {
|
fetch(window.addRFC("https://www.torn.com/item.php"), {
|
||||||
"headers": {
|
"headers": {
|
||||||
"accept": "*/*",
|
"accept": "*/*",
|
||||||
@ -133,19 +129,17 @@ const useItem = (itemId) => {
|
|||||||
const menuItemList = [
|
const menuItemList = [
|
||||||
{
|
{
|
||||||
title: '💊 吃 XAN',
|
title: '💊 吃 XAN',
|
||||||
template: () => useItem(206),
|
template: () => useItem('206'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '🍺 喝啤酒',
|
title: '🍺 喝啤酒',
|
||||||
template: () => useItem(180),
|
template: () => useItem('180'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '♻️ REFILL',
|
title: '♻️ REFILL',
|
||||||
template: () => fetch(window.addRFC("https://www.torn.com/points.php?step=pointsbuy&action=energyrefill2"), {
|
template: () => fetch(window.addRFC("https://www.torn.com/points.php?step=pointsbuy&action=energyrefill2"), {
|
||||||
"headers": {
|
"headers": {
|
||||||
"accept": "text/plain, */*; q=0.01",
|
"accept": "text/plain, */*; q=0.01",
|
||||||
"accept-language": "zh-CN,zh;q=0.9",
|
|
||||||
"sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"92\"",
|
|
||||||
"sec-ch-ua-mobile": "?0",
|
"sec-ch-ua-mobile": "?0",
|
||||||
"sec-fetch-dest": "empty",
|
"sec-fetch-dest": "empty",
|
||||||
"sec-fetch-mode": "cors",
|
"sec-fetch-mode": "cors",
|
||||||
@ -161,8 +155,8 @@ const menuItemList = [
|
|||||||
})
|
})
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => ElMessage({
|
.then(res => ElMessage({
|
||||||
message: res.msg,
|
message: `<p>${ res.msg }</p><p>剩余refill: ${ res.refills }</p>`,
|
||||||
type: res.success ? 'success' : 'error',
|
type: res.state === 'done' ? 'success' : 'error',
|
||||||
dangerouslyUseHTMLString: true
|
dangerouslyUseHTMLString: true
|
||||||
}))
|
}))
|
||||||
.catch(e => ElMessage({
|
.catch(e => ElMessage({
|
||||||
@ -198,6 +192,10 @@ const menuItemList = [
|
|||||||
title: '🛒 购物助手',
|
title: '🛒 购物助手',
|
||||||
template: MarketHelper,
|
template: MarketHelper,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '🅿️ PT购买',
|
||||||
|
template: PTMarketView,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '⚙️ 插件配置',
|
title: '⚙️ 插件配置',
|
||||||
template: Config,
|
template: Config,
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="itemInfo.id !== -1">
|
<div v-if="itemInfo.id !== -1">
|
||||||
<p><img :alt="itemInfo.id" :src="`/images/items/${itemInfo.id}/medium.png`"/></p>
|
<p><img :alt="itemInfo.id.toString()" :src="`/images/items/${itemInfo.id}/medium.png`"/></p>
|
||||||
<p>
|
<p>
|
||||||
物品名:{{ itemInfo.name }}{{ itemNameDict[itemInfo.name] ? '(' + itemNameDict[itemInfo.name] + ')' : '' }}
|
物品名:{{ itemInfo.name }}{{ itemNameDict[itemInfo.name] ? '(' + itemNameDict[itemInfo.name] + ')' : '' }}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -80,7 +80,6 @@ type ItemInfo = {
|
|||||||
price: number,
|
price: number,
|
||||||
amount: number,
|
amount: number,
|
||||||
inputAmount: number,
|
inputAmount: number,
|
||||||
// index: number,
|
|
||||||
onBuying: boolean,
|
onBuying: boolean,
|
||||||
itemId: string,
|
itemId: string,
|
||||||
};
|
};
|
||||||
|
|||||||
149
src/vue/PTMarketView.vue
Normal file
149
src/vue/PTMarketView.vue
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { Refresh, ShoppingCart } from '@element-plus/icons-vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { inject, onMounted, ref } from 'vue';
|
||||||
|
import { LoggerKey } from '../ts/class/Logger';
|
||||||
|
|
||||||
|
const logger = inject(LoggerKey);
|
||||||
|
|
||||||
|
type TableData = {
|
||||||
|
player: string,
|
||||||
|
amount: string,
|
||||||
|
each: string,
|
||||||
|
totalPrice: string,
|
||||||
|
id: string,
|
||||||
|
onBuying: boolean,
|
||||||
|
afterBought: boolean,
|
||||||
|
};
|
||||||
|
const tableData = ref<TableData[]>([]);
|
||||||
|
const fetchingList = ref(false);
|
||||||
|
const buy = async (tableRowData: TableData): Promise<void> => {
|
||||||
|
tableRowData.onBuying = true;
|
||||||
|
let res: string;
|
||||||
|
let resJson: { color: 'red' | 'green', msg: string };
|
||||||
|
try {
|
||||||
|
res = await (await fetch(window.addRFC("https://www.torn.com/pmarket.php"), {
|
||||||
|
"headers": {
|
||||||
|
"accept": "*/*",
|
||||||
|
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"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/pmarket.php",
|
||||||
|
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||||
|
"body": "ajax_action=buy1&ID=" + tableRowData.id,
|
||||||
|
"method": "POST",
|
||||||
|
"mode": "cors",
|
||||||
|
"credentials": "include"
|
||||||
|
})).text();
|
||||||
|
resJson = JSON.parse(res);
|
||||||
|
} catch (error) {
|
||||||
|
tableRowData.onBuying = false;
|
||||||
|
ElMessage.error('购买失败 ' + error.message);
|
||||||
|
logger.error(error.stack);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
if (resJson.color === 'green') {
|
||||||
|
ElMessage.success('成功 ' + resJson.msg);
|
||||||
|
tableRowData.afterBought = true;
|
||||||
|
} else {
|
||||||
|
ElMessage.error('失败 ' + resJson.msg);
|
||||||
|
}
|
||||||
|
tableRowData.onBuying = false;
|
||||||
|
};
|
||||||
|
const fetchList = async (): Promise<void> => {
|
||||||
|
tableData.value = [];
|
||||||
|
fetchingList.value = true;
|
||||||
|
let fetchRes: string;
|
||||||
|
try {
|
||||||
|
fetchRes = await (await fetch(window.addRFC("https://www.torn.com/pmarket.php?ajax_action=refresh"), {
|
||||||
|
"headers": {
|
||||||
|
"accept": "text/plain, */*; q=0.01",
|
||||||
|
"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/pmarket.php",
|
||||||
|
"referrerPolicy": "strict-origin-when-cross-origin",
|
||||||
|
"body": null,
|
||||||
|
"method": "GET",
|
||||||
|
"mode": "cors",
|
||||||
|
"credentials": "include"
|
||||||
|
})).text();
|
||||||
|
} catch (e) {
|
||||||
|
fetchingList.value = false;
|
||||||
|
logger.error('PT出售列表获取错误', e.stack);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
let tmpNode = document.createElement('div');
|
||||||
|
tmpNode.innerHTML = fetchRes;
|
||||||
|
let itemNodeList = tmpNode.querySelectorAll('li .expander');
|
||||||
|
if (!itemNodeList.length) {
|
||||||
|
tmpNode = null;
|
||||||
|
itemNodeList = null;
|
||||||
|
fetchingList.value = false;
|
||||||
|
logger.error('无法获取PT出售列表数据, 状态是否为Torn OK?');
|
||||||
|
ElMessage.error('无法获取PT出售列表数据, 状态是否为Torn OK?');
|
||||||
|
throw new Error('无法获取PT出售列表数据, 状态是否为Torn OK?');
|
||||||
|
}
|
||||||
|
for (let i = 0; i < itemNodeList.length; i++) {
|
||||||
|
const node = itemNodeList[i];
|
||||||
|
const tableRowData: TableData = {
|
||||||
|
player: '',
|
||||||
|
amount: '',
|
||||||
|
each: '',
|
||||||
|
totalPrice: '',
|
||||||
|
id: '',
|
||||||
|
onBuying: false,
|
||||||
|
afterBought: false
|
||||||
|
};
|
||||||
|
let href = node.getAttribute('href').trim();
|
||||||
|
tableRowData.amount = href.split('points=')[1];
|
||||||
|
tableRowData.player = node.querySelector('.user-info span[title]').getAttribute('title').trim().replaceAll(' ', '');
|
||||||
|
tableRowData.each = node.querySelector('.cost-each').innerText?.split('Cost each')[1].trim();
|
||||||
|
tableRowData.totalPrice = node.querySelector('.total-price').innerText?.split('Total price')[1].trim();
|
||||||
|
let hrefSplit = href.split('&');
|
||||||
|
for (let index = 0; index < hrefSplit.length; index++) {
|
||||||
|
const element = hrefSplit[index];
|
||||||
|
if (element.startsWith('ID=')) {
|
||||||
|
tableRowData.id = element.replace('ID=', '');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tableData.value.push(tableRowData);
|
||||||
|
}
|
||||||
|
fetchingList.value = false;
|
||||||
|
itemNodeList = null;
|
||||||
|
tmpNode = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-table :data="tableData" style="width: 100%">
|
||||||
|
<el-table-column label="玩家" prop="player"/>
|
||||||
|
<el-table-column label="数量" prop="amount"/>
|
||||||
|
<el-table-column label="单价" prop="each"/>
|
||||||
|
<el-table-column label="共计" prop="totalPrice"/>
|
||||||
|
<el-table-column>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button :disabled="scope.row.afterBought" :icon="ShoppingCart" :loading="scope.row.onBuying"
|
||||||
|
@click="buy(scope.row)"/>
|
||||||
|
</template>
|
||||||
|
<template #header>
|
||||||
|
<el-button :icon="Refresh" :loading="fetchingList" circle @click="fetchList"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
Loading…
x
Reference in New Issue
Block a user