mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-27 15:41:32 +08:00
feat: multi-language component
This commit is contained in:
@@ -1,3 +1,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')}
|
||||
|
@@ -1,4 +1,8 @@
|
||||
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>,
|
||||
|
@@ -1,5 +1,10 @@
|
||||
<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} />
|
||||
</>
|
||||
)}
|
||||
|
@@ -1,14 +1,17 @@
|
||||
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 '';
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<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>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import { ComputedRef } from 'vue';
|
||||
import { ThemeEnum } from '/@/enums/appEnum';
|
||||
import { MenuModeEnum } from '/@/enums/menuEnum';
|
||||
export interface MenuState {
|
||||
// 默认选中的列表
|
||||
defaultSelectedKeys: string[];
|
||||
|
@@ -1,5 +1,9 @@
|
||||
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,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<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,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<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),
|
||||
});
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
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(',');
|
||||
});
|
||||
|
@@ -1,3 +1,5 @@
|
||||
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
|
||||
|
@@ -1,44 +0,0 @@
|
||||
<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>
|
@@ -1,5 +1,7 @@
|
||||
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>,
|
||||
|
5
src/locales/lang/en/component/drawer.ts
Normal file
5
src/locales/lang/en/component/drawer.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
loadingText: 'Loading...',
|
||||
cancelText: 'Close',
|
||||
okText: 'Confirm',
|
||||
};
|
5
src/locales/lang/en/component/excel.ts
Normal file
5
src/locales/lang/en/component/excel.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
exportModalTitle: 'Export data',
|
||||
fileType: 'File type',
|
||||
fileName: 'File name',
|
||||
};
|
9
src/locales/lang/en/component/form.ts
Normal file
9
src/locales/lang/en/component/form.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
resetButton: 'Reset',
|
||||
submitButton: 'Search',
|
||||
putAway: 'Put away',
|
||||
unfold: 'Unfold',
|
||||
|
||||
input: 'Please Input',
|
||||
choose: 'Please Choose',
|
||||
};
|
3
src/locales/lang/en/component/menu.ts
Normal file
3
src/locales/lang/en/component/menu.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
search: 'Menu search',
|
||||
};
|
4
src/locales/lang/en/component/modal.ts
Normal file
4
src/locales/lang/en/component/modal.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
cancelText: 'Close',
|
||||
okText: 'Confirm',
|
||||
};
|
15
src/locales/lang/en/component/table.ts
Normal file
15
src/locales/lang/en/component/table.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
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}',
|
||||
};
|
32
src/locales/lang/en/component/upload.ts
Normal file
32
src/locales/lang/en/component/upload.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
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',
|
||||
};
|
9
src/locales/lang/en/component/verify.ts
Normal file
9
src/locales/lang/en/component/verify.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
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',
|
||||
};
|
5
src/locales/lang/zh_CN/component/drawer.ts
Normal file
5
src/locales/lang/zh_CN/component/drawer.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
loadingText: '加载中...',
|
||||
cancelText: '关闭',
|
||||
okText: '确认',
|
||||
};
|
5
src/locales/lang/zh_CN/component/excel.ts
Normal file
5
src/locales/lang/zh_CN/component/excel.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
exportModalTitle: '导出数据',
|
||||
fileType: '文件类型',
|
||||
fileName: '文件名',
|
||||
};
|
9
src/locales/lang/zh_CN/component/form.ts
Normal file
9
src/locales/lang/zh_CN/component/form.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
resetButton: '重置',
|
||||
submitButton: '查询',
|
||||
putAway: '收起',
|
||||
unfold: '展开',
|
||||
|
||||
input: '请输入',
|
||||
choose: '请选择',
|
||||
};
|
3
src/locales/lang/zh_CN/component/menu.ts
Normal file
3
src/locales/lang/zh_CN/component/menu.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
search: '菜单搜索',
|
||||
};
|
5
src/locales/lang/zh_CN/component/modal.ts
Normal file
5
src/locales/lang/zh_CN/component/modal.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
loadingText: '加载中...',
|
||||
cancelText: '关闭',
|
||||
okText: '确认',
|
||||
};
|
15
src/locales/lang/zh_CN/component/table.ts
Normal file
15
src/locales/lang/zh_CN/component/table.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export default {
|
||||
settingRedo: '刷新',
|
||||
settingDens: '密度',
|
||||
settingDensDefault: '默认',
|
||||
settingDensMiddle: '中等',
|
||||
settingDensSmall: '紧凑',
|
||||
settingColumn: '列设置',
|
||||
settingColumnShow: '列展示',
|
||||
settingReset: '重置',
|
||||
settingFullScreen: '全屏',
|
||||
|
||||
index: '序号',
|
||||
|
||||
total: '共 {total} 条数据',
|
||||
};
|
32
src/locales/lang/zh_CN/component/upload.ts
Normal file
32
src/locales/lang/zh_CN/component/upload.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
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: '重新上传失败文件',
|
||||
};
|
9
src/locales/lang/zh_CN/component/verify.ts
Normal file
9
src/locales/lang/zh_CN/component/verify.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
error: '验证失败!',
|
||||
time: '验证校验成功,耗时{time}秒!',
|
||||
|
||||
redoTip: '点击图片可刷新',
|
||||
|
||||
dragText: '请按住滑块拖动',
|
||||
successText: '验证通过',
|
||||
};
|
Reference in New Issue
Block a user