feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
25
frontend/packages/studio/components/src/monetize/index.ts
Normal file
25
frontend/packages/studio/components/src/monetize/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
MonetizeConfigPanel,
|
||||
MonetizeConfigValue,
|
||||
} from './monetize-config-panel';
|
||||
export { MonetizeCreditRefreshCycle } from './monetize-credit-refresh-cycle';
|
||||
export { MonetizeDescription } from './monetize-description';
|
||||
export { MonetizeFreeChatCount } from './monetize-free-chat-count';
|
||||
export { MonetizeSwitch } from './monetize-switch';
|
||||
export { MonetizePublishInfo } from './monetize-publish-info';
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useDebounceFn } from 'ahooks';
|
||||
import { type BotMonetizationRefreshPeriod } from '@coze-arch/bot-api/benefit';
|
||||
|
||||
import { MonetizeSwitch } from '../monetize-switch';
|
||||
import { MonetizeFreeChatCount } from '../monetize-free-chat-count';
|
||||
import { MonetizeDescription } from '../monetize-description';
|
||||
import { MonetizeCreditRefreshCycle } from '../monetize-credit-refresh-cycle';
|
||||
|
||||
export interface MonetizeConfigValue {
|
||||
/** 是否开启付费 */
|
||||
isOn: boolean;
|
||||
/** 开启付费后,用户免费体验的次数 */
|
||||
freeCount: number;
|
||||
/** 刷新周期 */
|
||||
refreshCycle: BotMonetizationRefreshPeriod;
|
||||
}
|
||||
|
||||
interface MonetizeConfigPanelProps {
|
||||
disabled?: boolean;
|
||||
value: MonetizeConfigValue;
|
||||
onChange: (value: MonetizeConfigValue) => void;
|
||||
/**
|
||||
* 内置防抖后的 onChange 事件,业务侧可选择性使用,正常只传 onChange 即可
|
||||
* (由于该组件是完全受控组件,因此不能只传 onDebouncedChange,必须传 onChange 实时更新视图)
|
||||
*/
|
||||
onDebouncedChange?: (value: MonetizeConfigValue) => void;
|
||||
}
|
||||
|
||||
export function MonetizeConfigPanel({
|
||||
disabled = false,
|
||||
value,
|
||||
onChange,
|
||||
onDebouncedChange,
|
||||
}: MonetizeConfigPanelProps) {
|
||||
const { run: debouncedChange } = useDebounceFn(
|
||||
({ isOn, freeCount, refreshCycle }: MonetizeConfigValue) => {
|
||||
onDebouncedChange?.({
|
||||
isOn,
|
||||
freeCount,
|
||||
refreshCycle,
|
||||
});
|
||||
},
|
||||
{ wait: 300 },
|
||||
);
|
||||
|
||||
const refreshCycleDisabled = !value.isOn || disabled || value.freeCount <= 0;
|
||||
|
||||
return (
|
||||
<div className="w-[480px] p-[24px] flex flex-col gap-[24px]">
|
||||
<MonetizeSwitch
|
||||
disabled={disabled}
|
||||
isOn={value.isOn}
|
||||
onChange={v => {
|
||||
onChange({ ...value, isOn: v });
|
||||
debouncedChange({
|
||||
...value,
|
||||
isOn: v,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<MonetizeDescription isOn={value.isOn} />
|
||||
<MonetizeFreeChatCount
|
||||
isOn={value.isOn}
|
||||
disabled={disabled}
|
||||
freeCount={value.freeCount}
|
||||
onFreeCountChange={v => {
|
||||
onChange({ ...value, freeCount: v });
|
||||
debouncedChange({
|
||||
...value,
|
||||
freeCount: v,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<MonetizeCreditRefreshCycle
|
||||
freeCount={value.freeCount}
|
||||
disabled={refreshCycleDisabled}
|
||||
refreshCycle={value.refreshCycle}
|
||||
onRefreshCycleChange={v => {
|
||||
onChange({ ...value, refreshCycle: v });
|
||||
debouncedChange({ ...value, refreshCycle: v });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozInfoCircle } from '@coze-arch/coze-design/icons';
|
||||
import { Tooltip, Select } from '@coze-arch/coze-design';
|
||||
import { BotMonetizationRefreshPeriod } from '@coze-arch/bot-api/benefit';
|
||||
|
||||
const refreshCycleTextMap: Record<BotMonetizationRefreshPeriod, string> = {
|
||||
[BotMonetizationRefreshPeriod.Unknown]: I18n.t(
|
||||
'coze_premium_credits_cycle_4',
|
||||
),
|
||||
[BotMonetizationRefreshPeriod.Never]: I18n.t('coze_premium_credits_cycle_4'),
|
||||
[BotMonetizationRefreshPeriod.Day]: I18n.t('coze_premium_credits_cycle_1'),
|
||||
[BotMonetizationRefreshPeriod.Week]: I18n.t('coze_premium_credits_cycle_2'),
|
||||
[BotMonetizationRefreshPeriod.Month]: I18n.t('coze_premium_credits_cycle_3'),
|
||||
};
|
||||
|
||||
const getOptionList = () => [
|
||||
{
|
||||
value: BotMonetizationRefreshPeriod.Never,
|
||||
text: refreshCycleTextMap[BotMonetizationRefreshPeriod.Never],
|
||||
},
|
||||
{
|
||||
value: BotMonetizationRefreshPeriod.Day,
|
||||
text: refreshCycleTextMap[BotMonetizationRefreshPeriod.Day],
|
||||
tooltip: I18n.t('coze_premium_credits_cycle_tip6'),
|
||||
},
|
||||
{
|
||||
value: BotMonetizationRefreshPeriod.Week,
|
||||
text: refreshCycleTextMap[BotMonetizationRefreshPeriod.Week],
|
||||
tooltip: I18n.t('coze_premium_credits_cycle_tip7'),
|
||||
},
|
||||
{
|
||||
value: BotMonetizationRefreshPeriod.Month,
|
||||
text: refreshCycleTextMap[BotMonetizationRefreshPeriod.Month],
|
||||
tooltip: I18n.t('coze_premium_credits_cycle_tip8'),
|
||||
},
|
||||
];
|
||||
|
||||
export function MonetizeCreditRefreshCycle({
|
||||
refreshCycle,
|
||||
onRefreshCycleChange,
|
||||
disabled,
|
||||
freeCount,
|
||||
}: {
|
||||
freeCount: number;
|
||||
disabled: boolean;
|
||||
refreshCycle: number;
|
||||
onRefreshCycleChange: (value: number) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-4px">
|
||||
<div className="coz-fg-primary text-lg font-medium">
|
||||
{I18n.t('coze_premium_credits_cycle_5')}
|
||||
</div>
|
||||
<Tooltip
|
||||
theme="dark"
|
||||
content={I18n.t('coze_premium_credits_cycle_tip1')}
|
||||
>
|
||||
<IconCozInfoCircle className="text-base coz-fg-secondary" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
key={freeCount}
|
||||
trigger={freeCount <= 0 ? 'hover' : 'custom'}
|
||||
content={I18n.t('coze_premium_credits_cycle_tip4')}
|
||||
>
|
||||
<Select
|
||||
disabled={disabled}
|
||||
onChange={value => {
|
||||
onRefreshCycleChange(Number(value));
|
||||
}}
|
||||
value={refreshCycle}
|
||||
position="bottomRight"
|
||||
className="w-[140px]"
|
||||
renderSelectedItem={(item: Record<string, unknown>) =>
|
||||
refreshCycleTextMap[item.value as BotMonetizationRefreshPeriod]
|
||||
}
|
||||
>
|
||||
{getOptionList().map(item => (
|
||||
<Select.Option key={item.value} value={item.value}>
|
||||
<div className="mx-8px w-[100px]">{item.text}</div>
|
||||
{item.tooltip ? (
|
||||
<Tooltip theme="dark" position="right" content={item.tooltip}>
|
||||
<IconCozInfoCircle className="mr-8px coz-fg-secondary text-base" />
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Popover } from '@coze-arch/coze-design';
|
||||
|
||||
import previewCard from './preview-card.png';
|
||||
|
||||
export function MonetizeDescription({ isOn }: { isOn: boolean }) {
|
||||
return (
|
||||
<div className="coz-fg-primary">
|
||||
<span>
|
||||
{isOn ? I18n.t('monetization_on_des') : I18n.t('monetization_off_des')}
|
||||
</span>
|
||||
{isOn ? (
|
||||
<Popover
|
||||
content={
|
||||
<div className="p-[12px] coz-bg-max rounded-[10px]">
|
||||
<img width={320} src={previewCard} />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<span className="coz-fg-hglt cursor-pointer">
|
||||
{I18n.t('monetization_on_viewbill')}
|
||||
</span>
|
||||
</Popover>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozInfoCircle } from '@coze-arch/coze-design/icons';
|
||||
import { InputNumber, Tooltip } from '@coze-arch/coze-design';
|
||||
|
||||
export function MonetizeFreeChatCount({
|
||||
isOn,
|
||||
disabled,
|
||||
freeCount,
|
||||
onFreeCountChange,
|
||||
}: {
|
||||
isOn: boolean;
|
||||
disabled: boolean;
|
||||
freeCount: number;
|
||||
onFreeCountChange: (value: number) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="flex items-center font-semibold leading-[20px]">
|
||||
<span className="coz-fg-primary">
|
||||
{I18n.t('free_chat_allowance')}
|
||||
</span>
|
||||
<Tooltip theme="dark" content={I18n.t('free_chat_allowance_tips')}>
|
||||
<span className="ml-[4px] h-[12px] w-[12px] text-[12px] leading-[12px] coz-fg-secondary">
|
||||
<IconCozInfoCircle />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="coz-fg-secondary text-base leading-[16px]">
|
||||
{freeCount > 5
|
||||
? I18n.t('coze_premium_credits_cycle_tip2')
|
||||
: I18n.t('coze_premium_credits_cycle_tip3')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<InputNumber
|
||||
keepFocus
|
||||
className="w-[140px]"
|
||||
disabled={!isOn || disabled}
|
||||
precision={0}
|
||||
min={0}
|
||||
max={100}
|
||||
value={freeCount}
|
||||
onNumberChange={onFreeCountChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import cls from 'classnames';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozInfoCircle } from '@coze-arch/coze-design/icons';
|
||||
import { Avatar, Tooltip } from '@coze-arch/coze-design';
|
||||
import { type PublishConnectorInfo } from '@coze-arch/bot-api/developer_api';
|
||||
import { type BotMonetizationConfigData } from '@coze-arch/bot-api/benefit';
|
||||
|
||||
export function MonetizePublishInfo({
|
||||
className,
|
||||
monetizeConfig,
|
||||
supportPlatforms,
|
||||
}: {
|
||||
className?: string;
|
||||
monetizeConfig: BotMonetizationConfigData;
|
||||
supportPlatforms: Array<Pick<PublishConnectorInfo, 'id' | 'name' | 'icon'>>;
|
||||
}) {
|
||||
const supportPlatformsText = supportPlatforms.map(p => p.name).join(', ');
|
||||
|
||||
return (
|
||||
<div className={cls('flex justify-end items-center gap-[12px]', className)}>
|
||||
<div className="flex items-center gap-[4px]">
|
||||
<span className="font-medium coz-fg-plus">
|
||||
{`${I18n.t('monetization')}: ${
|
||||
monetizeConfig.is_enable
|
||||
? I18n.t('monetization_publish_on')
|
||||
: I18n.t('monetization_publish_off')
|
||||
}`}
|
||||
</span>
|
||||
<Tooltip
|
||||
content={
|
||||
<div className="flex flex-col">
|
||||
<div>
|
||||
{monetizeConfig.is_enable
|
||||
? I18n.t('monetization_on_des')
|
||||
: I18n.t('monetization_off_des')}
|
||||
</div>
|
||||
{monetizeConfig.is_enable ? (
|
||||
<div className="mt-[8px] pt-[8px] border-0 border-t border-solid coz-stroke-primary">
|
||||
{`${I18n.t('free_chat_allowance')} : ${
|
||||
monetizeConfig.free_chat_allowance_count
|
||||
}`}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<IconCozInfoCircle className="w-[16px] h-[16px] coz-fg-secondary" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-[4px]">
|
||||
<span className="font-normal coz-fg-tertiary">
|
||||
{I18n.t('monetization_support')}:
|
||||
</span>
|
||||
<span className="flex items-center gap-[4px]">
|
||||
{supportPlatforms.map(p => (
|
||||
<Avatar
|
||||
key={p.id}
|
||||
className="h-[16px] w-[16px] rounded-[4px]"
|
||||
size="extra-extra-small"
|
||||
shape="square"
|
||||
src={p.icon}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
<Tooltip
|
||||
content={`${I18n.t(
|
||||
'monetization_support_tips',
|
||||
)}: ${supportPlatformsText}`}
|
||||
>
|
||||
<IconCozInfoCircle className="w-[16px] h-[16px] coz-fg-secondary" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Switch } from '@coze-arch/coze-design';
|
||||
|
||||
export function MonetizeSwitch({
|
||||
disabled,
|
||||
isOn,
|
||||
onChange,
|
||||
}: {
|
||||
disabled: boolean;
|
||||
isOn: boolean;
|
||||
onChange: (isOn: boolean) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex justify-between">
|
||||
<h3 className="m-0 text-[20px] font-medium coz-fg-plus">
|
||||
{I18n.t('premium_monetization_config')}
|
||||
</h3>
|
||||
<Switch
|
||||
disabled={disabled}
|
||||
className="ml-[5px]"
|
||||
size="small"
|
||||
checked={isOn}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user