mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-04-16 12:35:54 +00:00
- Implemented a function to detect RTL languages and updated the Vue component to apply the appropriate class based on the language. - Enhanced the subscription page styles to support RTL layout, ensuring proper text alignment and direction for Arabic and Persian languages.
275 lines
No EOL
16 KiB
HTML
275 lines
No EOL
16 KiB
HTML
{{ template "page/head_start" .}}
|
|
<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
|
|
<script src="{{ .base_path }}assets/moment/moment-jalali.min.js?{{ .cur_ver }}"></script>
|
|
<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/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
|
<style>
|
|
.subscription-page.rtl {
|
|
direction: rtl;
|
|
}
|
|
|
|
.subscription-page.rtl .ant-descriptions-item-label {
|
|
text-align: right;
|
|
}
|
|
|
|
.subscription-page.rtl .ant-form-item-label > label {
|
|
float: right;
|
|
}
|
|
|
|
/* Keep technical URLs readable regardless of page direction */
|
|
.subscription-page.rtl .subscription-link-box {
|
|
direction: ltr;
|
|
text-align: left;
|
|
}
|
|
|
|
.subscription-page .subscription-link-box {
|
|
cursor: pointer;
|
|
border-radius: 12px;
|
|
padding: 25px 20px 15px 20px;
|
|
margin-top: -12px;
|
|
word-break: break-all;
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
text-align: left;
|
|
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
|
transition: all 0.3s;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.dark.subscription-page .subscription-link-box {
|
|
background: rgba(0, 0, 0, 0.2);
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
color: #fff;
|
|
}
|
|
|
|
.dark.subscription-page .subscription-link-box:hover {
|
|
background: rgba(0, 0, 0, 0.3);
|
|
border-color: rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.light.subscription-page .subscription-link-box {
|
|
background: rgba(0, 0, 0, 0.03);
|
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
color: rgba(0, 0, 0, 0.85);
|
|
}
|
|
|
|
.light.subscription-page .subscription-link-box:hover {
|
|
background: rgba(0, 0, 0, 0.05);
|
|
border-color: rgba(0, 0, 0, 0.14);
|
|
}
|
|
</style>
|
|
{{ template "page/head_end" .}}
|
|
|
|
{{ template "page/body_start" .}}
|
|
<a-layout id="app" v-cloak :class="[themeSwitcher.currentTheme, 'subscription-page', isRtl ? 'rtl' : 'ltr']"
|
|
:dir="isRtl ? 'rtl' : 'ltr'">
|
|
<a-layout-content class="p-2">
|
|
<a-row type="flex" justify="center" class="mt-2">
|
|
<a-col :xs="24" :sm="22" :md="18" :lg="14" :xl="12">
|
|
<a-card hoverable class="subscription-card">
|
|
<template #title>
|
|
<a-space>
|
|
<span>{{ i18n "subscription.title" }}</span>
|
|
<a-tag>{{ .sId }}</a-tag>
|
|
</a-space>
|
|
</template>
|
|
<template #extra>
|
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}'
|
|
placement="bottomRight" trigger="click">
|
|
<template #content>
|
|
<a-space direction="vertical" :size="10">
|
|
<a-theme-switch-login></a-theme-switch-login>
|
|
<span>{{ i18n "pages.settings.language"
|
|
}}</span>
|
|
<a-select ref="selectLang" class="w-100" v-model="lang"
|
|
@change="LanguageManager.setLanguage(lang)"
|
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
|
<a-select-option :value="l.value" label="English"
|
|
v-for="l in LanguageManager.supportedLanguages" :key="l.value">
|
|
<span role="img" :aria-label="l.name" v-text="l.icon"></span>
|
|
<span v-text="l.name"></span>
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-space>
|
|
</template>
|
|
<a-button shape="circle" icon="setting"></a-button>
|
|
</a-popover>
|
|
</template>
|
|
|
|
<a-form layout="vertical">
|
|
<a-form-item>
|
|
<a-space direction="vertical" align="center">
|
|
<a-row type="flex" :gutter="[8,8]" justify="center" style="width:100%">
|
|
<a-col :xs="24" :sm="app.subJsonUrl ? 12 : 24" style="text-align:center;">
|
|
<tr-qr-box class="qr-box">
|
|
<a-tag color="purple" class="qr-tag">
|
|
<span>{{ i18n
|
|
"pages.settings.subSettings"}}</span>
|
|
</a-tag>
|
|
<tr-qr-bg class="qr-bg-sub">
|
|
<tr-qr-bg-inner class="qr-bg-sub-inner">
|
|
<canvas id="qrcode" class="qr-cv" title='{{ i18n "copy" }}'
|
|
@click="copy(app.subUrl)"></canvas>
|
|
</tr-qr-bg-inner>
|
|
</tr-qr-bg>
|
|
</tr-qr-box>
|
|
</a-col>
|
|
<a-col v-if="app.subJsonUrl" :xs="24" :sm="12" style="text-align:center;">
|
|
<tr-qr-box class="qr-box">
|
|
<a-tag color="purple" class="qr-tag">
|
|
<span>{{ i18n
|
|
"pages.settings.subSettings"}}
|
|
Json</span>
|
|
</a-tag>
|
|
<tr-qr-bg class="qr-bg-sub">
|
|
<tr-qr-bg-inner class="qr-bg-sub-inner">
|
|
<canvas id="qrcode-subjson" class="qr-cv" title='{{ i18n "copy" }}'
|
|
@click="copy(app.subJsonUrl)"></canvas>
|
|
</tr-qr-bg-inner>
|
|
</tr-qr-bg>
|
|
</tr-qr-box>
|
|
</a-col>
|
|
</a-row>
|
|
</a-space>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<a-descriptions bordered :column="1" size="small">
|
|
<a-descriptions-item label='{{ i18n "subscription.subId" }}'>[[
|
|
app.sId
|
|
]]</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "subscription.status" }}'>
|
|
<template v-if="isUnlimited">
|
|
<a-tag color="purple">{{ i18n
|
|
"subscription.unlimited" }}</a-tag>
|
|
</template>
|
|
<template v-else>
|
|
<a-tag :color="isActive ? 'green' : 'red'">[[
|
|
isActive ? '{{ i18n
|
|
"subscription.active" }}' : '{{ i18n
|
|
"subscription.inactive" }}'
|
|
]]</a-tag>
|
|
</template>
|
|
</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "subscription.downloaded" }}'>[[
|
|
app.download
|
|
]]</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "subscription.uploaded" }}'>[[
|
|
app.upload
|
|
]]</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "usage" }}'>[[ app.used
|
|
]]</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "subscription.totalQuota" }}'>[[
|
|
app.total
|
|
]]</a-descriptions-item>
|
|
<a-descriptions-item v-if="app.totalByte > 0" label='{{ i18n "remained" }}'>[[
|
|
app.remained ]]</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "lastOnline" }}'>
|
|
<template v-if="app.lastOnlineMs > 0">
|
|
[[ IntlUtil.formatDate(app.lastOnlineMs) ]]
|
|
</template>
|
|
<template v-else>
|
|
<span>-</span>
|
|
</template>
|
|
</a-descriptions-item>
|
|
<a-descriptions-item label='{{ i18n "subscription.expiry" }}'>
|
|
<template v-if="app.expireMs === 0">
|
|
{{ i18n "subscription.noExpiry" }}
|
|
</template>
|
|
<template v-else>
|
|
[[ IntlUtil.formatDate(app.expireMs) ]]
|
|
</template>
|
|
</a-descriptions-item>
|
|
</a-descriptions>
|
|
</a-form-item>
|
|
</a-form>
|
|
|
|
<br />
|
|
<div v-for="(link, idx) in links" :key="link"
|
|
style="position: relative; margin-bottom: 20px; text-align: center;">
|
|
<div class="qr-box" style="display: inline-block; width: 100%; max-width: 100%;">
|
|
<a-tag color="purple"
|
|
style="margin-bottom: -10px; position: relative; z-index: 2; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">
|
|
<span>[[ linkName(link, idx) ]]</span>
|
|
</a-tag>
|
|
<div @click="copy(link)" class="subscription-link-box">
|
|
[[ link ]]
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<br />
|
|
|
|
<a-form layout="vertical">
|
|
<a-form-item>
|
|
<a-row type="flex" justify="center" :gutter="[8,8]" style="width:100%">
|
|
<a-col :xs="24" :sm="12" style="text-align:center;">
|
|
<!-- Android dropdown -->
|
|
<a-dropdown :trigger="['click']">
|
|
<a-button icon="android" :block="isMobile"
|
|
:style="{ marginTop: isMobile ? '6px' : 0 }" size="large" type="primary">
|
|
Android <a-icon type="down" />
|
|
</a-button>
|
|
<a-menu slot="overlay" :class="themeSwitcher.currentTheme">
|
|
<a-menu-item key="android-v2box"
|
|
@click="open('v2box://install-sub?url=' + encodeURIComponent(app.subUrl) + '&name=' + encodeURIComponent(app.sId))">V2Box</a-menu-item>
|
|
<a-menu-item key="android-v2rayng"
|
|
@click="open('v2rayng://install-config?url=' + encodeURIComponent(app.subUrl))">V2RayNG</a-menu-item>
|
|
<a-menu-item key="android-singbox"
|
|
@click="copy(app.subUrl)">Sing-box</a-menu-item>
|
|
<a-menu-item key="android-v2raytun"
|
|
@click="copy(app.subUrl)">V2RayTun</a-menu-item>
|
|
<a-menu-item key="android-npvtunnel" @click="copy(app.subUrl)">NPV
|
|
Tunnel</a-menu-item>
|
|
<a-menu-item key="android-happ"
|
|
@click="open('happ://add/' + app.subUrl)">Happ</a-menu-item>
|
|
</a-menu>
|
|
</a-dropdown>
|
|
</a-col>
|
|
<a-col :xs="24" :sm="12" style="text-align:center;">
|
|
<!-- iOS dropdown -->
|
|
<a-dropdown :trigger="['click']">
|
|
<a-button icon="apple" :block="isMobile"
|
|
:style="{ marginTop: isMobile ? '6px' : 0 }" size="large" type="primary">
|
|
iOS <a-icon type="down" />
|
|
</a-button>
|
|
<a-menu slot="overlay" :class="themeSwitcher.currentTheme">
|
|
<a-menu-item key="ios-shadowrocket"
|
|
@click="open(shadowrocketUrl)">Shadowrocket</a-menu-item>
|
|
<a-menu-item key="ios-v2box" @click="open(v2boxUrl)">V2Box</a-menu-item>
|
|
<a-menu-item key="ios-streisand"
|
|
@click="open(streisandUrl)">Streisand</a-menu-item>
|
|
<a-menu-item key="ios-v2raytun"
|
|
@click="copy(v2raytunUrl)">V2RayTun</a-menu-item>
|
|
<a-menu-item key="ios-npvtunnel" @click="copy(npvtunUrl)">NPV
|
|
Tunnel
|
|
</a-menu-item>
|
|
<a-menu-item key="ios-happ" @click="open(happUrl)">Happ</a-menu-item>
|
|
</a-menu>
|
|
</a-dropdown>
|
|
</a-col>
|
|
</a-row>
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-card>
|
|
</a-col>
|
|
</a-row>
|
|
</a-layout-content>
|
|
</a-layout>
|
|
|
|
<!-- Bootstrap data for external JS -->
|
|
<template id="subscription-data" data-sid="{{ .sId }}" data-sub-url="{{ .subUrl }}" data-subjson-url="{{ .subJsonUrl }}"
|
|
data-download="{{ .download }}" data-upload="{{ .upload }}" data-used="{{ .used }}" data-total="{{ .total }}"
|
|
data-remained="{{ .remained }}" data-expire="{{ .expire }}" data-lastonline="{{ .lastOnline }}"
|
|
data-downloadbyte="{{ .downloadByte }}" data-uploadbyte="{{ .uploadByte }}" data-totalbyte="{{ .totalByte }}"
|
|
data-datepicker="{{ .datepicker }}"></template>
|
|
<textarea id="subscription-links" style="display:none">{{ range .result }}{{ . }}
|
|
{{ end }}</textarea>
|
|
|
|
{{template "component/aThemeSwitch" .}}
|
|
<script src="{{ .base_path }}assets/js/subscription.js?{{ .cur_ver }}"></script>
|
|
|
|
{{ template "page/body_end" .}} |