mirror of
https://github.com/xfgryujk/blivechat.git
synced 2024-12-27 13:20:29 +08:00
完成配置保存和读取
This commit is contained in:
parent
22e8f88533
commit
920e6fff96
275
frontend/src/api/config.js
Normal file
275
frontend/src/api/config.js
Normal file
@ -0,0 +1,275 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const DEFAULT_CSS = `@import url("https://fonts.googleapis.com/css?family=Changa%20One");
|
||||
@import url("https://fonts.googleapis.com/css?family=Imprima");
|
||||
/* @import url("https://fonts.lug.ustc.edu.cn/css?family=Changa%20One"); */
|
||||
/* @import url("https://fonts.lug.ustc.edu.cn/css?family=Imprima"); */
|
||||
|
||||
/* Background colors*/
|
||||
body {
|
||||
overflow: hidden;
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
/* Transparent background. */
|
||||
yt-live-chat-renderer {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-text-message-renderer[is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="owner"],
|
||||
yt-live-chat-text-message-renderer[author-type="owner"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"],
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="member"],
|
||||
yt-live-chat-text-message-renderer[author-type="member"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-author-chip #author-name {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* Outlines */
|
||||
yt-live-chat-renderer * {
|
||||
text-shadow: -2px -2px #000000,-2px -1px #000000,-2px 0px #000000,-2px 1px #000000,-2px 2px #000000,-1px -2px #000000,-1px -1px #000000,-1px 0px #000000,-1px 1px #000000,-1px 2px #000000,0px -2px #000000,0px -1px #000000,0px 0px #000000,0px 1px #000000,0px 2px #000000,1px -2px #000000,1px -1px #000000,1px 0px #000000,1px 1px #000000,1px 2px #000000,2px -2px #000000,2px -1px #000000,2px 0px #000000,2px 1px #000000,2px 2px #000000;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #content,
|
||||
yt-live-chat-legacy-paid-message-renderer #content {
|
||||
overflow: initial !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar. */
|
||||
yt-live-chat-item-list-renderer #items{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
yt-live-chat-item-list-renderer #item-scroller{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* Hide header and input. */
|
||||
yt-live-chat-header-renderer,
|
||||
yt-live-chat-message-input-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Reduce side padding. */
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #header {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
/* Avatars. */
|
||||
yt-live-chat-text-message-renderer #author-photo,
|
||||
yt-live-chat-paid-message-renderer #author-photo,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo {
|
||||
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
border-radius: 24px !important;
|
||||
margin-right: 6px !important;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* Hide badges. */
|
||||
yt-live-chat-text-message-renderer #author-badges {
|
||||
display: none !important;
|
||||
vertical-align: text-top !important;
|
||||
}
|
||||
|
||||
/* Timestamps. */
|
||||
yt-live-chat-text-message-renderer #timestamp {
|
||||
|
||||
color: #999999 !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 16px !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
/* Badges. */
|
||||
yt-live-chat-text-message-renderer #author-name[type="owner"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="owner"] {
|
||||
color: #ffd600 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="moderator"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="moderator"] {
|
||||
color: #5e84f1 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="member"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="member"] {
|
||||
color: #0f9d58 !important;
|
||||
}
|
||||
|
||||
/* Channel names. */
|
||||
yt-live-chat-text-message-renderer #author-name {
|
||||
color: #cccccc !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name::after {
|
||||
content: ":";
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
/* Messages. */
|
||||
yt-live-chat-text-message-renderer #message,
|
||||
yt-live-chat-text-message-renderer #message * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
|
||||
/* SuperChat/Fan Funding Messages. */
|
||||
yt-live-chat-paid-message-renderer #author-name,
|
||||
yt-live-chat-paid-message-renderer #author-name *,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #purchase-amount,
|
||||
yt-live-chat-paid-message-renderer #purchase-amount *,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #content,
|
||||
yt-live-chat-paid-message-renderer #content * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer {
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
background-color: #0f9d58 !important;
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer a,
|
||||
yt-live-chat-legacy-paid-message-renderer a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[is-deleted],
|
||||
yt-live-chat-legacy-paid-message-renderer[is-deleted] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-ticker-renderer {
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
yt-live-chat-ticker-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-ticker-paid-message-item-renderer,
|
||||
yt-live-chat-ticker-paid-message-item-renderer *,
|
||||
yt-live-chat-ticker-sponsor-item-renderer,
|
||||
yt-live-chat-ticker-sponsor-item-renderer * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
}
|
||||
|
||||
yt-live-chat-mode-change-message-renderer,
|
||||
yt-live-chat-viewer-engagement-message-renderer,
|
||||
yt-live-chat-restricted-participation-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
`
|
||||
|
||||
export const DEFAULT_CONFIG = {
|
||||
minGiftPrice: 6.911, // $1
|
||||
mergeSimilarDanmaku: true,
|
||||
|
||||
blockGiftDanmaku: true,
|
||||
blockLevel: 0,
|
||||
blockNewbie: true,
|
||||
blockNotMobileVerified: true,
|
||||
blockKeywords: '',
|
||||
blockUsers: '',
|
||||
|
||||
css: DEFAULT_CSS
|
||||
}
|
||||
|
||||
function mergeConfig (config) {
|
||||
let res = {}
|
||||
for (let i in DEFAULT_CONFIG) {
|
||||
res[i] = i in config ? config[i] : DEFAULT_CONFIG[i]
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
export function setLocalConfig (config) {
|
||||
config = mergeConfig(config)
|
||||
window.localStorage.config = JSON.stringify(config)
|
||||
}
|
||||
|
||||
export function getLocalConfig () {
|
||||
if (!window.localStorage.config) {
|
||||
return DEFAULT_CONFIG
|
||||
}
|
||||
return mergeConfig(JSON.parse(window.localStorage.config))
|
||||
}
|
||||
|
||||
export async function createRemoteConfig (config) {
|
||||
config = mergeConfig(config)
|
||||
return (await axios.post('/config', config)).data
|
||||
}
|
||||
|
||||
export async function setRemoteConfig (id, config) {
|
||||
config = mergeConfig(config)
|
||||
return (await axios.put(`/config/${id}`, config)).data
|
||||
}
|
||||
|
||||
export async function getRemoteConfig (id) {
|
||||
let config = (await axios.get(`/config/${id}`)).data
|
||||
return mergeConfig(config)
|
||||
}
|
||||
|
||||
export default {
|
||||
DEFAULT_CONFIG,
|
||||
setLocalConfig,
|
||||
getLocalConfig,
|
||||
createRemoteConfig,
|
||||
setRemoteConfig,
|
||||
getRemoteConfig
|
||||
}
|
@ -207,220 +207,3 @@ yt-live-chat-ticker-paid-message-item-renderer #fake-avatar {
|
||||
border-radius: 24px;
|
||||
|
||||
}
|
||||
|
||||
/* 以下为自动生成:https://chatv2.septapus.com/ */
|
||||
|
||||
/* @import url("https://fonts.googleapis.com/css?family=Changa%20One"); */
|
||||
/* @import url("https://fonts.googleapis.com/css?family=Imprima"); */
|
||||
@import url("https://fonts.lug.ustc.edu.cn/css?family=Changa%20One");
|
||||
@import url("https://fonts.lug.ustc.edu.cn/css?family=Imprima");
|
||||
|
||||
/* Background colors*/
|
||||
body {
|
||||
overflow: hidden;
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
/* Transparent background. */
|
||||
yt-live-chat-renderer {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-text-message-renderer[is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="owner"],
|
||||
yt-live-chat-text-message-renderer[author-type="owner"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"],
|
||||
yt-live-chat-text-message-renderer[author-type="moderator"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[author-type="member"],
|
||||
yt-live-chat-text-message-renderer[author-type="member"][is-highlighted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-author-chip #author-name {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* Outlines */
|
||||
yt-live-chat-renderer * {
|
||||
text-shadow: -2px -2px #000000,-2px -1px #000000,-2px 0px #000000,-2px 1px #000000,-2px 2px #000000,-1px -2px #000000,-1px -1px #000000,-1px 0px #000000,-1px 1px #000000,-1px 2px #000000,0px -2px #000000,0px -1px #000000,0px 0px #000000,0px 1px #000000,0px 2px #000000,1px -2px #000000,1px -1px #000000,1px 0px #000000,1px 1px #000000,1px 2px #000000,2px -2px #000000,2px -1px #000000,2px 0px #000000,2px 1px #000000,2px 2px #000000;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #content,
|
||||
yt-live-chat-legacy-paid-message-renderer #content {
|
||||
overflow: initial !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar. */
|
||||
yt-live-chat-item-list-renderer #items{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
yt-live-chat-item-list-renderer #item-scroller{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* Hide header and input. */
|
||||
yt-live-chat-header-renderer,
|
||||
yt-live-chat-message-input-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Reduce side padding. */
|
||||
yt-live-chat-text-message-renderer,
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #header {
|
||||
padding-left: 4px !important;
|
||||
padding-right: 4px !important;
|
||||
}
|
||||
|
||||
/* Avatars. */
|
||||
yt-live-chat-text-message-renderer #author-photo,
|
||||
yt-live-chat-paid-message-renderer #author-photo,
|
||||
yt-live-chat-legacy-paid-message-renderer #author-photo {
|
||||
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
border-radius: 24px !important;
|
||||
margin-right: 6px !important;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
/* Hide badges. */
|
||||
yt-live-chat-text-message-renderer #author-badges {
|
||||
display: none !important;
|
||||
vertical-align: text-top !important;
|
||||
}
|
||||
|
||||
/* Timestamps. */
|
||||
yt-live-chat-text-message-renderer #timestamp {
|
||||
|
||||
color: #999999 !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 16px !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
/* Badges. */
|
||||
yt-live-chat-text-message-renderer #author-name[type="owner"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="owner"] {
|
||||
color: #ffd600 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="moderator"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="moderator"] {
|
||||
color: #5e84f1 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name[type="member"],
|
||||
yt-live-chat-text-message-renderer yt-live-chat-author-badge-renderer[type="member"] {
|
||||
color: #0f9d58 !important;
|
||||
}
|
||||
|
||||
/* Channel names. */
|
||||
yt-live-chat-text-message-renderer #author-name {
|
||||
color: #cccccc !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer #author-name::after {
|
||||
content: ":";
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
/* Messages. */
|
||||
yt-live-chat-text-message-renderer #message,
|
||||
yt-live-chat-text-message-renderer #message * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
|
||||
/* SuperChat/Fan Funding Messages. */
|
||||
yt-live-chat-paid-message-renderer #author-name,
|
||||
yt-live-chat-paid-message-renderer #author-name *,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #event-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Changa One";
|
||||
font-size: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #purchase-amount,
|
||||
yt-live-chat-paid-message-renderer #purchase-amount *,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text,
|
||||
yt-live-chat-legacy-paid-message-renderer #detail-text * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer #content,
|
||||
yt-live-chat-paid-message-renderer #content * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
font-size: 18px !important;
|
||||
line-height: 18px !important;
|
||||
}
|
||||
|
||||
yt-live-chat-paid-message-renderer {
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-legacy-paid-message-renderer {
|
||||
background-color: #0f9d58 !important;
|
||||
margin: 4px 0 !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer a,
|
||||
yt-live-chat-legacy-paid-message-renderer a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-text-message-renderer[is-deleted],
|
||||
yt-live-chat-legacy-paid-message-renderer[is-deleted] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
yt-live-chat-ticker-renderer {
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
yt-live-chat-ticker-renderer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
yt-live-chat-ticker-paid-message-item-renderer,
|
||||
yt-live-chat-ticker-paid-message-item-renderer *,
|
||||
yt-live-chat-ticker-sponsor-item-renderer,
|
||||
yt-live-chat-ticker-sponsor-item-renderer * {
|
||||
color: #ffffff !important;
|
||||
font-family: "Imprima";
|
||||
}
|
||||
|
||||
yt-live-chat-mode-change-message-renderer,
|
||||
yt-live-chat-viewer-engagement-message-renderer,
|
||||
yt-live-chat-restricted-participation-renderer {
|
||||
display: none !important;
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.1 KiB |
@ -2,6 +2,7 @@ import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import axios from 'axios'
|
||||
|
||||
import App from './App.vue'
|
||||
import Layout from './layout'
|
||||
@ -10,6 +11,11 @@ import StyleGenerator from './views/StyleGenerator.vue'
|
||||
import Room from './views/Room'
|
||||
import NotFound from './views/NotFound.vue'
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// 开发时使用localhost:80
|
||||
axios.defaults.baseURL = 'http://localhost'
|
||||
}
|
||||
|
||||
Vue.use(VueRouter)
|
||||
Vue.use(ElementUI)
|
||||
|
||||
|
@ -43,52 +43,68 @@
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-divider></el-divider>
|
||||
<el-form-item label="房间URL" v-show="roomUrl">
|
||||
<el-input ref="roomUrlInput" readonly :value="roomUrl" style="width: calc(100% - 6em); margin-right: 1em;"></el-input>
|
||||
<el-button type="primary" @click="copyUrl">复制</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="enterRoom">进入房间</el-button>
|
||||
<el-button type="primary" @click="popupRoom">弹出房间</el-button>
|
||||
<el-button type="primary" @click="saveConfig()">保存配置</el-button>
|
||||
<el-button type="primary" :disabled="!roomUrl" @click="enterRoom">进入房间</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/api/config'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
roomId: parseInt(window.localStorage.roomId || '1'),
|
||||
minGiftPrice: 6.911, // $1
|
||||
mergeSimilarDanmaku: true,
|
||||
|
||||
blockGiftDanmaku: true,
|
||||
blockLevel: 0,
|
||||
blockNewbie: true,
|
||||
blockNotMobileVerified: true,
|
||||
blockKeywords: '',
|
||||
blockUsers: '',
|
||||
|
||||
css: ''
|
||||
}
|
||||
...config.getLocalConfig()
|
||||
},
|
||||
roomUrl: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
saveConfig(callback) {
|
||||
this.$refs.form.validate(valid => {
|
||||
saveConfig() {
|
||||
this.$refs.form.validate(async valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
window.localStorage.roomId = this.form.roomId
|
||||
callback()
|
||||
config.setLocalConfig(this.form)
|
||||
|
||||
try {
|
||||
if (window.localStorage.configId) {
|
||||
try {
|
||||
await config.setRemoteConfig(window.localStorage.configId, this.form)
|
||||
} catch (e) { // 404
|
||||
window.localStorage.configId = (await config.createRemoteConfig(this.form)).id
|
||||
}
|
||||
} else {
|
||||
window.localStorage.configId = (await config.createRemoteConfig(this.form)).id
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error('保存失败:' + e)
|
||||
return
|
||||
}
|
||||
this.$message({message: '保存成功', type: 'success'})
|
||||
|
||||
let resolved = this.$router.resolve({name: 'room', params: {roomId: this.form.roomId},
|
||||
query: {config_id: window.localStorage.configId}})
|
||||
this.roomUrl = `http://${window.location.host}${resolved.href}`
|
||||
})
|
||||
},
|
||||
enterRoom() {
|
||||
this.saveConfig(() => this.$router.push({name: 'room', params: {roomId: this.form.roomId}}))
|
||||
window.open(this.roomUrl, `room ${this.form.roomId}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||
},
|
||||
popupRoom() {
|
||||
this.saveConfig(() => {
|
||||
let resolved = this.$router.resolve({name: 'room', params: {roomId: this.form.roomId}})
|
||||
window.open(resolved.href, `room ${this.form.roomId}`, 'menubar=0,location=0,scrollbars=0,toolbar=0,width=600,height=600')
|
||||
})
|
||||
copyUrl() {
|
||||
this.$refs.roomUrlInput.select()
|
||||
document.execCommand('Copy')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/api/config'
|
||||
import TextMessage from './TextMessage.vue'
|
||||
import LegacyPaidMessage from './LegacyPaidMessage.vue'
|
||||
import PaidMessage from './PaidMessage.vue'
|
||||
@ -50,13 +51,18 @@ export default {
|
||||
PaidMessage
|
||||
},
|
||||
data() {
|
||||
let styleElement = document.createElement('style')
|
||||
styleElement.innerText = config.DEFAULT_CONFIG.css
|
||||
document.head.appendChild(styleElement)
|
||||
return {
|
||||
config: config.DEFAULT_CONFIG,
|
||||
styleElement,
|
||||
websocket: null,
|
||||
messages: [],
|
||||
nextId: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
async created() {
|
||||
// 开发时使用localhost:80
|
||||
const url = process.env.NODE_ENV === 'development' ? 'ws://localhost/chat' : `ws://${window.location.host}/chat`
|
||||
this.websocket = new WebSocket(url)
|
||||
@ -85,7 +91,7 @@ export default {
|
||||
break
|
||||
case COMMAND_ADD_GIFT:
|
||||
price = body.data.totalCoin / 1000
|
||||
if (price < 6.911) // 丢人
|
||||
if (price < this.config.minGiftPrice) // 丢人
|
||||
break
|
||||
message = {
|
||||
id: this.nextId++,
|
||||
@ -112,8 +118,18 @@ export default {
|
||||
this.messages.shift()
|
||||
}
|
||||
}
|
||||
|
||||
if (this.$route.query.config_id) {
|
||||
try {
|
||||
this.config = await config.getRemoteConfig(this.$route.query.config_id)
|
||||
this.styleElement.innerText = this.config.css
|
||||
} catch (e) {
|
||||
this.$message.error('获取配置失败:' + e)
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
document.head.removeChild(this.styleElement)
|
||||
this.websocket.close()
|
||||
},
|
||||
updated() {
|
||||
|
18
main.py
18
main.py
@ -7,20 +7,15 @@ import os
|
||||
import tornado.ioloop
|
||||
import tornado.web
|
||||
|
||||
import chat
|
||||
import views.chat
|
||||
import views.config
|
||||
import views.main
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
WEB_ROOT = os.path.join(os.path.dirname(__file__), 'frontend', 'dist')
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class MainHandler(tornado.web.StaticFileHandler):
|
||||
"""为了使用Vue Router的history模式,把所有请求转发到index.html"""
|
||||
async def get(self, *args, **kwargs):
|
||||
await super().get('index.html', *args, **kwargs)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='用于OBS的仿YouTube风格的bilibili直播聊天层')
|
||||
parser.add_argument('--host', help='服务器host,默认为127.0.0.1', default='127.0.0.1')
|
||||
@ -37,10 +32,13 @@ def main():
|
||||
|
||||
app = tornado.web.Application(
|
||||
[
|
||||
(r'/chat', chat.ChatHandler),
|
||||
(r'/chat', views.chat.ChatHandler),
|
||||
(r'/config', views.config.ConfigsHandler),
|
||||
(r'/config/(.+)', views.config.ConfigHandler),
|
||||
|
||||
(r'/((css|img|js)/.*)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
||||
(r'/(favicon\.ico)', tornado.web.StaticFileHandler, {'path': WEB_ROOT}),
|
||||
(r'/.*', MainHandler, {'path': WEB_ROOT})
|
||||
(r'/.*', views.main.MainHandler, {'path': WEB_ROOT})
|
||||
],
|
||||
websocket_ping_interval=30,
|
||||
debug=args.debug,
|
||||
|
28
views/base.py
Normal file
28
views/base.py
Normal file
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
|
||||
import tornado.web
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class ApiHandler(tornado.web.RequestHandler):
|
||||
def set_default_headers(self):
|
||||
# 跨域测试用
|
||||
if not self.application.settings['debug']:
|
||||
return
|
||||
self.set_header('Access-Control-Allow-Origin', '*')
|
||||
self.set_header('Access-Control-Allow-Methods', 'OPTIONS, PUT, POST, GET, DELETE')
|
||||
if 'Access-Control-Request-Headers' in self.request.headers:
|
||||
self.set_header('Access-Control-Allow-Headers',
|
||||
self.request.headers['Access-Control-Request-Headers'])
|
||||
|
||||
def prepare(self):
|
||||
if self.request.headers.get('Content-Type', '').startswith('application/json'):
|
||||
self.json_args = json.loads(self.request.body)
|
||||
else:
|
||||
self.json_args = None
|
||||
|
||||
async def options(self, *_args, **_kwargs):
|
||||
# 跨域测试用
|
||||
self.set_status(204 if self.application.settings['debug'] else 405)
|
50
views/config.py
Normal file
50
views/config.py
Normal file
@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import uuid
|
||||
|
||||
import views.base
|
||||
from typing import *
|
||||
|
||||
configs: Dict[str, dict] = {}
|
||||
|
||||
ALLOWED_FIELDS = (
|
||||
'minGiftPrice', 'mergeSimilarDanmaku', 'blockGiftDanmaku', 'blockLevel',
|
||||
'blockNewbie', 'blockNotMobileVerified', 'blockKeywords', 'blockUsers',
|
||||
'css'
|
||||
)
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class ConfigsHandler(views.base.ApiHandler):
|
||||
async def post(self):
|
||||
config_id = str(uuid.uuid4())
|
||||
config = {
|
||||
name: self.json_args[name] for name in ALLOWED_FIELDS
|
||||
}
|
||||
config['id'] = config_id
|
||||
configs[config_id] = config
|
||||
self.set_status(201)
|
||||
self.write(config)
|
||||
|
||||
if len(configs) > 10000:
|
||||
for _, key in zip(range(100), configs):
|
||||
del configs[key]
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class ConfigHandler(views.base.ApiHandler):
|
||||
async def put(self, config_id):
|
||||
config = configs.get(config_id, None)
|
||||
if config is None:
|
||||
self.set_status(404)
|
||||
return
|
||||
for name in ALLOWED_FIELDS:
|
||||
config[name] = self.json_args[name]
|
||||
self.write(config)
|
||||
|
||||
async def get(self, config_id):
|
||||
config = configs.get(config_id, None)
|
||||
if config is None:
|
||||
self.set_status(404)
|
||||
return
|
||||
self.write(config)
|
10
views/main.py
Normal file
10
views/main.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import tornado.web
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class MainHandler(tornado.web.StaticFileHandler):
|
||||
"""为了使用Vue Router的history模式,把所有请求转发到index.html"""
|
||||
async def get(self, *args, **kwargs):
|
||||
await super().get('index.html', *args, **kwargs)
|
Loading…
Reference in New Issue
Block a user