feat: 修改S3配置的类型,并实现系统管理页面中S3相关的账号和cos配置
This commit is contained in:
parent
6ce0cf80aa
commit
88482b96c1
|
|
@ -11,6 +11,140 @@ import {
|
||||||
LocalCloudConfig,
|
LocalCloudConfig,
|
||||||
} from '../../../../types/Config';
|
} from '../../../../types/Config';
|
||||||
|
|
||||||
|
function S3Account(props: {
|
||||||
|
accounts: LocalCloudConfig[];
|
||||||
|
setValue: (path: string, value: any) => void;
|
||||||
|
removeItem: (path: string, index: number) => void;
|
||||||
|
addItem: (path: string, index: number) => void;
|
||||||
|
}) {
|
||||||
|
const { accounts, setValue, removeItem, addItem } = props;
|
||||||
|
return (
|
||||||
|
<Col flex="auto">
|
||||||
|
<Divider orientation="left" className={Styles.title}>
|
||||||
|
S3配置
|
||||||
|
</Divider>
|
||||||
|
<Tabs
|
||||||
|
tabPosition={'top'}
|
||||||
|
size={'middle'}
|
||||||
|
type="editable-card"
|
||||||
|
hideAdd={!(accounts.length > 0)}
|
||||||
|
onEdit={(targetKey: any, action: 'add' | 'remove') => {
|
||||||
|
if (action === 'add') {
|
||||||
|
addItem('', accounts.length);
|
||||||
|
} else {
|
||||||
|
removeItem('', parseInt(targetKey, 10));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
items={
|
||||||
|
accounts.length > 0
|
||||||
|
? accounts.map((ele, idx) => ({
|
||||||
|
key: `${idx}`,
|
||||||
|
label: `帐号${idx + 1}`,
|
||||||
|
children: (
|
||||||
|
<Form
|
||||||
|
colon={false}
|
||||||
|
labelAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
style={{ marginTop: 10 }}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="accessKey"
|
||||||
|
//name="accessKey"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入accessKey"
|
||||||
|
type="text"
|
||||||
|
value={ele.accessKey}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`${idx}.accessKey`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="secretKey"
|
||||||
|
//name="secretKey"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入secretKey"
|
||||||
|
type="text"
|
||||||
|
value={ele.secretKey}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`${idx}.secretKey`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
|
||||||
|
</Form>
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
label: '新建帐号',
|
||||||
|
key: '0',
|
||||||
|
children: (
|
||||||
|
<Form
|
||||||
|
colon={true}
|
||||||
|
labelAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
style={{ marginTop: 10 }}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="accessKey"
|
||||||
|
// name="accessKey"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入accessKey"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`0.accessKey`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="secretKey"
|
||||||
|
// name="secretKey"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入secretKey"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`0.secretKey`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
></Tabs>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function LocalAccount(props: {
|
function LocalAccount(props: {
|
||||||
accounts: LocalCloudConfig[];
|
accounts: LocalCloudConfig[];
|
||||||
setValue: (path: string, value: any) => void;
|
setValue: (path: string, value: any) => void;
|
||||||
|
|
@ -1035,7 +1169,7 @@ export default function Account(props: {
|
||||||
removeItem: (path: string, index: number) => void;
|
removeItem: (path: string, index: number) => void;
|
||||||
}) {
|
}) {
|
||||||
const { account, setValue, removeItem } = props;
|
const { account, setValue, removeItem } = props;
|
||||||
const { tencent, qiniu, ali, amap, ctyun, local } = account;
|
const { tencent, qiniu, ali, amap, ctyun, local, s3 } = account;
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||||
<Row>
|
<Row>
|
||||||
|
|
@ -1073,6 +1207,12 @@ export default function Account(props: {
|
||||||
removeItem={(path, index) => removeItem(`local`, index)}
|
removeItem={(path, index) => removeItem(`local`, index)}
|
||||||
addItem={(path, index) => setValue(`local.${index}`, {})}
|
addItem={(path, index) => setValue(`local.${index}`, {})}
|
||||||
/>
|
/>
|
||||||
|
<S3Account
|
||||||
|
accounts={s3 || []}
|
||||||
|
setValue={(path, value) => setValue(`s3.${path}`, value)}
|
||||||
|
removeItem={(path, index) => removeItem(`s3`, index)}
|
||||||
|
addItem={(path, index) => setValue(`s3.${index}`, {})}
|
||||||
|
/>
|
||||||
<AmapAccount
|
<AmapAccount
|
||||||
accounts={amap || []}
|
accounts={amap || []}
|
||||||
setValue={(path, value) => setValue(`amap.${path}`, value)}
|
setValue={(path, value) => setValue(`amap.${path}`, value)}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import {
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import Styles from './web.module.less';
|
import Styles from './web.module.less';
|
||||||
import { QiniuZone, CTYunZone, ALiYunZone, TencentYunZone } from 'oak-external-sdk';
|
import { QiniuZone, CTYunZone, ALiYunZone, TencentYunZone } from 'oak-external-sdk';
|
||||||
import { Config, QiniuCosConfig, CTYunCosConfig, ALiYunCosConfig, TencentYunCosConfig, LocalCosConfig, Protocol } from '../../../../types/Config';
|
import { Config, QiniuCosConfig, CTYunCosConfig, ALiYunCosConfig, TencentYunCosConfig, LocalCosConfig, Protocol, S3CosConfig } from '../../../../types/Config';
|
||||||
|
|
||||||
// https://developer.qiniu.com/kodo/1671/region-endpoint-fq
|
// https://developer.qiniu.com/kodo/1671/region-endpoint-fq
|
||||||
const QiniuZoneArray: Array<{ label: string; value: QiniuZone }> = [
|
const QiniuZoneArray: Array<{ label: string; value: QiniuZone }> = [
|
||||||
|
|
@ -386,8 +386,7 @@ function CTYunCos(props: {
|
||||||
) => {
|
) => {
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
setValue(
|
setValue(
|
||||||
`buckets.${
|
`buckets.${cos?.buckets?.length || 0
|
||||||
cos?.buckets?.length || 0
|
|
||||||
}`,
|
}`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
@ -707,8 +706,7 @@ function ALiYunCos(props: {
|
||||||
) => {
|
) => {
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
setValue(
|
setValue(
|
||||||
`buckets.${
|
`buckets.${cos?.buckets?.length || 0
|
||||||
cos?.buckets?.length || 0
|
|
||||||
}`,
|
}`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
@ -1008,8 +1006,7 @@ function TencentYunCos(props: {
|
||||||
) => {
|
) => {
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
setValue(
|
setValue(
|
||||||
`buckets.${
|
`buckets.${cos?.buckets?.length || 0
|
||||||
cos?.buckets?.length || 0
|
|
||||||
}`,
|
}`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
@ -1249,8 +1246,7 @@ function LocalCos(props: {
|
||||||
) => {
|
) => {
|
||||||
if (action === 'add') {
|
if (action === 'add') {
|
||||||
setValue(
|
setValue(
|
||||||
`buckets.${
|
`buckets.${cos?.buckets?.length || 0
|
||||||
cos?.buckets?.length || 0
|
|
||||||
}`,
|
}`,
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
@ -1482,13 +1478,425 @@ function LocalCos(props: {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AWSS3RegionArray: Array<{ label: string; value: string }> = [
|
||||||
|
{
|
||||||
|
label: "使用自定义endpoint",
|
||||||
|
value: "custom",
|
||||||
|
},
|
||||||
|
// 美国
|
||||||
|
{
|
||||||
|
label: '美国东部(弗吉尼亚北部)',
|
||||||
|
value: 'us-east-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '美国东部(俄亥俄)',
|
||||||
|
value: 'us-east-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '美国西部(加利福尼亚北部)',
|
||||||
|
value: 'us-west-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '美国西部(俄勒冈)',
|
||||||
|
value: 'us-west-2',
|
||||||
|
},
|
||||||
|
// 亚太地区
|
||||||
|
{
|
||||||
|
label: '亚太地区(孟买)',
|
||||||
|
value: 'ap-south-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(海得拉巴)',
|
||||||
|
value: 'ap-south-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(东京)',
|
||||||
|
value: 'ap-northeast-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(首尔)',
|
||||||
|
value: 'ap-northeast-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(大阪)',
|
||||||
|
value: 'ap-northeast-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(新加坡)',
|
||||||
|
value: 'ap-southeast-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(悉尼)',
|
||||||
|
value: 'ap-southeast-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(雅加达)',
|
||||||
|
value: 'ap-southeast-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(墨尔本)',
|
||||||
|
value: 'ap-southeast-4',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚太地区(中国香港)',
|
||||||
|
value: 'ap-east-1',
|
||||||
|
},
|
||||||
|
// 欧洲
|
||||||
|
{
|
||||||
|
label: '欧洲(爱尔兰)',
|
||||||
|
value: 'eu-west-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(伦敦)',
|
||||||
|
value: 'eu-west-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(巴黎)',
|
||||||
|
value: 'eu-west-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(法兰克福)',
|
||||||
|
value: 'eu-central-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(苏黎世)',
|
||||||
|
value: 'eu-central-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(斯德哥尔摩)',
|
||||||
|
value: 'eu-north-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(米兰)',
|
||||||
|
value: 'eu-south-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '欧洲(西班牙)',
|
||||||
|
value: 'eu-south-2',
|
||||||
|
},
|
||||||
|
// 加拿大
|
||||||
|
{
|
||||||
|
label: '加拿大(中部)',
|
||||||
|
value: 'ca-central-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '加拿大西部(卡尔加里)',
|
||||||
|
value: 'ca-west-1',
|
||||||
|
},
|
||||||
|
// 南美洲
|
||||||
|
{
|
||||||
|
label: '南美洲(圣保罗)',
|
||||||
|
value: 'sa-east-1',
|
||||||
|
},
|
||||||
|
// 中东
|
||||||
|
{
|
||||||
|
label: '中东(巴林)',
|
||||||
|
value: 'me-south-1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '中东(阿联酋)',
|
||||||
|
value: 'me-central-1',
|
||||||
|
},
|
||||||
|
// 非洲
|
||||||
|
{
|
||||||
|
label: '非洲(开普敦)',
|
||||||
|
value: 'af-south-1',
|
||||||
|
},
|
||||||
|
// 以色列
|
||||||
|
{
|
||||||
|
label: '以色列(特拉维夫)',
|
||||||
|
value: 'il-central-1',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function S3Cos(props: {
|
||||||
|
cos: S3CosConfig;
|
||||||
|
setValue: (path: string, value: any) => void;
|
||||||
|
removeItem: (path: string, index: number) => void;
|
||||||
|
}) {
|
||||||
|
const { cos, setValue, removeItem } = props;
|
||||||
|
return (
|
||||||
|
<Col flex="auto">
|
||||||
|
<Divider orientation="left" className={Styles.title}>
|
||||||
|
S3对象存储配置
|
||||||
|
</Divider>
|
||||||
|
<Tabs
|
||||||
|
tabPosition={'top'}
|
||||||
|
size={'middle'}
|
||||||
|
type="card"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
key: '0',
|
||||||
|
label: '配置项',
|
||||||
|
children: (
|
||||||
|
<Form
|
||||||
|
colon={true}
|
||||||
|
labelAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
style={{ marginTop: 10 }}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="accessKey"
|
||||||
|
//name="accessKey"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入accessKey"
|
||||||
|
type="text"
|
||||||
|
value={cos?.accessKey}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`accessKey`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="endpoint"
|
||||||
|
//name="accessKey"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
pattern: /^(([0-9]{1,3}\.){3}[0-9]{1,3}|[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(:\d{1,5})?$/,
|
||||||
|
message: '格式必须为: 域名:端口 或 IP:端口,不可包含http://、https://前缀或/后缀'
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入endpoint"
|
||||||
|
type="text"
|
||||||
|
value={cos?.endpoint}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`endpoint`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
{/* <Form.Item
|
||||||
|
label="bucket"
|
||||||
|
//name="bucket"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入bucket"
|
||||||
|
type="text"
|
||||||
|
value={cos?.bucket}
|
||||||
|
onChange={(e) =>
|
||||||
|
setValue(
|
||||||
|
`bucket`,
|
||||||
|
e.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item> */}
|
||||||
|
<Divider
|
||||||
|
orientation="left"
|
||||||
|
className={Styles.title}
|
||||||
|
>
|
||||||
|
bucket配置
|
||||||
|
</Divider>
|
||||||
|
<Tabs
|
||||||
|
tabPosition={'top'}
|
||||||
|
size={'middle'}
|
||||||
|
type="editable-card"
|
||||||
|
// hideAdd={!(sms.length > 0)}
|
||||||
|
onEdit={(
|
||||||
|
targetKey: any,
|
||||||
|
action: 'add' | 'remove'
|
||||||
|
) => {
|
||||||
|
if (action === 'add') {
|
||||||
|
setValue(
|
||||||
|
`buckets.${cos?.buckets?.length || 0
|
||||||
|
}`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
removeItem(
|
||||||
|
'buckets',
|
||||||
|
parseInt(targetKey, 10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
items={
|
||||||
|
cos?.buckets?.length > 0
|
||||||
|
? cos.buckets.map((ele, idx) => ({
|
||||||
|
key: `${idx}`,
|
||||||
|
label: `bucket:${idx + 1}`,
|
||||||
|
children: (
|
||||||
|
<Form
|
||||||
|
colon={false}
|
||||||
|
labelAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
style={{
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label="name"
|
||||||
|
// name="name"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入name"
|
||||||
|
type="text"
|
||||||
|
value={
|
||||||
|
ele.name
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
e
|
||||||
|
) =>
|
||||||
|
setValue(
|
||||||
|
`buckets.${idx}.name`,
|
||||||
|
e
|
||||||
|
.target
|
||||||
|
.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="zone"
|
||||||
|
//name="uploadHost"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Select
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
placeholder="请选择存储区域"
|
||||||
|
value={
|
||||||
|
ele.zone
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
value: string
|
||||||
|
) => {
|
||||||
|
setValue(
|
||||||
|
`buckets.${idx}.zone`,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={
|
||||||
|
AWSS3RegionArray
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="domain"
|
||||||
|
// name="domain"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
placeholder="请输入domain"
|
||||||
|
type="text"
|
||||||
|
value={
|
||||||
|
ele.domain
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
e
|
||||||
|
) =>
|
||||||
|
setValue(
|
||||||
|
`buckets.${idx}.domain`,
|
||||||
|
e
|
||||||
|
.target
|
||||||
|
.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="protocol"
|
||||||
|
// name="protocol"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Select
|
||||||
|
mode="multiple"
|
||||||
|
allowClear
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
}}
|
||||||
|
placeholder="请选择协议"
|
||||||
|
value={
|
||||||
|
ele?.protocol as Protocol[]
|
||||||
|
}
|
||||||
|
onChange={(
|
||||||
|
value: Protocol[]
|
||||||
|
) => {
|
||||||
|
setValue(
|
||||||
|
`buckets.${idx}.protocol`,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: 'http:',
|
||||||
|
value: 'http:',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'https:',
|
||||||
|
value: 'https:',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{cos?.buckets?.length > 0 && (
|
||||||
|
<Form.Item
|
||||||
|
label="defaultBucket"
|
||||||
|
//name="uploadHost"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Select
|
||||||
|
allowClear
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
placeholder="请选择默认bucket"
|
||||||
|
value={cos.defaultBucket}
|
||||||
|
onChange={(value: string) => {
|
||||||
|
setValue(
|
||||||
|
`defaultBucket`,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={cos.buckets.map(
|
||||||
|
(ele) => ({
|
||||||
|
label: ele.name,
|
||||||
|
value: ele.name,
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></Tabs>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function Cos(props: {
|
export default function Cos(props: {
|
||||||
cos: Required<Config>['Cos'];
|
cos: Required<Config>['Cos'];
|
||||||
setValue: (path: string, value: any) => void;
|
setValue: (path: string, value: any) => void;
|
||||||
removeItem: (path: string, index: number) => void;
|
removeItem: (path: string, index: number) => void;
|
||||||
}) {
|
}) {
|
||||||
const { cos, setValue, removeItem } = props;
|
const { cos, setValue, removeItem } = props;
|
||||||
const { qiniu, ctyun, aliyun, tencent, local } = cos;
|
const { qiniu, ctyun, aliyun, tencent, local, s3 } = cos;
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
<Space direction="vertical" size="middle" style={{ display: 'flex' }}>
|
||||||
<Row>
|
<Row>
|
||||||
|
|
@ -1520,6 +1928,11 @@ export default function Cos(props: {
|
||||||
removeItem(`tencent.${path}`, index)
|
removeItem(`tencent.${path}`, index)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<S3Cos
|
||||||
|
cos={s3!}
|
||||||
|
setValue={(path, value) => setValue(`s3.${path}`, value)}
|
||||||
|
removeItem={(path, index) => removeItem(`s3.${path}`, index)}
|
||||||
|
/>
|
||||||
<LocalCos
|
<LocalCos
|
||||||
cos={local!}
|
cos={local!}
|
||||||
setValue={(path, value) => setValue(`local.${path}`, value)}
|
setValue={(path, value) => setValue(`local.${path}`, value)}
|
||||||
|
|
|
||||||
|
|
@ -94,13 +94,12 @@ export type S3Zone =
|
||||||
// S3/Minio 配置类型
|
// S3/Minio 配置类型
|
||||||
export type S3CosConfig = {
|
export type S3CosConfig = {
|
||||||
accessKey: string;
|
accessKey: string;
|
||||||
secretKey: string; // S3 需要 secretKey
|
endpoint?: string; // 自定义端点(Minio 必需,AWS S3 可选)
|
||||||
buckets: {
|
buckets: {
|
||||||
zone?: S3Zone; // S3 区域 (某些 S3 兼容服务可能不需要)
|
zone?: S3Zone; // S3 区域 (某些 S3 兼容服务可能不需要)
|
||||||
name: string; // 桶名称
|
name: string; // 桶名称
|
||||||
domain: string; // 访问域名
|
domain: string; // 访问域名
|
||||||
protocol: Protocol | Protocol[];
|
protocol: Protocol | Protocol[];
|
||||||
endpoint?: string; // 自定义端点(Minio 必需,AWS S3 可选)
|
|
||||||
pathStyle?: boolean; // 是否使用路径风格 URL(Minio 常用)
|
pathStyle?: boolean; // 是否使用路径风格 URL(Minio 常用)
|
||||||
}[];
|
}[];
|
||||||
defaultBucket: string; // 默认上传桶
|
defaultBucket: string; // 默认上传桶
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,36 @@ import { CosBackend } from '../../types/Cos';
|
||||||
import S3 from './s3';
|
import S3 from './s3';
|
||||||
import { OpSchema } from '../../oak-app-domain/ExtraFile/Schema';
|
import { OpSchema } from '../../oak-app-domain/ExtraFile/Schema';
|
||||||
|
|
||||||
import { S3CosConfig } from '../../types/Config';
|
import { S3CosConfig, S3Zone } from '../../types/Config';
|
||||||
import { S3Instance, S3SDK } from 'oak-external-sdk';
|
import { S3Instance, S3SDK } from 'oak-external-sdk';
|
||||||
import { OakExternalException } from 'oak-domain/lib/types/Exception';
|
import { OakExternalException } from 'oak-domain/lib/types/Exception';
|
||||||
|
|
||||||
export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
private getConfigAndInstance(
|
private getConfigAndInstance(
|
||||||
application: EntityDict['application']['Schema']
|
application: EntityDict['application']['Schema'],
|
||||||
|
bucket: string | null | undefined
|
||||||
) {
|
) {
|
||||||
const { config, account } = this.getConfig(application);
|
const { config, account, endpoint, defaultBucket } = this.getConfig(application);
|
||||||
|
|
||||||
|
const realBucket = bucket || defaultBucket;
|
||||||
|
assert(realBucket, '没有指定上传桶,且配置中也没有默认上传桶');
|
||||||
|
|
||||||
|
// 在配置中找名称匹配的桶
|
||||||
|
const { buckets } = config as S3CosConfig;
|
||||||
|
let bucketConfig = bucket
|
||||||
|
? buckets.find((ele) => ele.name === realBucket)
|
||||||
|
: buckets[0];
|
||||||
|
|
||||||
const instance = S3SDK.getInstance(
|
const instance = S3SDK.getInstance(
|
||||||
account.accessKey,
|
account.accessKey,
|
||||||
account.secretKey,
|
account.secretKey,
|
||||||
config.buckets[0]?.endpoint, // 使用第一个 bucket 的 endpoint 作为默认
|
endpoint,
|
||||||
config.buckets[0]?.zone
|
bucketConfig?.zone || 'us-east-1' as S3Zone
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
config,
|
config,
|
||||||
instance,
|
instance,
|
||||||
|
endpoint,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,8 +43,7 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
) {
|
) {
|
||||||
const { bucket } = extraFile;
|
const { bucket } = extraFile;
|
||||||
const key = this.formKey(extraFile);
|
const key = this.formKey(extraFile);
|
||||||
const { instance, config: s3CosConfig } =
|
const { instance, config: s3CosConfig, endpoint } = this.getConfigAndInstance(application, bucket);
|
||||||
this.getConfigAndInstance(application);
|
|
||||||
|
|
||||||
const { buckets } = s3CosConfig as S3CosConfig;
|
const { buckets } = s3CosConfig as S3CosConfig;
|
||||||
let bucket2 = bucket;
|
let bucket2 = bucket;
|
||||||
|
|
@ -48,7 +59,7 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
const uploadInfo = await (instance as S3Instance).getUploadInfo(
|
const uploadInfo = await (instance as S3Instance).getUploadInfo(
|
||||||
bucket2,
|
bucket2,
|
||||||
key,
|
key,
|
||||||
b.endpoint,
|
endpoint,
|
||||||
b.pathStyle
|
b.pathStyle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -65,9 +76,10 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
application: EntityDict['application']['Schema'],
|
application: EntityDict['application']['Schema'],
|
||||||
extraFile: OpSchema
|
extraFile: OpSchema
|
||||||
) {
|
) {
|
||||||
|
const { bucket } = extraFile;
|
||||||
const key = this.formKey(extraFile);
|
const key = this.formKey(extraFile);
|
||||||
const { instance, config: s3CosConfig } =
|
const { instance, config: s3CosConfig, endpoint } =
|
||||||
this.getConfigAndInstance(application);
|
this.getConfigAndInstance(application, bucket);
|
||||||
|
|
||||||
const b = (s3CosConfig as S3CosConfig).buckets.find(
|
const b = (s3CosConfig as S3CosConfig).buckets.find(
|
||||||
(ele) => ele.name === extraFile.bucket
|
(ele) => ele.name === extraFile.bucket
|
||||||
|
|
@ -81,7 +93,7 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
const result = await (instance as S3Instance).isExistObject(
|
const result = await (instance as S3Instance).isExistObject(
|
||||||
extraFile.bucket!,
|
extraFile.bucket!,
|
||||||
key,
|
key,
|
||||||
b.endpoint,
|
endpoint,
|
||||||
b.pathStyle
|
b.pathStyle
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -95,9 +107,10 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
application: EntityDict['application']['Schema'],
|
application: EntityDict['application']['Schema'],
|
||||||
extraFile: OpSchema
|
extraFile: OpSchema
|
||||||
) {
|
) {
|
||||||
|
const { bucket } = extraFile
|
||||||
const key = this.formKey(extraFile);
|
const key = this.formKey(extraFile);
|
||||||
const { instance, config: s3CosConfig } =
|
const { instance, config: s3CosConfig, endpoint } =
|
||||||
this.getConfigAndInstance(application);
|
this.getConfigAndInstance(application, bucket);
|
||||||
|
|
||||||
const b = (s3CosConfig as S3CosConfig).buckets.find(
|
const b = (s3CosConfig as S3CosConfig).buckets.find(
|
||||||
(ele) => ele.name === extraFile.bucket
|
(ele) => ele.name === extraFile.bucket
|
||||||
|
|
@ -111,7 +124,7 @@ export default class S3Backend extends S3 implements CosBackend<EntityDict> {
|
||||||
await (instance as S3Instance).removeFile(
|
await (instance as S3Instance).removeFile(
|
||||||
extraFile.bucket!,
|
extraFile.bucket!,
|
||||||
key,
|
key,
|
||||||
b.endpoint,
|
endpoint,
|
||||||
b.pathStyle
|
b.pathStyle
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default class S3 implements Cos<EntityDict> {
|
||||||
const { config } = system!;
|
const { config } = system!;
|
||||||
const s3Config = config.Cos?.s3;
|
const s3Config = config.Cos?.s3;
|
||||||
assert(s3Config);
|
assert(s3Config);
|
||||||
const { accessKey } = s3Config;
|
const { accessKey, endpoint, defaultBucket } = s3Config;
|
||||||
const account = config.Account?.s3?.find(
|
const account = config.Account?.s3?.find(
|
||||||
(ele) => ele.accessKey === accessKey
|
(ele) => ele.accessKey === accessKey
|
||||||
);
|
);
|
||||||
|
|
@ -28,6 +28,8 @@ export default class S3 implements Cos<EntityDict> {
|
||||||
return {
|
return {
|
||||||
config: s3Config,
|
config: s3Config,
|
||||||
account,
|
account,
|
||||||
|
endpoint,
|
||||||
|
defaultBucket,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +92,7 @@ export default class S3 implements Cos<EntityDict> {
|
||||||
extraFile: Partial<EntityDict['extraFile']['OpSchema']>,
|
extraFile: Partial<EntityDict['extraFile']['OpSchema']>,
|
||||||
style?: string
|
style?: string
|
||||||
) {
|
) {
|
||||||
const { config: s3CosConfig } = this.getConfig(application);
|
const { config: s3CosConfig, endpoint } = this.getConfig(application);
|
||||||
|
|
||||||
if (s3CosConfig) {
|
if (s3CosConfig) {
|
||||||
let bucket = (
|
let bucket = (
|
||||||
|
|
@ -98,7 +100,7 @@ export default class S3 implements Cos<EntityDict> {
|
||||||
).find((ele) => ele.name === extraFile.bucket!);
|
).find((ele) => ele.name === extraFile.bucket!);
|
||||||
|
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
const { domain, protocol, endpoint, pathStyle } = bucket;
|
const { domain, protocol, pathStyle } = bucket;
|
||||||
let protocol2 = protocol;
|
let protocol2 = protocol;
|
||||||
if (protocol instanceof Array) {
|
if (protocol instanceof Array) {
|
||||||
const index = (protocol as Protocol[]).includes('https:')
|
const index = (protocol as Protocol[]).includes('https:')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue