From 4c317906ca400ef69cf4c627522cff1c049283a9 Mon Sep 17 00:00:00 2001 From: qcqcqc <1220204124@zust.edu.cn> Date: Fri, 24 Oct 2025 15:35:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BA=86application,?= =?UTF-8?q?=20system,platform=E7=9A=84defaultOrigin=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- es/components/application/cos/index.d.ts | 11 ++ es/components/application/cos/index.js | 112 +++++++++++++++ .../application/cos/locales/zh_CN.json | 8 ++ .../application/cos/styles.module.less | 5 + es/components/application/cos/web.pc.d.ts | 18 +++ es/components/application/cos/web.pc.js | 46 ++++++ .../application/panel/locales/zh-CN.json | 3 +- es/components/application/panel/web.pc.js | 7 + es/components/config/upsert/cos/index.js | 21 ++- es/components/extraFile/upload/index.js | 2 +- es/data/i18n.js | 18 ++- es/utils/strings.d.ts | 2 + es/utils/strings.js | 37 +++++ lib/data/i18n.js | 18 ++- lib/utils/strings.d.ts | 2 + lib/utils/strings.js | 41 ++++++ src/components/application/cos/index.ts | 131 ++++++++++++++++++ .../application/cos/locales/zh_CN.json | 8 ++ .../application/cos/styles.module.less | 5 + src/components/application/cos/web.pc.tsx | 103 ++++++++++++++ .../application/panel/locales/zh-CN.json | 3 +- src/components/application/panel/web.pc.tsx | 17 ++- src/components/config/upsert/cos/index.tsx | 28 ++++ src/components/extraFile/upload/index.ts | 2 +- src/data/i18n.ts | 18 ++- src/utils/strings.ts | 41 ++++++ 26 files changed, 698 insertions(+), 9 deletions(-) create mode 100644 es/components/application/cos/index.d.ts create mode 100644 es/components/application/cos/index.js create mode 100644 es/components/application/cos/locales/zh_CN.json create mode 100644 es/components/application/cos/styles.module.less create mode 100644 es/components/application/cos/web.pc.d.ts create mode 100644 es/components/application/cos/web.pc.js create mode 100644 es/utils/strings.d.ts create mode 100644 es/utils/strings.js create mode 100644 lib/utils/strings.d.ts create mode 100644 lib/utils/strings.js create mode 100644 src/components/application/cos/index.ts create mode 100644 src/components/application/cos/locales/zh_CN.json create mode 100644 src/components/application/cos/styles.module.less create mode 100644 src/components/application/cos/web.pc.tsx create mode 100644 src/utils/strings.ts diff --git a/es/components/application/cos/index.d.ts b/es/components/application/cos/index.d.ts new file mode 100644 index 000000000..c974521fa --- /dev/null +++ b/es/components/application/cos/index.d.ts @@ -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) => React.ReactElement; +export default _default; diff --git a/es/components/application/cos/index.js b/es/components/application/cos/index.js new file mode 100644 index 000000000..a587bdbcf --- /dev/null +++ b/es/components/application/cos/index.js @@ -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, + }); + }, + }, +}); diff --git a/es/components/application/cos/locales/zh_CN.json b/es/components/application/cos/locales/zh_CN.json new file mode 100644 index 000000000..e6dc09dfa --- /dev/null +++ b/es/components/application/cos/locales/zh_CN.json @@ -0,0 +1,8 @@ +{ + "qiniu": "七牛云", + "ctyun": "天翼云", + "aliyun": "阿里云", + "tencent": "腾讯云", + "local": "本地存储", + "s3": "S3存储" +} diff --git a/es/components/application/cos/styles.module.less b/es/components/application/cos/styles.module.less new file mode 100644 index 000000000..fd26aba3c --- /dev/null +++ b/es/components/application/cos/styles.module.less @@ -0,0 +1,5 @@ + + +.contains { + margin-top: 20px; +} \ No newline at end of file diff --git a/es/components/application/cos/web.pc.d.ts b/es/components/application/cos/web.pc.d.ts new file mode 100644 index 000000000..4dfb1dbf1 --- /dev/null +++ b/es/components/application/cos/web.pc.d.ts @@ -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 void; + resetConfig: () => void; + updateConfig: () => void; +}>) => React.JSX.Element; +export default Cos; diff --git a/es/components/application/cos/web.pc.js b/es/components/application/cos/web.pc.js new file mode 100644 index 000000000..9b1dc00c5 --- /dev/null +++ b/es/components/application/cos/web.pc.js @@ -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 (<> + + + + 您正在更新 + + {entity} + + 对象 + + {name} + + 的COS配置,请谨慎操作 + + } type="info" showIcon action={ + + + }/> + +
+ + 默认COS源 + + +
+ ); +}; +export default Cos; diff --git a/es/components/application/panel/locales/zh-CN.json b/es/components/application/panel/locales/zh-CN.json index 1f54a41a6..02a132124 100644 --- a/es/components/application/panel/locales/zh-CN.json +++ b/es/components/application/panel/locales/zh-CN.json @@ -6,5 +6,6 @@ "menu": "菜单管理", "autoReply": "被关注回复管理", "tag": "标签管理", - "user": "用户管理" + "user": "用户管理", + "cos": "COS配置" } diff --git a/es/components/application/panel/web.pc.js b/es/components/application/panel/web.pc.js index 2dc0711b7..a0710816c 100644 --- a/es/components/application/panel/web.pc.js +++ b/es/components/application/panel/web.pc.js @@ -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: (), }, + { + label:
{t('cos')}
, + key: 'cos', + children: ( + ), + }, ]; if (type === 'wechatPublic') { items.push({ diff --git a/es/components/config/upsert/cos/index.js b/es/components/config/upsert/cos/index.js index fc756b757..a768be332 100644 --- a/es/components/config/upsert/cos/index.js +++ b/es/components/config/upsert/cos/index.js @@ -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 ( + {/* 默认项选择 */} + + 默认COS源 + + 每种均可配置一个,相应的服务所使用的帐号请准确对应 diff --git a/es/components/extraFile/upload/index.js b/es/components/extraFile/upload/index.js index c61143357..7b7338ce1 100644 --- a/es/components/extraFile/upload/index.js +++ b/es/components/extraFile/upload/index.js @@ -64,7 +64,7 @@ export default OakComponent({ disableAdd: false, // 上传按钮隐藏 disableDownload: false, // 下载按钮隐藏 type: 'image', - origin: 'qiniu', + origin: null, tag1: '', tag2: '', entity: '', diff --git a/es/data/i18n.js b/es/data/i18n.js index 8905f1679..297ab6d14 100644 --- a/es/data/i18n.js +++ b/es/data/i18n.js @@ -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配置" } }, { diff --git a/es/utils/strings.d.ts b/es/utils/strings.d.ts new file mode 100644 index 000000000..c3949b681 --- /dev/null +++ b/es/utils/strings.d.ts @@ -0,0 +1,2 @@ +export declare function isEmptyJsonObject(jsonString: string): boolean; +export declare function isEmptyObject(obj: any): boolean; diff --git a/es/utils/strings.js b/es/utils/strings.js new file mode 100644 index 000000000..d69a7753e --- /dev/null +++ b/es/utils/strings.js @@ -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; +} diff --git a/lib/data/i18n.js b/lib/data/i18n.js index 6ebf866c3..a2acd377f 100644 --- a/lib/data/i18n.js +++ b/lib/data/i18n.js @@ -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配置" } }, { diff --git a/lib/utils/strings.d.ts b/lib/utils/strings.d.ts new file mode 100644 index 000000000..c3949b681 --- /dev/null +++ b/lib/utils/strings.d.ts @@ -0,0 +1,2 @@ +export declare function isEmptyJsonObject(jsonString: string): boolean; +export declare function isEmptyObject(obj: any): boolean; diff --git a/lib/utils/strings.js b/lib/utils/strings.js new file mode 100644 index 000000000..78c912845 --- /dev/null +++ b/lib/utils/strings.js @@ -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; +} diff --git a/src/components/application/cos/index.ts b/src/components/application/cos/index.ts new file mode 100644 index 000000000..d2b714b80 --- /dev/null +++ b/src/components/application/cos/index.ts @@ -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, + } + ) + }, + }, +}) diff --git a/src/components/application/cos/locales/zh_CN.json b/src/components/application/cos/locales/zh_CN.json new file mode 100644 index 000000000..bea31f1d1 --- /dev/null +++ b/src/components/application/cos/locales/zh_CN.json @@ -0,0 +1,8 @@ +{ + "qiniu": "七牛云", + "ctyun": "天翼云", + "aliyun": "阿里云", + "tencent": "腾讯云", + "local": "本地存储", + "s3": "S3存储" +} \ No newline at end of file diff --git a/src/components/application/cos/styles.module.less b/src/components/application/cos/styles.module.less new file mode 100644 index 000000000..fd26aba3c --- /dev/null +++ b/src/components/application/cos/styles.module.less @@ -0,0 +1,5 @@ + + +.contains { + margin-top: 20px; +} \ No newline at end of file diff --git a/src/components/application/cos/web.pc.tsx b/src/components/application/cos/web.pc.tsx new file mode 100644 index 000000000..e667e7ed9 --- /dev/null +++ b/src/components/application/cos/web.pc.tsx @@ -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 ( + <> + + + + 您正在更新 + + {entity} + + 对象 + + {name} + + 的COS配置,请谨慎操作 + + + } + type="info" + showIcon + action={ + + + + + } + /> + +
+ + 默认COS源 + + +
+ + ); +}; + +export default Cos; \ No newline at end of file diff --git a/src/components/application/panel/locales/zh-CN.json b/src/components/application/panel/locales/zh-CN.json index 176e11a69..c810c35b8 100644 --- a/src/components/application/panel/locales/zh-CN.json +++ b/src/components/application/panel/locales/zh-CN.json @@ -6,5 +6,6 @@ "menu": "菜单管理", "autoReply": "被关注回复管理", "tag": "标签管理", - "user": "用户管理" + "user": "用户管理", + "cos": "COS配置" } \ No newline at end of file diff --git a/src/components/application/panel/web.pc.tsx b/src/components/application/panel/web.pc.tsx index fc36c9173..ff898cd59 100644 --- a/src/components/application/panel/web.pc.tsx +++ b/src/components/application/panel/web.pc.tsx @@ -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 ), }, + { + label:
{t('cos')}
, + key: 'cos', + children: ( + + + ), + }, ]; if (type === 'wechatPublic') { items.push( diff --git a/src/components/config/upsert/cos/index.tsx b/src/components/config/upsert/cos/index.tsx index 5595cb3e3..3778d2ee9 100644 --- a/src/components/config/upsert/cos/index.tsx +++ b/src/components/config/upsert/cos/index.tsx @@ -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 ( + {/* 默认项选择 */} + + 默认COS源 + + 每种均可配置一个,相应的服务所使用的帐号请准确对应 diff --git a/src/components/extraFile/upload/index.ts b/src/components/extraFile/upload/index.ts index d7efb66f2..7f3d16842 100644 --- a/src/components/extraFile/upload/index.ts +++ b/src/components/extraFile/upload/index.ts @@ -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, diff --git a/src/data/i18n.ts b/src/data/i18n.ts index fc3bd4fd7..90a812551 100644 --- a/src/data/i18n.ts +++ b/src/data/i18n.ts @@ -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配置" } }, { diff --git a/src/utils/strings.ts b/src/utils/strings.ts new file mode 100644 index 000000000..68a80d7f2 --- /dev/null +++ b/src/utils/strings.ts @@ -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; +} \ No newline at end of file