mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 16:07:33 +08:00
migrate to typescript
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { ThemeType } from '@/core/theme.ts';
|
||||
|
||||
import { type AmountColor, PresetAmountColor } from '@/core/color.ts';
|
||||
|
||||
export function getSystemTheme(): ThemeType {
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return ThemeType.Dark;
|
||||
} else {
|
||||
return ThemeType.Light;
|
||||
}
|
||||
}
|
||||
|
||||
export function getExpenseAndIncomeAmountColor(expenseAmountColorType: number, incomeAmountColorType: number, isDarkMode: boolean): AmountColor {
|
||||
let expenseAmountColor = expenseAmountColorType ? PresetAmountColor.valueOf(expenseAmountColorType) : null;
|
||||
let incomeAmountColor = incomeAmountColorType ? PresetAmountColor.valueOf(incomeAmountColorType) : null;
|
||||
|
||||
if (!expenseAmountColor) {
|
||||
expenseAmountColor = PresetAmountColor.DefaultExpenseColor;
|
||||
}
|
||||
|
||||
if (!incomeAmountColor) {
|
||||
incomeAmountColor = PresetAmountColor.DefaultIncomeColor;
|
||||
}
|
||||
|
||||
if (isDarkMode) {
|
||||
return {
|
||||
expenseAmountColor: expenseAmountColor.darkThemeColor,
|
||||
incomeAmountColor: incomeAmountColor.darkThemeColor
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
expenseAmountColor: expenseAmountColor.lightThemeColor,
|
||||
incomeAmountColor: incomeAmountColor.lightThemeColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setExpenseAndIncomeAmountColor(expenseAmountColorType: number, incomeAmountColorType: number): void {
|
||||
let expenseAmountColor = expenseAmountColorType ? PresetAmountColor.valueOf(expenseAmountColorType) : null;
|
||||
let incomeAmountColor = incomeAmountColorType ? PresetAmountColor.valueOf(incomeAmountColorType) : null;
|
||||
|
||||
if (!expenseAmountColor) {
|
||||
expenseAmountColor = PresetAmountColor.DefaultExpenseColor;
|
||||
}
|
||||
|
||||
if (!incomeAmountColor) {
|
||||
incomeAmountColor = PresetAmountColor.DefaultIncomeColor;
|
||||
}
|
||||
|
||||
const htmlElement = document.querySelector('html');
|
||||
|
||||
if (!htmlElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const allPresetAmountColors = PresetAmountColor.values();
|
||||
|
||||
for (let i = 0; i < allPresetAmountColors.length; i++) {
|
||||
const amountColor = allPresetAmountColors[i];
|
||||
|
||||
if (amountColor.type === expenseAmountColor.type) {
|
||||
if (!htmlElement.classList.contains(amountColor.expenseClassName)) {
|
||||
htmlElement.classList.add(amountColor.expenseClassName);
|
||||
}
|
||||
} else {
|
||||
htmlElement.classList.remove(amountColor.expenseClassName);
|
||||
}
|
||||
|
||||
if (amountColor.type === incomeAmountColor.type) {
|
||||
if (!htmlElement.classList.contains(amountColor.incomeClassName)) {
|
||||
htmlElement.classList.add(amountColor.incomeClassName);
|
||||
}
|
||||
} else {
|
||||
htmlElement.classList.remove(amountColor.incomeClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function startDownloadFile(fileName: string, fileData: Blob): void {
|
||||
const dataObjectUrl = URL.createObjectURL(fileData);
|
||||
const dataLink = document.createElement('a');
|
||||
|
||||
dataLink.style.display = 'none';
|
||||
dataLink.href = dataObjectUrl;
|
||||
dataLink.setAttribute('download', fileName);
|
||||
|
||||
document.body.appendChild(dataLink);
|
||||
|
||||
dataLink.click();
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
export function getOuterHeight(element) {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
|
||||
return ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom']
|
||||
.map((key) => parseInt(computedStyle.getPropertyValue(key), 10))
|
||||
.reduce((prev, cur) => prev + cur);
|
||||
}
|
||||
|
||||
export function getNavSideBarOuterHeight(element) {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const contentEl = element.querySelectorAll('.v-navigation-drawer__content');
|
||||
|
||||
if (!contentEl || !contentEl[0]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const children = contentEl[0].children;
|
||||
|
||||
if (!children || children.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let totalHeight = 0;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
totalHeight += getOuterHeight(children[i]);
|
||||
}
|
||||
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
export function getCssValue(element, name) {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const computedStyle = window.getComputedStyle(element);
|
||||
return computedStyle.getPropertyValue(name);
|
||||
}
|
||||
|
||||
export function scrollToSelectedItem(parentEl, containerSelector, selectedItemSelector) {
|
||||
if (!parentEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
let container = parentEl;
|
||||
|
||||
if (containerSelector) {
|
||||
const lists = parentEl.querySelectorAll(containerSelector);
|
||||
|
||||
if (!lists.length || !lists[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
container = lists[0];
|
||||
}
|
||||
|
||||
const selectedItems = container.querySelectorAll(selectedItemSelector);
|
||||
|
||||
if (!selectedItems.length || !selectedItems[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedItem = selectedItems[0];
|
||||
const containerOuterHeight = getOuterHeight(container);
|
||||
const selectedItemOuterHeight = getOuterHeight(selectedItem);
|
||||
|
||||
let targetPos = selectedItem.offsetTop - container.offsetTop - parseInt(getCssValue(container, 'padding-top'), 10)
|
||||
- (containerOuterHeight - selectedItemOuterHeight) / 2;
|
||||
|
||||
if (selectedItems.length > 1) {
|
||||
|
||||
let firstSelectedItem = selectedItems[0];
|
||||
let lastSelectedItem = selectedItems[selectedItems.length - 1];
|
||||
|
||||
let firstSelectedItemInTop = firstSelectedItem.offsetTop - container.offsetTop - parseInt(getCssValue(container, 'padding-top'), 10);
|
||||
let lastSelectedItemInTop = lastSelectedItem.offsetTop - container.offsetTop - parseInt(getCssValue(container, 'padding-top'), 10);
|
||||
let lastSelectedItemInBottom = lastSelectedItem.offsetTop - container.offsetTop - parseInt(getCssValue(container, 'padding-top'), 10)
|
||||
- (containerOuterHeight - selectedItemOuterHeight);
|
||||
|
||||
targetPos = (firstSelectedItemInTop + lastSelectedItemInBottom) / 2;
|
||||
|
||||
if (lastSelectedItemInTop - firstSelectedItemInTop > containerOuterHeight) {
|
||||
targetPos = firstSelectedItemInTop;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPos <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.scrollTop = targetPos;
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
import { f7, f7ready } from 'framework7-vue';
|
||||
|
||||
import { FontSize, FONT_SIZE_PREVIEW_CLASSNAME_PREFIX } from '@/core/font.ts';
|
||||
import { isEnableAnimate } from '../settings.js';
|
||||
import { translateError } from '../i18n.js';
|
||||
|
||||
export function showAlert(message, confirmCallback, translateFn) {
|
||||
f7ready((f7) => {
|
||||
f7.dialog.create({
|
||||
title: translateFn('global.app.title'),
|
||||
text: translateError(message, translateFn),
|
||||
animate: isEnableAnimate(),
|
||||
buttons: [
|
||||
{
|
||||
text: translateFn('OK'),
|
||||
onClick: confirmCallback
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
});
|
||||
}
|
||||
|
||||
export function showConfirm(message, confirmCallback, cancelCallback, translateFn) {
|
||||
f7ready((f7) => {
|
||||
f7.dialog.create({
|
||||
title: translateFn('global.app.title'),
|
||||
text: translateFn(message),
|
||||
animate: isEnableAnimate(),
|
||||
buttons: [
|
||||
{
|
||||
text: translateFn('Cancel'),
|
||||
onClick: cancelCallback
|
||||
},
|
||||
{
|
||||
text: translateFn('OK'),
|
||||
onClick: confirmCallback
|
||||
}
|
||||
]
|
||||
}).open();
|
||||
});
|
||||
}
|
||||
|
||||
export function showToast(message, timeout, translateFn) {
|
||||
f7ready((f7) => {
|
||||
f7.toast.create({
|
||||
text: translateError(message, translateFn),
|
||||
position: 'center',
|
||||
closeTimeout: timeout || 1500
|
||||
}).open();
|
||||
});
|
||||
}
|
||||
|
||||
export function showLoading(delayConditionFunc, delayMills) {
|
||||
if (!delayConditionFunc) {
|
||||
f7ready((f7) => {
|
||||
return f7.preloader.show();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
f7ready((f7) => {
|
||||
setTimeout(() => {
|
||||
if (delayConditionFunc()) {
|
||||
f7.preloader.show();
|
||||
}
|
||||
}, delayMills || 200);
|
||||
});
|
||||
}
|
||||
|
||||
export function hideLoading() {
|
||||
f7ready((f7) => {
|
||||
return f7.preloader.hide();
|
||||
});
|
||||
}
|
||||
|
||||
export function createInlinePicker(containerEl, inputEl, cols, value, events) {
|
||||
return f7.picker.create({
|
||||
containerEl: containerEl,
|
||||
inputEl: inputEl,
|
||||
toolbar: false,
|
||||
rotateEffect: true,
|
||||
value: value,
|
||||
cols: cols,
|
||||
on: events || {}
|
||||
});
|
||||
}
|
||||
|
||||
export function routeBackOnError(f7router, errorPropertyName) {
|
||||
const self = this;
|
||||
const router = f7router;
|
||||
|
||||
const unwatch = self.$watch(errorPropertyName, () => {
|
||||
if (self[errorPropertyName]) {
|
||||
setTimeout(() => {
|
||||
if (unwatch) {
|
||||
unwatch();
|
||||
}
|
||||
|
||||
router.back();
|
||||
}, 200);
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
}
|
||||
|
||||
export function elements(selector) {
|
||||
return f7.$(selector);
|
||||
}
|
||||
|
||||
export function isModalShowing() {
|
||||
return f7.$('.modal-in').length;
|
||||
}
|
||||
|
||||
export function onSwipeoutDeleted(domId, callback) {
|
||||
f7.swipeout.delete(f7.$('#' + domId), callback);
|
||||
}
|
||||
|
||||
export function autoChangeTextareaSize(el) {
|
||||
f7.$(el).find('textarea').each(el => {
|
||||
el.scrollTop = 0;
|
||||
el.style.height = '';
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
export function setAppFontSize(type) {
|
||||
const htmlElement = elements('html');
|
||||
const allFontSizes = FontSize.values();
|
||||
|
||||
for (let i = 0; i < allFontSizes.length; i++) {
|
||||
const fontSizeType = allFontSizes[i];
|
||||
|
||||
if (fontSizeType.type === type) {
|
||||
if (!htmlElement.hasClass(fontSizeType.className)) {
|
||||
htmlElement.addClass(fontSizeType.className);
|
||||
}
|
||||
} else {
|
||||
htmlElement.removeClass(fontSizeType.className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getFontSizePreviewClassName(type) {
|
||||
const allFontSizes = FontSize.values();
|
||||
|
||||
for (let i = 0; i < allFontSizes.length; i++) {
|
||||
const fontSizeType = allFontSizes[i];
|
||||
|
||||
if (fontSizeType.type === type) {
|
||||
return FONT_SIZE_PREVIEW_CLASSNAME_PREFIX + fontSizeType.className;
|
||||
}
|
||||
}
|
||||
|
||||
return FONT_SIZE_PREVIEW_CLASSNAME_PREFIX + FontSize.Default.className;
|
||||
}
|
||||
|
||||
export function scrollToSelectedItem(parentEl, containerSelector, selectedItemSelector) {
|
||||
if (!parentEl || !parentEl.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = parentEl.find(containerSelector);
|
||||
const selectedItem = parentEl.find(selectedItemSelector);
|
||||
|
||||
if (!container.length || !selectedItem.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetPos = selectedItem.offset().top - container.offset().top - parseInt(container.css('padding-top'), 10)
|
||||
- (container.outerHeight() - selectedItem.outerHeight()) / 2;
|
||||
|
||||
if (selectedItem.length > 1) {
|
||||
let firstSelectedItem = elements(selectedItem[0]);
|
||||
let lastSelectedItem = elements(selectedItem[selectedItem.length - 1]);
|
||||
|
||||
let firstSelectedItemInTop = firstSelectedItem.offset().top - container.offset().top - parseInt(container.css('padding-top'), 10);
|
||||
let lastSelectedItemInTop = lastSelectedItem.offset().top - container.offset().top - parseInt(container.css('padding-top'), 10);
|
||||
let lastSelectedItemInBottom = lastSelectedItem.offset().top - container.offset().top - parseInt(container.css('padding-top'), 10)
|
||||
- (container.outerHeight() - firstSelectedItem.outerHeight());
|
||||
|
||||
targetPos = (firstSelectedItemInTop + lastSelectedItemInBottom) / 2;
|
||||
|
||||
if (lastSelectedItemInTop - firstSelectedItemInTop > container.outerHeight()) {
|
||||
targetPos = firstSelectedItemInTop;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPos <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.scrollTop(targetPos);
|
||||
}
|
||||
Reference in New Issue
Block a user