mirror of https://github.com/certd/certd
chore:
parent
154f627f2a
commit
92aa4a6d63
|
@ -22,3 +22,18 @@ export async function getInstallInfo(): Promise<SysInstallInfo> {
|
||||||
method: "get"
|
method: "get"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSiteInfo(): Promise<SysInstallInfo> {
|
||||||
|
return await request({
|
||||||
|
url: "/basic/settings/siteInfo",
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function bindUrl(data): Promise<SysInstallInfo> {
|
||||||
|
return await request({
|
||||||
|
url: "/sys/plus/bindUrl",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import dayjs from "dayjs";
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { message, Modal } from "ant-design-vue";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -90,6 +91,7 @@ const formState = reactive({
|
||||||
code: ""
|
code: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
async function doActive() {
|
async function doActive() {
|
||||||
if (!formState.code) {
|
if (!formState.code) {
|
||||||
message.error("请输入激活码");
|
message.error("请输入激活码");
|
||||||
|
@ -100,7 +102,19 @@ async function doActive() {
|
||||||
await userStore.reInit();
|
await userStore.reInit();
|
||||||
Modal.success({
|
Modal.success({
|
||||||
title: "激活成功",
|
title: "激活成功",
|
||||||
content: `您已成功激活专业版,有效期至:${dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD")}`
|
content: `您已成功激活专业版,有效期至:${dayjs(userStore.plusInfo.expireTime).format("YYYY-MM-DD")}`,
|
||||||
|
onOk() {
|
||||||
|
if (!(settingStore.installInfo.bindUserId > 0)) {
|
||||||
|
//未绑定账号
|
||||||
|
Modal.confirm({
|
||||||
|
title: "是否绑定袖手账号",
|
||||||
|
content: "绑定账号后,可以避免专业版License丢失,强烈建议绑定",
|
||||||
|
onOk() {
|
||||||
|
router.push("/sys/account");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +146,7 @@ function openUpgrade() {
|
||||||
<li>可加VIP群,需求优先实现</li>
|
<li>可加VIP群,需求优先实现</li>
|
||||||
<li>证书流水线数量无限制(免费版限制10条)</li>
|
<li>证书流水线数量无限制(免费版限制10条)</li>
|
||||||
<li>免配置发邮件功能</li>
|
<li>免配置发邮件功能</li>
|
||||||
<li>FTP上传、cdnfly、宝塔、易盾等部署插件</li>
|
<li>FTP上传、cdnfly、宝塔、易盾、群晖等部署插件</li>
|
||||||
<li>更多特权敬请期待</li>
|
<li>更多特权敬请期待</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -144,7 +158,6 @@ function openUpgrade() {
|
||||||
<span>站点ID:</span>
|
<span>站点ID:</span>
|
||||||
<fs-copyable class="flex-1" v-model={computedSiteId.value}></fs-copyable>
|
<fs-copyable class="flex-1" v-model={computedSiteId.value}></fs-copyable>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-10">注意保存好数据库,暂不支持换绑(默认数据库路径/data/certd/db.sqlite)</div>
|
|
||||||
<a-input class="mt-10" v-model:value={formState.code} placeholder={placeholder} />
|
<a-input class="mt-10" v-model:value={formState.code} placeholder={placeholder} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ export const sysResources = [
|
||||||
title: "账号绑定",
|
title: "账号绑定",
|
||||||
name: "account",
|
name: "account",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "ion:settings-outline",
|
icon: "ion:golf-outline",
|
||||||
permission: "sys:settings:view"
|
permission: "sys:settings:view"
|
||||||
},
|
},
|
||||||
path: "/sys/account",
|
path: "/sys/account",
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { theme } from "ant-design-vue";
|
import { Modal, theme } from "ant-design-vue";
|
||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { LocalStorage } from "/src/utils/util.storage";
|
import { LocalStorage } from "/src/utils/util.storage";
|
||||||
|
|
||||||
import * as basicApi from "/@/api/modules/api.basic";
|
import * as basicApi from "/@/api/modules/api.basic";
|
||||||
import { SysInstallInfo, SysPublicSetting } from "/@/api/modules/api.basic";
|
import { SysInstallInfo, SysPublicSetting } from "/@/api/modules/api.basic";
|
||||||
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
|
import { mitter } from "/@/utils/util.mitt";
|
||||||
|
|
||||||
export type ThemeToken = {
|
export type ThemeToken = {
|
||||||
token: {
|
token: {
|
||||||
|
@ -24,6 +26,16 @@ export interface SettingState {
|
||||||
installInfo?: {
|
installInfo?: {
|
||||||
siteId: string;
|
siteId: string;
|
||||||
installTime?: number;
|
installTime?: number;
|
||||||
|
bindUserId?: number;
|
||||||
|
bindUrl?: string;
|
||||||
|
accountServerBaseUrl?: string;
|
||||||
|
appKey?: string;
|
||||||
|
};
|
||||||
|
siteInfo?: {
|
||||||
|
TITLE: string;
|
||||||
|
SLOGAN: string;
|
||||||
|
LOGO: string;
|
||||||
|
ICP_NO: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +57,17 @@ export const useSettingStore = defineStore({
|
||||||
managerOtherUserPipeline: false
|
managerOtherUserPipeline: false
|
||||||
},
|
},
|
||||||
installInfo: {
|
installInfo: {
|
||||||
siteId: ""
|
siteId: "",
|
||||||
|
bindUserId: null,
|
||||||
|
bindUrl: "",
|
||||||
|
accountServerBaseUrl: "",
|
||||||
|
appKey: ""
|
||||||
|
},
|
||||||
|
siteInfo: {
|
||||||
|
TITLE: "",
|
||||||
|
SLOGAN: "",
|
||||||
|
LOGO: "",
|
||||||
|
ICP_NO: ""
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
@ -64,9 +86,59 @@ export const useSettingStore = defineStore({
|
||||||
const settings = await basicApi.getSysPublicSettings();
|
const settings = await basicApi.getSysPublicSettings();
|
||||||
_.merge(this.sysPublic, settings);
|
_.merge(this.sysPublic, settings);
|
||||||
|
|
||||||
|
const siteInfo = await basicApi.getSiteInfo();
|
||||||
|
_.merge(this.siteInfo, siteInfo);
|
||||||
|
|
||||||
|
await this.loadInstallInfo();
|
||||||
|
|
||||||
|
await this.checkUrlBound();
|
||||||
|
},
|
||||||
|
async loadInstallInfo() {
|
||||||
const installInfo = await basicApi.getInstallInfo();
|
const installInfo = await basicApi.getInstallInfo();
|
||||||
_.merge(this.installInfo, installInfo);
|
_.merge(this.installInfo, installInfo);
|
||||||
},
|
},
|
||||||
|
async checkUrlBound() {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
if (!userStore.isAdmin || !userStore.isPlus) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bindUrl = this.installInfo.bindUrl;
|
||||||
|
|
||||||
|
function getBaseUrl() {
|
||||||
|
let url = window.location.href;
|
||||||
|
//只要hash前面的部分
|
||||||
|
url = url.split("#")[0];
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const doBindUrl = async (url: string) => {
|
||||||
|
await basicApi.bindUrl({ url });
|
||||||
|
await this.loadInstallInfo();
|
||||||
|
};
|
||||||
|
const baseUrl = getBaseUrl();
|
||||||
|
if (!bindUrl) {
|
||||||
|
//绑定url
|
||||||
|
await doBindUrl(baseUrl);
|
||||||
|
} else {
|
||||||
|
//检查当前url 是否与绑定的url一致
|
||||||
|
const url = window.location.href;
|
||||||
|
if (!url.startsWith(bindUrl)) {
|
||||||
|
Modal.confirm({
|
||||||
|
title: "URL地址有变化",
|
||||||
|
content: "以后都用这个新地址访问本系统吗?",
|
||||||
|
onOk: async () => {
|
||||||
|
await doBindUrl(baseUrl);
|
||||||
|
},
|
||||||
|
okText: "是的,继续",
|
||||||
|
cancelText: "不是,回到原来的地址",
|
||||||
|
onCancel: () => {
|
||||||
|
window.location.href = bindUrl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
persistThemeConfig() {
|
persistThemeConfig() {
|
||||||
LocalStorage.set(SETTING_THEME_KEY, this.getThemeConfig);
|
LocalStorage.set(SETTING_THEME_KEY, this.getThemeConfig);
|
||||||
},
|
},
|
||||||
|
@ -109,3 +181,7 @@ export const useSettingStore = defineStore({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mitter.on("app.login", async () => {
|
||||||
|
await useSettingStore().init();
|
||||||
|
});
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<fs-page class="cd-page-account">
|
<fs-page class="cd-page-account">
|
||||||
<iframe ref="iframeRef" class="account-iframe" src="http://localhost:1017/#/?appKey=z4nXOeTeSnnpUpnmsV"> </iframe>
|
<template #header>
|
||||||
|
<div class="title">
|
||||||
|
站点绑定
|
||||||
|
<span class="sub">管理你安装过的Certd站点,可以通过转移功能避免丢失VIP,强烈建议绑定</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<iframe ref="iframeRef" class="account-iframe" :src="iframeSrcRef"> </iframe>
|
||||||
</fs-page>
|
</fs-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import { IframeClient } from "@certd/lib-iframe";
|
import { IframeClient } from "@certd/lib-iframe";
|
||||||
import { onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
import { useUserStore } from "/@/store/modules/user";
|
import { useUserStore } from "/@/store/modules/user";
|
||||||
import { useSettingStore } from "/@/store/modules/settings";
|
import { useSettingStore } from "/@/store/modules/settings";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
|
@ -15,6 +22,14 @@ const iframeRef = ref();
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
|
|
||||||
|
const iframeSrcRef = computed(() => {
|
||||||
|
if (!settingStore.installInfo.accountServerBaseUrl) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return `${settingStore.installInfo.accountServerBaseUrl}/#/?appKey=${settingStore.installInfo.appKey}`;
|
||||||
|
});
|
||||||
|
|
||||||
type SubjectInfo = {
|
type SubjectInfo = {
|
||||||
subjectId: string;
|
subjectId: string;
|
||||||
installTime?: number;
|
installTime?: number;
|
||||||
|
|
|
@ -96,6 +96,7 @@ export default ({ command, mode }) => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
host: "0.0.0.0",
|
||||||
port: 3002,
|
port: 3002,
|
||||||
fs: devServerFs,
|
fs: devServerFs,
|
||||||
proxy: {
|
proxy: {
|
||||||
|
|
|
@ -6,3 +6,7 @@ plus:
|
||||||
#plus:
|
#plus:
|
||||||
# server:
|
# server:
|
||||||
# baseUrl: 'https://api.ai.handsfree.work'
|
# baseUrl: 'https://api.ai.handsfree.work'
|
||||||
|
|
||||||
|
account:
|
||||||
|
server:
|
||||||
|
baseUrl: 'http://127.0.0.1:1017/subject'
|
||||||
|
|
|
@ -10,3 +10,7 @@ typeorm:
|
||||||
plus:
|
plus:
|
||||||
server:
|
server:
|
||||||
baseUrl: 'https://api.ai.handsfree.work'
|
baseUrl: 'https://api.ai.handsfree.work'
|
||||||
|
|
||||||
|
account:
|
||||||
|
server:
|
||||||
|
baseUrl: 'https://ai.handsfree.work/subject'
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { Controller, Get, Inject, Provide } from '@midwayjs/core';
|
import { Config, Controller, Get, Inject, Provide } from '@midwayjs/core';
|
||||||
import { BaseController } from '../../../basic/base-controller.js';
|
import { BaseController } from '../../../basic/base-controller.js';
|
||||||
import { Constants } from '../../../basic/constants.js';
|
import { Constants } from '../../../basic/constants.js';
|
||||||
import { SysSettingsService } from '../../system/service/sys-settings-service.js';
|
import { SysSettingsService } from '../../system/service/sys-settings-service.js';
|
||||||
import { SysInstallInfo, SysPublicSettings, SysSiteInfo } from '../../system/service/models.js';
|
import { SysInstallInfo, SysPublicSettings, SysSiteInfo } from '../../system/service/models.js';
|
||||||
|
import { AppKey } from '@certd/pipeline';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +12,8 @@ import { SysInstallInfo, SysPublicSettings, SysSiteInfo } from '../../system/ser
|
||||||
export class BasicSettingsController extends BaseController {
|
export class BasicSettingsController extends BaseController {
|
||||||
@Inject()
|
@Inject()
|
||||||
sysSettingsService: SysSettingsService;
|
sysSettingsService: SysSettingsService;
|
||||||
|
@Config('account.server.baseUrl')
|
||||||
|
accountServerBaseUrl: any;
|
||||||
|
|
||||||
@Get('/public', { summary: Constants.per.guest })
|
@Get('/public', { summary: Constants.per.guest })
|
||||||
public async getSysPublic() {
|
public async getSysPublic() {
|
||||||
|
@ -20,13 +23,15 @@ export class BasicSettingsController extends BaseController {
|
||||||
|
|
||||||
@Get('/install', { summary: Constants.per.guest })
|
@Get('/install', { summary: Constants.per.guest })
|
||||||
public async getInstallInfo() {
|
public async getInstallInfo() {
|
||||||
const settings = await this.sysSettingsService.getSetting(SysInstallInfo);
|
const settings: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||||
|
settings.accountServerBaseUrl = this.accountServerBaseUrl;
|
||||||
|
settings.appKey = AppKey;
|
||||||
return this.ok(settings);
|
return this.ok(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('/siteInfo', { summary: Constants.per.guest })
|
@Get('/siteInfo', { summary: Constants.per.guest })
|
||||||
public async getSiteInfo() {
|
public async getSiteInfo() {
|
||||||
const settings = await this.sysSettingsService.getSetting(SysSiteInfo);
|
const settings: SysSiteInfo = await this.sysSettingsService.getSetting(SysSiteInfo);
|
||||||
return this.ok(settings);
|
return this.ok(settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,4 +97,15 @@ export class PlusService {
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async bindUrl(subjectId: string, url: string) {
|
||||||
|
return await this.request({
|
||||||
|
url: '/activation/subject/urlBind',
|
||||||
|
data: {
|
||||||
|
subjectId,
|
||||||
|
appKey: AppKey,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,18 @@ export class SysPlusController extends BaseController {
|
||||||
|
|
||||||
await this.plusService.updateLicense(siteId, license);
|
await this.plusService.updateLicense(siteId, license);
|
||||||
|
|
||||||
|
return this.ok(true);
|
||||||
|
}
|
||||||
|
@Post('/bindUrl', { summary: 'sys:settings:edit' })
|
||||||
|
async bindUrl(@Body(ALL) body: { url: string }) {
|
||||||
|
const { url } = body;
|
||||||
|
|
||||||
|
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||||
|
await this.plusService.bindUrl(installInfo.siteId, url);
|
||||||
|
|
||||||
|
installInfo.bindUrl = url;
|
||||||
|
await this.sysSettingsService.saveSetting(installInfo);
|
||||||
|
|
||||||
return this.ok(true);
|
return this.ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ export class SysInstallInfo extends BaseSettings {
|
||||||
siteId?: string;
|
siteId?: string;
|
||||||
bindUserId?: number;
|
bindUserId?: number;
|
||||||
bindUrl?: string;
|
bindUrl?: string;
|
||||||
|
accountServerBaseUrl?: string;
|
||||||
|
appKey?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SysLicenseInfo extends BaseSettings {
|
export class SysLicenseInfo extends BaseSettings {
|
||||||
|
|
Loading…
Reference in New Issue