Merge remote-tracking branch 'origin/modular' into modular
This commit is contained in:
@@ -1,46 +1,280 @@
|
|||||||
# customer
|
# Khanegi — اپ مشتری (User Panel)
|
||||||
|
|
||||||
This template should help get you started developing with Vue 3 in Vite.
|
پنل وب/PWA برای **مشتریان خانگی** پلتفرم معاملات طلا و آبشده. این اپ بخش front-end مشتری در monorepo پروژه Khanegi است.
|
||||||
|
|
||||||
## Recommended IDE Setup
|
| مورد | مقدار |
|
||||||
|
|------|--------|
|
||||||
|
| نام پکیج | `customer` |
|
||||||
|
| نسخه | `1.0.8` |
|
||||||
|
| فریمورک | Vue 3 + TypeScript |
|
||||||
|
| بیلد | Vite 4 |
|
||||||
|
| State | Pinia |
|
||||||
|
| UI | Ant Design Vue 3 + Vant 4 (موبایل) |
|
||||||
|
| پورت dev | `3100` |
|
||||||
|
|
||||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
---
|
||||||
|
|
||||||
## Type Support for `.vue` Imports in TS
|
## نقش در معماری Khanegi
|
||||||
|
|
||||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
```
|
||||||
|
Khanegi/
|
||||||
|
├── userModular/ ← این پروژه (پنل مشتری)
|
||||||
|
├── admin/ ← پنل مدیریت
|
||||||
|
└── server/ ← API اصلی (Laravel)
|
||||||
|
```
|
||||||
|
|
||||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
| اتصال | پروتکل | آدرس |
|
||||||
|
|--------|--------|------|
|
||||||
|
| API اصلی | HTTPS + JWT | `{node_server}/customer/*`, `/auth/*` |
|
||||||
|
| قیمت لحظهای | SSE | `{node_server}/api/price/stream` |
|
||||||
|
| تنظیمات tenant | HTTPS | `/get_user` (قبل از لود اپ) |
|
||||||
|
|
||||||
1. Disable the built-in TypeScript Extension
|
---
|
||||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
|
||||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
|
||||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
|
||||||
|
|
||||||
## Customize configuration
|
## پیشنیازها
|
||||||
|
|
||||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
- Node.js 18+
|
||||||
|
- npm، yarn یا pnpm
|
||||||
|
|
||||||
## Project Setup
|
---
|
||||||
|
|
||||||
```sh
|
## نصب و اجرا
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd userModular
|
||||||
npm install
|
npm install
|
||||||
|
npm run dev # http://localhost:3100
|
||||||
|
npm run build # vite build
|
||||||
|
npm run preview # پیشنمایش production
|
||||||
|
npm run type-check # بررسی TypeScript
|
||||||
|
npm run lint # ESLint
|
||||||
|
npm run format # Prettier
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compile and Hot-Reload for Development
|
---
|
||||||
|
|
||||||
```sh
|
## ساختار پروژه
|
||||||
npm run dev
|
|
||||||
|
```
|
||||||
|
userModular/
|
||||||
|
├── src/
|
||||||
|
│ ├── views/ # صفحات اصلی
|
||||||
|
│ │ ├── login/ # ورود / ثبتنام
|
||||||
|
│ │ └── base/ # صفحات اپ (mobile/ + desktop/)
|
||||||
|
│ ├── api/ # لایه REST (18 ماژول)
|
||||||
|
│ ├── router/ # مسیرها + guard
|
||||||
|
│ ├── store/ # Pinia (user, wallet, fund, settings, config)
|
||||||
|
│ ├── config/ # بارگذاری tenant config
|
||||||
|
│ ├── app/ # bootstrap.ts, createApp.ts, setupRouter
|
||||||
|
│ ├── utils/ # priceSocket (SSE), authToken, useAxios
|
||||||
|
│ ├── modules/ # PWA manifest
|
||||||
|
│ ├── models/ # TypeScript types
|
||||||
|
│ ├── layouts/ # Layout موبایل/دسکتاپ
|
||||||
|
│ └── sw.ts # Service Worker (PWA)
|
||||||
|
├── public/
|
||||||
|
├── index.html
|
||||||
|
├── vite.config.ts
|
||||||
|
├── uno.config.ts
|
||||||
|
├── themeConfig.ts
|
||||||
|
└── src/mainConfig.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
### Type-Check, Compile and Minify for Production
|
---
|
||||||
|
|
||||||
```sh
|
## قابلیتهای اصلی
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint with [ESLint](https://eslint.org/)
|
### احراز هویت
|
||||||
|
- ورود با رمز عبور یا SMS
|
||||||
|
- تأیید OTP (`POST /auth/verify`)
|
||||||
|
- ثبتنام (`POST /auth/register`) — کد معرف، احراز Jibit (اختیاری)
|
||||||
|
- Provider: `customer`
|
||||||
|
|
||||||
```sh
|
### صفحه اصلی و معاملات
|
||||||
npm run lint
|
- نمودار قیمت و صفحه home
|
||||||
```
|
- خرید/فروش طلا (`/gold`)
|
||||||
|
- خرید محصول (`/buyProduct`)
|
||||||
|
- قیمت لحظهای از SSE با fallback polling
|
||||||
|
|
||||||
|
### کیف پول و تراکنشها
|
||||||
|
- مانده ریال و طلا (`/wallet`)
|
||||||
|
- تاریخچه تراکنشها (`/transactions`)
|
||||||
|
- برداشت نقدی و فیزیکی
|
||||||
|
- شارژ از درگاه PayPing
|
||||||
|
|
||||||
|
### صندوق (Fund)
|
||||||
|
- لیست صندوقها (`/fund`)
|
||||||
|
- جزئیات صندوق (`/fund/:id`)
|
||||||
|
- واریز/برداشت صندوق
|
||||||
|
|
||||||
|
### سایر
|
||||||
|
- پروفایل کاربر (`/user`)
|
||||||
|
- آدرس (`/address`)
|
||||||
|
- دریافت فیزیکی طلا (`/physicalReceive`)
|
||||||
|
- هشدار قیمت (`/notifyTrigger`)
|
||||||
|
- کسب درآمد / معرف (`/earnMoney`)
|
||||||
|
- کارت هدیه (`/giftCard`)
|
||||||
|
- قوانین و مجوزها (`/rules`, `/permissions`)
|
||||||
|
- آموزش (`/educate`)
|
||||||
|
- درباره ما (`/aboutUs`)
|
||||||
|
|
||||||
|
### حالت فروشگاهی (`is_store`)
|
||||||
|
- سبد خرید (`/api/cart/*`)
|
||||||
|
- حواله (`/customer/havale`)
|
||||||
|
- checkout (`/customer/cart/checkout`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مسیرها (Routes)
|
||||||
|
|
||||||
|
| مسیر | نام | توضیح |
|
||||||
|
|------|-----|--------|
|
||||||
|
| `/login` | login | ورود |
|
||||||
|
| `/home` | home | صفحه اصلی / نمودار |
|
||||||
|
| `/gold` | gold | معامله طلا |
|
||||||
|
| `/buyProduct` | buyProduct | خرید محصول |
|
||||||
|
| `/wallet` | wallet | کیف پول |
|
||||||
|
| `/transactions` | transactions | تراکنشها |
|
||||||
|
| `/user` | user | پروفایل |
|
||||||
|
| `/notifyTrigger` | notifyTrigger | هشدار قیمت |
|
||||||
|
| `/address` | address | آدرس |
|
||||||
|
| `/physicalReceive` | physicalReceive | دریافت فیزیکی |
|
||||||
|
| `/physicalReceive/new` | new | درخواست جدید |
|
||||||
|
| `/earnMoney` | earnMoney | کسب درآمد / معرف |
|
||||||
|
| `/giftCard` | giftCard | کارت هدیه |
|
||||||
|
| `/fund` | fund | صندوقها |
|
||||||
|
| `/fund/:id` | fund_info | جزئیات صندوق |
|
||||||
|
| `/fund/add` | fund_add | صندوق جدید |
|
||||||
|
| `/rules` | rules | قوانین |
|
||||||
|
| `/permissions` | permissions | مجوزها |
|
||||||
|
| `/educate` | educate | آموزش |
|
||||||
|
| `/aboutUs` | aboutUs | درباره ما |
|
||||||
|
|
||||||
|
**ساختار UI:** هر صفحه معمولاً `mobile/` و `desktop/` دارد.
|
||||||
|
|
||||||
|
**Guard:** بدون token به `/login` هدایت میشود.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## اتصال به Backend
|
||||||
|
|
||||||
|
### Bootstrap
|
||||||
|
|
||||||
|
1. `index.html` — loader
|
||||||
|
2. `bootstrap.ts` → `loadAppConfig()` — fetch config tenant
|
||||||
|
3. `setAppConfig()` + `applyAppConfig()` — نگاشت `node_server`
|
||||||
|
4. `startPwaManifest()` — PWA
|
||||||
|
5. mount Vue؛ اگر token باشد: `getUserInfo()` + `initPriceRealtimeChannel()`
|
||||||
|
|
||||||
|
### REST API
|
||||||
|
|
||||||
|
- **Base URL:** `getConfigApp('node_server')` ← فیلد `node_server` در JSON tenant
|
||||||
|
- **Token:** `customer_session_token` (ثابت) یا `{name}_app_token` (legacy)
|
||||||
|
- **Header:** `Authorization: Bearer <token>`
|
||||||
|
- **Axios:** `src/utils/useAxios.ts` — 401 → logout؛ verify با `/customer/me`
|
||||||
|
|
||||||
|
| پیشوند | کاربرد |
|
||||||
|
|--------|--------|
|
||||||
|
| `/auth/*` | login, verify, register |
|
||||||
|
| `/customer/*` | me, order, wallet, fund, address |
|
||||||
|
| `/api/*` | candle, price/last, city, get_settings |
|
||||||
|
|
||||||
|
### قیمت لحظهای (SSE)
|
||||||
|
|
||||||
|
- **فایل:** `src/utils/priceSocket.ts`
|
||||||
|
- **Endpoint:** `GET /api/price/stream` (EventSource)
|
||||||
|
- **Fallback:** polling هر 10 ثانیه اگر SSE قطع شود
|
||||||
|
- **Reconnection:** exponential backoff (3s → 30s)
|
||||||
|
- در حالت non-store نیاز به JWT customer دارد
|
||||||
|
|
||||||
|
### Multi-tenant Config
|
||||||
|
|
||||||
|
URLهای failover برای `/get_user`:
|
||||||
|
|
||||||
|
- `https://nerkh.gold/get_user`
|
||||||
|
- `https://tablo.talasevin.ir/get_user`
|
||||||
|
- `https://abshode-service.montgit.ir/server/get_user`
|
||||||
|
- `http://212.23.201.173:8381/get_user`
|
||||||
|
- `http://91.212.174.137:4040/server/get_user`
|
||||||
|
|
||||||
|
| فیلد JSON | معادل اپ |
|
||||||
|
|-----------|----------|
|
||||||
|
| `node_server` | API base |
|
||||||
|
| `name`, `name_fa`, `avatar` | برند |
|
||||||
|
| `color`, `background_color` | تم |
|
||||||
|
|
||||||
|
Cache: `localStorage.CONFIG_Success_URL` + cookie `APP_CONFIG_CACHE`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pinia Stores
|
||||||
|
|
||||||
|
| Store | نقش |
|
||||||
|
|-------|-----|
|
||||||
|
| `userStore` | اطلاعات کاربر، auth |
|
||||||
|
| `walletStore` | مانده کیف پول |
|
||||||
|
| `fundStore` | صندوقها |
|
||||||
|
| `settingsStore` | تنظیمات اپ |
|
||||||
|
| `configStore` | config tenant |
|
||||||
|
| `useAuthStore` | وضعیت احراز هویت |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Modules
|
||||||
|
|
||||||
|
| فایل | Endpoints |
|
||||||
|
|------|-----------|
|
||||||
|
| `login.ts` | `/auth/login`, `/auth/verify`, `/auth/register` |
|
||||||
|
| `me.ts` | `/customer/me`, `/customer/me/update` |
|
||||||
|
| `home.ts` | نمودار، قیمت |
|
||||||
|
| `order.ts` | `/customer/order` |
|
||||||
|
| `wallet.ts` | `/customer/wallet/*` |
|
||||||
|
| `fund.ts` | `/customer/fund/*` |
|
||||||
|
| `products.ts` | محصولات |
|
||||||
|
| `address.ts` | `/customer/address` |
|
||||||
|
| `giftCard.ts` | `/customer/giftcard/use` |
|
||||||
|
| `earnMoney.ts` | معرف |
|
||||||
|
| `triggerPrice.ts` | هشدار قیمت |
|
||||||
|
| `physicalreceive.ts` | دریافت فیزیکی |
|
||||||
|
| `configuration.ts` | `/api/get_settings` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PWA
|
||||||
|
|
||||||
|
- `vite-plugin-pwa` با `injectManifest`
|
||||||
|
- Service Worker: `src/sw.ts`
|
||||||
|
- Manifest: نام و آیکون از config tenant
|
||||||
|
- `display: standalone`, `orientation: portrait-primary`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## فایلهای Config مهم
|
||||||
|
|
||||||
|
| فایل | نقش |
|
||||||
|
|------|-----|
|
||||||
|
| `vite.config.ts` | Vite، PWA، UnoCSS، port 3100 |
|
||||||
|
| `src/config/load-config.ts` | fetch config ریموت |
|
||||||
|
| `src/config/app-config.ts` | نگاشت tenant |
|
||||||
|
| `src/themeConfig.ts` | token keys، رنگها |
|
||||||
|
| `src/utils/useAxios.ts` | Axios + auth |
|
||||||
|
| `src/router/index.ts` | routes |
|
||||||
|
| `src/app/bootstrap.ts` | راهاندازی اپ |
|
||||||
|
| `src/sw.ts` | Service Worker |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## نکات توسعه
|
||||||
|
|
||||||
|
1. **دو لایه realtime:** REST روی Laravel؛ قیمت از SSE با fallback polling.
|
||||||
|
2. **Multi-tenant:** یک build برای چند برند؛ رفتار با `settings` و `is_store` تغییر میکند.
|
||||||
|
3. **Responsive:** هر view دو نسخه `mobile/` و `desktop/` دارد.
|
||||||
|
4. **Token persistence:** `customer_session_token` برای جلوگیری از گم شدن token هنگام بهروزرسانی config.
|
||||||
|
5. **انیمیشن:** Lottie (`@lottiefiles/dotlottie-vue`)، Odometer برای اعداد.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مستندات مرتبط
|
||||||
|
|
||||||
|
- [README سرور Laravel](../server/README.md)
|
||||||
|
- [README پنل ادمین](../admin/README.md)
|
||||||
|
- [README نمای کلی](../README.md)
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export interface Product {
|
|||||||
percent_fee_sell: number | undefined
|
percent_fee_sell: number | undefined
|
||||||
cash_fee_buy: number | undefined
|
cash_fee_buy: number | undefined
|
||||||
cash_fee_sell: number | undefined
|
cash_fee_sell: number | undefined
|
||||||
|
cash_fee_buy_is_percent?: boolean
|
||||||
|
cash_fee_sell_is_percent?: boolean
|
||||||
order_limit_enabled?: boolean
|
order_limit_enabled?: boolean
|
||||||
min_order_cash?: number | null
|
min_order_cash?: number | null
|
||||||
max_order_cash?: number | null
|
max_order_cash?: number | null
|
||||||
@@ -56,6 +58,8 @@ export interface PInventory {
|
|||||||
percent_fee_sell: number
|
percent_fee_sell: number
|
||||||
cash_fee_buy: number
|
cash_fee_buy: number
|
||||||
cash_fee_sell: number
|
cash_fee_sell: number
|
||||||
|
cash_fee_buy_is_percent?: boolean
|
||||||
|
cash_fee_sell_is_percent?: boolean
|
||||||
reading_method: any
|
reading_method: any
|
||||||
created_at: any
|
created_at: any
|
||||||
updated_at: any
|
updated_at: any
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Product } from '@/models/products'
|
import type { Product } from '@/models/products'
|
||||||
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
import { formatGoldAmount, formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import type { UserWalletLine } from '@/models/wallet'
|
import type { UserWalletLine } from '@/models/wallet'
|
||||||
import type { ProductFile } from '@/utils/file'
|
import type { ProductFile } from '@/utils/file'
|
||||||
import type { WalletInventoryCard, WalletMetalTotal } from '@/models/walletAssets'
|
import type { WalletInventoryCard, WalletMetalTotal } from '@/models/walletAssets'
|
||||||
@@ -426,6 +426,48 @@ export function formatPortfolioProfitPercent(percent?: number | null): string {
|
|||||||
return `${sign}${value.toFixed(2)}٪`
|
return `${sign}${value.toFixed(2)}٪`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** متن توضیح مودال سود/زیان تحققنیافته طلا */
|
||||||
|
export function formatPortfolioProfitInfoText(
|
||||||
|
portfolio: {
|
||||||
|
average_buy_price?: number | null
|
||||||
|
live_gold_price?: number | null
|
||||||
|
cost_basis_rial?: number | null
|
||||||
|
gold_weight?: number | null
|
||||||
|
gold_rial_value?: number | null
|
||||||
|
unrealized_profit_rial?: number | null
|
||||||
|
unrealized_profit_percent?: number | null
|
||||||
|
},
|
||||||
|
weightUnit = 'گرم'
|
||||||
|
): string {
|
||||||
|
const lines: string[] = []
|
||||||
|
|
||||||
|
if (portfolio.average_buy_price != null && portfolio.average_buy_price > 0) {
|
||||||
|
lines.push(`میانگین قیمت خرید: ${formatRialNumber(portfolio.average_buy_price)} ریال`)
|
||||||
|
}
|
||||||
|
if (portfolio.live_gold_price != null && portfolio.live_gold_price > 0) {
|
||||||
|
lines.push(`قیمت فعلی طلا: ${formatRialNumber(portfolio.live_gold_price)} ریال`)
|
||||||
|
}
|
||||||
|
if (portfolio.gold_weight != null && portfolio.gold_weight > 0) {
|
||||||
|
lines.push(`وزن طلای شما: ${formatWeightAmount(portfolio.gold_weight)} ${weightUnit}`)
|
||||||
|
}
|
||||||
|
if (portfolio.cost_basis_rial != null && portfolio.cost_basis_rial > 0) {
|
||||||
|
lines.push(`بهای تمامشده طلا: ${formatRialNumber(portfolio.cost_basis_rial)} ریال`)
|
||||||
|
}
|
||||||
|
if (portfolio.gold_rial_value != null && portfolio.gold_rial_value > 0) {
|
||||||
|
lines.push(`ارزش فعلی طلا: ${formatRialNumber(portfolio.gold_rial_value)} ریال`)
|
||||||
|
}
|
||||||
|
if (portfolio.unrealized_profit_rial != null) {
|
||||||
|
const pct = formatPortfolioProfitPercent(portfolio.unrealized_profit_percent)
|
||||||
|
lines.push(
|
||||||
|
`سود/زیان تحققنیافته: ${formatPortfolioProfitText(portfolio.unrealized_profit_rial)}${pct ? ` (${pct})` : ''}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push('محاسبه بر اساس میانگین وزنی قیمت خرید و قیمت لحظهای بازار است.')
|
||||||
|
|
||||||
|
return lines.join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
/** متن توضیح مودال دارایی ریالی */
|
/** متن توضیح مودال دارایی ریالی */
|
||||||
export function formatRialAssetsInfoText(
|
export function formatRialAssetsInfoText(
|
||||||
cashWallet: number,
|
cashWallet: number,
|
||||||
@@ -545,8 +587,10 @@ export function formatProductWalletBalanceText(
|
|||||||
const quantity = card ? Number(card.quantity ?? 0) : Number(mainWalletGold ?? 0)
|
const quantity = card ? Number(card.quantity ?? 0) : Number(mainWalletGold ?? 0)
|
||||||
const unit = card?.unit ?? getProductQuantityUnit(product)
|
const unit = card?.unit ?? getProductQuantityUnit(product)
|
||||||
const title = product?.title?.trim() || 'محصول'
|
const title = product?.title?.trim() || 'محصول'
|
||||||
|
const formattedQty =
|
||||||
|
unit === 'عدد' ? usePriceWithoutType(quantity, false) : formatGoldAmount(quantity)
|
||||||
|
|
||||||
return `موجودی کیف ${title}: ${quantity} ${unit}`
|
return `موجودی کیف ${title}: ${formattedQty} ${unit}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSingleMetalCatalog(metalIds: number[]): boolean {
|
export function isSingleMetalCatalog(metalIds: number[]): boolean {
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
export type ProductCashFeeSource = {
|
||||||
|
cash_fee_buy?: number | null
|
||||||
|
cash_fee_sell?: number | null
|
||||||
|
cash_fee_buy_is_percent?: boolean | null
|
||||||
|
cash_fee_sell_is_percent?: boolean | null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 0.5 => 0.5% ، 5 => 5% — همیشه عدد درصد */
|
||||||
|
export function resolveCashFeePercentRatio(percentValue?: number | null) {
|
||||||
|
const offset = Number(percentValue ?? 0)
|
||||||
|
if (!offset || !Number.isFinite(offset)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated از resolveCashFeePercentRatio استفاده کنید */
|
||||||
|
export function resolveFeePercentRatio(percentValue?: number | null) {
|
||||||
|
return resolveCashFeePercentRatio(percentValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveProductCashFeeRial(
|
||||||
|
feeValue: number | null | undefined,
|
||||||
|
isPercent: boolean | null | undefined,
|
||||||
|
basePriceRial: number,
|
||||||
|
) {
|
||||||
|
const raw = Number(feeValue ?? 0)
|
||||||
|
if (!raw || !Number.isFinite(raw)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPercent) {
|
||||||
|
return Math.round(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
const base = Number(basePriceRial)
|
||||||
|
if (!base || base <= 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.round(Math.abs(base * resolveCashFeePercentRatio(raw)))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveProductCashFeeBuyRial(product: ProductCashFeeSource, basePriceRial: number) {
|
||||||
|
return resolveProductCashFeeRial(
|
||||||
|
product.cash_fee_buy,
|
||||||
|
product.cash_fee_buy_is_percent,
|
||||||
|
basePriceRial,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveProductCashFeeSellRial(product: ProductCashFeeSource, basePriceRial: number) {
|
||||||
|
return resolveProductCashFeeRial(
|
||||||
|
product.cash_fee_sell,
|
||||||
|
product.cash_fee_sell_is_percent,
|
||||||
|
basePriceRial,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatProductCashFeeLabel(
|
||||||
|
feeValue: number | null | undefined,
|
||||||
|
isPercent?: boolean | null,
|
||||||
|
) {
|
||||||
|
const raw = Number(feeValue ?? 0)
|
||||||
|
if (!raw) {
|
||||||
|
return '۰'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPercent) {
|
||||||
|
const text = Number.isInteger(raw) ? String(raw) : String(parseFloat(raw.toFixed(4)))
|
||||||
|
return `${text}%`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${raw} ریال`
|
||||||
|
}
|
||||||
@@ -13,6 +13,9 @@ import {
|
|||||||
usesQuantityTrade,
|
usesQuantityTrade,
|
||||||
} from '@/utils/productCategories'
|
} from '@/utils/productCategories'
|
||||||
import { formatInventoryCardValue } from '@/utils/productAssets'
|
import { formatInventoryCardValue } from '@/utils/productAssets'
|
||||||
|
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
||||||
|
import { TRADE_GRAM_DISPLAY_DECIMALS } from '@/utils/serviceFee'
|
||||||
|
import { formatGoldAmount } from '@/utils/usePrice'
|
||||||
|
|
||||||
/** @deprecated از isMeltedTradeGroup استفاده کنید */
|
/** @deprecated از isMeltedTradeGroup استفاده کنید */
|
||||||
export const BOURSECU_GROUP_ABSHODE = PRODUCT_CATEGORY_ABSHODE
|
export const BOURSECU_GROUP_ABSHODE = PRODUCT_CATEGORY_ABSHODE
|
||||||
@@ -369,7 +372,7 @@ export function resolveProductTradeBuyUnitPrice(product?: Product | null) {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const basePrice = (product.price ?? 0) + (product.cash_fee_buy ?? 0)
|
const basePrice = (product.price ?? 0) + resolveProductCashFeeBuyRial(product, product.price ?? 0)
|
||||||
return basePrice * productPriceAmountFactor(product)
|
return basePrice * productPriceAmountFactor(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,7 +381,7 @@ export function resolveProductTradeSellUnitPrice(product?: Product | null) {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const basePrice = (product.price ?? 0) - (product.cash_fee_sell ?? 0)
|
const basePrice = (product.price ?? 0) - resolveProductCashFeeSellRial(product, product.price ?? 0)
|
||||||
return basePrice * productPriceAmountFactor(product)
|
return basePrice * productPriceAmountFactor(product)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,6 +638,57 @@ export function resolveTransactionTradeProduct(
|
|||||||
return item.wallet?.product ?? null
|
return item.wallet?.product ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** معامله آبشده / کیف طلای اصلی — نه سکه و محصول تعدادی */
|
||||||
|
export function isMeltedGoldTransaction(
|
||||||
|
item?: (TransactionTradeProductSource & { type?: number | null; title?: string | null }) | null,
|
||||||
|
): boolean {
|
||||||
|
if (!item) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const tradeProduct = resolveTransactionTradeProduct(item)
|
||||||
|
if (tradeProduct) {
|
||||||
|
if (usesQuantityTrade(tradeProduct) && !isMeltedTradeGroup(tradeProduct.group_type)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isMeltedTradeGroup(tradeProduct.group_type)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (isCountBasedProduct(tradeProduct)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = (item.title ?? '').trim()
|
||||||
|
const meltedLabel = getMeltedGoldTradeLabel()
|
||||||
|
if (title.includes(PRODUCT_CATEGORY_ABSHODE) || (meltedLabel && title.includes(meltedLabel))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.type !== 1 && item.type !== 2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMeltedTradeGroup(item.wallet?.product?.group_type)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const tradeTitle = (tradeProduct?.title ?? '').trim()
|
||||||
|
if (tradeTitle === meltedLabel || tradeTitle.includes(PRODUCT_CATEGORY_ABSHODE)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return !item.wallet?.product && !tradeTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatTransactionGoldAmount(
|
||||||
|
item?: (TransactionTradeProductSource & { type?: number | null; title?: string | null }) | null,
|
||||||
|
amount?: number | null,
|
||||||
|
): string {
|
||||||
|
const decimals = isMeltedGoldTransaction(item) ? TRADE_GRAM_DISPLAY_DECIMALS : 3
|
||||||
|
return formatGoldAmount(amount, decimals)
|
||||||
|
}
|
||||||
|
|
||||||
/** برچسب قیمت حین معامله — نام و واحد همان محصول معاملهشده */
|
/** برچسب قیمت حین معامله — نام و واحد همان محصول معاملهشده */
|
||||||
export function getTransactionTradePriceLabel(product?: (ProductUnitSource & { title?: string | null }) | null) {
|
export function getTransactionTradePriceLabel(product?: (ProductUnitSource & { title?: string | null }) | null) {
|
||||||
if (!product) {
|
if (!product) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Product } from '@/models/products'
|
import type { Product } from '@/models/products'
|
||||||
import { getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@/utils/price'
|
import { getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@/utils/price'
|
||||||
|
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
||||||
import { isMetalCommodityGroup, isMeltedProductUsingAppPrice, isMeltedTradeGroup, usesQuantityTrade } from '@/utils/productCategories'
|
import { isMetalCommodityGroup, isMeltedProductUsingAppPrice, isMeltedTradeGroup, usesQuantityTrade } from '@/utils/productCategories'
|
||||||
import { productPriceAmountFactor } from '@/utils/productDealMethod'
|
import { productPriceAmountFactor } from '@/utils/productDealMethod'
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ export function getProductBuyPrice(product: Product): number {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const fee = Number(product.cash_fee_buy ?? 0)
|
const fee = resolveProductCashFeeBuyRial(product, base)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isMeltedProductUsingAppPrice(product)
|
isMeltedProductUsingAppPrice(product)
|
||||||
@@ -159,7 +160,7 @@ export function getProductSellPrice(product: Product): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isMeltedProductUsingAppPrice(product) || isMeltedTradeGroup(product.group_type) || usesQuantityTrade(product)) {
|
if (isMeltedProductUsingAppPrice(product) || isMeltedTradeGroup(product.group_type) || usesQuantityTrade(product)) {
|
||||||
return base - Number(product.cash_fee_sell ?? 0)
|
return base - resolveProductCashFeeSellRial(product, base)
|
||||||
}
|
}
|
||||||
|
|
||||||
return base
|
return base
|
||||||
|
|||||||
+115
-13
@@ -6,6 +6,31 @@ export const serviceFeePercentage = ref<number>(0.01)
|
|||||||
/** true = مبالغ رند: فروش → ریال دقیق (کارمزد از طلا)؛ خرید → وزن دقیق (کارمزد از ریال) */
|
/** true = مبالغ رند: فروش → ریال دقیق (کارمزد از طلا)؛ خرید → وزن دقیق (کارمزد از ریال) */
|
||||||
export const feeDeductFromGold = ref(false)
|
export const feeDeductFromGold = ref(false)
|
||||||
|
|
||||||
|
/** آخرین فیلدی که کاربر مستقیم ویرایش کرده — مبنای بهروزرسانی هنگام تغییر قیمت */
|
||||||
|
export type TradeInputLock = 'gram' | 'rial' | null
|
||||||
|
|
||||||
|
/** حداکثر اعشار ذخیره/ارسال به سرور (مطابق orders.amount) */
|
||||||
|
export const TRADE_GRAM_STORAGE_DECIMALS = 10
|
||||||
|
|
||||||
|
/** حداکثر اعشار نمایش به کاربر در اپ */
|
||||||
|
export const TRADE_GRAM_DISPLAY_DECIMALS = 8
|
||||||
|
|
||||||
|
export function normalizeOrderGoldAmount(grams?: number | null): number {
|
||||||
|
const value = Number(grams ?? 0)
|
||||||
|
if (!Number.isFinite(value) || value === 0) return 0
|
||||||
|
return parseFloat(value.toFixed(TRADE_GRAM_STORAGE_DECIMALS))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatTradeGramDisplay(grams?: number | null): number {
|
||||||
|
const value = Number(grams ?? 0)
|
||||||
|
if (!Number.isFinite(value)) return 0
|
||||||
|
return parseFloat(value.toFixed(TRADE_GRAM_DISPLAY_DECIMALS))
|
||||||
|
}
|
||||||
|
|
||||||
|
function feeRate() {
|
||||||
|
return Number(serviceFeePercentage.value)
|
||||||
|
}
|
||||||
|
|
||||||
export async function loadServiceFeeFromSettings() {
|
export async function loadServiceFeeFromSettings() {
|
||||||
try {
|
try {
|
||||||
const settings = await getSettings()
|
const settings = await getSettings()
|
||||||
@@ -39,7 +64,58 @@ export function calcFeeInGrams(goldValue?: number | null) {
|
|||||||
/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */
|
/** گرم معادل برای دریافت دقیق مبلغ ریالی در فروش */
|
||||||
export function calcGoldAmountFromTargetRial(rialAmount: number, unitPriceRial: number) {
|
export function calcGoldAmountFromTargetRial(rialAmount: number, unitPriceRial: number) {
|
||||||
if (!rialAmount || !unitPriceRial) return 0
|
if (!rialAmount || !unitPriceRial) return 0
|
||||||
return parseFloat((rialAmount / unitPriceRial).toFixed(6))
|
return normalizeOrderGoldAmount(rialAmount / unitPriceRial)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** وقتی کاربر گرم را قفل کرده — ریال نمایشی/قابل پرداخت از همان گرم */
|
||||||
|
export function calcRialFromLockedGram(displayGram: number, unitPriceRial: number, isBuy: boolean) {
|
||||||
|
const grams = Number(displayGram)
|
||||||
|
const unit = Number(unitPriceRial)
|
||||||
|
if (!grams || !unit) return 0
|
||||||
|
const fee = feeRate()
|
||||||
|
|
||||||
|
if (isBuy) {
|
||||||
|
if (feeDeductFromGold.value) {
|
||||||
|
return Math.round(grams * unit * (1 + fee))
|
||||||
|
}
|
||||||
|
return Math.round(grams * unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feeDeductFromGold.value) {
|
||||||
|
return Math.round(grams * unit)
|
||||||
|
}
|
||||||
|
return Math.round(grams * unit * (1 - fee))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** وقتی کاربر ریال را قفل کرده — گرم نمایشی از همان مبلغ */
|
||||||
|
export function calcGramFromLockedRial(rialAmount: number, unitPriceRial: number, isBuy: boolean) {
|
||||||
|
const rial = Number(rialAmount)
|
||||||
|
const unit = Number(unitPriceRial)
|
||||||
|
if (!rial || !unit) return 0
|
||||||
|
const fee = feeRate()
|
||||||
|
|
||||||
|
if (isBuy) {
|
||||||
|
if (feeDeductFromGold.value) {
|
||||||
|
return rial / (unit * (1 + fee))
|
||||||
|
}
|
||||||
|
return (rial / unit) * (1 - fee)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feeDeductFromGold.value) {
|
||||||
|
return rial / unit
|
||||||
|
}
|
||||||
|
return rial / (unit * (1 - fee))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** مبلغ ریالی قفلشده توسط کاربر — برای ارسال به سرور */
|
||||||
|
export function calcTradeTargetCash(
|
||||||
|
goldCash?: number | null,
|
||||||
|
inputLock?: TradeInputLock,
|
||||||
|
): number | undefined {
|
||||||
|
if (inputLock !== 'rial') return undefined
|
||||||
|
const cash = Number(goldCash ?? 0)
|
||||||
|
if (cash <= 0) return undefined
|
||||||
|
return Math.round(cash)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** مبلغ نهایی قابل پرداخت (خرید) یا دریافت (فروش) به ریال */
|
/** مبلغ نهایی قابل پرداخت (خرید) یا دریافت (فروش) به ریال */
|
||||||
@@ -49,41 +125,67 @@ export function calcPayablePriceRial(
|
|||||||
isBuy: boolean,
|
isBuy: boolean,
|
||||||
targetRialCash?: number | null
|
targetRialCash?: number | null
|
||||||
) {
|
) {
|
||||||
|
if (targetRialCash != null && Number(targetRialCash) > 0) {
|
||||||
|
return Number(targetRialCash)
|
||||||
|
}
|
||||||
|
|
||||||
if (feeDeductFromGold.value) {
|
if (feeDeductFromGold.value) {
|
||||||
if (isBuy) return finalPriceRial + feeInRial
|
if (isBuy) return finalPriceRial + feeInRial
|
||||||
if (targetRialCash != null && Number(targetRialCash) > 0) return Number(targetRialCash)
|
|
||||||
return finalPriceRial
|
return finalPriceRial
|
||||||
}
|
}
|
||||||
return isBuy ? finalPriceRial : Math.max(0, finalPriceRial - feeInRial)
|
return isBuy ? finalPriceRial : Math.max(0, finalPriceRial - feeInRial)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** وزن ارسالی به سرور — فروش رند: از مبلغ ریالی هدف */
|
/** وزن ارسالی به سرور */
|
||||||
export function calcOrderGoldAmount(
|
export function calcOrderGoldAmount(
|
||||||
goldValue?: number | null,
|
goldValue?: number | null,
|
||||||
goldCash?: number | null,
|
goldCash?: number | null,
|
||||||
unitPriceRial?: number,
|
unitPriceRial?: number,
|
||||||
isBuy?: boolean
|
isBuy?: boolean,
|
||||||
|
inputLock?: TradeInputLock
|
||||||
) {
|
) {
|
||||||
const gold = Number(goldValue ?? 0)
|
const gold = Number(goldValue ?? 0)
|
||||||
if (isBuy || !feeDeductFromGold.value) {
|
const cash = Number(goldCash ?? 0)
|
||||||
return parseFloat(gold.toFixed(6))
|
|
||||||
}
|
|
||||||
const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial)
|
|
||||||
const unit = Number(unitPriceRial ?? 0)
|
const unit = Number(unitPriceRial ?? 0)
|
||||||
if (targetCash != null && unit > 0) {
|
|
||||||
return calcGoldAmountFromTargetRial(targetCash, unit)
|
if (isBuy && inputLock === 'rial' && cash > 0 && unit > 0) {
|
||||||
|
if (feeDeductFromGold.value) {
|
||||||
|
const fee = feeRate()
|
||||||
|
return normalizeOrderGoldAmount(cash / (unit * (1 + fee)))
|
||||||
|
}
|
||||||
|
return normalizeOrderGoldAmount(cash / unit)
|
||||||
}
|
}
|
||||||
return parseFloat(gold.toFixed(6))
|
|
||||||
|
if (!isBuy && feeDeductFromGold.value) {
|
||||||
|
if (inputLock === 'rial' && cash > 0 && unit > 0) {
|
||||||
|
return calcGoldAmountFromTargetRial(cash, unit)
|
||||||
|
}
|
||||||
|
if (inputLock !== 'rial') {
|
||||||
|
return normalizeOrderGoldAmount(gold)
|
||||||
|
}
|
||||||
|
const targetCash = calcSellTargetCash(goldCash, goldValue, unitPriceRial, inputLock)
|
||||||
|
if (targetCash != null && unit > 0) {
|
||||||
|
return calcGoldAmountFromTargetRial(targetCash, unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizeOrderGoldAmount(gold)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** مبلغ ریالی دقیق دریافتی در فروش (فقط وقتی کاربر با ریال وارد کرده) */
|
/** مبلغ ریالی دقیق دریافتی در فروش (فقط وقتی کاربر با ریال وارد کرده) */
|
||||||
export function calcSellTargetCash(
|
export function calcSellTargetCash(
|
||||||
goldCash?: number | null,
|
goldCash?: number | null,
|
||||||
goldValue?: number | null,
|
goldValue?: number | null,
|
||||||
unitPriceRial?: number
|
unitPriceRial?: number,
|
||||||
|
inputLock?: TradeInputLock
|
||||||
) {
|
) {
|
||||||
|
if (!feeDeductFromGold.value) return undefined
|
||||||
|
if (inputLock === 'gram') return undefined
|
||||||
|
|
||||||
const cash = Number(goldCash ?? 0)
|
const cash = Number(goldCash ?? 0)
|
||||||
if (!feeDeductFromGold.value || cash <= 0) return undefined
|
if (cash <= 0) return undefined
|
||||||
|
if (inputLock === 'rial') return Math.round(cash)
|
||||||
|
|
||||||
const gold = Number(goldValue ?? 0)
|
const gold = Number(goldValue ?? 0)
|
||||||
const unit = Number(unitPriceRial ?? 0)
|
const unit = Number(unitPriceRial ?? 0)
|
||||||
if (gold > 0 && unit > 0) {
|
if (gold > 0 && unit > 0) {
|
||||||
|
|||||||
+49
-2
@@ -50,11 +50,26 @@ export function useFormat(num: string | number, unit = '') {
|
|||||||
type TransactionPriceSource = {
|
type TransactionPriceSource = {
|
||||||
cash?: number | null
|
cash?: number | null
|
||||||
gold?: number | null
|
gold?: number | null
|
||||||
|
type?: number | null
|
||||||
order?: {
|
order?: {
|
||||||
price?: number | null
|
price?: number | null
|
||||||
total_price?: number | null
|
total_price?: number | null
|
||||||
amount?: number | null
|
amount?: number | null
|
||||||
|
sts?: number | null
|
||||||
|
sts_str?: string | number | null
|
||||||
|
payment_sts?: number | null
|
||||||
} | null
|
} | null
|
||||||
|
withdraw?: {
|
||||||
|
sts?: number | null
|
||||||
|
sts_str?: string | number | null
|
||||||
|
} | null
|
||||||
|
order_id?: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const ORDER_STATUS_LABELS: Record<number, string> = {
|
||||||
|
1: 'باز',
|
||||||
|
2: 'موفق',
|
||||||
|
3: 'ناموفق',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTransactionTradePrice(item: TransactionPriceSource): number {
|
export function getTransactionTradePrice(item: TransactionPriceSource): number {
|
||||||
@@ -79,6 +94,38 @@ export function getTransactionTradePrice(item: TransactionPriceSource): number {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveTransactionStatusLabel(item?: TransactionPriceSource | null): string {
|
||||||
|
if (!item) return ''
|
||||||
|
|
||||||
|
const raw = item.order?.sts_str ?? item.withdraw?.sts_str
|
||||||
|
if (typeof raw === 'string') {
|
||||||
|
const trimmed = raw.trim()
|
||||||
|
if (trimmed && trimmed !== 'بدون مقدار') {
|
||||||
|
return trimmed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof raw === 'number' || (typeof raw === 'string' && /^\d+$/.test(String(raw).trim()))) {
|
||||||
|
const mapped = ORDER_STATUS_LABELS[Number(raw)]
|
||||||
|
if (mapped) return mapped
|
||||||
|
}
|
||||||
|
|
||||||
|
const sts = item.order?.sts ?? item.withdraw?.sts
|
||||||
|
if (sts != null && ORDER_STATUS_LABELS[Number(sts)]) {
|
||||||
|
return ORDER_STATUS_LABELS[Number(sts)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.order_id && Number(item.order?.payment_sts) === 4) {
|
||||||
|
return 'موفق'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.order_id && (item.type === 1 || item.type === 2 || item.type === 10)) {
|
||||||
|
return 'موفق'
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
export function getTransactionGoldAmount(item: TransactionPriceSource): number {
|
export function getTransactionGoldAmount(item: TransactionPriceSource): number {
|
||||||
const gold = Number(item.gold) || 0
|
const gold = Number(item.gold) || 0
|
||||||
if (Math.abs(gold) > 0) {
|
if (Math.abs(gold) > 0) {
|
||||||
@@ -96,10 +143,10 @@ export function getTransactionGoldAmount(item: TransactionPriceSource): number {
|
|||||||
return gold
|
return gold
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatGoldAmount(amount?: number | null): string {
|
export function formatGoldAmount(amount?: number | null, decimals = 8): string {
|
||||||
const num = Number(amount)
|
const num = Number(amount)
|
||||||
if (!Number.isFinite(num)) return '0'
|
if (!Number.isFinite(num)) return '0'
|
||||||
return formatGroupedPrice(Number(num.toFixed(3)), false)
|
return formatGroupedPrice(Number(num.toFixed(decimals)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** وزن فلز (گرم/کیلو) — بدون گرد کردن به بالا (برخلاف usePriceWithoutType) */
|
/** وزن فلز (گرم/کیلو) — بدون گرد کردن به بالا (برخلاف usePriceWithoutType) */
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ import BasicSelect from '@/components/BasicPacks/BasicSelect.vue'
|
|||||||
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
|
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
|
||||||
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
|
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
|
||||||
import BasicTextArea from '@/components/BasicPacks/BasicTextArea.vue'
|
import BasicTextArea from '@/components/BasicPacks/BasicTextArea.vue'
|
||||||
import { loading } from '@/utils'
|
|
||||||
import { createAddress, getCity, updateAddress } from '@/api/address'
|
import { createAddress, getCity, updateAddress } from '@/api/address'
|
||||||
import { FormInstance, message } from 'ant-design-vue'
|
import { FormInstance, message } from 'ant-design-vue'
|
||||||
import { Address } from '@/models/address'
|
import { Address } from '@/models/address'
|
||||||
@@ -130,14 +129,11 @@ const changeProvince = async (obj: any) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
|
||||||
cityList.value = undefined
|
cityList.value = undefined
|
||||||
address.value.city = undefined
|
address.value.city = undefined
|
||||||
cityList.value = await getCity(obj.id)
|
cityList.value = await getCity(obj.id)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
message.error('خطا در دریافت شهرها')
|
message.error('خطا در دریافت شهرها')
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,14 +98,11 @@ export function useAddressPage() {
|
|||||||
|
|
||||||
const changeProvince = async (obj: { id: number }) => {
|
const changeProvince = async (obj: { id: number }) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
|
||||||
cityList.value = undefined
|
cityList.value = undefined
|
||||||
address.value.city = undefined
|
address.value.city = undefined
|
||||||
cityList.value = await getCity(obj.id)
|
cityList.value = await getCity(obj.id)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
message.error('خطا در دریافت شهرها')
|
message.error('خطا در دریافت شهرها')
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,9 +232,11 @@ import type { Product } from '@/models/products'
|
|||||||
import { useFundUserStore } from '@/store/fundStore'
|
import { useFundUserStore } from '@/store/fundStore'
|
||||||
import {useConfigStore} from "@/store/configStore";
|
import {useConfigStore} from "@/store/configStore";
|
||||||
import { calcFeeInGrams, calcPayablePriceRial, calcSellGoldDebit, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee'
|
import { calcFeeInGrams, calcPayablePriceRial, calcSellGoldDebit, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee'
|
||||||
|
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
||||||
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
|
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
|
||||||
import { getCashWalletBalance } from '@/utils/productAssets'
|
import { getCashWalletBalance } from '@/utils/productAssets'
|
||||||
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
||||||
|
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
||||||
|
|
||||||
const infoVisible = ref(false)
|
const infoVisible = ref(false)
|
||||||
const walletStore = useWalletStore()
|
const walletStore = useWalletStore()
|
||||||
@@ -282,13 +284,12 @@ const basePriceValue = computed(() => {
|
|||||||
const product = props?.ProductItem
|
const product = props?.ProductItem
|
||||||
if (!product) return undefined
|
if (!product) return undefined
|
||||||
|
|
||||||
const { price_profit = 0, price = 0, cash_fee_buy = 0, cash_fee_sell = 0 } = product
|
const { price_profit = 0, price = 0 } = product
|
||||||
const base = price_profit + price
|
const base = price_profit + price
|
||||||
|
const buyFee = resolveProductCashFeeBuyRial(product, base)
|
||||||
|
const sellFee = resolveProductCashFeeSellRial(product, base)
|
||||||
|
|
||||||
const rawPrice = isBuy.value
|
return isBuy.value ? base + buyFee : base - sellFee
|
||||||
? base + cash_fee_buy
|
|
||||||
: base - cash_fee_sell
|
|
||||||
return rawPrice
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const finalPrice = computed(() => {
|
const finalPrice = computed(() => {
|
||||||
@@ -298,15 +299,17 @@ const finalPrice = computed(() => {
|
|||||||
const product = props?.ProductItem
|
const product = props?.ProductItem
|
||||||
if (!product) return 0
|
if (!product) return 0
|
||||||
|
|
||||||
const { price_profit = 0, price = 0, cash_fee_buy = 0, cash_fee_sell = 0 } = product
|
const { price_profit = 0, price = 0 } = product
|
||||||
|
|
||||||
const base = price_profit + price
|
const base = price_profit + price
|
||||||
|
const buyFee = resolveProductCashFeeBuyRial(product, base)
|
||||||
|
const sellFee = resolveProductCashFeeSellRial(product, base)
|
||||||
|
|
||||||
if (isBuy.value) {
|
if (isBuy.value) {
|
||||||
return gold * (base + cash_fee_buy)
|
return gold * (base + buyFee)
|
||||||
} else {
|
|
||||||
return gold * (base - cash_fee_sell)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return gold * (base - sellFee)
|
||||||
})
|
})
|
||||||
|
|
||||||
const payablePrice = computed(() =>
|
const payablePrice = computed(() =>
|
||||||
@@ -532,20 +535,30 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
function productFeeBase(product?: Product) {
|
||||||
|
return (product?.price_profit ?? 0) + (product?.price ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
function calculateCash(val: number) {
|
function calculateCash(val: number) {
|
||||||
priceErrorVisible.value = false
|
priceErrorVisible.value = false
|
||||||
if (!lastPrice.value) return
|
if (!lastPrice.value) return
|
||||||
|
|
||||||
|
const product = props?.ProductItem
|
||||||
|
if (!product) return
|
||||||
|
|
||||||
|
const base = productFeeBase(product)
|
||||||
|
const buyFee = resolveProductCashFeeBuyRial(product, base)
|
||||||
|
const sellFee = resolveProductCashFeeSellRial(product, base)
|
||||||
const tradeBuy = getTradeBuyPrice(lastPrice.value)
|
const tradeBuy = getTradeBuyPrice(lastPrice.value)
|
||||||
form.value.goldVazn = parseFloat((val * ((props?.ProductItem?.price) + (props?.ProductItem?.cash_fee_buy))) / tradeBuy).toFixed(1)
|
form.value.goldVazn = parseFloat(String((val * (base + buyFee)) / tradeBuy)).toFixed(1)
|
||||||
if (isBuy.value) {
|
if (isBuy.value) {
|
||||||
form.value.goldCash = val
|
form.value.goldCash = val
|
||||||
? parseFloat(String(val * ((props?.ProductItem?.price) + (props?.ProductItem?.cash_fee_buy))))
|
? parseFloat(String(val * (base + buyFee)))
|
||||||
: 0
|
: 0
|
||||||
if (!val) form.value.goldVazn = 0
|
if (!val) form.value.goldVazn = 0
|
||||||
} else {
|
} else {
|
||||||
form.value.goldCash = val
|
form.value.goldCash = val
|
||||||
? parseFloat(String((val * props?.ProductItem?.price) - (props?.ProductItem?.cash_fee_sell)))
|
? parseFloat(String(val * base - sellFee))
|
||||||
: 0
|
: 0
|
||||||
if (!val) form.value.goldVazn = 0
|
if (!val) form.value.goldVazn = 0
|
||||||
}
|
}
|
||||||
@@ -553,9 +566,16 @@ function calculateCash(val: number) {
|
|||||||
|
|
||||||
function calculateGold(val: number) {
|
function calculateGold(val: number) {
|
||||||
if (price.value) {
|
if (price.value) {
|
||||||
|
const product = props?.ProductItem
|
||||||
|
if (!product) return
|
||||||
|
|
||||||
|
const base = productFeeBase(product)
|
||||||
|
const buyFee = resolveProductCashFeeBuyRial(product, base)
|
||||||
|
const sellFee = resolveProductCashFeeSellRial(product, base)
|
||||||
|
|
||||||
if (isBuy.value) {
|
if (isBuy.value) {
|
||||||
if (val) {
|
if (val) {
|
||||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(val / (((props?.ProductItem?.price_profit) + (props?.ProductItem?.price)) + (props?.ProductItem?.cash_fee_buy))))
|
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / (base + buyFee))))
|
||||||
if (parseInt(finalPrice.value) > 0) priceErrorVisible.value = true
|
if (parseInt(finalPrice.value) > 0) priceErrorVisible.value = true
|
||||||
if (parseInt(finalPrice.value) === 0) priceErrorVisible.value = false
|
if (parseInt(finalPrice.value) === 0) priceErrorVisible.value = false
|
||||||
}
|
}
|
||||||
@@ -570,7 +590,7 @@ function calculateGold(val: number) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (val) {
|
if (val) {
|
||||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(val / (((props?.ProductItem?.price_profit) + (props?.ProductItem?.price)) + (props?.ProductItem?.cash_fee_sell))))
|
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / (base - sellFee))))
|
||||||
if (parseInt(finalPrice.value) > 0) priceErrorVisible.value = true
|
if (parseInt(finalPrice.value) > 0) priceErrorVisible.value = true
|
||||||
if (parseInt(finalPrice.value) === 0) priceErrorVisible.value = false
|
if (parseInt(finalPrice.value) === 0) priceErrorVisible.value = false
|
||||||
} else if (val.toString() === '') {
|
} else if (val.toString() === '') {
|
||||||
@@ -658,6 +678,7 @@ async function ok() {
|
|||||||
})
|
})
|
||||||
confirmAction.value = false
|
confirmAction.value = false
|
||||||
await walletStore.getMyWallet()
|
await walletStore.getMyWallet()
|
||||||
|
resetTransactionsPageData()
|
||||||
await router.push({ name: 'transactions' })
|
await router.push({ name: 'transactions' })
|
||||||
form.value = {
|
form.value = {
|
||||||
goldValue: undefined,
|
goldValue: undefined,
|
||||||
|
|||||||
@@ -102,20 +102,6 @@
|
|||||||
@change="percentChange" />
|
@change="percentChange" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</Transition>
|
</Transition>
|
||||||
<!-- <Transition mode="out-in" name="fade">
|
|
||||||
<div v-if="priceErrorVisible" class="flex gap-1 items-center text-xs mt-[-15px] text-orange-600">
|
|
||||||
<BasicIcon icon="vuesax-linear:danger" />
|
|
||||||
ارزش کل وارد شده بر حسب گرم طلا محاسبه خواهد شد و قیمت وارد شده معادل {{ usePrice(finalPrice) }} می
|
|
||||||
باشد!
|
|
||||||
</div>
|
|
||||||
</Transition>-->
|
|
||||||
<Transition mode="out-in" name="fade">
|
|
||||||
<div v-if="priceErrorVisible" class="flex gap-1 items-center text-xs mt-[-15px] text-blue-600">
|
|
||||||
<BasicIcon icon="vuesax-linear:info-circle" />
|
|
||||||
ارزش کل وارد شده بر حسب گرم طلا محاسبه خواهد شد و قیمت وارد شده معادل {{ usePrice(parseInt(finalPrice.toFixed(0))) }} می
|
|
||||||
باشد!
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<GoldLoading v-model:show="infoVisible" />
|
<GoldLoading v-model:show="infoVisible" />
|
||||||
@@ -173,7 +159,7 @@
|
|||||||
<div class="flex justify-between ">
|
<div class="flex justify-between ">
|
||||||
<div>وزن:</div>
|
<div>وزن:</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="font-bold">{{ form.goldValue }}</div>
|
<div class="font-bold">{{ displayTradeGoldAmount }}</div>
|
||||||
<div class="text-xs mr-1">{{ weightUnit }}</div>
|
<div class="text-xs mr-1">{{ weightUnit }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -195,7 +181,7 @@
|
|||||||
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
||||||
<div>طلا دریافتی:</div>
|
<div>طلا دریافتی:</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="font-bold">{{ form.goldValue }}</div>
|
<div class="font-bold">{{ displayTradeGoldAmount }}</div>
|
||||||
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
|
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -214,7 +200,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BasicButton class="mb-20 mt-5 w-full" type="primary" @click="ok(); confirmAction= false">ثبت نهایی</BasicButton>
|
<BasicButton
|
||||||
|
class="mb-20 mt-5 w-full"
|
||||||
|
type="primary"
|
||||||
|
:disabled="loading"
|
||||||
|
@click="ok"
|
||||||
|
>
|
||||||
|
ثبت نهایی
|
||||||
|
</BasicButton>
|
||||||
</BasicActionSheet>
|
</BasicActionSheet>
|
||||||
<BasicModal
|
<BasicModal
|
||||||
v-else
|
v-else
|
||||||
@@ -228,7 +221,7 @@
|
|||||||
<div class="flex justify-between ">
|
<div class="flex justify-between ">
|
||||||
<div>وزن:</div>
|
<div>وزن:</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="font-bold">{{ form.goldValue }}</div>
|
<div class="font-bold">{{ displayTradeGoldAmount }}</div>
|
||||||
<div class="text-xs mr-1">{{ weightUnit }}</div>
|
<div class="text-xs mr-1">{{ weightUnit }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -250,7 +243,7 @@
|
|||||||
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
<div v-if="isBuy && feeDeductFromGold" class="flex justify-between mt-3">
|
||||||
<div>طلا دریافتی:</div>
|
<div>طلا دریافتی:</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="font-bold">{{ form.goldValue }}</div>
|
<div class="font-bold">{{ displayTradeGoldAmount }}</div>
|
||||||
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
|
<div class="text-xs mr-1">{{ weightUnit }} (دقیق — کارمزد از ریال)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -269,7 +262,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BasicButton class="mt-5 w-full" type="primary" @click="ok(); confirmAction = false">
|
<BasicButton class="mt-5 w-full" type="primary" :disabled="loading" @click="ok">
|
||||||
ثبت نهایی
|
ثبت نهایی
|
||||||
</BasicButton>
|
</BasicButton>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -299,7 +292,7 @@ import img1 from '@/assets/img/home_ly2.svg'
|
|||||||
import { usePrice, usePriceWithoutType } from '@/utils/usePrice'
|
import { usePrice, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
|
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
|
||||||
import type { Gold } from '@/models/gold'
|
import type { Gold } from '@/models/gold'
|
||||||
import { isIphone, loading, loadingMore, toFixedDownThreeChar } from '@/utils'
|
import { isIphone, loading, loadingMore } from '@/utils'
|
||||||
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
|
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { useWalletStore } from '@/store/walletStore'
|
import { useWalletStore } from '@/store/walletStore'
|
||||||
@@ -330,8 +323,24 @@ import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@
|
|||||||
import type { Product } from '@/models/products'
|
import type { Product } from '@/models/products'
|
||||||
import { useFundUserStore } from '@/store/fundStore'
|
import { useFundUserStore } from '@/store/fundStore'
|
||||||
import {useConfigStore} from "@/store/configStore";
|
import {useConfigStore} from "@/store/configStore";
|
||||||
import { calcFeeInGrams, calcOrderGoldAmount, calcPayablePriceRial, calcSellGoldDebit, calcSellTargetCash, feeDeductFromGold, loadServiceFeeFromSettings } from '@/utils/serviceFee'
|
import {
|
||||||
|
calcFeeInGrams,
|
||||||
|
calcGramFromLockedRial,
|
||||||
|
calcOrderGoldAmount,
|
||||||
|
calcPayablePriceRial,
|
||||||
|
calcRialFromLockedGram,
|
||||||
|
calcSellGoldDebit,
|
||||||
|
calcSellTargetCash,
|
||||||
|
calcTradeTargetCash,
|
||||||
|
feeDeductFromGold,
|
||||||
|
formatTradeGramDisplay,
|
||||||
|
loadServiceFeeFromSettings,
|
||||||
|
normalizeOrderGoldAmount,
|
||||||
|
serviceFeePercentage,
|
||||||
|
type TradeInputLock,
|
||||||
|
} from '@/utils/serviceFee'
|
||||||
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
|
||||||
|
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
||||||
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
|
||||||
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
|
||||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
@@ -359,7 +368,6 @@ const confirmAction = ref<boolean>(false)
|
|||||||
const noCompleteVisible = ref<boolean>(false)
|
const noCompleteVisible = ref<boolean>(false)
|
||||||
const buyItems = ref<Transaction[]>([])
|
const buyItems = ref<Transaction[]>([])
|
||||||
const sellItems = ref<Transaction[]>([])
|
const sellItems = ref<Transaction[]>([])
|
||||||
const priceErrorVisible = ref<boolean>(false)
|
|
||||||
const buyTableOutput = ref<TableOutput<Transaction> | null>(null)
|
const buyTableOutput = ref<TableOutput<Transaction> | null>(null)
|
||||||
const sellTableOutput = ref<TableOutput<Transaction> | null>(null)
|
const sellTableOutput = ref<TableOutput<Transaction> | null>(null)
|
||||||
const el = ref()
|
const el = ref()
|
||||||
@@ -386,6 +394,7 @@ const contentClass = computed(() => {
|
|||||||
return 'mt-5 px-3 pb-4'
|
return 'mt-5 px-3 pb-4'
|
||||||
})
|
})
|
||||||
const isBuy = ref<boolean>(true)
|
const isBuy = ref<boolean>(true)
|
||||||
|
const inputLock = ref<TradeInputLock>(null)
|
||||||
|
|
||||||
const tradeProductLabel = computed(() => {
|
const tradeProductLabel = computed(() => {
|
||||||
const title = props.ProductItem?.title?.trim()
|
const title = props.ProductItem?.title?.trim()
|
||||||
@@ -436,7 +445,13 @@ const unitPrice = computed(() => {
|
|||||||
return isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
|
return isBuy.value ? getTradeBuyPrice(lastPrice.value) : getTradeSellPrice(lastPrice.value)
|
||||||
})
|
})
|
||||||
const orderGoldAmount = computed(() =>
|
const orderGoldAmount = computed(() =>
|
||||||
calcOrderGoldAmount(form.value?.goldValue, form.value?.goldCash, unitPrice.value, isBuy.value)
|
calcOrderGoldAmount(
|
||||||
|
form.value?.goldValue,
|
||||||
|
form.value?.goldCash,
|
||||||
|
unitPrice.value,
|
||||||
|
isBuy.value,
|
||||||
|
inputLock.value
|
||||||
|
)
|
||||||
)
|
)
|
||||||
const feeInGrams = computed(() => calcFeeInGrams(orderGoldAmount.value))
|
const feeInGrams = computed(() => calcFeeInGrams(orderGoldAmount.value))
|
||||||
const finalPrice = computed(() => orderGoldAmount.value * unitPrice.value)
|
const finalPrice = computed(() => orderGoldAmount.value * unitPrice.value)
|
||||||
@@ -447,11 +462,15 @@ const payablePrice = computed(() =>
|
|||||||
finalPrice.value,
|
finalPrice.value,
|
||||||
feeInRial.value,
|
feeInRial.value,
|
||||||
isBuy.value,
|
isBuy.value,
|
||||||
!isBuy.value ? form.value?.goldCash : undefined
|
inputLock.value === 'rial' ? form.value?.goldCash : undefined
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const sellGoldDebit = computed(() => calcSellGoldDebit(orderGoldAmount.value, feeInGrams.value))
|
const sellGoldDebit = computed(() => calcSellGoldDebit(orderGoldAmount.value, feeInGrams.value))
|
||||||
|
|
||||||
|
const displayTradeGoldAmount = computed(() =>
|
||||||
|
formatTradeGramDisplay(orderGoldAmount.value)
|
||||||
|
)
|
||||||
|
|
||||||
const minOrderCash = computed(() => productMinOrderCash(props.ProductItem, isBuy.value))
|
const minOrderCash = computed(() => productMinOrderCash(props.ProductItem, isBuy.value))
|
||||||
const maxOrderCash = computed(() => productMaxOrderCash(props.ProductItem))
|
const maxOrderCash = computed(() => productMaxOrderCash(props.ProductItem))
|
||||||
const cashValidationMessage = computed(() =>
|
const cashValidationMessage = computed(() =>
|
||||||
@@ -620,20 +639,18 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
function percentChange(val: number) {
|
function percentChange(val: number) {
|
||||||
if (val !== 0)
|
if (val !== 0) {
|
||||||
if (isBuy.value) {
|
if (isBuy.value) {
|
||||||
form.value.goldCash = unitCashCalculator.value * val
|
form.value.goldCash = unitCashCalculator.value * val
|
||||||
calculateGold(form.value.goldCash)
|
calculateGold(form.value.goldCash)
|
||||||
calculateCash(form.value.goldValue)
|
|
||||||
} else {
|
} else {
|
||||||
// console.log((unitGoldCalculator.value * val).toFixed(2))
|
form.value.goldValue = formatTradeGramDisplay(parseFloat(String(unitGoldCalculator.value * val)))
|
||||||
// form.value.goldValue = parseFloat((unitGoldCalculator.value * val).toFixed(2))
|
|
||||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(unitGoldCalculator.value * val))
|
|
||||||
calculateCash(form.value.goldValue)
|
calculateCash(form.value.goldValue)
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
form.value.goldValue = undefined
|
form.value.goldValue = undefined
|
||||||
form.value.goldCash = undefined
|
form.value.goldCash = undefined
|
||||||
|
inputLock.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,11 +662,13 @@ const unitCashCalculator = computed(() => {
|
|||||||
|
|
||||||
function syncFormWithLatestPrice() {
|
function syncFormWithLatestPrice() {
|
||||||
const unit = unitPrice.value
|
const unit = unitPrice.value
|
||||||
if (!unit || Number.isNaN(unit)) return
|
if (!unit || Number.isNaN(unit) || !inputLock.value) return
|
||||||
|
|
||||||
const goldValue = form.value.goldValue
|
if (inputLock.value === 'gram') {
|
||||||
if (goldValue !== undefined && goldValue !== null && goldValue !== '' && !isNaN(Number(goldValue))) {
|
const goldValue = form.value.goldValue
|
||||||
calculateCash(Number(goldValue))
|
if (goldValue !== undefined && goldValue !== null && goldValue !== '' && !isNaN(Number(goldValue))) {
|
||||||
|
calculateCash(Number(goldValue))
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,42 +685,36 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch([feeDeductFromGold, () => serviceFeePercentage.value], () => {
|
||||||
|
syncFormWithLatestPrice()
|
||||||
|
})
|
||||||
|
|
||||||
function calculateCash(val: number) {
|
function calculateCash(val: number) {
|
||||||
priceErrorVisible.value = false
|
inputLock.value = 'gram'
|
||||||
const unit = unitPrice.value
|
const unit = unitPrice.value
|
||||||
if (!unit || Number.isNaN(unit)) return
|
if (!unit || Number.isNaN(unit)) return
|
||||||
|
|
||||||
form.value.goldCash = val ? parseFloat((val * unit).toFixed(0)) : undefined
|
if (val === undefined || val === null || Number.isNaN(val)) {
|
||||||
|
form.value.goldCash = undefined
|
||||||
|
inputLock.value = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
form.value.goldCash = calcRialFromLockedGram(val, unit, isBuy.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateGold(val: number) {
|
function calculateGold(val: number) {
|
||||||
|
inputLock.value = 'rial'
|
||||||
const unit = unitPrice.value
|
const unit = unitPrice.value
|
||||||
if (!unit || Number.isNaN(unit)) return
|
if (!unit || Number.isNaN(unit)) return
|
||||||
|
|
||||||
if (isBuy.value) {
|
if (val) {
|
||||||
if (val) {
|
form.value.goldValue = formatTradeGramDisplay(calcGramFromLockedRial(val, unit, isBuy.value))
|
||||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
|
|
||||||
priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0
|
|
||||||
} else if (val.toString() === '') {
|
|
||||||
form.value.goldValue = undefined
|
|
||||||
priceErrorVisible.value = false
|
|
||||||
} else {
|
|
||||||
form.value.goldValue = 0
|
|
||||||
priceErrorVisible.value = false
|
|
||||||
}
|
|
||||||
} else if (val) {
|
|
||||||
if (!isBuy.value && feeDeductFromGold.value) {
|
|
||||||
form.value.goldValue = parseFloat((val / unit).toFixed(6))
|
|
||||||
} else {
|
|
||||||
form.value.goldValue = toFixedDownThreeChar(parseFloat(String(val / unit)))
|
|
||||||
}
|
|
||||||
priceErrorVisible.value = parseInt(String(finalPrice.value)) > 0
|
|
||||||
} else if (val.toString() === '') {
|
} else if (val.toString() === '') {
|
||||||
form.value.goldValue = undefined
|
form.value.goldValue = undefined
|
||||||
priceErrorVisible.value = false
|
inputLock.value = null
|
||||||
} else {
|
} else {
|
||||||
form.value.goldValue = 0
|
form.value.goldValue = 0
|
||||||
priceErrorVisible.value = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,7 +737,7 @@ function setIsBuy(val: boolean) {
|
|||||||
form.value.goldValue = undefined
|
form.value.goldValue = undefined
|
||||||
form.value.goldCash = undefined
|
form.value.goldCash = undefined
|
||||||
form.value.percentWallet = 0
|
form.value.percentWallet = 0
|
||||||
priceErrorVisible.value = false
|
inputLock.value = null
|
||||||
// console.log(bganim.value.classList)
|
// console.log(bganim.value.classList)
|
||||||
// bganim?.value?.classList.add(val?'right':'left')
|
// bganim?.value?.classList.add(val?'right':'left')
|
||||||
// bganim?.value?.style.transform = `translateX(${val ? '0' : '-100'});`
|
// bganim?.value?.style.transform = `translateX(${val ? '0' : '-100'});`
|
||||||
@@ -767,6 +780,9 @@ function okConfirm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function ok() {
|
async function ok() {
|
||||||
|
if (loading.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (isStoreClosed()) {
|
if (isStoreClosed()) {
|
||||||
message.warning(getStoreClosedMessage())
|
message.warning(getStoreClosedMessage())
|
||||||
return
|
return
|
||||||
@@ -777,19 +793,27 @@ async function ok() {
|
|||||||
await createOrder({
|
await createOrder({
|
||||||
direction: isBuy.value ? 1 : 2,
|
direction: isBuy.value ? 1 : 2,
|
||||||
price: Math.round(unitPrice.value),
|
price: Math.round(unitPrice.value),
|
||||||
amount: orderGoldAmount.value,
|
amount: normalizeOrderGoldAmount(orderGoldAmount.value),
|
||||||
target_cash: calcSellTargetCash(form.value.goldCash, form.value.goldValue, unitPrice.value),
|
target_cash: calcTradeTargetCash(form.value.goldCash, inputLock.value)
|
||||||
|
?? calcSellTargetCash(
|
||||||
|
form.value.goldCash,
|
||||||
|
form.value.goldValue,
|
||||||
|
unitPrice.value,
|
||||||
|
inputLock.value
|
||||||
|
),
|
||||||
abshode_id: props.ProductItem?.id,
|
abshode_id: props.ProductItem?.id,
|
||||||
})
|
})
|
||||||
confirmAction.value = false
|
confirmAction.value = false
|
||||||
await walletStore.getMyWallet()
|
await walletStore.getMyWallet()
|
||||||
await loadWalletAssets(true)
|
await loadWalletAssets(true)
|
||||||
|
resetTransactionsPageData()
|
||||||
await router.push({ name: 'transactions' })
|
await router.push({ name: 'transactions' })
|
||||||
form.value = {
|
form.value = {
|
||||||
goldValue: undefined,
|
goldValue: undefined,
|
||||||
goldCash: undefined,
|
goldCash: undefined,
|
||||||
percentWallet: undefined
|
percentWallet: undefined
|
||||||
}
|
}
|
||||||
|
inputLock.value = null
|
||||||
message.success('سفارش شما با موفقیت انجام شد')
|
message.success('سفارش شما با موفقیت انجام شد')
|
||||||
await fundStore.getMyFund()
|
await fundStore.getMyFund()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -9,15 +9,13 @@
|
|||||||
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(countBasedInventory, false) }} عدد</div>
|
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(countBasedInventory, false) }} عدد</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<PortfolioOverview v-if="!boursecuLayout" variant="mobile" />
|
|
||||||
|
|
||||||
<BoursecuAssetsSummary
|
<BoursecuAssetsSummary
|
||||||
v-else-if="boursecuLayout"
|
v-if="boursecuLayout"
|
||||||
variant="mobile"
|
variant="mobile"
|
||||||
icon-color="primary"
|
icon-color="primary"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<template v-else-if="showLegacyRows && meta?.single_metal && primaryMetalTotal">
|
<template v-else-if="meta?.single_metal && primaryMetalTotal">
|
||||||
<div :class="[rowClass, meta?.has_count_based_products ? 'mt-2' : '']" class="flex justify-center w-full z-20">
|
<div :class="[rowClass, meta?.has_count_based_products ? 'mt-2' : '']" class="flex justify-center w-full z-20">
|
||||||
{{ primaryMetalTotal.label }}:
|
{{ primaryMetalTotal.label }}:
|
||||||
<div class="text-l mr-2 font-bold">{{ formatMetalTotal(primaryMetalTotal) }}</div>
|
<div class="text-l mr-2 font-bold">{{ formatMetalTotal(primaryMetalTotal) }}</div>
|
||||||
@@ -29,6 +27,8 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PortfolioProfitInsight variant="mobile" />
|
||||||
|
|
||||||
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
|
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
|
||||||
دارایی ریالی:
|
دارایی ریالی:
|
||||||
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
|
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="showLegacyRows && !boursecuLayout">
|
<template v-else-if="!boursecuLayout">
|
||||||
<div
|
<div
|
||||||
v-for="(metal, index) in metalTotals"
|
v-for="(metal, index) in metalTotals"
|
||||||
:key="metal.metal_id"
|
:key="metal.metal_id"
|
||||||
@@ -59,6 +59,8 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PortfolioProfitInsight variant="mobile" />
|
||||||
|
|
||||||
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
|
<div :class="[rowClass, 'mt-2']" class="flex justify-center w-full z-20">
|
||||||
دارایی ریالی:
|
دارایی ریالی:
|
||||||
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
|
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
|
||||||
@@ -77,7 +79,7 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
import BoursecuAssetsSummary from './BoursecuAssetsSummary.vue'
|
import BoursecuAssetsSummary from './BoursecuAssetsSummary.vue'
|
||||||
import PortfolioOverview from './PortfolioOverview.vue'
|
import PortfolioProfitInsight from './PortfolioProfitInsight.vue'
|
||||||
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
import type { WalletMetalTotal } from '@/models/walletAssets'
|
import type { WalletMetalTotal } from '@/models/walletAssets'
|
||||||
@@ -119,8 +121,6 @@ const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? []
|
|||||||
const countBasedInventory = computed(() =>
|
const countBasedInventory = computed(() =>
|
||||||
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
|
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
|
||||||
)
|
)
|
||||||
const showLegacyRows = computed(() => !assetsSummary.value?.portfolio)
|
|
||||||
|
|
||||||
function formatMetalTotal(metal: WalletMetalTotal) {
|
function formatMetalTotal(metal: WalletMetalTotal) {
|
||||||
return `${formatWeightAmount(resolveSummaryMetalWeight(metal, inventoryCards.value))}${metal.unit}`
|
return `${formatWeightAmount(resolveSummaryMetalWeight(metal, inventoryCards.value))}${metal.unit}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,21 @@
|
|||||||
'portfolio-overview__profit--down': profitTone === 'loss',
|
'portfolio-overview__profit--down': profitTone === 'loss',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<span class="portfolio-overview__profit-amount">{{ profitText }}</span>
|
<div class="portfolio-overview__profit-main">
|
||||||
<span v-if="profitPercent" class="portfolio-overview__profit-percent">{{ profitPercent }}</span>
|
<span class="portfolio-overview__profit-amount">{{ profitText }}</span>
|
||||||
<span class="portfolio-overview__profit-hint">سود/زیان تحققنیافته طلا</span>
|
<span v-if="profitPercent" class="portfolio-overview__profit-percent">{{ profitPercent }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="portfolio-overview__profit-label">
|
||||||
|
<span class="portfolio-overview__profit-hint">سود/زیان تحققنیافته طلا</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="portfolio-overview__profit-info"
|
||||||
|
aria-label="اطلاعات بیشتر"
|
||||||
|
@click="openProfitInfo"
|
||||||
|
>
|
||||||
|
<BasicIcon icon="vuesax-linear:info-circle" size="14" color="tertiary" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="portfolio-overview__grid">
|
<div class="portfolio-overview__grid">
|
||||||
@@ -36,17 +48,16 @@
|
|||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p v-if="hasProfitInsight && averageBuyPrice" class="portfolio-overview__footnote">
|
|
||||||
بر اساس میانگین خرید {{ usePriceWithoutType(averageBuyPrice) }} ریال و قیمت فعلی
|
|
||||||
{{ usePriceWithoutType(liveGoldPrice) }} ریال
|
|
||||||
</p>
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, h } from 'vue'
|
||||||
|
import { Modal } from 'ant-design-vue'
|
||||||
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
import {
|
import {
|
||||||
|
formatPortfolioProfitInfoText,
|
||||||
formatPortfolioProfitLabel,
|
formatPortfolioProfitLabel,
|
||||||
formatPortfolioProfitPercent,
|
formatPortfolioProfitPercent,
|
||||||
formatPortfolioProfitText,
|
formatPortfolioProfitText,
|
||||||
@@ -79,8 +90,6 @@ const metalRial = computed(() => {
|
|||||||
return resolveAssetsRialValue(assetsSummary.value, getTradeBuyPrice(lastPrice.value))
|
return resolveAssetsRialValue(assetsSummary.value, getTradeBuyPrice(lastPrice.value))
|
||||||
})
|
})
|
||||||
const goldWeight = computed(() => Number(portfolio.value?.gold_weight ?? 0))
|
const goldWeight = computed(() => Number(portfolio.value?.gold_weight ?? 0))
|
||||||
const averageBuyPrice = computed(() => portfolio.value?.average_buy_price ?? null)
|
|
||||||
const liveGoldPrice = computed(() => Number(portfolio.value?.live_gold_price ?? 0))
|
|
||||||
|
|
||||||
const hasProfitInsight = computed(() => portfolio.value?.unrealized_profit_rial != null)
|
const hasProfitInsight = computed(() => portfolio.value?.unrealized_profit_rial != null)
|
||||||
const profitTone = computed(() => formatPortfolioProfitLabel(portfolio.value?.unrealized_profit_rial))
|
const profitTone = computed(() => formatPortfolioProfitLabel(portfolio.value?.unrealized_profit_rial))
|
||||||
@@ -89,6 +98,33 @@ const profitPercent = computed(() =>
|
|||||||
formatPortfolioProfitPercent(portfolio.value?.unrealized_profit_percent)
|
formatPortfolioProfitPercent(portfolio.value?.unrealized_profit_percent)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
function renderModalLines(text: string) {
|
||||||
|
return h(
|
||||||
|
'div',
|
||||||
|
{ style: { lineHeight: '1.9' } },
|
||||||
|
text.split('\n').map((line, index) =>
|
||||||
|
h(
|
||||||
|
'div',
|
||||||
|
{ key: index, style: index > 0 ? { marginTop: '6px' } : undefined },
|
||||||
|
line
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openProfitInfo() {
|
||||||
|
const p = portfolio.value
|
||||||
|
if (!p) return
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: 'سود/زیان تحققنیافته طلا',
|
||||||
|
content: renderModalLines(formatPortfolioProfitInfoText(p, weightUnit.value)),
|
||||||
|
okText: 'متوجه شدم',
|
||||||
|
centered: true,
|
||||||
|
cancelButtonProps: { style: { display: 'none' } },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const rootClass = computed(() => [
|
const rootClass = computed(() => [
|
||||||
'portfolio-overview',
|
'portfolio-overview',
|
||||||
`portfolio-overview--${props.variant}`,
|
`portfolio-overview--${props.variant}`,
|
||||||
@@ -146,17 +182,46 @@ const rootClass = computed(() => [
|
|||||||
|
|
||||||
.portfolio-overview__profit {
|
.portfolio-overview__profit {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
align-items: center;
|
gap: 6px;
|
||||||
gap: 8px;
|
padding: 10px 12px;
|
||||||
padding: 8px 10px;
|
border-radius: 12px;
|
||||||
border-radius: 10px;
|
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
background: rgba(255, 255, 255, 0.12);
|
background: rgba(255, 255, 255, 0.12);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.portfolio-overview__profit-main {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-overview__profit-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-overview__profit-info {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 0;
|
||||||
|
opacity: 0.85;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.portfolio-overview--desktop .portfolio-overview__profit {
|
.portfolio-overview--desktop .portfolio-overview__profit {
|
||||||
background: #f9fafb;
|
background: #f9fafb;
|
||||||
}
|
}
|
||||||
@@ -244,16 +309,4 @@ const rootClass = computed(() => [
|
|||||||
color: #9ca3af;
|
color: #9ca3af;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portfolio-overview__footnote {
|
|
||||||
margin: 10px 0 0;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 1.6;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.portfolio-overview--desktop .portfolio-overview__footnote {
|
|
||||||
color: #6b7280;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="hasProfitInsight"
|
||||||
|
class="portfolio-profit"
|
||||||
|
:class="[
|
||||||
|
`portfolio-profit--${variant}`,
|
||||||
|
{
|
||||||
|
'portfolio-profit--up': profitTone === 'profit',
|
||||||
|
'portfolio-profit--down': profitTone === 'loss',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<div class="portfolio-profit__main">
|
||||||
|
<span class="portfolio-profit__amount">{{ profitText }}</span>
|
||||||
|
<span v-if="profitPercent" class="portfolio-profit__percent">{{ profitPercent }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="portfolio-profit__label-row">
|
||||||
|
<span class="portfolio-profit__hint">سود/زیان تحققنیافته طلا</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="portfolio-profit__info"
|
||||||
|
aria-label="اطلاعات بیشتر"
|
||||||
|
@click="openInfoModal"
|
||||||
|
>
|
||||||
|
<BasicIcon
|
||||||
|
icon="vuesax-linear:info-circle"
|
||||||
|
:size="variant === 'desktop' ? 14 : 16"
|
||||||
|
:color="infoIconColor"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, h } from 'vue'
|
||||||
|
import { Modal } from 'ant-design-vue'
|
||||||
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
|
import {
|
||||||
|
formatPortfolioProfitInfoText,
|
||||||
|
formatPortfolioProfitLabel,
|
||||||
|
formatPortfolioProfitPercent,
|
||||||
|
formatPortfolioProfitText,
|
||||||
|
} from '@/utils/productAssets'
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
variant?: 'mobile' | 'desktop'
|
||||||
|
}>(),
|
||||||
|
{ variant: 'mobile' }
|
||||||
|
)
|
||||||
|
|
||||||
|
const { assetsSummary } = useWalletAssets()
|
||||||
|
|
||||||
|
const portfolio = computed(() => assetsSummary.value?.portfolio)
|
||||||
|
const weightUnit = computed(() => assetsSummary.value?.meta?.weight_unit || 'گرم')
|
||||||
|
|
||||||
|
const hasProfitInsight = computed(() => portfolio.value?.unrealized_profit_rial != null)
|
||||||
|
const profitTone = computed(() => formatPortfolioProfitLabel(portfolio.value?.unrealized_profit_rial))
|
||||||
|
const profitText = computed(() => formatPortfolioProfitText(portfolio.value?.unrealized_profit_rial))
|
||||||
|
const profitPercent = computed(() =>
|
||||||
|
formatPortfolioProfitPercent(portfolio.value?.unrealized_profit_percent)
|
||||||
|
)
|
||||||
|
const infoIconColor = computed(() => (props.variant === 'desktop' ? 'tertiary' : 'tertiary'))
|
||||||
|
|
||||||
|
function renderModalLines(text: string) {
|
||||||
|
return h(
|
||||||
|
'div',
|
||||||
|
{ style: { lineHeight: '1.9' } },
|
||||||
|
text.split('\n').map((line, index) =>
|
||||||
|
h(
|
||||||
|
'div',
|
||||||
|
{ key: index, style: index > 0 ? { marginTop: '6px' } : undefined },
|
||||||
|
line
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInfoModal() {
|
||||||
|
const p = portfolio.value
|
||||||
|
if (!p) return
|
||||||
|
|
||||||
|
Modal.confirm({
|
||||||
|
title: 'سود/زیان تحققنیافته طلا',
|
||||||
|
content: renderModalLines(formatPortfolioProfitInfoText(p, weightUnit.value)),
|
||||||
|
okText: 'متوجه شدم',
|
||||||
|
centered: true,
|
||||||
|
cancelButtonProps: { style: { display: 'none' } },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.portfolio-profit {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-top: 10px;
|
||||||
|
background: linear-gradient(145deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.06));
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.22);
|
||||||
|
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop {
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: linear-gradient(145deg, #f9fafb, #f3f4f6);
|
||||||
|
border: 1px solid rgba(15, 23, 42, 0.06);
|
||||||
|
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
|
||||||
|
backdrop-filter: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit__main {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop .portfolio-profit__main {
|
||||||
|
justify-content: flex-start;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--up {
|
||||||
|
color: #bbf7d0;
|
||||||
|
border-color: rgba(187, 247, 208, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop.portfolio-profit--up {
|
||||||
|
color: #027a48;
|
||||||
|
background: linear-gradient(145deg, #ecfdf3, #d1fae5);
|
||||||
|
border-color: rgba(2, 122, 72, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--down {
|
||||||
|
color: #fecaca;
|
||||||
|
border-color: rgba(254, 202, 202, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop.portfolio-profit--down {
|
||||||
|
color: #b42318;
|
||||||
|
background: linear-gradient(145deg, #fef3f2, #fee4e2);
|
||||||
|
border-color: rgba(180, 35, 24, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit__percent {
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: isolate;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
font-size: 0.92em;
|
||||||
|
opacity: 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit__label-row {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop .portfolio-profit__label-row {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit__hint {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.88;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit--desktop .portfolio-profit__hint {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portfolio-profit__info {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.85;
|
||||||
|
line-height: 0;
|
||||||
|
transition: opacity 0.15s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
import BoursecuAssetsSummary from '../../components/BoursecuAssetsSummary.vue'
|
import BoursecuAssetsSummary from '../../components/BoursecuAssetsSummary.vue'
|
||||||
import PortfolioOverview from '../../components/PortfolioOverview.vue'
|
import PortfolioProfitInsight from '../../components/PortfolioProfitInsight.vue'
|
||||||
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
import { formatWeightAmount, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import { useWalletAssets } from '@/composables/useWalletAssets'
|
import { useWalletAssets } from '@/composables/useWalletAssets'
|
||||||
import type { WalletMetalTotal } from '@/models/walletAssets'
|
import type { WalletMetalTotal } from '@/models/walletAssets'
|
||||||
@@ -25,7 +25,6 @@ const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
|
|||||||
const countBasedInventory = computed(() =>
|
const countBasedInventory = computed(() =>
|
||||||
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0),
|
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0),
|
||||||
)
|
)
|
||||||
const showLegacyMetrics = computed(() => !assetsSummary.value?.portfolio)
|
|
||||||
|
|
||||||
type MetricItem = {
|
type MetricItem = {
|
||||||
id: string
|
id: string
|
||||||
@@ -104,9 +103,9 @@ function handleInfo(metric: MetricItem) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<PortfolioOverview variant="desktop" />
|
<PortfolioProfitInsight variant="desktop" />
|
||||||
|
|
||||||
<div v-if="showLegacyMetrics" class="dhome-metrics">
|
<div class="dhome-metrics">
|
||||||
<article v-for="metric in metrics" :key="metric.id" class="dhome-metric-tile">
|
<article v-for="metric in metrics" :key="metric.id" class="dhome-metric-tile">
|
||||||
<div class="dhome-metric-tile__head">
|
<div class="dhome-metric-tile__head">
|
||||||
<span class="dhome-metric-tile__label">{{ metric.label }}</span>
|
<span class="dhome-metric-tile__label">{{ metric.label }}</span>
|
||||||
|
|||||||
@@ -37,13 +37,7 @@ const showSkeleton = computed(() => Boolean(getToken()) && !userInfo.value)
|
|||||||
<HomeSkeleton v-if="showSkeleton" />
|
<HomeSkeleton v-if="showSkeleton" />
|
||||||
|
|
||||||
<template v-if="showContent">
|
<template v-if="showContent">
|
||||||
<DesktopAssetsMetrics
|
<section v-if="ctx.isGaroosi.value" class="dhome-hero-row">
|
||||||
v-if="!ctx.isGaroosi.value"
|
|
||||||
@open-gold-modal="ctx.openGoldModal"
|
|
||||||
@open-rial-modal="ctx.openRialModal"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<section class="dhome-hero-row">
|
|
||||||
<DesktopLivePrice />
|
<DesktopLivePrice />
|
||||||
<DesktopPriceRange />
|
<DesktopPriceRange />
|
||||||
</section>
|
</section>
|
||||||
@@ -74,6 +68,17 @@ const showSkeleton = computed(() => Boolean(getToken()) && !userInfo.value)
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<DesktopDefaultActions />
|
<DesktopDefaultActions />
|
||||||
|
|
||||||
|
<DesktopAssetsMetrics
|
||||||
|
@open-gold-modal="ctx.openGoldModal"
|
||||||
|
@open-rial-modal="ctx.openRialModal"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<section class="dhome-hero-row">
|
||||||
|
<DesktopLivePrice />
|
||||||
|
<DesktopPriceRange />
|
||||||
|
</section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
v-if="ctx.bannerEnabled.value && ctx.banners.value?.length"
|
v-if="ctx.bannerEnabled.value && ctx.banners.value?.length"
|
||||||
class="dhome-surface dhome-chart-banner-combined"
|
class="dhome-surface dhome-chart-banner-combined"
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ const innerSections = computed(() =>
|
|||||||
layoutConfig.value.sections.filter((section) => section.visible !== false)
|
layoutConfig.value.sections.filter((section) => section.visible !== false)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const tailSections = computed(() =>
|
||||||
|
(layoutConfig.value.tailSections ?? []).filter((section) => section.visible !== false)
|
||||||
|
)
|
||||||
|
|
||||||
/** محتوا با userInfo — دادههای API در پسزمینه لود میشوند */
|
/** محتوا با userInfo — دادههای API در پسزمینه لود میشوند */
|
||||||
const showContent = computed(() => Boolean(userInfo.value))
|
const showContent = computed(() => Boolean(userInfo.value))
|
||||||
const showSkeleton = computed(() => Boolean(getToken()) && !userInfo.value)
|
const showSkeleton = computed(() => Boolean(getToken()) && !userInfo.value)
|
||||||
@@ -56,6 +60,12 @@ function resolveSectionComponent(sectionId: HomeSectionId) {
|
|||||||
:key="section.id"
|
:key="section.id"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<component
|
||||||
|
:is="resolveSectionComponent(section.id)"
|
||||||
|
v-for="section in tailSections"
|
||||||
|
:key="`tail-${section.id}`"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HomeSkeleton v-else-if="showSkeleton" class="w-full" />
|
<HomeSkeleton v-else-if="showSkeleton" class="w-full" />
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ import type { HomeLayoutConfig } from '../types'
|
|||||||
/** چیدمان پیشفرض — همه پروژهها بهجز boursecu */
|
/** چیدمان پیشفرض — همه پروژهها بهجز boursecu */
|
||||||
export const defaultHomeLayoutConfig: HomeLayoutConfig = {
|
export const defaultHomeLayoutConfig: HomeLayoutConfig = {
|
||||||
id: 'default',
|
id: 'default',
|
||||||
wrapperClass: 'p-1 from-primary rounded-lg p-px to-transparent mt-5',
|
wrapperClass: 'p-1 shadow-lg from-primary rounded-lg p-px to-transparent mt-5',
|
||||||
sections: [
|
sections: [
|
||||||
{ id: 'garoosiAssets' },
|
{ id: 'garoosiAssets' },
|
||||||
{ id: 'assets' },
|
|
||||||
{ id: 'mainActions' },
|
{ id: 'mainActions' },
|
||||||
{ id: 'referral' },
|
{ id: 'referral' },
|
||||||
|
{ id: 'assets' },
|
||||||
|
],
|
||||||
|
tailSections: [
|
||||||
{ id: 'marketClosed' },
|
{ id: 'marketClosed' },
|
||||||
{ id: 'currentPrice' },
|
{ id: 'currentPrice' },
|
||||||
{ id: 'banners' },
|
{ id: 'banners' },
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export interface HomeLayoutConfig {
|
|||||||
wrapperClass?: string
|
wrapperClass?: string
|
||||||
outerSections?: HomeLayoutSectionConfig[]
|
outerSections?: HomeLayoutSectionConfig[]
|
||||||
sections: HomeLayoutSectionConfig[]
|
sections: HomeLayoutSectionConfig[]
|
||||||
|
/** بعد از wrapper — مثل قیمت و نمودار در UI قدیمی */
|
||||||
|
tailSections?: HomeLayoutSectionConfig[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HomeActionItem {
|
export interface HomeActionItem {
|
||||||
|
|||||||
@@ -281,11 +281,13 @@ import type { TableEngineInput, TableOutput } from '@/models/table'
|
|||||||
import { getTransactionTable } from '@/api/transaction'
|
import { getTransactionTable } from '@/api/transaction'
|
||||||
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
|
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
|
||||||
import { getProductBuyPrice, getProductSellPrice, isProductPriceInactive } from '@/utils/productPrice'
|
import { getProductBuyPrice, getProductSellPrice, isProductPriceInactive } from '@/utils/productPrice'
|
||||||
|
import { resolveProductCashFeeBuyRial, resolveProductCashFeeSellRial } from '@/utils/productCashFee'
|
||||||
import { Product } from '@/models/products'
|
import { Product } from '@/models/products'
|
||||||
import BasicSelect from '@/components/BasicPacks/BasicSelect.vue'
|
import BasicSelect from '@/components/BasicPacks/BasicSelect.vue'
|
||||||
import Bg_main from '@/components/bg_main.vue'
|
import Bg_main from '@/components/bg_main.vue'
|
||||||
import { useFundUserStore } from '@/store/fundStore'
|
import { useFundUserStore } from '@/store/fundStore'
|
||||||
import { getProductsCatalogRef } from '@/composables/useProductsCatalog'
|
import { getProductsCatalogRef } from '@/composables/useProductsCatalog'
|
||||||
|
import { resetTransactionsPageData } from '@/views/base/transactions/composables/useTransactionsPageData'
|
||||||
import {
|
import {
|
||||||
getDefaultProductDealMethod,
|
getDefaultProductDealMethod,
|
||||||
getProductDealMethodOptions,
|
getProductDealMethodOptions,
|
||||||
@@ -401,22 +403,9 @@ interface Prop {
|
|||||||
const props = withDefaults(defineProps<Prop>(), {})
|
const props = withDefaults(defineProps<Prop>(), {})
|
||||||
const emit = defineEmits<{ ordered: [] }>()
|
const emit = defineEmits<{ ordered: [] }>()
|
||||||
const isBuy = ref<boolean>(true)
|
const isBuy = ref<boolean>(true)
|
||||||
const buyTotalPrice = computed(() => {
|
const buyTotalPrice = computed(() => resolveProductTradeBuyUnitPrice(props?.ProductItem))
|
||||||
const item = props?.ProductItem
|
|
||||||
if (!item) return 0
|
|
||||||
const basePrice = (item.price ?? 0) + (item.cash_fee_buy ?? 0)
|
|
||||||
|
|
||||||
return basePrice * productPriceAmountFactor(item)
|
const sellTotalPrice = computed(() => resolveProductTradeSellUnitPrice(props?.ProductItem))
|
||||||
})
|
|
||||||
|
|
||||||
const sellTotalPrice = computed(() => {
|
|
||||||
const item = props?.ProductItem
|
|
||||||
if (!item) return 0
|
|
||||||
|
|
||||||
const basePrice = (item.price ?? 0) - (item.cash_fee_sell ?? 0)
|
|
||||||
|
|
||||||
return basePrice * productPriceAmountFactor(item)
|
|
||||||
})
|
|
||||||
const buyFee = computed(() => ((props?.ProductItem?.amount * (props?.ProductItem?.percent_fee_buy ?? 0) * (props?.ProductItem?.price ?? 0)).toFixed(0)))
|
const buyFee = computed(() => ((props?.ProductItem?.amount * (props?.ProductItem?.percent_fee_buy ?? 0) * (props?.ProductItem?.price ?? 0)).toFixed(0)))
|
||||||
const sellFee = computed(() => ((props?.ProductItem?.amount * (props?.ProductItem?.percent_fee_sell ?? 0) * (props?.ProductItem?.sellPrice ?? 0)).toFixed(0)))
|
const sellFee = computed(() => ((props?.ProductItem?.amount * (props?.ProductItem?.percent_fee_sell ?? 0) * (props?.ProductItem?.sellPrice ?? 0)).toFixed(0)))
|
||||||
|
|
||||||
@@ -737,7 +726,8 @@ function calculateCash(val: number) {
|
|||||||
// form.value.goldVazn = parseFloat((val * (( props?.ProductItem?.price) + (props?.ProductItem?.cash_fee_buy)))/lastPrice.value?.buy).toFixed(2)
|
// form.value.goldVazn = parseFloat((val * (( props?.ProductItem?.price) + (props?.ProductItem?.cash_fee_buy)))/lastPrice.value?.buy).toFixed(2)
|
||||||
if (isBuy.value) {
|
if (isBuy.value) {
|
||||||
if (val){
|
if (val){
|
||||||
const unitPrice = (props?.ProductItem?.price ?? 0) + (props?.ProductItem?.cash_fee_buy ?? 0)
|
const base = props?.ProductItem?.price ?? 0
|
||||||
|
const unitPrice = base + resolveProductCashFeeBuyRial(props?.ProductItem, base)
|
||||||
form.value.goldCash = parseFloat(String(val * unitPrice * productPriceAmountFactor(props?.ProductItem))).toFixed(0)
|
form.value.goldCash = parseFloat(String(val * unitPrice * productPriceAmountFactor(props?.ProductItem))).toFixed(0)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -747,7 +737,8 @@ function calculateCash(val: number) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (val){
|
if (val){
|
||||||
const unitPrice = (props?.ProductItem?.price ?? 0) - (props?.ProductItem?.cash_fee_sell ?? 0)
|
const base = props?.ProductItem?.price ?? 0
|
||||||
|
const unitPrice = base - resolveProductCashFeeSellRial(props?.ProductItem, base)
|
||||||
form.value.goldCash = parseFloat(String(val * unitPrice * productPriceAmountFactor(props?.ProductItem))).toFixed(0)
|
form.value.goldCash = parseFloat(String(val * unitPrice * productPriceAmountFactor(props?.ProductItem))).toFixed(0)
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -838,8 +829,11 @@ async function initPrice() {
|
|||||||
await getLastPrices()
|
await getLastPrices()
|
||||||
// await setIntervalGetPrice()
|
// await setIntervalGetPrice()
|
||||||
loading.value = true
|
loading.value = true
|
||||||
props.ProductItem.price = lastPrice?.value?.price? (lastPrice?.value?.price + props.ProductItem?.cash_fee_buy) * props.ProductItem?.amount: 0
|
const livePrice = lastPrice?.value?.price ?? 0
|
||||||
props.ProductItem.sellPrice = lastPrice?.value?.price? (lastPrice?.value?.price - props.ProductItem?.percent_fee_sell) * props.ProductItem?.amount:0
|
const buyFee = resolveProductCashFeeBuyRial(props.ProductItem, livePrice)
|
||||||
|
const sellFee = resolveProductCashFeeSellRial(props.ProductItem, livePrice)
|
||||||
|
props.ProductItem.price = livePrice ? (livePrice + buyFee) * props.ProductItem.amount : 0
|
||||||
|
props.ProductItem.sellPrice = livePrice ? (livePrice - sellFee) * props.ProductItem.amount : 0
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -898,6 +892,7 @@ async function ok() {
|
|||||||
await loadWalletAssets(true)
|
await loadWalletAssets(true)
|
||||||
await fundStore.getMyFund()
|
await fundStore.getMyFund()
|
||||||
message.success('سفارش شما با موفقیت انجام شد')
|
message.success('سفارش شما با موفقیت انجام شد')
|
||||||
|
resetTransactionsPageData()
|
||||||
await router.push({ name: 'transactions' })
|
await router.push({ name: 'transactions' })
|
||||||
form.value = {
|
form.value = {
|
||||||
goldValue: undefined,
|
goldValue: undefined,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
? 'drules-content'
|
? 'drules-content'
|
||||||
: 'rules-panel border-solid border-2 border-primary text-primary rounded-[12px] p-4 mobile-content-box'"
|
: 'rules-panel border-solid border-2 border-primary text-primary rounded-[12px] p-4 mobile-content-box'"
|
||||||
>
|
>
|
||||||
<div :class="variant !== 'desktop' ? 'mobile-content-box__scroll' : undefined">
|
<div :class="variant === 'desktop' ? 'drules-content__scroll' : 'mobile-content-box__scroll'">
|
||||||
<div :class="variant === 'desktop' ? 'drules-content__title' : 'font-bold text-sm text-primary'">
|
<div :class="variant === 'desktop' ? 'drules-content__title' : 'font-bold text-sm text-primary'">
|
||||||
{{ rulesTitle }}
|
{{ rulesTitle }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -77,6 +77,10 @@
|
|||||||
|
|
||||||
.drules-main {
|
.drules-main {
|
||||||
padding: 28px;
|
padding: 28px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
max-height: calc(100vh - 180px);
|
||||||
|
|
||||||
&__intro {
|
&__intro {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -85,6 +89,7 @@
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
border-bottom: 1px solid #eef0f3;
|
border-bottom: 1px solid #eef0f3;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__logo {
|
&__logo {
|
||||||
@@ -114,12 +119,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.drules-content {
|
.drules-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border: 1px solid rgba(9, 61, 81, 0.12);
|
border: 1px solid rgba(9, 61, 81, 0.12);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: rgba(9, 61, 81, 0.02);
|
background: rgba(9, 61, 81, 0.02);
|
||||||
color: @App-primary-color;
|
color: @App-primary-color;
|
||||||
|
|
||||||
|
&__scroll {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overscroll-behavior-y: contain;
|
||||||
|
padding-left: 4px;
|
||||||
|
margin-left: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -206,6 +226,10 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drules-main {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
.drules-side {
|
.drules-side {
|
||||||
position: static;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<div class="dtxn-row__meta">
|
<div class="dtxn-row__meta">
|
||||||
<span>{{ toJalaliOutOfUTC(props.item.expire_at) }}</span>
|
<span>{{ toJalaliOutOfUTC(props.item.expire_at) }}</span>
|
||||||
<span :class="goldAmount >= 0 ? 'text-green-600' : 'text-red-600'">
|
<span :class="goldAmount >= 0 ? 'text-green-600' : 'text-red-600'">
|
||||||
{{ formatGoldAmount(goldAmount) }} {{ props.item.unit }}
|
{{ formatTransactionGoldAmount(props.item, goldAmount) }} {{ props.item.unit }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="isGold">
|
<span v-if="isGold">
|
||||||
قیمت معامله:
|
قیمت معامله:
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
{{ usePriceWithoutType(props.item.cash ?? 0) }} ریال
|
{{ usePriceWithoutType(props.item.cash ?? 0) }} ریال
|
||||||
</div>
|
</div>
|
||||||
<div class="dtxn-row__status">
|
<div class="dtxn-row__status">
|
||||||
<ATag color="blue" class="!py-1 !px-4 !ml-0 !text-xs">
|
<ATag v-if="statusLabel" color="blue" class="!py-1 !px-4 !ml-0 !text-xs">
|
||||||
{{ props.item.order?.sts_str ?? props.item.withdraw?.sts_str }}
|
{{ statusLabel }}
|
||||||
</ATag>
|
</ATag>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
:class="goldAmount >= 0 ? 'text-green-600' : 'text-red-600'"
|
:class="goldAmount >= 0 ? 'text-green-600' : 'text-red-600'"
|
||||||
class="text-gray-500 text-xs number-ltr"
|
class="text-gray-500 text-xs number-ltr"
|
||||||
>
|
>
|
||||||
{{ formatGoldAmount(goldAmount) }}
|
{{ formatTransactionGoldAmount(props.item, goldAmount) }}
|
||||||
<div>{{ props.item.unit }}</div>
|
<div>{{ props.item.unit }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-gray-500 flex gap-1 text-xs items-center number-ltr">
|
<div class="text-gray-500 flex gap-1 text-xs items-center number-ltr">
|
||||||
@@ -83,8 +83,8 @@
|
|||||||
<div class="flex w-full justify-between mt-2">
|
<div class="flex w-full justify-between mt-2">
|
||||||
<div class="text-gray-500">وضعیت :</div>
|
<div class="text-gray-500">وضعیت :</div>
|
||||||
<div class="text-gray-500 flex gap-1 text-xs items-center">
|
<div class="text-gray-500 flex gap-1 text-xs items-center">
|
||||||
<ATag class="!py-1 !px-6 !ml-0" color="blue">
|
<ATag v-if="statusLabel" class="!py-1 !px-6 !ml-0" color="blue">
|
||||||
{{ props.item.order?.sts_str ?? props.item.withdraw?.sts_str }}
|
{{ statusLabel }}
|
||||||
</ATag>
|
</ATag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,11 +115,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
||||||
import {
|
import {
|
||||||
formatGoldAmount,
|
|
||||||
getTransactionGoldAmount,
|
getTransactionGoldAmount,
|
||||||
getTransactionTradePrice,
|
getTransactionTradePrice,
|
||||||
|
resolveTransactionStatusLabel,
|
||||||
usePriceWithoutType,
|
usePriceWithoutType,
|
||||||
} from '@/utils/usePrice'
|
} from '@/utils/usePrice'
|
||||||
|
import { formatTransactionGoldAmount } from '@/utils/productDealMethod'
|
||||||
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
|
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
|
||||||
import BasicModal from '@/components/BasicPacks/BasicModal.vue'
|
import BasicModal from '@/components/BasicPacks/BasicModal.vue'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
@@ -140,6 +141,7 @@ const props = withDefaults(
|
|||||||
|
|
||||||
const goldAmount = computed(() => getTransactionGoldAmount(props.item))
|
const goldAmount = computed(() => getTransactionGoldAmount(props.item))
|
||||||
const tradePrice = computed(() => getTransactionTradePrice(props.item))
|
const tradePrice = computed(() => getTransactionTradePrice(props.item))
|
||||||
|
const statusLabel = computed(() => resolveTransactionStatusLabel(props.item))
|
||||||
|
|
||||||
const isUp = computed(
|
const isUp = computed(
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<div class="text-base">{{ formatGoldAmount(item.gold) }}</div>
|
<div class="text-base">{{ formatTransactionGoldAmount(item, item.gold) }}</div>
|
||||||
{{ item.unit }}
|
{{ item.unit }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-end text-xs text-yellow-700">
|
<div class="flex flex-col items-end text-xs text-yellow-700">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="text-base ml-1">{{ formatGoldAmount(item.balance_gold) }}</div>
|
<div class="text-base ml-1">{{ formatTransactionGoldAmount(item, item.balance_gold) }}</div>
|
||||||
{{ metalWalletBalanceUnit }}
|
{{ metalWalletBalanceUnit }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="getProductUnitWeightLabel(metalWalletProduct)" class="text-gray-500">
|
<div v-if="getProductUnitWeightLabel(metalWalletProduct)" class="text-gray-500">
|
||||||
@@ -93,8 +93,8 @@
|
|||||||
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
<div :class="variant === 'desktop' ? 'dtxn-detail__row' : 'flex justify-between mb-3'">
|
||||||
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">وضعیت:</div>
|
<div :class="variant === 'desktop' ? 'dtxn-detail__label' : 'text-primary'">وضعیت:</div>
|
||||||
<div class="flex text-xs items-center">
|
<div class="flex text-xs items-center">
|
||||||
<ATag color="blue" class="!py-1 !px-6 !ml-0">
|
<ATag v-if="statusLabel" color="blue" class="!py-1 !px-6 !ml-0">
|
||||||
{{ item.order?.sts_str ?? item.withdraw?.sts_str }}
|
{{ statusLabel }}
|
||||||
</ATag>
|
</ATag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,9 +115,10 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { formatGoldAmount, usePriceWithoutType } from '@/utils/usePrice'
|
import { resolveTransactionStatusLabel, usePriceWithoutType } from '@/utils/usePrice'
|
||||||
import type { Transaction } from '@/models/transaction'
|
import type { Transaction } from '@/models/transaction'
|
||||||
import {
|
import {
|
||||||
|
formatTransactionGoldAmount,
|
||||||
getCashWalletLabel,
|
getCashWalletLabel,
|
||||||
getProductTotalWeightLabel,
|
getProductTotalWeightLabel,
|
||||||
getProductUnitWeightLabel,
|
getProductUnitWeightLabel,
|
||||||
@@ -139,6 +140,7 @@ const props = withDefaults(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const tradeProduct = computed(() => resolveTransactionTradeProduct(props.item))
|
const tradeProduct = computed(() => resolveTransactionTradeProduct(props.item))
|
||||||
|
const statusLabel = computed(() => resolveTransactionStatusLabel(props.item))
|
||||||
const tradeProductLabel = computed(
|
const tradeProductLabel = computed(
|
||||||
() => (tradeProduct.value?.title ?? '').trim() || getMeltedGoldTradeLabel(),
|
() => (tradeProduct.value?.title ?? '').trim() || getMeltedGoldTradeLabel(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { computed, inject, onMounted, provide, ref, type ComponentPublicInstance, type InjectionKey } from 'vue'
|
import { computed, inject, onActivated, onMounted, provide, ref, type ComponentPublicInstance, type InjectionKey } from 'vue'
|
||||||
import { useIntersectionObserver } from '@vueuse/core'
|
import { useIntersectionObserver } from '@vueuse/core'
|
||||||
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
|
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
|
||||||
import { getProductsCatalog, getProductsCatalogRef } from '@/composables/useProductsCatalog'
|
import { getProductsCatalog, getProductsCatalogRef } from '@/composables/useProductsCatalog'
|
||||||
@@ -166,7 +166,7 @@ export function useTransactionsPageProvider(options?: { boursecu?: boolean }) {
|
|||||||
useIntersectionObserver(
|
useIntersectionObserver(
|
||||||
activeObserverEl,
|
activeObserverEl,
|
||||||
async ([entry]) => {
|
async ([entry]) => {
|
||||||
if (entry?.isIntersecting) {
|
if (entry?.isIntersecting && !loading.value && !loadingMore.value) {
|
||||||
await loadMoreTransactions()
|
await loadMoreTransactions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -184,6 +184,10 @@ export function useTransactionsPageProvider(options?: { boursecu?: boolean }) {
|
|||||||
await initTransactionsPageData(isBoursecu)
|
await initTransactionsPageData(isBoursecu)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onActivated(async () => {
|
||||||
|
await reloadTransactionsTable()
|
||||||
|
})
|
||||||
|
|
||||||
const context: TransactionsPageContext = {
|
const context: TransactionsPageContext = {
|
||||||
pagination: transactionPagination,
|
pagination: transactionPagination,
|
||||||
items: transactionItems,
|
items: transactionItems,
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ import {
|
|||||||
type BoursecuTransactionTabId,
|
type BoursecuTransactionTabId,
|
||||||
} from '../config/boursecuTabs'
|
} from '../config/boursecuTabs'
|
||||||
|
|
||||||
/** Shared transactions datasets — mobile/desktop views read this module state only. */
|
/** Shared transactions page state — refetched on every page visit (no list cache). */
|
||||||
let initPromise: Promise<void> | null = null
|
let activeFetchId = 0
|
||||||
const initialized = ref(false)
|
|
||||||
|
|
||||||
export const transactionsBoursecuMode = ref(false)
|
export const transactionsBoursecuMode = ref(false)
|
||||||
export const transactionPagination = ref<TableEngineInput>({ filters: [], limit: 7, page: 0 })
|
export const transactionPagination = ref<TableEngineInput>({ filters: [], limit: 7, page: 0 })
|
||||||
@@ -27,10 +26,6 @@ export const transactionProductFilter = ref<number>()
|
|||||||
export const transactionActiveTabId = ref<BoursecuTransactionTabId>('trades')
|
export const transactionActiveTabId = ref<BoursecuTransactionTabId>('trades')
|
||||||
export const transactionTradeSide = ref<BoursecuTradeSide>('buy')
|
export const transactionTradeSide = ref<BoursecuTradeSide>('buy')
|
||||||
|
|
||||||
export function isTransactionsPageDataInitialized() {
|
|
||||||
return initialized.value
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getActiveBoursecuTab(): BoursecuTransactionTab {
|
export function getActiveBoursecuTab(): BoursecuTransactionTab {
|
||||||
return (
|
return (
|
||||||
BOURSECU_TRANSACTION_TABS.find((tab) => tab.id === transactionActiveTabId.value) ??
|
BOURSECU_TRANSACTION_TABS.find((tab) => tab.id === transactionActiveTabId.value) ??
|
||||||
@@ -65,46 +60,67 @@ export function resetTransactionsPagination() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchTransactionsPage(append: boolean) {
|
function resolveTransactionFetcher() {
|
||||||
|
const activeTab = getActiveBoursecuTab()
|
||||||
|
return transactionsBoursecuMode.value && activeTab.fetchMode === 'deposit'
|
||||||
|
? getTransactionTable2
|
||||||
|
: getTransactionTable
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchTransactionsPage(append: boolean): Promise<boolean> {
|
||||||
|
const fetchId = ++activeFetchId
|
||||||
const isFirstPage = transactionPagination.value.page === 0 && !append
|
const isFirstPage = transactionPagination.value.page === 0 && !append
|
||||||
|
|
||||||
if (isFirstPage) {
|
if (isFirstPage) {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
loadingMore.value = false
|
||||||
} else {
|
} else {
|
||||||
loadingMore.value = true
|
loadingMore.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const activeTab = getActiveBoursecuTab()
|
const output = await resolveTransactionFetcher()(transactionPagination.value)
|
||||||
const fetcher =
|
if (fetchId !== activeFetchId) {
|
||||||
transactionsBoursecuMode.value && activeTab.fetchMode === 'deposit'
|
return false
|
||||||
? getTransactionTable2
|
}
|
||||||
: getTransactionTable
|
|
||||||
|
|
||||||
transactionTableOutput.value = await fetcher(transactionPagination.value)
|
transactionTableOutput.value = output
|
||||||
const rows = transactionTableOutput.value.rows ?? []
|
const rows = output.rows ?? []
|
||||||
|
|
||||||
if (isFirstPage) {
|
if (isFirstPage) {
|
||||||
transactionItems.value = [...rows]
|
transactionItems.value = [...rows]
|
||||||
} else {
|
} else {
|
||||||
transactionItems.value.push(...rows)
|
transactionItems.value.push(...rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching transactions:', error)
|
if (fetchId === activeFetchId) {
|
||||||
|
console.error('Error fetching transactions:', error)
|
||||||
|
}
|
||||||
|
return false
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
if (fetchId === activeFetchId) {
|
||||||
loadingMore.value = false
|
loading.value = false
|
||||||
|
loadingMore.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** همیشه از سرور — بدون کش لیست */
|
||||||
export async function reloadTransactionsTable() {
|
export async function reloadTransactionsTable() {
|
||||||
transactionPagination.value.page = 0
|
transactionPagination.value.page = 0
|
||||||
transactionItems.value = []
|
transactionItems.value = []
|
||||||
|
transactionTableOutput.value = null
|
||||||
resetTransactionsPagination()
|
resetTransactionsPagination()
|
||||||
await fetchTransactionsPage(false)
|
await fetchTransactionsPage(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadMoreTransactions() {
|
export async function loadMoreTransactions() {
|
||||||
|
if (loading.value || loadingMore.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!transactionTableOutput.value
|
!transactionTableOutput.value
|
||||||
|| (transactionPagination.value.page + 1) * transactionPagination.value.limit
|
|| (transactionPagination.value.page + 1) * transactionPagination.value.limit
|
||||||
@@ -117,40 +133,16 @@ export async function loadMoreTransactions() {
|
|||||||
await fetchTransactionsPage(true)
|
await fetchTransactionsPage(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initTransactionsPageData(boursecu: boolean, force = false) {
|
/** هر بار ورود به صفحه تراکنشها */
|
||||||
if (!force && initialized.value && transactionsBoursecuMode.value === boursecu) {
|
export async function initTransactionsPageData(boursecu: boolean) {
|
||||||
return
|
transactionsBoursecuMode.value = boursecu
|
||||||
}
|
await reloadTransactionsTable()
|
||||||
|
|
||||||
if (!force && initPromise) {
|
|
||||||
return initPromise
|
|
||||||
}
|
|
||||||
|
|
||||||
initPromise = (async () => {
|
|
||||||
try {
|
|
||||||
if (force) {
|
|
||||||
resetTransactionsPageData()
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionsBoursecuMode.value = boursecu
|
|
||||||
transactionPagination.value.page = 0
|
|
||||||
transactionItems.value = []
|
|
||||||
resetTransactionsPagination()
|
|
||||||
await fetchTransactionsPage(false)
|
|
||||||
initialized.value = true
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Transactions page initialization error:', error)
|
|
||||||
} finally {
|
|
||||||
initPromise = null
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
|
|
||||||
return initPromise
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetTransactionsPageData() {
|
export function resetTransactionsPageData() {
|
||||||
initialized.value = false
|
activeFetchId += 1
|
||||||
initPromise = null
|
loading.value = false
|
||||||
|
loadingMore.value = false
|
||||||
transactionsBoursecuMode.value = false
|
transactionsBoursecuMode.value = false
|
||||||
transactionPagination.value = { filters: [], limit: 7, page: 0 }
|
transactionPagination.value = { filters: [], limit: 7, page: 0 }
|
||||||
transactionItems.value = []
|
transactionItems.value = []
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz"
|
||||||
integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==
|
integrity sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==
|
||||||
|
|
||||||
"@babel/core@^7.11.1", "@babel/core@^7.22.10":
|
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.1", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.22.10", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0":
|
||||||
version "7.22.10"
|
version "7.22.10"
|
||||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz"
|
resolved "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz"
|
||||||
integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==
|
integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==
|
||||||
@@ -291,7 +291,7 @@
|
|||||||
"@babel/template" "^7.27.1"
|
"@babel/template" "^7.27.1"
|
||||||
"@babel/types" "^7.27.1"
|
"@babel/types" "^7.27.1"
|
||||||
|
|
||||||
"@babel/parser@^7.20.15", "@babel/parser@^7.21.3", "@babel/parser@^7.22.10", "@babel/parser@^7.25.3", "@babel/parser@^7.26.5", "@babel/parser@^7.27.2":
|
"@babel/parser@^7.15.8", "@babel/parser@^7.20.15", "@babel/parser@^7.21.3", "@babel/parser@^7.22.10", "@babel/parser@^7.25.3", "@babel/parser@^7.26.5", "@babel/parser@^7.27.2":
|
||||||
version "7.27.2"
|
version "7.27.2"
|
||||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz"
|
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz"
|
||||||
integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==
|
integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==
|
||||||
@@ -1006,114 +1006,9 @@
|
|||||||
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
|
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
|
||||||
integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
|
integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
|
||||||
|
|
||||||
"@esbuild/android-arm64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
|
|
||||||
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
|
|
||||||
|
|
||||||
"@esbuild/android-arm@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
|
|
||||||
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
|
|
||||||
|
|
||||||
"@esbuild/android-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
|
|
||||||
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
|
|
||||||
|
|
||||||
"@esbuild/darwin-arm64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
|
|
||||||
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
|
|
||||||
|
|
||||||
"@esbuild/darwin-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
|
|
||||||
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
|
|
||||||
|
|
||||||
"@esbuild/freebsd-arm64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
|
|
||||||
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
|
|
||||||
|
|
||||||
"@esbuild/freebsd-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
|
|
||||||
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
|
|
||||||
|
|
||||||
"@esbuild/linux-arm64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
|
|
||||||
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
|
|
||||||
|
|
||||||
"@esbuild/linux-arm@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
|
|
||||||
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
|
|
||||||
|
|
||||||
"@esbuild/linux-ia32@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
|
|
||||||
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
|
|
||||||
|
|
||||||
"@esbuild/linux-loong64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
|
|
||||||
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
|
|
||||||
|
|
||||||
"@esbuild/linux-mips64el@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
|
|
||||||
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
|
|
||||||
|
|
||||||
"@esbuild/linux-ppc64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
|
|
||||||
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
|
|
||||||
|
|
||||||
"@esbuild/linux-riscv64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
|
|
||||||
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
|
|
||||||
|
|
||||||
"@esbuild/linux-s390x@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
|
|
||||||
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
|
|
||||||
|
|
||||||
"@esbuild/linux-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338"
|
|
||||||
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
|
|
||||||
|
|
||||||
"@esbuild/netbsd-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
|
|
||||||
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
|
|
||||||
|
|
||||||
"@esbuild/openbsd-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
|
|
||||||
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
|
|
||||||
|
|
||||||
"@esbuild/sunos-x64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
|
|
||||||
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
|
|
||||||
|
|
||||||
"@esbuild/win32-arm64@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
|
|
||||||
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
|
|
||||||
|
|
||||||
"@esbuild/win32-ia32@0.18.20":
|
|
||||||
version "0.18.20"
|
|
||||||
resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
|
|
||||||
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
|
|
||||||
|
|
||||||
"@esbuild/win32-x64@0.18.20":
|
"@esbuild/win32-x64@0.18.20":
|
||||||
version "0.18.20"
|
version "0.18.20"
|
||||||
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
|
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz"
|
||||||
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
|
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
|
||||||
|
|
||||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||||
@@ -1244,7 +1139,7 @@
|
|||||||
"@nodelib/fs.stat" "2.0.5"
|
"@nodelib/fs.stat" "2.0.5"
|
||||||
run-parallel "^1.1.9"
|
run-parallel "^1.1.9"
|
||||||
|
|
||||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||||
@@ -1348,16 +1243,16 @@
|
|||||||
resolved "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.0.tgz"
|
resolved "https://registry.npmjs.org/@tsconfig/node18/-/node18-18.2.0.tgz"
|
||||||
integrity sha512-yhxwIlFVSVcMym3O31HoMnRXpoenmpIxcj4Yoes2DUpe+xCJnA7ECQP1Vw889V0jTt/2nzvpLQ/UuMYCd3JPIg==
|
integrity sha512-yhxwIlFVSVcMym3O31HoMnRXpoenmpIxcj4Yoes2DUpe+xCJnA7ECQP1Vw889V0jTt/2nzvpLQ/UuMYCd3JPIg==
|
||||||
|
|
||||||
"@types/estree@0.0.39":
|
|
||||||
version "0.0.39"
|
|
||||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz"
|
|
||||||
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
|
||||||
|
|
||||||
"@types/estree@^1.0.0":
|
"@types/estree@^1.0.0":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz"
|
||||||
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
||||||
|
|
||||||
|
"@types/estree@0.0.39":
|
||||||
|
version "0.0.39"
|
||||||
|
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz"
|
||||||
|
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
||||||
|
|
||||||
"@types/json-schema@^7.0.9":
|
"@types/json-schema@^7.0.9":
|
||||||
version "7.0.12"
|
version "7.0.12"
|
||||||
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz"
|
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz"
|
||||||
@@ -1368,7 +1263,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
|
resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz"
|
||||||
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
|
integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==
|
||||||
|
|
||||||
"@types/node@*", "@types/node@^18.17.0":
|
"@types/node@*", "@types/node@^18.17.0", "@types/node@>= 14":
|
||||||
version "18.17.5"
|
version "18.17.5"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz"
|
||||||
integrity sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==
|
integrity sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==
|
||||||
@@ -1411,7 +1306,7 @@
|
|||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^5.59.1":
|
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.59.1":
|
||||||
version "5.62.0"
|
version "5.62.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz"
|
||||||
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
|
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
|
||||||
@@ -1697,7 +1592,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.1.tgz"
|
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.1.tgz"
|
||||||
integrity sha512-tUBEtWcF7wFtII7ayNiLNDTCE1X1afySEo+XNVMNkFXaThENyCowIEX095QqbJZGTgoOcSVDJGlnde2NG4jtbQ==
|
integrity sha512-tUBEtWcF7wFtII7ayNiLNDTCE1X1afySEo+XNVMNkFXaThENyCowIEX095QqbJZGTgoOcSVDJGlnde2NG4jtbQ==
|
||||||
|
|
||||||
"@volar/language-core@2.4.11", "@volar/language-core@~2.4.11":
|
"@volar/language-core@~2.4.11", "@volar/language-core@2.4.11":
|
||||||
version "2.4.11"
|
version "2.4.11"
|
||||||
resolved "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz"
|
resolved "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz"
|
||||||
integrity sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==
|
integrity sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==
|
||||||
@@ -1759,14 +1654,6 @@
|
|||||||
estree-walker "^2.0.2"
|
estree-walker "^2.0.2"
|
||||||
source-map-js "^1.2.0"
|
source-map-js "^1.2.0"
|
||||||
|
|
||||||
"@vue/compiler-dom@3.3.4":
|
|
||||||
version "3.3.4"
|
|
||||||
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz"
|
|
||||||
integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==
|
|
||||||
dependencies:
|
|
||||||
"@vue/compiler-core" "3.3.4"
|
|
||||||
"@vue/shared" "3.3.4"
|
|
||||||
|
|
||||||
"@vue/compiler-dom@^3.5.0":
|
"@vue/compiler-dom@^3.5.0":
|
||||||
version "3.5.13"
|
version "3.5.13"
|
||||||
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz"
|
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz"
|
||||||
@@ -1775,6 +1662,14 @@
|
|||||||
"@vue/compiler-core" "3.5.13"
|
"@vue/compiler-core" "3.5.13"
|
||||||
"@vue/shared" "3.5.13"
|
"@vue/shared" "3.5.13"
|
||||||
|
|
||||||
|
"@vue/compiler-dom@3.3.4":
|
||||||
|
version "3.3.4"
|
||||||
|
resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz"
|
||||||
|
integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==
|
||||||
|
dependencies:
|
||||||
|
"@vue/compiler-core" "3.3.4"
|
||||||
|
"@vue/shared" "3.3.4"
|
||||||
|
|
||||||
"@vue/compiler-sfc@3.3.4":
|
"@vue/compiler-sfc@3.3.4":
|
||||||
version "3.3.4"
|
version "3.3.4"
|
||||||
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz"
|
resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz"
|
||||||
@@ -1886,12 +1781,12 @@
|
|||||||
"@vue/compiler-ssr" "3.3.4"
|
"@vue/compiler-ssr" "3.3.4"
|
||||||
"@vue/shared" "3.3.4"
|
"@vue/shared" "3.3.4"
|
||||||
|
|
||||||
"@vue/shared@3.3.4", "@vue/shared@^3.0.0":
|
"@vue/shared@^3.0.0", "@vue/shared@3.3.4":
|
||||||
version "3.3.4"
|
version "3.3.4"
|
||||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz"
|
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz"
|
||||||
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
|
integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==
|
||||||
|
|
||||||
"@vue/shared@3.5.13", "@vue/shared@^3.5.0":
|
"@vue/shared@^3.5.0", "@vue/shared@3.5.13":
|
||||||
version "3.5.13"
|
version "3.5.13"
|
||||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz"
|
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz"
|
||||||
integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
|
integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
|
||||||
@@ -1933,7 +1828,7 @@ acorn-jsx@^5.3.2:
|
|||||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
acorn@^8.8.2, acorn@^8.9.0:
|
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.8.2, acorn@^8.9.0:
|
||||||
version "8.10.0"
|
version "8.10.0"
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz"
|
||||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||||
@@ -1948,7 +1843,7 @@ ajv@^6.12.4:
|
|||||||
json-schema-traverse "^0.4.1"
|
json-schema-traverse "^0.4.1"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
ajv@^8.6.0:
|
ajv@^8.6.0, ajv@>=8:
|
||||||
version "8.12.0"
|
version "8.12.0"
|
||||||
resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz"
|
resolved "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz"
|
||||||
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
|
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
|
||||||
@@ -2013,7 +1908,7 @@ anymatch@~3.1.2:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
apexcharts@^3.44.0:
|
apexcharts@^3.44.0, "apexcharts@> 3.0.0":
|
||||||
version "3.44.0"
|
version "3.44.0"
|
||||||
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.44.0.tgz"
|
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.44.0.tgz"
|
||||||
integrity sha512-u7Xzrbcxc2yWznN78Jh5NMCYVAsWDfBjRl5ea++rVzFAqjU2hLz4RgKIFwYOBDRQtW1e/Qz8azJTqIJ1+Vu9Qg==
|
integrity sha512-u7Xzrbcxc2yWznN78Jh5NMCYVAsWDfBjRl5ea++rVzFAqjU2hLz4RgKIFwYOBDRQtW1e/Qz8azJTqIJ1+Vu9Qg==
|
||||||
@@ -2168,7 +2063,7 @@ braces@^3.0.3, braces@~3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.1.1"
|
fill-range "^7.1.1"
|
||||||
|
|
||||||
browserslist@^4.21.9, browserslist@^4.22.1:
|
browserslist@^4.21.9, browserslist@^4.22.1, "browserslist@>= 4.21.0":
|
||||||
version "4.22.1"
|
version "4.22.1"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz"
|
||||||
integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==
|
integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==
|
||||||
@@ -2232,7 +2127,7 @@ chalk@^2.4.1:
|
|||||||
escape-string-regexp "^1.0.5"
|
escape-string-regexp "^1.0.5"
|
||||||
supports-color "^5.3.0"
|
supports-color "^5.3.0"
|
||||||
|
|
||||||
chalk@^4.0.0, chalk@^4.0.2:
|
chalk@^4.0.0:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||||
@@ -2240,7 +2135,15 @@ chalk@^4.0.0, chalk@^4.0.2:
|
|||||||
ansi-styles "^4.1.0"
|
ansi-styles "^4.1.0"
|
||||||
supports-color "^7.1.0"
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3:
|
chalk@^4.0.2:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||||
|
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.1.0"
|
||||||
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
|
chokidar@^3.5.3, "chokidar@>=3.0.0 <4.0.0":
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
|
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz"
|
||||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||||
@@ -2269,16 +2172,16 @@ color-convert@^2.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
color-name "~1.1.4"
|
color-name "~1.1.4"
|
||||||
|
|
||||||
color-name@1.1.3:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
|
||||||
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
|
||||||
|
|
||||||
color-name@~1.1.4:
|
color-name@~1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
|
color-name@1.1.3:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
|
||||||
|
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
|
||||||
|
|
||||||
colorette@^2.0.20:
|
colorette@^2.0.20:
|
||||||
version "2.0.20"
|
version "2.0.20"
|
||||||
resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz"
|
resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz"
|
||||||
@@ -2666,7 +2569,7 @@ eslint-plugin-prettier@^5.0.0:
|
|||||||
prettier-linter-helpers "^1.0.0"
|
prettier-linter-helpers "^1.0.0"
|
||||||
synckit "^0.8.5"
|
synckit "^0.8.5"
|
||||||
|
|
||||||
eslint-plugin-vue@^9.15.1:
|
eslint-plugin-vue@^9.0.0, eslint-plugin-vue@^9.15.1:
|
||||||
version "9.17.0"
|
version "9.17.0"
|
||||||
resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz"
|
||||||
integrity sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==
|
integrity sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==
|
||||||
@@ -2687,7 +2590,15 @@ eslint-scope@^5.1.1:
|
|||||||
esrecurse "^4.3.0"
|
esrecurse "^4.3.0"
|
||||||
estraverse "^4.1.1"
|
estraverse "^4.1.1"
|
||||||
|
|
||||||
eslint-scope@^7.1.1, eslint-scope@^7.2.2:
|
eslint-scope@^7.1.1:
|
||||||
|
version "7.2.2"
|
||||||
|
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
|
||||||
|
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
|
||||||
|
dependencies:
|
||||||
|
esrecurse "^4.3.0"
|
||||||
|
estraverse "^5.2.0"
|
||||||
|
|
||||||
|
eslint-scope@^7.2.2:
|
||||||
version "7.2.2"
|
version "7.2.2"
|
||||||
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
|
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
|
||||||
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
|
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
|
||||||
@@ -2700,7 +2611,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
|||||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
|
|
||||||
eslint@^8.45.0:
|
eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^6.2.0 || ^7.0.0 || ^8.0.0", eslint@^8.45.0, "eslint@>= 8.0.0", eslint@>=6.0.0, eslint@>=7.0.0, eslint@>=8.0.0:
|
||||||
version "8.47.0"
|
version "8.47.0"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz"
|
||||||
integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==
|
integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==
|
||||||
@@ -2771,7 +2682,12 @@ estraverse@^4.1.1:
|
|||||||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
|
resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
|
||||||
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||||
|
|
||||||
estraverse@^5.1.0, estraverse@^5.2.0:
|
estraverse@^5.1.0:
|
||||||
|
version "5.3.0"
|
||||||
|
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
||||||
|
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
||||||
|
|
||||||
|
estraverse@^5.2.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
||||||
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
||||||
@@ -2796,7 +2712,22 @@ eventemitter3@^5.0.1:
|
|||||||
resolved "https://mirror-npm.runflare.com/eventemitter3/-/eventemitter3-5.0.4.tgz"
|
resolved "https://mirror-npm.runflare.com/eventemitter3/-/eventemitter3-5.0.4.tgz"
|
||||||
integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==
|
integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==
|
||||||
|
|
||||||
execa@^5.0.0, execa@^5.1.1:
|
execa@^5.0.0:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
|
||||||
|
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
|
||||||
|
dependencies:
|
||||||
|
cross-spawn "^7.0.3"
|
||||||
|
get-stream "^6.0.0"
|
||||||
|
human-signals "^2.1.0"
|
||||||
|
is-stream "^2.0.0"
|
||||||
|
merge-stream "^2.0.0"
|
||||||
|
npm-run-path "^4.0.1"
|
||||||
|
onetime "^5.1.2"
|
||||||
|
signal-exit "^3.0.3"
|
||||||
|
strip-final-newline "^2.0.0"
|
||||||
|
|
||||||
|
execa@^5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
|
resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz"
|
||||||
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
|
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
|
||||||
@@ -2942,11 +2873,6 @@ fs.realpath@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||||
|
|
||||||
fsevents@~2.3.2:
|
|
||||||
version "2.3.3"
|
|
||||||
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
|
||||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
|
||||||
|
|
||||||
function-bind@^1.1.1:
|
function-bind@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
|
||||||
@@ -3000,7 +2926,7 @@ get-symbol-description@^1.0.0:
|
|||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
get-intrinsic "^1.1.1"
|
get-intrinsic "^1.1.1"
|
||||||
|
|
||||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
glob-parent@^5.1.2:
|
||||||
version "5.1.2"
|
version "5.1.2"
|
||||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||||
@@ -3014,6 +2940,13 @@ glob-parent@^6.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
|
|
||||||
|
glob-parent@~5.1.2:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||||
|
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||||
|
dependencies:
|
||||||
|
is-glob "^4.0.1"
|
||||||
|
|
||||||
glob@^7.1.3, glob@^7.1.6:
|
glob@^7.1.3, glob@^7.1.6:
|
||||||
version "7.2.3"
|
version "7.2.3"
|
||||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||||
@@ -3525,7 +3458,7 @@ kolorist@^1.8.0:
|
|||||||
resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz"
|
resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz"
|
||||||
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
|
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
|
||||||
|
|
||||||
less@^4.2.0:
|
less@*, less@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz"
|
resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz"
|
||||||
integrity sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==
|
integrity sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==
|
||||||
@@ -3633,7 +3566,14 @@ lru-cache@^6.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
magic-string@^0.25.0, magic-string@^0.25.7:
|
magic-string@^0.25.0:
|
||||||
|
version "0.25.9"
|
||||||
|
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
|
||||||
|
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
||||||
|
dependencies:
|
||||||
|
sourcemap-codec "^1.4.8"
|
||||||
|
|
||||||
|
magic-string@^0.25.7:
|
||||||
version "0.25.9"
|
version "0.25.9"
|
||||||
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
|
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz"
|
||||||
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
|
||||||
@@ -3775,7 +3715,7 @@ mrmime@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz"
|
||||||
integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
|
integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==
|
||||||
|
|
||||||
ms@2.1.2, ms@^2.1.1:
|
ms@^2.1.1, ms@2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
@@ -3900,7 +3840,7 @@ object.assign@^4.1.4:
|
|||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
odometer@^0.4.8:
|
odometer@^0.4.8, odometer@latest:
|
||||||
version "0.4.8"
|
version "0.4.8"
|
||||||
resolved "https://registry.npmjs.org/odometer/-/odometer-0.4.8.tgz"
|
resolved "https://registry.npmjs.org/odometer/-/odometer-0.4.8.tgz"
|
||||||
integrity sha512-bfKuAhWE/qMCiX9bwX90c5bTpt7MDVeq1e6YsOHQrYokNhv9jhS5JbR9kg6i+FeWmDgalf3VUtwNx1aVaZ8cgg==
|
integrity sha512-bfKuAhWE/qMCiX9bwX90c5bTpt7MDVeq1e6YsOHQrYokNhv9jhS5JbR9kg6i+FeWmDgalf3VUtwNx1aVaZ8cgg==
|
||||||
@@ -4124,7 +4064,7 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^3.0.0:
|
prettier@^3.0.0, "prettier@>= 3.0.0", prettier@>=3.0.0:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz"
|
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz"
|
||||||
integrity sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==
|
integrity sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==
|
||||||
@@ -4294,14 +4234,14 @@ rollup-plugin-terser@^7.0.0:
|
|||||||
serialize-javascript "^4.0.0"
|
serialize-javascript "^4.0.0"
|
||||||
terser "^5.0.0"
|
terser "^5.0.0"
|
||||||
|
|
||||||
rollup@^2.43.1:
|
"rollup@^1.20.0 || ^2.0.0", rollup@^1.20.0||^2.0.0, rollup@^2.0.0, rollup@^2.43.1:
|
||||||
version "2.79.2"
|
version "2.79.2"
|
||||||
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
|
resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz"
|
||||||
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
|
integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
rollup@^3.27.1:
|
rollup@^1.20.0||^2.0.0||^3.0.0, rollup@^3.27.1:
|
||||||
version "3.29.5"
|
version "3.29.5"
|
||||||
resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz"
|
resolved "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz"
|
||||||
integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==
|
integrity sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==
|
||||||
@@ -4351,7 +4291,7 @@ safe-regex-test@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
sass@^1.69.4:
|
sass@*, sass@^1.69.4:
|
||||||
version "1.69.5"
|
version "1.69.5"
|
||||||
resolved "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz"
|
resolved "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz"
|
||||||
integrity sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==
|
integrity sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==
|
||||||
@@ -4372,7 +4312,12 @@ scroll-into-view-if-needed@^2.2.25:
|
|||||||
dependencies:
|
dependencies:
|
||||||
compute-scroll-into-view "^1.0.20"
|
compute-scroll-into-view "^1.0.20"
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0:
|
semver@^5.5.0:
|
||||||
|
version "5.7.2"
|
||||||
|
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
||||||
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
|
|
||||||
|
semver@^5.6.0:
|
||||||
version "5.7.2"
|
version "5.7.2"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
||||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
@@ -4382,13 +4327,32 @@ semver@^6.3.1:
|
|||||||
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.3.6, semver@^7.3.7, semver@^7.5.4:
|
semver@^7.3.6:
|
||||||
version "7.5.4"
|
version "7.5.4"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
|
||||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^6.0.0"
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
|
semver@^7.3.7:
|
||||||
|
version "7.5.4"
|
||||||
|
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
|
||||||
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
|
semver@^7.5.4:
|
||||||
|
version "7.5.4"
|
||||||
|
resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz"
|
||||||
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
|
dependencies:
|
||||||
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
|
"semver@2 || 3 || 4 || 5":
|
||||||
|
version "5.7.2"
|
||||||
|
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
||||||
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
|
|
||||||
serialize-javascript@^4.0.0:
|
serialize-javascript@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz"
|
||||||
@@ -4467,7 +4431,7 @@ slash@^3.0.0:
|
|||||||
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
|
||||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||||
|
|
||||||
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1:
|
source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1, "source-map-js@>=0.6.2 <2.0.0":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
||||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||||
@@ -4622,7 +4586,14 @@ supports-color@^5.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^3.0.0"
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
supports-color@^7.0.0, supports-color@^7.1.0:
|
supports-color@^7.0.0:
|
||||||
|
version "7.2.0"
|
||||||
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
||||||
|
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
|
supports-color@^7.1.0:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
||||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||||
@@ -4660,7 +4631,7 @@ svg.filter.js@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
svg.js "^2.2.5"
|
svg.js "^2.2.5"
|
||||||
|
|
||||||
svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5:
|
svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5, svg.js@>=2.3.x:
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz"
|
resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz"
|
||||||
integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
|
integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
|
||||||
@@ -4722,7 +4693,7 @@ tempy@^0.6.0:
|
|||||||
type-fest "^0.16.0"
|
type-fest "^0.16.0"
|
||||||
unique-string "^2.0.0"
|
unique-string "^2.0.0"
|
||||||
|
|
||||||
terser@^5.0.0:
|
terser@^5.0.0, terser@^5.4.0:
|
||||||
version "5.24.0"
|
version "5.24.0"
|
||||||
resolved "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz"
|
resolved "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz"
|
||||||
integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==
|
integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==
|
||||||
@@ -4761,11 +4732,6 @@ tr46@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
tslib@2.3.0:
|
|
||||||
version "2.3.0"
|
|
||||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz"
|
|
||||||
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
|
|
||||||
|
|
||||||
tslib@^1.8.1:
|
tslib@^1.8.1:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
||||||
@@ -4776,6 +4742,11 @@ tslib@^2.3.0, tslib@^2.5.0, tslib@^2.6.0:
|
|||||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz"
|
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz"
|
||||||
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==
|
||||||
|
|
||||||
|
tslib@2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz"
|
||||||
|
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
|
||||||
|
|
||||||
tsutils@^3.21.0:
|
tsutils@^3.21.0:
|
||||||
version "3.21.0"
|
version "3.21.0"
|
||||||
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
|
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
|
||||||
@@ -4839,7 +4810,7 @@ typed-array-length@^1.0.4:
|
|||||||
for-each "^0.3.3"
|
for-each "^0.3.3"
|
||||||
is-typed-array "^1.1.9"
|
is-typed-array "^1.1.9"
|
||||||
|
|
||||||
typescript@~5.1.6:
|
typescript@*, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@>=4.4.4, typescript@>=5.0.0, typescript@~5.1.6:
|
||||||
version "5.1.6"
|
version "5.1.6"
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz"
|
||||||
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
||||||
@@ -5014,7 +4985,7 @@ vite-plugin-pwa@^0.16.7:
|
|||||||
workbox-build "^7.0.0"
|
workbox-build "^7.0.0"
|
||||||
workbox-window "^7.0.0"
|
workbox-window "^7.0.0"
|
||||||
|
|
||||||
vite@^4.4.6:
|
"vite@^2.9.0 || ^3.0.0-0 || ^4.0.0", "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0", vite@^4.0.0, vite@^4.4.6:
|
||||||
version "4.5.14"
|
version "4.5.14"
|
||||||
resolved "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz"
|
resolved "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz"
|
||||||
integrity sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==
|
integrity sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==
|
||||||
@@ -5035,6 +5006,11 @@ vue-content-loader@^2.0.1:
|
|||||||
resolved "https://registry.npmjs.org/vue-content-loader/-/vue-content-loader-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/vue-content-loader/-/vue-content-loader-2.0.1.tgz"
|
||||||
integrity sha512-pkof4+q2xmzNEdhqelxtJejeP/vQUJtLle4/v2ueG+HURqM9Q/GIGC8GJ2bVVWeLfTDET51jqimwQdmxJTlu0g==
|
integrity sha512-pkof4+q2xmzNEdhqelxtJejeP/vQUJtLle4/v2ueG+HURqM9Q/GIGC8GJ2bVVWeLfTDET51jqimwQdmxJTlu0g==
|
||||||
|
|
||||||
|
vue-demi@^0.12.5:
|
||||||
|
version "0.12.5"
|
||||||
|
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz"
|
||||||
|
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
|
||||||
|
|
||||||
vue-demi@>=0.14.5:
|
vue-demi@>=0.14.5:
|
||||||
version "0.14.5"
|
version "0.14.5"
|
||||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz"
|
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz"
|
||||||
@@ -5045,11 +5021,6 @@ vue-demi@>=0.14.6:
|
|||||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz"
|
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz"
|
||||||
integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==
|
integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==
|
||||||
|
|
||||||
vue-demi@^0.12.5:
|
|
||||||
version "0.12.5"
|
|
||||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.5.tgz"
|
|
||||||
integrity sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==
|
|
||||||
|
|
||||||
vue-eslint-parser@^9.1.1, vue-eslint-parser@^9.3.1:
|
vue-eslint-parser@^9.1.1, vue-eslint-parser@^9.3.1:
|
||||||
version "9.3.1"
|
version "9.3.1"
|
||||||
resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz"
|
resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz"
|
||||||
@@ -5097,6 +5068,17 @@ vue-types@^3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-plain-object "3.0.1"
|
is-plain-object "3.0.1"
|
||||||
|
|
||||||
|
"vue@^2.0.0 || >=3.0.0", "vue@^2.6.14 || ^3.3.0", vue@^3, vue@^3.0.*, vue@^3.0.0, "vue@^3.0.0-0 || ^2.6.0", vue@^3.2.0, vue@^3.2.25, vue@^3.3.4, "vue@> 3.0.0", "vue@>= 2.0.0", vue@>=3.0.3, vue@>=3.2.0, "vue@2 || 3", vue@3.3.4, vue@latest:
|
||||||
|
version "3.3.4"
|
||||||
|
resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
|
||||||
|
integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
|
||||||
|
dependencies:
|
||||||
|
"@vue/compiler-dom" "3.3.4"
|
||||||
|
"@vue/compiler-sfc" "3.3.4"
|
||||||
|
"@vue/runtime-dom" "3.3.4"
|
||||||
|
"@vue/server-renderer" "3.3.4"
|
||||||
|
"@vue/shared" "3.3.4"
|
||||||
|
|
||||||
vue3-apexcharts@^1.4.4:
|
vue3-apexcharts@^1.4.4:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.4.4.tgz"
|
resolved "https://registry.npmjs.org/vue3-apexcharts/-/vue3-apexcharts-1.4.4.tgz"
|
||||||
@@ -5122,17 +5104,6 @@ vue3-otp-input@^0.4.1:
|
|||||||
resolved "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.4.1.tgz"
|
resolved "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.4.1.tgz"
|
||||||
integrity sha512-wVl9i3DcWlO0C7fBI9V+RIP3crm/1tY72fuhvb3YM2JfbLoYofB96aPl5AgFhA0Cse5bQEMYtIvOeiqW3rfbAw==
|
integrity sha512-wVl9i3DcWlO0C7fBI9V+RIP3crm/1tY72fuhvb3YM2JfbLoYofB96aPl5AgFhA0Cse5bQEMYtIvOeiqW3rfbAw==
|
||||||
|
|
||||||
vue@^3.2.25, vue@^3.3.4:
|
|
||||||
version "3.3.4"
|
|
||||||
resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz"
|
|
||||||
integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==
|
|
||||||
dependencies:
|
|
||||||
"@vue/compiler-dom" "3.3.4"
|
|
||||||
"@vue/compiler-sfc" "3.3.4"
|
|
||||||
"@vue/runtime-dom" "3.3.4"
|
|
||||||
"@vue/server-renderer" "3.3.4"
|
|
||||||
"@vue/shared" "3.3.4"
|
|
||||||
|
|
||||||
warning@^4.0.0:
|
warning@^4.0.0:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
|
resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz"
|
||||||
@@ -5350,7 +5321,7 @@ workbox-sw@7.0.0:
|
|||||||
resolved "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz"
|
resolved "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz"
|
||||||
integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==
|
integrity sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==
|
||||||
|
|
||||||
workbox-window@7.0.0, workbox-window@^7.0.0:
|
workbox-window@^7.0.0, workbox-window@7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz"
|
resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz"
|
||||||
integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==
|
integrity sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==
|
||||||
|
|||||||
Reference in New Issue
Block a user