diff --git a/README.md b/README.md
index 9252875..6bb389c 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,8 @@ Languages: English, 中文
[TODO](https://github.com/CzBiX/qb-web/projects/2)
-## Download
-
-[Releases](https://github.com/CzBiX/qb-web/releases/latest)
+## How to use
+see: [Wiki](https://github.com/CzBiX/qb-web/wiki/How-to-use)
## Install
diff --git a/screenshot/CORS-settings.png b/screenshot/CORS-settings.png
new file mode 100644
index 0000000..70218de
Binary files /dev/null and b/screenshot/CORS-settings.png differ
diff --git a/src/Api.ts b/src/Api.ts
index 8aa8103..7fb68ce 100644
--- a/src/Api.ts
+++ b/src/Api.ts
@@ -2,18 +2,36 @@
import Axios, { AxiosInstance, AxiosResponse } from 'axios';
import { RssNode, RssRule, SearchPlugin, ApiCategory, SearchTaskResponse } from '@/types';
-class Api {
+const apiEndpoint = 'api/v2';
+class Api {
private axios: AxiosInstance;
constructor() {
this.axios = Axios.create({
- baseURL: 'api/v2',
+ baseURL: apiEndpoint,
+ withCredentials: true,
});
this.axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
}
+ private normalizeBaseUrl(baseUrl?: string) {
+ if (!baseUrl) {
+ return apiEndpoint;
+ }
+
+ if (!baseUrl.endsWith('/')) {
+ baseUrl += '/';
+ }
+
+ return baseUrl + apiEndpoint;
+ }
+
+ public changeBaseUrl(baseUrl: string) {
+ this.axios.defaults.baseURL = this.normalizeBaseUrl(baseUrl);
+ }
+
public getAppVersion() {
return this.axios.get('/app/version');
}
@@ -22,12 +40,13 @@ class Api {
return this.axios.get('/app/webapiVersion');
}
- public login(params: any) {
+ public login(params: any, baseUrl?: string) {
const data = new URLSearchParams(params);
return this.axios.post('/auth/login', data, {
validateStatus(status) {
return status === 200 || status === 403;
},
+ baseURL: this.normalizeBaseUrl(baseUrl),
}).then(Api.handleResponse);
}
@@ -330,4 +349,5 @@ class Api {
}
}
-export default new Api();
+const api = new Api();
+export default api;
diff --git a/src/App.vue b/src/App.vue
index 09a664e..bafa6ea 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -75,6 +75,8 @@ import api from './Api';
import Component from 'vue-class-component';
import { Watch } from 'vue-property-decorator';
import { MainData } from './types';
+import { Config } from './store/config';
+import Api from './Api';
let appWrapEl: HTMLElement;
@@ -98,6 +100,7 @@ let appWrapEl: HTMLElement;
'mainData',
'rid',
'preferences',
+ 'needAuth',
]),
...mapGetters(['config']),
},
@@ -106,11 +109,11 @@ let appWrapEl: HTMLElement;
'updateMainData',
'updatePreferences',
'setPasteUrl',
+ 'updateNeedAuth',
]),
}
})
export default class App extends Vue {
- needAuth = false
drawer = true
drawerOptions = {
showLogs: false,
@@ -122,11 +125,13 @@ export default class App extends Vue {
mainData!: MainData
rid!: number
preferences!: any
- config!: any
+ config!: Config
+ needAuth!: boolean
updateMainData!: (_: any) => void
updatePreferences!: (_: any) => void
setPasteUrl!: (_: any) => void
+ updateNeedAuth!: (_: boolean) => void
get phoneLayout() {
return this.$vuetify.breakpoint.xsOnly;
@@ -159,13 +164,22 @@ export default class App extends Vue {
}
async getInitData() {
+ const href = location.href;
+ if (!this.config.baseUrl) {
+ if (href.includes("czbix.github.io") || href.includes("localhost")) {
+ this.updateNeedAuth(true);
+ return;
+ } else {
+ Api.changeBaseUrl(href);
+ }
+ } else {
+ Api.changeBaseUrl(this.config.baseUrl);
+ }
+
try {
await this.getMainData();
} catch (e) {
- if (e.response.status === 403) {
- this.needAuth = true;
- }
-
+ this.updateNeedAuth(true);
return;
}
diff --git a/src/components/LoginForm.vue b/src/components/LoginForm.vue
index e5e7aac..3a1315d 100644
--- a/src/components/LoginForm.vue
+++ b/src/components/LoginForm.vue
@@ -21,11 +21,17 @@
@keyup.enter.capture="submit"
v-bind="{ [`grid-list-${$vuetify.breakpoint.name}`]: true }"
>
+
@@ -36,7 +42,6 @@
@click:append="showPassword = !showPassword"
:label="$t('password')"
:type="showPassword ? 'text' : 'password'"
- :rules="[v => !!v || $t('msg.item_is_required', { item: $t('password') })]"
required
/>
@@ -63,56 +68,64 @@
diff --git a/src/locale/en.ts b/src/locale/en.ts
index 984f97c..dfaff16 100644
--- a/src/locale/en.ts
+++ b/src/locale/en.ts
@@ -99,6 +99,7 @@ export default {
reannounced: 'Reannounced',
rechecking: 'Rechecking…',
dht_nodes: '%{smart_count} node |||| %{smart_count} nodes',
+ base_url: 'Base URL',
},
msg: {
diff --git a/src/locale/index.ts b/src/locale/index.ts
index 9b85e81..70453a8 100644
--- a/src/locale/index.ts
+++ b/src/locale/index.ts
@@ -30,7 +30,7 @@ function matchLocale() {
export const defaultLocale = matchLocale()
function updateLocale() {
- let locale: LocaleKey | undefined = loadConfig()['locale'];
+ let locale = loadConfig()['locale'] as LocaleKey;
if (!locale) {
locale = defaultLocale;
diff --git a/src/store/config.ts b/src/store/config.ts
index 9ef6e9c..d4be7b7 100644
--- a/src/store/config.ts
+++ b/src/store/config.ts
@@ -5,7 +5,22 @@ import { ConfigState, ConfigPayload } from './types';
const configKey = 'qb-config';
+export interface Config {
+ baseUrl: string | null;
+ updateInterval: number;
+ pageOptions: any;
+ filter: {
+ state: string | null;
+ category: string | null;
+ site: string | null;
+ query: string | null;
+ };
+ locale: string | null;
+ darkMode: string | null;
+}
+
const defaultConfig = {
+ baseUrl: null,
updateInterval: 2000,
pageOptions: {
itemsPerPage: 50,
@@ -20,8 +35,6 @@ const defaultConfig = {
darkMode: null,
};
-export type Config = typeof defaultConfig
-
function saveConfig(obj: any) {
localStorage.setItem(configKey, JSON.stringify(obj));
}
diff --git a/src/store/index.ts b/src/store/index.ts
index 9e47e5c..b9e4bcc 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -27,6 +27,7 @@ const store = new Vuex.Store({
mainData: undefined,
preferences: null,
pasteUrl: null,
+ needAuth: false,
},
mutations: {
/* eslint-disable no-param-reassign */
@@ -60,6 +61,9 @@ const store = new Vuex.Store({
const { url } = payload;
state.pasteUrl = url;
},
+ updateNeedAuth(state, payload) {
+ state.needAuth = payload;
+ },
/* eslint-enable no-param-reassign */
},
getters: {
diff --git a/src/store/types.ts b/src/store/types.ts
index 262f2db..1f6fbc9 100644
--- a/src/store/types.ts
+++ b/src/store/types.ts
@@ -6,6 +6,7 @@ export interface RootState {
mainData?: MainData;
preferences: any;
pasteUrl: string | null;
+ needAuth: boolean;
}
export interface SearchEnginePage {
diff --git a/tests/unit/store/index.spec.ts b/tests/unit/store/index.spec.ts
index 71f2241..90bb4d0 100644
--- a/tests/unit/store/index.spec.ts
+++ b/tests/unit/store/index.spec.ts
@@ -13,6 +13,7 @@ const emtpyState: RootState = {
mainData: undefined,
preferences: null,
pasteUrl: null,
+ needAuth: false,
};
const mockState = mock(emtpyState);