This commit is contained in:
47
src/components/MarkdownViewver.vue
Normal file
47
src/components/MarkdownViewver.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<q-markdown
|
||||
:src="markdownContent"
|
||||
no-heading-anchor-links
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
locale: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
documentName: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
// Импорт всех Markdown-файлов как raw-строк
|
||||
const mdFiles = import.meta.glob('assets/docs/*.md', {
|
||||
query: '?raw',
|
||||
import: 'default',
|
||||
eager: true
|
||||
})
|
||||
|
||||
const markdownContent = computed(() => {
|
||||
const baseLang = props.locale.split('-')[0]?.toLowerCase()
|
||||
|
||||
// Формируем имена файлов
|
||||
const localizedFileName = `${props.documentName}_${baseLang}.md`
|
||||
const fallbackFileName = `${props.documentName}_en.md`
|
||||
|
||||
// Находим пути к файлам
|
||||
const filePaths = Object.keys(mdFiles)
|
||||
const localizedPath = filePaths.find(path => path.endsWith(localizedFileName))
|
||||
const fallbackPath = filePaths.find(path => path.endsWith(fallbackFileName))
|
||||
|
||||
// Возвращаем контент в порядке приоритета
|
||||
if (localizedPath) return mdFiles[localizedPath]
|
||||
if (fallbackPath) return mdFiles[fallbackPath]
|
||||
|
||||
return `# Document load error\n> Missing files for ${props.documentName}`
|
||||
})
|
||||
</script>
|
||||
@@ -10,7 +10,7 @@
|
||||
<q-step
|
||||
:name="1"
|
||||
:title="$t('account_helper__enter_email')"
|
||||
:done="step > 1"
|
||||
:done="step>1"
|
||||
>
|
||||
<q-input
|
||||
v-model="login"
|
||||
@@ -23,7 +23,7 @@
|
||||
no-error-icon
|
||||
@focus="($refs.emailInput as typeof QInput)?.resetValidation()"
|
||||
ref="emailInput"
|
||||
:disable="type === 'changePwd'"
|
||||
:disable="type==='changePwd'"
|
||||
/>
|
||||
<q-stepper-navigation>
|
||||
<q-btn
|
||||
@@ -31,6 +31,8 @@
|
||||
color="primary"
|
||||
:label="$t('continue')"
|
||||
:disabled="!isEmailValid"
|
||||
:unelevated="!isEmailValid"
|
||||
class="fix-disabled-btn"
|
||||
/>
|
||||
</q-stepper-navigation>
|
||||
</q-step>
|
||||
@@ -38,7 +40,7 @@
|
||||
<q-step
|
||||
:name="2"
|
||||
:title="$t('account_helper__confirm_email')"
|
||||
:done="step > 2"
|
||||
:done="step>2"
|
||||
>
|
||||
<div class="q-pb-md">{{$t('account_helper__confirm_email_message')}}</div>
|
||||
<q-input
|
||||
@@ -55,11 +57,13 @@
|
||||
@click="handleSubmit"
|
||||
color="primary"
|
||||
:label="$t('continue')"
|
||||
:disable="code.length === 0"
|
||||
:disable="code.length===0"
|
||||
:unelevated="code.length===0"
|
||||
class="fix-disabled-btn"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
@click="step = 1"
|
||||
@click="step=1"
|
||||
color="primary"
|
||||
:label="$t('back')"
|
||||
class="q-ml-sm"
|
||||
@@ -76,7 +80,7 @@
|
||||
dense
|
||||
filled
|
||||
autofocus
|
||||
:label = "$t('account_helper__password')"
|
||||
:label="$t('account_helper__password')"
|
||||
:type="isPwd ? 'password' : 'text'"
|
||||
hide-hint
|
||||
:hint="passwordHint"
|
||||
@@ -91,7 +95,7 @@
|
||||
color="grey-5"
|
||||
:name="isPwd ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
|
||||
class="cursor-pointer"
|
||||
@click="isPwd = !isPwd"
|
||||
@click="isPwd=!isPwd"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
@@ -101,11 +105,13 @@
|
||||
@click="handleSubmit"
|
||||
color="primary"
|
||||
:label="$t('account_helper__finish')"
|
||||
:disabled = "!isPasswordValid"
|
||||
:disabled="!isPasswordValid"
|
||||
:unelevated="!isPasswordValid"
|
||||
class="fix-disabled-btn"
|
||||
/>
|
||||
<q-btn
|
||||
flat
|
||||
@click="step = 2"
|
||||
@click="step=2"
|
||||
color="primary"
|
||||
:label="$t('back')"
|
||||
class="q-ml-sm"
|
||||
|
||||
@@ -4,79 +4,40 @@
|
||||
{{ $t(type + '__title') }}
|
||||
</template>
|
||||
<pn-scroll-list>
|
||||
<div class="q-px-md">
|
||||
<div
|
||||
v-if="fileText"
|
||||
style="white-space: pre-wrap;"
|
||||
>
|
||||
{{ fileText }}
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
align="center"
|
||||
class="text-negative"
|
||||
>
|
||||
{{ $t(type + '__not_ready') }}
|
||||
</div>
|
||||
</div>
|
||||
<markdown-viewver
|
||||
class="q-pa-md"
|
||||
:locale
|
||||
:documentName = "getDocumentName()"
|
||||
/>
|
||||
</pn-scroll-list>
|
||||
<div
|
||||
class="flex column justify-center items-center w100"
|
||||
style="position: absolute; bottom: 0;"
|
||||
v-if="isLoading"
|
||||
>
|
||||
<q-linear-progress indeterminate />
|
||||
</div>
|
||||
</pn-page-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useSettingsStore } from 'stores/settings'
|
||||
import MarkdownViewver from 'components/MarkdownViewver.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
type: 'terms_of_use' | 'privacy'
|
||||
type: 'terms_of_use' | 'privacy' | 'consent'
|
||||
}>()
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
const fileText = ref<string | null>('')
|
||||
const isLoading = ref(true)
|
||||
const DEFAULT_LANG = 'ru'
|
||||
const DEFAULT_LOCALE = 'ru'
|
||||
const locale = ref('ru')
|
||||
|
||||
const baseDocName = props.type === 'terms_of_use'
|
||||
? 'Terms_of_use'
|
||||
: 'Privacy'
|
||||
|
||||
const parseLocale = (locale: string) => locale.split(/[-_]/)[0] || DEFAULT_LANG
|
||||
|
||||
const fetchDocument = async (language: string) => {
|
||||
try {
|
||||
const response = await fetch(`/admin/doc/${baseDocName}_${language}.txt`)
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
||||
return await response.text()
|
||||
} catch (error) {
|
||||
console.error(`Failed to load ${language} version:`, error)
|
||||
return null
|
||||
const getDocumentName = () =>{
|
||||
switch(props.type) {
|
||||
case 'terms_of_use': return 'Terms_of_use'
|
||||
case 'privacy': return 'Privacy-Policy'
|
||||
case 'consent': return 'Consent_to_Personal_Data_Processing'
|
||||
}
|
||||
}
|
||||
|
||||
const parseLocale = (locale: string) => locale.split(/[-_]/)[0] || DEFAULT_LOCALE
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const lang = parseLocale(settingsStore.settings.locale)
|
||||
|
||||
fileText.value = await fetchDocument(lang)
|
||||
|
||||
if (!fileText.value && lang !== DEFAULT_LANG) {
|
||||
fileText.value = await fetchDocument(DEFAULT_LANG)
|
||||
}
|
||||
|
||||
if (!fileText.value) throw new Error('All loading attempts failed')
|
||||
|
||||
} catch (error) {
|
||||
console.error('Document loading failed:', error)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
onMounted(() => {
|
||||
locale.value = parseLocale(settingsStore.settings.locale)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<slot name="title"/>
|
||||
</div>
|
||||
<slot/>
|
||||
<div class="bg-white w100 q-ma-none q-px-md">
|
||||
<div class="bg-white w100 q-ma-none q-px-md flex items-center">
|
||||
<slot name="footer"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user