test-server
This commit is contained in:
parent
fb146659c8
commit
a764948bc7
@ -13,10 +13,10 @@ function defaultDataResponseProcessor(data) {
|
||||
}
|
||||
|
||||
|
||||
export const API_PATH_MAIN = "https://hostapay.trade/api/v1/";
|
||||
export const API_PATH_TEST = "https://test.0x000f.ru/api/v1/";
|
||||
|
||||
let BasicURLValue = "https://hostapay.trade/api/v1/";
|
||||
|
||||
|
||||
let BasicURLValue = API_PATH_TEST;
|
||||
|
||||
async function makePost(url, data, options = undefined,
|
||||
responseProcessor = defaultResponseProcessor,
|
||||
|
@ -9,4 +9,15 @@ export function isStringEmptyOrSpaces(str) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function truncateMiddle(str, n) {
|
||||
if (str.length <= 2 * n) {
|
||||
return str; // Если длина строки меньше или равна 2n, то ничего не обрезаем
|
||||
}
|
||||
|
||||
const leftPart = str.slice(0, n); // Первые n символов
|
||||
const rightPart = str.slice(-n); // Последние n символов
|
||||
|
||||
return leftPart + '...' + rightPart; // Соединяем с "..."
|
||||
}
|
@ -47,6 +47,8 @@
|
||||
{#if jwtDecode(getAuthInfo()?.a)?.role == "4"}
|
||||
<li><a href="/admin/merchants">Мерчанты</a></li>
|
||||
<li><a href="/admin/currencies">Валюты</a></li>
|
||||
<li><a href="/admin/sms">СМС</a></li>
|
||||
<li><a href="/admin/withdrawals">Вывод средств</a></li>
|
||||
{/if}
|
||||
<!-- <li><a>Item 3</a></li> -->
|
||||
</ul>
|
||||
@ -78,6 +80,8 @@
|
||||
{#if jwtDecode(getAuthInfo()?.a)?.role == "4"}
|
||||
<li><a on:click={()=>{showMenu = false;}} href="/admin/merchants">Мерчанты</a></li>
|
||||
<li><a on:click={()=>{showMenu = false;}} href="/admin/currencies">Валюты</a></li>
|
||||
<li><a on:click={()=>{showMenu = false;}} href="/admin/sms">СМС</a></li>
|
||||
<li><a on:click={()=>{showMenu = false;}} href="/admin/withdrawals">Вывод средств</a></li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth";
|
||||
import { makePost } from "$lib/tools/requests/requests";
|
||||
import { API_PATH_TEST, API_PATH_MAIN, makePost } from "$lib/tools/requests/requests";
|
||||
import { sayError, sayInfo } from "$lib/tools/toaster/Toaster";
|
||||
import Pagination from "$lib/ui-components/pagination.svelte";
|
||||
import { redirect } from "$lib/tools/url/URLTools";
|
||||
@ -161,7 +161,7 @@
|
||||
try {
|
||||
|
||||
const response = await axios.get(
|
||||
"https://hostapay.trade/api/v1/loadFile?dispute=" +
|
||||
API_PATH_TEST + "loadFile?dispute=" +
|
||||
selectedDispute["order_id"],
|
||||
// "17731",
|
||||
{
|
||||
@ -338,7 +338,7 @@
|
||||
on:click={() => {
|
||||
axios
|
||||
.get(
|
||||
"https://hostapay.trade/api/v1/loadFile?dispute=" +
|
||||
API_PATH_TEST + "loadFile?dispute=" +
|
||||
selectedDispute["order_id"],
|
||||
{
|
||||
responseType: "blob",
|
||||
|
@ -220,6 +220,7 @@
|
||||
<option value="1">Пользователь</option>
|
||||
<option value="2">Модератор</option>
|
||||
<option value="4">Администратор</option>
|
||||
<option value="5">Тим лид</option>
|
||||
</select>
|
||||
<select
|
||||
bind:value={value_currency_code}
|
||||
|
@ -54,6 +54,7 @@
|
||||
return;
|
||||
}
|
||||
foundedDispute = res.data;
|
||||
console.log(foundedDispute);
|
||||
showFoundedOrderWindow = true;
|
||||
showLoadingFind = false;
|
||||
}
|
||||
@ -174,8 +175,12 @@
|
||||
</p>
|
||||
<p class="text-sm mt-3">Курс</p>
|
||||
<p>{foundedDispute["rate"]} {foundedDispute["currency_code"]}</p>
|
||||
<p class="text-sm mt-3">Владелец</p>
|
||||
<p>{foundedDispute["name"]}</p>
|
||||
<p class="text-sm mt-3">Карта</p>
|
||||
<p>{foundedDispute["cardnumber"]}</p>
|
||||
<p class="text-sm mt-3">Телефон</p>
|
||||
<p>{foundedDispute["phone"]}</p>
|
||||
<p class="text-sm mt-3">Время создания</p>
|
||||
<p>{foundedDispute["creationtime"]}</p>
|
||||
<!-- <p>{foundedDispute["closetime"]}</p> -->
|
||||
|
@ -2,7 +2,7 @@
|
||||
// @ts-nocheck
|
||||
|
||||
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth";
|
||||
import { makePost } from "$lib/tools/requests/requests";
|
||||
import { API_PATH_TEST, API_PATH_MAIN, makePost } from "$lib/tools/requests/requests";
|
||||
import { sayError, sayInfo } from "$lib/tools/toaster/Toaster";
|
||||
import Pagination from "$lib/ui-components/pagination.svelte";
|
||||
import { redirect } from "$lib/tools/url/URLTools";
|
||||
@ -451,7 +451,7 @@
|
||||
on:click={() => {
|
||||
axios
|
||||
.get(
|
||||
"https://hostapay.trade/api/v1/loadFile?dispute=" +
|
||||
API_PATH_TEST + "loadFile?dispute=" +
|
||||
selectedPayout["order_id"],
|
||||
{
|
||||
responseType: "blob",
|
||||
|
242
src/routes/sms/+page.svelte
Normal file
242
src/routes/sms/+page.svelte
Normal file
@ -0,0 +1,242 @@
|
||||
<script>
|
||||
// @ts-nocheck
|
||||
|
||||
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth";
|
||||
import { makePost } from "$lib/tools/requests/requests";
|
||||
import { sayError, sayInfo } from "$lib/tools/toaster/Toaster";
|
||||
import Pagination from "$lib/ui-components/pagination.svelte";
|
||||
|
||||
const headNamesMap = {
|
||||
amount: "Сумма",
|
||||
balance: "Баланс",
|
||||
card_currency: "Валюта карты",
|
||||
card_number: "Номер карты",
|
||||
comment: "Комментарий",
|
||||
currency: "Валюта",
|
||||
date_of_message_creation: "Время создания сообщения",
|
||||
from_bank_name: "Название банка",
|
||||
from_to: "Получатель",
|
||||
got_from_device_uuid: "Девайс UUID",
|
||||
initial_text:
|
||||
"Текст сообщения",
|
||||
matched_order_uuid: "Совпадение с заявкой",
|
||||
on_device_msg_creation: "Время сообщения на устройство",
|
||||
to_bank_id: "ID банка",
|
||||
type: "Тип",
|
||||
uuid: "UUID",
|
||||
requisite_type: "Тип реквизита"
|
||||
};
|
||||
|
||||
let selectedNotificationType = "push";
|
||||
let value_startTime = "";
|
||||
let value_endTime = "";
|
||||
|
||||
let totalPages = 1;
|
||||
let currentPage = 1;
|
||||
let disabledPages = false;
|
||||
let showLoadingNotifies = false;
|
||||
let notifications = [];
|
||||
let tableHeads = [];
|
||||
let noData = false;
|
||||
let value_token = "";
|
||||
async function getNotifications() {
|
||||
if (value_endTime === "" || value_startTime === "") {
|
||||
return;
|
||||
}
|
||||
noData = false;
|
||||
showLoadingNotifies = true;
|
||||
const res = await makePost(
|
||||
"admin/loadNotifications",
|
||||
{
|
||||
notification_type: selectedNotificationType === "push" ? 1 : 2,
|
||||
fromDate: formatDateTime(value_startTime),
|
||||
toDate: formatDateTime(value_endTime),
|
||||
token: (value_token.length >= 36 ? value_token:undefined),
|
||||
page: currentPage,
|
||||
},
|
||||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||||
);
|
||||
// console.log(res);
|
||||
// console.log(formatDateTime(value_startTime));
|
||||
// console.log(value_endTime);
|
||||
|
||||
if (res.error) {
|
||||
showLoadingNotifies = false;
|
||||
sayError("Не удалось получить уведомления");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(res.data.data) && res.data.data.length > 0) {
|
||||
let o = res.data.data[0];
|
||||
tableHeads = [...Object.keys(o)];
|
||||
notifications = [...res.data.data];
|
||||
totalPages = res.data.pages;
|
||||
if (notifications.length < 1) noData = true;
|
||||
} else {
|
||||
tableHeads = [];
|
||||
notifications = [];
|
||||
noData = true;
|
||||
}
|
||||
showLoadingNotifies = false;
|
||||
}
|
||||
|
||||
$: if(selectedNotificationType) {
|
||||
currentPage = 1;
|
||||
}
|
||||
$: if (value_startTime !== "" && value_endTime !== "") {
|
||||
currentPage = 1;
|
||||
getNotifications();
|
||||
}
|
||||
$: if(typeof value_token === 'string' && value_token.length >= 36 || value_token.length === 0) {
|
||||
currentPage = 1;
|
||||
getNotifications();
|
||||
}
|
||||
|
||||
function formatDateForStartup(date) {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
// Сегодняшняя дата
|
||||
const today = new Date();
|
||||
value_endTime = formatDateForStartup(today);
|
||||
|
||||
// Вчерашняя дата
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(today.getDate() - 1);
|
||||
value_startTime = formatDateForStartup(yesterday);
|
||||
|
||||
function formatDateTime(input) {
|
||||
// Создаем объект Date из значения инпута
|
||||
let date = new Date(input);
|
||||
|
||||
// Получаем значения
|
||||
let year = date.getFullYear();
|
||||
let month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
let day = String(date.getDate()).padStart(2, "0");
|
||||
let hours = String(date.getHours()).padStart(2, "0");
|
||||
let minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
let seconds = String(date.getSeconds()).padStart(2, "0");
|
||||
let milliseconds = String(date.getMilliseconds()).padStart(3, "0");
|
||||
|
||||
// Форматируем строку с временной зоной +03:00
|
||||
let timezoneOffsetMinutes = -date.getTimezoneOffset(); // инвертируем для правильного отображения
|
||||
|
||||
let sign = timezoneOffsetMinutes >= 0 ? "+" : "-";
|
||||
let offsetHours = String(
|
||||
Math.floor(Math.abs(timezoneOffsetMinutes) / 60)
|
||||
).padStart(2, "0");
|
||||
let offsetMinutes = String(Math.abs(timezoneOffsetMinutes) % 60).padStart(
|
||||
2,
|
||||
"0"
|
||||
);
|
||||
let timezoneOffset = `${sign}${offsetHours}:${offsetMinutes}`;
|
||||
|
||||
// Собираем финальную строку
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds} ${timezoneOffset}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="w-full flex flex-col gap-8">
|
||||
<div class="flex gap-4">
|
||||
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
|
||||
<h1 class="text-2xl font-semibold">Сообщения</h1>
|
||||
</div>
|
||||
<div
|
||||
class="flex w-full flex-col items-center bg-base-300 p-4 rounded-box overflow-x-auto"
|
||||
>
|
||||
<div class="flex flex-wrap w-full gap-8">
|
||||
<!-- toggle -->
|
||||
<div class="flex gap-2 items-center">
|
||||
<p
|
||||
class={(selectedNotificationType === "sms"
|
||||
? "text-primary"
|
||||
: "opacity-60") + " text-lg font-bold"}
|
||||
>
|
||||
SMS
|
||||
</p>
|
||||
<input
|
||||
on:change={(e) => {
|
||||
if (e.currentTarget.checked) {
|
||||
selectedNotificationType = "push";
|
||||
} else {
|
||||
selectedNotificationType = "sms";
|
||||
}
|
||||
getNotifications();
|
||||
}}
|
||||
type="checkbox"
|
||||
class="toggle border-base-content bg-base-content hover:bg-base-content"
|
||||
checked="checked"
|
||||
/>
|
||||
<p
|
||||
class={(selectedNotificationType === "push"
|
||||
? "text-primary"
|
||||
: "opacity-60") + " text-lg font-bold"}
|
||||
>
|
||||
Push
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<p>С:</p>
|
||||
<input
|
||||
bind:value={value_startTime}
|
||||
type="datetime-local"
|
||||
class="input input-bordered input-sm max-w-[200px]"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<p>По:</p>
|
||||
<input
|
||||
bind:value={value_endTime}
|
||||
type="datetime-local"
|
||||
class="input input-bordered input-sm max-w-[200px]"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<p>Токен:</p>
|
||||
<input type="text" bind:value={value_token} class="input input-sm input-bordered">
|
||||
</div>
|
||||
</div>
|
||||
<Pagination
|
||||
{totalPages}
|
||||
pageChangedCallback={(n) => {
|
||||
currentPage = n;
|
||||
getNotifications();
|
||||
}}
|
||||
disableButtons={disabledPages}
|
||||
css={"btn-neutral self-center mt-8"}
|
||||
/>
|
||||
<div class="overflow-x-auto mt-4 flex flex-col w-full">
|
||||
{#if showLoadingNotifies}
|
||||
<span class="loading self-center"></span>
|
||||
{:else if noData}
|
||||
<p class="self-center">Нет данных</p>
|
||||
{:else}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
{#each tableHeads as head}
|
||||
<th>{headNamesMap[head]}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each notifications as noti}
|
||||
<tr class="hover:bg-neutral group border-t-[2px] border-neutral">
|
||||
{#each tableHeads as head}
|
||||
<td class={head === "initial_text" ? "text-xs" : ""}
|
||||
>{noti[head]}</td
|
||||
>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
195
src/routes/withdrawals/+page.svelte
Normal file
195
src/routes/withdrawals/+page.svelte
Normal file
@ -0,0 +1,195 @@
|
||||
<script>
|
||||
// @ts-nocheck
|
||||
|
||||
import { getAuthInfo, makeAuthHeaderForAxios } from "$lib/auth/Auth";
|
||||
import { makePost } from "$lib/tools/requests/requests";
|
||||
import { truncateMiddle } from "$lib/tools/strings/Strings";
|
||||
import { sayError, sayInfo, sayWarning } from "$lib/tools/toaster/Toaster";
|
||||
import Pagination from "$lib/ui-components/pagination.svelte";
|
||||
|
||||
const headNamesMap = {
|
||||
address: "Адрес",
|
||||
amount: "Сумма",
|
||||
closetime: "Время закрытия",
|
||||
creationtime: "Время создания",
|
||||
is_active: "Статус",
|
||||
token: "Токен",
|
||||
tx_hash: "Хэш",
|
||||
uuid: "UUID",
|
||||
opt: "Опции",
|
||||
};
|
||||
|
||||
// let selectedNotificationType = "push";
|
||||
// let value_startTime = "";
|
||||
// let value_endTime = "";
|
||||
|
||||
let totalPages = 1;
|
||||
let currentPage = 1;
|
||||
let disabledPages = false;
|
||||
let showLoadingWithdrawals = false;
|
||||
let withdrawals = [];
|
||||
let tableHeads = [];
|
||||
let noData = false;
|
||||
// let value_token = "";
|
||||
async function getWithdrawals() {
|
||||
noData = false;
|
||||
showLoadingWithdrawals = true;
|
||||
const res = await makePost(
|
||||
"admin/getWithdrawals",
|
||||
{
|
||||
page: currentPage,
|
||||
},
|
||||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||||
);
|
||||
// console.log(res);
|
||||
// console.log(formatDateTime(value_startTime));
|
||||
// console.log(value_endTime);
|
||||
|
||||
if (res.error) {
|
||||
showLoadingWithdrawals = false;
|
||||
sayError("Не удалось получить уведомления");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(res.data.data) && res.data.data.length > 0) {
|
||||
let o = res.data.data[0];
|
||||
tableHeads = [...Object.keys(o), "opt"];
|
||||
withdrawals = [...res.data.data];
|
||||
totalPages = res.data.pages;
|
||||
if (withdrawals.length < 1) noData = true;
|
||||
} else {
|
||||
tableHeads = [];
|
||||
withdrawals = [];
|
||||
noData = true;
|
||||
}
|
||||
showLoadingWithdrawals = false;
|
||||
}
|
||||
getWithdrawals();
|
||||
|
||||
let txHash_value = "";
|
||||
let uuid_value = "";
|
||||
let showClosingWindow = false;
|
||||
let showLoadingClosing = false;
|
||||
async function closeWithdrawal() {
|
||||
if (txHash_value.length <= 10 && uuid_value.length <= 10) {
|
||||
sayWarning("Проверьте введенные данные");
|
||||
return;
|
||||
}
|
||||
showLoadingClosing = true;
|
||||
const res = await makePost(
|
||||
"admin/closeWithrawal",
|
||||
{
|
||||
tx_hash: txHash_value,
|
||||
uuid: uuid_value,
|
||||
},
|
||||
makeAuthHeaderForAxios(getAuthInfo()?.a)
|
||||
);
|
||||
if (res.error) {
|
||||
sayError("Не удалось закрыть заявку");
|
||||
showLoadingClosing = false;
|
||||
return;
|
||||
}
|
||||
showClosingWindow = false;
|
||||
showLoadingClosing = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="w-full flex flex-col gap-8">
|
||||
<div class="flex gap-4">
|
||||
<div class="bg-accent rounded-[4px] w-[10px] h-full"></div>
|
||||
<h1 class="text-2xl font-semibold">Вывод средств</h1>
|
||||
</div>
|
||||
<div
|
||||
class="flex w-full flex-col items-center bg-base-300 p-4 rounded-box overflow-x-auto"
|
||||
>
|
||||
<Pagination
|
||||
{totalPages}
|
||||
pageChangedCallback={(n) => {
|
||||
currentPage = n;
|
||||
getWithdrawals();
|
||||
}}
|
||||
disableButtons={disabledPages}
|
||||
css={"btn-neutral self-center mt-8"}
|
||||
/>
|
||||
<div class="overflow-x-auto mt-4 flex flex-col w-full">
|
||||
{#if showLoadingWithdrawals}
|
||||
<span class="loading self-center"></span>
|
||||
{:else if noData}
|
||||
<p class="self-center">Нет данных</p>
|
||||
{:else}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
{#each tableHeads as head}
|
||||
<th>{headNamesMap[head]}</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each withdrawals as noti}
|
||||
<tr class="hover:bg-neutral group border-t-[2px] border-neutral">
|
||||
{#each tableHeads as head}
|
||||
{#if head === "tx_hash" || head === "address"}
|
||||
<td class={head === "initial_text" ? "text-xs" : ""}
|
||||
>{truncateMiddle(noti[head], 4)}</td
|
||||
>
|
||||
{:else if head === "is_active"}
|
||||
<td
|
||||
class={noti[head] === "t" ? "text-success" : "text-error"}
|
||||
>{noti[head] === "t" ? "Активна" : "Неактивна"}</td
|
||||
>
|
||||
{:else if head === "amount"}
|
||||
<td>{(Number(noti[head]) / 1e6).toFixed(0)} USDT</td>
|
||||
{:else if head === "opt" && noti["is_active"] === "t"}
|
||||
<td>
|
||||
<button on:click={()=>{showClosingWindow = true;}} class="btn btn-info">Закрыть заявку</button>
|
||||
</td>
|
||||
{:else}
|
||||
<td class={head === "initial_text" ? "text-xs" : ""}
|
||||
>{noti[head]}</td
|
||||
>
|
||||
{/if}
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if showClosingWindow}
|
||||
<div class="fixed inset-0 flex justify-center items-center z-[1000] bg-base-100 bg-opacity-50">
|
||||
<div class="bg-base-300 p-4 rounded-lg flex flex-col">
|
||||
<p>Хэш</p>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-bordered"
|
||||
bind:value={txHash_value}
|
||||
/>
|
||||
<p class="mt-1">UUID</p>
|
||||
<input type="text" class="input input-bordered" bind:value={uuid_value} />
|
||||
<button
|
||||
on:click={() => {
|
||||
closeWithdrawal();
|
||||
}}
|
||||
class="btn btn-success mt-4"
|
||||
>
|
||||
{#if !showLoadingClosing}
|
||||
{"Закрыть"}
|
||||
{:else}
|
||||
<span class="loading loading-xs"></span>
|
||||
{/if}
|
||||
</button>
|
||||
<button
|
||||
on:click={() => {
|
||||
showClosingWindow = false;
|
||||
txHash_value = "";
|
||||
uuid_value = "";
|
||||
}}
|
||||
class="btn">Отмена</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
@ -32,7 +32,9 @@ const config = {
|
||||
"/payouts",
|
||||
"/merchants",
|
||||
"/orders",
|
||||
"/currencies"
|
||||
"/currencies",
|
||||
"/sms",
|
||||
"/withdrawals"
|
||||
],
|
||||
},
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user