mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-20 17:54:30 +08:00
migrate services.js to ts
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getMobileUrlQrCodePath } from '@/lib/qrcode.js';
|
import { getMobileUrlQrCodePath } from '@/lib/qrcode.ts';
|
||||||
import { getMobileVersionPath } from '@/lib/version.ts';
|
import { getMobileVersionPath } from '@/lib/version.ts';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ export interface TimeRange {
|
|||||||
readonly maxTime: number;
|
readonly maxTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StartEndTime {
|
||||||
|
readonly startTime: number;
|
||||||
|
readonly endTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface UnixTimeRange {
|
export interface UnixTimeRange {
|
||||||
readonly minUnixTime: number;
|
readonly minUnixTime: number;
|
||||||
readonly maxUnixTime: number;
|
readonly maxUnixTime: number;
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ import {
|
|||||||
} from './account.js';
|
} from './account.js';
|
||||||
|
|
||||||
import logger from './logger.ts';
|
import logger from './logger.ts';
|
||||||
import services from './services.js';
|
import services from './services.ts';
|
||||||
|
|
||||||
function getLanguageDisplayName(translateFn, languageName) {
|
function getLanguageDisplayName(translateFn, languageName) {
|
||||||
return translateFn(`language.${languageName}`);
|
return translateFn(`language.${languageName}`);
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
||||||
|
|
||||||
import { asyncLoadAssets } from '@/lib/misc.ts';
|
import { asyncLoadAssets } from '@/lib/misc.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import {
|
import {
|
||||||
getAmapSecurityVerificationMethod,
|
getAmapSecurityVerificationMethod,
|
||||||
getAmapApiExternalProxyUrl,
|
getAmapApiExternalProxyUrl,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
||||||
|
|
||||||
import { asyncLoadAssets } from '@/lib/misc.ts';
|
import { asyncLoadAssets } from '@/lib/misc.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
|
|
||||||
export class BaiduMapProvider implements MapProvider {
|
export class BaiduMapProvider implements MapProvider {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
import type { MapProvider, MapInstance, MapInstanceInitOptions, MapPosition } from './base.ts';
|
||||||
|
|
||||||
import { asyncLoadAssets } from '@/lib/misc.ts';
|
import { asyncLoadAssets } from '@/lib/misc.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
|
|
||||||
export class GoogleMapProvider implements MapProvider {
|
export class GoogleMapProvider implements MapProvider {
|
||||||
public static GoogleMap: unknown = null;
|
public static GoogleMap: unknown = null;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
getTomTomMapAPIKey,
|
getTomTomMapAPIKey,
|
||||||
getTianDiTuMapAPIKey
|
getTianDiTuMapAPIKey
|
||||||
} from '@/lib/server_settings.ts';
|
} from '@/lib/server_settings.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
|
|
||||||
export class LeafletMapProvider implements MapProvider {
|
export class LeafletMapProvider implements MapProvider {
|
||||||
public static Leaflet: unknown = null;
|
public static Leaflet: unknown = null;
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import services from './services.js';
|
|
||||||
|
|
||||||
export function getMobileUrlQrCodePath() {
|
|
||||||
return services.generateQrCodeUrl('mobile_url');
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import services from './services.ts';
|
||||||
|
|
||||||
|
export function getMobileUrlQrCodePath(): string {
|
||||||
|
return services.generateQrCodeUrl('mobile_url');
|
||||||
|
}
|
||||||
@@ -1,741 +0,0 @@
|
|||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BASE_API_URL_PATH,
|
|
||||||
BASE_QRCODE_PATH,
|
|
||||||
BASE_PROXY_URL_PATH,
|
|
||||||
BASE_AMAP_API_PROXY_URL_PATH,
|
|
||||||
DEFAULT_API_TIMEOUT,
|
|
||||||
DEFAULT_UPLOAD_API_TIMEOUT,
|
|
||||||
DEFAULT_IMPORT_API_TIMEOUT,
|
|
||||||
GOOGLE_MAP_JAVASCRIPT_URL,
|
|
||||||
BAIDU_MAP_JAVASCRIPT_URL,
|
|
||||||
AMAP_JAVASCRIPT_URL
|
|
||||||
} from '@/consts/api.ts';
|
|
||||||
import userState from './userstate.ts';
|
|
||||||
import {
|
|
||||||
isDefined,
|
|
||||||
isBoolean
|
|
||||||
} from './common.ts';
|
|
||||||
import {
|
|
||||||
getGoogleMapAPIKey,
|
|
||||||
getBaiduMapAK,
|
|
||||||
getAmapApplicationKey,
|
|
||||||
getExchangeRatesRequestTimeout
|
|
||||||
} from './server_settings.ts';
|
|
||||||
import { getTimezoneOffsetMinutes } from './datetime.ts';
|
|
||||||
import { generateRandomUUID } from './misc.ts';
|
|
||||||
|
|
||||||
let needBlockRequest = false;
|
|
||||||
let blockedRequests = [];
|
|
||||||
|
|
||||||
axios.defaults.baseURL = BASE_API_URL_PATH;
|
|
||||||
axios.defaults.timeout = DEFAULT_API_TIMEOUT;
|
|
||||||
axios.interceptors.request.use(config => {
|
|
||||||
const token = userState.getToken();
|
|
||||||
|
|
||||||
if (token && !config.noAuth) {
|
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
config.headers['X-Timezone-Offset'] = getTimezoneOffsetMinutes();
|
|
||||||
|
|
||||||
if (needBlockRequest && !config.ignoreBlocked) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
blockedRequests.push(newToken => {
|
|
||||||
if (newToken) {
|
|
||||||
config.headers.Authorization = `Bearer ${newToken}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(config);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
}, error => {
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
axios.interceptors.response.use(response => {
|
|
||||||
return response;
|
|
||||||
}, error => {
|
|
||||||
if (error.response && !error.response.config.ignoreError && error.response.data && error.response.data.errorCode) {
|
|
||||||
const errorCode = error.response.data.errorCode;
|
|
||||||
|
|
||||||
if (errorCode === 202001 // unauthorized access
|
|
||||||
|| errorCode === 202002 // current token is invalid
|
|
||||||
|| errorCode === 202003 // current token is expired
|
|
||||||
|| errorCode === 202004 // current token type is invalid
|
|
||||||
|| errorCode === 202005 // current token requires two-factor authorization
|
|
||||||
|| errorCode === 202006 // current token does not require two-factor authorization
|
|
||||||
|| errorCode === 202012 // token is empty
|
|
||||||
) {
|
|
||||||
userState.clearTokenAndUserInfo(false);
|
|
||||||
location.reload();
|
|
||||||
return Promise.reject({ processed: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default {
|
|
||||||
setLocale: locale => {
|
|
||||||
axios.defaults.headers.common['Accept-Language'] = locale;
|
|
||||||
},
|
|
||||||
authorize: ({ loginName, password }) => {
|
|
||||||
return axios.post('authorize.json', {
|
|
||||||
loginName,
|
|
||||||
password
|
|
||||||
});
|
|
||||||
},
|
|
||||||
authorize2FA: ({ passcode, token }) => {
|
|
||||||
return axios.post('2fa/authorize.json', {
|
|
||||||
passcode
|
|
||||||
}, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
authorize2FAByBackupCode: ({ recoveryCode, token }) => {
|
|
||||||
return axios.post('2fa/recovery.json', {
|
|
||||||
recoveryCode
|
|
||||||
}, {
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
register: ({ username, email, nickname, password, language, defaultCurrency, firstDayOfWeek, categories }) => {
|
|
||||||
return axios.post('register.json', {
|
|
||||||
username,
|
|
||||||
email,
|
|
||||||
nickname,
|
|
||||||
password,
|
|
||||||
language,
|
|
||||||
defaultCurrency,
|
|
||||||
firstDayOfWeek,
|
|
||||||
categories
|
|
||||||
});
|
|
||||||
},
|
|
||||||
verifyEmail: ({ token, requestNewToken }) => {
|
|
||||||
return axios.post('verify_email/by_token.json?token=' + token, {
|
|
||||||
requestNewToken
|
|
||||||
}, {
|
|
||||||
noAuth: true,
|
|
||||||
ignoreError: true
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resendVerifyEmailByUnloginUser: ({ email, password }) => {
|
|
||||||
return axios.post('verify_email/resend.json', {
|
|
||||||
email,
|
|
||||||
password
|
|
||||||
});
|
|
||||||
},
|
|
||||||
requestResetPassword: ({ email }) => {
|
|
||||||
return axios.post('forget_password/request.json', {
|
|
||||||
email
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetPassword: ({ email, token, password }) => {
|
|
||||||
return axios.post('forget_password/reset/by_token.json?token=' + token, {
|
|
||||||
email,
|
|
||||||
password
|
|
||||||
}, {
|
|
||||||
noAuth: true,
|
|
||||||
ignoreError: true
|
|
||||||
});
|
|
||||||
},
|
|
||||||
logout: () => {
|
|
||||||
return axios.get('logout.json');
|
|
||||||
},
|
|
||||||
refreshToken: () => {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
needBlockRequest = true;
|
|
||||||
|
|
||||||
axios.post('v1/tokens/refresh.json', {}, {
|
|
||||||
ignoreBlocked: true
|
|
||||||
}).then(response => {
|
|
||||||
const data = response.data;
|
|
||||||
|
|
||||||
resolve(response);
|
|
||||||
needBlockRequest = false;
|
|
||||||
|
|
||||||
return data.result.newToken;
|
|
||||||
}).then(newToken => {
|
|
||||||
blockedRequests.forEach(func => func(newToken));
|
|
||||||
blockedRequests.length = 0;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTokens: () => {
|
|
||||||
return axios.get('v1/tokens/list.json');
|
|
||||||
},
|
|
||||||
revokeToken: ({ tokenId, ignoreError }) => {
|
|
||||||
return axios.post('v1/tokens/revoke.json', {
|
|
||||||
tokenId
|
|
||||||
}, {
|
|
||||||
ignoreError: !!ignoreError
|
|
||||||
});
|
|
||||||
},
|
|
||||||
revokeAllTokens: () => {
|
|
||||||
return axios.post('v1/tokens/revoke_all.json');
|
|
||||||
},
|
|
||||||
getProfile: () => {
|
|
||||||
return axios.get('v1/users/profile/get.json');
|
|
||||||
},
|
|
||||||
updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat, decimalSeparator, digitGroupingSymbol, digitGrouping, currencyDisplayType, expenseAmountColor, incomeAmountColor }) => {
|
|
||||||
return axios.post('v1/users/profile/update.json', {
|
|
||||||
email,
|
|
||||||
nickname,
|
|
||||||
password,
|
|
||||||
oldPassword,
|
|
||||||
defaultAccountId,
|
|
||||||
transactionEditScope,
|
|
||||||
language,
|
|
||||||
defaultCurrency,
|
|
||||||
firstDayOfWeek,
|
|
||||||
longDateFormat,
|
|
||||||
shortDateFormat,
|
|
||||||
longTimeFormat,
|
|
||||||
shortTimeFormat,
|
|
||||||
decimalSeparator,
|
|
||||||
digitGroupingSymbol,
|
|
||||||
digitGrouping,
|
|
||||||
currencyDisplayType,
|
|
||||||
expenseAmountColor,
|
|
||||||
incomeAmountColor
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateAvatar: ({ avatarFile }) => {
|
|
||||||
return axios.postForm('v1/users/avatar/update.json', {
|
|
||||||
avatar: avatarFile
|
|
||||||
}, {
|
|
||||||
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
|
||||||
});
|
|
||||||
},
|
|
||||||
removeAvatar: () => {
|
|
||||||
return axios.post('v1/users/avatar/remove.json');
|
|
||||||
},
|
|
||||||
resendVerifyEmailByLoginedUser: () => {
|
|
||||||
return axios.post('v1/users/verify_email/resend.json');
|
|
||||||
},
|
|
||||||
get2FAStatus: () => {
|
|
||||||
return axios.get('v1/users/2fa/status.json');
|
|
||||||
},
|
|
||||||
enable2FA: () => {
|
|
||||||
return axios.post('v1/users/2fa/enable/request.json');
|
|
||||||
},
|
|
||||||
confirmEnable2FA: ({ secret, passcode }) => {
|
|
||||||
return axios.post('v1/users/2fa/enable/confirm.json', {
|
|
||||||
secret,
|
|
||||||
passcode
|
|
||||||
});
|
|
||||||
},
|
|
||||||
disable2FA: ({ password }) => {
|
|
||||||
return axios.post('v1/users/2fa/disable.json', {
|
|
||||||
password
|
|
||||||
});
|
|
||||||
},
|
|
||||||
regenerate2FARecoveryCode: ({ password }) => {
|
|
||||||
return axios.post('v1/users/2fa/recovery/regenerate.json', {
|
|
||||||
password
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getUserDataStatistics: () => {
|
|
||||||
return axios.get('v1/data/statistics.json');
|
|
||||||
},
|
|
||||||
getExportedUserData: (fileType) => {
|
|
||||||
if (fileType === 'csv') {
|
|
||||||
return axios.get('v1/data/export.csv');
|
|
||||||
} else if (fileType === 'tsv') {
|
|
||||||
return axios.get('v1/data/export.tsv');
|
|
||||||
} else {
|
|
||||||
return Promise.reject('Parameter Invalid');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearData: ({ password }) => {
|
|
||||||
return axios.post('v1/data/clear.json', {
|
|
||||||
password
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getAllAccounts: ({ visibleOnly }) => {
|
|
||||||
return axios.get('v1/accounts/list.json?visible_only=' + !!visibleOnly);
|
|
||||||
},
|
|
||||||
getAccount: ({ id }) => {
|
|
||||||
return axios.get('v1/accounts/get.json?id=' + id);
|
|
||||||
},
|
|
||||||
addAccount: ({ category, type, name, icon, color, currency, balance, balanceTime, comment, creditCardStatementDate, subAccounts, clientSessionId }) => {
|
|
||||||
return axios.post('v1/accounts/add.json', {
|
|
||||||
category,
|
|
||||||
type,
|
|
||||||
name,
|
|
||||||
icon,
|
|
||||||
color,
|
|
||||||
currency,
|
|
||||||
balance,
|
|
||||||
balanceTime,
|
|
||||||
comment,
|
|
||||||
creditCardStatementDate,
|
|
||||||
subAccounts,
|
|
||||||
clientSessionId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
modifyAccount: ({ id, category, name, icon, color, comment, creditCardStatementDate, hidden, subAccounts }) => {
|
|
||||||
return axios.post('v1/accounts/modify.json', {
|
|
||||||
id,
|
|
||||||
category,
|
|
||||||
name,
|
|
||||||
icon,
|
|
||||||
color,
|
|
||||||
comment,
|
|
||||||
creditCardStatementDate,
|
|
||||||
hidden,
|
|
||||||
subAccounts
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hideAccount: ({ id, hidden }) => {
|
|
||||||
return axios.post('v1/accounts/hide.json', {
|
|
||||||
id,
|
|
||||||
hidden
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moveAccount: ({ newDisplayOrders }) => {
|
|
||||||
return axios.post('v1/accounts/move.json', {
|
|
||||||
newDisplayOrders,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteAccount: ({ id }) => {
|
|
||||||
return axios.post('v1/accounts/delete.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTransactions: ({ maxTime, minTime, count, page, withCount, type, categoryIds, accountIds, tagIds, tagFilterType, amountFilter, keyword }) => {
|
|
||||||
amountFilter = encodeURIComponent(amountFilter);
|
|
||||||
keyword = encodeURIComponent(keyword);
|
|
||||||
return axios.get(`v1/transactions/list.json?max_time=${maxTime}&min_time=${minTime}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&tag_filter_type=${tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&count=${count}&page=${page}&with_count=${withCount}&trim_account=true&trim_category=true&trim_tag=true`);
|
|
||||||
},
|
|
||||||
getAllTransactionsByMonth: ({ year, month, type, categoryIds, accountIds, tagIds, tagFilterType, amountFilter, keyword }) => {
|
|
||||||
amountFilter = encodeURIComponent(amountFilter);
|
|
||||||
keyword = encodeURIComponent(keyword);
|
|
||||||
return axios.get(`v1/transactions/list/by_month.json?year=${year}&month=${month}&type=${type}&category_ids=${categoryIds}&account_ids=${accountIds}&tag_ids=${tagIds}&tag_filter_type=${tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&trim_account=true&trim_category=true&trim_tag=true`);
|
|
||||||
},
|
|
||||||
getTransactionStatistics: ({ startTime, endTime, useTransactionTimezone, tagIds, tagFilterType }) => {
|
|
||||||
const queryParams = [];
|
|
||||||
|
|
||||||
if (startTime) {
|
|
||||||
queryParams.push(`start_time=${startTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endTime) {
|
|
||||||
queryParams.push(`end_time=${endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagIds) {
|
|
||||||
queryParams.push(`tag_ids=${tagIds}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagFilterType) {
|
|
||||||
queryParams.push(`tag_filter_type=${tagFilterType}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return axios.get(`v1/transactions/statistics.json?use_transaction_timezone=${useTransactionTimezone}` + (queryParams.length ? '&' + queryParams.join('&') : ''));
|
|
||||||
},
|
|
||||||
getTransactionStatisticsTrends: ({ startYearMonth, endYearMonth, useTransactionTimezone, tagIds, tagFilterType }) => {
|
|
||||||
const queryParams = [];
|
|
||||||
|
|
||||||
if (startYearMonth) {
|
|
||||||
queryParams.push(`start_year_month=${startYearMonth}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endYearMonth) {
|
|
||||||
queryParams.push(`end_year_month=${endYearMonth}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagIds) {
|
|
||||||
queryParams.push(`tag_ids=${tagIds}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagFilterType) {
|
|
||||||
queryParams.push(`tag_filter_type=${tagFilterType}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return axios.get(`v1/transactions/statistics/trends.json?use_transaction_timezone=${useTransactionTimezone}` + (queryParams.length ? '&' + queryParams.join('&') : ''));
|
|
||||||
},
|
|
||||||
getTransactionAmounts: ({ useTransactionTimezone, today, thisWeek, thisMonth, thisYear, lastMonth, monthBeforeLastMonth, monthBeforeLast2Months, monthBeforeLast3Months, monthBeforeLast4Months, monthBeforeLast5Months, monthBeforeLast6Months, monthBeforeLast7Months, monthBeforeLast8Months, monthBeforeLast9Months, monthBeforeLast10Months }) => {
|
|
||||||
const queryParams = [];
|
|
||||||
|
|
||||||
if (today) {
|
|
||||||
queryParams.push(`today_${today.startTime}_${today.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisWeek) {
|
|
||||||
queryParams.push(`thisWeek_${thisWeek.startTime}_${thisWeek.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisMonth) {
|
|
||||||
queryParams.push(`thisMonth_${thisMonth.startTime}_${thisMonth.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thisYear) {
|
|
||||||
queryParams.push(`thisYear_${thisYear.startTime}_${thisYear.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastMonth) {
|
|
||||||
queryParams.push(`lastMonth_${lastMonth.startTime}_${lastMonth.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLastMonth) {
|
|
||||||
queryParams.push(`monthBeforeLastMonth_${monthBeforeLastMonth.startTime}_${monthBeforeLastMonth.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast2Months) {
|
|
||||||
queryParams.push(`monthBeforeLast2Months_${monthBeforeLast2Months.startTime}_${monthBeforeLast2Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast3Months) {
|
|
||||||
queryParams.push(`monthBeforeLast3Months_${monthBeforeLast3Months.startTime}_${monthBeforeLast3Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast4Months) {
|
|
||||||
queryParams.push(`monthBeforeLast4Months_${monthBeforeLast4Months.startTime}_${monthBeforeLast4Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast5Months) {
|
|
||||||
queryParams.push(`monthBeforeLast5Months_${monthBeforeLast5Months.startTime}_${monthBeforeLast5Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast6Months) {
|
|
||||||
queryParams.push(`monthBeforeLast6Months_${monthBeforeLast6Months.startTime}_${monthBeforeLast6Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast7Months) {
|
|
||||||
queryParams.push(`monthBeforeLast7Months_${monthBeforeLast7Months.startTime}_${monthBeforeLast7Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast8Months) {
|
|
||||||
queryParams.push(`monthBeforeLast8Months_${monthBeforeLast8Months.startTime}_${monthBeforeLast8Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast9Months) {
|
|
||||||
queryParams.push(`monthBeforeLast9Months_${monthBeforeLast9Months.startTime}_${monthBeforeLast9Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monthBeforeLast10Months) {
|
|
||||||
queryParams.push(`monthBeforeLast10Months_${monthBeforeLast10Months.startTime}_${monthBeforeLast10Months.endTime}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return axios.get(`v1/transactions/amounts.json?use_transaction_timezone=${useTransactionTimezone}` + (queryParams.length ? '&query=' + queryParams.join('|') : ''));
|
|
||||||
},
|
|
||||||
getTransaction: ({ id, withPictures }) => {
|
|
||||||
if (!isDefined(withPictures)) {
|
|
||||||
withPictures = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return axios.get(`v1/transactions/get.json?id=${id}&with_pictures=${withPictures}&trim_account=true&trim_category=true&trim_tag=true`);
|
|
||||||
},
|
|
||||||
addTransaction: ({ type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, pictureIds, comment, geoLocation, utcOffset, clientSessionId }) => {
|
|
||||||
return axios.post('v1/transactions/add.json', {
|
|
||||||
type,
|
|
||||||
categoryId,
|
|
||||||
time,
|
|
||||||
sourceAccountId,
|
|
||||||
destinationAccountId,
|
|
||||||
sourceAmount,
|
|
||||||
destinationAmount,
|
|
||||||
hideAmount,
|
|
||||||
tagIds,
|
|
||||||
pictureIds,
|
|
||||||
comment,
|
|
||||||
geoLocation,
|
|
||||||
utcOffset,
|
|
||||||
clientSessionId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
modifyTransaction: ({ id, type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, pictureIds, comment, geoLocation, utcOffset }) => {
|
|
||||||
return axios.post('v1/transactions/modify.json', {
|
|
||||||
id,
|
|
||||||
type,
|
|
||||||
categoryId,
|
|
||||||
time,
|
|
||||||
sourceAccountId,
|
|
||||||
destinationAccountId,
|
|
||||||
sourceAmount,
|
|
||||||
destinationAmount,
|
|
||||||
hideAmount,
|
|
||||||
tagIds,
|
|
||||||
pictureIds,
|
|
||||||
comment,
|
|
||||||
geoLocation,
|
|
||||||
utcOffset
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteTransaction: ({ id }) => {
|
|
||||||
return axios.post('v1/transactions/delete.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
parseImportTransaction: ({ fileType, importFile }) => {
|
|
||||||
return axios.postForm('v1/transactions/parse_import.json', {
|
|
||||||
fileType: fileType,
|
|
||||||
file: importFile
|
|
||||||
}, {
|
|
||||||
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
|
||||||
});
|
|
||||||
},
|
|
||||||
importTransactions: ({ transactions, clientSessionId }) => {
|
|
||||||
return axios.post('v1/transactions/import.json', {
|
|
||||||
transactions: transactions,
|
|
||||||
clientSessionId: clientSessionId
|
|
||||||
}, {
|
|
||||||
timeout: DEFAULT_IMPORT_API_TIMEOUT
|
|
||||||
});
|
|
||||||
},
|
|
||||||
uploadTransactionPicture: ({ pictureFile, clientSessionId }) => {
|
|
||||||
return axios.postForm('v1/transaction/pictures/upload.json', {
|
|
||||||
picture: pictureFile,
|
|
||||||
clientSessionId: clientSessionId
|
|
||||||
}, {
|
|
||||||
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
|
||||||
});
|
|
||||||
},
|
|
||||||
removeUnusedTransactionPicture: ({ id }) => {
|
|
||||||
return axios.post('v1/transaction/pictures/remove_unused.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getAllTransactionCategories: () => {
|
|
||||||
return axios.get('v1/transaction/categories/list.json');
|
|
||||||
},
|
|
||||||
getTransactionCategory: ({ id }) => {
|
|
||||||
return axios.get('v1/transaction/categories/get.json?id=' + id);
|
|
||||||
},
|
|
||||||
addTransactionCategory: ({ name, type, parentId, icon, color, comment, clientSessionId }) => {
|
|
||||||
return axios.post('v1/transaction/categories/add.json', {
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
parentId,
|
|
||||||
icon,
|
|
||||||
color,
|
|
||||||
comment,
|
|
||||||
clientSessionId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
addTransactionCategoryBatch: ({ categories }) => {
|
|
||||||
return axios.post('v1/transaction/categories/add_batch.json', {
|
|
||||||
categories
|
|
||||||
});
|
|
||||||
},
|
|
||||||
modifyTransactionCategory: ({ id, name, parentId, icon, color, comment, hidden }) => {
|
|
||||||
return axios.post('v1/transaction/categories/modify.json', {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
parentId,
|
|
||||||
icon,
|
|
||||||
color,
|
|
||||||
comment,
|
|
||||||
hidden
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hideTransactionCategory: ({ id, hidden }) => {
|
|
||||||
return axios.post('v1/transaction/categories/hide.json', {
|
|
||||||
id,
|
|
||||||
hidden
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moveTransactionCategory: ({ newDisplayOrders }) => {
|
|
||||||
return axios.post('v1/transaction/categories/move.json', {
|
|
||||||
newDisplayOrders,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteTransactionCategory: ({ id }) => {
|
|
||||||
return axios.post('v1/transaction/categories/delete.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getAllTransactionTags: () => {
|
|
||||||
return axios.get('v1/transaction/tags/list.json');
|
|
||||||
},
|
|
||||||
getTransactionTag: ({ id }) => {
|
|
||||||
return axios.get('v1/transaction/tags/get.json?id=' + id);
|
|
||||||
},
|
|
||||||
addTransactionTag: ({ name }) => {
|
|
||||||
return axios.post('v1/transaction/tags/add.json', {
|
|
||||||
name
|
|
||||||
});
|
|
||||||
},
|
|
||||||
modifyTransactionTag: ({ id, name }) => {
|
|
||||||
return axios.post('v1/transaction/tags/modify.json', {
|
|
||||||
id,
|
|
||||||
name
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hideTransactionTag: ({ id, hidden }) => {
|
|
||||||
return axios.post('v1/transaction/tags/hide.json', {
|
|
||||||
id,
|
|
||||||
hidden
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moveTransactionTag: ({ newDisplayOrders }) => {
|
|
||||||
return axios.post('v1/transaction/tags/move.json', {
|
|
||||||
newDisplayOrders,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteTransactionTag: ({ id }) => {
|
|
||||||
return axios.post('v1/transaction/tags/delete.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getAllTransactionTemplates: ({ templateType }) => {
|
|
||||||
return axios.get('v1/transaction/templates/list.json?templateType=' + templateType);
|
|
||||||
},
|
|
||||||
getTransactionTemplate: ({ id }) => {
|
|
||||||
return axios.get('v1/transaction/templates/get.json?id=' + id);
|
|
||||||
},
|
|
||||||
addTransactionTemplate: ({ templateType, name, type, categoryId, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, scheduledFrequencyType, scheduledFrequency, utcOffset, clientSessionId }) => {
|
|
||||||
return axios.post('v1/transaction/templates/add.json', {
|
|
||||||
templateType,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
categoryId,
|
|
||||||
sourceAccountId,
|
|
||||||
destinationAccountId,
|
|
||||||
sourceAmount,
|
|
||||||
destinationAmount,
|
|
||||||
hideAmount,
|
|
||||||
tagIds,
|
|
||||||
comment,
|
|
||||||
scheduledFrequencyType,
|
|
||||||
scheduledFrequency,
|
|
||||||
utcOffset,
|
|
||||||
clientSessionId
|
|
||||||
});
|
|
||||||
},
|
|
||||||
modifyTransactionTemplate: ({ id, name, type, categoryId, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, comment, scheduledFrequencyType, scheduledFrequency, utcOffset }) => {
|
|
||||||
return axios.post('v1/transaction/templates/modify.json', {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
categoryId,
|
|
||||||
sourceAccountId,
|
|
||||||
destinationAccountId,
|
|
||||||
sourceAmount,
|
|
||||||
destinationAmount,
|
|
||||||
hideAmount,
|
|
||||||
tagIds,
|
|
||||||
comment,
|
|
||||||
scheduledFrequencyType,
|
|
||||||
scheduledFrequency,
|
|
||||||
utcOffset
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hideTransactionTemplate: ({ id, hidden }) => {
|
|
||||||
return axios.post('v1/transaction/templates/hide.json', {
|
|
||||||
id,
|
|
||||||
hidden
|
|
||||||
});
|
|
||||||
},
|
|
||||||
moveTransactionTemplate: ({ newDisplayOrders }) => {
|
|
||||||
return axios.post('v1/transaction/templates/move.json', {
|
|
||||||
newDisplayOrders,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
deleteTransactionTemplate: ({ id }) => {
|
|
||||||
return axios.post('v1/transaction/templates/delete.json', {
|
|
||||||
id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getLatestExchangeRates: ({ ignoreError }) => {
|
|
||||||
return axios.get('v1/exchange_rates/latest.json', {
|
|
||||||
ignoreError: !!ignoreError,
|
|
||||||
timeout: getExchangeRatesRequestTimeout() || DEFAULT_API_TIMEOUT
|
|
||||||
});
|
|
||||||
},
|
|
||||||
generateQrCodeUrl: (qrCodeName) => {
|
|
||||||
return `${BASE_QRCODE_PATH}/${qrCodeName}.png`;
|
|
||||||
},
|
|
||||||
generateMapProxyTileImageUrl: (mapProvider, language) => {
|
|
||||||
const token = userState.getToken();
|
|
||||||
let url = `${BASE_PROXY_URL_PATH}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
|
|
||||||
|
|
||||||
if (language) {
|
|
||||||
url = url + `&language=${language}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
},
|
|
||||||
generateMapProxyAnnotationImageUrl: (mapProvider, language) => {
|
|
||||||
const token = userState.getToken();
|
|
||||||
let url = `${BASE_PROXY_URL_PATH}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
|
|
||||||
|
|
||||||
if (language) {
|
|
||||||
url = url + `&language=${language}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
},
|
|
||||||
generateGoogleMapJavascriptUrl: (language, callbackFnName) => {
|
|
||||||
let url = `${GOOGLE_MAP_JAVASCRIPT_URL}?key=${getGoogleMapAPIKey()}&libraries=core,marker&callback=${callbackFnName}`;
|
|
||||||
|
|
||||||
if (language) {
|
|
||||||
url = url + `&language=${language}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
},
|
|
||||||
generateBaiduMapJavascriptUrl: (callbackFnName) => {
|
|
||||||
return `${BAIDU_MAP_JAVASCRIPT_URL}&ak=${getBaiduMapAK()}&callback=${callbackFnName}`;
|
|
||||||
},
|
|
||||||
generateAmapJavascriptUrl: (callbackFnName) => {
|
|
||||||
return `${AMAP_JAVASCRIPT_URL}&key=${getAmapApplicationKey()}&plugin=AMap.ToolBar&callback=${callbackFnName}`;
|
|
||||||
},
|
|
||||||
generateAmapApiInternalProxyUrl: () => {
|
|
||||||
return `${window.location.origin}${BASE_AMAP_API_PROXY_URL_PATH}`;
|
|
||||||
},
|
|
||||||
getInternalAvatarUrlWithToken(avatarUrl, disableBrowserCache) {
|
|
||||||
if (!avatarUrl) {
|
|
||||||
return avatarUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = [];
|
|
||||||
params.push('token=' + userState.getToken());
|
|
||||||
|
|
||||||
if (disableBrowserCache) {
|
|
||||||
if (isBoolean(disableBrowserCache)) {
|
|
||||||
params.push('_nocache=' + generateRandomUUID());
|
|
||||||
} else {
|
|
||||||
params.push('_nocache=' + disableBrowserCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (avatarUrl.indexOf('?') >= 0) {
|
|
||||||
return avatarUrl + '&' + params.join('&');
|
|
||||||
} else {
|
|
||||||
return avatarUrl + '?' + params.join('&');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTransactionPictureUrlWithToken(pictureUrl, disableBrowserCache) {
|
|
||||||
if (!pictureUrl) {
|
|
||||||
return pictureUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = [];
|
|
||||||
params.push('token=' + userState.getToken());
|
|
||||||
|
|
||||||
if (disableBrowserCache) {
|
|
||||||
if (isBoolean(disableBrowserCache)) {
|
|
||||||
params.push('_nocache=' + generateRandomUUID());
|
|
||||||
} else {
|
|
||||||
params.push('_nocache=' + disableBrowserCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pictureUrl.indexOf('?') >= 0) {
|
|
||||||
return pictureUrl + '&' + params.join('&');
|
|
||||||
} else {
|
|
||||||
return pictureUrl + '?' + params.join('&');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,605 @@
|
|||||||
|
import axios, { type AxiosRequestConfig, type AxiosRequestHeaders, type AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BASE_API_URL_PATH,
|
||||||
|
BASE_QRCODE_PATH,
|
||||||
|
BASE_PROXY_URL_PATH,
|
||||||
|
BASE_AMAP_API_PROXY_URL_PATH,
|
||||||
|
DEFAULT_API_TIMEOUT,
|
||||||
|
DEFAULT_UPLOAD_API_TIMEOUT,
|
||||||
|
DEFAULT_IMPORT_API_TIMEOUT,
|
||||||
|
GOOGLE_MAP_JAVASCRIPT_URL,
|
||||||
|
BAIDU_MAP_JAVASCRIPT_URL,
|
||||||
|
AMAP_JAVASCRIPT_URL
|
||||||
|
} from '@/consts/api.ts';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
AccountCreateRequest,
|
||||||
|
AccountModifyRequest,
|
||||||
|
AccountInfoResponse,
|
||||||
|
AccountHideRequest,
|
||||||
|
AccountMoveRequest,
|
||||||
|
AccountDeleteRequest
|
||||||
|
} from '@/models/account.ts';
|
||||||
|
import type {
|
||||||
|
AuthResponse,
|
||||||
|
RegisterResponse
|
||||||
|
} from '@/models/auth_response.ts';
|
||||||
|
import type {
|
||||||
|
ClearDataRequest,
|
||||||
|
DataStatisticsResponse
|
||||||
|
} from '@/models/data_management.ts';
|
||||||
|
import type {
|
||||||
|
LatestExchangeRateResponse
|
||||||
|
} from '@/models/exchange_rate.ts';
|
||||||
|
import type {
|
||||||
|
ForgetPasswordRequest
|
||||||
|
} from '@/models/forget_password.ts';
|
||||||
|
import type {
|
||||||
|
ImportTransactionResponsePageWrapper
|
||||||
|
} from '@/models/imported_transaction.ts';
|
||||||
|
import type {
|
||||||
|
TransactionCreateRequest,
|
||||||
|
TransactionModifyRequest,
|
||||||
|
TransactionDeleteRequest,
|
||||||
|
TransactionImportRequest,
|
||||||
|
TransactionListByMaxTimeRequest,
|
||||||
|
TransactionListInMonthByPageRequest,
|
||||||
|
TransactionInfoResponse,
|
||||||
|
TransactionInfoPageWrapperResponse,
|
||||||
|
TransactionInfoPageWrapperResponse2,
|
||||||
|
TransactionStatisticRequest,
|
||||||
|
TransactionStatisticResponse,
|
||||||
|
TransactionStatisticTrendsRequest,
|
||||||
|
TransactionStatisticTrendsItem,
|
||||||
|
TransactionAmountsRequestParams,
|
||||||
|
TransactionAmountsResponseItem
|
||||||
|
} from '@/models/transaction.ts';
|
||||||
|
import {
|
||||||
|
TransactionAmountsRequest
|
||||||
|
} from '@/models/transaction.ts';
|
||||||
|
import type {
|
||||||
|
TransactionCategoryCreateRequest,
|
||||||
|
TransactionCategoryCreateBatchRequest,
|
||||||
|
TransactionCategoryModifyRequest,
|
||||||
|
TransactionCategoryHideRequest,
|
||||||
|
TransactionCategoryMoveRequest,
|
||||||
|
TransactionCategoryDeleteRequest,
|
||||||
|
TransactionCategoryInfoResponse
|
||||||
|
} from '@/models/transaction_category.ts';
|
||||||
|
import type {
|
||||||
|
TransactionPictureUnusedDeleteRequest,
|
||||||
|
TransactionPictureInfoBasicResponse
|
||||||
|
} from '@/models/transaction_picture_info.ts';
|
||||||
|
import type {
|
||||||
|
TransactionTagCreateRequest,
|
||||||
|
TransactionTagModifyRequest,
|
||||||
|
TransactionTagHideRequest,
|
||||||
|
TransactionTagMoveRequest,
|
||||||
|
TransactionTagDeleteRequest,
|
||||||
|
TransactionTagInfoResponse
|
||||||
|
} from '@/models/transaction_tag.ts';
|
||||||
|
import type {
|
||||||
|
TransactionTemplateCreateRequest,
|
||||||
|
TransactionTemplateModifyRequest,
|
||||||
|
TransactionTemplateHideRequest,
|
||||||
|
TransactionTemplateMoveRequest,
|
||||||
|
TransactionTemplateDeleteRequest,
|
||||||
|
TransactionTemplateInfoResponse
|
||||||
|
} from '@/models/transaction_template.ts';
|
||||||
|
import type {
|
||||||
|
TokenRefreshResponse,
|
||||||
|
TokenInfoResponse
|
||||||
|
} from '@/models/token.ts';
|
||||||
|
import type {
|
||||||
|
TwoFactorEnableConfirmRequest,
|
||||||
|
TwoFactorEnableResponse,
|
||||||
|
TwoFactorEnableConfirmResponse,
|
||||||
|
TwoFactorDisableRequest,
|
||||||
|
TwoFactorRegenerateRecoveryCodeRequest,
|
||||||
|
TwoFactorStatusResponse
|
||||||
|
} from '@/models/two_factor.ts';
|
||||||
|
import type {
|
||||||
|
UserLoginRequest,
|
||||||
|
UserRegisterRequest,
|
||||||
|
UserVerifyEmailResponse,
|
||||||
|
UserResendVerifyEmailRequest,
|
||||||
|
UserProfileResponse,
|
||||||
|
UserProfileUpdateRequest,
|
||||||
|
UserProfileUpdateResponse
|
||||||
|
} from '@/models/user.ts';
|
||||||
|
|
||||||
|
import userState from './userstate.ts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
isDefined,
|
||||||
|
isBoolean
|
||||||
|
} from './common.ts';
|
||||||
|
import {
|
||||||
|
getGoogleMapAPIKey,
|
||||||
|
getBaiduMapAK,
|
||||||
|
getAmapApplicationKey,
|
||||||
|
getExchangeRatesRequestTimeout
|
||||||
|
} from './server_settings.ts';
|
||||||
|
import { getTimezoneOffsetMinutes } from './datetime.ts';
|
||||||
|
import { generateRandomUUID } from './misc.ts';
|
||||||
|
|
||||||
|
interface ApiRequestConfig extends AxiosRequestConfig {
|
||||||
|
headers: AxiosRequestHeaders;
|
||||||
|
noAuth?: boolean;
|
||||||
|
ignoreBlocked?: boolean;
|
||||||
|
ignoreError?: boolean;
|
||||||
|
timeout?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ApiResponse<T> {
|
||||||
|
readonly success: boolean;
|
||||||
|
readonly result: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiResponsePromise<T> = Promise<AxiosResponse<ApiResponse<T>>>;
|
||||||
|
|
||||||
|
let needBlockRequest = false;
|
||||||
|
const blockedRequests: ((token: string | undefined) => void)[] = [];
|
||||||
|
|
||||||
|
axios.defaults.baseURL = BASE_API_URL_PATH;
|
||||||
|
axios.defaults.timeout = DEFAULT_API_TIMEOUT;
|
||||||
|
axios.interceptors.request.use((config: ApiRequestConfig) => {
|
||||||
|
const token = userState.getToken();
|
||||||
|
|
||||||
|
if (token && !config.noAuth) {
|
||||||
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.headers['X-Timezone-Offset'] = getTimezoneOffsetMinutes();
|
||||||
|
|
||||||
|
if (needBlockRequest && !config.ignoreBlocked) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
blockedRequests.push(newToken => {
|
||||||
|
if (newToken) {
|
||||||
|
config.headers.Authorization = `Bearer ${newToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(config);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}, error => {
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
axios.interceptors.response.use(response => {
|
||||||
|
return response;
|
||||||
|
}, error => {
|
||||||
|
if (error.response && !error.response.config.ignoreError && error.response.data && error.response.data.errorCode) {
|
||||||
|
const errorCode = error.response.data.errorCode;
|
||||||
|
|
||||||
|
if (errorCode === 202001 // unauthorized access
|
||||||
|
|| errorCode === 202002 // current token is invalid
|
||||||
|
|| errorCode === 202003 // current token is expired
|
||||||
|
|| errorCode === 202004 // current token type is invalid
|
||||||
|
|| errorCode === 202005 // current token requires two-factor authorization
|
||||||
|
|| errorCode === 202006 // current token does not require two-factor authorization
|
||||||
|
|| errorCode === 202012 // token is empty
|
||||||
|
) {
|
||||||
|
userState.clearTokenAndUserInfo(false);
|
||||||
|
location.reload();
|
||||||
|
return Promise.reject({ processed: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setLocale: (locale: string) => {
|
||||||
|
axios.defaults.headers.common['Accept-Language'] = locale;
|
||||||
|
},
|
||||||
|
authorize: (data: UserLoginRequest): ApiResponsePromise<AuthResponse> => {
|
||||||
|
return axios.post<ApiResponse<AuthResponse>>('authorize.json', data);
|
||||||
|
},
|
||||||
|
authorize2FA: (req: { passcode: string, token: string }): ApiResponsePromise<AuthResponse> => {
|
||||||
|
return axios.post<ApiResponse<AuthResponse>>('2fa/authorize.json', {
|
||||||
|
passcode: req.passcode
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${req.token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
authorize2FAByBackupCode: (req: { recoveryCode: string, token: string }): ApiResponsePromise<AuthResponse> => {
|
||||||
|
return axios.post<ApiResponse<AuthResponse>>('2fa/recovery.json', {
|
||||||
|
recoveryCode: req.recoveryCode
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${req.token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
register: (req: UserRegisterRequest): ApiResponsePromise<RegisterResponse> => {
|
||||||
|
return axios.post<ApiResponse<RegisterResponse>>('register.json', req);
|
||||||
|
},
|
||||||
|
verifyEmail: (req: { token: string, requestNewToken: boolean }): ApiResponsePromise<UserVerifyEmailResponse> => {
|
||||||
|
return axios.post<ApiResponse<UserVerifyEmailResponse>>('verify_email/by_token.json?token=' + req.token, {
|
||||||
|
requestNewToken: req.requestNewToken
|
||||||
|
}, {
|
||||||
|
noAuth: true,
|
||||||
|
ignoreError: true
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
resendVerifyEmailByUnloginUser: (req: UserResendVerifyEmailRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('verify_email/resend.json', req);
|
||||||
|
},
|
||||||
|
requestResetPassword: (req: ForgetPasswordRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('forget_password/request.json', req);
|
||||||
|
},
|
||||||
|
resetPassword: (req: { email: string, token: string, password: string }): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('forget_password/reset/by_token.json?token=' + req.token, {
|
||||||
|
email: req.email,
|
||||||
|
password: req.password
|
||||||
|
}, {
|
||||||
|
noAuth: true,
|
||||||
|
ignoreError: true
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
logout: (): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.get<ApiResponse<boolean>>('logout.json');
|
||||||
|
},
|
||||||
|
refreshToken: (): ApiResponsePromise<TokenRefreshResponse> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
needBlockRequest = true;
|
||||||
|
|
||||||
|
axios.post<ApiResponse<TokenRefreshResponse>>('v1/tokens/refresh.json', {}, {
|
||||||
|
ignoreBlocked: true
|
||||||
|
} as ApiRequestConfig).then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
resolve(response);
|
||||||
|
needBlockRequest = false;
|
||||||
|
|
||||||
|
return data.result.newToken;
|
||||||
|
}).then(newToken => {
|
||||||
|
blockedRequests.forEach(func => func(newToken));
|
||||||
|
blockedRequests.length = 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getTokens: (): ApiResponsePromise<TokenInfoResponse[]> => {
|
||||||
|
return axios.get<ApiResponse<TokenInfoResponse[]>>('v1/tokens/list.json');
|
||||||
|
},
|
||||||
|
revokeToken: (req: { tokenId: string, ignoreError: boolean }): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/tokens/revoke.json', {
|
||||||
|
tokenId: req.tokenId
|
||||||
|
}, {
|
||||||
|
ignoreError: req.ignoreError
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
revokeAllTokens: (): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/tokens/revoke_all.json');
|
||||||
|
},
|
||||||
|
getProfile: (): ApiResponsePromise<UserProfileResponse> => {
|
||||||
|
return axios.get<ApiResponse<UserProfileResponse>>('v1/users/profile/get.json');
|
||||||
|
},
|
||||||
|
updateProfile: (req: UserProfileUpdateRequest): ApiResponsePromise<UserProfileUpdateResponse> => {
|
||||||
|
return axios.post<ApiResponse<UserProfileUpdateResponse>>('v1/users/profile/update.json', req);
|
||||||
|
},
|
||||||
|
updateAvatar: (req: { avatarFile: unknown }): ApiResponsePromise<UserProfileResponse> => {
|
||||||
|
return axios.postForm<ApiResponse<UserProfileResponse>>('v1/users/avatar/update.json', {
|
||||||
|
avatar: req.avatarFile
|
||||||
|
}, {
|
||||||
|
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
||||||
|
});
|
||||||
|
},
|
||||||
|
removeAvatar: (): ApiResponsePromise<UserProfileResponse> => {
|
||||||
|
return axios.post<ApiResponse<UserProfileResponse>>('v1/users/avatar/remove.json');
|
||||||
|
},
|
||||||
|
resendVerifyEmailByLoginedUser: (): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/users/verify_email/resend.json');
|
||||||
|
},
|
||||||
|
get2FAStatus: (): ApiResponsePromise<TwoFactorStatusResponse> => {
|
||||||
|
return axios.get<ApiResponse<TwoFactorStatusResponse>>('v1/users/2fa/status.json');
|
||||||
|
},
|
||||||
|
enable2FA: (): ApiResponsePromise<TwoFactorEnableResponse> => {
|
||||||
|
return axios.post<ApiResponse<TwoFactorEnableResponse>>('v1/users/2fa/enable/request.json');
|
||||||
|
},
|
||||||
|
confirmEnable2FA: (req: TwoFactorEnableConfirmRequest): ApiResponsePromise<TwoFactorEnableConfirmResponse> => {
|
||||||
|
return axios.post<ApiResponse<TwoFactorEnableConfirmResponse>>('v1/users/2fa/enable/confirm.json', req);
|
||||||
|
},
|
||||||
|
disable2FA: (req: TwoFactorDisableRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/users/2fa/disable.json', req);
|
||||||
|
},
|
||||||
|
regenerate2FARecoveryCode: (req: TwoFactorRegenerateRecoveryCodeRequest): ApiResponsePromise<TwoFactorEnableConfirmResponse> => {
|
||||||
|
return axios.post<ApiResponse<TwoFactorEnableConfirmResponse>>('v1/users/2fa/recovery/regenerate.json', req);
|
||||||
|
},
|
||||||
|
getUserDataStatistics: (): ApiResponsePromise<DataStatisticsResponse> => {
|
||||||
|
return axios.get<ApiResponse<DataStatisticsResponse>>('v1/data/statistics.json');
|
||||||
|
},
|
||||||
|
getExportedUserData: (fileType: string): Promise<AxiosResponse<unknown>> => {
|
||||||
|
if (fileType === 'csv') {
|
||||||
|
return axios.get<unknown>('v1/data/export.csv');
|
||||||
|
} else if (fileType === 'tsv') {
|
||||||
|
return axios.get<unknown>('v1/data/export.tsv');
|
||||||
|
} else {
|
||||||
|
return Promise.reject('Parameter Invalid');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearData: (req: ClearDataRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/data/clear.json', req);
|
||||||
|
},
|
||||||
|
getAllAccounts: (req: { visibleOnly: boolean }): ApiResponsePromise<AccountInfoResponse[]> => {
|
||||||
|
return axios.get<ApiResponse<AccountInfoResponse[]>>('v1/accounts/list.json?visible_only=' + req.visibleOnly);
|
||||||
|
},
|
||||||
|
getAccount: (req: { id: string }): ApiResponsePromise<AccountInfoResponse> => {
|
||||||
|
return axios.get<ApiResponse<AccountInfoResponse>>('v1/accounts/get.json?id=' + req.id);
|
||||||
|
},
|
||||||
|
addAccount: (req: AccountCreateRequest): ApiResponsePromise<AccountInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<AccountInfoResponse>>('v1/accounts/add.json', req);
|
||||||
|
},
|
||||||
|
modifyAccount: (req: AccountModifyRequest): ApiResponsePromise<AccountInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<AccountInfoResponse>>('v1/accounts/modify.json', req);
|
||||||
|
},
|
||||||
|
hideAccount: (req: AccountHideRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/accounts/hide.json', req);
|
||||||
|
},
|
||||||
|
moveAccount: (req: AccountMoveRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/accounts/move.json', req);
|
||||||
|
},
|
||||||
|
deleteAccount: (req: AccountDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/accounts/delete.json', req);
|
||||||
|
},
|
||||||
|
getTransactions: (req: TransactionListByMaxTimeRequest): ApiResponsePromise<TransactionInfoPageWrapperResponse> => {
|
||||||
|
const amountFilter = encodeURIComponent(req.amountFilter);
|
||||||
|
const keyword = encodeURIComponent(req.keyword);
|
||||||
|
return axios.get<ApiResponse<TransactionInfoPageWrapperResponse>>(`v1/transactions/list.json?max_time=${req.maxTime}&min_time=${req.minTime}&type=${req.type}&category_ids=${req.categoryIds}&account_ids=${req.accountIds}&tag_ids=${req.tagIds}&tag_filter_type=${req.tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&count=${req.count}&page=${req.page}&with_count=${req.withCount}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||||
|
},
|
||||||
|
getAllTransactionsByMonth: (req: TransactionListInMonthByPageRequest): ApiResponsePromise<TransactionInfoPageWrapperResponse2> => {
|
||||||
|
const amountFilter = encodeURIComponent(req.amountFilter);
|
||||||
|
const keyword = encodeURIComponent(req.keyword);
|
||||||
|
return axios.get<ApiResponse<TransactionInfoPageWrapperResponse2>>(`v1/transactions/list/by_month.json?year=${req.year}&month=${req.month}&type=${req.type}&category_ids=${req.categoryIds}&account_ids=${req.accountIds}&tag_ids=${req.tagIds}&tag_filter_type=${req.tagFilterType}&amount_filter=${amountFilter}&keyword=${keyword}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||||
|
},
|
||||||
|
getTransactionStatistics: (req: TransactionStatisticRequest): ApiResponsePromise<TransactionStatisticResponse> => {
|
||||||
|
const queryParams = [];
|
||||||
|
|
||||||
|
if (req.startTime) {
|
||||||
|
queryParams.push(`start_time=${req.startTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.endTime) {
|
||||||
|
queryParams.push(`end_time=${req.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.tagIds) {
|
||||||
|
queryParams.push(`tag_ids=${req.tagIds}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.tagFilterType) {
|
||||||
|
queryParams.push(`tag_filter_type=${req.tagFilterType}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return axios.get<ApiResponse<TransactionStatisticResponse>>(`v1/transactions/statistics.json?use_transaction_timezone=${req.useTransactionTimezone}` + (queryParams.length ? '&' + queryParams.join('&') : ''));
|
||||||
|
},
|
||||||
|
getTransactionStatisticsTrends: (req: TransactionStatisticTrendsRequest): ApiResponsePromise<TransactionStatisticTrendsItem[]> => {
|
||||||
|
const queryParams = [];
|
||||||
|
|
||||||
|
if (req.startYearMonth) {
|
||||||
|
queryParams.push(`start_year_month=${req.startYearMonth}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.endYearMonth) {
|
||||||
|
queryParams.push(`end_year_month=${req.endYearMonth}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.tagIds) {
|
||||||
|
queryParams.push(`tag_ids=${req.tagIds}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.tagFilterType) {
|
||||||
|
queryParams.push(`tag_filter_type=${req.tagFilterType}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return axios.get<ApiResponse<TransactionStatisticTrendsItem[]>>(`v1/transactions/statistics/trends.json?use_transaction_timezone=${req.useTransactionTimezone}` + (queryParams.length ? '&' + queryParams.join('&') : ''));
|
||||||
|
},
|
||||||
|
getTransactionAmounts: (params: TransactionAmountsRequestParams): ApiResponsePromise<TransactionAmountsResponseItem> => {
|
||||||
|
const req = TransactionAmountsRequest.of(params);
|
||||||
|
return axios.get<ApiResponse<TransactionAmountsResponseItem>>(`v1/transactions/amounts.json?${req.buildQuery()}`);
|
||||||
|
},
|
||||||
|
getTransaction: (req: { id: string, withPictures: boolean | undefined }): ApiResponsePromise<TransactionInfoResponse> => {
|
||||||
|
if (!isDefined(req.withPictures)) {
|
||||||
|
req.withPictures = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return axios.get<ApiResponse<TransactionInfoResponse>>(`v1/transactions/get.json?id=${req.id}&with_pictures=${req.withPictures}&trim_account=true&trim_category=true&trim_tag=true`);
|
||||||
|
},
|
||||||
|
addTransaction: (req: TransactionCreateRequest): ApiResponsePromise<TransactionInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionInfoResponse>>('v1/transactions/add.json', req);
|
||||||
|
},
|
||||||
|
modifyTransaction: (req: TransactionModifyRequest): ApiResponsePromise<TransactionInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionInfoResponse>>('v1/transactions/modify.json', req);
|
||||||
|
},
|
||||||
|
deleteTransaction: (req: TransactionDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transactions/delete.json', req);
|
||||||
|
},
|
||||||
|
parseImportTransaction: (req: { fileType: string, importFile: unknown }): ApiResponsePromise<ImportTransactionResponsePageWrapper> => {
|
||||||
|
return axios.postForm<ApiResponse<ImportTransactionResponsePageWrapper>>('v1/transactions/parse_import.json', {
|
||||||
|
fileType: req.fileType,
|
||||||
|
file: req.importFile
|
||||||
|
}, {
|
||||||
|
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
importTransactions: (req: TransactionImportRequest): ApiResponsePromise<number> => {
|
||||||
|
return axios.post<ApiResponse<number>>('v1/transactions/import.json', req, {
|
||||||
|
timeout: DEFAULT_IMPORT_API_TIMEOUT
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
uploadTransactionPicture: (req: { pictureFile: unknown, clientSessionId: string }): ApiResponsePromise<TransactionPictureInfoBasicResponse> => {
|
||||||
|
return axios.postForm<ApiResponse<TransactionPictureInfoBasicResponse>>('v1/transaction/pictures/upload.json', {
|
||||||
|
picture: req.pictureFile,
|
||||||
|
clientSessionId: req.clientSessionId
|
||||||
|
}, {
|
||||||
|
timeout: DEFAULT_UPLOAD_API_TIMEOUT
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
removeUnusedTransactionPicture: (req: TransactionPictureUnusedDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/pictures/remove_unused.json', req);
|
||||||
|
},
|
||||||
|
getAllTransactionCategories: (): ApiResponsePromise<TransactionCategoryInfoResponse[]> => {
|
||||||
|
return axios.get<ApiResponse<TransactionCategoryInfoResponse[]>>('v1/transaction/categories/list.json');
|
||||||
|
},
|
||||||
|
getTransactionCategory: (req: { id: string }): ApiResponsePromise<TransactionCategoryInfoResponse> => {
|
||||||
|
return axios.get<ApiResponse<TransactionCategoryInfoResponse>>('v1/transaction/categories/get.json?id=' + req.id);
|
||||||
|
},
|
||||||
|
addTransactionCategory: (req: TransactionCategoryCreateRequest): ApiResponsePromise<TransactionCategoryInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionCategoryInfoResponse>>('v1/transaction/categories/add.json', req);
|
||||||
|
},
|
||||||
|
addTransactionCategoryBatch: (req: TransactionCategoryCreateBatchRequest): ApiResponsePromise<Record<number, TransactionCategoryInfoResponse[]>> => {
|
||||||
|
return axios.post<ApiResponse<Record<number, TransactionCategoryInfoResponse[]>>>('v1/transaction/categories/add_batch.json', req);
|
||||||
|
},
|
||||||
|
modifyTransactionCategory: (req: TransactionCategoryModifyRequest): ApiResponsePromise<TransactionCategoryInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionCategoryInfoResponse>>('v1/transaction/categories/modify.json', req);
|
||||||
|
},
|
||||||
|
hideTransactionCategory: (req: TransactionCategoryHideRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/categories/hide.json', req);
|
||||||
|
},
|
||||||
|
moveTransactionCategory: (req: TransactionCategoryMoveRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/categories/move.json', req);
|
||||||
|
},
|
||||||
|
deleteTransactionCategory: (req: TransactionCategoryDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/categories/delete.json', req);
|
||||||
|
},
|
||||||
|
getAllTransactionTags: (): ApiResponsePromise<TransactionTagInfoResponse[]> => {
|
||||||
|
return axios.get<ApiResponse<TransactionTagInfoResponse[]>>('v1/transaction/tags/list.json');
|
||||||
|
},
|
||||||
|
getTransactionTag: (req: { id: string }): ApiResponsePromise<TransactionTagInfoResponse> => {
|
||||||
|
return axios.get<ApiResponse<TransactionTagInfoResponse>>('v1/transaction/tags/get.json?id=' + req.id);
|
||||||
|
},
|
||||||
|
addTransactionTag: (req: TransactionTagCreateRequest): ApiResponsePromise<TransactionTagInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionTagInfoResponse>>('v1/transaction/tags/add.json', req);
|
||||||
|
},
|
||||||
|
modifyTransactionTag: (req: TransactionTagModifyRequest): ApiResponsePromise<TransactionTagInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionTagInfoResponse>>('v1/transaction/tags/modify.json', req);
|
||||||
|
},
|
||||||
|
hideTransactionTag: (req: TransactionTagHideRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/tags/hide.json', req);
|
||||||
|
},
|
||||||
|
moveTransactionTag: (req: TransactionTagMoveRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/tags/move.json', req);
|
||||||
|
},
|
||||||
|
deleteTransactionTag: (req: TransactionTagDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/tags/delete.json', req);
|
||||||
|
},
|
||||||
|
getAllTransactionTemplates: (req: { templateType: number }): ApiResponsePromise<TransactionTemplateInfoResponse[]> => {
|
||||||
|
return axios.get<ApiResponse<TransactionTemplateInfoResponse[]>>('v1/transaction/templates/list.json?templateType=' + req.templateType);
|
||||||
|
},
|
||||||
|
getTransactionTemplate: (req: { id: string }): ApiResponsePromise<TransactionTemplateInfoResponse> => {
|
||||||
|
return axios.get<ApiResponse<TransactionTemplateInfoResponse>>('v1/transaction/templates/get.json?id=' + req.id);
|
||||||
|
},
|
||||||
|
addTransactionTemplate: (req: TransactionTemplateCreateRequest): ApiResponsePromise<TransactionTemplateInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionTemplateInfoResponse>>('v1/transaction/templates/add.json', req);
|
||||||
|
},
|
||||||
|
modifyTransactionTemplate: (req: TransactionTemplateModifyRequest): ApiResponsePromise<TransactionTemplateInfoResponse> => {
|
||||||
|
return axios.post<ApiResponse<TransactionTemplateInfoResponse>>('v1/transaction/templates/modify.json', req);
|
||||||
|
},
|
||||||
|
hideTransactionTemplate: (req: TransactionTemplateHideRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/templates/hide.json', req);
|
||||||
|
},
|
||||||
|
moveTransactionTemplate: (req: TransactionTemplateMoveRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/templates/move.json', req);
|
||||||
|
},
|
||||||
|
deleteTransactionTemplate: (req: TransactionTemplateDeleteRequest): ApiResponsePromise<boolean> => {
|
||||||
|
return axios.post<ApiResponse<boolean>>('v1/transaction/templates/delete.json', req);
|
||||||
|
},
|
||||||
|
getLatestExchangeRates: (param: { ignoreError: boolean }): ApiResponsePromise<LatestExchangeRateResponse> => {
|
||||||
|
return axios.get<ApiResponse<LatestExchangeRateResponse>>('v1/exchange_rates/latest.json', {
|
||||||
|
ignoreError: param.ignoreError,
|
||||||
|
timeout: getExchangeRatesRequestTimeout() || DEFAULT_API_TIMEOUT
|
||||||
|
} as ApiRequestConfig);
|
||||||
|
},
|
||||||
|
generateQrCodeUrl: (qrCodeName: string): string => {
|
||||||
|
return `${BASE_QRCODE_PATH}/${qrCodeName}.png`;
|
||||||
|
},
|
||||||
|
generateMapProxyTileImageUrl: (mapProvider: string, language: string): string => {
|
||||||
|
const token = userState.getToken();
|
||||||
|
let url = `${BASE_PROXY_URL_PATH}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
|
||||||
|
|
||||||
|
if (language) {
|
||||||
|
url = url + `&language=${language}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
},
|
||||||
|
generateMapProxyAnnotationImageUrl: (mapProvider: string, language: string): string => {
|
||||||
|
const token = userState.getToken();
|
||||||
|
let url = `${BASE_PROXY_URL_PATH}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
|
||||||
|
|
||||||
|
if (language) {
|
||||||
|
url = url + `&language=${language}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
},
|
||||||
|
generateGoogleMapJavascriptUrl: (language: string, callbackFnName: string): string => {
|
||||||
|
let url = `${GOOGLE_MAP_JAVASCRIPT_URL}?key=${getGoogleMapAPIKey()}&libraries=core,marker&callback=${callbackFnName}`;
|
||||||
|
|
||||||
|
if (language) {
|
||||||
|
url = url + `&language=${language}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
},
|
||||||
|
generateBaiduMapJavascriptUrl: (callbackFnName: string): string => {
|
||||||
|
return `${BAIDU_MAP_JAVASCRIPT_URL}&ak=${getBaiduMapAK()}&callback=${callbackFnName}`;
|
||||||
|
},
|
||||||
|
generateAmapJavascriptUrl: (callbackFnName: string): string => {
|
||||||
|
return `${AMAP_JAVASCRIPT_URL}&key=${getAmapApplicationKey()}&plugin=AMap.ToolBar&callback=${callbackFnName}`;
|
||||||
|
},
|
||||||
|
generateAmapApiInternalProxyUrl: (): string => {
|
||||||
|
return `${window.location.origin}${BASE_AMAP_API_PROXY_URL_PATH}`;
|
||||||
|
},
|
||||||
|
getInternalAvatarUrlWithToken(avatarUrl: string, disableBrowserCache: boolean | string): string {
|
||||||
|
if (!avatarUrl) {
|
||||||
|
return avatarUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = [];
|
||||||
|
params.push('token=' + userState.getToken());
|
||||||
|
|
||||||
|
if (disableBrowserCache) {
|
||||||
|
if (isBoolean(disableBrowserCache)) {
|
||||||
|
params.push('_nocache=' + generateRandomUUID());
|
||||||
|
} else {
|
||||||
|
params.push('_nocache=' + disableBrowserCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avatarUrl.indexOf('?') >= 0) {
|
||||||
|
return avatarUrl + '&' + params.join('&');
|
||||||
|
} else {
|
||||||
|
return avatarUrl + '?' + params.join('&');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getTransactionPictureUrlWithToken(pictureUrl: string, disableBrowserCache: boolean | string): string {
|
||||||
|
if (!pictureUrl) {
|
||||||
|
return pictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = [];
|
||||||
|
params.push('token=' + userState.getToken());
|
||||||
|
|
||||||
|
if (disableBrowserCache) {
|
||||||
|
if (isBoolean(disableBrowserCache)) {
|
||||||
|
params.push('_nocache=' + generateRandomUUID());
|
||||||
|
} else {
|
||||||
|
params.push('_nocache=' + disableBrowserCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pictureUrl.indexOf('?') >= 0) {
|
||||||
|
return pictureUrl + '&' + params.join('&');
|
||||||
|
} else {
|
||||||
|
return pictureUrl + '?' + params.join('&');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
export interface AccountCreateRequest {
|
||||||
|
readonly name: string;
|
||||||
|
readonly category: number;
|
||||||
|
readonly type: number;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly currency: string;
|
||||||
|
readonly balance: number;
|
||||||
|
readonly balanceTime: number;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly creditCardStatementDate: number;
|
||||||
|
readonly subAccounts?: AccountCreateRequest[];
|
||||||
|
readonly clientSessionId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountModifyRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly category: number;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly creditCardStatementDate?: number;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
readonly subAccounts?: AccountModifyRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountInfoResponse {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly parentId: string;
|
||||||
|
readonly category: number;
|
||||||
|
readonly type: number;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly currency: string;
|
||||||
|
readonly balance: number;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly creditCardStatementDate?: number;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
readonly isAsset?: boolean;
|
||||||
|
readonly isLiability?: boolean;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
readonly subAccounts?: AccountInfoResponse[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountHideRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountMoveRequest {
|
||||||
|
readonly newDisplayOrders: AccountNewDisplayOrderRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountNewDisplayOrderRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AccountDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import type { UserBasicInfo } from './user.ts';
|
||||||
|
|
||||||
|
export interface AuthResponse {
|
||||||
|
token: string;
|
||||||
|
need2FA: boolean;
|
||||||
|
user?: UserBasicInfo;
|
||||||
|
notificationContent?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RegisterResponse extends AuthResponse {
|
||||||
|
needVerifyEmail: boolean;
|
||||||
|
presetCategoriesSaved: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
export interface ClearDataRequest {
|
||||||
|
readonly password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DataStatisticsResponse {
|
||||||
|
readonly totalAccountCount: number;
|
||||||
|
readonly totalTransactionCategoryCount: number;
|
||||||
|
readonly totalTransactionTagCount: number;
|
||||||
|
readonly totalTransactionCount: number;
|
||||||
|
readonly totalTransactionPictureCount: number;
|
||||||
|
readonly totalTransactionTemplateCount: number;
|
||||||
|
readonly totalScheduledTransactionCount: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export interface LatestExchangeRate {
|
||||||
|
readonly currency: string;
|
||||||
|
readonly rate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LatestExchangeRateResponse {
|
||||||
|
readonly dataSource: string;
|
||||||
|
readonly referenceUrl: string;
|
||||||
|
readonly updateTime: number;
|
||||||
|
readonly baseCurrency: string;
|
||||||
|
readonly exchangeRates: LatestExchangeRate[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export interface ForgetPasswordRequest {
|
||||||
|
readonly email: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import type { TransactionGeoLocationResponse } from './transaction.ts';
|
||||||
|
|
||||||
|
export interface ImportTransactionResponse {
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly originalCategoryName: string;
|
||||||
|
readonly time: number;
|
||||||
|
readonly utcOffset: number;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly originalSourceAccountName: string;
|
||||||
|
readonly originalSourceAccountCurrency: string;
|
||||||
|
readonly destinationAccountId?: string;
|
||||||
|
readonly originalDestinationAccountName?: string;
|
||||||
|
readonly originalDestinationAccountCurrency?: string;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount?: number;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly originalTagNames: string[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly geoLocation?: TransactionGeoLocationResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportTransactionResponsePageWrapper {
|
||||||
|
readonly items: ImportTransactionResponse[];
|
||||||
|
readonly totalCount: number;
|
||||||
|
}
|
||||||
@@ -1,5 +1,14 @@
|
|||||||
|
import type { UserBasicInfo } from './user.ts';
|
||||||
|
|
||||||
export const TOKEN_CLI_USER_AGENT: string = 'ezbookkeeping Cli';
|
export const TOKEN_CLI_USER_AGENT: string = 'ezbookkeeping Cli';
|
||||||
|
|
||||||
|
export interface TokenRefreshResponse {
|
||||||
|
readonly newToken?: string;
|
||||||
|
readonly oldTokenId?: string;
|
||||||
|
readonly user: UserBasicInfo;
|
||||||
|
readonly notificationContent?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TokenInfoResponse {
|
export interface TokenInfoResponse {
|
||||||
readonly tokenId: string;
|
readonly tokenId: string;
|
||||||
readonly tokenType: number;
|
readonly tokenType: number;
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
import type { StartEndTime } from '@/core/datetime.ts';
|
||||||
|
|
||||||
|
import type { AccountInfoResponse } from './account.ts';
|
||||||
|
import type { TransactionCategoryInfoResponse } from './transaction_category.ts';
|
||||||
|
import type { TransactionPictureInfoBasicResponse } from './transaction_picture_info.ts';
|
||||||
|
import type { TransactionTagInfoResponse } from './transaction_tag.ts';
|
||||||
|
|
||||||
|
export interface TransactionGeoLocationRequest {
|
||||||
|
readonly latitude: number;
|
||||||
|
readonly longitude: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCreateRequest {
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly time: number;
|
||||||
|
readonly utcOffset: number;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly destinationAccountId: string;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount: number;
|
||||||
|
readonly hideAmount: boolean;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly pictureIds: string[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly geoLocation?: TransactionGeoLocationRequest;
|
||||||
|
readonly clientSessionId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionModifyRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly time: number;
|
||||||
|
readonly utcOffset: number;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly destinationAccountId: string;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount: number;
|
||||||
|
readonly hideAmount: boolean;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly pictureIds: string[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly geoLocation?: TransactionGeoLocationRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionImportRequest {
|
||||||
|
readonly transactions: TransactionCreateRequest[];
|
||||||
|
readonly clientSessionId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionListByMaxTimeRequest {
|
||||||
|
readonly maxTime: number;
|
||||||
|
readonly minTime: number;
|
||||||
|
readonly count: number;
|
||||||
|
readonly page: number;
|
||||||
|
readonly withCount: boolean;
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryIds: string;
|
||||||
|
readonly accountIds: string;
|
||||||
|
readonly tagIds: string;
|
||||||
|
readonly tagFilterType: number;
|
||||||
|
readonly amountFilter: string;
|
||||||
|
readonly keyword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionListInMonthByPageRequest {
|
||||||
|
readonly year: number;
|
||||||
|
readonly month: number;
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryIds: string;
|
||||||
|
readonly accountIds: string;
|
||||||
|
readonly tagIds: string;
|
||||||
|
readonly tagFilterType: number;
|
||||||
|
readonly amountFilter: string;
|
||||||
|
readonly keyword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionGeoLocationResponse {
|
||||||
|
readonly latitude: number;
|
||||||
|
readonly longitude: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionInfoResponse {
|
||||||
|
readonly id: string;
|
||||||
|
readonly timeSequenceId: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly category?: TransactionCategoryInfoResponse;
|
||||||
|
readonly time: number;
|
||||||
|
readonly utcOffset: number;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly sourceAccount?: AccountInfoResponse;
|
||||||
|
readonly destinationAccountId: string;
|
||||||
|
readonly destinationAccount?: AccountInfoResponse;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount: number;
|
||||||
|
readonly hideAmount: boolean;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly tags?: TransactionTagInfoResponse[];
|
||||||
|
readonly pictures?: TransactionPictureInfoBasicResponse[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly geoLocation?: TransactionGeoLocationResponse;
|
||||||
|
readonly editable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionStatisticRequest {
|
||||||
|
readonly startTime: number;
|
||||||
|
readonly endTime: number;
|
||||||
|
readonly tagIds: string;
|
||||||
|
readonly tagFilterType: number;
|
||||||
|
readonly useTransactionTimezone: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface YearMonthRangeRequest {
|
||||||
|
readonly startYearMonth: string;
|
||||||
|
readonly endYearMonth: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionStatisticTrendsRequest extends YearMonthRangeRequest {
|
||||||
|
readonly tagIds: string;
|
||||||
|
readonly tagFilterType: number;
|
||||||
|
readonly useTransactionTimezone: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionAmountsRequestParams {
|
||||||
|
readonly useTransactionTimezone: boolean;
|
||||||
|
readonly today: StartEndTime;
|
||||||
|
readonly thisWeek: StartEndTime;
|
||||||
|
readonly thisMonth: StartEndTime;
|
||||||
|
readonly thisYear: StartEndTime;
|
||||||
|
readonly lastMonth: StartEndTime;
|
||||||
|
readonly monthBeforeLastMonth: StartEndTime;
|
||||||
|
readonly monthBeforeLast2Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast3Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast4Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast5Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast6Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast7Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast8Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast9Months: StartEndTime;
|
||||||
|
readonly monthBeforeLast10Months: StartEndTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TransactionAmountsRequest {
|
||||||
|
public readonly useTransactionTimezone: boolean;
|
||||||
|
public readonly query: string;
|
||||||
|
|
||||||
|
constructor(useTransactionTimezone: boolean, query: string) {
|
||||||
|
this.useTransactionTimezone = useTransactionTimezone;
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public buildQuery(): string {
|
||||||
|
return `use_transaction_timezone=${this.useTransactionTimezone}` + (this.query.length ? '&query=' + this.query : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static of(params: TransactionAmountsRequestParams): TransactionAmountsRequest {
|
||||||
|
const queryParams = [];
|
||||||
|
|
||||||
|
if (params.today) {
|
||||||
|
queryParams.push(`today_${params.today.startTime}_${params.today.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.thisWeek) {
|
||||||
|
queryParams.push(`thisWeek_${params.thisWeek.startTime}_${params.thisWeek.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.thisMonth) {
|
||||||
|
queryParams.push(`thisMonth_${params.thisMonth.startTime}_${params.thisMonth.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.thisYear) {
|
||||||
|
queryParams.push(`thisYear_${params.thisYear.startTime}_${params.thisYear.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.lastMonth) {
|
||||||
|
queryParams.push(`lastMonth_${params.lastMonth.startTime}_${params.lastMonth.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLastMonth) {
|
||||||
|
queryParams.push(`monthBeforeLastMonth_${params.monthBeforeLastMonth.startTime}_${params.monthBeforeLastMonth.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast2Months) {
|
||||||
|
queryParams.push(`monthBeforeLast2Months_${params.monthBeforeLast2Months.startTime}_${params.monthBeforeLast2Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast3Months) {
|
||||||
|
queryParams.push(`monthBeforeLast3Months_${params.monthBeforeLast3Months.startTime}_${params.monthBeforeLast3Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast4Months) {
|
||||||
|
queryParams.push(`monthBeforeLast4Months_${params.monthBeforeLast4Months.startTime}_${params.monthBeforeLast4Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast5Months) {
|
||||||
|
queryParams.push(`monthBeforeLast5Months_${params.monthBeforeLast5Months.startTime}_${params.monthBeforeLast5Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast6Months) {
|
||||||
|
queryParams.push(`monthBeforeLast6Months_${params.monthBeforeLast6Months.startTime}_${params.monthBeforeLast6Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast7Months) {
|
||||||
|
queryParams.push(`monthBeforeLast7Months_${params.monthBeforeLast7Months.startTime}_${params.monthBeforeLast7Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast8Months) {
|
||||||
|
queryParams.push(`monthBeforeLast8Months_${params.monthBeforeLast8Months.startTime}_${params.monthBeforeLast8Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast9Months) {
|
||||||
|
queryParams.push(`monthBeforeLast9Months_${params.monthBeforeLast9Months.startTime}_${params.monthBeforeLast9Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.monthBeforeLast10Months) {
|
||||||
|
queryParams.push(`monthBeforeLast10Months_${params.monthBeforeLast10Months.startTime}_${params.monthBeforeLast10Months.endTime}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TransactionAmountsRequest(params.useTransactionTimezone, (queryParams.length ? queryParams.join('|') : ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionInfoPageWrapperResponse {
|
||||||
|
readonly items: TransactionInfoResponse[];
|
||||||
|
readonly nextTimeSequenceId?: string;
|
||||||
|
readonly totalCount?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionInfoPageWrapperResponse2 {
|
||||||
|
readonly items: TransactionInfoResponse[];
|
||||||
|
readonly totalCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionStatisticResponse {
|
||||||
|
readonly startTime: number;
|
||||||
|
readonly endTime: number;
|
||||||
|
readonly items: TransactionStatisticResponseItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionStatisticResponseItem {
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly accountId: string;
|
||||||
|
readonly totalAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionStatisticTrendsItem {
|
||||||
|
readonly year: number;
|
||||||
|
readonly month: number;
|
||||||
|
readonly items: TransactionStatisticResponseItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionAmountsResponseItem {
|
||||||
|
readonly startTime: number;
|
||||||
|
readonly endTime: number;
|
||||||
|
readonly amounts: TransactionAmountsResponseItemAmountInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionAmountsResponseItemAmountInfo {
|
||||||
|
readonly currency: string;
|
||||||
|
readonly incomeAmount: number;
|
||||||
|
readonly expenseAmount: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
export interface TransactionCategoryCreateRequest {
|
||||||
|
readonly name: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly parentId: string;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly clientSessionId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryCreateBatchRequest {
|
||||||
|
readonly categories: TransactionCategoryCreateWithSubCategories[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryCreateWithSubCategories {
|
||||||
|
readonly name: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly subCategories: TransactionCategoryCreateRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryModifyRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly parentId: string;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryHideRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryMoveRequest {
|
||||||
|
readonly newDisplayOrders: TransactionCategoryNewDisplayOrderRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryNewDisplayOrderRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionCategoryInfoResponse {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly parentId: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly icon: string;
|
||||||
|
readonly color: string;
|
||||||
|
readonly comment: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
readonly subCategories?: TransactionCategoryInfoResponse[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export interface TransactionPictureUnusedDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionPictureInfoBasicResponse {
|
||||||
|
readonly pictureId: string;
|
||||||
|
readonly originalUrl: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
export interface TransactionTagCreateRequest {
|
||||||
|
readonly name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagModifyRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagHideRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagMoveRequest {
|
||||||
|
readonly newDisplayOrders: TransactionTagNewDisplayOrderRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagNewDisplayOrderRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTagInfoResponse {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import type { TransactionInfoResponse } from './transaction.ts';
|
||||||
|
|
||||||
|
export interface TransactionTemplateCreateRequest {
|
||||||
|
readonly templateType: number;
|
||||||
|
readonly name: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly destinationAccountId: string;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount: number;
|
||||||
|
readonly hideAmount: boolean;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly scheduledFrequencyType?: number;
|
||||||
|
readonly scheduledFrequency?: string;
|
||||||
|
readonly utcOffset?: number;
|
||||||
|
readonly clientSessionId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateModifyRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly name: string;
|
||||||
|
readonly type: number;
|
||||||
|
readonly categoryId: string;
|
||||||
|
readonly sourceAccountId: string;
|
||||||
|
readonly destinationAccountId: string;
|
||||||
|
readonly sourceAmount: number;
|
||||||
|
readonly destinationAmount: number;
|
||||||
|
readonly hideAmount: boolean;
|
||||||
|
readonly tagIds: string[];
|
||||||
|
readonly comment: string;
|
||||||
|
readonly scheduledFrequencyType?: number;
|
||||||
|
readonly scheduledFrequency?: string;
|
||||||
|
readonly utcOffset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateHideRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateMoveRequest {
|
||||||
|
readonly newDisplayOrders: TransactionTemplateNewDisplayOrderRequest[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateNewDisplayOrderRequest {
|
||||||
|
readonly id: string;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateDeleteRequest {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TransactionTemplateInfoResponse extends TransactionInfoResponse {
|
||||||
|
readonly templateType: number;
|
||||||
|
readonly name: string;
|
||||||
|
readonly scheduledFrequencyType?: number;
|
||||||
|
readonly scheduledFrequency?: string;
|
||||||
|
readonly scheduledAt?: number;
|
||||||
|
readonly displayOrder: number;
|
||||||
|
readonly hidden: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
export interface TwoFactorEnableConfirmRequest {
|
||||||
|
readonly secret: string;
|
||||||
|
readonly passcode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TwoFactorEnableResponse {
|
||||||
|
readonly secret: string;
|
||||||
|
readonly qrcode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TwoFactorEnableConfirmResponse {
|
||||||
|
readonly token?: string;
|
||||||
|
readonly recoveryCodes: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TwoFactorDisableRequest {
|
||||||
|
readonly password?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TwoFactorRegenerateRecoveryCodeRequest {
|
||||||
|
readonly password?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TwoFactorStatusResponse {
|
||||||
|
readonly enable: boolean;
|
||||||
|
readonly createdAt?: number;
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import type { TransactionCategoryCreateBatchRequest } from './transaction_category.ts';
|
||||||
|
|
||||||
export interface UserBasicInfo {
|
export interface UserBasicInfo {
|
||||||
readonly username: string;
|
readonly username: string;
|
||||||
readonly email: string;
|
readonly email: string;
|
||||||
@@ -21,3 +23,61 @@ export interface UserBasicInfo {
|
|||||||
readonly incomeAmountColor: number;
|
readonly incomeAmountColor: number;
|
||||||
readonly emailVerified: boolean;
|
readonly emailVerified: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserLoginRequest {
|
||||||
|
readonly loginName: string;
|
||||||
|
readonly password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserRegisterRequest {
|
||||||
|
readonly username: string;
|
||||||
|
readonly email: string;
|
||||||
|
readonly nickname: string;
|
||||||
|
readonly password: string;
|
||||||
|
readonly language: string;
|
||||||
|
readonly defaultCurrency: string;
|
||||||
|
readonly firstDayOfWeek: number;
|
||||||
|
readonly categories?: TransactionCategoryCreateBatchRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserVerifyEmailResponse {
|
||||||
|
readonly newToken?: string;
|
||||||
|
readonly user: UserBasicInfo;
|
||||||
|
readonly notificationContent?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserResendVerifyEmailRequest {
|
||||||
|
readonly email: string;
|
||||||
|
readonly password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfileUpdateRequest {
|
||||||
|
readonly email?: string;
|
||||||
|
readonly nickname?: string;
|
||||||
|
readonly password?: string;
|
||||||
|
readonly oldPassword?: string;
|
||||||
|
readonly defaultAccountId?: string;
|
||||||
|
readonly transactionEditScope?: number;
|
||||||
|
readonly language?: string;
|
||||||
|
readonly defaultCurrency?: string;
|
||||||
|
readonly firstDayOfWeek?: number;
|
||||||
|
readonly longDateFormat?: number;
|
||||||
|
readonly shortDateFormat?: number;
|
||||||
|
readonly longTimeFormat?: number;
|
||||||
|
readonly shortTimeFormat?: number;
|
||||||
|
readonly decimalSeparator?: number;
|
||||||
|
readonly digitGroupingSymbol?: number;
|
||||||
|
readonly digitGrouping?: number;
|
||||||
|
readonly currencyDisplayType?: number;
|
||||||
|
readonly expenseAmountColor?: number;
|
||||||
|
readonly incomeAmountColor?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfileUpdateResponse {
|
||||||
|
readonly user: UserBasicInfo;
|
||||||
|
readonly newToken?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfileResponse extends UserBasicInfo {
|
||||||
|
readonly lastLoginAt: number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { AccountType, AccountCategory } from '@/core/account.ts';
|
|||||||
import { PARENT_ACCOUNT_CURRENCY_PLACEHOLDER } from '@/consts/currency.ts';
|
import { PARENT_ACCOUNT_CURRENCY_PLACEHOLDER } from '@/consts/currency.ts';
|
||||||
import { DEFAULT_ACCOUNT_ICON_ID } from '@/consts/icon.ts';
|
import { DEFAULT_ACCOUNT_ICON_ID } from '@/consts/icon.ts';
|
||||||
import { DEFAULT_ACCOUNT_COLOR } from '@/consts/color.ts';
|
import { DEFAULT_ACCOUNT_COLOR } from '@/consts/color.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import { isNumber, isEquals } from '@/lib/common.ts';
|
import { isNumber, isEquals } from '@/lib/common.ts';
|
||||||
import { getCurrentUnixTime } from '@/lib/datetime.ts';
|
import { getCurrentUnixTime } from '@/lib/datetime.ts';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import { isEquals } from '@/lib/common.ts';
|
import { isEquals } from '@/lib/common.ts';
|
||||||
import { getCurrentUnixTime, formatUnixTime } from '@/lib/datetime.ts';
|
import { getCurrentUnixTime, formatUnixTime } from '@/lib/datetime.ts';
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import { useStatisticsStore } from './statistics.js';
|
|||||||
import { useExchangeRatesStore } from './exchangeRates.js';
|
import { useExchangeRatesStore } from './exchangeRates.js';
|
||||||
|
|
||||||
import userState from '@/lib/userstate.ts';
|
import userState from '@/lib/userstate.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import { isObject, isString } from '@/lib/common.ts';
|
import { isObject, isString } from '@/lib/common.ts';
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
getThisYearFirstUnixTime,
|
getThisYearFirstUnixTime,
|
||||||
getThisYearLastUnixTime
|
getThisYearLastUnixTime
|
||||||
} from '@/lib/datetime.ts';
|
} from '@/lib/datetime.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
|
|
||||||
function updateTransactionDateRange(state) {
|
function updateTransactionDateRange(state) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
} from '@/core/statistics.ts';
|
} from '@/core/statistics.ts';
|
||||||
import { DEFAULT_ACCOUNT_ICON, DEFAULT_CATEGORY_ICON } from '@/consts/icon.ts';
|
import { DEFAULT_ACCOUNT_ICON, DEFAULT_CATEGORY_ICON } from '@/consts/icon.ts';
|
||||||
import { DEFAULT_ACCOUNT_COLOR, DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
|
import { DEFAULT_ACCOUNT_COLOR, DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import {
|
import {
|
||||||
isEquals,
|
isEquals,
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import { defineStore } from 'pinia';
|
|||||||
import { useUserStore } from './user.js';
|
import { useUserStore } from './user.js';
|
||||||
|
|
||||||
import userState from '@/lib/userstate.ts';
|
import userState from '@/lib/userstate.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import { isObject } from '@/lib/common.ts';
|
import { isObject } from '@/lib/common.ts';
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { CategoryType } from '@/core/category.ts';
|
|||||||
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
|
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
|
||||||
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
|
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
|
||||||
import userState from '@/lib/userstate.ts';
|
import userState from '@/lib/userstate.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import {
|
import {
|
||||||
isDefined,
|
isDefined,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { CategoryType } from '@/core/category.ts';
|
|||||||
import { DEFAULT_CATEGORY_ICON_ID } from '@/consts/icon.ts';
|
import { DEFAULT_CATEGORY_ICON_ID } from '@/consts/icon.ts';
|
||||||
import { DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
|
import { DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
|
||||||
import { isEquals } from '@/lib/common.ts';
|
import { isEquals } from '@/lib/common.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
|
|
||||||
function loadTransactionCategoryList(state, allCategories) {
|
function loadTransactionCategoryList(state, allCategories) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import { isEquals } from '@/lib/common.ts';
|
import { isEquals } from '@/lib/common.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
|
|
||||||
function loadTransactionTagList(state, tags) {
|
function loadTransactionTagList(state, tags) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { defineStore } from 'pinia';
|
|||||||
import { TransactionType } from '@/core/transaction.ts';
|
import { TransactionType } from '@/core/transaction.ts';
|
||||||
import { TemplateType } from '@/core/template.ts';
|
import { TemplateType } from '@/core/template.ts';
|
||||||
import { isDefined, isObject, isArray, isEquals } from '@/lib/common.ts';
|
import { isDefined, isObject, isArray, isEquals } from '@/lib/common.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
|
|
||||||
function loadTransactionTemplateList(state, templateType, templates) {
|
function loadTransactionTemplateList(state, templateType, templates) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
import userState from '@/lib/userstate.ts';
|
import userState from '@/lib/userstate.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import { isBoolean } from '@/lib/common.ts';
|
import { isBoolean } from '@/lib/common.ts';
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ import { defineStore } from 'pinia';
|
|||||||
import { useSettingsStore } from './setting.js';
|
import { useSettingsStore } from './setting.js';
|
||||||
|
|
||||||
import userState from '@/lib/userstate.ts';
|
import userState from '@/lib/userstate.ts';
|
||||||
import services from '@/lib/services.js';
|
import services from '@/lib/services.ts';
|
||||||
import logger from '@/lib/logger.ts';
|
import logger from '@/lib/logger.ts';
|
||||||
import {
|
import {
|
||||||
isObject,
|
isObject,
|
||||||
|
|||||||
Reference in New Issue
Block a user