Merge branch 'qb' into dev
# Conflicts: # openRenamerFront/src/App.vue
This commit is contained in:
commit
7691a8f66f
@ -1,15 +1,22 @@
|
|||||||
import { Context } from "koa";
|
import { Context } from "koa";
|
||||||
import service from "../service/GlobalService";
|
import service from "../service/GlobalConfigService";
|
||||||
|
|
||||||
const router = {};
|
const router = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预览文件修改后的状态
|
* 获取单个配置
|
||||||
*/
|
*/
|
||||||
router["GET /config/code"] = async function (ctx: Context) {
|
router["GET /config/code"] = async function (ctx: Context) {
|
||||||
ctx.body = await service.getVal(ctx.request.query.code as string);
|
ctx.body = await service.getVal(ctx.request.query.code as string);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个配置项
|
||||||
|
*/
|
||||||
|
router["POST /config/multCode"] = async function (ctx: Context) {
|
||||||
|
ctx.body = await service.getMultVal(ctx.request.body);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提交修改
|
* 提交修改
|
||||||
*/
|
*/
|
||||||
|
14
openRenamerBackend/api/QbServiceApi.ts
Normal file
14
openRenamerBackend/api/QbServiceApi.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Context } from "koa";
|
||||||
|
import service from "../service/QbService";
|
||||||
|
|
||||||
|
const router = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单个配置
|
||||||
|
*/
|
||||||
|
router["POST /qb/saveQbInfo"] = async function (ctx: Context) {
|
||||||
|
ctx.body = await service.saveAddress(ctx.request.body);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default router;
|
@ -43,7 +43,26 @@ export default class GlobalConfigDao {
|
|||||||
static async getByCode(code: string): Promise<string> {
|
static async getByCode(code: string): Promise<string> {
|
||||||
let res = await SqliteHelper.pool.get('select val from global_config where code=?', code);
|
let res = await SqliteHelper.pool.get('select val from global_config where code=?', code);
|
||||||
return res ? res.val : null;
|
return res ? res.val : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询多个code
|
||||||
|
* @param code
|
||||||
|
*/
|
||||||
|
static async getByMulCode(codes: Array<string>): Promise<Array<GlobalConfig>> {
|
||||||
|
if (codes.length == 0) {
|
||||||
|
return new Array();
|
||||||
|
}
|
||||||
|
let codeStr = codes.map(item => `'${item}'`).join(',');
|
||||||
|
return await SqliteHelper.pool.all(`select * from global_config where code in (${codeStr})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入一条
|
||||||
|
* @param body body
|
||||||
|
*/
|
||||||
|
static async insertOrReplace(body: GlobalConfig): Promise<void> {
|
||||||
|
await SqliteHelper.pool.run(`insert or replace into global_config values (?,?,?)`, body.code, body.val, body.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
5
openRenamerBackend/entity/dto/QbAddressDto.ts
Normal file
5
openRenamerBackend/entity/dto/QbAddressDto.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default interface QbAddressDto {
|
||||||
|
address: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
@ -9,6 +9,7 @@ import handleError from "./middleware/handleError";
|
|||||||
import init from "./middleware/init";
|
import init from "./middleware/init";
|
||||||
import SqliteUtil from './util/SqliteHelper';
|
import SqliteUtil from './util/SqliteHelper';
|
||||||
import log from './util/LogUtil';
|
import log from './util/LogUtil';
|
||||||
|
import { updateQbInfo } from './util/QbApiUtil';
|
||||||
|
|
||||||
|
|
||||||
console.log(config);
|
console.log(config);
|
||||||
@ -30,6 +31,7 @@ app.use(handleError);
|
|||||||
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
|
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
|
||||||
(async () => {
|
(async () => {
|
||||||
await SqliteUtil.createPool();
|
await SqliteUtil.createPool();
|
||||||
|
await updateQbInfo(null, null);
|
||||||
app.listen(config.port);
|
app.listen(config.port);
|
||||||
log.info(`server listened `, config.port);
|
log.info(`server listened `, config.port);
|
||||||
})();
|
})();
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
"@types/fs-extra": "^5.0.4",
|
"@types/fs-extra": "^5.0.4",
|
||||||
"@types/koa": "^2.0.47",
|
"@types/koa": "^2.0.47",
|
||||||
"@types/node": "^11.13.4",
|
"@types/node": "^11.13.4",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.4",
|
||||||
"fs-extra": "^7.0.0",
|
"fs-extra": "^7.0.0",
|
||||||
"koa": "^2.5.3",
|
"koa": "^2.5.3",
|
||||||
"koa-body": "^4.0.4",
|
"koa-body": "^4.0.4",
|
||||||
|
@ -10,9 +10,24 @@ class GlobalConfigService {
|
|||||||
return GlobalConfigDao.getByCode(code);
|
return GlobalConfigDao.getByCode(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个配置
|
||||||
|
* @param codes codes
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async getMultVal(codes: Array<string>): Promise<any> {
|
||||||
|
let re = {};
|
||||||
|
(await GlobalConfigDao.getByMulCode(codes)).forEach(item => re[item.code] = item.val);
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
static async updateVal(code: string, val: string): Promise<void> {
|
static async updateVal(code: string, val: string): Promise<void> {
|
||||||
return GlobalConfigDao.updateOne(code, val);
|
return GlobalConfigDao.updateOne(code, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async insertOrReplace(body: GlobalConfig): Promise<void> {
|
||||||
|
return GlobalConfigDao.insertOrReplace(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GlobalConfigService;
|
export default GlobalConfigService;
|
17
openRenamerBackend/service/QbService.ts
Normal file
17
openRenamerBackend/service/QbService.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import QbAddressDto from "../entity/dto/QbAddressDto";
|
||||||
|
import { tryLogin, updateQbInfo } from '../util/QbApiUtil';
|
||||||
|
import GlobalConfigService from "./GlobalConfigService";
|
||||||
|
import GlobalConfig from "../entity/po/GlobalConfig";
|
||||||
|
|
||||||
|
class QbService {
|
||||||
|
|
||||||
|
static async saveAddress(body: QbAddressDto) {
|
||||||
|
await tryLogin(body.address, body.username, body.password, false);
|
||||||
|
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbAddress", body.address, "qbAdress"));
|
||||||
|
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbUsername", body.username, ""));
|
||||||
|
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbPassword", body.password, ""));
|
||||||
|
await updateQbInfo(body, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default QbService;
|
102
openRenamerBackend/util/QbApiUtil.ts
Normal file
102
openRenamerBackend/util/QbApiUtil.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { Method } from "axios";
|
||||||
|
import axios from "axios";
|
||||||
|
import QbAddressDto from "../entity/dto/QbAddressDto";
|
||||||
|
import GlobalService from '../service/GlobalConfigService';
|
||||||
|
import { setUncaughtExceptionCaptureCallback } from "process";
|
||||||
|
|
||||||
|
//qb状态,true正常,false:无法访问
|
||||||
|
let qbStatus = true;
|
||||||
|
let qbInfo: QbAddressDto = null;
|
||||||
|
let cookie: string = null;
|
||||||
|
|
||||||
|
export function getQbStatus() {
|
||||||
|
return qbStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateQbInfo(info: QbAddressDto, status: boolean) {
|
||||||
|
if (!info) {
|
||||||
|
let obj = await GlobalService.getMultVal(["qbAddress", "qbUsername", "qbPassword"]);
|
||||||
|
if (!obj.qbAddress) {
|
||||||
|
qbStatus = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qbInfo.address = obj.qbAddress;
|
||||||
|
qbInfo.username = obj.qbUsername;
|
||||||
|
qbInfo.password = obj.qbPassword;
|
||||||
|
} else {
|
||||||
|
qbInfo = info;
|
||||||
|
}
|
||||||
|
if (status) {
|
||||||
|
qbStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.defaults.baseURL = qbInfo.address;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function get() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function post() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function request(method: Method, url: string, query: any, body: any, isForm = false) {
|
||||||
|
if (!qbStatus) {
|
||||||
|
throw new Error("qbittorrent无法连接,请检查配置");
|
||||||
|
}
|
||||||
|
let isTryLogin = false;
|
||||||
|
while (true) {
|
||||||
|
let headers = { "Cookie": cookie };
|
||||||
|
if (isForm) {
|
||||||
|
headers['content-type'] = "multipart/form-data";
|
||||||
|
} else if (method == "post") {
|
||||||
|
headers['content-type'] = "application/json";
|
||||||
|
}
|
||||||
|
let res = await axios.request({
|
||||||
|
baseURL: qbInfo.address,
|
||||||
|
url: url,
|
||||||
|
method,
|
||||||
|
params: query,
|
||||||
|
data: body,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
if (res.status == 200) {
|
||||||
|
return res.data;
|
||||||
|
} if (res.status == 403) {
|
||||||
|
if (isTryLogin) {
|
||||||
|
throw new Error("qb用户名密码设置有误");
|
||||||
|
} else {
|
||||||
|
await tryLogin(qbInfo.address, qbInfo.username, qbInfo.password, true);
|
||||||
|
isTryLogin = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error("请求报错:" + res.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tryLogin(address: string, username: string, password: string, updateStatus: boolean): Promise<void> {
|
||||||
|
let body = { username, password };
|
||||||
|
try {
|
||||||
|
let res = await axios.post(address + "/api/v2/auth/login", body, {
|
||||||
|
headers: { "Content-Type": "multipart/form-data;boundary=--------------------------125002698093981740970152" }
|
||||||
|
});
|
||||||
|
let success = res.data.toLocaleLowerCase().contains('ok');
|
||||||
|
if (updateStatus) {
|
||||||
|
qbStatus = success;
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
throw new Error("登录失败");
|
||||||
|
} else {
|
||||||
|
cookie = res.headers['Cookie'];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("登录报错:", error);
|
||||||
|
if (updateStatus) {
|
||||||
|
qbStatus = false;
|
||||||
|
}
|
||||||
|
throw new Error("登录出错");
|
||||||
|
}
|
||||||
|
}
|
12
openRenamerFront/jsconfig.json
Normal file
12
openRenamerFront/jsconfig.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
},
|
||||||
|
"target": "ES6",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"element-plus": "^2.2.25",
|
"element-plus": "^2.2.25",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.2.45",
|
||||||
"vue-router": "^4.0.0-0"
|
"vue-router": "^4.0.0-0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app">
|
<div class="app">
|
||||||
<el-menu :default-active="activeIndex" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" router>
|
<el-menu :default-active="activeIndex" mode="horizontal" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" router>
|
||||||
<el-menu-item index="">重命名</el-menu-item>
|
<el-menu-item index="/">重命名</el-menu-item>
|
||||||
|
<el-sub-menu index="/download">
|
||||||
|
<template #title>bt下载</template>
|
||||||
|
<el-menu-item index="/download/center">下载中心</el-menu-item>
|
||||||
|
<el-menu-item index="/download/config">配置</el-menu-item>
|
||||||
|
</el-sub-menu>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<router-view />
|
<router-view />
|
||||||
@ -17,7 +22,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
version: "1.2",
|
version: "1.2",
|
||||||
activeIndex: this.$route.hash,
|
activeIndex: this.$route.path,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
@ -7,8 +7,11 @@ const routes = [
|
|||||||
path: "/",
|
path: "/",
|
||||||
name: "Home",
|
name: "Home",
|
||||||
component: Home,
|
component: Home,
|
||||||
},
|
}, {
|
||||||
{
|
path: "/download/config",
|
||||||
|
name: "downloadConfig",
|
||||||
|
component: () => import("@/views/download/config/index"),
|
||||||
|
}, {
|
||||||
path: "/public/login",
|
path: "/public/login",
|
||||||
name: "login",
|
name: "login",
|
||||||
component: Login,
|
component: Login,
|
||||||
|
63
openRenamerFront/src/views/download/config/index.vue
Normal file
63
openRenamerFront/src/views/download/config/index.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div>配置qb</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="left">qb信息</div>
|
||||||
|
<div class="right">{{ qbInfo }}</div>
|
||||||
|
</div>
|
||||||
|
<el-form v-if="showHostConfig" :model="qbBody" label-width="4em">
|
||||||
|
<div v-if="qbReach" style="text-align: center">qb实例不可访问,请重新配置</div>
|
||||||
|
<el-form-item label="qb地址"><el-input type="text" v-model="qbbody.address" placeholder="例如:http://192.168.1.4:8080" /></el-form-item>
|
||||||
|
<el-form-item label="用户名"><el-input type="text" v-model="qbbody.username" placeholder="qb访问用户名" /></el-form-item>
|
||||||
|
<el-form-item label="密码"><el-input type="password" v-model="qbbody.password" placeholder="qb访问密码" /></el-form-item>
|
||||||
|
<div style="text-align: center"><el-button type="primary" @click="submitQb">提交</el-button></div>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, computed } from "vue";
|
||||||
|
import http from "@/utils/HttpUtil";
|
||||||
|
//表单
|
||||||
|
const qbBody = reactive({
|
||||||
|
address: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
});
|
||||||
|
//配置中心数据
|
||||||
|
let downloadConfig = reactive({});
|
||||||
|
//qb是否可访问
|
||||||
|
let qbReach = ref(true);
|
||||||
|
|
||||||
|
const qbInfo = computed(() => {
|
||||||
|
if (downloadConfig.qbAddress) {
|
||||||
|
return downloadConfig.qbAddress + " 用户名:" + downloadConfig.qbUsername;
|
||||||
|
} else {
|
||||||
|
return "尚未配置";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const showHostConfig = computed(() => {
|
||||||
|
return !downloadConfig.qbAddress || !qbReach;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
downloadConfig = reactive(await http.post("/config/multCode", null, ["qbAddress", "qbUsername", "qbPassword"]));
|
||||||
|
});
|
||||||
|
|
||||||
|
async function submitQb() {
|
||||||
|
let res = await http.post('')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
text-align: left;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
.left {
|
||||||
|
width: 6em;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
x
Reference in New Issue
Block a user