Skip to content

Commit fdb0f3d

Browse files
committed
feat: expose MCP settings and HTML preview
1 parent b4c8aa8 commit fdb0f3d

9 files changed

Lines changed: 56 additions & 13 deletions

File tree

‎src/components/common/FileDetailModal.vue‎

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,21 @@
6565
</button>
6666
</div>
6767
<div v-else class="ml-2 flex flex-wrap gap-2">
68+
<a
69+
v-if="isHtmlPreviewable(record)"
70+
:href="getHtmlPreviewUrl(record)"
71+
target="_blank"
72+
rel="noopener noreferrer"
73+
class="rounded-xl px-4 py-2 text-sm font-semibold transition duration-300"
74+
:class="isDarkMode ? 'bg-zinc-200 text-zinc-950 hover:bg-zinc-100' : 'bg-zinc-800 text-white hover:bg-zinc-900'"
75+
>
76+
{{ t('fileRecord.preview') }}
77+
</a>
6878
<button
69-
v-if="isPreviewable(record)"
79+
v-else-if="isPreviewable(record)"
7080
type="button"
7181
class="rounded-xl px-4 py-2 text-sm font-semibold transition duration-300"
72-
:class="
73-
isDarkMode
74-
? 'bg-zinc-200 text-zinc-950 hover:bg-zinc-100'
75-
: 'bg-zinc-800 text-white hover:bg-zinc-900'
76-
"
82+
:class="isDarkMode ? 'bg-zinc-200 text-zinc-950 hover:bg-zinc-100' : 'bg-zinc-800 text-white hover:bg-zinc-900'"
7783
@click="$emit('preview-file')"
7884
>
7985
{{ t('fileRecord.preview') }}
@@ -132,7 +138,7 @@ import { useI18n } from 'vue-i18n'
132138
import { FileIcon, CalendarIcon, HardDriveIcon, DownloadIcon } from 'lucide-vue-next'
133139
import QRCode from 'qrcode.vue'
134140
import type { ReceivedFileRecord } from '@/types'
135-
import { buildDownloadUrl, buildReceivedRecordQrValue } from '@/utils/share-url'
141+
import { buildAbsoluteUrl, buildDownloadUrl, buildReceivedRecordQrValue } from '@/utils/share-url'
136142
137143
interface Props {
138144
visible: boolean
@@ -154,6 +160,14 @@ const getDownloadUrl = (record: ReceivedFileRecord) => {
154160
return buildDownloadUrl(record.downloadUrl)
155161
}
156162
163+
const isHtmlPreviewable = (record: ReceivedFileRecord) => {
164+
const extension = record.filename.split('.').pop()?.toLowerCase() || ''
165+
return Boolean(record.downloadUrl) && ['html', 'htm'].includes(extension)
166+
}
167+
168+
const getHtmlPreviewUrl = (record: ReceivedFileRecord) =>
169+
buildAbsoluteUrl(`/share/preview/html/${encodeURIComponent(record.code)}`)
170+
157171
const getQRCodeValue = (record: ReceivedFileRecord) => {
158172
return buildReceivedRecordQrValue(record)
159173
}
@@ -178,7 +192,9 @@ const isPreviewable = (record: ReceivedFileRecord) => {
178192
'wav',
179193
'm4a',
180194
'flac',
181-
'pdf'
195+
'pdf',
196+
'html',
197+
'htm'
182198
].includes(extension)
183199
}
184200
</script>

‎src/components/common/MediaPreviewModal.vue‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</h3>
1919
<div class="flex items-center gap-2">
2020
<a
21-
:href="previewUrl"
21+
:href="downloadUrl"
2222
target="_blank"
2323
rel="noopener noreferrer"
2424
class="rounded-xl px-3 py-1.5 text-sm font-semibold transition duration-300"
@@ -87,7 +87,7 @@ import { XIcon } from 'lucide-vue-next'
8787
import { useI18n } from 'vue-i18n'
8888
import { useInjectedDarkMode } from '@/composables'
8989
import type { ReceivedFileRecord } from '@/types'
90-
import { buildDownloadUrl } from '@/utils/share-url'
90+
import { buildAbsoluteUrl, buildDownloadUrl } from '@/utils/share-url'
9191
9292
interface Props {
9393
visible: boolean
@@ -102,10 +102,16 @@ defineEmits<{
102102
const { t } = useI18n()
103103
const isDarkMode = useInjectedDarkMode()
104104
105-
const previewUrl = computed(() =>
105+
const extension = computed(() => props.record?.filename.split('.').pop()?.toLowerCase() || '')
106+
const downloadUrl = computed(() =>
106107
props.record?.downloadUrl ? buildDownloadUrl(props.record.downloadUrl) : ''
107108
)
108-
const extension = computed(() => props.record?.filename.split('.').pop()?.toLowerCase() || '')
109+
const previewUrl = computed(() => {
110+
if (['html', 'htm'].includes(extension.value) && props.record?.code) {
111+
return buildAbsoluteUrl(`/share/preview/html/${encodeURIComponent(props.record.code)}`)
112+
}
113+
return downloadUrl.value
114+
})
109115
const mediaType = computed(() => {
110116
if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'].includes(extension.value)) return 'image'
111117
if (['mp4', 'webm', 'ogg', 'mov', 'm4v'].includes(extension.value)) return 'video'

‎src/composables/useSystemConfig.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
type SaveTimeUnit
1515
} from '@/utils/config-form'
1616

17-
type ConfigFlagKey = 'enable_chunk' | 's3_proxy' | 'open_upload' | 'show_admin_addr'
17+
type ConfigFlagKey = 'enable_chunk' | 's3_proxy' | 'open_upload' | 'show_admin_addr' | 'mcp_require_token'
1818

1919
const SECONDS_PER_DAY = 24 * 60 * 60
2020

‎src/i18n/locales/en-US.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ export default {
752752
allowedFileTypesPlaceholder: '* or .rar, .zip, image/*',
753753
allowedFileTypesHelp:
754754
'Separate multiple types with commas. * allows all; extensions and MIME wildcards are supported.',
755+
mcpRequireToken: 'Require admin token for MCP uploads',
756+
mcpRequireTokenHelp: 'When enabled, pass your admin login token as Authorization: Bearer when calling /mcp.',
755757
codeGenerateType: 'Passcode Rule',
756758
codeGenerateNumber: 'Numeric Passcode',
757759
codeGenerateSecret: 'Secret Passcode',

‎src/i18n/locales/zh-CN.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@ export default {
771771
allowedFileTypes: '允许上传类型',
772772
allowedFileTypesPlaceholder: '* 或 .rar, .zip, image/*',
773773
allowedFileTypesHelp: '多个类型用英文逗号分隔,* 表示不限制;支持扩展名和 MIME 通配。',
774+
mcpRequireToken: 'MCP 上传需要管理员 Token',
775+
mcpRequireTokenHelp: '启用后调用 /mcp 上传时,需在 Authorization: Bearer 中提供管理员登录 Token。',
774776
codeGenerateType: '取件码规则',
775777
codeGenerateNumber: '数字取件码',
776778
codeGenerateSecret: 'Secret 取件码',

‎src/types/config.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export interface ConfigState {
4545
storage_limit: number
4646
upload_minute: number
4747
max_save_seconds: number
48+
mcp_require_token: number
4849
opacity: number
4950
enable_chunk: number
5051
s3_access_key_id: string

‎src/utils/config-storage.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const DEFAULT_CONFIG_STATE: ConfigState = {
5454
storage_path: '',
5555
storage_limit: 0,
5656
upload_minute: 1,
57+
mcp_require_token: 0,
5758
max_save_seconds: DEFAULT_PUBLIC_CONFIG.max_save_seconds,
5859
opacity: 0.9,
5960
enable_chunk: DEFAULT_PUBLIC_CONFIG.enable_chunk,

‎src/views/manage/SystemSettingsView.vue‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,17 @@ onMounted(() => {
742742
<p class="text-xs" :class="[isDarkMode ? 'text-zinc-400' : 'text-zinc-500']">
743743
{{ t('manage.settings.codeGenerateTypeHelp') }}
744744
</p>
745+
746+
<SettingSwitch
747+
:label="t('manage.settings.mcpRequireToken')"
748+
:model-value="config.mcp_require_token"
749+
:enabled-text="t('common.enabled')"
750+
:disabled-text="t('common.disabled')"
751+
@toggle="toggleConfigFlag('mcp_require_token')"
752+
/>
753+
<p class="text-xs" :class="[isDarkMode ? 'text-zinc-400' : 'text-zinc-500']">
754+
{{ t('manage.settings.mcpRequireTokenHelp') }}
755+
</p>
745756
</div>
746757

747758
<div class="space-y-2">

‎vite.config.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ export default defineConfig({
4343
'@': fileURLToPath(new URL('./src', import.meta.url))
4444
}
4545
},
46+
build: {
47+
outDir: '../FileCodeBox/themes/2024',
48+
emptyOutDir: true
49+
},
4650
css: {
4751
postcss: {
4852
plugins: [tailwindcss, autoprefixer]

0 commit comments

Comments
 (0)