diff --git a/package-lock.json b/package-lock.json index 66e57874..532876d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4623,22 +4623,6 @@ "safer-buffer": "^2.1.0" } }, - "echarts": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.0.1.tgz", - "integrity": "sha512-JYn22Dolt2esY2jEzUsw1OxbobuW67oGjIoTjZO3rW89SWkfJ4kbrmC2OW9JjsBrD1rdkmaWBuZZ2HgmThyxJw==", - "requires": { - "tslib": "2.0.3", - "zrender": "5.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" - } - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7074,7 +7058,8 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true }, "lodash.defaultsdeep": { "version": "4.6.1", @@ -9376,11 +9361,6 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, - "resize-detector": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/resize-detector/-/resize-detector-0.1.10.tgz", - "integrity": "sha512-iLcXC8A6Fb0DfA+TRiywrK/0A22bFqkhntjMJMEzXDA4XkcEkfwpNbv7W8iewUiD0xYIaeiXOfiEehTqGKsUFw==" - }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -11116,16 +11096,6 @@ "clipboard": "^2.0.0" } }, - "vue-echarts": { - "version": "5.0.0-beta.0", - "resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-5.0.0-beta.0.tgz", - "integrity": "sha512-QZFKGXDAYFQo+F20REpzcdLx79nsl4kOorJRpN+08aYq4YiIlmtWss1Lxadm7Fo+NYyWm8nnT+h4xHv3uqWIDQ==", - "requires": { - "core-js": "^3.4.4", - "lodash": "^4.17.15", - "resize-detector": "^0.1.10" - } - }, "vue-eslint-parser": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz", @@ -12184,21 +12154,6 @@ "dev": true } } - }, - "zrender": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.0.3.tgz", - "integrity": "sha512-TVcN2IMdo7je3GEq/E4CER4AGBe/n50/izILdupppyHf/hVHuiXCRliqdu8+32Z1OmGg6RfKt5qQlkX+bOtU0g==", - "requires": { - "tslib": "2.0.3" - }, - "dependencies": { - "tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" - } - } } } } diff --git a/package.json b/package.json index 2b8f7bd7..92a1ca1b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "cbor-js": "^0.1.0", "core-js": "^3.6.5", "crypto-js": "^4.0.0", - "echarts": "^5.0.1", "framework7": "^5.7.14", "framework7-icons": "^3.0.1", "framework7-vue": "^5.7.14", @@ -22,7 +21,6 @@ "ua-parser-js": "^0.7.22", "vue": "^2.6.12", "vue-clipboard2": "^0.3.1", - "vue-echarts": "^5.0.0-beta.0", "vue-i18n": "^8.22.1", "vue-moment": "^4.1.0", "vue-pincode-input": "^0.4.0", diff --git a/src/components/mobile/PieChart.vue b/src/components/mobile/PieChart.vue new file mode 100644 index 00000000..3f746a7f --- /dev/null +++ b/src/components/mobile/PieChart.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/src/filters/defaultIconColor.js b/src/filters/defaultIconColor.js new file mode 100644 index 00000000..805ebdb0 --- /dev/null +++ b/src/filters/defaultIconColor.js @@ -0,0 +1,11 @@ +import colorConstants from '../consts/color.js'; + +export default function (color, defaultColor) { + if (color && color !== colorConstants.defaultColor) { + color = '#' + color; + } else { + color = defaultColor; + } + + return color; +} diff --git a/src/mobile-main.js b/src/mobile-main.js index 82324651..899fecb9 100644 --- a/src/mobile-main.js +++ b/src/mobile-main.js @@ -2,7 +2,6 @@ import Vue from 'vue'; import Vuex from 'vuex'; import VueI18n from 'vue-i18n'; -import ECharts from 'vue-echarts'; import PincodeInput from 'vue-pincode-input'; import VueMoment from 'vue-moment'; import VueClipboard from 'vue-clipboard2'; @@ -46,14 +45,6 @@ import 'framework7-icons'; import 'line-awesome/dist/line-awesome/css/line-awesome.css'; -import 'echarts/lib/chart/line'; -import 'echarts/lib/chart/pie'; -import 'echarts/lib/chart/bar'; -import 'echarts/lib/component/title'; -import 'echarts/lib/component/legend'; -import 'echarts/lib/component/grid'; -import 'echarts/lib/component/tooltip'; - import { getAllLanguages, getLanguage, getDefaultLanguage, getI18nOptions, getLocalizedError, getLocalizedErrorParameters } from './lib/i18n.js'; import api from './consts/api.js'; import datetime from './consts/datetime.js'; @@ -79,6 +70,7 @@ import itemFieldContentFilter from './filters/itemFieldContent.js'; import currencyFilter from './filters/currency.js'; import iconFilter from './filters/icon.js'; import iconStyleFilter from './filters/iconStyle.js'; +import defaultIconColorFilter from './filters/defaultIconColor.js'; import accountIconFilter from './filters/accountIcon.js'; import accountIconStyleFilter from './filters/accountIconStyle.js'; import categoryIconFilter from './filters/categoryIcon.js'; @@ -86,6 +78,7 @@ import categoryIconStyleFilter from './filters/categoryIconStyle.js'; import tokenDeviceFilter from './filters/tokenDevice.js'; import tokenIconFilter from './filters/tokenIcon.js'; +import PieChart from "./components/mobile/PieChart.vue"; import PasswordInputSheet from "./components/mobile/PasswordInputSheet.vue"; import PasscodeInputSheet from "./components/mobile/PasscodeInputSheet.vue"; import PinCodeInputSheet from "./components/mobile/PinCodeInputSheet.vue"; @@ -136,8 +129,8 @@ Vue.use(VueI18n); Vue.use(VueMoment, { moment }); Vue.use(VueClipboard); -Vue.component('v-chart', ECharts); Vue.component('PincodeInput', PincodeInput); +Vue.component('PieChart', PieChart); Vue.component('PasswordInputSheet', PasswordInputSheet); Vue.component('PasscodeInputSheet', PasscodeInputSheet); Vue.component('PinCodeInputSheet', PinCodeInputSheet); @@ -296,6 +289,7 @@ Vue.filter('itemFieldContent', (value, fieldName, defaultValue, translate) => it Vue.filter('currency', (value, currencyCode) => currencyFilter({ i18n }, value, currencyCode)); Vue.filter('icon', (value, iconType) => iconFilter(value, iconType)); Vue.filter('iconStyle', (value, iconType, defaultColor) => iconStyleFilter(value, iconType, defaultColor)); +Vue.filter('defaultIconColor', (value, defaultColor) => defaultIconColorFilter(value, defaultColor)); Vue.filter('accountIcon', (value) => accountIconFilter(value)); Vue.filter('accountIconStyle', (value, defaultColor) => accountIconStyleFilter(value, defaultColor)); Vue.filter('categoryIcon', (value) => categoryIconFilter(value)); diff --git a/src/views/mobile/statistics/Transaction.vue b/src/views/mobile/statistics/Transaction.vue index 9c69bdc6..73cc5ca7 100644 --- a/src/views/mobile/statistics/Transaction.vue +++ b/src/views/mobile/statistics/Transaction.vue @@ -22,8 +22,30 @@ - - + + + + {{ $t('Total Expense') }} + {{ $t('Total Income') }} + + {{ statisticsData.totalAmount | currency(defaultCurrency) }} + + @@ -361,97 +383,6 @@ export default { totalAmount: allAmount, items: allStatisticsItems }; - }, - chartData() { - const self = this; - - if (!self.$store.state.transactionStatistics || - !self.$store.state.transactionStatistics.items || - !self.$store.state.transactionStatistics.items.length) { - return self.skeletonChart(); - } - - const allData = []; - - for (let i = 0; i < this.statisticsData.items.length; i++) { - const data = this.statisticsData.items[i]; - - allData.push({ - name: data.name, - value: data.totalAmount / 100, - itemStyle: { - color: `#${data.color}` - } - }); - } - - const chartData = { - label: { - show: true, - overflow: 'truncate', - align: 'left', - formatter: params => { - return `${params.name} ${self.$options.filters.currency(params.value * 100, self.defaultCurrency)}`; - } - }, - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'shadow' - } - }, - series: [ - { - data: allData, - } - ], - animation: false - }; - - if (this.query.chartType === this.$constants.statistics.allChartTypes.Bar) { - return this.$utilities.copyObjectTo({ - grid: { - left: 30, - top: 30, - right: 50, - bottom: 50 - }, - xAxis: { - type: 'value' - }, - yAxis: { - type: 'category' - }, - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'shadow' - } - }, - series: [{ - type: 'bar' - }] - }, chartData); - } else { - return this.$utilities.copyObjectTo({ - tooltip: { - trigger: 'item' - }, - series: [{ - type: 'pie', - label: { - position: 'inside' - }, - emphasis: { - itemStyle: { - shadowBlur: 10, - shadowOffsetX: 0, - shadowColor: 'rgba(0, 0, 0, 0.5)' - } - } - }] - }, chartData); - } } }, created() { @@ -608,64 +539,6 @@ export default { const displayEndTime = this.$utilities.formatUnixTime(query.endTime, this.$t(startTimeYear !== endTimeYear ? 'format.date.short' : 'format.date.shortMonthDay')); return `${displayStartTime} ~ ${displayEndTime}`; - }, - skeletonChart() { - const skeletonChartData = { - series: [{ - data: [{ - value: 20, - itemStyle: { - color: '#7c7c7f' - } - },{ - value: 20, - itemStyle: { - color: '#a5a5aa' - } - },{ - value: 60, - itemStyle: { - color: '#c5c5c9' - } - }] - }], - animation: false - }; - - if (this.query.chartType === this.$constants.statistics.allChartTypes.Bar) { - return this.$utilities.copyObjectTo({ - grid: { - left: 30, - top: 30, - right: 50, - bottom: 50 - }, - xAxis: { - type: 'value', - axisLabel: { - show: false - }, - splitLine: { - show: false - } - }, - yAxis: { - type: 'category' - }, - series: [{ - type: 'bar' - }] - }, skeletonChartData); - } else { - return this.$utilities.copyObjectTo({ - series: [{ - type: 'pie', - label: { - position: 'inside' - } - }] - }, skeletonChartData); - } } }, filters: { @@ -704,6 +577,24 @@ export default {