pull/330/head
xiaojunnuo 2024-12-24 01:12:12 +08:00
parent cb27d4b490
commit ffa4de6911
14 changed files with 107 additions and 33 deletions

View File

@ -231,6 +231,7 @@ function openUpgrade() {
title: "基础版",
desc: "社区免费版",
type: "free",
icon: "lucide:package-open",
privilege: ["证书申请无限制", "域名数量无限制", "证书流水线数量无限制", "常用的主机、云平台、cdn等部署插件", "邮件、webhook通知方式"]
},
plus: {
@ -244,6 +245,7 @@ function openUpgrade() {
openStarModal();
}
},
icon: "stash:thumb-up",
price: 29.9,
get() {
return (
@ -259,6 +261,7 @@ function openUpgrade() {
title: "商业版",
desc: "商业授权,可对外运营",
type: "comm",
icon: "vaadin:handshake",
privilege: ["拥有专业版所有特权", "允许商用可修改logo、标题", "数据统计", "插件管理", "多用户无限制", "支持用户支付"],
price: 399,
get() {
@ -293,8 +296,8 @@ function openUpgrade() {
slots.push(
<a-col span={8}>
<div class={vipBlockClass}>
<h3 class="block-header">
<span>{item.title}</span>
<h3 class="block-header ">
<span class="flex-o">{item.title}</span>
{item.trial && (
<span class="trial">
<a-tooltip title={item.trial.message}>
@ -303,8 +306,11 @@ function openUpgrade() {
</span>
)}
</h3>
<div style="color:green">{item.desc}</div>
<ul class="flex-1">
<div style="color:green" class="flex-o">
<fs-icon icon={item.icon} class="fs-16 flex-o" />
{item.desc}
</div>
<ul class="flex-1 privilege">
{item.privilege.map((p: string) => (
<li class="flex-baseline">
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
@ -430,9 +436,13 @@ onMounted(() => {
color: green;
}
.vip-type-vs {
.privilege {
.fs-icon {
color: green;
}
}
.fs-icon {
margin-right: 5px;
color: green;
}
}
}

View File

@ -1,7 +1,7 @@
import Validator from "async-validator";
// 自定义验证器函数
export function isDomain(rule: any, value: any) {
if (value == null) {
if (value == null || value == "") {
return true;
}
let domains: string[] = value;

View File

@ -216,7 +216,7 @@ export const sysResources = [
title: "用户套餐",
name: "UserSuites",
path: "/sys/suite/user-suite",
component: "/certd/suite/user-suite/index.vue",
component: "/sys/suite/user-suite/index.vue",
meta: {
show: () => {
const settingStore = useSettingStore();

View File

@ -59,7 +59,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
order: 0,
type: "link",
text: null,
title: "立即检查",
tooltip: {
title: "立即检查"
},
icon: "ion:play-sharp",
click: async ({ row }) => {
await api.DoCheck(row.id);
@ -107,7 +109,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
type: "text",
form: {
rules: [{ required: true, message: "请输入域名" }]
rules: [
{ required: true, message: "请输入域名" },
{ type: "domains", message: "请输入正确的域名" }
]
},
column: {
width: 160,

View File

@ -76,7 +76,7 @@ async function orderCreate() {
payType: formRef.value.payType
});
function onPaid() {
async function onPaid() {
openRef.value = false;
router.push({
path: "/"
@ -114,7 +114,7 @@ async function orderCreate() {
}
function doAlipay(paymentReq: any) {
window.open(paymentReq.api);
window.open(paymentReq.url);
}
async function doWxpay(qrcodeText: string, onPaid: () => Promise<void>) {
@ -157,7 +157,7 @@ function doYizhifu(paymentReq: any) {
* 签名类型 sign_type String MD5 默认为MD5
*/
const form = document.createElement("form");
form.action = paymentReq.api;
form.action = paymentReq.url;
form.method = "post";
form.target = "_blank";
// form.style.display = "none";

View File

@ -11,7 +11,7 @@
<a-tab-pane key="register" tab="注册设置">
<SettingRegister v-if="activeKey === 'register'" />
</a-tab-pane>
<a-tab-pane key="payment" tab="支付设置">
<a-tab-pane v-if="settingsStore.isComm" key="payment" tab="支付设置">
<SettingPayment v-if="activeKey === 'payment'" />
</a-tab-pane>
</a-tabs>
@ -25,10 +25,11 @@ import SettingRegister from "/@/views/sys/settings/tabs/register.vue";
import SettingPayment from "/@/views/sys/settings/tabs/payment.vue";
import { useRoute, useRouter } from "vue-router";
import { ref } from "vue";
import { useSettingStore } from "/@/store/modules/settings";
defineOptions({
name: "SysSettings"
});
const settingsStore = useSettingStore();
const activeKey = ref("");
const route = useRoute();
const router = useRouter();

View File

@ -68,7 +68,11 @@ const formState = reactive<
alipay: PaymentItem;
wxpay: PaymentItem;
}>
>({});
>({
yizhifu: { enabled: false },
alipay: { enabled: false },
wxpay: { enabled: false }
});
async function loadSettings() {
const data: any = await api.SettingGet();

View File

@ -106,7 +106,9 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
]
}),
form: {
rules: [{ required: true, message: "此项必填" }]
value: "suite",
rules: [{ required: true, message: "此项必填" }],
helper: "目前没区别,重复购买可叠加数量"
},
column: {
width: 80,

View File

@ -3,7 +3,7 @@
<template #header>
<div class="title">
套餐设置
<span class="sub"> 需要<router-link to="/sys/settings" :query="{ tab: 'payment' }">开启至少一种支付方式</router-link></span>
<span class="sub"> 需要<router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></span>
</div>
</template>
@ -31,6 +31,7 @@
<a-form-item label=" " :colon="false">
<loading-button type="primary" html-type="button" :click="onClick">保存</loading-button>
<div class="helper">需要 <router-link :to="{ path: '/sys/settings', query: { tab: 'payment' } }">开启至少一种支付方式</router-link></div>
</a-form-item>
</a-form>
</div>

View File

@ -1,7 +1,7 @@
import { request } from "/src/api/service";
export function createApi() {
const apiPrefix = "/sys/suite/userSuites";
const apiPrefix = "/sys/suite/user-suite";
return {
async GetList(query: any) {
return await request({
@ -47,6 +47,14 @@ export function createApi() {
url: apiPrefix + "/all",
method: "post"
});
},
async GetSimpleUserByIds(ids: number[]) {
return await request({
url: "/sys/authority/user/getSimpleUserByIds",
method: "post",
data: { ids }
});
}
};
}

View File

@ -55,26 +55,26 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
},
actionbar: {
buttons: {
add: { show: false },
buy: {
text: "购买",
type: "primary",
click() {
router.push({
path: "/certd/suite/buy"
});
}
}
add: { show: false }
// buy: {
// text: "购买",
// type: "primary",
// click() {
// router.push({
// path: "/certd/suite/buy"
// });
// }
// }
}
},
rowHandle: {
width: 200,
fixed: "right",
buttons: {
view: { show: false },
view: { show: true },
copy: { show: false },
edit: { show: false },
remove: { show: false }
remove: { show: true }
// continue:{
// text:"续期",
// type:"link",
@ -115,6 +115,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
width: 200
}
},
userId: {
title: "用户",
type: "table-select",
dict: dict({
async getNodesByValues(ids: number[]) {
return await api.GetSimpleUserByIds(ids);
},
value: "id",
label: "nickName"
})
},
productType: {
title: "类型",
type: "dict-select",

View File

@ -39,14 +39,18 @@ export class SiteInfoController extends CrudController<SiteInfoService> {
@Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) {
bean.userId = this.getUserId();
return await super.add(bean);
const res = await this.service.add(bean);
await this.service.check(res.id);
return this.ok(res);
}
@Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean) {
await this.service.checkUserId(bean.id, this.getUserId());
delete bean.userId;
return await super.update(bean);
await this.service.update(bean);
await this.service.check(bean.id);
return this.ok();
}
@Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) {

View File

@ -4,6 +4,7 @@ import { CrudController } from '@certd/lib-server';
import { RoleService } from '../../../modules/sys/authority/service/role-service.js';
import { PermissionService } from '../../../modules/sys/authority/service/permission-service.js';
import { Constants } from '@certd/lib-server';
import { In } from 'typeorm';
/**
*
@ -23,6 +24,24 @@ export class UserController extends CrudController<UserService> {
return this.service;
}
@Post('/getSimpleUserByIds', { summary: 'sys:auth:user:add' })
async getSimpleUserByIds(@Body('ids') ids: number[]) {
const users = await this.service.find({
select: {
id: true,
username: true,
nickName: true,
mobile: true,
phoneCode: true,
},
where: {
id: In(ids),
},
});
return this.ok(users);
}
@Post('/page', { summary: 'sys:auth:user:view' })
async page(
@Body(ALL)

View File

@ -51,7 +51,16 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
}
}
return await this.repository.save(data);
data.disabled = false;
return await super.add(data);
}
async update(data: any) {
if (!data.id) {
throw new Error('id is required');
}
delete data.userId;
await super.update(data);
}
async getUserMonitorCount(userId: number) {