From f30199f9aec57f29cd1e1665356b8444a36fb5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=90=E5=A4=9C?= <278898052@qq.com> Date: Wed, 7 May 2025 17:31:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=8F=96=E6=B6=88=E6=B5=81=E7=A8=8B=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=B5=81=E7=A8=8B=E5=AE=9E=E4=BE=8B=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E5=BE=85=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/bpm/processInstance/index.ts | 163 +++++++++++++ apps/web-antd/src/utils/constants.ts | 129 ++++++++++ apps/web-antd/src/utils/formatTime.ts | 31 +++ apps/web-antd/src/utils/index.ts | 1 + .../views/bpm/processInstance/manager/data.ts | 227 +++++++++++++++++ .../bpm/processInstance/manager/index.vue | 141 +++++++++-- packages/locales/src/langs/en-US/ui.json | 229 +++++++++--------- packages/locales/src/langs/zh-CN/ui.json | 229 +++++++++--------- 8 files changed, 900 insertions(+), 250 deletions(-) create mode 100644 apps/web-antd/src/api/bpm/processInstance/index.ts create mode 100644 apps/web-antd/src/utils/formatTime.ts create mode 100644 apps/web-antd/src/views/bpm/processInstance/manager/data.ts diff --git a/apps/web-antd/src/api/bpm/processInstance/index.ts b/apps/web-antd/src/api/bpm/processInstance/index.ts new file mode 100644 index 000000000..cec0a1fdd --- /dev/null +++ b/apps/web-antd/src/api/bpm/processInstance/index.ts @@ -0,0 +1,163 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import type { BpmModelApi } from '#/api/bpm/model'; +import type { CandidateStrategy, NodeType } from '#/utils'; + +import { requestClient } from '#/api/request'; + +export namespace BpmProcessInstanceApi { + export type Task = { + id: number; + name: string; + }; + + export type User = { + avatar: string; + id: number; + nickname: string; + }; + + // 审批任务信息 + export type ApprovalTaskInfo = { + assigneeUser: User; + id: number; + ownerUser: User; + reason: string; + signPicUrl: string; + status: number; + }; + + // 审批节点信息 + export type ApprovalNodeInfo = { + candidateStrategy?: CandidateStrategy; + candidateUsers?: User[]; + endTime?: Date; + id: number; + name: string; + nodeType: NodeType; + startTime?: Date; + status: number; + tasks: ApprovalTaskInfo[]; + }; + + export type ProcessInstanceVO = { + businessKey: string; + category: string; + createTime: string; + endTime: string; + fields: string[]; + id: number; + name: string; + processDefinition?: BpmModelApi.ProcessDefinitionVO; + processDefinitionId: string; + remark: string; + result: number; + status: number; + tasks: BpmProcessInstanceApi.Task[]; + }; +} + +/** 查询我的流程实例分页 */ +export async function getProcessInstanceMyPage(params: PageParam) { + return requestClient.get>( + '/bpm/process-instance/my-page', + { params }, + ); +} + +/** 查询管理员流程实例分页 */ +export async function getProcessInstanceManagerPage(params: PageParam) { + return requestClient.get>( + '/bpm/process-instance/manager-page', + { params }, + ); +} + +/** 新增流程实例 */ +export async function createProcessInstance( + data: BpmProcessInstanceApi.ProcessInstanceVO, +) { + return requestClient.post( + '/bpm/process-instance/create', + data, + ); +} + +/** 申请人主动取消流程实例 */ +export async function cancelProcessInstanceByStartUser( + id: number, + reason: string, +) { + return requestClient.delete( + '/bpm/process-instance/cancel-by-start-user', + { + data: { id, reason }, + }, + ); +} + +/** 管理员取消流程实例 */ +export async function cancelProcessInstanceByAdmin(id: number, reason: string) { + return requestClient.delete( + '/bpm/process-instance/cancel-by-admin', + { + data: { id, reason }, + }, + ); +} + +/** 查询流程实例详情 */ +export async function getProcessInstance(id: number) { + return requestClient.get( + `/bpm/process-instance/get?id=${id}`, + ); +} + +/** 查询复制流程实例分页 */ +export async function getProcessInstanceCopyPage(params: PageParam) { + return requestClient.get>( + '/bpm/process-instance/copy/page', + { params }, + ); +} + +/** 更新流程实例 */ +export async function updateProcessInstance( + data: BpmProcessInstanceApi.ProcessInstanceVO, +) { + return requestClient.put( + '/bpm/process-instance/update', + data, + ); +} + +/** 获取审批详情 */ +export async function getApprovalDetail(params: any) { + return requestClient.get( + `/bpm/process-instance/get-approval-detail`, + { params }, + ); +} + +/** 获取下一个执行的流程节点 */ +export async function getNextApprovalNodes(params: any) { + return requestClient.get( + `/bpm/process-instance/get-next-approval-nodes`, + { params }, + ); +} + +/** 获取表单字段权限 */ +export async function getFormFieldsPermission(params: any) { + return requestClient.get( + `/bpm/process-instance/get-form-fields-permission`, + { params }, + ); +} + +/** 获取流程实例 BPMN 模型视图 */ +export async function getProcessInstanceBpmnModelView(id: number) { + return requestClient.get( + `/bpm/process-instance/get-bpmn-model-view?id=${id}`, + ); +} diff --git a/apps/web-antd/src/utils/constants.ts b/apps/web-antd/src/utils/constants.ts index ac1d8120a..ec58eec82 100644 --- a/apps/web-antd/src/utils/constants.ts +++ b/apps/web-antd/src/utils/constants.ts @@ -464,3 +464,132 @@ export const BpmAutoApproveType = { APPROVE_ALL: 1, // 仅审批一次,后续重复的审批节点均自动通过 APPROVE_SEQUENT: 2, // 仅针对连续审批的节点自动通过 }; + +// 候选人策略枚举 ( 用于审批节点。抄送节点 ) +export enum CandidateStrategy { + /** + * 审批人自选 + */ + APPROVE_USER_SELECT = 34, + /** + * 部门的负责人 + */ + DEPT_LEADER = 21, + /** + * 部门成员 + */ + DEPT_MEMBER = 20, + /** + * 流程表达式 + */ + EXPRESSION = 60, + /** + * 表单内部门负责人 + */ + FORM_DEPT_LEADER = 51, + /** + * 表单内用户字段 + */ + FORM_USER = 50, + /** + * 连续多级部门的负责人 + */ + MULTI_LEVEL_DEPT_LEADER = 23, + /** + * 指定岗位 + */ + POST = 22, + /** + * 指定角色 + */ + ROLE = 10, + /** + * 发起人自己 + */ + START_USER = 36, + /** + * 发起人部门负责人 + */ + START_USER_DEPT_LEADER = 37, + /** + * 发起人连续多级部门的负责人 + */ + START_USER_MULTI_LEVEL_DEPT_LEADER = 38, + /** + * 发起人自选 + */ + START_USER_SELECT = 35, + /** + * 指定用户 + */ + USER = 30, + /** + * 指定用户组 + */ + USER_GROUP = 40, +} + +/** + * 节点类型 + */ +export enum NodeType { + /** + * 子流程节点 + */ + CHILD_PROCESS_NODE = 20, + /** + * 条件分支节点 (对应排他网关) + */ + CONDITION_BRANCH_NODE = 51, + /** + * 条件节点 + */ + CONDITION_NODE = 50, + + /** + * 抄送人节点 + */ + COPY_TASK_NODE = 12, + + /** + * 延迟器节点 + */ + DELAY_TIMER_NODE = 14, + + /** + * 结束节点 + */ + END_EVENT_NODE = 1, + + /** + * 包容分支节点 (对应包容网关) + */ + INCLUSIVE_BRANCH_NODE = 53, + + /** + * 并行分支节点 (对应并行网关) + */ + PARALLEL_BRANCH_NODE = 52, + + /** + * 路由分支节点 + */ + ROUTER_BRANCH_NODE = 54, + /** + * 发起人节点 + */ + START_USER_NODE = 10, + /** + * 办理人节点 + */ + TRANSACTOR_NODE = 13, + + /** + * 触发器节点 + */ + TRIGGER_NODE = 15, + /** + * 审批人节点 + */ + USER_TASK_NODE = 11, +} diff --git a/apps/web-antd/src/utils/formatTime.ts b/apps/web-antd/src/utils/formatTime.ts new file mode 100644 index 000000000..3d4e47228 --- /dev/null +++ b/apps/web-antd/src/utils/formatTime.ts @@ -0,0 +1,31 @@ +/** + * 将毫秒,转换成时间字符串。例如说,xx 分钟 + * + * @param ms 毫秒 + * @returns {string} 字符串 + */ +export function formatPast2(ms: number): string { + // 定义时间单位常量,便于维护 + const SECOND = 1000; + const MINUTE = 60 * SECOND; + const HOUR = 60 * MINUTE; + const DAY = 24 * HOUR; + + // 计算各时间单位 + const day = Math.floor(ms / DAY); + const hour = Math.floor((ms % DAY) / HOUR); + const minute = Math.floor((ms % HOUR) / MINUTE); + const second = Math.floor((ms % MINUTE) / SECOND); + + // 根据时间长短返回不同格式 + if (day > 0) { + return `${day} 天${hour} 小时 ${minute} 分钟`; + } + if (hour > 0) { + return `${hour} 小时 ${minute} 分钟`; + } + if (minute > 0) { + return `${minute} 分钟`; + } + return second > 0 ? `${second} 秒` : `${0} 秒`; +} diff --git a/apps/web-antd/src/utils/index.ts b/apps/web-antd/src/utils/index.ts index 9dc13ef18..dfcc60466 100644 --- a/apps/web-antd/src/utils/index.ts +++ b/apps/web-antd/src/utils/index.ts @@ -1,4 +1,5 @@ export * from './constants'; export * from './dict'; +export * from './formatTime'; export * from './rangePickerProps'; export * from './validator'; diff --git a/apps/web-antd/src/views/bpm/processInstance/manager/data.ts b/apps/web-antd/src/views/bpm/processInstance/manager/data.ts new file mode 100644 index 000000000..2821c5822 --- /dev/null +++ b/apps/web-antd/src/views/bpm/processInstance/manager/data.ts @@ -0,0 +1,227 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance'; + +import { h } from 'vue'; + +import { useAccess } from '@vben/access'; + +import { Button } from 'ant-design-vue'; + +import { getCategorySimpleList } from '#/api/bpm/category'; +import { getSimpleUserList } from '#/api/system/user'; +import { $t } from '#/locales'; +import { + DICT_TYPE, + formatPast2, + getDictOptions, + getRangePickerDefaultProps, +} from '#/utils'; + +import { BpmProcessInstanceStatus } from '../../../../utils/constants'; + +const { hasAccessByCodes } = useAccess(); + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'startUserId', + label: '发起人', + component: 'ApiSelect', + componentProps: { + placeholder: '请选择发起人', + allowClear: true, + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + }, + { + fieldName: 'name', + label: '流程名称', + component: 'Input', + componentProps: { + placeholder: '请输入流程名称', + allowClear: true, + }, + }, + { + fieldName: 'processDefinitionId', + label: '所属流程', + component: 'Input', + componentProps: { + placeholder: '请输入流程定义的编号', + allowClear: true, + }, + }, + // 流程分类 + { + fieldName: 'category', + label: '流程分类', + component: 'ApiSelect', + componentProps: { + placeholder: '请输入流程分类', + allowClear: true, + api: getCategorySimpleList, + labelField: 'name', + valueField: 'code', + }, + }, + // 流程状态 + { + fieldName: 'status', + label: '流程状态', + component: 'Select', + componentProps: { + options: getDictOptions( + DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS, + 'number', + ), + placeholder: '请选择流程状态', + allowClear: true, + }, + }, + // 发起时间 + { + fieldName: 'createTime', + label: '发起时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onActionClick: OnActionClickFn, + onTaskClick: (task: BpmProcessInstanceApi.Task) => void, +): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '流程名称', + minWidth: 200, + fixed: 'left', + }, + + { + field: 'categoryName', + title: '流程分类', + minWidth: 120, + fixed: 'left', + }, + + { + field: 'startUser.nickname', + title: '流程发起人', + minWidth: 120, + }, + + { + field: 'startUser.deptName', + title: '发起部门', + minWidth: 120, + }, + + // 流程状态 + { + field: 'status', + title: '流程状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS }, + }, + }, + + { + field: 'startTime', + title: '发起时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'endTime', + title: '结束时间', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + field: 'durationInMillis', + title: '流程耗时', + minWidth: 180, + slots: { + default: ({ row }) => { + return row.durationInMillis > 0 + ? formatPast2(row.durationInMillis) + : '-'; + }, + }, + }, + + // 当前审批任务 tasks + { + field: 'tasks', + title: '当前审批任务', + minWidth: 320, + slots: { + default: ({ row }) => { + if (!row?.tasks?.length) return '-'; + + return row.tasks.map((task: BpmProcessInstanceApi.Task) => + h( + Button, + { + type: 'link', + size: 'small', + onClick: () => onTaskClick(task), + }, + { default: () => task.name }, + ), + ); + }, + }, + }, + + { + field: 'id', + title: '流程编号', + minWidth: 320, + }, + { + field: 'operation', + title: '操作', + minWidth: 180, + align: 'center', + fixed: 'right', + cellRender: { + attrs: { + nameField: 'name', + nameTitle: '流程分类', + onClick: onActionClick, + }, + name: 'CellOperation', + options: [ + { + code: 'detail', + text: $t('ui.actionTitle.detail'), + show: hasAccessByCodes(['bpm:process-instance:query']), + }, + { + code: 'cancel', + text: $t('ui.actionTitle.cancel'), + show: (row: BpmProcessInstanceApi.ProcessInstanceVO) => { + return ( + row.status === BpmProcessInstanceStatus.RUNNING && + hasAccessByCodes(['bpm:process-instance:cancel']) + ); + }, + }, + ], + }, + }, + ]; +} diff --git a/apps/web-antd/src/views/bpm/processInstance/manager/index.vue b/apps/web-antd/src/views/bpm/processInstance/manager/index.vue index 9dd48e7cb..3b3ce81b9 100644 --- a/apps/web-antd/src/views/bpm/processInstance/manager/index.vue +++ b/apps/web-antd/src/views/bpm/processInstance/manager/index.vue @@ -1,31 +1,128 @@ diff --git a/packages/locales/src/langs/en-US/ui.json b/packages/locales/src/langs/en-US/ui.json index 8d91dc415..ee96986f5 100644 --- a/packages/locales/src/langs/en-US/ui.json +++ b/packages/locales/src/langs/en-US/ui.json @@ -1,131 +1,40 @@ { - "formRules": { - "required": "Please enter {0}", - "selectRequired": "Please select {0}", - "minLength": "{0} must be at least {1} characters", - "maxLength": "{0} can be at most {1} characters", - "length": "{0} must be {1} characters long", - "alreadyExists": "{0} `{1}` already exists", - "startWith": "{0} must start with `{1}`", - "invalidURL": "Please input a valid URL", - "mobile": "Please input a valid {0}" + "actionMessage": { + "deleteConfirm": "Are you sure to delete {0}?", + "deleteSuccess": "{0} deleted successfully", + "deleting": "Deleting {0} ...", + "downloadTemplateFail": "Download template failed", + "importFail": "Import failed", + "importSuccess": "Import succeeded", + "operationFailed": "Operation failed", + "operationSuccess": "Operation succeeded", + "updating": "Updating {0}..." }, "actionTitle": { - "edit": "Modify {0}", + "cancel": "Cancel {0}", "create": "Create {0}", "delete": "Delete {0}", "detail": "Detail {0}", - "view": "View {0}", + "edit": "Modify {0}", + "export": "Export", "import": "Import", - "export": "Export" - }, - "actionMessage": { - "deleteConfirm": "Are you sure to delete {0}?", - "deleting": "Deleting {0} ...", - "deleteSuccess": "{0} deleted successfully", - "operationSuccess": "Operation succeeded", - "operationFailed": "Operation failed", - "importSuccess": "Import succeeded", - "importFail": "Import failed", - "downloadTemplateFail": "Download template failed", - "updating": "Updating {0}..." - }, - "placeholder": { - "input": "Please enter", - "select": "Please select" + "view": "View {0}" }, "captcha": { - "title": "Please complete the security verification", - "sliderSuccessText": "Passed", - "sliderDefaultText": "Slider and drag", "alt": "Supports img tag src attribute value", + "clickInOrder": "Please click in order", + "confirm": "Confirm", + "confirmAriaLabel": "Confirm selection", + "pointAriaLabel": "Click point", + "refreshAriaLabel": "Refresh captcha", + "sliderDefaultText": "Slider and drag", "sliderRotateDefaultTip": "Click picture to refresh", "sliderRotateFailTip": "Validation failed", "sliderRotateSuccessTip": "Validation successful, time {0} seconds", - "refreshAriaLabel": "Refresh captcha", - "confirmAriaLabel": "Confirm selection", - "confirm": "Confirm", - "pointAriaLabel": "Click point", - "clickInOrder": "Please click in order" - }, - "iconPicker": { - "placeholder": "Select an icon", - "search": "Search icon..." - }, - "jsonViewer": { - "copy": "Copy", - "copied": "Copied" - }, - "fallback": { - "pageNotFound": "Oops! Page Not Found", - "pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for.", - "forbidden": "Oops! Access Denied", - "forbiddenDesc": "Sorry, but you don't have permission to access this page.", - "internalError": "Oops! Something Went Wrong", - "internalErrorDesc": "Sorry, but the server encountered an error.", - "offline": "Offline Page", - "offlineError": "Oops! Network Error", - "offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.", - "comingSoon": "Coming Soon", - "http": { - "requestTimeout": "The request timed out. Please try again later.", - "networkError": "A network error occurred. Please check your internet connection and try again.", - "badRequest": "Bad Request. Please check your input and try again.", - "unauthorized": "Unauthorized. Please log in to continue.", - "forbidden": "Forbidden. You do not have permission to access this resource.", - "notFound": "Not Found. The requested resource could not be found.", - "internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later." - } - }, - "widgets": { - "document": "Document", - "profile": "Profile", - "qa": "Q&A", - "setting": "Settings", - "logoutTip": "Do you want to logout?", - "viewAll": "View All Messages", - "notifications": "Notifications", - "markAllAsRead": "Make All as Read", - "clearNotifications": "Clear", - "checkUpdatesTitle": "New Version Available", - "checkUpdatesDescription": "Click to refresh and get the latest version", - "search": { - "title": "Search", - "searchNavigate": "Search Navigation", - "select": "Select", - "navigate": "Navigate", - "close": "Close", - "noResults": "No Search Results Found", - "noRecent": "No Search History", - "recent": "Search History" - }, - "lockScreen": { - "title": "Lock Screen", - "screenButton": "Locking", - "password": "Password", - "placeholder": "Please enter password", - "unlock": "Click to unlock", - "errorPasswordTip": "Password error, please re-enter", - "backToLogin": "Back to login", - "entry": "Enter the system" - } - }, - "upload": { - "upload": "Upload", - "imgUpload": "ImageUpload", - "accept": "Support {0} format", - "acceptUpload": "Only upload files in {0} format", - "maxSize": "A single file does not exceed {0}MB", - "maxSizeMultiple": "Only upload files up to {0}MB!", - "maxNumber": "Only upload up to {0} files", - "uploadSuccess": "Upload successfully" + "sliderSuccessText": "Passed", + "title": "Please complete the security verification" }, "cropper": { - "selectImage": "Select Image", - "uploadSuccess": "Uploaded success!", - "imageTooBig": "Image too big", - "modalTitle": "Avatar upload", - "okText": "Confirm and upload", "btn_reset": "Reset", "btn_rotate_left": "Counterclockwise rotation", "btn_rotate_right": "Clockwise rotation", @@ -133,6 +42,98 @@ "btn_scale_y": "Flip vertical", "btn_zoom_in": "Zoom in", "btn_zoom_out": "Zoom out", - "preview": "Preview" + "imageTooBig": "Image too big", + "modalTitle": "Avatar upload", + "okText": "Confirm and upload", + "preview": "Preview", + "selectImage": "Select Image", + "uploadSuccess": "Uploaded success!" + }, + "fallback": { + "comingSoon": "Coming Soon", + "forbidden": "Oops! Access Denied", + "forbiddenDesc": "Sorry, but you don't have permission to access this page.", + "http": { + "badRequest": "Bad Request. Please check your input and try again.", + "forbidden": "Forbidden. You do not have permission to access this resource.", + "internalServerError": "Internal Server Error. Something went wrong on our end. Please try again later.", + "networkError": "A network error occurred. Please check your internet connection and try again.", + "notFound": "Not Found. The requested resource could not be found.", + "requestTimeout": "The request timed out. Please try again later.", + "unauthorized": "Unauthorized. Please log in to continue." + }, + "internalError": "Oops! Something Went Wrong", + "internalErrorDesc": "Sorry, but the server encountered an error.", + "offline": "Offline Page", + "offlineError": "Oops! Network Error", + "offlineErrorDesc": "Sorry, can't connect to the internet. Check your connection.", + "pageNotFound": "Oops! Page Not Found", + "pageNotFoundDesc": "Sorry, we couldn't find the page you were looking for." + }, + "formRules": { + "alreadyExists": "{0} `{1}` already exists", + "invalidURL": "Please input a valid URL", + "length": "{0} must be {1} characters long", + "maxLength": "{0} can be at most {1} characters", + "minLength": "{0} must be at least {1} characters", + "mobile": "Please input a valid {0}", + "required": "Please enter {0}", + "selectRequired": "Please select {0}", + "startWith": "{0} must start with `{1}`" + }, + "iconPicker": { + "placeholder": "Select an icon", + "search": "Search icon..." + }, + "jsonViewer": { + "copied": "Copied", + "copy": "Copy" + }, + "placeholder": { + "input": "Please enter", + "select": "Please select" + }, + "upload": { + "accept": "Support {0} format", + "acceptUpload": "Only upload files in {0} format", + "imgUpload": "ImageUpload", + "maxNumber": "Only upload up to {0} files", + "maxSize": "A single file does not exceed {0}MB", + "maxSizeMultiple": "Only upload files up to {0}MB!", + "upload": "Upload", + "uploadSuccess": "Upload successfully" + }, + "widgets": { + "checkUpdatesDescription": "Click to refresh and get the latest version", + "checkUpdatesTitle": "New Version Available", + "clearNotifications": "Clear", + "document": "Document", + "lockScreen": { + "backToLogin": "Back to login", + "entry": "Enter the system", + "errorPasswordTip": "Password error, please re-enter", + "password": "Password", + "placeholder": "Please enter password", + "screenButton": "Locking", + "title": "Lock Screen", + "unlock": "Click to unlock" + }, + "logoutTip": "Do you want to logout?", + "markAllAsRead": "Make All as Read", + "notifications": "Notifications", + "profile": "Profile", + "qa": "Q&A", + "search": { + "close": "Close", + "navigate": "Navigate", + "noRecent": "No Search History", + "noResults": "No Search Results Found", + "recent": "Search History", + "searchNavigate": "Search Navigation", + "select": "Select", + "title": "Search" + }, + "setting": "Settings", + "viewAll": "View All Messages" } } diff --git a/packages/locales/src/langs/zh-CN/ui.json b/packages/locales/src/langs/zh-CN/ui.json index 652d43f75..2fe147bf2 100644 --- a/packages/locales/src/langs/zh-CN/ui.json +++ b/packages/locales/src/langs/zh-CN/ui.json @@ -1,131 +1,40 @@ { - "formRules": { - "required": "请输入{0}", - "selectRequired": "请选择{0}", - "minLength": "{0}至少{1}个字符", - "maxLength": "{0}最多{1}个字符", - "length": "{0}长度必须为{1}个字符", - "alreadyExists": "{0} `{1}` 已存在", - "startWith": "{0}必须以 {1} 开头", - "invalidURL": "请输入有效的链接", - "mobile": "请输入正确的{0}" + "actionMessage": { + "deleteConfirm": "确定删除 {0} 吗?", + "deleteSuccess": "{0} 删除成功", + "deleting": "正在删除 {0} ...", + "downloadTemplateFail": "下载模板失败", + "importFail": "导入失败", + "importSuccess": "导入成功", + "operationFailed": "操作失败", + "operationSuccess": "操作成功", + "updating": "正在更新 {0}..." }, "actionTitle": { - "edit": "修改{0}", + "cancel": "取消{0}", "create": "新增{0}", "delete": "删除{0}", "detail": "详情{0}", - "view": "查看{0}", + "edit": "修改{0}", + "export": "导出", "import": "导入", - "export": "导出" - }, - "actionMessage": { - "deleteConfirm": "确定删除 {0} 吗?", - "deleting": "正在删除 {0} ...", - "deleteSuccess": "{0} 删除成功", - "operationSuccess": "操作成功", - "operationFailed": "操作失败", - "importSuccess": "导入成功", - "importFail": "导入失败", - "downloadTemplateFail": "下载模板失败", - "updating": "正在更新 {0}..." - }, - "placeholder": { - "input": "请输入", - "select": "请选择" + "view": "查看{0}" }, "captcha": { - "title": "请完成安全验证", - "sliderSuccessText": "验证通过", + "alt": "支持img标签src属性值", + "clickInOrder": "请依次点击", + "confirm": "确认", + "confirmAriaLabel": "确认选择", + "pointAriaLabel": "点击点", + "refreshAriaLabel": "刷新验证码", "sliderDefaultText": "请按住滑块拖动", "sliderRotateDefaultTip": "点击图片可刷新", "sliderRotateFailTip": "验证失败", "sliderRotateSuccessTip": "验证成功,耗时{0}秒", - "alt": "支持img标签src属性值", - "refreshAriaLabel": "刷新验证码", - "confirmAriaLabel": "确认选择", - "confirm": "确认", - "pointAriaLabel": "点击点", - "clickInOrder": "请依次点击" - }, - "iconPicker": { - "placeholder": "选择一个图标", - "search": "搜索图标..." - }, - "jsonViewer": { - "copy": "复制", - "copied": "已复制" - }, - "fallback": { - "pageNotFound": "哎呀!未找到页面", - "pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。", - "forbidden": "哎呀!访问被拒绝", - "forbiddenDesc": "抱歉,您没有权限访问此页面。", - "internalError": "哎呀!出错了", - "internalErrorDesc": "抱歉,服务器遇到错误。", - "offline": "离线页面", - "offlineError": "哎呀!网络错误", - "offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。", - "comingSoon": "即将推出", - "http": { - "requestTimeout": "请求超时,请稍后再试。", - "networkError": "网络异常,请检查您的网络连接后重试。", - "badRequest": "请求错误。请检查您的输入并重试。", - "unauthorized": "登录认证过期,请重新登录后继续。", - "forbidden": "禁止访问, 您没有权限访问此资源。", - "notFound": "未找到, 请求的资源不存在。", - "internalServerError": "内部服务器错误,请稍后再试。" - } - }, - "widgets": { - "document": "文档", - "profile": "个人中心", - "qa": "问题 & 帮助", - "setting": "设置", - "logoutTip": "是否退出登录?", - "viewAll": "查看所有消息", - "notifications": "通知", - "markAllAsRead": "全部标记为已读", - "clearNotifications": "清空", - "checkUpdatesTitle": "新版本可用", - "checkUpdatesDescription": "点击刷新以获取最新版本", - "search": { - "title": "搜索", - "searchNavigate": "搜索导航菜单", - "select": "选择", - "navigate": "导航", - "close": "关闭", - "noResults": "未找到搜索结果", - "noRecent": "没有搜索历史", - "recent": "搜索历史" - }, - "lockScreen": { - "title": "锁定屏幕", - "screenButton": "锁定", - "password": "密码", - "placeholder": "请输入锁屏密码", - "unlock": "点击解锁", - "errorPasswordTip": "密码错误,请重新输入", - "backToLogin": "返回登录", - "entry": "进入系统" - } - }, - "upload": { - "upload": "上传", - "imgUpload": "图片上传", - "accept": "支持{0}格式", - "acceptUpload": "只能上传{0}格式文件", - "maxSize": "单个文件不超过{0}MB", - "maxSizeMultiple": "只能上传不超过{0}MB的文件!", - "maxNumber": "最多只能上传{0}个文件", - "uploadSuccess": "上传成功" + "sliderSuccessText": "验证通过", + "title": "请完成安全验证" }, "cropper": { - "selectImage": "选择图片", - "uploadSuccess": "上传成功", - "imageTooBig": "图片超限", - "modalTitle": "头像上传", - "okText": "确认并上传", "btn_reset": "重置", "btn_rotate_left": "逆时针旋转", "btn_rotate_right": "顺时针旋转", @@ -133,6 +42,98 @@ "btn_scale_y": "垂直翻转", "btn_zoom_in": "放大", "btn_zoom_out": "缩小", - "preview": "预览" + "imageTooBig": "图片超限", + "modalTitle": "头像上传", + "okText": "确认并上传", + "preview": "预览", + "selectImage": "选择图片", + "uploadSuccess": "上传成功" + }, + "fallback": { + "comingSoon": "即将推出", + "forbidden": "哎呀!访问被拒绝", + "forbiddenDesc": "抱歉,您没有权限访问此页面。", + "http": { + "badRequest": "请求错误。请检查您的输入并重试。", + "forbidden": "禁止访问, 您没有权限访问此资源。", + "internalServerError": "内部服务器错误,请稍后再试。", + "networkError": "网络异常,请检查您的网络连接后重试。", + "notFound": "未找到, 请求的资源不存在。", + "requestTimeout": "请求超时,请稍后再试。", + "unauthorized": "登录认证过期,请重新登录后继续。" + }, + "internalError": "哎呀!出错了", + "internalErrorDesc": "抱歉,服务器遇到错误。", + "offline": "离线页面", + "offlineError": "哎呀!网络错误", + "offlineErrorDesc": "抱歉,无法连接到互联网,请检查您的网络连接并重试。", + "pageNotFound": "哎呀!未找到页面", + "pageNotFoundDesc": "抱歉,我们无法找到您要找的页面。" + }, + "formRules": { + "alreadyExists": "{0} `{1}` 已存在", + "invalidURL": "请输入有效的链接", + "length": "{0}长度必须为{1}个字符", + "maxLength": "{0}最多{1}个字符", + "minLength": "{0}至少{1}个字符", + "mobile": "请输入正确的{0}", + "required": "请输入{0}", + "selectRequired": "请选择{0}", + "startWith": "{0}必须以 {1} 开头" + }, + "iconPicker": { + "placeholder": "选择一个图标", + "search": "搜索图标..." + }, + "jsonViewer": { + "copied": "已复制", + "copy": "复制" + }, + "placeholder": { + "input": "请输入", + "select": "请选择" + }, + "upload": { + "accept": "支持{0}格式", + "acceptUpload": "只能上传{0}格式文件", + "imgUpload": "图片上传", + "maxNumber": "最多只能上传{0}个文件", + "maxSize": "单个文件不超过{0}MB", + "maxSizeMultiple": "只能上传不超过{0}MB的文件!", + "upload": "上传", + "uploadSuccess": "上传成功" + }, + "widgets": { + "checkUpdatesDescription": "点击刷新以获取最新版本", + "checkUpdatesTitle": "新版本可用", + "clearNotifications": "清空", + "document": "文档", + "lockScreen": { + "backToLogin": "返回登录", + "entry": "进入系统", + "errorPasswordTip": "密码错误,请重新输入", + "password": "密码", + "placeholder": "请输入锁屏密码", + "screenButton": "锁定", + "title": "锁定屏幕", + "unlock": "点击解锁" + }, + "logoutTip": "是否退出登录?", + "markAllAsRead": "全部标记为已读", + "notifications": "通知", + "profile": "个人中心", + "qa": "问题 & 帮助", + "search": { + "close": "关闭", + "navigate": "导航", + "noRecent": "没有搜索历史", + "noResults": "未找到搜索结果", + "recent": "搜索历史", + "searchNavigate": "搜索导航菜单", + "select": "选择", + "title": "搜索" + }, + "setting": "设置", + "viewAll": "查看所有消息" } }