mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-11 13:59:01 +08:00
夜间模式
This commit is contained in:
parent
1f998f70b5
commit
3f002e0c52
@ -76,6 +76,13 @@ function service() {
|
||||
|
||||
// rules API
|
||||
$app.get("/download/rule/:name", downloadRule);
|
||||
$app.route("/api/rules")
|
||||
.post(createRule)
|
||||
.get(getAllRules);
|
||||
$app.route("/api/rule/:name")
|
||||
.patch(updateRule)
|
||||
.delete(deleteRule)
|
||||
.get(getRule);
|
||||
|
||||
// Storage management
|
||||
$app.route("/api/storage")
|
||||
@ -435,6 +442,22 @@ function service() {
|
||||
}
|
||||
}
|
||||
|
||||
function createRule(req, res) {
|
||||
|
||||
}
|
||||
function deleteRule(req, res) {
|
||||
|
||||
}
|
||||
function updateRule(req, res) {
|
||||
|
||||
}
|
||||
function getAllRules(req, res) {
|
||||
|
||||
}
|
||||
function getRule(req, res) {
|
||||
|
||||
}
|
||||
|
||||
// settings API
|
||||
function getSettings(req, res) {
|
||||
const settings = $.read(SETTINGS_KEY);
|
||||
|
@ -5,8 +5,11 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
||||
<!-- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>-->
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"/>
|
||||
<link rel="Bookmark" href="https://raw.githubusercontent.com/58xinian/icon/master/Sub-Store1.png"/>
|
||||
|
@ -34,20 +34,20 @@ import BottomNav from "@/components/BottomNav";
|
||||
import {showError} from "@/utils";
|
||||
|
||||
|
||||
function initStore(store) {
|
||||
store.dispatch('FETCH_SUBSCRIPTIONS').catch(() => {
|
||||
async function initStore(store) {
|
||||
await store.dispatch('FETCH_SUBSCRIPTIONS').catch(() => {
|
||||
showError(`无法拉取订阅列表!`);
|
||||
});
|
||||
store.dispatch("FETCH_COLLECTIONS").catch(() => {
|
||||
await store.dispatch("FETCH_COLLECTIONS").catch(() => {
|
||||
showError(`无法拉取组合订阅列表!`);
|
||||
});
|
||||
store.dispatch("FETCH_ARTIFACTS").catch(() => {
|
||||
await store.dispatch("FETCH_ARTIFACTS").catch(() => {
|
||||
showError(`无法拉取配置列表!`);
|
||||
});
|
||||
store.dispatch("FETCH_SETTINGS").catch(() => {
|
||||
await store.dispatch("FETCH_SETTINGS").catch(() => {
|
||||
showError(`无法拉取配置列表!`);
|
||||
});
|
||||
store.dispatch("FETCH_ENV").catch(() => {
|
||||
await store.dispatch("FETCH_ENV").catch(() => {
|
||||
showError(`无法获取当前运行环境!`);
|
||||
});
|
||||
}
|
||||
@ -60,7 +60,12 @@ export default {
|
||||
|
||||
created() {
|
||||
initStore(this.$store);
|
||||
// this.$vuetify.theme.dark = !this.$vuetify.theme.dark;
|
||||
this.$store.watch(
|
||||
(state => state.settings.theme.darkMode),
|
||||
(value => {
|
||||
this.$vuetify.theme.dark = value
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
computed: {
|
||||
@ -74,15 +79,23 @@ export default {
|
||||
|
||||
watch: {
|
||||
successMessage() {
|
||||
setTimeout(() => {
|
||||
if (this.$store.state.snackbarTimer) {
|
||||
clearTimeout(this.$store.state.snackbarTimer);
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
this.$store.commit("SET_SUCCESS_MESSAGE", "");
|
||||
}, 1000);
|
||||
}, 3000);
|
||||
this.$store.commit("SET_SNACK_BAR_TIMER", timer);
|
||||
},
|
||||
errorMessage() {
|
||||
setTimeout(() => {
|
||||
if (this.$store.state.snackbarTimer) {
|
||||
clearTimeout(this.$store.state.snackbarTimer);
|
||||
}
|
||||
const timer = setTimeout(() => {
|
||||
this.$store.commit("SET_ERROR_MESSAGE", "");
|
||||
}, 1000);
|
||||
},
|
||||
}, 3000);
|
||||
this.$store.commit("SET_SNACK_BAR_TIMER", timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -17,25 +17,25 @@ const router = new Router({
|
||||
path: "/",
|
||||
name: "subscriptions",
|
||||
component: Subscription,
|
||||
meta: {title: "订阅"}
|
||||
meta: {title: "订阅", keepAlive: true}
|
||||
},
|
||||
{
|
||||
path: "/dashboard",
|
||||
name: "dashboard",
|
||||
component: Dashboard,
|
||||
meta: {title: "首页"}
|
||||
meta: {title: "首页", keepAlive: true}
|
||||
},
|
||||
{
|
||||
path: "/cloud",
|
||||
name: "artifact",
|
||||
component: Cloud,
|
||||
meta: {title: "同步"}
|
||||
meta: {title: "同步", keepAlive: true}
|
||||
},
|
||||
{
|
||||
path: "/user",
|
||||
name: "user",
|
||||
component: User,
|
||||
meta: {title: "我的"}
|
||||
meta: {title: "我的", keepAlive: true}
|
||||
},
|
||||
{
|
||||
path: "/sub-edit/:name",
|
||||
|
@ -7,17 +7,21 @@ Vue.use(Vuex);
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
title: "Sub-Store",
|
||||
isDarkMode: false,
|
||||
clipboard: "",
|
||||
|
||||
successMessage: "",
|
||||
errorMessage: "",
|
||||
snackbarTimer: "",
|
||||
|
||||
subscriptions: {},
|
||||
collections: {},
|
||||
artifacts: {},
|
||||
env: {},
|
||||
settings: {}
|
||||
settings: {
|
||||
theme: {
|
||||
darkMode: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
@ -28,8 +32,9 @@ const store = new Vuex.Store({
|
||||
SET_NAV_TITLE(state, title) {
|
||||
state.title = title;
|
||||
},
|
||||
SET_DARK_MODE(state, isDarkMode) {
|
||||
state.isDarkMode = isDarkMode
|
||||
|
||||
SET_SNACK_BAR_TIMER(state, timer) {
|
||||
state.snackbarTimer = timer;
|
||||
},
|
||||
|
||||
SET_SUCCESS_MESSAGE(state, msg) {
|
||||
@ -40,6 +45,9 @@ const store = new Vuex.Store({
|
||||
state.errorMessage = msg;
|
||||
},
|
||||
|
||||
SET_DARK_MODE(state, on) {
|
||||
state.settings.theme.darkMode = on;
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -71,7 +79,12 @@ const store = new Vuex.Store({
|
||||
},
|
||||
async FETCH_SETTINGS({state}) {
|
||||
return axios.get("/settings").then(resp => {
|
||||
state.settings = resp.data;
|
||||
state.settings = {
|
||||
theme: {
|
||||
darkMode: false
|
||||
},
|
||||
...resp.data
|
||||
}
|
||||
});
|
||||
},
|
||||
// update subscriptions
|
||||
|
@ -2,14 +2,12 @@
|
||||
<v-container fluid>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon left>mdi-cloud</v-icon>
|
||||
同步配置
|
||||
<v-spacer></v-spacer>
|
||||
<!-- <v-btn icon>-->
|
||||
<!-- <v-icon>mdi-cloud-circle</v-icon>-->
|
||||
<!-- </v-btn>-->
|
||||
<!-- <v-btn icon>-->
|
||||
<!-- <v-icon>mdi-refresh-circle</v-icon>-->
|
||||
<!-- </v-btn>-->
|
||||
<v-btn icon @click="openGist()">
|
||||
<v-icon>visibility</v-icon>
|
||||
</v-btn>
|
||||
<v-dialog max-width="400px" v-model="addArtifactDialog">
|
||||
<template #activator="{on}">
|
||||
<v-btn icon v-on="on">
|
||||
@ -195,6 +193,9 @@ export default {
|
||||
artifacts() {
|
||||
const items = this.$store.state.artifacts;
|
||||
return Object.keys(items).map(k => items[k]);
|
||||
},
|
||||
settings() {
|
||||
return this.$store.state.settings;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -287,6 +288,10 @@ export default {
|
||||
data = this.$store.state.collections;
|
||||
}
|
||||
return Object.keys(data);
|
||||
},
|
||||
|
||||
openGist() {
|
||||
window.open(`https://gist.github.com${ '/' + this.settings.githubUser || ''}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
<v-list-item v-for="sub in availableSubs" :key="sub.name">
|
||||
<v-list-item-avatar>
|
||||
<v-icon v-if="!sub.icon" color="teal darken-1">mdi-cloud</v-icon>
|
||||
<v-img :src="sub.icon" v-else color="blue"/>
|
||||
<v-img :src="sub.icon" v-else :class="sub.icon.indexOf('#invert') !== -1 ? 'invert' : ''"/>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
{{ sub.name }}
|
||||
@ -571,7 +571,7 @@ function uuidv4() {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.v-label {
|
||||
font-size: small;
|
||||
.invert {
|
||||
filter: invert(100%);
|
||||
}
|
||||
</style>
|
@ -2,6 +2,7 @@
|
||||
<v-container fluid>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon left>local_airport</v-icon>
|
||||
单个订阅
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="createSub">
|
||||
@ -17,7 +18,7 @@
|
||||
>
|
||||
<v-list-item-avatar>
|
||||
<v-icon v-if="!sub.icon" color="teal darken-1">mdi-cloud</v-icon>
|
||||
<v-img :src="sub.icon" v-else color="blue"/>
|
||||
<v-img :src="sub.icon" v-else :class="sub.icon.indexOf('#invert') !== -1 ? 'invert' : ''"/>
|
||||
</v-list-item-avatar>
|
||||
|
||||
<v-list-item-content>
|
||||
@ -54,6 +55,7 @@
|
||||
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon left>work_outline</v-icon>
|
||||
组合订阅
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="createCol">
|
||||
@ -70,7 +72,7 @@
|
||||
>
|
||||
<v-list-item-avatar>
|
||||
<v-icon v-if="!collection.icon" color="teal darken-1">mdi-cloud</v-icon>
|
||||
<v-img :src="collection.icon" v-else color="blue"/>
|
||||
<v-img :src="collection.icon" v-else :class="collection.icon.indexOf('#invert') !== -1 ? 'invert' : ''"/>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="collection.name" class="font-weight-medium"></v-list-item-title>
|
||||
@ -166,6 +168,14 @@ export default {
|
||||
title: "删除",
|
||||
action: "DELETE"
|
||||
},
|
||||
// {
|
||||
// title: "上移",
|
||||
// action: "MOVE_UP"
|
||||
// },
|
||||
// {
|
||||
// title: "下移",
|
||||
// action: "MOVE_DOWN"
|
||||
// }
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -174,9 +184,14 @@ export default {
|
||||
subscriptionBaseURL() {
|
||||
return BACKEND_BASE;
|
||||
},
|
||||
subscriptions() {
|
||||
const subs = this.$store.state.subscriptions;
|
||||
return Object.keys(subs).map(k => subs[k]);
|
||||
subscriptions: {
|
||||
get(){
|
||||
const subs = this.$store.state.subscriptions;
|
||||
return Object.keys(subs).map(k => subs[k]);
|
||||
},
|
||||
set(){
|
||||
|
||||
}
|
||||
},
|
||||
collections() {
|
||||
const cols = this.$store.state.collections;
|
||||
@ -197,6 +212,12 @@ export default {
|
||||
break
|
||||
case 'DELETE':
|
||||
this.$store.dispatch("DELETE_SUBSCRIPTION", sub.name);
|
||||
break
|
||||
case 'MOVE_UP':
|
||||
this.moveUpSubscription(sub.name);
|
||||
break
|
||||
case 'MOVE_DOWN':
|
||||
|
||||
break
|
||||
}
|
||||
},
|
||||
@ -232,15 +253,29 @@ export default {
|
||||
},
|
||||
refreshProxyList() {
|
||||
this.$refs.proxyList.refresh();
|
||||
}
|
||||
},
|
||||
moveUpSubscription(name) {
|
||||
let index = 0;
|
||||
for (; index < this.subscriptions.length; index++) {
|
||||
if (this.subscriptions[index].name === name) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index === 0) return;
|
||||
// otherwise swap with previous one
|
||||
const prev = this.subscriptions[index - 1];
|
||||
const cur = this.subscriptions[index];
|
||||
this.subscriptions.splice(index - 1, 2, cur, prev);
|
||||
},
|
||||
// moveDownSubscription(name) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.top-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
.invert {
|
||||
filter: invert(100%);
|
||||
}
|
||||
</style>
|
@ -2,25 +2,86 @@
|
||||
<v-container fluid>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
GitHub 配置
|
||||
<v-icon left>mdi-cloud</v-icon>
|
||||
数据同步
|
||||
<v-spacer></v-spacer>
|
||||
<v-icon small>settings</v-icon>
|
||||
<v-btn icon @click="openGist()">
|
||||
<v-icon small color="primary">visibility</v-icon>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
label="GitHub 用户名"
|
||||
hint="填入GitHub用户名"
|
||||
v-model="settings.githubUser"
|
||||
clearable clear-icon="clear"
|
||||
>
|
||||
最近同步于:{{ syncTime }}
|
||||
</v-card-text>
|
||||
<v-divider></v-divider>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn small
|
||||
:loading="status.uploading"
|
||||
color="blue-grey"
|
||||
class="ma-2 white--text"
|
||||
@click="sync('upload')">
|
||||
上传
|
||||
<v-icon right>
|
||||
mdi-cloud-upload
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
<v-btn small
|
||||
:loading="status.downloading"
|
||||
color="blue-grey"
|
||||
class="ma-2 white--text"
|
||||
@click="sync('download')">
|
||||
恢复
|
||||
<v-icon right>
|
||||
mdi-cloud-download
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
||||
</v-text-field>
|
||||
<v-text-field
|
||||
label="GitHub Token"
|
||||
hint="填入GitHub Token"
|
||||
v-model="settings.gistToken"
|
||||
clearable clear-icon="clear"
|
||||
/>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<v-icon left>settings</v-icon>
|
||||
设置
|
||||
<v-spacer></v-spacer>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-list dense>
|
||||
<v-subheader>GitHub配置</v-subheader>
|
||||
<v-list-item>
|
||||
<v-col>
|
||||
<v-row>
|
||||
<v-text-field
|
||||
label="GitHub 用户名"
|
||||
hint="填入GitHub用户名"
|
||||
v-model="settings.githubUser"
|
||||
clearable clear-icon="clear"
|
||||
/>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-text-field
|
||||
label="GitHub Token"
|
||||
hint="填入GitHub Token"
|
||||
v-model="settings.gistToken"
|
||||
clearable clear-icon="clear"
|
||||
/>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-list-item>
|
||||
<v-divider></v-divider>
|
||||
<v-subheader>外观</v-subheader>
|
||||
<v-list-item>
|
||||
<v-list-item-content>
|
||||
夜间模式 (实验性支持)
|
||||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-switch
|
||||
label=""
|
||||
hide-details
|
||||
v-model="settings.theme.darkMode"
|
||||
/>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
<v-divider></v-divider>
|
||||
<v-card-actions>
|
||||
@ -30,21 +91,21 @@
|
||||
<v-divider/>
|
||||
</v-card>
|
||||
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
Gist 数据同步
|
||||
<v-spacer></v-spacer>
|
||||
<v-icon small>mdi-cloud</v-icon>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
最近同步于:{{syncTime}}
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn small text @click="sync('upload')">上传</v-btn>
|
||||
<v-btn small text @click="sync('download')">恢复</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
<!-- <v-card>-->
|
||||
<!-- <v-card-title>-->
|
||||
<!-- <v-icon left>-->
|
||||
<!-- mdi-star-->
|
||||
<!-- </v-icon>-->
|
||||
<!-- 关于-->
|
||||
<!-- </v-card-title>-->
|
||||
<!-- <v-card-text>-->
|
||||
<!-- <v-list>-->
|
||||
<!-- <v-list-item>-->
|
||||
<!-- <v-list-item-title>GitHub</v-list-item-title>-->
|
||||
<!-- </v-list-item>-->
|
||||
<!-- </v-list>-->
|
||||
<!-- </v-card-text>-->
|
||||
<!-- </v-card>-->
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@ -53,11 +114,24 @@ import {axios, showError} from "@/utils";
|
||||
import {format} from "timeago.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
status: {
|
||||
uploading: false,
|
||||
downloading: false
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
settings() {
|
||||
return this.$store.state.settings;
|
||||
settings: {
|
||||
get() {
|
||||
return this.$store.state.settings;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.state.settings = value;
|
||||
}
|
||||
},
|
||||
syncTime(){
|
||||
syncTime() {
|
||||
if (this.settings.syncTime) {
|
||||
return format(this.settings.syncTime, "zh_CN");
|
||||
} else {
|
||||
@ -66,26 +140,41 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
axios.patch(`/settings`, this.settings);
|
||||
this.$store.dispatch("FETCH_SETTINGS");
|
||||
async save() {
|
||||
await axios.patch(`/settings`, this.settings);
|
||||
await this.$store.dispatch("FETCH_SETTINGS");
|
||||
this.$store.commit("SET_SUCCESS_MESSAGE", `保存成功!`);
|
||||
},
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
sync(action) {
|
||||
const setLoading = (status) => {
|
||||
if (action === 'upload') {
|
||||
this.status.uploading = status;
|
||||
} else if (action === 'download'){
|
||||
this.status.downloading = status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.settings.gistToken) {
|
||||
this.$store.commit("SET_ERROR_MESSAGE", "未设置GitHub Token!");
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
axios.get(`/utils/backup?action=${action}`).then(resp => {
|
||||
if (resp.data.status === 'success') {
|
||||
this.$store.commit("SET_SUCCESS_MESSAGE", `${action === 'upload' ? "备份" : "还原"}成功!`);
|
||||
this.settings.syncTime = new Date().getTime();
|
||||
if (action === 'upload') {
|
||||
this.settings.syncTime = new Date().getTime();
|
||||
}
|
||||
axios.patch(`/settings`, this.settings);
|
||||
this.updateStore(this.$store);
|
||||
} else
|
||||
this.$store.commit("SET_ERROR_MESSAGE", `备份失败!${resp.data.message}`);
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$store.commit("SET_ERROR_MESSAGE", `备份失败!${err}`);
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
},
|
||||
|
||||
@ -96,9 +185,16 @@ export default {
|
||||
store.dispatch("FETCH_COLLECTIONS").catch(() => {
|
||||
showError(`无法拉取组合订阅列表!`);
|
||||
});
|
||||
store.dispatch("FETCH_SETTINGS").catch(() => {
|
||||
showError(`无法拉取设置!`);
|
||||
});
|
||||
store.dispatch("FETCH_ARTIFACTS").catch(() => {
|
||||
showError(`无法拉取同步配置!`);
|
||||
});
|
||||
},
|
||||
|
||||
openGist() {
|
||||
window.open(`https://gist.github.com${'/' + this.settings.githubUser || ''}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user