mirror of
https://github.com/xfgryujk/blivechat.git
synced 2026-08-19 09:43:28 +08:00
前端添加自定义模板配置
This commit is contained in:
@@ -9,3 +9,7 @@ export async function uploadEmoticon(file) {
|
||||
body.set('file', file)
|
||||
return (await axios.post('/api/emoticon', body)).data
|
||||
}
|
||||
|
||||
export async function getTemplates() {
|
||||
return (await axios.get('/api/templates')).data
|
||||
}
|
||||
|
||||
@@ -65,6 +65,13 @@ export default {
|
||||
addEmoticon: 'Add emote',
|
||||
emoticonFileTooLarge: 'File size is too large. Max size is 1MB',
|
||||
|
||||
template: 'Custom HTML Templates',
|
||||
templateDefaultTitle: 'Default',
|
||||
templateDefaultDescription: 'A YouTube-style template that can be styled with custom CSS. Choose this if you are unfamiliar with custom HTML templates, otherwise your custom CSS will not take effect',
|
||||
templateCustomUrlTitle: 'Enter template URL',
|
||||
templateCustomUrlDescription: 'For templates not listed, you can manually enter the URL provided by the author here',
|
||||
author: 'Author: ',
|
||||
|
||||
urlTooLong: 'The room URL is too long, and will be truncated by Livehime (but not by OBS)',
|
||||
roomUrlUpdated: 'The room URL is updated. Remember to copy it again',
|
||||
roomUrl: 'Room URL',
|
||||
|
||||
@@ -65,6 +65,13 @@ export default {
|
||||
addEmoticon: 'スタンプを追加',
|
||||
emoticonFileTooLarge: 'ファイルサイズが大きすぎます。最大サイズは1MBです',
|
||||
|
||||
template: 'カスタムHTMLテンプレート',
|
||||
templateDefaultTitle: 'デフォルト',
|
||||
templateDefaultDescription: 'YouTube風のテンプレートで、カスタムCSSでスタイルを変更できます。カスタムHTMLテンプレートの機能に慣れていない場合はこれを選択してください。そうでない場合、カスタムCSSが適用されない',
|
||||
templateCustomUrlTitle: 'テンプレートURLを入力',
|
||||
templateCustomUrlDescription: 'リストにないテンプレートは、作者が提供するURLをここで手動で入力できます',
|
||||
author: '作者:',
|
||||
|
||||
urlTooLong: 'ルームのURLが長すぎて、直播姬によって切り詰められます(ただし、OBSでは切り詰められません)',
|
||||
roomUrlUpdated: 'ルームのURLが更新されました。再度コピーすることをお忘れなく',
|
||||
roomUrl: 'ルームのURL',
|
||||
|
||||
@@ -65,6 +65,13 @@ export default {
|
||||
addEmoticon: '添加表情',
|
||||
emoticonFileTooLarge: '文件尺寸太大,最大1MB',
|
||||
|
||||
template: '自定义HTML模板',
|
||||
templateDefaultTitle: '默认',
|
||||
templateDefaultDescription: '仿YouTube风格的模板,可以用自定义CSS修改样式。如果你不了解自定义HTML模板的功能,就选择这个,否则自定义CSS不会生效',
|
||||
templateCustomUrlTitle: '输入模板URL',
|
||||
templateCustomUrlDescription: '没有列出的模板,也可以在这里手动输入作者提供的URL',
|
||||
author: '作者:',
|
||||
|
||||
urlTooLong: '房间URL太长了,会被直播姬截断(OBS不会)',
|
||||
roomUrlUpdated: '房间URL已更新,记得重新复制',
|
||||
roomUrl: '房间URL',
|
||||
|
||||
177
frontend/src/views/Home/TemplateSelect.vue
Normal file
177
frontend/src/views/Home/TemplateSelect.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-radio-group :value="selectedIndex" @input="onSelect">
|
||||
<el-radio :label="INDEX_DEFAULT" border>
|
||||
<div class="card-body">
|
||||
<div class="title-line">
|
||||
<h3 class="name">{{ $t('home.templateDefaultTitle') }}</h3>
|
||||
</div>
|
||||
<div class="description">{{ $t('home.templateDefaultDescription') }}</div>
|
||||
</div>
|
||||
</el-radio>
|
||||
|
||||
<el-radio :label="INDEX_CUSTOM" border>
|
||||
<div class="card-body">
|
||||
<div class="title-line">
|
||||
<h3 class="name">{{ $t('home.templateCustomUrlTitle') }}</h3>
|
||||
</div>
|
||||
<div class="description">{{ $t('home.templateCustomUrlDescription') }}</div>
|
||||
<div>
|
||||
<el-input v-model="customUrl" placeholder="https://example.com/path/to/you/template/index.html"></el-input>
|
||||
</div>
|
||||
</div>
|
||||
</el-radio>
|
||||
|
||||
<el-radio v-for="(template, index) in templates" :key="template.id" :label="index" border>
|
||||
<div class="card-body">
|
||||
<div class="title-line">
|
||||
<h3 class="name">{{ template.name }}</h3>
|
||||
<span class="version">{{ template.version }}</span>
|
||||
<span class="author push-inline-end">{{ $t('home.author') }}{{ template.author }}</span>
|
||||
</div>
|
||||
<div v-if="template.description !== ''" class="description">{{ template.description }}</div>
|
||||
<div>URL: {{ template.url }}</div>
|
||||
</div>
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as mainApi from '@/api/main'
|
||||
|
||||
const INDEX_DEFAULT = 'default'
|
||||
const INDEX_CUSTOM = 'custom'
|
||||
|
||||
export default {
|
||||
name: 'TemplateSelect',
|
||||
props: {
|
||||
value: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
INDEX_DEFAULT,
|
||||
INDEX_CUSTOM,
|
||||
|
||||
templates: [],
|
||||
customUrl: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectedIndex() {
|
||||
if (this.value == '') {
|
||||
return INDEX_DEFAULT
|
||||
}
|
||||
let index = this.templates.findIndex(template => template.url === this.value)
|
||||
if (index !== -1) {
|
||||
return index
|
||||
}
|
||||
return INDEX_CUSTOM
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (this.selectedIndex === INDEX_CUSTOM) {
|
||||
this.customUrl = val
|
||||
}
|
||||
}
|
||||
},
|
||||
customUrl(val) {
|
||||
if (this.selectedIndex === INDEX_CUSTOM) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.updateTemplates()
|
||||
},
|
||||
methods: {
|
||||
async updateTemplates() {
|
||||
try {
|
||||
this.templates = (await mainApi.getTemplates()).templates
|
||||
} catch (e) {
|
||||
this.$message.error(`Failed to fetch templates: ${e}`)
|
||||
throw e
|
||||
} finally {
|
||||
if (this.selectedIndex !== INDEX_CUSTOM) {
|
||||
this.customUrl = ''
|
||||
}
|
||||
}
|
||||
},
|
||||
onSelect(selectedIndex) {
|
||||
let url
|
||||
if (selectedIndex === INDEX_DEFAULT) {
|
||||
url = ''
|
||||
} else if (selectedIndex === INDEX_CUSTOM) {
|
||||
url = this.customUrl
|
||||
} else {
|
||||
url = this.templates[selectedIndex].url
|
||||
}
|
||||
this.$emit('input', url)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-radio-group {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.el-radio {
|
||||
display: block;
|
||||
height: unset;
|
||||
margin: 0 0 16px 0 !important;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.el-radio >>> .el-radio__input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-radio >>> .el-radio__label {
|
||||
padding-left: unset;
|
||||
}
|
||||
|
||||
.push-inline-end {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.card-body {
|
||||
max-height: 200px;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
|
||||
.title-line {
|
||||
margin-block-end: 1em;
|
||||
flex: none;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: baseline;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-block: 0 0;
|
||||
margin-inline-end: 8px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.version {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.author {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-block-end: 1em;
|
||||
flex: auto;
|
||||
overflow-y: auto;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
@@ -217,6 +217,10 @@
|
||||
<el-button type="primary" icon="el-icon-plus" @click="addEmoticon">{{$t('home.addEmoticon')}}</el-button>
|
||||
</p>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('home.template')" lazy>
|
||||
<template-select v-model="form.templateUrl"></template-select>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</p>
|
||||
@@ -249,12 +253,14 @@
|
||||
import _ from 'lodash'
|
||||
import download from 'downloadjs'
|
||||
|
||||
import TemplateSelect from './TemplateSelect'
|
||||
import { mergeConfig } from '@/utils'
|
||||
import * as mainApi from '@/api/main'
|
||||
import * as chatConfig from '@/api/chatConfig'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: { TemplateSelect },
|
||||
data() {
|
||||
return {
|
||||
serverConfig: {
|
||||
Reference in New Issue
Block a user