mirror of
https://github.com/MCSManager/MCSManager.git
synced 2025-03-31 17:00:24 +08:00
feat: for redeem.mcsmanager.com
This commit is contained in:
parent
0ba3e32abc
commit
1748fcd751
@ -72,6 +72,9 @@ const handleSubmit = async () => {
|
||||
:label="t('TXT_CODE_c38813a8')"
|
||||
:rules="[{ required: true, message: t('TXT_CODE_2695488c') }]"
|
||||
>
|
||||
<a-typography-paragraph type="secondary">
|
||||
{{ t("TXT_CODE_b90e9abd") }}
|
||||
</a-typography-paragraph>
|
||||
<a-input
|
||||
v-model:value="formData.username"
|
||||
name="mcsm-redeem-username"
|
||||
@ -93,9 +96,6 @@ const handleSubmit = async () => {
|
||||
</a-form-item>
|
||||
<div class="text-center flex justify-center">
|
||||
<div>
|
||||
<a-typography-paragraph type="secondary">
|
||||
{{ t("TXT_CODE_b90e9abd") }}
|
||||
</a-typography-paragraph>
|
||||
<div class="flex justify-center">
|
||||
<a-button
|
||||
class="w-28"
|
||||
|
@ -3,6 +3,7 @@ import { computed, onMounted, ref, type Ref } from "vue";
|
||||
import { queryUsername } from "./user";
|
||||
import { Modal } from "ant-design-vue";
|
||||
import { t } from "@/lang/i18n";
|
||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||
|
||||
export interface ShopItem {
|
||||
productId: number;
|
||||
@ -71,8 +72,9 @@ export const requestRedeemPlatform = useDefineApi<
|
||||
export function useShopInfo() {
|
||||
const config = requestRedeemPlatform();
|
||||
const isError = ref<Error>();
|
||||
const { state: appState } = useAppStateStore();
|
||||
|
||||
onMounted(async () => {
|
||||
const loadProducts = async (businessId?: string) => {
|
||||
try {
|
||||
isError.value = undefined;
|
||||
await config.execute({
|
||||
@ -80,18 +82,25 @@ export function useShopInfo() {
|
||||
targetUrl: "/api/instances/query_products",
|
||||
method: "GET",
|
||||
params: {
|
||||
addr: CURRENT_PANEL_ADDR
|
||||
addr: CURRENT_PANEL_ADDR,
|
||||
businessId: businessId || appState.settings.businessId
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
isError.value = error as Error;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await loadProducts();
|
||||
});
|
||||
|
||||
return {
|
||||
...config,
|
||||
isError,
|
||||
loadProducts,
|
||||
isLoading: config.isLoading,
|
||||
state: config.state as Ref<ShopInfoResponse>,
|
||||
shopInfo: computed<ShopInfo>(() => config.state.value?.ispInfo),
|
||||
products: computed<ShopItem[]>(() => config.state.value?.products)
|
||||
@ -99,6 +108,7 @@ export function useShopInfo() {
|
||||
}
|
||||
|
||||
export function useRedeem() {
|
||||
const { state: appState } = useAppStateStore();
|
||||
const { execute, isLoading } = requestRedeemPlatform();
|
||||
|
||||
const preCheckUsername = (username: string) => {
|
||||
@ -135,7 +145,7 @@ export function useRedeem() {
|
||||
data: {
|
||||
targetUrl: "/api/instances/use_redeem",
|
||||
method: "POST",
|
||||
data: { code, username }
|
||||
data: { code, username, businessId: appState.settings.businessId }
|
||||
}
|
||||
});
|
||||
return res.value as BuyInstanceResponse;
|
||||
@ -146,7 +156,7 @@ export function useRedeem() {
|
||||
data: {
|
||||
targetUrl: "/api/instances/use_redeem",
|
||||
method: "POST",
|
||||
data: { code, instanceId, username }
|
||||
data: { code, instanceId, username, businessId: appState.settings.businessId }
|
||||
}
|
||||
});
|
||||
return res.value as BuyInstanceResponse;
|
||||
@ -157,7 +167,7 @@ export function useRedeem() {
|
||||
data: {
|
||||
targetUrl: "/api/instances/purchase_history",
|
||||
method: "GET",
|
||||
params: { code }
|
||||
params: { code, businessId: appState.settings.businessId }
|
||||
}
|
||||
});
|
||||
return res.value as PurchaseQueryResponse;
|
||||
|
@ -21,7 +21,8 @@ export const useAppStateStore = createGlobalState(() => {
|
||||
settings: {
|
||||
canFileManager: false,
|
||||
allowUsePreset: false,
|
||||
businessMode: false
|
||||
businessMode: false,
|
||||
businessId: ""
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -75,6 +75,7 @@ export interface Settings {
|
||||
redisUrl: string;
|
||||
allowUsePreset: boolean;
|
||||
businessMode: boolean;
|
||||
businessId: string;
|
||||
}
|
||||
|
||||
export interface ImageInfo {
|
||||
@ -244,5 +245,6 @@ export interface PanelStatus {
|
||||
canFileManager: boolean;
|
||||
allowUsePreset: boolean;
|
||||
businessMode: boolean;
|
||||
businessId: string;
|
||||
};
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ interface MySettings extends Settings {
|
||||
bgUrl?: string;
|
||||
}
|
||||
|
||||
const ApacheLicense = `Copyright 2024 MCSManager Dev
|
||||
const ApacheLicense = `Copyright ${new Date().getFullYear()} MCSManager Dev
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -398,7 +398,10 @@ onMounted(async () => {
|
||||
{{ t("TXT_CODE_e5b7522d") }}
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<a-select v-model:value.prop="formData.canFileManager" style="max-width: 320px">
|
||||
<a-select
|
||||
v-model:value.prop="(formData as any).canFileManager"
|
||||
style="max-width: 320px"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in allYesNo"
|
||||
:key="item.value"
|
||||
@ -418,7 +421,10 @@ onMounted(async () => {
|
||||
{{ t("TXT_CODE_f5f9664") }}
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<a-select v-model:value.prop="formData.allowUsePreset" style="max-width: 320px">
|
||||
<a-select
|
||||
v-model:value.prop="(formData as any).allowUsePreset"
|
||||
style="max-width: 320px"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in allYesNo"
|
||||
:key="item.value"
|
||||
@ -439,7 +445,10 @@ onMounted(async () => {
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
|
||||
<a-select v-model:value.prop="formData.crossDomain" style="max-width: 320px">
|
||||
<a-select
|
||||
v-model:value.prop="(formData as any).crossDomain"
|
||||
style="max-width: 320px"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in allYesNo"
|
||||
:key="item.value"
|
||||
@ -461,7 +470,7 @@ onMounted(async () => {
|
||||
</a-typography-paragraph>
|
||||
|
||||
<a-select
|
||||
v-model:value.prop="formData.reverseProxyMode"
|
||||
v-model:value.prop="(formData as any).reverseProxyMode"
|
||||
style="max-width: 320px"
|
||||
>
|
||||
<a-select-option
|
||||
@ -484,7 +493,10 @@ onMounted(async () => {
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
|
||||
<a-select v-model:value.prop="formData.loginCheckIp" style="max-width: 320px">
|
||||
<a-select
|
||||
v-model:value.prop="(formData as any).loginCheckIp"
|
||||
style="max-width: 320px"
|
||||
>
|
||||
<a-select-option
|
||||
v-for="item in allYesNo"
|
||||
:key="item.value"
|
||||
@ -527,7 +539,7 @@ onMounted(async () => {
|
||||
<a-switch v-model:checked="formData.businessMode" @change="submit(false)" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-24">
|
||||
<a-typography-paragraph>
|
||||
<a-typography-title :level="5">
|
||||
{{ t("TXT_CODE_d31196db") }}
|
||||
@ -537,15 +549,31 @@ onMounted(async () => {
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<div>
|
||||
<a-button
|
||||
type="primary"
|
||||
:disabled="!formData.businessMode"
|
||||
@click="gotoBusinessCenter()"
|
||||
>
|
||||
<a-button :disabled="!formData.businessMode" @click="gotoBusinessCenter()">
|
||||
{{ t("TXT_CODE_2dbd3cd3") }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="formData.businessMode" class="mb-24">
|
||||
<a-typography-paragraph>
|
||||
<a-typography-title :level="5">节点ID</a-typography-title>
|
||||
<a-typography-text type="secondary">
|
||||
在 “商家控制台 - 节点列表” 中可以找到节点ID
|
||||
</a-typography-text>
|
||||
</a-typography-paragraph>
|
||||
<div>
|
||||
<a-input
|
||||
v-model:value="formData.businessId"
|
||||
style="max-width: 200px"
|
||||
placeholder="eg: 123"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-button type="primary" :loading="submitIsLoading" @click="submit(false)">
|
||||
保存
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -8,7 +8,6 @@ import { t } from "@/lang/i18n";
|
||||
import { useShopInfo } from "@/services/apis/redeem";
|
||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||
import type { LayoutCard } from "@/types";
|
||||
|
||||
defineProps<{
|
||||
card: LayoutCard;
|
||||
}>();
|
||||
@ -56,6 +55,7 @@ const openLoginPage = () => {
|
||||
<div v-if="isLoading">
|
||||
<Loading />
|
||||
</div>
|
||||
|
||||
<div v-if="shopItems" class="shop-item-container">
|
||||
<div class="flex justify-end mb-20" style="gap: 10px">
|
||||
<a-button type="primary" @click="openDialog">
|
||||
@ -90,8 +90,8 @@ const openLoginPage = () => {
|
||||
<div>
|
||||
<div class="shelves-card-item-price-label">{{ t("TXT_CODE_4bf8a52f") }}</div>
|
||||
<div>
|
||||
<span class="price-text"> {{ item.price }} </span
|
||||
><span>/{{ t("TXT_CODE_6cb9bb04") }}</span>
|
||||
<span class="price-text"> {{ item.price }} </span>
|
||||
<span>/{{ t("TXT_CODE_6cb9bb04") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1996,7 +1996,7 @@
|
||||
"TXT_CODE_ef27fda1": "售后渠道:",
|
||||
"TXT_CODE_ec0b25f5": "您可以将此页面地址复制通过互联网分享给用户,用户无需登录即可访问此页面。",
|
||||
"TXT_CODE_e5bf0df1": "暂时无法获取商家信息,可能服务器正在维护中,请稍后再稍后再尝试!",
|
||||
"TXT_CODE_4ef3f800": "如果您是商家,请留言 https://redeem.mcsmanager.com 或官网网站的公告以获取帮助。",
|
||||
"TXT_CODE_4ef3f800": "如果您是商家,请留意 https://redeem.mcsmanager.com 或官网网站的公告以获取帮助。",
|
||||
"TXT_CODE_aa43b248": "进入控制台",
|
||||
"TXT_CODE_4770de17": "商家信息",
|
||||
"TXT_CODE_381f8f22": "商品列表",
|
||||
|
@ -55,4 +55,6 @@ export default class SystemConfig {
|
||||
// to sell instances based on redeem
|
||||
// (this feature may not be available in some countries)
|
||||
businessMode = false;
|
||||
|
||||
businessId = "";
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ router.all(
|
||||
settings: {
|
||||
canFileManager: systemConfig?.canFileManager || false,
|
||||
allowUsePreset: systemConfig?.allowUsePreset || false,
|
||||
businessMode: systemConfig?.businessMode || false
|
||||
businessMode: systemConfig?.businessMode || false,
|
||||
businessId: systemConfig?.businessId || null
|
||||
} as Partial<SystemConfig>
|
||||
};
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ router.put("/setting", permission({ level: ROLE.ADMIN }), async (ctx) => {
|
||||
if (config.allowUsePreset != null) systemConfig.allowUsePreset = Boolean(config.allowUsePreset);
|
||||
if (config.presetPackAddr != null) systemConfig.presetPackAddr = String(config.presetPackAddr);
|
||||
if (config.businessMode != null) systemConfig.businessMode = Boolean(config.businessMode);
|
||||
if (config.businessId != null) systemConfig.businessId = String(config.businessId);
|
||||
if (config.language != null) {
|
||||
logger.warn($t("TXT_CODE_e29a9317"), config.language);
|
||||
systemConfig.language = String(config.language);
|
||||
|
@ -10,8 +10,7 @@ import type { IGlobalInstanceConfig } from "common/global";
|
||||
// A commercial platform for selling instances released by the MCSManager Dev Team.
|
||||
// Currently, it only supports some countries and regions.
|
||||
// If you do not turn on "Commercial Mode", MCSManager will not send any data.
|
||||
export const REDEEM_PLATFORM_ADDR = "http://localhost:5174";
|
||||
// export const REDEEM_PLATFORM_ADDR = "https://redeem.mcsmanager.com";
|
||||
export const REDEEM_PLATFORM_ADDR = "https://redeem.mcsmanager.com";
|
||||
|
||||
// ------- Protocol Define -------
|
||||
export interface INodeStatusProtocol {
|
||||
|
Loading…
x
Reference in New Issue
Block a user