feat: 支持了application, system,platform的defaultOrigin配置
This commit is contained in:
parent
021276346d
commit
7beeb8afeb
|
|
@ -0,0 +1,11 @@
|
|||
import { NativeConfig, WebConfig, WechatMpConfig, WechatPublicConfig } from '../../../entities/Application';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
export type AppConfig = WebConfig | WechatMpConfig | WechatPublicConfig | NativeConfig;
|
||||
export type CosConfig = AppConfig['cos'];
|
||||
declare const _default: (props: import("oak-frontend-base").ReactComponentProps<EntityDict, keyof EntityDict, false, {
|
||||
config: AppConfig;
|
||||
entity: string;
|
||||
entityId: string;
|
||||
name: string;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
import { cloneDeep, set } from 'oak-domain/lib/utils/lodash';
|
||||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { isEmptyJsonObject } from '../../../utils/strings';
|
||||
export default OakComponent({
|
||||
isList: false,
|
||||
properties: {
|
||||
config: {},
|
||||
entity: 'application',
|
||||
entityId: '',
|
||||
name: '',
|
||||
},
|
||||
data: {
|
||||
initialConfig: {},
|
||||
dirty: false,
|
||||
currentConfig: {},
|
||||
selections: [],
|
||||
},
|
||||
lifetimes: {
|
||||
async ready() {
|
||||
const { config } = this.props;
|
||||
this.setState({
|
||||
initialConfig: config,
|
||||
dirty: false,
|
||||
currentConfig: cloneDeep(config),
|
||||
});
|
||||
const systemId = this.features.application.getApplication().systemId;
|
||||
const { data: [system] } = await this.features.cache.refresh("system", {
|
||||
action: 'select',
|
||||
data: {
|
||||
config: {
|
||||
Cos: {
|
||||
qiniu: 1,
|
||||
ctyun: 1,
|
||||
aliyun: 1,
|
||||
tencent: 1,
|
||||
local: 1,
|
||||
s3: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
id: systemId,
|
||||
}
|
||||
});
|
||||
const cosConfig = system?.config?.Cos;
|
||||
// 如果key存在并且不为defaultOrigin并且value的keys长度大于0,则加入选择项
|
||||
const selections = [];
|
||||
if (cosConfig) {
|
||||
for (const [key, value] of Object.entries(cosConfig)) {
|
||||
if (key === 'defaultOrigin') {
|
||||
continue;
|
||||
}
|
||||
if (value && !isEmptyJsonObject(value)) {
|
||||
selections.push({
|
||||
name: key,
|
||||
value: key,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
selections,
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setValue(path, value) {
|
||||
const { currentConfig } = this.state;
|
||||
const newConfig = cloneDeep(currentConfig || {});
|
||||
set(newConfig, path, value);
|
||||
this.setState({
|
||||
currentConfig: newConfig,
|
||||
dirty: true,
|
||||
});
|
||||
},
|
||||
resetConfig() {
|
||||
const { initialConfig } = this.state;
|
||||
this.setState({
|
||||
dirty: false,
|
||||
currentConfig: cloneDeep(initialConfig),
|
||||
});
|
||||
},
|
||||
async updateConfig() {
|
||||
const { currentConfig } = this.state;
|
||||
const { entity, entityId } = this.props;
|
||||
if (!entityId) {
|
||||
this.setMessage({
|
||||
content: '缺少实体ID,无法更新配置',
|
||||
type: 'error',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.features.cache.operate("application", {
|
||||
id: generateNewId(),
|
||||
action: 'update',
|
||||
data: {
|
||||
config: currentConfig,
|
||||
},
|
||||
filter: {
|
||||
id: entityId,
|
||||
}
|
||||
}, {});
|
||||
this.setMessage({
|
||||
content: '操作成功',
|
||||
type: 'success',
|
||||
});
|
||||
this.setState({
|
||||
dirty: false,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"qiniu": "七牛云",
|
||||
"ctyun": "天翼云",
|
||||
"aliyun": "阿里云",
|
||||
"tencent": "腾讯云",
|
||||
"local": "本地存储",
|
||||
"s3": "S3存储"
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
.contains {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import React from 'react';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
declare const Cos: (props: WebComponentProps<EntityDict, keyof EntityDict, false, {
|
||||
currentConfig: EntityDict["application"]["OpSchema"]["config"];
|
||||
dirty: boolean;
|
||||
entity: string;
|
||||
name: string;
|
||||
selections: {
|
||||
name: string;
|
||||
value: string;
|
||||
}[];
|
||||
}, {
|
||||
setValue: (path: string, value: any) => void;
|
||||
resetConfig: () => void;
|
||||
updateConfig: () => void;
|
||||
}>) => React.JSX.Element;
|
||||
export default Cos;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import Styles from './styles.module.less';
|
||||
import { Affix, Alert, Button, Select, Space, Typography } from 'antd';
|
||||
const Cos = (props) => {
|
||||
const { currentConfig, dirty, entity, name, selections } = props.data;
|
||||
const { t, setValue, resetConfig, updateConfig } = props.methods;
|
||||
return (<>
|
||||
<Affix offsetTop={64}>
|
||||
<Alert message={<div>
|
||||
<text>
|
||||
您正在更新
|
||||
<Typography.Text keyboard>
|
||||
{entity}
|
||||
</Typography.Text>
|
||||
对象
|
||||
<Typography.Text keyboard>
|
||||
{name}
|
||||
</Typography.Text>
|
||||
的COS配置,请谨慎操作
|
||||
</text>
|
||||
</div>} type="info" showIcon action={<Space>
|
||||
<Button disabled={!dirty} type="primary" danger onClick={() => resetConfig()} style={{
|
||||
marginRight: 10,
|
||||
}}>
|
||||
{t('common::reset')}
|
||||
</Button>
|
||||
<Button disabled={!dirty} type="primary" onClick={() => updateConfig()}>
|
||||
{t('common::action.confirm')}
|
||||
</Button>
|
||||
</Space>}/>
|
||||
</Affix>
|
||||
<div className={Styles.contains}>
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<Typography.Text strong>默认COS源</Typography.Text>
|
||||
<Select value={currentConfig?.cos?.defaultOrigin} onChange={(v) => {
|
||||
setValue('cos.defaultOrigin', v);
|
||||
}} style={{ width: '100%' }} allowClear placeholder="请选择默认COS源">
|
||||
{selections.map((item) => (<Select.Option key={item.value} value={item.value}>
|
||||
{t(item.name)}
|
||||
</Select.Option>))}
|
||||
</Select>
|
||||
</Space>
|
||||
</div>
|
||||
</>);
|
||||
};
|
||||
export default Cos;
|
||||
|
|
@ -6,5 +6,6 @@
|
|||
"menu": "菜单管理",
|
||||
"autoReply": "被关注回复管理",
|
||||
"tag": "标签管理",
|
||||
"user": "用户管理"
|
||||
"user": "用户管理",
|
||||
"cos": "COS配置"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import WechatMenu from '../../wechatMenu';
|
|||
import UserWechatPublicTag from '../../userWechatPublicTag';
|
||||
import WechatPublicTag from '../..//wechatPublicTag/list';
|
||||
import WechatPublicAutoReply from '../../wechatPublicAutoReply';
|
||||
import Cos from '../cos';
|
||||
export default function Render(props) {
|
||||
const { id, config, oakFullpath, name, style, type } = props.data;
|
||||
const { t, update } = props.methods;
|
||||
|
|
@ -29,6 +30,12 @@ export default function Render(props) {
|
|||
key: 'style',
|
||||
children: (<StyleUpsert style={style} entity={'platform'} entityId={id} name={name}/>),
|
||||
},
|
||||
{
|
||||
label: <div className={Styles.tabLabel}>{t('cos')}</div>,
|
||||
key: 'cos',
|
||||
children: (<Cos oakPath={`#application-panel-cos-${id}`} config={config} entity="application" entityId={id} name={name}>
|
||||
</Cos>),
|
||||
},
|
||||
];
|
||||
if (type === 'wechatPublic') {
|
||||
items.push({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Tabs, Row, Col, Card, Divider, Input, Form, Space, Select, } from 'antd';
|
||||
import { Tabs, Row, Col, Card, Divider, Input, Form, Space, Select, Typography, } from 'antd';
|
||||
import Styles from './web.module.less';
|
||||
import { isEmptyObject } from '../../../../utils/strings';
|
||||
// https://developer.qiniu.com/kodo/1671/region-endpoint-fq
|
||||
const QiniuZoneArray = [
|
||||
{
|
||||
|
|
@ -987,6 +988,24 @@ export default function Cos(props) {
|
|||
const { cos, setValue, removeItem } = props;
|
||||
const { qiniu, ctyun, aliyun, tencent, local, s3 } = cos;
|
||||
return (<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
{/* 默认项选择 */}
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<Typography.Text strong>默认COS源</Typography.Text>
|
||||
<Select value={cos?.defaultOrigin} onChange={(v) => {
|
||||
setValue('defaultOrigin', v);
|
||||
}} style={{ width: '100%' }} allowClear placeholder="请选择默认COS源">
|
||||
{Object.entries(cos).map(([key, value]) => {
|
||||
if (key === 'defaultOrigin') {
|
||||
return null;
|
||||
}
|
||||
if (value && !isEmptyObject(value)) {
|
||||
return (<Select.Option key={key} value={key}>
|
||||
{key}
|
||||
</Select.Option>);
|
||||
}
|
||||
}).filter(Boolean)}
|
||||
</Select>
|
||||
</Space>
|
||||
<Row>
|
||||
<Card className={Styles.tips}>
|
||||
每种均可配置一个,相应的服务所使用的帐号请准确对应
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default OakComponent({
|
|||
disableAdd: false, // 上传按钮隐藏
|
||||
disableDownload: false, // 下载按钮隐藏
|
||||
type: 'image',
|
||||
origin: 'qiniu',
|
||||
origin: null,
|
||||
tag1: '',
|
||||
tag2: '',
|
||||
entity: '',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,20 @@
|
|||
// 本文件为自动编译产生,请勿直接修改
|
||||
const i18ns = [
|
||||
{
|
||||
id: "ce78f226978ae5cc7f23a6b72d2cb8cb",
|
||||
namespace: "oak-general-business-c-application-cos",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/application/cos",
|
||||
data: {
|
||||
"qiniu": "七牛云",
|
||||
"ctyun": "天翼云",
|
||||
"aliyun": "阿里云",
|
||||
"tencent": "腾讯云",
|
||||
"local": "本地存储",
|
||||
"s3": "S3存储"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "c0ce3f84c8cd6f70457b7e57a8ac8b8f",
|
||||
namespace: "oak-general-business-c-application-detail",
|
||||
|
|
@ -24,7 +39,8 @@ const i18ns = [
|
|||
"menu": "菜单管理",
|
||||
"autoReply": "被关注回复管理",
|
||||
"tag": "标签管理",
|
||||
"user": "用户管理"
|
||||
"user": "用户管理",
|
||||
"cos": "COS配置"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
export declare function isEmptyJsonObject(jsonString: string): boolean;
|
||||
export declare function isEmptyObject(obj: any): boolean;
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
export function isEmptyJsonObject(jsonString) {
|
||||
try {
|
||||
const obj = JSON.parse(jsonString);
|
||||
return isEmptyObject(obj);
|
||||
}
|
||||
catch (error) {
|
||||
// 如果解析失败,返回 false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export function isEmptyObject(obj) {
|
||||
// 处理 null 或 undefined
|
||||
if (obj === null || obj === undefined) {
|
||||
return true;
|
||||
}
|
||||
// 处理空字符串
|
||||
if (typeof obj === 'string' && obj === '') {
|
||||
return true;
|
||||
}
|
||||
// 如果是数组
|
||||
if (Array.isArray(obj)) {
|
||||
// 所有元素都为空才返回 true
|
||||
return obj.length === 0 || obj.every(item => isEmptyObject(item));
|
||||
}
|
||||
// 如果是对象
|
||||
if (typeof obj === 'object') {
|
||||
const keys = Object.keys(obj);
|
||||
// 空对象返回 true
|
||||
if (keys.length === 0) {
|
||||
return true;
|
||||
}
|
||||
// 递归检查所有值
|
||||
return keys.every(key => isEmptyObject(obj[key]));
|
||||
}
|
||||
// 其他类型(数字、布尔值等)视为非空
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2,6 +2,21 @@
|
|||
// 本文件为自动编译产生,请勿直接修改
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const i18ns = [
|
||||
{
|
||||
id: "ce78f226978ae5cc7f23a6b72d2cb8cb",
|
||||
namespace: "oak-general-business-c-application-cos",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/application/cos",
|
||||
data: {
|
||||
"qiniu": "七牛云",
|
||||
"ctyun": "天翼云",
|
||||
"aliyun": "阿里云",
|
||||
"tencent": "腾讯云",
|
||||
"local": "本地存储",
|
||||
"s3": "S3存储"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "c0ce3f84c8cd6f70457b7e57a8ac8b8f",
|
||||
namespace: "oak-general-business-c-application-detail",
|
||||
|
|
@ -26,7 +41,8 @@ const i18ns = [
|
|||
"menu": "菜单管理",
|
||||
"autoReply": "被关注回复管理",
|
||||
"tag": "标签管理",
|
||||
"user": "用户管理"
|
||||
"user": "用户管理",
|
||||
"cos": "COS配置"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
export declare function isEmptyJsonObject(jsonString: string): boolean;
|
||||
export declare function isEmptyObject(obj: any): boolean;
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isEmptyJsonObject = isEmptyJsonObject;
|
||||
exports.isEmptyObject = isEmptyObject;
|
||||
function isEmptyJsonObject(jsonString) {
|
||||
try {
|
||||
const obj = JSON.parse(jsonString);
|
||||
return isEmptyObject(obj);
|
||||
}
|
||||
catch (error) {
|
||||
// 如果解析失败,返回 false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isEmptyObject(obj) {
|
||||
// 处理 null 或 undefined
|
||||
if (obj === null || obj === undefined) {
|
||||
return true;
|
||||
}
|
||||
// 处理空字符串
|
||||
if (typeof obj === 'string' && obj === '') {
|
||||
return true;
|
||||
}
|
||||
// 如果是数组
|
||||
if (Array.isArray(obj)) {
|
||||
// 所有元素都为空才返回 true
|
||||
return obj.length === 0 || obj.every(item => isEmptyObject(item));
|
||||
}
|
||||
// 如果是对象
|
||||
if (typeof obj === 'object') {
|
||||
const keys = Object.keys(obj);
|
||||
// 空对象返回 true
|
||||
if (keys.length === 0) {
|
||||
return true;
|
||||
}
|
||||
// 递归检查所有值
|
||||
return keys.every(key => isEmptyObject(obj[key]));
|
||||
}
|
||||
// 其他类型(数字、布尔值等)视为非空
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
import { cloneDeep, set, get, omit } from 'oak-domain/lib/utils/lodash';
|
||||
import { Config } from '../../../types/Config';
|
||||
import { NativeConfig, WebConfig, WechatMpConfig, WechatPublicConfig } from '../../../entities/Application';
|
||||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { MakeOakComponent } from 'oak-frontend-base';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { isEmptyJsonObject } from '../../../utils/strings';
|
||||
|
||||
export type AppConfig = WebConfig | WechatMpConfig | WechatPublicConfig | NativeConfig
|
||||
export type CosConfig = AppConfig['cos']
|
||||
|
||||
export default OakComponent({
|
||||
isList: false,
|
||||
properties: {
|
||||
config: {} as AppConfig,
|
||||
entity: 'application',
|
||||
entityId: '',
|
||||
name: '',
|
||||
},
|
||||
data: {
|
||||
initialConfig: {} as AppConfig,
|
||||
dirty: false,
|
||||
currentConfig: {} as AppConfig,
|
||||
selections: [] as { name: string; value: string }[],
|
||||
},
|
||||
lifetimes: {
|
||||
async ready() {
|
||||
const { config } = this.props;
|
||||
this.setState({
|
||||
initialConfig: config,
|
||||
dirty: false,
|
||||
currentConfig: cloneDeep(config),
|
||||
})
|
||||
|
||||
const systemId = this.features.application.getApplication().systemId!;
|
||||
|
||||
const { data: [system] } = await this.features.cache.refresh("system", {
|
||||
action: 'select',
|
||||
data: {
|
||||
config: {
|
||||
Cos: {
|
||||
qiniu: 1,
|
||||
ctyun: 1,
|
||||
aliyun: 1,
|
||||
tencent: 1,
|
||||
local: 1,
|
||||
s3: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
id: systemId,
|
||||
}
|
||||
});
|
||||
|
||||
const cosConfig = system?.config?.Cos;
|
||||
|
||||
// 如果key存在并且不为defaultOrigin并且value的keys长度大于0,则加入选择项
|
||||
const selections: { name: string; value: string }[] = [];
|
||||
if (cosConfig) {
|
||||
for (const [key, value] of Object.entries(cosConfig)) {
|
||||
if (key === 'defaultOrigin') {
|
||||
continue;
|
||||
}
|
||||
if (value && !isEmptyJsonObject(value as string)) {
|
||||
selections.push({
|
||||
name: key,
|
||||
value: key,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selections,
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setValue(path: string, value: any) {
|
||||
const { currentConfig } = this.state;
|
||||
const newConfig = cloneDeep(currentConfig || {});
|
||||
set(newConfig, path, value);
|
||||
this.setState({
|
||||
currentConfig: newConfig,
|
||||
dirty: true,
|
||||
});
|
||||
},
|
||||
resetConfig() {
|
||||
const { initialConfig } = this.state;
|
||||
this.setState({
|
||||
dirty: false,
|
||||
currentConfig: cloneDeep(initialConfig),
|
||||
});
|
||||
},
|
||||
|
||||
async updateConfig() {
|
||||
const { currentConfig } = this.state;
|
||||
const { entity, entityId } = this.props;
|
||||
|
||||
if (!entityId) {
|
||||
this.setMessage({
|
||||
content: '缺少实体ID,无法更新配置',
|
||||
type: 'error',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await this.features.cache.operate("application", {
|
||||
id: generateNewId(),
|
||||
action: 'update',
|
||||
data: {
|
||||
config: currentConfig,
|
||||
},
|
||||
filter: {
|
||||
id: entityId,
|
||||
}
|
||||
}, {})
|
||||
|
||||
this.setMessage({
|
||||
content: '操作成功',
|
||||
type: 'success',
|
||||
});
|
||||
this.setState(
|
||||
{
|
||||
dirty: false,
|
||||
}
|
||||
)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"qiniu": "七牛云",
|
||||
"ctyun": "天翼云",
|
||||
"aliyun": "阿里云",
|
||||
"tencent": "腾讯云",
|
||||
"local": "本地存储",
|
||||
"s3": "S3存储"
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
.contains {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import React from 'react';
|
||||
import { RowWithActions, WebComponentProps } from 'oak-frontend-base';
|
||||
import Styles from './styles.module.less';
|
||||
import { EntityDict } from '../../../oak-app-domain';
|
||||
import { Affix, Alert, Button, Select, Space, Typography } from 'antd';
|
||||
|
||||
const Cos = (
|
||||
props: WebComponentProps<
|
||||
EntityDict,
|
||||
keyof EntityDict,
|
||||
false,
|
||||
{
|
||||
// virtual
|
||||
currentConfig: EntityDict['application']['OpSchema']['config'];
|
||||
dirty: boolean;
|
||||
entity: string;
|
||||
name: string;
|
||||
selections: { name: string; value: string }[];
|
||||
},
|
||||
{
|
||||
setValue: (path: string, value: any) => void;
|
||||
resetConfig: () => void;
|
||||
updateConfig: () => void;
|
||||
}
|
||||
>
|
||||
) => {
|
||||
const { currentConfig, dirty, entity, name, selections } = props.data;
|
||||
const { t, setValue, resetConfig, updateConfig } = props.methods;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Affix offsetTop={64}>
|
||||
<Alert
|
||||
message={
|
||||
<div>
|
||||
<text>
|
||||
您正在更新
|
||||
<Typography.Text
|
||||
keyboard
|
||||
>
|
||||
{entity}
|
||||
</Typography.Text>
|
||||
对象
|
||||
<Typography.Text
|
||||
keyboard
|
||||
>
|
||||
{name}
|
||||
</Typography.Text>
|
||||
的COS配置,请谨慎操作
|
||||
</text>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
showIcon
|
||||
action={
|
||||
<Space>
|
||||
<Button
|
||||
disabled={!dirty}
|
||||
type="primary"
|
||||
danger
|
||||
onClick={() => resetConfig()}
|
||||
style={{
|
||||
marginRight: 10,
|
||||
}}
|
||||
>
|
||||
{t('common::reset')}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!dirty}
|
||||
type="primary"
|
||||
onClick={() => updateConfig()}
|
||||
>
|
||||
{t('common::action.confirm')}
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
</Affix>
|
||||
<div className={Styles.contains}>
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<Typography.Text strong>默认COS源</Typography.Text>
|
||||
<Select
|
||||
value={currentConfig?.cos?.defaultOrigin}
|
||||
onChange={(v) => {
|
||||
setValue('cos.defaultOrigin', v);
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
allowClear
|
||||
placeholder="请选择默认COS源"
|
||||
>
|
||||
{selections.map((item) => (
|
||||
<Select.Option key={item.value} value={item.value}>
|
||||
{t(item.name)}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Space>
|
||||
</div >
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Cos;
|
||||
|
|
@ -6,5 +6,6 @@
|
|||
"menu": "菜单管理",
|
||||
"autoReply": "被关注回复管理",
|
||||
"tag": "标签管理",
|
||||
"user": "用户管理"
|
||||
"user": "用户管理",
|
||||
"cos": "COS配置"
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Tabs, TabsProps } from 'antd';
|
||||
import { Select, Tabs, TabsProps } from 'antd';
|
||||
import { WebComponentProps } from 'oak-frontend-base';
|
||||
import ApplicationDetail from '../detail';
|
||||
import ConfigUpsert from '../../config/application';
|
||||
|
|
@ -12,6 +12,7 @@ import WechatMenu from '../../wechatMenu';
|
|||
import UserWechatPublicTag from '../../userWechatPublicTag';
|
||||
import WechatPublicTag from '../..//wechatPublicTag/list';
|
||||
import WechatPublicAutoReply from '../../wechatPublicAutoReply';
|
||||
import Cos from '../cos';
|
||||
|
||||
export default function Render(props: WebComponentProps<EntityDict, 'application', false, {
|
||||
id: string;
|
||||
|
|
@ -59,6 +60,20 @@ export default function Render(props: WebComponentProps<EntityDict, 'application
|
|||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: <div className={Styles.tabLabel}>{t('cos')}</div>,
|
||||
key: 'cos',
|
||||
children: (
|
||||
<Cos
|
||||
oakPath={`#application-panel-cos-${id}`}
|
||||
config={config}
|
||||
entity="application"
|
||||
entityId={id}
|
||||
name={name}
|
||||
>
|
||||
</Cos>
|
||||
),
|
||||
},
|
||||
];
|
||||
if (type === 'wechatPublic') {
|
||||
items.push(
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ import {
|
|||
Form,
|
||||
Space,
|
||||
Select,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import Styles from './web.module.less';
|
||||
import { QiniuZone, CTYunZone, ALiYunZone, TencentYunZone } from 'oak-external-sdk';
|
||||
import { Config, QiniuCosConfig, CTYunCosConfig, ALiYunCosConfig, TencentYunCosConfig, LocalCosConfig, Protocol, S3CosConfig } from '../../../../types/Config';
|
||||
import { isEmptyObject } from '../../../../utils/strings';
|
||||
|
||||
// https://developer.qiniu.com/kodo/1671/region-endpoint-fq
|
||||
const QiniuZoneArray: Array<{ label: string; value: QiniuZone }> = [
|
||||
|
|
@ -1899,6 +1901,32 @@ export default function Cos(props: {
|
|||
const { qiniu, ctyun, aliyun, tencent, local, s3 } = cos;
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||
{/* 默认项选择 */}
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<Typography.Text strong>默认COS源</Typography.Text>
|
||||
<Select
|
||||
value={cos?.defaultOrigin}
|
||||
onChange={(v) => {
|
||||
setValue('defaultOrigin', v);
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
allowClear
|
||||
placeholder="请选择默认COS源"
|
||||
>
|
||||
{Object.entries(cos).map(([key, value]) => {
|
||||
if (key === 'defaultOrigin') {
|
||||
return null;
|
||||
}
|
||||
if (value && !isEmptyObject(value)) {
|
||||
return (
|
||||
<Select.Option key={key} value={key}>
|
||||
{key}
|
||||
</Select.Option>
|
||||
);
|
||||
}
|
||||
}).filter(Boolean)}
|
||||
</Select>
|
||||
</Space>
|
||||
<Row>
|
||||
<Card className={Styles.tips}>
|
||||
每种均可配置一个,相应的服务所使用的帐号请准确对应
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default OakComponent({
|
|||
disableAdd: false, // 上传按钮隐藏
|
||||
disableDownload: false, // 下载按钮隐藏
|
||||
type: 'image' as ExtraFile['type'],
|
||||
origin: 'qiniu' as ExtraFile['origin'],
|
||||
origin: null as ExtraFile['origin'] | null,
|
||||
tag1: '',
|
||||
tag2: '',
|
||||
entity: '' as keyof EntityDict,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,21 @@
|
|||
|
||||
import { CreateOperationData as I18n } from "../oak-app-domain/I18n/Schema";
|
||||
const i18ns: I18n[] = [
|
||||
{
|
||||
id: "ce78f226978ae5cc7f23a6b72d2cb8cb",
|
||||
namespace: "oak-general-business-c-application-cos",
|
||||
language: "zh-CN",
|
||||
module: "oak-general-business",
|
||||
position: "src/components/application/cos",
|
||||
data: {
|
||||
"qiniu": "七牛云",
|
||||
"ctyun": "天翼云",
|
||||
"aliyun": "阿里云",
|
||||
"tencent": "腾讯云",
|
||||
"local": "本地存储",
|
||||
"s3": "S3存储"
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "c0ce3f84c8cd6f70457b7e57a8ac8b8f",
|
||||
namespace: "oak-general-business-c-application-detail",
|
||||
|
|
@ -26,7 +41,8 @@ const i18ns: I18n[] = [
|
|||
"menu": "菜单管理",
|
||||
"autoReply": "被关注回复管理",
|
||||
"tag": "标签管理",
|
||||
"user": "用户管理"
|
||||
"user": "用户管理",
|
||||
"cos": "COS配置"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
export function isEmptyJsonObject(jsonString: string): boolean {
|
||||
try {
|
||||
const obj = JSON.parse(jsonString);
|
||||
return isEmptyObject(obj);
|
||||
} catch (error) {
|
||||
// 如果解析失败,返回 false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isEmptyObject(obj: any): boolean {
|
||||
// 处理 null 或 undefined
|
||||
if (obj === null || obj === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 处理空字符串
|
||||
if (typeof obj === 'string' && obj === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果是数组
|
||||
if (Array.isArray(obj)) {
|
||||
// 所有元素都为空才返回 true
|
||||
return obj.length === 0 || obj.every(item => isEmptyObject(item));
|
||||
}
|
||||
|
||||
// 如果是对象
|
||||
if (typeof obj === 'object') {
|
||||
const keys = Object.keys(obj);
|
||||
// 空对象返回 true
|
||||
if (keys.length === 0) {
|
||||
return true;
|
||||
}
|
||||
// 递归检查所有值
|
||||
return keys.every(key => isEmptyObject(obj[key]));
|
||||
}
|
||||
|
||||
// 其他类型(数字、布尔值等)视为非空
|
||||
return false;
|
||||
}
|
||||
Loading…
Reference in New Issue