diff options
| author | Danil S. <135337715+sh1shd@users.noreply.github.com> | 2025-12-04 01:37:27 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-04 01:37:27 +0300 |
| commit | 70f6d6b21a6761444c54898a6ed48793e72e7177 (patch) | |
| tree | 1e9cdf81fe84da349b525016f3c499f0992426aa /web | |
| parent | e8c509c720267f6da34b9a43104f83f3dd77ef88 (diff) | |
chore: use `Intl` for date formatting (#3588)
* chore: use `Intl` for date formatting
* fix: show last traffic reset
* chore: use raw timestamps
* fix: remove unnecessary import
Diffstat (limited to 'web')
| -rw-r--r-- | web/assets/js/util/date-util.js | 151 | ||||
| -rw-r--r-- | web/assets/js/util/index.js | 31 | ||||
| -rw-r--r-- | web/html/common/page.html | 1 | ||||
| -rw-r--r-- | web/html/component/aClientTable.html | 70 | ||||
| -rw-r--r-- | web/html/form/inbound.html | 4 | ||||
| -rw-r--r-- | web/html/inbounds.html | 28 | ||||
| -rw-r--r-- | web/html/index.html | 4 | ||||
| -rw-r--r-- | web/html/modals/inbound_info_modal.html | 21 | ||||
| -rw-r--r-- | web/html/settings/panel/subscription/subpage.html | 25 |
9 files changed, 57 insertions, 278 deletions
diff --git a/web/assets/js/util/date-util.js b/web/assets/js/util/date-util.js deleted file mode 100644 index bbca1272..00000000 --- a/web/assets/js/util/date-util.js +++ /dev/null @@ -1,151 +0,0 @@ -const oneMinute = 1000 * 60; // MilliseConds in a Minute -const oneHour = oneMinute * 60; // The milliseconds of one hour -const oneDay = oneHour * 24; // The Number of MilliseConds A Day -const oneWeek = oneDay * 7; // The milliseconds per week -const oneMonth = oneDay * 30; // The milliseconds of a month - -/** - * Decrease according to the number of days - * - * @param days to reduce the number of days to be reduced - */ -Date.prototype.minusDays = function (days) { - return this.minusMillis(oneDay * days); -}; - -/** - * Increase according to the number of days - * - * @param days The number of days to be increased - */ -Date.prototype.plusDays = function (days) { - return this.plusMillis(oneDay * days); -}; - -/** - * A few - * - * @param hours to be reduced - */ -Date.prototype.minusHours = function (hours) { - return this.minusMillis(oneHour * hours); -}; - -/** - * Increase hourly - * - * @param hours to increase the number of hours - */ -Date.prototype.plusHours = function (hours) { - return this.plusMillis(oneHour * hours); -}; - -/** - * Make reduction in minutes - * - * @param minutes to reduce the number of minutes - */ -Date.prototype.minusMinutes = function (minutes) { - return this.minusMillis(oneMinute * minutes); -}; - -/** - * Add in minutes - * - * @param minutes to increase the number of minutes - */ -Date.prototype.plusMinutes = function (minutes) { - return this.plusMillis(oneMinute * minutes); -}; - -/** - * Decrease in milliseconds - * - * @param millis to reduce the milliseconds - */ -Date.prototype.minusMillis = function(millis) { - let time = this.getTime() - millis; - let newDate = new Date(); - newDate.setTime(time); - return newDate; -}; - -/** - * Add in milliseconds to increase - * - * @param millis to increase the milliseconds to increase - */ -Date.prototype.plusMillis = function(millis) { - let time = this.getTime() + millis; - let newDate = new Date(); - newDate.setTime(time); - return newDate; -}; - -/** - * Setting time is 00: 00: 00.000 on the day - */ -Date.prototype.setMinTime = function () { - this.setHours(0); - this.setMinutes(0); - this.setSeconds(0); - this.setMilliseconds(0); - return this; -}; - -/** - * Setting time is 23: 59: 59.999 on the same day - */ -Date.prototype.setMaxTime = function () { - this.setHours(23); - this.setMinutes(59); - this.setSeconds(59); - this.setMilliseconds(999); - return this; -}; - -/** - * Formatting date - */ -Date.prototype.formatDate = function () { - return this.getFullYear() + "-" + NumberFormatter.addZero(this.getMonth() + 1) + "-" + NumberFormatter.addZero(this.getDate()); -}; - -/** - * Format time - */ -Date.prototype.formatTime = function () { - return NumberFormatter.addZero(this.getHours()) + ":" + NumberFormatter.addZero(this.getMinutes()) + ":" + NumberFormatter.addZero(this.getSeconds()); -}; - -/** - * Formatting date plus time - * - * @param split Date and time separation symbols, default is a space - */ -Date.prototype.formatDateTime = function (split = ' ') { - return this.formatDate() + split + this.formatTime(); -}; - -class DateUtil { - // String to date object - static parseDate(str) { - return new Date(str.replace(/-/g, '/')); - } - - static formatMillis(millis) { - return moment(millis).format('YYYY-M-D HH:mm:ss'); - } - - static firstDayOfMonth() { - const date = new Date(); - date.setDate(1); - date.setMinTime(); - return date; - } - - static convertToJalalian(date) { - return date && moment.isMoment(date) ? date.format('jYYYY/jMM/jDD HH:mm:ss') : null; - } - -} diff --git a/web/assets/js/util/index.js b/web/assets/js/util/index.js index 902974f0..13bf68b1 100644 --- a/web/assets/js/util/index.js +++ b/web/assets/js/util/index.js @@ -882,4 +882,35 @@ class FileManager { link.remove(); } +} + +class IntlUtil { + static formatDate(date) { + const language = LanguageManager.getLanguage() + + let intlOptions = { + year: "numeric", + month: "numeric", + day: "numeric", + hour: "numeric", + minute: "numeric", + second: "numeric" + } + + const intl = new Intl.DateTimeFormat( + language, + intlOptions + ) + + return intl.format(new Date(date)) + } + static formatRelativeTime(date) { + const language = LanguageManager.getLanguage() + const now = new Date() + + const diff = Math.round((date - now) / (1000 * 60 * 60 * 24)) + const formatter = new Intl.RelativeTimeFormat(language, { numeric: 'auto' }) + + return formatter.format(diff, 'day'); + } }
\ No newline at end of file diff --git a/web/html/common/page.html b/web/html/common/page.html index f1c58fe1..c0a7ca63 100644 --- a/web/html/common/page.html +++ b/web/html/common/page.html @@ -44,7 +44,6 @@ <script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script> <script src="{{ .base_path }}assets/qs/qs.min.js"></script> <script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script> -<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script> <script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script> <script> const basePath = '{{ .base_path }}'; diff --git a/web/html/component/aClientTable.html b/web/html/component/aClientTable.html index f28b821b..d9a9b5f5 100644 --- a/web/html/component/aClientTable.html +++ b/web/html/component/aClientTable.html @@ -111,20 +111,12 @@ <template v-if="client.expiryTime !=0 && client.reset >0"> <a-popover :overlay-class-name="themeSwitcher.currentTheme"> <template slot="content"> - <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }} - </span> - <span v-else> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client._expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]] - </template> - </span> + <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span> + <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span> </template> <table> <tr class="tr-table-box"> - <td class="tr-table-rt"> [[ remainedDays(client.expiryTime) ]] </td> + <td class="tr-table-rt"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </td> <td class="infinite-bar tr-table-bar"> <a-progress :show-info="false" :status="isClientDepleted(record, client.email)? 'exception' : ''" :percent="expireProgress(client.expiryTime, client.reset)" /> </td> @@ -136,18 +128,10 @@ <template v-else> <a-popover v-if="client.expiryTime != 0" :overlay-class-name="themeSwitcher.currentTheme"> <template slot="content"> - <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }} - </span> - <span v-else> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client._expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]] - </template> - </span> + <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span> + <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span> </template> - <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ remainedDays(client.expiryTime) ]] </a-tag> + <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </a-tag> </a-popover> <a-tag v-else :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)" :style="{ border: 'none' }" class="infinite-tag"> <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor"> @@ -232,20 +216,12 @@ </tr> <tr> <template v-if="client.expiryTime !=0 && client.reset >0"> - <td width="80px" :style="{ margin: '0', textAlign: 'right', fontSize: '1em' }"> [[ remainedDays(client.expiryTime) ]] </td> + <td width="80px" :style="{ margin: '0', textAlign: 'right', fontSize: '1em' }"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </td> <td width="120px" class="infinite-bar"> <a-popover :overlay-class-name="themeSwitcher.currentTheme"> <template slot="content"> - <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }} - </span> - <span v-else> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client._expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]] - </template> - </span> + <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span> + <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span> </template> <a-progress :show-info="false" :status="isClientDepleted(record, client.email)? 'exception' : ''" :percent="expireProgress(client.expiryTime, client.reset)" /> </a-popover> @@ -256,18 +232,10 @@ <td colspan="3" :style="{ textAlign: 'center' }"> <a-popover v-if="client.expiryTime != 0" :overlay-class-name="themeSwitcher.currentTheme"> <template slot="content"> - <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }} - </span> - <span v-else> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client._expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]] - </template> - </span> + <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span> + <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span> </template> - <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ remainedDays(client.expiryTime) ]] </a-tag> + <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </a-tag> </a-popover> <a-tag v-else :color="client.enable ? 'purple' : themeSwitcher.isDarkTheme ? '#2c3950' : '#bcbcbc'" class="infinite-tag"> <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor"> @@ -289,12 +257,7 @@ </template> <template slot="createdAt" slot-scope="text, client, index"> <template v-if="client.created_at"> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client.created_at) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client.created_at)) ]] - </template> + [[ IntlUtil.formatDate(client.created_at) ]] </template> <template v-else> - @@ -302,12 +265,7 @@ </template> <template slot="updatedAt" slot-scope="text, client, index"> <template v-if="client.updated_at"> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(client.updated_at) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(client.updated_at)) ]] - </template> + [[ IntlUtil.formatDate(client.updated_at) ]] </template> <template v-else> - diff --git a/web/html/form/inbound.html b/web/html/form/inbound.html index 00f97f6e..fdd381b0 100644 --- a/web/html/form/inbound.html +++ b/web/html/form/inbound.html @@ -52,9 +52,7 @@ <br v-if="dbInbound.lastTrafficResetTime && dbInbound.lastTrafficResetTime > 0"> <span v-if="dbInbound.lastTrafficResetTime && dbInbound.lastTrafficResetTime > 0"> <strong>{{ i18n "pages.inbounds.lastReset" }}:</strong> - <span v-if="datepicker == 'gregorian'">[[ - moment(dbInbound.lastTrafficResetTime).format('YYYY-MM-DD HH:mm:ss') ]]</span> - <span v-else>[[ DateUtil.convertToJalalian(moment(dbInbound.lastTrafficResetTime)) ]]</span> + <span>[[ IntlUtil.formatDate(dbInbound.lastTrafficResetTime) ]]</span> </span> </template> {{ i18n "pages.inbounds.periodicTrafficResetTitle" }} diff --git a/web/html/inbounds.html b/web/html/inbounds.html index 8616dce5..86bde2c8 100644 --- a/web/html/inbounds.html +++ b/web/html/inbounds.html @@ -384,15 +384,12 @@ </template> <template slot="expiryTime" slot-scope="text, dbInbound"> <a-popover v-if="dbInbound.expiryTime > 0" :overlay-class-name="themeSwitcher.currentTheme"> - <template slot="content" v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(dbInbound.expiryTime) ]] - </template> - <template v-else slot="content"> - [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]] + <template slot="content"> + [[ IntlUtil.formatDate(dbInbound.expiryTime) ]] </template> <a-tag :style="{ minWidth: '50px' }" :color="ColorUtils.usageColor(new Date().getTime(), app.expireDiff, dbInbound._expiryTime)"> - [[ remainedDays(dbInbound._expiryTime) ]] + [[ IntlUtil.formatRelativeTime(dbInbound.expiryTime) ]] </a-tag> </a-popover> <a-tag v-else color="purple" class="infinite-tag"> @@ -549,12 +546,7 @@ <td> <a-tag :style="{ minWidth: '50px', textAlign: 'center' }" v-if="dbInbound.expiryTime > 0" :color="dbInbound.isExpiry? 'red': 'blue'"> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(dbInbound.expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]] - </template> + [[ IntlUtil.formatDate(dbInbound.expiryTime) ]] </a-tag> <a-tag v-else :style="{ textAlign: 'center' }" color="purple" class="infinite-tag"> <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor"> @@ -1407,13 +1399,6 @@ if (remainedSeconds >= resetSeconds) return 0; return 100 * (1 - (remainedSeconds / resetSeconds)); }, - remainedDays(expTime) { - if (expTime == 0) return null; - if (expTime < 0) return TimeFormatter.formatSecond(expTime / -1000); - now = new Date().getTime(); - if (expTime < now) return '{{ i18n "depleted" }}'; - return TimeFormatter.formatSecond((expTime - now) / 1000); - }, statsExpColor(dbInbound, email) { if (email.length == 0) return '#7a316f'; clientStats = dbInbound.clientStats.find(stats => stats.email === email); @@ -1458,10 +1443,7 @@ formatLastOnline(email) { const ts = this.getLastOnline(email) if (!ts) return '-' - if (this.datepicker === 'gregorian') { - return DateUtil.formatMillis(ts) - } - return DateUtil.convertToJalalian(moment(ts)) + return IntlUtil.formatDate(ts) }, isRemovable(dbInboundId) { return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1; diff --git a/web/html/index.html b/web/html/index.html index 1c6bb0be..9cbb019d 100644 --- a/web/html/index.html +++ b/web/html/index.html @@ -844,11 +844,9 @@ text = `<td>${log.Email}</td>`; } - const { locale, timeZone } = Intl.DateTimeFormat().resolvedOptions(); - formattedLogs += ` <tr ${outboundColor}> - <td><b>${new Date(log.DateTime).toLocaleString(locale, { timeZone })}</b></td> + <td><b>${IntlUtil.formatDate(log.DateTime)}</b></td> <td>${log.FromAddress}</td> <td>${log.ToAddress}</td> <td>${log.Inbound}</td> diff --git a/web/html/modals/inbound_info_modal.html b/web/html/modals/inbound_info_modal.html index 8e4bfc2e..72023e75 100644 --- a/web/html/modals/inbound_info_modal.html +++ b/web/html/modals/inbound_info_modal.html @@ -199,12 +199,7 @@ <td>{{ i18n "pages.inbounds.createdAt" }}</td> <td> <template v-if="infoModal.clientSettings && infoModal.clientSettings.created_at"> - <template v-if="app.datepicker === 'gregorian'"> - <a-tag>[[ DateUtil.formatMillis(infoModal.clientSettings.created_at) ]]</a-tag> - </template> - <template v-else> - <a-tag>[[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.created_at)) ]]</a-tag> - </template> + <a-tag>[[ IntlUtil.formatDate(infoModal.clientSettings.created_at) ]]</a-tag> </template> <template v-else> <a-tag>-</a-tag> @@ -215,12 +210,7 @@ <td>{{ i18n "pages.inbounds.updatedAt" }}</td> <td> <template v-if="infoModal.clientSettings && infoModal.clientSettings.updated_at"> - <template v-if="app.datepicker === 'gregorian'"> - <a-tag>[[ DateUtil.formatMillis(infoModal.clientSettings.updated_at) ]]</a-tag> - </template> - <template v-else> - <a-tag>[[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.updated_at)) ]]</a-tag> - </template> + <a-tag>[[ IntlUtil.formatDate(infoModal.clientSettings.updated_at) ]]</a-tag> </template> <template v-else> <a-tag>-</a-tag> @@ -282,12 +272,7 @@ <td> <template v-if="infoModal.clientSettings.expiryTime > 0"> <a-tag :color="ColorUtils.usageColor(new Date().getTime(), app.expireDiff, infoModal.clientSettings.expiryTime)"> - <template v-if="app.datepicker === 'gregorian'"> - [[ DateUtil.formatMillis(infoModal.clientSettings.expiryTime) ]] - </template> - <template v-else> - [[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.expiryTime)) ]] - </template> + [[ IntlUtil.formatDate(infoModal.clientSettings.expiryTime) ]] </a-tag> </template> <a-tag v-else-if="infoModal.clientSettings.expiryTime < 0" color="green">[[ infoModal.clientSettings.expiryTime / -86400000 ]] {{ i18n "pages.client.days" }} diff --git a/web/html/settings/panel/subscription/subpage.html b/web/html/settings/panel/subscription/subpage.html index 670cc37b..0043d0d2 100644 --- a/web/html/settings/panel/subscription/subpage.html +++ b/web/html/settings/panel/subscription/subpage.html @@ -4,7 +4,6 @@ <script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script> <script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script> <script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script> -<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script> <script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script> {{ template "page/head_end" .}} @@ -141,17 +140,7 @@ <a-descriptions-item label='{{ i18n "lastOnline" }}'> <template v-if="app.lastOnlineMs > 0"> - <template - v-if="app.datepicker === 'gregorian'"> - [[ - DateUtil.formatMillis(app.lastOnlineMs) - ]] - </template> - <template v-else> - [[ - DateUtil.convertToJalalian(moment(app.lastOnlineMs)) - ]] - </template> + [[ IntlUtil.formatDate(app.lastOnlineMs) ]] </template> <template v-else> <span>-</span> @@ -163,17 +152,7 @@ {{ i18n "subscription.noExpiry" }} </template> <template v-else> - <template - v-if="app.datepicker === 'gregorian'"> - [[ - DateUtil.formatMillis(app.expireMs) - ]] - </template> - <template v-else> - [[ - DateUtil.convertToJalalian(moment(app.expireMs)) - ]] - </template> + [[ IntlUtil.formatDate(app.expireMs) ]] </template> </a-descriptions-item> </a-descriptions> |
