Browse Source

fix(Upload): The file name is too long bug

main
xingyu 2 years ago
parent
commit
b385f335de
  1. 15
      src/components/Form/src/components/ApiTreeSelect.vue
  2. 2
      src/components/SimpleMenu/src/components/Menu.vue
  3. 28
      src/components/SimpleMenu/src/components/useSimpleMenuContext.ts
  4. 79
      src/components/Upload/src/FileList.vue
  5. 8
      src/components/Upload/src/UploadModal.vue
  6. 8
      src/components/Upload/src/UploadPreviewModal.vue
  7. 30
      src/components/Upload/src/data.tsx
  8. 15
      src/components/Upload/src/typing.ts
  9. 1
      src/locales/lang/en/component.json
  10. 1
      src/locales/lang/zh-CN/component.json

15
src/components/Form/src/components/ApiTreeSelect.vue

@ -13,6 +13,7 @@ const props = defineProps({
api: { type: Function as PropType<(arg?: Recordable) => Promise<Recordable>> },
params: { type: Object },
immediate: propTypes.bool.def(true),
async: propTypes.bool.def(false),
resultField: propTypes.string.def(''),
handleTree: propTypes.string.def(''),
parentId: propTypes.number.def(0),
@ -20,7 +21,7 @@ const props = defineProps({
parentFiled: propTypes.string.def('name'),
alwaysLoad: propTypes.bool.def(true),
})
const emit = defineEmits(['optionsChange', 'change'])
const emit = defineEmits(['optionsChange', 'change', 'load-data'])
const attrs = useAttrs()
const treeData = ref<Recordable[]>([])
@ -64,6 +65,16 @@ onMounted(() => {
props.immediate && fetch()
})
function onLoadData(treeNode) {
return new Promise((resolve: (value?: unknown) => void) => {
if (isArray(treeNode.children) && treeNode.children.length > 0) {
resolve()
return
}
emit('load-data', { treeData, treeNode, resolve })
})
}
async function fetch() {
const { api } = props
if (!api || !isFunction(api))
@ -102,7 +113,7 @@ async function fetch() {
</script>
<template>
<TreeSelect v-bind="getAttrs" @change="handleChange">
<TreeSelect v-bind="getAttrs" :load-data="async ? onLoadData : undefined" @change="handleChange">
<template v-for="item in Object.keys($slots)" #[item]="data">
<slot :name="item" v-bind="data || {}" />
</template>

2
src/components/SimpleMenu/src/components/Menu.vue

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { computed, getCurrentInstance, nextTick, onMounted, provide, ref, watch, watchEffect } from 'vue'
import type { SubMenuProvider } from './types'
import { createSimpleRootMenuContext, type MenuEmitterEvents } from './useSimpleMenuContext'
import { type MenuEmitterEvents, createSimpleRootMenuContext } from './useSimpleMenuContext'
import { useDesign } from '@/hooks/web/useDesign'
import { propTypes } from '@/utils/propTypes'
import { mitt } from '@/utils/mitt'

28
src/components/SimpleMenu/src/components/useSimpleMenuContext.ts

@ -1,22 +1,22 @@
import type { InjectionKey, Ref, ComponentInternalInstance } from 'vue'
import type { ComponentInternalInstance, InjectionKey, Ref } from 'vue'
import type { Emitter } from '@/utils/mitt'
import { createContext, useContext } from '@/hooks/core/useContext'
export type MenuEmitterEvents = {
export interface MenuEmitterEvents {
'on-update-opened':
| (string | number)[]
| {
opend: boolean;
parent?: ComponentInternalInstance | null;
uidList: number[];
};
'on-menu-item-select': string | number;
| (string | number)[]
| {
opend: boolean
parent?: ComponentInternalInstance | null
uidList: number[]
}
'on-menu-item-select': string | number
'open-name-change': {
name: string | number;
opened: boolean;
};
'on-update-active-name:submenu': number[];
};
name: string | number
opened: boolean
}
'on-update-active-name:submenu': number[]
}
export interface SimpleRootMenuContextProps {
rootMenuEmitter: Emitter<MenuEmitterEvents>

79
src/components/Upload/src/FileList.vue

@ -22,47 +22,52 @@ export default defineComponent({
const { columns, actionColumn, dataSource } = props
const columnList = [...columns, actionColumn]
return (
<table class="file-table">
<colgroup>
{columnList.map((item) => {
const { width = 0, dataIndex } = item
const style: CSSProperties = {
width: `${width}px`,
minWidth: `${width}px`,
}
return <col style={width ? style : {}} key={dataIndex} />
})}
</colgroup>
<thead>
<tr class="file-table-tr">
// x scrollbar
<div class="overflow-x-auto">
<table class="file-table">
<colgroup>
{columnList.map((item) => {
const { title = '', align = 'center', dataIndex } = item
const { width = 0, dataIndex } = item
const style: CSSProperties = {
width: `${width}px`,
minWidth: `${width}px`,
}
return <col style={width ? style : {}} key={dataIndex} />
})}
</colgroup>
<thead>
<tr class="file-table-tr">
{columnList.map((item) => {
const { title = '', align = 'center', dataIndex } = item
return (
<th class={['file-table-th', align]} key={dataIndex}>
{title}
</th>
)
})}
</tr>
</thead>
<tbody>
{dataSource.map((record = {}, index) => {
return (
<th class={['file-table-th', align]} key={dataIndex}>
{title}
</th>
<tr class="file-table-tr" key={`${index + record.name || ''}`}>
{columnList.map((item) => {
const { dataIndex = '', customRender, align = 'center' } = item
const render = customRender && isFunction(customRender)
return (
<td class={['file-table-td break-all', align]} key={dataIndex}>
{render
? customRender?.({ text: record[dataIndex], record })
: record[dataIndex]}
</td>
)
})}
</tr>
)
})}
</tr>
</thead>
<tbody>
{dataSource.map((record = {}, index) => {
return (
<tr class="file-table-tr" key={`${index + record.name || ''}`}>
{columnList.map((item) => {
const { dataIndex = '', customRender, align = 'center' } = item
const render = customRender && isFunction(customRender)
return (
<td class={['file-table-td', align]} key={dataIndex}>
{render ? customRender?.({ text: record[dataIndex], record }) : record[dataIndex]}
</td>
)
})}
</tr>
)
})}
</tbody>
</table>
</tbody>
</table>
</div>
)
}
},

8
src/components/Upload/src/UploadModal.vue

@ -109,14 +109,6 @@ function handleRemove(record: FileItem) {
emit('delete', record)
}
//
// function handlePreview(record: FileItem) {
// const { thumbUrl = '' } = record;
// createImgPreview({
// imageList: [thumbUrl],
// });
// }
async function uploadApiByItem(item: FileItem) {
const { api } = props
if (!api || !isFunction(api))

8
src/components/Upload/src/UploadPreviewModal.vue

@ -47,14 +47,6 @@ function handleRemove(record: PreviewFileItem) {
}
}
// //
// function handlePreview(record: PreviewFileItem) {
// const { url = '' } = record;
// createImgPreview({
// imageList: [url],
// });
// }
//
function handleDownload(record: PreviewFileItem) {
const { url = '' } = record

30
src/components/Upload/src/data.tsx

@ -1,10 +1,7 @@
import { Progress, Tag } from 'ant-design-vue'
import type { FileItem, PreviewFileItem } from './typing'
import type { FileBasicColumn, FileItem, PreviewFileItem } from './typing'
import { UploadResultStatus } from './typing'
import {
// checkImgType,
isImgTypeByName,
} from './helper'
import { isImgTypeByName } from './helper'
import ThumbUrl from './ThumbUrl.vue'
import type { ActionItem, BasicColumn } from '@/components/Table'
import TableAction from '@/components/Table/src/components/TableAction.vue'
@ -13,7 +10,7 @@ import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
// 文件上传列表
export function createTableColumns(): BasicColumn[] {
export function createTableColumns(): FileBasicColumn[] {
return [
{
dataIndex: 'thumbUrl',
@ -39,12 +36,12 @@ export function createTableColumns(): BasicColumn[] {
status = 'success'
return (
<span>
<p class="mb-1 truncate" title={text}>
<div>
<p class="mb-1 max-w-70 truncate" title={text}>
{text}
</p>
<Progress percent={percent} size="small" status={status} />
</span>
</div>
)
},
},
@ -56,11 +53,6 @@ export function createTableColumns(): BasicColumn[] {
return text && `${(text / 1024).toFixed(2)}KB`
},
},
// {
// dataIndex: 'type',
// title: '文件类型',
// width: 100,
// },
{
dataIndex: 'status',
title: t('component.upload.fileStatue'),
@ -73,12 +65,12 @@ export function createTableColumns(): BasicColumn[] {
else if (text === UploadResultStatus.UPLOADING)
return <Tag color="blue">{() => t('component.upload.uploading')}</Tag>
return text
return text || t('component.upload.pending')
},
},
]
}
export function createActionColumn(handleRemove: Fn): BasicColumn {
export function createActionColumn(handleRemove: Fn): FileBasicColumn {
return {
width: 120,
title: t('component.upload.operating'),
@ -92,12 +84,6 @@ export function createActionColumn(handleRemove: Fn): BasicColumn {
onClick: handleRemove.bind(null, record),
},
]
// if (checkImgType(record)) {
// actions.unshift({
// label: t('component.upload.preview'),
// onClick: handlePreview.bind(null, record),
// });
// }
return <TableAction actions={actions} outside={true} />
},
}

15
src/components/Upload/src/typing.ts

@ -1,3 +1,4 @@
import type { BasicColumn } from '../../Table'
import type { UploadApiResult } from '@/api/base/model/uploadModel'
export enum UploadResultStatus {
@ -24,7 +25,7 @@ export interface PreviewFileItem {
type: string
}
export interface FileBasicColumn {
export interface FileBasicColumn extends Omit<BasicColumn, 'customRender'> {
/**
* Renderer of the table cell. The return value should be a VNode, or an object for colSpan/rowSpan config
* @type Function | ScopedSlot
@ -35,21 +36,9 @@ export interface FileBasicColumn {
* @type any (string | slot)
*/
title: string
/**
* Width of this column
* @type string | number
*/
width?: number
/**
* Display field of the data record, could be set like a.b.c
* @type string
*/
dataIndex: string
/**
* specify how content is aligned
* @default 'left'
* @type string
*/
align?: 'left' | 'right' | 'center'
}

1
src/locales/lang/en/component.json

@ -108,6 +108,7 @@
"maxSize": "A single file does not exceed {0}MB ",
"maxSizeMultiple": "Only upload files up to {0}MB!",
"operating": "Operating",
"pending": "Pendig",
"preview": "Preview",
"reUploadFailed": "Re-upload failed files",
"save": "Save",

1
src/locales/lang/zh-CN/component.json

@ -108,6 +108,7 @@
"maxSize": "单个文件不超过{0}MB",
"maxSizeMultiple": "只能上传不超过{0}MB的文件!",
"operating": "操作",
"pending": "待上传",
"preview": "预览",
"reUploadFailed": "重新上传失败文件",
"save": "保存",