Merge branch 'v2-dev-buy' into v2-dev

pull/576/head
xiaojunnuo 2025-11-09 02:06:57 +08:00
commit c3637e731f
13 changed files with 216 additions and 89 deletions

View File

@ -130,12 +130,15 @@ export class PlusService {
return res.accessToken; return res.accessToken;
} }
async getVipTrial() { async getVipTrial(vipType= "plus") {
await this.register(); await this.register();
const plusRequestService = await this.getPlusRequestService(); const plusRequestService = await this.getPlusRequestService();
const res = await plusRequestService.request({ const res = await plusRequestService.request({
url: '/activation/subject/vip/trialGet', url: '/activation/subject/vip/trialGet',
method: 'POST', method: 'POST',
data:{
vipType
}
}); });
if (res.license) { if (res.license) {
await this.updateLicense(res.license); await this.updateLicense(res.license);

View File

@ -10,4 +10,4 @@ VITE_APP_LOGO=static/images/logo/logo.svg
VITE_APP_LOGIN_LOGO=static/images/logo/rect-black.svg VITE_APP_LOGIN_LOGO=static/images/logo/rect-black.svg
VITE_APP_PROJECT_PATH=https://github.com/certd/certd VITE_APP_PROJECT_PATH=https://github.com/certd/certd
VITE_APP_NAMESPACE=fs VITE_APP_NAMESPACE=fs
VITE_APP_VIP_PRODUCT_URL=http://localhost:1017/subject#/product/list VITE_APP_VIP_PRODUCT_URL="http://localhost:1017/subject#/app/certd/product"

View File

@ -1,3 +1,6 @@
VITE_APP_API=api VITE_APP_API=api
#登录与权限开启 #登录与权限开启
VITE_APP_PM_ENABLED=true VITE_APP_PM_ENABLED=true
VITE_APP_VIP_PRODUCT_URL="https://app.handfree.work/subject#/app/certd/product"

View File

@ -8,10 +8,10 @@ export async function doActive(form: any) {
}); });
} }
export async function getVipTrial() { export async function getVipTrial(vipType: string) {
return await request({ return await request({
url: "/sys/plus/getVipTrial", url: "/sys/plus/getVipTrial",
method: "post", method: "post",
data: {}, data: { vipType },
}); });
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div v-if="!settingStore.isComm || userStore.isAdmin" class="layout-vip isPlus" @click="openUpgrade"> <div v-if="!settingStore.isComm || userStore.isAdmin" class="layout-vip isPlus" :class="{ isForever: settingStore.isForever }" @click="openUpgrade">
<contextHolder /> <contextHolder />
<fs-icon icon="mingcute:vip-1-line" :title="text.title" /> <fs-icon icon="mingcute:vip-1-line" :title="text.title" />
@ -12,7 +12,7 @@
</div> </div>
</template> </template>
<script lang="tsx" setup> <script lang="tsx" setup>
import { computed, onMounted, reactive } from "vue"; import { computed, onMounted, reactive, ref } from "vue";
import dayjs from "dayjs"; 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";
@ -21,7 +21,7 @@ import { useRouter } from "vue-router";
import { useUserStore } from "/@/store/user"; import { useUserStore } from "/@/store/user";
import { mitter } from "/@/utils/util.mitt"; import { mitter } from "/@/utils/util.mitt";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { env } from "/@/utils/util.env";
const { t } = useI18n(); const { t } = useI18n();
const settingStore = useSettingStore(); const settingStore = useSettingStore();
@ -106,7 +106,7 @@ const text = computed<Text>(() => {
const expireTime = computed(() => { const expireTime = computed(() => {
if (settingStore.isPlus) { if (settingStore.isPlus) {
return dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD"); return settingStore.expiresText;
} }
return ""; return "";
}); });
@ -165,34 +165,38 @@ function goAccount() {
router.push("/sys/account"); router.push("/sys/account");
} }
async function getVipTrial() { async function getVipTrial(vipType = "plus") {
const res = await api.getVipTrial(); const res = await api.getVipTrial(vipType);
message.success(t("vip.congratulations_vip_trial", { duration: res.duration })); message.success(t("vip.congratulations_vip_trial", { duration: res.duration }));
await settingStore.init(); await settingStore.init();
} }
function openTrialModal() { function openTrialModal(vipType = "plus") {
Modal.destroyAll(); Modal.destroyAll();
modal.confirm({ modal.confirm({
title: t("vip.trial_modal_title"), title: t("vip.trial_modal_title"),
okText: t("vip.trial_modal_ok_text"), okText: t("vip.trial_modal_ok_text"),
onOk() { onOk() {
getVipTrial(); getVipTrial(vipType);
}, },
width: 600, width: 600,
content: () => { content: () => {
return ( return (
<div class="flex-col mt-10 mb-10"> <div class="flex-col mt-10 mb-10">
<div>{t("vip.trial_modal_thanks")}</div> <div>{t("vip.trial_modal_thanks")}</div>
<div>{t("vip.trial_modal_click_confirm")}</div> <div>{t("vip.trial_modal_click_confirm", { vipType })}</div>
</div> </div>
); );
}, },
}); });
} }
function openStarModal() { function openStarModal(vipType: string) {
if (settingStore.isPlus) {
message.error(t("vip.already_vip"));
return;
}
Modal.destroyAll(); Modal.destroyAll();
const goGithub = () => { const goGithub = () => {
window.open("https://github.com/certd/certd/"); window.open("https://github.com/certd/certd/");
@ -203,7 +207,7 @@ function openStarModal() {
okText: t("vip.star_now"), okText: t("vip.star_now"),
onOk() { onOk() {
goGithub(); goGithub();
openTrialModal(); openTrialModal(vipType);
}, },
width: 600, width: 600,
content: () => { content: () => {
@ -231,7 +235,49 @@ function openUpgrade() {
title = t("vip.renew_pro_upgrade_business"); title = t("vip.renew_pro_upgrade_business");
} }
// const goBuyUrl = "https://afdian.com/a/greper"
const subjectId = settingStore.installInfo.siteId;
const appKey = settingStore.installInfo.appKey;
const location = window.location;
const callbackUrl = encodeURIComponent(`${location.origin}${location.pathname}#/sys/account`);
const goBuyUrl = `${env.VIP_PRODUCT_URL}?appKey=${appKey}&subjectId=${subjectId}&callback=${callbackUrl}`;
const goBuyCommUrl = `${goBuyUrl}&vipType=comm`;
const productInfo = settingStore.productInfo; const productInfo = settingStore.productInfo;
function checkPerpetualPlus() {
if (settingStore.isPerpetual) {
Modal.warn({
title: t("vip.already_perpetual_plus"),
okText: t("vip.confirm"),
});
throw new Error(t("vip.already_perpetual_plus"));
}
}
function goBuyPlusPage() {
checkPerpetualPlus();
if (settingStore.isComm) {
Modal.warn({
title: t("vip.already_comm"),
okText: t("vip.confirm"),
});
return;
}
window.open(goBuyUrl);
}
function goBuyCommPage() {
checkPerpetualPlus();
if (settingStore.isPlus && !settingStore.isComm) {
Modal.confirm({
title: t("vip.already_plus"),
okText: t("vip.confirm"),
onOk() {
window.open(goBuyCommUrl);
},
});
return;
}
window.open(goBuyCommUrl);
}
const vipTypeDefine = { const vipTypeDefine = {
free: { free: {
title: t("vip.basic_edition"), title: t("vip.basic_edition"),
@ -248,7 +294,7 @@ function openUpgrade() {
trial: { trial: {
title: t("vip.click_to_get_7_day_trial"), title: t("vip.click_to_get_7_day_trial"),
click: () => { click: () => {
openStarModal(); openStarModal("plus");
}, },
}, },
icon: "stash:thumb-up", icon: "stash:thumb-up",
@ -258,7 +304,7 @@ function openUpgrade() {
get() { get() {
return ( return (
<a-tooltip title={t("vip.afdian_support_vip")}> <a-tooltip title={t("vip.afdian_support_vip")}>
<a-button size="small" type="primary" href="https://afdian.com/a/greper" target="_blank"> <a-button size="small" type="primary" onClick={goBuyPlusPage}>
{t("vip.get_after_support")} {t("vip.get_after_support")}
</a-button> </a-button>
</a-tooltip> </a-tooltip>
@ -274,30 +320,57 @@ function openUpgrade() {
price: productInfo.comm.price, price: productInfo.comm.price,
price3: `¥${productInfo.comm.price3}/3${t("vip.years")}`, price3: `¥${productInfo.comm.price3}/3${t("vip.years")}`,
tooltip: productInfo.comm.tooltip, tooltip: productInfo.comm.tooltip,
trial: {
title: t("vip.click_to_get_7_day_trial"),
click: () => {
openStarModal("comm");
},
},
get() { get() {
return <a-button size="small">{t("vip.contact_author_for_trial")}</a-button>; return (
<a-button size="small" type="primary" onClick={goBuyCommPage}>
{t("vip.buy")}
</a-button>
);
}, },
}, },
}; };
const modalRef = modal.confirm({ const manualActiveFlag = ref();
function showManualActivation() {
manualActiveFlag.value = true;
}
const modalRef = modal.success({
title, title,
async onOk() {
return await doActive();
},
maskClosable: true, maskClosable: true,
okText: t("vip.activate"), okText: t("vip.close"),
width: 1100, width: 1100,
content: () => { content: () => {
let activationCodeGetWay = ( let manualActiveBlock: any = "";
<span> if (manualActiveFlag.value) {
<a href="https://afdian.com/a/greper" target="_blank"> manualActiveBlock = (
{t("vip.get_pro_code_after_support")} <div>
</a> <div class="mt-10">
<span> {t("vip.business_contact_author")}</span> <a-input-search class="w-2/6" v-model:value={formState.code} placeholder={placeholder} enter-button={t("vip.activate")} onSearch={doActive}></a-input-search>
</span> </div>
<div class="mt-10">
{t("vip.activation_code_one_use")}
<a onClick={goAccount}>{t("vip.bind_account")}</a>{t("vip.transfer_vip")}
</div>
</div>
); );
}
const vipLabel = settingStore.vipLabel; const vipLabel = settingStore.vipLabel;
let plusInfo: any = "";
if (isPlus) {
plusInfo = (
<div class="mt-10">
{t("vip.current")} {vipLabel} {t("vip.activated_expire_time")}
{settingStore.expiresText}
</div>
);
}
const slots = []; const slots = [];
for (const key in vipTypeDefine) { for (const key in vipTypeDefine) {
// @ts-ignore // @ts-ignore
@ -362,27 +435,20 @@ function openUpgrade() {
<div class="vip-type-vs"> <div class="vip-type-vs">
<a-row gutter={20}>{slots}</a-row> <a-row gutter={20}>{slots}</a-row>
</div> </div>
<div class="mt-10">
<h3 class="block-header">{isPlus ? t("vip.renew") : t("vip.activate_immediately")}</h3>
<div>{isPlus ? `${t("vip.current")} ${vipLabel} ${t("vip.activated_expire_time")}` + dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD") : ""}</div>
<div class="mt-10"> <div class="mt-10">
<div class="flex-o w-100"> <div class="flex-o w-100">
<span>{t("vip.site_id")}</span> <span>{t("vip.site_id")}</span>
<fs-copyable class="flex-1" v-model={computedSiteId.value}></fs-copyable> <fs-copyable v-model={computedSiteId.value}></fs-copyable>
</div> </div>
<a-input class="mt-10" v-model:value={formState.code} placeholder={placeholder} />
<a-input class="mt-10" v-model:value={formState.inviteCode} placeholder={t("vip.invite_code_optional")} />
</div> </div>
{plusInfo}
<div class="mt-10"> <div class="mt-10">
{t("vip.no_activation_code")} {t("vip.have_activation_code")}
{activationCodeGetWay} <span>
</div> <a onClick={showManualActivation}>{t("vip.manual_activation")}</a>
<div class="mt-10"> </span>
{t("vip.activation_code_one_use")}
<a onClick={goAccount}>{t("vip.bind_account")}</a>{t("vip.transfer_vip")}
</div>
</div> </div>
<div class="mt-10">{manualActiveBlock}</div>
</div> </div>
); );
}, },
@ -406,6 +472,10 @@ onMounted(() => {
&.isPlus { &.isPlus {
color: #c5913f; color: #c5913f;
&.isForever {
color: #ff2e83;
}
} }
.text { .text {
@ -420,6 +490,11 @@ onMounted(() => {
border: 1px solid #eee; border: 1px solid #eee;
border-radius: 5px; border-radius: 5px;
height: 275px; height: 275px;
line-height: 24px;
.privilege {
margin-top: 5px;
}
//background-color: rgba(250, 237, 167, 0.79); //background-color: rgba(250, 237, 167, 0.79);
&.current { &.current {

View File

@ -32,13 +32,14 @@ export default {
successContent: "You have successfully activated {vipLabel}, valid until: {expireDate}", successContent: "You have successfully activated {vipLabel}, valid until: {expireDate}",
bindAccountTitle: "Bind Your Account", bindAccountTitle: "Bind Your Account",
bindAccountContent: "Binding your account helps prevent license loss. Strongly recommended.", bindAccountContent: "Binding your account helps prevent license loss. Strongly recommended.",
congratulations_vip_trial: "Congratulations, you have received a Pro version {duration} days trial", congratulations_vip_trial: "Congratulations, you have received a VIP version {duration} days trial",
trial_modal_title: "7-day Pro version trial acquisition", trial_modal_title: "7-day VIP version trial acquisition",
trial_modal_ok_text: "Get now", trial_modal_ok_text: "Get now",
trial_modal_thanks: "Thank you for supporting the open source project", trial_modal_thanks: "Thank you for supporting the open source project",
trial_modal_click_confirm: "Click confirm to get a 7-day Pro version trial", trial_modal_click_confirm: "Click confirm to get a 7-day VIP({vipType}) version trial",
get_7_day_pro_trial: "7-day professional version trial", get_7_day_pro_trial: "7-day VIP version trial",
star_now: "Star Now", star_now: "Star Now",
already_vip: "Already VIP version, can't trial ",
please_help_star: "Could you please help by starring? Thanks a lot!", please_help_star: "Could you please help by starring? Thanks a lot!",
admin_only_operation: "Admin operation only", admin_only_operation: "Admin operation only",
enter_activation_code: "Please enter the activation code", enter_activation_code: "Please enter the activation code",
@ -61,7 +62,7 @@ export default {
plugins_fully_open: "All plugins open, including Synology and more", plugins_fully_open: "All plugins open, including Synology and more",
click_to_get_7_day_trial: "Click to get 7-day trial", click_to_get_7_day_trial: "Click to get 7-day trial",
years: "years", years: "years",
afdian_support_vip: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian, open source needs your support', afdian_support_vip: "Obtain the permanent professional version coupon",
get_after_support: "Get after sponsoring", get_after_support: "Get after sponsoring",
business_edition: "Business Edition", business_edition: "Business Edition",
@ -72,9 +73,9 @@ export default {
plugin_management: "Plugin management", plugin_management: "Plugin management",
unlimited_multi_users: "Unlimited multi-users", unlimited_multi_users: "Unlimited multi-users",
support_user_payment: "Supports user payments", support_user_payment: "Supports user payments",
contact_author_for_trial: "Please contact the author for trial", contact_author_for_trial: "Buy It Now",
activate: "Activate", activate: "Activate",
get_pro_code_after_support: 'Get a one-year professional activation code after supporting "VIP membership" on Afdian', get_pro_code_after_support: "Go to sponsoring",
business_contact_author: "Business edition please contact the author directly", business_contact_author: "Business edition please contact the author directly",
year: "year", year: "year",
freee: "Free", freee: "Free",
@ -89,4 +90,12 @@ export default {
bind_account: "bind account", bind_account: "bind account",
transfer_vip: ' then "Transfer VIP"', transfer_vip: ' then "Transfer VIP"',
needVipTip: "This feature requires a professional version, please upgrade to a professional version first.", needVipTip: "This feature requires a professional version, please upgrade to a professional version first.",
manual_activation: "Manual activation use code",
close: "Close",
have_activation_code: "Already have activation code?",
buy: "Buy",
already_plus: "Already Professional Edition, will upgrade to Business Edition, Professional Edition time will be lost",
already_comm: "Already Business Edition, can't change to Professional Edition",
already_perpetual_plus: "You already have a perpetual Professional Edition, can't upgrade",
confirm: "Confirm",
}; };

View File

@ -32,13 +32,14 @@ export default {
successContent: "您已成功激活{vipLabel},有效期至:{expireDate}", successContent: "您已成功激活{vipLabel},有效期至:{expireDate}",
bindAccountTitle: "是否绑定袖手账号", bindAccountTitle: "是否绑定袖手账号",
bindAccountContent: "绑定账号后可以避免License丢失强烈建议绑定", bindAccountContent: "绑定账号后可以避免License丢失强烈建议绑定",
congratulations_vip_trial: "恭喜,您已获得专业版{duration}天试用", congratulations_vip_trial: "恭喜,您已获得VIP{duration}天试用",
trial_modal_title: "7天专业版试用获取", trial_modal_title: "7天VIP试用获取",
trial_modal_ok_text: "立即获取", trial_modal_ok_text: "立即获取",
trial_modal_thanks: "感谢您对开源项目的支持", trial_modal_thanks: "感谢您对开源项目的支持",
trial_modal_click_confirm: "点击确认即可获取7天专业版试用", trial_modal_click_confirm: "点击确认即可获取7天VIP({vipType})试用",
get_7_day_pro_trial: "7天专业版试用获取", get_7_day_pro_trial: "7天VIP试用获取",
star_now: "立即去Star", star_now: "立即去Star",
already_vip: "您已经是VIP了不能试用",
please_help_star: "可以先请您帮忙点个star吗感谢感谢", please_help_star: "可以先请您帮忙点个star吗感谢感谢",
admin_only_operation: "仅限管理员操作", admin_only_operation: "仅限管理员操作",
enter_activation_code: "请输入激活码", enter_activation_code: "请输入激活码",
@ -61,8 +62,8 @@ export default {
plugins_fully_open: "插件全开放,群辉等更多插件", plugins_fully_open: "插件全开放,群辉等更多插件",
click_to_get_7_day_trial: "点击获取7天试用", click_to_get_7_day_trial: "点击获取7天试用",
years: "年", years: "年",
afdian_support_vip: "爱发电赞助“VIP会员”后获取一年期专业版激活码开源需要您的支持", afdian_support_vip: "新用户开通永久专业版立享50优惠券",
get_after_support: "爱发电赞助后获取", get_after_support: "立即赞助",
business_edition: "商业版", business_edition: "商业版",
commercial_license: "商业授权,可对外运营", commercial_license: "商业授权,可对外运营",
@ -72,10 +73,9 @@ export default {
plugin_management: "插件管理", plugin_management: "插件管理",
unlimited_multi_users: "多用户无限制", unlimited_multi_users: "多用户无限制",
support_user_payment: "支持用户支付", support_user_payment: "支持用户支付",
contact_author_for_trial: "请联系作者获取试用",
activate: "激活", activate: "激活",
get_pro_code_after_support: "爱发电赞助“VIP会员”后获取一年期专业版激活码", get_pro_code_after_support: "前往获取",
business_contact_author: "商业版请直接联系作者", business_contact_author: "",
year: "年", year: "年",
freee: "免费", freee: "免费",
renew: "续期", renew: "续期",
@ -89,4 +89,12 @@ export default {
bind_account: "绑定账号", bind_account: "绑定账号",
transfer_vip: ',然后"转移VIP"即可', transfer_vip: ',然后"转移VIP"即可',
needVipTip: "此为专业版功能,请先开通专业版", needVipTip: "此为专业版功能,请先开通专业版",
manual_activation: "激活码手动激活",
close: "关闭",
have_activation_code: "已经有激活码了?",
buy: "立即购买",
already_plus: "已经是专业版了,是否升级为商业版?注意:专业版时长将被覆盖",
already_comm: "已经是商业版了,不能降级为专业版",
already_perpetual_plus: "您已经是永久专业版了,无法继续升级",
confirm: "确认",
}; };

View File

@ -10,6 +10,7 @@ import { useTitle } from "@vueuse/core";
import { utils } from "/@/utils"; import { utils } from "/@/utils";
import { cloneDeep, merge } from "lodash-es"; import { cloneDeep, merge } from "lodash-es";
import { useI18n } from "/src/locales"; import { useI18n } from "/src/locales";
import dayjs from "dayjs";
import { $t } from "/src/locales"; import { $t } from "/src/locales";
export interface SettingState { export interface SettingState {
skipReset?: boolean; // 注销登录时不清空此store的状态 skipReset?: boolean; // 注销登录时不清空此store的状态
@ -126,12 +127,14 @@ export const useSettingStore = defineStore({
getInstallInfo(): SysInstallInfo { getInstallInfo(): SysInstallInfo {
return this.installInfo; return this.installInfo;
}, },
isPerpetual(): boolean {
return this.plusInfo?.isPlus && this.plusInfo?.expireTime === -1;
},
isPlus(): boolean { isPlus(): boolean {
return this.plusInfo?.isPlus && this.plusInfo?.expireTime > new Date().getTime(); return this.plusInfo?.isPlus && (this.plusInfo?.expireTime === -1 || this.plusInfo?.expireTime > new Date().getTime());
// return false;
}, },
isComm(): boolean { isComm(): boolean {
return this.plusInfo?.isComm && this.plusInfo?.expireTime > new Date().getTime(); return this.plusInfo?.isComm && (this.plusInfo?.expireTime === -1 || this.plusInfo?.expireTime > new Date().getTime());
}, },
isAgent(): boolean { isAgent(): boolean {
return this.siteEnv?.agent?.enabled === true; return this.siteEnv?.agent?.enabled === true;
@ -139,6 +142,18 @@ export const useSettingStore = defineStore({
isCommOrAgent() { isCommOrAgent() {
return this.isComm || this.isAgent; return this.isComm || this.isAgent;
}, },
expiresText() {
if (this.plusInfo?.expireTime == null) {
return "";
}
if (this.plusInfo?.expireTime === -1) {
return "永久";
}
return dayjs(this.plusInfo?.expireTime).format("YYYY-MM-DD");
},
isForever() {
return this.isPlus && this.plusInfo?.expireTime === -1;
},
vipLabel(): string { vipLabel(): string {
const { t } = useI18n(); const { t } = useI18n();
const vipLabelMap: any = { const vipLabelMap: any = {

View File

@ -6,22 +6,28 @@ export function getEnvValue(key: string) {
export class EnvConfig { export class EnvConfig {
MODE: string = import.meta.env.MODE; MODE: string = import.meta.env.MODE;
API: string = import.meta.env.VITE_APP_API; API: string;
STORAGE: string = import.meta.env.VITE_APP_STORAGE; STORAGE: string;
TITLE: string = import.meta.env.VITE_APP_TITLE; TITLE: string;
SLOGAN: string = import.meta.env.VITE_APP_SLOGAN; SLOGAN: string;
LOGO: string = import.meta.env.VITE_APP_LOGO; LOGO: string;
LOGIN_LOGO: string = import.meta.env.VITE_APP_LOGIN_LOGO; LOGIN_LOGO: string;
ICP_NO: string = import.meta.env.VITE_APP_ICP_NO; ICP_NO: string;
COPYRIGHT_YEAR: string = import.meta.env.VITE_APP_COPYRIGHT_YEAR; COPYRIGHT_YEAR: string;
COPYRIGHT_NAME: string = import.meta.env.VITE_APP_COPYRIGHT_NAME; COPYRIGHT_NAME: string;
COPYRIGHT_URL: string = import.meta.env.VITE_APP_COPYRIGHT_URL; COPYRIGHT_URL: string;
PM_ENABLED: string = import.meta.env.VITE_APP_PM_ENABLED; PM_ENABLED: string;
VIP_PRODUCT_URL: string;
init(env: any) { constructor() {
this.init();
}
init() {
const env = import.meta.env;
for (const key in this) { for (const key in this) {
if (this.hasOwnProperty(key)) { const metaKey = "VITE_APP_" + key;
this[key] = env[key]; if (this.hasOwnProperty(key) && env.hasOwnProperty(metaKey)) {
this[key] = env[metaKey];
} }
} }
} }

View File

@ -375,7 +375,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}, },
}, },
createTime: { createTime: {
title: t("certd.create_time"), title: t("certd.createTime"),
type: "datetime", type: "datetime",
form: { form: {
show: false, show: false,
@ -387,7 +387,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}, },
}, },
updateTime: { updateTime: {
title: t("certd.update_time"), title: t("certd.updateTime"),
type: "datetime", type: "datetime",
form: { form: {
show: false, show: false,

View File

@ -20,7 +20,7 @@
typeorm: typeorm:
dataSource: dataSource:
default: default:
database: './data/db-plus-dev-1.sqlite' database: './data/db-plus-dev.sqlite'
# plus server: 'http://127.0.0.1:11007' # plus server: 'http://127.0.0.1:11007'
account: account:

View File

@ -1,5 +1,6 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core'; import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from '@certd/lib-server'; import { BaseController, PlusService, SysInstallInfo, SysSettingsService } from '@certd/lib-server';
import { logger } from '@certd/basic';
/** /**
*/ */
@ -31,15 +32,20 @@ export class SysPlusController extends BaseController {
installInfo.bindUrl = url; installInfo.bindUrl = url;
await this.sysSettingsService.saveSetting(installInfo); await this.sysSettingsService.saveSetting(installInfo);
//重新验证配置 //重新验证vip
try{
await this.plusService.verify(); await this.plusService.verify();
}catch(e){
logger.error(`验证配置失败:${e}`);
}
return this.ok(true); return this.ok(true);
} }
@Post('/getVipTrial', { summary: 'sys:settings:edit' }) @Post('/getVipTrial', { summary: 'sys:settings:edit' })
async getVipTrial(@Body(ALL) body) { async getVipTrial(@Body("vipType") vipType?:string) {
const res = await this.plusService.getVipTrial(); const res = await this.plusService.getVipTrial(vipType);
return this.ok(res); return this.ok(res);
} }
// //

View File

@ -134,6 +134,8 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
if (!param.id) { if (!param.id) {
throw new ValidateException("id不能为空"); throw new ValidateException("id不能为空");
} }
//hostRecord包含所有权校验信息不允许用户修改hostRecord
delete param.hostRecord
const old = await this.info(param.id); const old = await this.info(param.id);
if (!old) { if (!old) {