提交 dc09de1e 作者: vben

feat: multi-language component

上级 e5f8ce3f
......@@ -14,6 +14,8 @@
### 🎫 Chores
- 更新 antdv 到`2.0.0-rc.2`
- 更新 vue 到`3.0.3`
- 更新 vite 到`1.0.0.rc10`
- 暂时删除 `@vueuse/core`.等稳定后在集成。目前不太稳定。
## 2.0.0-rc.11 (2020-11-18)
......
......@@ -35,7 +35,7 @@
"qrcode": "^1.4.4",
"sortablejs": "^1.12.0",
"vditor": "^3.6.6",
"vue": "^3.0.2",
"vue": "^3.0.3",
"vue-i18n": "^9.0.0-beta.8",
"vue-router": "^4.0.0-rc.5",
"vuex": "^4.0.0-rc.1",
......@@ -63,7 +63,7 @@
"@types/zxcvbn": "^4.4.0",
"@typescript-eslint/eslint-plugin": "^4.8.2",
"@typescript-eslint/parser": "^4.8.2",
"@vue/compiler-sfc": "^3.0.2",
"@vue/compiler-sfc": "^3.0.3",
"@vuedx/typecheck": "^0.2.4-0",
"@vuedx/typescript-plugin-vue": "^0.2.4-0",
"autoprefixer": "^9.8.6",
......@@ -96,7 +96,7 @@
"tasksfile": "^5.1.1",
"ts-node": "^9.0.0",
"typescript": "^4.1.2",
"vite": "^1.0.0-rc.9",
"vite": "^1.0.0-rc.10",
"vite-plugin-html": "^1.0.0-beta.2",
"vite-plugin-mock": "^1.0.6",
"vite-plugin-purge-icons": "^0.4.5",
......
import './index.less';
import type { DrawerInstance, DrawerProps } from './types';
import { defineComponent, ref, computed, watchEffect, watch, unref, nextTick, toRaw } from 'vue';
......@@ -13,8 +15,7 @@ import { getSlot } from '/@/utils/helper/tsxHelper';
import { isFunction, isNumber } from '/@/utils/is';
import { buildUUID } from '/@/utils/uuid';
import { deepMerge } from '/@/utils';
import './index.less';
import { useI18n } from '/@/hooks/web/useI18n';
const prefixCls = 'basic-drawer';
export default defineComponent({
......@@ -27,6 +28,8 @@ export default defineComponent({
const visibleRef = ref(false);
const propsRef = ref<Partial<DrawerProps> | null>(null);
const { t } = useI18n('component.drawer');
const getMergeProps = computed((): any => {
return deepMerge(toRaw(props), unref(propsRef));
});
......@@ -208,7 +211,7 @@ export default defineComponent({
>
<FullLoading
absolute
tip="加载中..."
tip={t('loadingText')}
class={[!unref(getProps).loading ? 'hidden' : '']}
/>
{getSlot(slots, 'default')}
......
import type { PropType } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.drawer');
export const footerProps = {
confirmLoading: Boolean as PropType<boolean>,
/**
......@@ -11,7 +15,7 @@ export const footerProps = {
cancelButtonProps: Object as PropType<any>,
cancelText: {
type: String as PropType<string>,
default: '关闭',
default: t('cancelText'),
},
/**
* @description: Show confirmation button
......@@ -23,7 +27,7 @@ export const footerProps = {
okButtonProps: Object as PropType<any>,
okText: {
type: String as PropType<string>,
default: '确认',
default: t('okText'),
},
okType: {
type: String as PropType<string>,
......
<template>
<BasicModal v-bind="$attrs" title="导出数据" @ok="handleOk" @register="registerModal">
<BasicModal
v-bind="$attrs"
:title="t('exportModalTitle')"
@ok="handleOk"
@register="registerModal"
>
<BasicForm
:labelWidth="100"
:schemas="schemas"
......@@ -9,22 +14,26 @@
</BasicModal>
</template>
<script lang="ts">
import type { ExportModalResult } from './types';
import { defineComponent } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
import { ExportModalResult } from './types';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.excel');
const schemas: FormSchema[] = [
{
field: 'filename',
component: 'Input',
label: '文件名',
label: t('fileName'),
rules: [{ required: true }],
},
{
field: 'bookType',
component: 'Select',
label: '文件类型',
label: t('fileType'),
defaultValue: 'xlsx',
rules: [{ required: true }],
componentProps: {
......@@ -76,6 +85,7 @@
handleOk,
registerForm,
registerModal,
t,
};
},
});
......
......@@ -79,7 +79,7 @@
/* DO SOMETHING WITH workbook HERE */
const excelData = getExcelData(workbook);
emit('success', excelData);
resolve();
resolve('');
} catch (error) {
reject(error);
} finally {
......
......@@ -6,6 +6,9 @@ import Button from '/@/components/Button/index.vue';
import { BasicArrow } from '/@/components/Basic/index';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.form');
export default defineComponent({
name: 'BasicFormAction',
......@@ -55,14 +58,14 @@ export default defineComponent({
setup(props, { slots, emit }) {
const getResetBtnOptionsRef = computed(() => {
return {
text: '重置',
text: t('resetButton'),
...props.resetButtonOptions,
};
});
const getSubmitBtnOptionsRef = computed(() => {
return {
text: '查询',
text: t('submitButton'),
// htmlType: 'submit',
...props.submitButtonOptions,
};
......@@ -108,7 +111,7 @@ export default defineComponent({
<Button type="default" class="mr-2" onClick={toggleAdvanced}>
{() => (
<>
{isAdvanced ? '收起' : '展开'}
{isAdvanced ? t('putAway') : t('unfold')}
<BasicArrow expand={!isAdvanced} />
</>
)}
......
import type { ComponentType } from './types/index';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.form');
/**
* @description: 生成placeholder
*/
export function createPlaceholderMessage(component: ComponentType) {
if (component.includes('Input') || component.includes('Complete')) {
return '请输入';
return t('input');
}
if (component.includes('Picker')) {
return '请选择';
return t('choose');
}
if (
component.includes('Select') ||
......@@ -18,7 +21,7 @@ export function createPlaceholderMessage(component: ComponentType) {
component.includes('Switch')
) {
// return `请选择${label}`;
return '请选择';
return t('choose');
}
return '';
}
......
<template>
<section class="menu-search-input" @Click="handleClick" :class="searchClass">
<a-input-search
placeholder="菜单搜索"
:placeholder="t('search')"
class="menu-search-input__search"
allowClear
@change="handleChange"
......@@ -12,9 +12,9 @@
import type { PropType } from 'vue';
import { defineComponent, computed } from 'vue';
import { ThemeEnum } from '/@/enums/appEnum';
// hook
import { useDebounce } from '/@/hooks/core/useDebounce';
import { useI18n } from '/@/hooks/web/useI18n';
//
export default defineComponent({
name: 'BasicMenuSearchInput',
......@@ -29,6 +29,8 @@
},
},
setup(props, { emit }) {
const { t } = useI18n('component.menu');
const [debounceEmitChange] = useDebounce(emitChange, 200);
function emitChange(value?: string): void {
......@@ -52,7 +54,7 @@
return cls;
});
return { handleClick, searchClass, handleChange };
return { handleClick, searchClass, handleChange, t };
},
});
</script>
......
import { ComputedRef } from 'vue';
import { ThemeEnum } from '/@/enums/appEnum';
import { MenuModeEnum } from '/@/enums/menuEnum';
export interface MenuState {
// 默认选中的列表
defaultSelectedKeys: string[];
......
import type { PropType } from 'vue';
import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.modal');
export const modalProps = {
visible: Boolean as PropType<boolean>,
// open drag
......@@ -13,11 +17,11 @@ export const modalProps = {
},
cancelText: {
type: String as PropType<string>,
default: '关闭',
default: t('cancelText'),
},
okText: {
type: String as PropType<string>,
default: '确认',
default: t('okText'),
},
closeFunc: Function as PropType<() => Promise<boolean>>,
};
......
......@@ -4,27 +4,27 @@
<Tooltip placement="top" v-if="getSetting.redo">
<template #title>
<span>刷新</span>
<span>{{ t('settingRedo') }}</span>
</template>
<RedoOutlined @click="redo" />
</Tooltip>
<Tooltip placement="top" v-if="getSetting.size">
<template #title>
<span>密度</span>
<span>{{ t('settingDens') }}</span>
</template>
<Dropdown placement="bottomCenter" :trigger="['click']">
<ColumnHeightOutlined />
<template #overlay>
<Menu @click="handleTitleClick" selectable v-model:selectedKeys="selectedKeysRef">
<MenuItem key="default">
<span>默认</span>
<span>{{ t('settingDensDefault') }}</span>
</MenuItem>
<MenuItem key="middle">
<span>中等</span>
<span>{{ t('settingDensMiddle') }}</span>
</MenuItem>
<MenuItem key="small">
<span>紧凑</span>
<span>{{ t('settingDensSmall') }}</span>
</MenuItem>
</Menu>
</template>
......@@ -33,7 +33,7 @@
<Tooltip placement="top" v-if="getSetting.setting">
<template #title>
<span>列设置</span>
<span>{{ t('settingColumn') }}</span>
</template>
<Popover
placement="bottomLeft"
......@@ -58,9 +58,9 @@
v-model:checked="checkAll"
@change="onCheckAllChange"
>
列展示
{{ t('settingColumnShow') }}
</Checkbox>
<a-button size="small" type="link" @click="reset">重置</a-button>
<a-button size="small" type="link" @click="reset"> {{ t('settingReset') }}</a-button>
</div>
</template>
<SettingOutlined />
......@@ -69,7 +69,7 @@
<Tooltip placement="top" v-if="getSetting.fullScreen">
<template #title>
<span>全屏</span>
<span>{{ t('settingFullScreen') }}</span>
</template>
<FullscreenOutlined @click="handleFullScreen" v-if="!isFullscreenRef" />
<FullscreenExitOutlined @click="handleFullScreen" v-else />
......@@ -90,6 +90,7 @@
import { useFullscreen } from '/@/hooks/web/useFullScreen';
import type { SizeType, TableSetting } from '../types/table';
import { useI18n } from '/@/hooks/web/useI18n';
interface Options {
label: string;
......@@ -139,6 +140,8 @@
defaultCheckList: [],
});
const { t } = useI18n('component.table');
function init() {
let ret: Options[] = [];
table.getColumns({ ignoreIndex: true, ignoreAction: true }).forEach((item) => {
......@@ -217,6 +220,7 @@
reset,
getSetting,
...toRefs(state),
t,
};
},
});
......
......@@ -4,7 +4,9 @@ import { unref, ComputedRef, Ref, computed, watchEffect, ref, toRaw } from 'vue'
import { isBoolean, isArray, isObject } from '/@/utils/is';
import { PAGE_SIZE } from '../const';
import { useProps } from './useProps';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.table');
export function useColumns(
refProps: ComputedRef<BasicTableProps>,
getPaginationRef: ComputedRef<false | PaginationProps>
......@@ -42,7 +44,7 @@ export function useColumns(
columns.unshift({
flag: 'INDEX',
width: 50,
title: '序号',
title: t('index'),
align: 'center',
customRender: ({ index }) => {
const getPagination = unref(getPaginationRef);
......
......@@ -8,6 +8,9 @@ import { isBoolean } from '/@/utils/is';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS } from '../const';
import { useProps } from './useProps';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.table');
export function usePagination(refProps: ComputedRef<BasicTableProps>) {
const configRef = ref<PaginationProps>({});
const { propsRef } = useProps(refProps);
......@@ -22,7 +25,7 @@ export function usePagination(refProps: ComputedRef<BasicTableProps>) {
pageSize: PAGE_SIZE,
size: 'small',
defaultPageSize: PAGE_SIZE,
showTotal: (total) => `共 ${total} 条数据`,
showTotal: (total) => t('total', { total }),
showSizeChanger: true,
pageSizeOptions: PAGE_SIZE_OPTIONS,
itemRender: ({ page, type, originalElement }) => {
......
......@@ -13,7 +13,7 @@ const lineHeight = function (tinymce: any) {
t.ui.registry.addMenuButton('lineheight', {
icon: 'lineheight',
tooltip: '设置行高',
tooltip: 'Line Height',
// fetch: function (callback: Fn) {
// var dom = t.dom;
// var blocks = t.selection.getSelectedBlocks();
......
......@@ -2,11 +2,11 @@
<div>
<a-button-group>
<a-button type="primary" @click="openUploadModal" preIcon="ant-design:cloud-upload-outlined">
上传
{{ t('upload') }}
</a-button>
<Tooltip placement="bottom" v-if="showPreview">
<template #title>
已上传
{{ t('uploaded') }}
<template v-if="fileListRef.length">{{ fileListRef.length }}</template>
</template>
<a-button @click="openPreviewModal">
......@@ -39,12 +39,14 @@
import { uploadContainerProps } from './props';
import { omit } from 'lodash-es';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'BasicUpload',
components: { UploadModal, UploadPreviewModal, Icon, Tooltip },
props: uploadContainerProps,
setup(props, { emit, attrs }) {
const { t } = useI18n('component.upload');
// 上传modal
const [registerUploadModal, { openModal: openUploadModal }] = useModal();
......@@ -94,6 +96,7 @@
fileListRef,
showPreview,
bindValue,
t,
};
},
});
......
<template>
<BasicModal
width="800px"
title="上传"
okText="保存"
:title="t('upload')"
:okText="t('save')"
v-bind="$attrs"
@register="register"
@ok="handleOk"
......@@ -31,7 +31,7 @@
:before-upload="beforeUpload"
class="upload-modal-toolbar__btn"
>
<a-button type="primary"> 选择文件 </a-button>
<a-button type="primary"> {{ t('choose') }} </a-button>
</Upload>
</div>
<FileList :dataSource="fileListRef" :columns="columns" :actionColumn="actionColumn" />
......@@ -57,11 +57,15 @@
import { isFunction } from '/@/utils/is';
import { warn } from '/@/utils/log';
import FileList from './FileList';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
components: { BasicModal, Upload, Alert, FileList },
props: basicProps,
setup(props, { emit }) {
// 是否正在上传
const { t } = useI18n('component.upload');
const isUploadingRef = ref(false);
const fileListRef = ref<FileItem[]>([]);
const state = reactive<{ fileList: FileItem[] }>({
......@@ -100,7 +104,11 @@
const someError = fileListRef.value.some(
(item) => item.status === UploadResultStatus.ERROR
);
return isUploadingRef.value ? '上传中' : someError ? '重新上传失败文件' : '开始上传';
return isUploadingRef.value
? t('uploading')
: someError
? t('reUploadFailed')
: t('startUpload');
});
// 上传前校验
......@@ -111,13 +119,13 @@
// 设置最大值,则判断
if (maxSize && file.size / 1024 / 1024 >= maxSize) {
createMessage.error(`只能上传不超过${maxSize}MB的文件!`);
createMessage.error(t('maxSizeMultiple', [maxSize]));
return false;
}
// 设置类型,则判断
if (accept.length > 0 && !checkFileType(file, accept)) {
createMessage.error!(`只能上传${accept.join(',')}格式文件`);
createMessage.error!(t('acceptUpload', [accept.join(',')]));
return false;
}
const commonItem = {
......@@ -198,7 +206,7 @@
async function handleStartUpload() {
const { maxNumber } = props;
if (fileListRef.value.length > maxNumber) {
return createMessage.warning(`最多只能上传${maxNumber}个文件`);
return createMessage.warning(t('maxNumber', [maxNumber]));
}
try {
isUploadingRef.value = true;
......@@ -225,10 +233,10 @@
const { maxNumber } = props;
if (fileListRef.value.length > maxNumber) {
return createMessage.warning(`最多只能上传${maxNumber}个文件`);
return createMessage.warning(t('maxNumber', [maxNumber]));
}
if (isUploadingRef.value) {
return createMessage.warning('请等待文件上传后,保存');
return createMessage.warning(t('saveWarn'));
}
const fileList: string[] = [];
......@@ -240,7 +248,7 @@
}
// 存在一个上传成功的即可保存
if (fileList.length <= 0) {
return createMessage.warning('没有上传成功的文件,无法保存');
return createMessage.warning(t('saveError'));
}
fileListRef.value = [];
closeModal();
......@@ -253,7 +261,7 @@
fileListRef.value = [];
return true;
} else {
createMessage.warning('请等待文件上传结束后操作');
createMessage.warning(t('uploadWait'));
return false;
}
}
......@@ -285,6 +293,7 @@
handleCloseFunc,
getIsSelectFile,
getUploadBtnText,
t,
};
},
});
......
<template>
<BasicModal
width="800px"
title="预览"
:title="t('preview')"
wrapClassName="upload-preview-modal"
v-bind="$attrs"
@register="register"
......@@ -23,11 +23,15 @@
import { downloadByUrl } from '/@/utils/file/download';
import { createPreviewColumns, createPreviewActionColumn } from './data';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
components: { BasicModal, FileList },
props: previewProps,
setup(props, { emit }) {
const [register, { closeModal }] = useModalInner();
const { t } = useI18n('component.upload');
const fileListRef = ref<PreviewFileItem[]>([]);
watch(
() => props.value,
......@@ -74,6 +78,7 @@
}
return {
t,
register,
closeModal,
fileListRef,
......
......@@ -6,12 +6,15 @@ import { Progress, Tag } from 'ant-design-vue';
import TableAction from '/@/components/Table/src/components/TableAction';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.upload');
// 文件上传列表
export function createTableColumns(): BasicColumn[] {
return [
{
dataIndex: 'thumbUrl',
title: '图例',
title: t('legend'),
width: 100,
customRender: ({ record }) => {
const { thumbUrl, type } = (record as FileItem) || {};
......@@ -20,7 +23,7 @@ export function createTableColumns(): BasicColumn[] {
},
{
dataIndex: 'name',
title: '文件名',
title: t('fileName'),
align: 'left',
customRender: ({ text, record }) => {
const { percent, status: uploadStatus } = (record as FileItem) || {};
......@@ -44,7 +47,7 @@ export function createTableColumns(): BasicColumn[] {
},
{
dataIndex: 'size',
title: '文件大小',
title: t('fileSize'),
width: 100,
customRender: ({ text = 0 }) => {
return text && (text / 1024).toFixed(2) + 'KB';
......@@ -57,15 +60,15 @@ export function createTableColumns(): BasicColumn[] {
// },
{
dataIndex: 'status',
title: '状态',
title: t('fileStatue'),
width: 100,
customRender: ({ text }) => {
if (text === UploadResultStatus.SUCCESS) {
return <Tag color="green">{() => '上传成功'}</Tag>;
return <Tag color="green">{() => t('uploadSuccess')}</Tag>;
} else if (text === UploadResultStatus.ERROR) {
return <Tag color="red">{() => '上传失败'}</Tag>;
return <Tag color="red">{() => t('uploadError')}</Tag>;
} else if (text === UploadResultStatus.UPLOADING) {
return <Tag color="blue">{() => '上传中'}</Tag>;
return <Tag color="blue">{() => t('uploading')}</Tag>;
}
return text;
......@@ -76,20 +79,20 @@ export function createTableColumns(): BasicColumn[] {
export function createActionColumn(handleRemove: Function, handlePreview: Function): BasicColumn {
return {
width: 120,
title: '操作',
title: t('operating'),
dataIndex: 'action',
fixed: false,
customRender: ({ record }) => {
const actions: ActionItem[] = [
{
label: '删除',
label: t('del'),
color: 'error',
onClick: handleRemove.bind(null, record),
},
];
if (checkImgType(record)) {
actions.unshift({
label: '预览',
label: t('preview'),
onClick: handlePreview.bind(null, record),
});
}
......@@ -102,7 +105,7 @@ export function createPreviewColumns(): BasicColumn[] {
return [
{
dataIndex: 'url',
title: '图例',
title: t('legend'),
width: 100,
customRender: ({ record }) => {
const { url, type } = (record as PreviewFileItem) || {};
......@@ -113,7 +116,7 @@ export function createPreviewColumns(): BasicColumn[] {
},
{
dataIndex: 'name',
title: '文件名',
title: t('fileName'),
align: 'left',
},
];
......@@ -130,7 +133,7 @@ export function createPreviewActionColumn({
}): BasicColumn {
return {
width: 160,
title: '操作',
title: t('operating'),
dataIndex: 'action',
fixed: false,
customRender: ({ record }) => {
......@@ -138,18 +141,18 @@ export function createPreviewActionColumn({
const actions: ActionItem[] = [
{
label: '删除',
label: t('del'),
color: 'error',
onClick: handleRemove.bind(null, record),
},
{
label: '下载',
label: t('download'),
onClick: handleDownload.bind(null, record),
},
];
if (isImgTypeByName(url)) {
actions.unshift({
label: '预览',
label: t('preview'),
onClick: handlePreview.bind(null, record),
});
}
......
import { Ref, unref, computed } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.upload');
export function useUploadType({
acceptRef,
// uploadTypeRef,
......@@ -37,17 +38,17 @@ export function useUploadType({
const accept = unref(acceptRef);
if (accept.length > 0) {
helpTexts.push(`支持${accept.join(',')}格式`);
helpTexts.push(t('accept', [accept.join(',')]));
}
const maxSize = unref(maxSizeRef);
if (maxSize) {
helpTexts.push(`单个文件不超过${maxSize}MB`);
helpTexts.push(t('maxSize', [maxSize]));
}
const maxNumber = unref(maxNumberRef);
if (maxNumber && maxNumber !== Infinity) {
helpTexts.push(`最多只能上传${maxNumber}个文件`);
helpTexts.push(t('maxNumber', [maxNumber]));
}
return helpTexts.join(',');
});
......
import './ImgRotate.less';
import type { MoveData, DragVerifyActionType } from './types';
import { defineComponent, computed, unref, reactive, watch, ref, getCurrentInstance } from 'vue';
......@@ -8,7 +10,8 @@ import BasicDragVerify from './DragVerify';
import { hackCss } from '/@/utils/domUtils';
import { rotateProps } from './props';
import './ImgRotate.less';
import { useI18n } from '/@/hooks/web/useI18n';
export default defineComponent({
name: 'ImgRotateDargVerify',
inheritAttrs: false,
......@@ -27,6 +30,7 @@ export default defineComponent({
endTime: 0,
draged: false,
});
const { t } = useI18n('component.verify');
watch(
() => state.isPassing,
......@@ -142,11 +146,11 @@ export default defineComponent({
/>
{state.showTip && (
<span class={[`ir-dv-img__tip`, state.isPassing ? 'success' : 'error']}>
{state.isPassing ? `校验成功,耗时${time.toFixed(1)}秒!` : '验证失败!'}
{state.isPassing ? t('time', { time: time.toFixed(1) }) : t('error')}
</span>
)}
{!state.showTip && !state.draged && (
<span class={[`ir-dv-img__tip`, 'normal']}>点击图片可刷新</span>
<span class={[`ir-dv-img__tip`, 'normal']}>t('redoTip')</span>
)}
</div>
<BasicDragVerify
......
<script lang="tsx">
import { defineComponent, ref, unref } from 'vue';
import { BasicModal } from '/@/components/Modal/index';
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { RotateDragVerify, DragVerifyActionType } from '/@/components/Verify/index';
export default defineComponent({
name: 'VerifyModal',
setup(_, { attrs, emit }) {
const dragRef = ref<DragVerifyActionType | null>(null);
function handleSuccess() {
useTimeoutFn(() => {
emit('success');
const dragEl = unref(dragRef);
if (dragEl) {
dragEl.resume();
}
}, 500);
}
return () => (
<BasicModal
{...attrs}
title="安全校验"
keyboard={false}
maskClosable={false}
canFullscreen={false}
footer={null}
wrapperFooterOffset={60}
destroyOnClose={true}
>
<RotateDragVerify
imgWidth={210}
ref={dragRef}
text="请拖动滑块将图片摆正"
{...attrs}
onSuccess={handleSuccess}
/>
</BasicModal>
);
},
});
</script>
import type { PropType } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
const { t } = useI18n('component.verify');
export const basicProps = {
value: {
type: Boolean as PropType<boolean>,
......@@ -13,11 +15,11 @@ export const basicProps = {
text: {
type: [String] as PropType<string>,
default: '请按住滑块拖动',
default: t('dragText'),
},
successText: {
type: [String] as PropType<string>,
default: '验证通过',
default: t('successText'),
},
height: {
type: [Number, String] as PropType<number | string>,
......
export default {
loadingText: 'Loading...',
cancelText: 'Close',
okText: 'Confirm',
};
export default {
exportModalTitle: 'Export data',
fileType: 'File type',
fileName: 'File name',
};
export default {
resetButton: 'Reset',
submitButton: 'Search',
putAway: 'Put away',
unfold: 'Unfold',
input: 'Please Input',
choose: 'Please Choose',
};
export default {
search: 'Menu search',
};
export default {
cancelText: 'Close',
okText: 'Confirm',
};
export default {
settingRedo: 'Refresh',
settingDens: 'Density',
settingDensDefault: 'Default',
settingDensMiddle: 'Middle',
settingDensSmall: 'Compact',
settingColumn: 'Column settings',
settingColumnShow: 'Column display',
settingReset: 'Reset',
settingFullScreen: 'Full Screen',
index: 'Index',
total: 'total of {total}',
};
export default {
save: 'Save',
upload: 'Upload',
uploaded: 'Uploaded',
operating: 'Operating',
del: 'Delete',
download: 'download',
saveWarn: 'Please wait for the file to upload and save!',
saveError: 'There is no file successfully uploaded and cannot be saved!',
preview: 'Preview',
choose: 'Select the file',
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',
legend: 'Legend',
fileName: 'File name',
fileSize: 'File size',
fileStatue: 'File status',
startUpload: 'Start upload',
uploadSuccess: 'Upload successfully',
uploadError: 'Upload failed',
uploading: 'Uploading',
uploadWait: 'Please wait for the file upload to finish',
reUploadFailed: 'Re-upload failed files',
};
export default {
error: 'verification failed!',
time: 'The verification is successful and it takes {time} seconds!',
redoTip: 'Click the picture to refresh',
dragText: 'Hold down the slider and drag',
successText: 'Verified',
};
export default {
loadingText: '加载中...',
cancelText: '关闭',
okText: '确认',
};
export default {
exportModalTitle: '导出数据',
fileType: '文件类型',
fileName: '文件名',
};
export default {
resetButton: '重置',
submitButton: '查询',
putAway: '收起',
unfold: '展开',
input: '请输入',
choose: '请选择',
};
export default {
search: '菜单搜索',
};
export default {
loadingText: '加载中...',
cancelText: '关闭',
okText: '确认',
};
export default {
settingRedo: '刷新',
settingDens: '密度',
settingDensDefault: '默认',
settingDensMiddle: '中等',
settingDensSmall: '紧凑',
settingColumn: '列设置',
settingColumnShow: '列展示',
settingReset: '重置',
settingFullScreen: '全屏',
index: '序号',
total: '共 {total} 条数据',
};
export default {
save: '保存',
upload: '上传',
uploaded: '已上传',
operating: '操作',
del: '删除',
download: '下载',
saveWarn: '请等待文件上传后,保存!',
saveError: '没有上传成功的文件,无法保存!',
preview: '预览',
choose: '选择文件',
accept: '支持{0}格式',
acceptUpload: '只能上传{0}格式文件',
maxSize: '单个文件不超过{0}MB',
maxSizeMultiple: '只能上传不超过{0}MB的文件!',
maxNumber: '最多只能上传{0}个文件',
legend: '图例',
fileName: '文件名',
fileSize: '文件大小',
fileStatue: '状态',
startUpload: '开始上传',
uploadSuccess: '上传成功',
uploadError: '上传失败',
uploading: '上传中',
uploadWait: '请等待文件上传结束后操作',
reUploadFailed: '重新上传失败文件',
};
export default {
error: '验证失败!',
time: '验证校验成功,耗时{time}秒!',
redoTip: '点击图片可刷新',
dragText: '请按住滑块拖动',
successText: '验证通过',
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论