Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
ChenSun1
vue-vben-admin
提交
661db0c7
V
vue-vben-admin
项目概览
ChenSun1
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
661db0c7
编写于
11月 15, 2020
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
perf(upload): improve upload component
上级
a161bfa8
变更
38
隐藏空白更改
内联
并排
Showing
38 changed file
with
482 addition
and
172 deletion
+482
-172
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+5
-0
README.en-US.md
README.en-US.md
+1
-1
README.md
README.md
+1
-1
package.json
package.json
+6
-6
src/api/sys/model/uploadModel.ts
src/api/sys/model/uploadModel.ts
+0
-0
src/api/sys/upload.ts
src/api/sys/upload.ts
+0
-0
src/components/Drawer/src/props.ts
src/components/Drawer/src/props.ts
+1
-1
src/components/Form/src/BasicForm.vue
src/components/Form/src/BasicForm.vue
+0
-1
src/components/Icon/index.tsx
src/components/Icon/index.tsx
+1
-1
src/components/Modal/src/props.ts
src/components/Modal/src/props.ts
+4
-3
src/components/Qrcode/src/index.vue
src/components/Qrcode/src/index.vue
+1
-1
src/components/Table/src/BasicTable.vue
src/components/Table/src/BasicTable.vue
+1
-0
src/components/Table/src/hooks/useDataSource.ts
src/components/Table/src/hooks/useDataSource.ts
+1
-1
src/components/Table/src/props.ts
src/components/Table/src/props.ts
+4
-1
src/components/Table/src/style/index.less
src/components/Table/src/style/index.less
+6
-0
src/components/Table/src/types/table.ts
src/components/Table/src/types/table.ts
+2
-0
src/components/Upload/index.ts
src/components/Upload/index.ts
+1
-1
src/components/Upload/src/BasicUpload.vue
src/components/Upload/src/BasicUpload.vue
+99
-0
src/components/Upload/src/ThumnUrl.vue
src/components/Upload/src/ThumnUrl.vue
+4
-7
src/components/Upload/src/UploadModal.vue
src/components/Upload/src/UploadModal.vue
+117
-62
src/components/Upload/src/UploadPreviewModal.vue
src/components/Upload/src/UploadPreviewModal.vue
+13
-7
src/components/Upload/src/data.tsx
src/components/Upload/src/data.tsx
+12
-15
src/components/Upload/src/props.ts
src/components/Upload/src/props.ts
+21
-4
src/components/Upload/src/types.ts
src/components/Upload/src/types.ts
+1
-1
src/components/Upload/src/useUpload.ts
src/components/Upload/src/useUpload.ts
+3
-3
src/components/Upload/src/utils.ts
src/components/Upload/src/utils.ts
+5
-6
src/design/ant/btn.less
src/design/ant/btn.less
+5
-0
src/design/var/index.less
src/design/var/index.less
+1
-1
src/router/menus/modules/demo/comp.ts
src/router/menus/modules/demo/comp.ts
+10
-4
src/types/global.d.ts
src/types/global.d.ts
+6
-2
src/utils/file/download.ts
src/utils/file/download.ts
+21
-1
src/utils/file/stream.ts
src/utils/file/stream.ts
+26
-0
src/utils/http/axios/Axios.ts
src/utils/http/axios/Axios.ts
+0
-3
src/utils/http/axios/index.ts
src/utils/http/axios/index.ts
+1
-3
src/utils/http/axios/types.ts
src/utils/http/axios/types.ts
+1
-0
src/views/demo/comp/upload/index.vue
src/views/demo/comp/upload/index.vue
+48
-5
src/views/demo/feat/download/index.vue
src/views/demo/feat/download/index.vue
+24
-1
yarn.lock
yarn.lock
+29
-29
未找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
661db0c7
...
...
@@ -3,6 +3,11 @@
### ✨ Features
-
新增 base64 文件流下载
-
优化上传组件及示例
### 🎫 Chores
-
更新 antdv 到
`2.0.0-rc.1`
## 2.0.0-rc.10 (2020-11-13)
...
...
README.en-US.md
浏览文件 @
661db0c7
...
...
@@ -226,10 +226,10 @@ yarn clean:lib # Delete node_modules, supported window
- [x] Data import and export
- [x] Global error handling
- [x] Rich text component
- [x] Upload component
## Developing features
- [ ] Upload component
- [ ] Theme configuration
- [ ] Dark theme
- [ ] Build CDN
...
...
README.md
浏览文件 @
661db0c7
...
...
@@ -228,10 +228,10 @@ yarn clean:lib # 删除node_modules,兼容window系统
-
[x] 系统性能优化
-
[x] 全局错误处理
-
[x] 富文本组件
-
[x] 上传组件
## 正在开发的功能
-
[ ] 上传组件
-
[ ] 主题配置
-
[ ] 黑暗主题
-
[ ] 打包 CDN
...
...
package.json
浏览文件 @
661db0c7
...
...
@@ -22,8 +22,8 @@
},
"dependencies"
:
{
"
@iconify/iconify
"
:
"
^2.0.0-rc.2
"
,
"
@vueuse/core
"
:
"
^4.0.0-beta.4
0
"
,
"
ant-design-vue
"
:
"
^2.0.0-
beta.15
"
,
"
@vueuse/core
"
:
"
^4.0.0-beta.4
1
"
,
"
ant-design-vue
"
:
"
^2.0.0-
rc.1
"
,
"
apexcharts
"
:
"
3.22.0
"
,
"
axios
"
:
"
^0.21.0
"
,
"
echarts
"
:
"
^4.9.0
"
,
...
...
@@ -33,10 +33,10 @@
"
nprogress
"
:
"
^0.2.0
"
,
"
path-to-regexp
"
:
"
^6.2.0
"
,
"
qrcode
"
:
"
^1.4.4
"
,
"
vditor
"
:
"
^3.6.
0
"
,
"
vditor
"
:
"
^3.6.
2
"
,
"
vue
"
:
"
^3.0.2
"
,
"
vue-i18n
"
:
"
^9.0.0-beta.6
"
,
"
vue-router
"
:
"
^4.0.0-rc.
2
"
,
"
vue-router
"
:
"
^4.0.0-rc.
3
"
,
"
vuex
"
:
"
^4.0.0-rc.1
"
,
"
vuex-module-decorators
"
:
"
^1.0.1
"
,
"
xlsx
"
:
"
^0.16.8
"
,
...
...
@@ -45,11 +45,11 @@
"devDependencies"
:
{
"
@commitlint/cli
"
:
"
^11.0.0
"
,
"
@commitlint/config-conventional
"
:
"
^11.0.0
"
,
"
@iconify/json
"
:
"
^1.1.25
4
"
,
"
@iconify/json
"
:
"
^1.1.25
8
"
,
"
@ls-lint/ls-lint
"
:
"
^1.9.2
"
,
"
@purge-icons/generated
"
:
"
^0.4.1
"
,
"
@types/echarts
"
:
"
^4.9.0
"
,
"
@types/fs-extra
"
:
"
^9.0.
2
"
,
"
@types/fs-extra
"
:
"
^9.0.
4
"
,
"
@types/koa-static
"
:
"
^4.0.1
"
,
"
@types/lodash-es
"
:
"
^4.17.3
"
,
"
@types/mockjs
"
:
"
^1.0.3
"
,
...
...
src/api/
demo
/model/uploadModel.ts
→
src/api/
sys
/model/uploadModel.ts
浏览文件 @
661db0c7
文件已移动
src/api/
demo
/upload.ts
→
src/api/
sys
/upload.ts
浏览文件 @
661db0c7
文件已移动
src/components/Drawer/src/props.ts
浏览文件 @
661db0c7
...
...
@@ -24,7 +24,7 @@ export const footerProps = {
okButtonProps
:
Object
as
PropType
<
any
>
,
okText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
'
保存
'
,
default
:
'
确认
'
,
},
okType
:
{
type
:
String
as
PropType
<
string
>
,
...
...
src/components/Form/src/BasicForm.vue
浏览文件 @
661db0c7
...
...
@@ -44,7 +44,6 @@
import
{
useFormValues
}
from
'
./hooks/useFormValues
'
;
import
useAdvanced
from
'
./hooks/useAdvanced
'
;
import
{
useFormAction
}
from
'
./hooks/useFormAction
'
;
export
default
defineComponent
({
name
:
'
BasicForm
'
,
components
:
{
FormItem
,
Form
,
Row
,
FormAction
},
...
...
src/components/Icon/index.tsx
浏览文件 @
661db0c7
...
...
@@ -18,7 +18,7 @@ export default defineComponent({
// icon size
size
:
{
type
:
[
String
,
Number
]
as
PropType
<
string
|
number
>
,
default
:
1
4
,
default
:
1
6
,
},
prefix
:
{
type
:
String
as
PropType
<
string
>
,
...
...
src/components/Modal/src/props.ts
浏览文件 @
661db0c7
import
type
{
PropType
}
from
'
vue
'
;
import
{
ButtonProps
}
from
'
ant-design-vue/es/button/buttonTypes
'
;
export
const
modalProps
=
{
visible
:
Boolean
as
PropType
<
boolean
>
,
// open drag
...
...
@@ -16,7 +17,7 @@ export const modalProps = {
},
okText
:
{
type
:
String
as
PropType
<
string
>
,
default
:
'
保存
'
,
default
:
'
确认
'
,
},
closeFunc
:
Function
as
PropType
<
()
=>
Promise
<
boolean
>>
,
};
...
...
@@ -100,9 +101,9 @@ export const basicProps = Object.assign({}, modalProps, {
default
:
'
primary
'
,
},
okButtonProps
:
Object
as
PropType
<
any
>
,
okButtonProps
:
Object
as
PropType
<
ButtonProps
>
,
cancelButtonProps
:
Object
as
PropType
<
any
>
,
cancelButtonProps
:
Object
as
PropType
<
ButtonProps
>
,
title
:
{
type
:
String
as
PropType
<
string
>
,
...
...
src/components/Qrcode/src/index.vue
浏览文件 @
661db0c7
...
...
@@ -7,7 +7,7 @@
import
{
defineComponent
,
watchEffect
,
PropType
,
ref
,
unref
}
from
'
vue
'
;
import
{
toCanvas
,
QRCodeRenderersOptions
,
LogoType
}
from
'
./qrcodePlus
'
;
import
{
toDataURL
}
from
'
qrcode
'
;
import
{
downloadByUrl
}
from
'
/@/utils/file/
FileD
ownload
'
;
import
{
downloadByUrl
}
from
'
/@/utils/file/
d
ownload
'
;
export
default
defineComponent
({
name
:
'
QrCode
'
,
...
...
src/components/Table/src/BasicTable.vue
浏览文件 @
661db0c7
...
...
@@ -4,6 +4,7 @@
class=
"basic-table"
:class=
"
{
'table-form-container': getBindValues.useSearchForm,
inset: getBindValues.inset,
}"
>
<BasicForm
...
...
src/components/Table/src/hooks/useDataSource.ts
浏览文件 @
661db0c7
...
...
@@ -84,7 +84,7 @@ export function useDataSource(
const
{
api
,
searchInfo
,
fetchSetting
,
beforeFetch
,
afterFetch
,
useSearchForm
}
=
unref
(
propsRef
);
if
(
!
api
&&
!
isFunction
(
api
))
return
;
if
(
!
api
||
!
isFunction
(
api
))
return
;
try
{
loadingRef
.
value
=
true
;
const
{
pageField
,
sizeField
,
listField
,
totalField
}
=
fetchSetting
||
FETCH_SETTING
;
...
...
src/components/Table/src/props.ts
浏览文件 @
661db0c7
...
...
@@ -16,7 +16,10 @@ export const basicProps = {
tableSetting
:
{
type
:
Object
as
PropType
<
TableSetting
>
,
},
inset
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
sortFn
:
{
type
:
Function
as
PropType
<
(
sortInfo
:
SorterResult
)
=>
any
>
,
default
:
DEFAULT_SORT_FN
,
...
...
src/components/Table/src/style/index.less
浏览文件 @
661db0c7
...
...
@@ -49,6 +49,12 @@
}
}
&.inset {
.ant-table-wrapper {
padding: 0;
}
}
//
.ant-table {
border: none;
...
...
src/components/Table/src/types/table.ts
浏览文件 @
661db0c7
...
...
@@ -126,6 +126,8 @@ export interface TableSetting {
export
interface
BasicTableProps
<
T
=
any
>
{
// 自定义排序方法
sortFn
?:
(
sortInfo
:
SorterResult
)
=>
any
;
// 取消表格的默认padding
inset
?:
boolean
;
// 显示表格设置
showTableSetting
?:
boolean
;
tableSetting
?:
TableSetting
;
...
...
src/components/Upload/index.ts
浏览文件 @
661db0c7
export
{
default
as
UploadContainer
}
from
'
./src/UploadContainer
.vue
'
;
export
{
default
as
BasicUpload
}
from
'
./src/BasicUpload
.vue
'
;
// export * from './src/types';
src/components/Upload/src/
UploadContainer
.vue
→
src/components/Upload/src/
BasicUpload
.vue
浏览文件 @
661db0c7
<
template
>
<div>
<a-button-group>
<a-button
type=
"primary"
@
click=
"openUploadModal"
>
上传
</a-button>
<a-button
@
click=
"openPreviewModal"
>
<Icon
icon=
"ant-design:eye-outlined"
/>
<a-button
type=
"primary"
@
click=
"openUploadModal"
preIcon=
"ant-design:cloud-upload-outlined"
>
上传
</a-button>
<Tooltip
placement=
"bottom"
v-if=
"showPreview"
>
<template
#title
>
已上传
<template
v-if=
"fileListRef.length"
>
{{
fileListRef
.
length
}}
</
template
>
</template>
<a-button
@
click=
"openPreviewModal"
>
<Icon
icon=
"ant-design:eye-outlined"
/>
<
template
v-if=
"fileListRef.length && showPreviewNumber"
>
{{
fileListRef
.
length
}}
</
template
>
</a-button>
</Tooltip>
</a-button-group>
<UploadModal
v-bind=
"$props"
@
register=
"registerUploadModal"
@
change=
"handleChange"
/>
<UploadModal
v-bind=
"bindValue"
@
register=
"registerUploadModal"
@
change=
"handleChange"
/>
<UploadPreviewModal
:value=
"fileListRef"
@
register=
"registerPreviewModal"
@
change=
"handlePreviewChange"
@
list-
change=
"handlePreviewChange"
/>
</div>
</template>
<
script
lang=
"ts"
>
import
{
defineComponent
,
ref
,
watch
,
unref
}
from
'
vue
'
;
import
{
useModal
}
from
'
/@/components/Modal
'
;
import
{
defineComponent
,
ref
,
watch
,
unref
,
computed
}
from
'
vue
'
;
import
UploadModal
from
'
./UploadModal.vue
'
;
import
{
uploadContainerProps
}
from
'
./props
'
;
import
UploadPreviewModal
from
'
./UploadPreviewModal.vue
'
;
import
Icon
from
'
/@/components/Icon/index
'
;
import
Icon
from
'
/@/components/Icon
'
;
import
{
Tooltip
}
from
'
ant-design-vue
'
;
import
{
useModal
}
from
'
/@/components/Modal
'
;
import
{
uploadContainerProps
}
from
'
./props
'
;
import
{
omit
}
from
'
lodash-es
'
;
export
default
defineComponent
({
components
:
{
UploadModal
,
UploadPreviewModal
,
Icon
},
components
:
{
UploadModal
,
UploadPreviewModal
,
Icon
,
Tooltip
},
props
:
uploadContainerProps
,
setup
(
props
,
{
emit
})
{
setup
(
props
,
{
emit
,
attrs
})
{
// 上传modal
const
[
registerUploadModal
,
{
openModal
:
openUploadModal
}]
=
useModal
();
// 预览modal
const
[
registerPreviewModal
,
{
openModal
:
openPreviewModal
}]
=
useModal
();
const
fileListRef
=
ref
<
string
[]
>
([]);
const
showPreview
=
computed
(()
=>
{
const
{
emptyHidePreview
}
=
props
;
if
(
!
emptyHidePreview
)
return
true
;
return
emptyHidePreview
?
fileListRef
.
value
.
length
>
0
:
true
;
});
const
bindValue
=
computed
(()
=>
{
const
value
=
{
...
attrs
,
...
props
};
return
omit
(
value
,
'
onChange
'
);
});
watch
(
()
=>
props
.
value
,
(
value
)
=>
{
fileListRef
.
value
=
[...(
value
||
[])]
;
(
value
=
[]
)
=>
{
fileListRef
.
value
=
value
;
},
{
immediate
:
true
}
);
// 上传modal保存操作
function
handleChange
(
urls
:
string
[])
{
fileListRef
.
value
=
[...
unref
(
fileListRef
),
...(
urls
||
[])];
emit
(
'
change
'
,
fileListRef
.
value
);
}
// 预览modal保存操作
function
handlePreviewChange
(
urls
:
string
[])
{
fileListRef
.
value
=
[...(
urls
||
[])];
emit
(
'
change
'
,
fileListRef
.
value
);
}
return
{
registerUploadModal
,
openUploadModal
,
...
...
@@ -56,6 +91,8 @@
registerPreviewModal
,
openPreviewModal
,
fileListRef
,
showPreview
,
bindValue
,
};
},
});
...
...
src/components/Upload/src/ThumnUrl.vue
浏览文件 @
661db0c7
...
...
@@ -5,25 +5,22 @@
</span>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
defineComponent
,
PropType
}
from
'
vue
'
;
export
default
defineComponent
({
props
:
{
fileUrl
:
{
type
:
String
,
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
fileType
:
{
type
:
String
,
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
fileName
:
{
type
:
String
,
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
},
setup
()
{
return
{};
},
});
</
script
>
src/components/Upload/src/UploadModal.vue
浏览文件 @
661db0c7
<
template
>
<BasicModal
width=
"800px"
title=
"上传"
okText=
"保存"
v-bind=
"$attrs"
@
register=
"register"
@
ok=
"handleOk"
:closeFunc=
"handleCloseFunc"
:maskClosable=
"false"
width=
"800px"
title=
"上传组件"
:keyboard=
"false"
wrapClassName=
"upload-modal"
:okButtonProps=
"
{ disabled: isUploadingRef }
"
:okButtonProps=
"
getOkButtonProps
"
:cancelButtonProps=
"
{ disabled: isUploadingRef }"
>
<template
#centerdFooter
>
<a-button
@
click=
"handleStartUpload"
color=
"success"
:loading=
"isUploadingRef"
>
{{
isUploadingRef
?
'
上传中
'
:
'
开始上传
'
}}
<a-button
@
click=
"handleStartUpload"
color=
"success"
:disabled=
"!getIsSelectFile"
:loading=
"isUploadingRef"
>
{{
getUploadBtnText
}}
</a-button>
</
template
>
<Upload
:accept=
"getStringAccept"
:multiple=
"multiple"
:before-upload=
"beforeUpload"
>
<a-button
type=
"primary"
>
选择文件
</a-button>
<span
class=
"px-2"
>
{{ getHelpText }}
</span>
</Upload>
<BasicTable
@
register=
"registerTable"
:dataSource=
"fileListRef"
/>
<BasicTable
@
register=
"registerTable"
:dataSource=
"fileListRef"
>
<
template
#toolbar
>
<Upload
:accept=
"getStringAccept"
:multiple=
"multiple"
:before-upload=
"beforeUpload"
>
<a-button
type=
"primary"
>
选择文件
</a-button>
</Upload>
</
template
>
<
template
#tableTitle
>
<Alert
:message=
"getHelpText"
type=
"info"
banner
></Alert>
</
template
>
</BasicTable>
</BasicModal>
</template>
<
script
lang=
"ts"
>
import
{
defineComponent
,
reactive
,
ref
,
toRef
,
unref
}
from
'
vue
'
;
import
{
Upload
}
from
'
ant-design-vue
'
;
import
{
defineComponent
,
reactive
,
ref
,
toRef
s
,
unref
,
computed
}
from
'
vue
'
;
import
{
Upload
,
Alert
}
from
'
ant-design-vue
'
;
import
{
BasicModal
,
useModalInner
}
from
'
/@/components/Modal
'
;
import
{
BasicTable
,
useTable
}
from
'
/@/components/Table
'
;
// hooks
...
...
@@ -39,23 +52,56 @@
import
{
checkFileType
,
checkImgType
,
getBase64WithFile
}
from
'
./utils
'
;
import
{
buildUUID
}
from
'
/@/utils/uuid
'
;
import
{
createImgPreview
}
from
'
/@/components/Preview/index
'
;
import
{
uploadApi
}
from
'
/@/api/demo/upload
'
;
import
{
uploadApi
}
from
'
/@/api/sys/upload
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
warn
}
from
'
/@/utils/log
'
;
export
default
defineComponent
({
components
:
{
BasicModal
,
Upload
,
BasicTable
},
components
:
{
BasicModal
,
Upload
,
BasicTable
,
Alert
},
props
:
basicProps
,
setup
(
props
,
{
emit
})
{
// 是否正在上传
const
isUploadingRef
=
ref
(
false
);
const
fileListRef
=
ref
<
FileItem
[]
>
([]);
const
state
=
reactive
<
{
fileList
:
FileItem
[]
}
>
({
fileList
:
[],
});
const
[
register
,
{
closeModal
}]
=
useModalInner
();
const
{
accept
,
helpText
,
maxNumber
,
maxSize
}
=
toRefs
(
props
);
const
{
getAccept
,
getStringAccept
,
getHelpText
}
=
useUploadType
({
acceptRef
:
toRef
(
props
,
'
accept
'
)
,
helpTextRef
:
toRef
(
props
,
'
helpText
'
)
,
maxNumberRef
:
toRef
(
props
,
'
maxNumber
'
)
,
maxSizeRef
:
toRef
(
props
,
'
maxSize
'
)
,
acceptRef
:
accept
,
helpTextRef
:
helpText
,
maxNumberRef
:
maxNumber
,
maxSizeRef
:
maxSize
,
});
const
fileListRef
=
ref
<
FileItem
[]
>
([]);
const
state
=
reactive
<
{
fileList
:
FileItem
[]
}
>
({
fileList
:
[]
});
const
{
createMessage
}
=
useMessage
();
const
getIsSelectFile
=
computed
(()
=>
{
return
(
fileListRef
.
value
.
length
>
0
&&
!
fileListRef
.
value
.
every
((
item
)
=>
item
.
status
===
UploadResultStatus
.
SUCCESS
)
);
});
const
getOkButtonProps
=
computed
(()
=>
{
const
someSuccess
=
fileListRef
.
value
.
some
(
(
item
)
=>
item
.
status
===
UploadResultStatus
.
SUCCESS
);
return
{
disabled
:
isUploadingRef
.
value
||
fileListRef
.
value
.
length
===
0
||
!
someSuccess
,
};
});
const
getUploadBtnText
=
computed
(()
=>
{
const
someError
=
fileListRef
.
value
.
some
(
(
item
)
=>
item
.
status
===
UploadResultStatus
.
ERROR
);
return
isUploadingRef
.
value
?
'
上传中
'
:
someError
?
'
重新上传失败文件
'
:
'
开始上传
'
;
});
// 上传前校验
function
beforeUpload
(
file
:
File
)
{
const
{
size
,
name
}
=
file
;
...
...
@@ -73,6 +119,14 @@
createMessage
.
error
!
(
`只能上传
${
accept
.
join
(
'
,
'
)}
格式文件`
);
return
false
;
}
const
commonItem
=
{
uuid
:
buildUUID
(),
file
,
size
,
name
,
percent
:
0
,
type
:
name
.
split
(
'
.
'
).
pop
(),
};
// 生成图片缩略图
if
(
checkImgType
(
file
))
{
// beforeUpload,如果异步会调用自带上传方法
...
...
@@ -81,29 +135,13 @@
fileListRef
.
value
=
[
...
unref
(
fileListRef
),
{
uuid
:
buildUUID
(),
file
,
thumbUrl
,
size
,
name
,
percent
:
0
,
type
:
name
.
split
(
'
.
'
).
pop
(),
...
commonItem
,
},
];
});
}
else
{
fileListRef
.
value
=
[
...
unref
(
fileListRef
),
{
uuid
:
buildUUID
(),
file
,
size
,
name
,
percent
:
0
,
type
:
name
.
split
(
'
.
'
).
pop
(),
},
];
fileListRef
.
value
=
[...
unref
(
fileListRef
),
commonItem
];
}
return
false
;
}
...
...
@@ -112,6 +150,7 @@
const
index
=
fileListRef
.
value
.
findIndex
((
item
)
=>
item
.
uuid
===
record
.
uuid
);
index
!==
-
1
&&
fileListRef
.
value
.
splice
(
index
,
1
);
}
// 预览
function
handlePreview
(
record
:
FileItem
)
{
const
{
thumbUrl
=
''
}
=
record
;
...
...
@@ -119,19 +158,18 @@
imageList
:
[
thumbUrl
],
});
}
const
[
registerTable
]
=
useTable
({
columns
:
createTableColumns
(),
actionColumn
:
createActionColumn
(
handleRemove
,
handlePreview
),
pagination
:
false
,
});
// 是否正在上传
const
isUploadingRef
=
ref
(
false
);
async
function
uploadApiByItem
(
item
:
FileItem
)
{
const
{
api
}
=
props
;
if
(
!
api
||
!
isFunction
(
api
))
{
return
warn
(
'
upload api must exist and be a function
'
);
}
try
{
item
.
status
=
UploadResultStatus
.
UPLOADING
;
const
{
data
}
=
await
uploadApi
(
{
...(
props
.
uploadParams
||
{}),
file
:
item
.
file
,
},
function
onUploadProgress
(
progressEvent
:
ProgressEvent
)
{
...
...
@@ -154,32 +192,42 @@
};
}
}
// 点击开始上传
async
function
handleStartUpload
()
{
const
{
maxNumber
}
=
props
;
if
(
fileListRef
.
value
.
length
>
maxNumber
)
{
return
createMessage
.
warning
(
`最多只能上传
${
maxNumber
}
个文件`
);
}
try
{
isUploadingRef
.
value
=
true
;
// 只上传不是成功状态的
const
uploadFileList
=
fileListRef
.
value
.
filter
((
item
)
=>
item
.
status
!==
UploadResultStatus
.
SUCCESS
)
||
[];
const
data
=
await
Promise
.
all
(
u
nref
(
fileListRef
)
.
map
((
item
)
=>
{
u
ploadFileList
.
map
((
item
)
=>
{
return
uploadApiByItem
(
item
);
})
);
isUploadingRef
.
value
=
false
;
// 生产环境:抛出错误
const
errorList
=
data
.
filter
((
item
)
=>
!
item
.
success
);
if
(
errorList
.
length
>
0
)
{
throw
errorList
;
}
const
errorList
=
data
.
filter
((
item
:
any
)
=>
!
item
.
success
);
if
(
errorList
.
length
>
0
)
throw
errorList
;
}
catch
(
e
)
{
isUploadingRef
.
value
=
false
;
throw
e
;
}
}
// 点击保存
function
handleOk
()
{
// TODO: 没起作用:okButtonProps={{ disabled: state.isUploading }}
const
{
maxNumber
}
=
props
;
if
(
fileListRef
.
value
.
length
>
maxNumber
)
{
return
createMessage
.
warning
(
`最多只能上传
${
maxNumber
}
个文件`
);
}
if
(
isUploadingRef
.
value
)
{
createMessage
.
warning
(
'
请等待文件上传后,保存
'
);
return
;
return
createMessage
.
warning
(
'
请等待文件上传后,保存
'
);
}
const
fileList
:
string
[]
=
[];
...
...
@@ -189,18 +237,15 @@
fileList
.
push
(
responseData
.
url
);
}
}
// 存在一个上传成功的即可保存
if
(
fileList
.
length
<=
0
)
{
createMessage
.
warning
(
'
没有上传成功的文件,无法保存
'
);
return
;
return
createMessage
.
warning
(
'
没有上传成功的文件,无法保存
'
);
}
console
.
log
(
fileList
);
emit
(
'
change
'
,
fileList
);
fileListRef
.
value
=
[];
closeModal
();
emit
(
'
change
'
,
fileList
);
}
// 点击关闭:则所有操作不保存,包括上传的
function
handleCloseFunc
()
{
if
(
!
isUploadingRef
.
value
)
{
...
...
@@ -211,11 +256,22 @@
return
false
;
}
}
const
[
registerTable
]
=
useTable
({
columns
:
createTableColumns
(),
actionColumn
:
createActionColumn
(
handleRemove
,
handlePreview
),
pagination
:
false
,
inset
:
true
,
scroll
:
{
y
:
3000
,
},
});
return
{
register
,
closeModal
,
getHelpText
,
getStringAccept
,
getOkButtonProps
,
beforeUpload
,
registerTable
,
fileListRef
,
...
...
@@ -224,14 +280,13 @@
handleStartUpload
,
handleOk
,
handleCloseFunc
,
getIsSelectFile
,
getUploadBtnText
,
};
},
});
</
script
>
<
style
lang=
"less"
>
// /deep/ .ant-upload-list {
// display: none;
// }
.upload-modal {
.ant-upload-list {
display: none;
...
...
src/components/Upload/src/UploadPreviewModal.vue
浏览文件 @
661db0c7
<
template
>
<BasicModal
width=
"800px"
title=
"预览"
wrapClassName=
"upload-preview-modal"
v-bind=
"$attrs"
width=
"800px"
@
register=
"register"
title=
"预览"
:showOkBtn=
"false"
>
<BasicTable
@
register=
"registerTable"
:dataSource=
"fileListRef"
/>
...
...
@@ -12,17 +12,18 @@
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
watch
,
ref
,
unref
}
from
'
vue
'
;
import
{
BasicTable
,
useTable
}
from
'
/@/components/Table
'
;
import
{
createPreviewColumns
,
createPreviewActionColumn
}
from
'
./data
'
;
import
{
BasicModal
,
useModalInner
}
from
'
/@/components/Modal
'
;
import
{
pr
i
viewProps
}
from
'
./props
'
;
import
{
pr
e
viewProps
}
from
'
./props
'
;
import
{
PreviewFileItem
}
from
'
./types
'
;
import
{
createImgPreview
}
from
'
/@/components/Preview/index
'
;
import
{
downloadByUrl
}
from
'
/@/utils/file/
FileD
ownload
'
;
import
{
downloadByUrl
}
from
'
/@/utils/file/
d
ownload
'
;
import
{
createPreviewColumns
,
createPreviewActionColumn
}
from
'
./data
'
;
export
default
defineComponent
({
components
:
{
BasicModal
,
BasicTable
},
props
:
pr
i
viewProps
,
props
:
pr
e
viewProps
,
setup
(
props
,
{
emit
})
{
const
[
register
,
{
closeModal
}]
=
useModalInner
();
const
fileListRef
=
ref
<
PreviewFileItem
[]
>
([]);
...
...
@@ -43,17 +44,19 @@
},
{
immediate
:
true
}
);
// 删除
function
handleRemove
(
record
:
PreviewFileItem
)
{
const
index
=
fileListRef
.
value
.
findIndex
((
item
)
=>
item
.
url
===
record
.
url
);
if
(
index
!==
-
1
)
{
fileListRef
.
value
.
splice
(
index
,
1
);
emit
(
'
change
'
,
'
list-
change
'
,
fileListRef
.
value
.
map
((
item
)
=>
item
.
url
)
);
}
}
// 预览
function
handlePreview
(
record
:
PreviewFileItem
)
{
const
{
url
=
''
}
=
record
;
...
...
@@ -61,16 +64,19 @@
imageList
:
[
url
],
});
}
// 下载
function
handleDownload
(
record
:
PreviewFileItem
)
{
const
{
url
=
''
}
=
record
;
downloadByUrl
({
url
});
}
const
[
registerTable
]
=
useTable
({
columns
:
createPreviewColumns
(),
pagination
:
false
,
actionColumn
:
createPreviewActionColumn
({
handleRemove
,
handlePreview
,
handleDownload
}),
});
return
{
register
,
closeModal
,
...
...
src/components/Upload/src/data.tsx
浏览文件 @
661db0c7
// import { BasicColumn, TableAction, ActionItem } from '@/components/table';
import
{
checkImgType
,
isImgTypeByName
}
from
'
./utils
'
;
// import ThumnUrl from './ThumbUrl.vue';
import
{
Progress
}
from
'
ant-design-vue
'
;
import
{
Progress
,
Tag
}
from
'
ant-design-vue
'
;
import
{
FileItem
,
PreviewFileItem
,
UploadResultStatus
}
from
'
./types
'
;
// import { ElecArchivesSaveResult } from '@/api/biz/file/model/fileModel';
// import { quryFile } from '@/api/biz/file/file';
import
{
BasicColumn
,
ActionItem
,
TableAction
}
from
'
/@/components/Table/index
'
;
// 文件上传列表
...
...
@@ -16,8 +12,7 @@ export function createTableColumns(): BasicColumn[] {
width
:
100
,
customRender
:
({
record
})
=>
{
const
{
thumbUrl
,
type
}
=
(
record
as
FileItem
)
||
{};
return
<
span
>
{
thumbUrl
?
<
img
src
=
{
thumbUrl
}
style
=
{
{
width
:
'
50px
'
}
}
/>
:
type
}
</
span
>;
// return <ThumnUrl fileUrl={thumbUrl} fileType={type} fileName={type} />;
return
<
span
>
{
thumbUrl
?
<
img
style
=
{
{
maxWidth
:
'
60px
'
}
}
src
=
{
thumbUrl
}
/>
:
type
}
</
span
>;
},
},
{
...
...
@@ -26,7 +21,7 @@ export function createTableColumns(): BasicColumn[] {
align
:
'
left
'
,
customRender
:
({
text
,
record
})
=>
{
const
{
percent
,
status
:
uploadStatus
}
=
(
record
as
FileItem
)
||
{};
let
status
=
'
normal
'
;
let
status
:
'
normal
'
|
'
exception
'
|
'
active
'
|
'
success
'
=
'
normal
'
;
if
(
uploadStatus
===
UploadResultStatus
.
ERROR
)
{
status
=
'
exception
'
;
}
else
if
(
uploadStatus
===
UploadResultStatus
.
UPLOADING
)
{
...
...
@@ -63,11 +58,11 @@ export function createTableColumns(): BasicColumn[] {
width
:
100
,
customRender
:
({
text
})
=>
{
if
(
text
===
UploadResultStatus
.
SUCCESS
)
{
return
'
上传成功
'
;
return
<
Tag
color
=
"green"
>
{
()
=>
'
上传成功
'
}
</
Tag
>
;
}
else
if
(
text
===
UploadResultStatus
.
ERROR
)
{
return
'
上传失败
'
;
return
<
Tag
color
=
"red"
>
{
()
=>
'
上传失败
'
}
</
Tag
>
;
}
else
if
(
text
===
UploadResultStatus
.
UPLOADING
)
{
return
'
上传中
'
;
return
<
Tag
color
=
"blue"
>
{
()
=>
'
上传中
'
}
</
Tag
>
;
}
return
text
;
...
...
@@ -85,6 +80,7 @@ export function createActionColumn(handleRemove: Function, handlePreview: Functi
const
actions
:
ActionItem
[]
=
[
{
label
:
'
删除
'
,
color
:
'
error
'
,
onClick
:
handleRemove
.
bind
(
null
,
record
),
},
];
...
...
@@ -125,9 +121,9 @@ export function createPreviewActionColumn({
handlePreview
,
handleDownload
,
}:
{
handleRemove
:
F
unctio
n
;
handlePreview
:
F
unctio
n
;
handleDownload
:
F
unctio
n
;
handleRemove
:
Fn
;
handlePreview
:
Fn
;
handleDownload
:
Fn
;
}):
BasicColumn
{
return
{
width
:
160
,
...
...
@@ -135,11 +131,12 @@ export function createPreviewActionColumn({
dataIndex
:
'
action
'
,
fixed
:
false
,
customRender
:
({
record
})
=>
{
const
{
url
}
=
(
record
as
PreviewFileItem
)
||
{}
;
const
{
url
}
=
(
record
||
{})
as
PreviewFileItem
;
const
actions
:
ActionItem
[]
=
[
{
label
:
'
删除
'
,
color
:
'
error
'
,
onClick
:
handleRemove
.
bind
(
null
,
record
),
},
{
...
...
src/components/Upload/src/props.ts
浏览文件 @
661db0c7
...
...
@@ -10,10 +10,10 @@ export const basicProps = {
type
:
Number
as
PropType
<
number
>
,
default
:
2
,
},
// 最大数量的文件,
0
不限制
// 最大数量的文件,
Infinity
不限制
maxNumber
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
0
,
default
:
Infinity
,
},
// 根据后缀,或者其他
accept
:
{
...
...
@@ -21,9 +21,18 @@ export const basicProps = {
default
:
()
=>
[],
},
multiple
:
{
type
:
Boolean
,
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
uploadParams
:
{
type
:
Object
as
PropType
<
any
>
,
default
:
{},
},
api
:
{
type
:
Function
as
PropType
<
PromiseFn
>
,
default
:
null
,
required
:
true
,
},
};
export
const
uploadContainerProps
=
{
...
...
@@ -32,9 +41,17 @@ export const uploadContainerProps = {
default
:
()
=>
[],
},
...
basicProps
,
showPreviewNumber
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
emptyHidePreview
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
};
export
const
pr
i
viewProps
=
{
export
const
pr
e
viewProps
=
{
value
:
{
type
:
Array
as
PropType
<
string
[]
>
,
default
:
()
=>
[],
...
...
src/components/Upload/src/types.ts
浏览文件 @
661db0c7
import
{
UploadApiResult
}
from
'
/@/api/
demo
/model/uploadModel
'
;
import
{
UploadApiResult
}
from
'
/@/api/
sys
/model/uploadModel
'
;
export
enum
UploadResultStatus
{
SUCCESS
=
'
success
'
,
...
...
src/components/Upload/src/useUpload.ts
浏览文件 @
661db0c7
...
...
@@ -42,12 +42,12 @@ export function useUploadType({
const
maxSize
=
unref
(
maxSizeRef
);
if
(
maxSize
)
{
helpTexts
.
push
(
`不超过
${
maxSize
}
MB`
);
helpTexts
.
push
(
`
单个文件
不超过
${
maxSize
}
MB`
);
}
const
maxNumber
=
unref
(
maxNumberRef
);
if
(
maxNumber
)
{
helpTexts
.
push
(
`最多
可选择
${
maxNumber
}
个文件`
);
if
(
maxNumber
&&
maxNumber
!==
Infinity
)
{
helpTexts
.
push
(
`最多
只能上传
${
maxNumber
}
个文件`
);
}
return
helpTexts
.
join
(
'
,
'
);
});
...
...
src/components/Upload/src/utils.ts
浏览文件 @
661db0c7
...
...
@@ -3,18 +3,17 @@ export function checkFileType(file: File, accepts: string[]) {
// const reg = /\.(jpg|jpeg|png|gif|txt|doc|docx|xls|xlsx|xml)$/i;
const
reg
=
new
RegExp
(
'
\\
.(
'
+
newTypes
+
'
)$
'
,
'
i
'
);
if
(
!
reg
.
test
(
file
.
name
))
{
return
false
;
}
else
{
return
true
;
}
return
reg
.
test
(
file
.
name
);
}
export
function
checkImgType
(
file
:
File
)
{
return
/
\.(
jpg|jpeg|png|gif
)
$/i
.
test
(
file
.
name
);
return
isImgTypeByName
(
file
.
name
);
}
export
function
isImgTypeByName
(
name
:
string
)
{
return
/
\.(
jpg|jpeg|png|gif
)
$/i
.
test
(
name
);
}
export
function
getBase64WithFile
(
file
:
File
)
{
return
new
Promise
<
{
result
:
string
;
...
...
src/design/ant/btn.less
浏览文件 @
661db0c7
...
...
@@ -6,6 +6,11 @@
// &.ant-btn-primary:not(.ant-btn-link) {
// box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.12), 0 2px 4px 0 rgba(0, 0, 0, 0.08) !important;
// }
// &-group {
// .ant-btn:not(:first-child) {
// bottom: 1px;
// }
// }
&-primary {
color: @white;
...
...
src/design/var/index.less
浏览文件 @
661db0c7
...
...
@@ -16,4 +16,4 @@
@page-loading-z-index: 10000;
// left-menu
@app-menu-item-height: 4
6
px;
@app-menu-item-height: 4
4
px;
src/router/menus/modules/demo/comp.ts
浏览文件 @
661db0c7
...
...
@@ -4,6 +4,9 @@ const menu: MenuModule = {
menu
:
{
name
:
'
组件
'
,
path
:
'
/comp
'
,
tag
:
{
dot
:
true
,
},
children
:
[
{
path
:
'
basic
'
,
...
...
@@ -38,10 +41,13 @@ const menu: MenuModule = {
path
:
'
strength-meter
'
,
name
:
'
密码强度组件
'
,
},
// {
// path: 'upload',
// name: '上传组件',
// },
{
path
:
'
upload
'
,
name
:
'
上传组件
'
,
tag
:
{
content
:
'
new
'
,
},
},
{
path
:
'
scroll
'
,
name
:
'
滚动组件
'
,
...
...
src/types/global.d.ts
浏览文件 @
661db0c7
declare
interface
Fn
<
T
=
any
>
{
(...
arg
:
T
[]):
T
;
declare
interface
Fn
<
T
=
any
,
R
=
T
>
{
(...
arg
:
T
[]):
R
;
}
declare
interface
PromiseFn
<
T
=
any
,
R
=
T
>
{
(...
arg
:
T
[]):
Promise
<
R
>
;
}
// 任意对象
...
...
src/utils/file/
FileD
ownload.ts
→
src/utils/file/
d
ownload.ts
浏览文件 @
661db0c7
import
{
dataURLtoBlob
}
from
'
./stream
'
;
import
{
dataURLtoBlob
,
urlToBase64
}
from
'
./stream
'
;
/**
* Download online pictures
* @param url
* @param filename
* @param mime
* @param bom
*/
export
function
downloadByOnlineUrl
(
url
:
string
,
filename
:
string
,
mime
?:
string
,
bom
?:
BlobPart
)
{
urlToBase64
(
url
).
then
((
base64
)
=>
{
downloadByBase64
(
base64
,
filename
,
mime
,
bom
);
});
}
/**
* Download pictures based on base64
* @param buf
* @param filename
* @param mime
* @param bom
*/
export
function
downloadByBase64
(
buf
:
string
,
filename
:
string
,
mime
?:
string
,
bom
?:
BlobPart
)
{
const
base64Buf
=
dataURLtoBlob
(
buf
);
downloadByData
(
base64Buf
,
filename
,
mime
,
bom
);
...
...
src/utils/file/stream.ts
浏览文件 @
661db0c7
...
...
@@ -13,3 +13,29 @@ export function dataURLtoBlob(base64Buf: string): Blob {
}
return
new
Blob
([
u8arr
],
{
type
:
mime
});
}
/**
* img url to base64
* @param url
*/
export
function
urlToBase64
(
url
:
string
,
mineType
?:
string
):
Promise
<
string
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
let
canvas
=
document
.
createElement
(
'
CANVAS
'
)
as
Nullable
<
HTMLCanvasElement
>
;
const
ctx
=
canvas
!
.
getContext
(
'
2d
'
);
const
img
=
new
Image
();
img
.
crossOrigin
=
''
;
img
.
onload
=
function
()
{
if
(
!
canvas
||
!
ctx
)
{
return
reject
();
}
canvas
.
height
=
img
.
height
;
canvas
.
width
=
img
.
width
;
ctx
.
drawImage
(
img
,
0
,
0
);
const
dataURL
=
canvas
.
toDataURL
(
mineType
||
'
image/png
'
);
canvas
=
null
;
resolve
(
dataURL
);
};
img
.
src
=
url
;
});
}
src/utils/http/axios/Axios.ts
浏览文件 @
661db0c7
...
...
@@ -118,11 +118,8 @@ export class VAxios {
Object
.
keys
(
params
.
data
).
forEach
((
key
)
=>
{
if
(
!
params
.
data
)
return
;
const
value
=
params
.
data
[
key
];
// support key-value array data
if
(
Array
.
isArray
(
value
))
{
value
.
forEach
((
item
)
=>
{
// { list: [ 11, 22 ] }
// formData.append('list[]', 11);
formData
.
append
(
`
${
key
}
[]`
,
item
);
});
return
;
...
...
src/utils/http/axios/index.ts
浏览文件 @
661db0c7
...
...
@@ -160,20 +160,18 @@ const transform: AxiosTransform = {
try
{
if
(
code
===
'
ECONNABORTED
'
&&
message
.
indexOf
(
'
timeout
'
)
!==
-
1
)
{
createMessage
.
error
(
'
接口请求超时,请刷新页面重试!
'
);
return
;
}
if
(
err
&&
err
.
includes
(
'
Network Error
'
))
{
createErrorModal
({
title
:
'
网络异常
'
,
content
:
'
请检查您的网络连接是否正常!
'
,
});
return
;
}
}
catch
(
error
)
{
throw
new
Error
(
error
);
}
checkStatus
(
error
.
response
&&
error
.
response
.
status
,
msg
);
return
error
;
return
Promise
.
reject
(
error
)
;
},
};
...
...
src/utils/http/axios/types.ts
浏览文件 @
661db0c7
...
...
@@ -38,4 +38,5 @@ export interface UploadFileParams {
file
:
File
|
Blob
;
// 文件名
filename
?:
string
;
[
key
:
string
]:
any
;
}
src/views/demo/comp/upload/index.vue
浏览文件 @
661db0c7
<
template
>
<div
class=
"p-4"
>
<UploadContainer
:maxSize=
"5"
/>
<a-alert
message=
"基础示例"
class=
"my-5"
></a-alert>
<BasicUpload
:maxSize=
"20"
:maxNumber=
"10"
@
change=
"handleChange"
:api=
"uploadApi"
/>
<a-alert
message=
"嵌入表单,加入表单校验"
class=
"my-5"
></a-alert>
<BasicForm
@
register=
"register"
/>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
UploadContainer
}
from
'
/@/components/Upload/index
'
;
import
{
defineComponent
,
h
}
from
'
vue
'
;
import
{
BasicUpload
}
from
'
/@/components/Upload
'
;
import
{
useMessage
}
from
'
/@/hooks/web/useMessage
'
;
import
{
BasicForm
,
FormSchema
,
useForm
}
from
'
/@/components/Form/index
'
;
import
{
uploadApi
}
from
'
/@/api/sys/upload
'
;
// import { Alert } from 'ant-design-vue';
const
schemas
:
FormSchema
[]
=
[
{
field
:
'
field1
'
,
component
:
'
Input
'
,
label
:
'
字段1
'
,
colProps
:
{
span
:
8
,
},
rules
:
[{
required
:
true
,
type
:
'
array
'
,
message
:
'
请选择上传文件
'
}],
render
:
({
model
,
field
})
=>
{
return
h
(
BasicUpload
,
{
value
:
model
[
field
],
api
:
uploadApi
,
onChange
:
(
val
:
string
[])
=>
{
model
[
field
]
=
val
;
},
});
},
},
];
export
default
defineComponent
({
components
:
{
UploadContainer
},
components
:
{
BasicUpload
,
BasicForm
},
setup
()
{
return
{};
const
{
createMessage
}
=
useMessage
();
const
[
register
]
=
useForm
({
labelWidth
:
120
,
schemas
,
actionColOptions
:
{
span
:
16
,
},
});
return
{
handleChange
:
(
list
:
string
[])
=>
{
createMessage
.
info
(
`已上传文件
${
JSON
.
stringify
(
list
)}
`
);
},
uploadApi
,
register
,
};
},
});
</
script
>
src/views/demo/feat/download/index.vue
浏览文件 @
661db0c7
...
...
@@ -8,11 +8,21 @@
<a-alert
message=
"base64流下载"
/>
<a-button
type=
"primary"
class=
"my-4"
@
click=
"handleDownloadByBase64"
>
base64流下载
</a-button>
<a-alert
message=
"图片Url下载,如果有跨域问题,需要处理图片跨域"
/>
<a-button
type=
"primary"
class=
"my-4"
@
click=
"handleDownloadByOnlineUrl"
>
图片Url下载
</a-button>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
downloadByUrl
,
downloadByData
,
downloadByBase64
}
from
'
/@/utils/file/FileDownload
'
;
import
{
downloadByUrl
,
downloadByData
,
downloadByBase64
,
downloadByOnlineUrl
,
}
from
'
/@/utils/file/download
'
;
import
imgBase64
from
'
./imgBase64
'
;
export
default
defineComponent
({
setup
()
{
...
...
@@ -24,15 +34,28 @@
url
:
'
https://codeload.github.com/anncwb/vue-vben-admin-doc/zip/master
'
,
target
:
'
_self
'
,
});
downloadByUrl
({
url
:
'
https://vebn.oss-cn-beijing.aliyuncs.com/vben/logo.png
'
,
target
:
'
_self
'
,
});
}
function
handleDownloadByBase64
()
{
downloadByBase64
(
imgBase64
,
'
logo.png
'
);
}
function
handleDownloadByOnlineUrl
()
{
downloadByOnlineUrl
(
'
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5944817f47b8408e9f1442ece49d68ca~tplv-k3u1fbpfcp-watermark.image
'
,
'
logo.png
'
);
}
return
{
handleDownloadByUrl
,
handleDownByData
,
handleDownloadByBase64
,
handleDownloadByOnlineUrl
,
};
},
});
...
...
yarn.lock
浏览文件 @
661db0c7
...
...
@@ -1050,10 +1050,10 @@
resolved "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.0.0-rc.2.tgz#c4a95ddc06ca9b9496df03604e66fdefb39f4c4b"
integrity sha512-BybEHU5/I9EQ0CcwKAqmreZ2bMnAXrqLCTptAc6vPetHMbrXdZfejP5mt57e/8PNSt/qE7BHniU5PCYA+PGIHw==
"@iconify/json@^1.1.25
4
":
version "1.1.25
6
"
resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.25
6.tgz#0f138d421ab12faca2fdd49aaf4fbc0122db08e3
"
integrity sha512-
CeLKbKL3lvq8afhR3LEyaBqXZDC52fgU0Ij3LbTRCwPUsumLNzhXA7MzN/f0JDYfXm9LShkfpgMcm00wQaANgg
==
"@iconify/json@^1.1.25
8
":
version "1.1.25
8
"
resolved "https://registry.npmjs.org/@iconify/json/-/json-1.1.25
8.tgz#392064ae8fd4c6d542c21bb4d0d57d5860f38abb
"
integrity sha512-
x5DKhRrg8v1NWmClWa8zA80gWQ9xevivsUAF4s8CyAl/ZplBsEE1funKuuVcIKjexyE1UXb7uFWrUKt1fB5n1A
==
"@koa/cors@^3.1.0":
version "3.1.0"
...
...
@@ -1316,10 +1316,10 @@
"@types/qs" "*"
"@types/serve-static" "*"
"@types/fs-extra@^9.0.
2
":
version "9.0.
3
"
resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.
3.tgz#9996e5cce993508c32325380b429f04a1327523e
"
integrity sha512-
NKdGoXLTFTRED3ENcfCsH8+ekV4gbsysanx2OPbstXVV6fZMgUCqTxubs6I9r7pbOJbFgVq1rpFtLURjKCZWUw
==
"@types/fs-extra@^9.0.
4
":
version "9.0.
4
"
resolved "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.
4.tgz#12553138cf0438db9a31cdc8b0a3aa9332eb67aa
"
integrity sha512-
50GO5ez44lxK5MDH90DYHFFfqxH7+fTqEEnvguQRzJ/tY9qFrMSHLiYHite+F3SNmf7+LHC1eMXojuD+E3Qcyg
==
dependencies:
"@types/node" "*"
...
...
@@ -1725,18 +1725,18 @@
vscode-languageserver-textdocument "^1.0.1"
vscode-uri "^2.1.2"
"@vueuse/core@^4.0.0-beta.4
0
":
version "4.0.0-beta.4
0
"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-beta.4
0.tgz#7efdc15c1b994647dff7ae65c0ca573d96ce9b28
"
integrity sha512-
FOTOUrXAAp0NOmy8hMlP1HpUhnB8LeRJZDOEUl/A9gKMDwWvPTEvxKsDAIzSa4s7I0MapVzfeP3soNCNfl9+vQ
==
"@vueuse/core@^4.0.0-beta.4
1
":
version "4.0.0-beta.4
1
"
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-beta.4
1.tgz#0058aed5ade75ae2866283498009ad5172cbae84
"
integrity sha512-
CgUih65PzYScorm1S4F93e6XXm+qxA8GrRLOSB1kXaqtP6vXedwkBxKkNEYNACx4reL4VEHqM/BrM6FajXkQUg
==
dependencies:
"@vueuse/shared" "4.0.0-beta.4
0
"
"@vueuse/shared" "4.0.0-beta.4
1
"
vue-demi latest
"@vueuse/shared@4.0.0-beta.4
0
":
version "4.0.0-beta.4
0
"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-beta.4
0.tgz#76e9b52228159e7ec88df2c8f4eea8fce1a42ec3
"
integrity sha512-
Ay71viUTXs0XX2hQ04kEExhpsCrw3KankBMP7euorsPjuQmIZjUA4NNOb45UAudg+uF5HXLpgWLvwb4cMOLHnQ
==
"@vueuse/shared@4.0.0-beta.4
1
":
version "4.0.0-beta.4
1
"
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-beta.4
1.tgz#395782ea2e580f1fc9488d25c89bd09f70170b25
"
integrity sha512-
dqnuEPPC3OUJ6L6rhMiOCuPWIR698DtdwOydwCZBISsG2V6gZ2QFND6xtRwLib6/lhUMYVYPwIz3hPjlx7BIzw
==
dependencies:
vue-demi latest
...
...
@@ -1850,10 +1850,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
ant-design-vue@^2.0.0-
beta.15
:
version "2.0.0-
beta.15
"
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-
beta.15.tgz#3c787dabb70a33885d0e751e58f9a5610ed06134
"
integrity sha512-
OxZy+ZYU3LauIL4Rhqwy441K/iD++Cit6upnQy5+LVUrX0PSObPqPqMWVpncbAmJJYTEz88gkvgGeYqBdzouWA
==
ant-design-vue@^2.0.0-
rc.1
:
version "2.0.0-
rc.1
"
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-2.0.0-
rc.1.tgz#2ef02475f3aa4c1474f2fe3cf44a52c34787be02
"
integrity sha512-
iKXkFtTHarvLHV7LWmYh6g/Cmkv+xK+vS621A1Qvg37Z6lCGg3K9BGAizmklAYzOTiPz0Ltt63eSiNqYMGh52g
==
dependencies:
"@ant-design-vue/use" "^0.0.1-0"
"@ant-design/icons-vue" "^5.1.5"
...
...
@@ -8109,10 +8109,10 @@ vary@^1.1.2:
resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
vditor@^3.6.
0
:
version "3.6.
1
"
resolved "https://registry.npmjs.org/vditor/-/vditor-3.6.
1.tgz#b0b510f23d0cf0e5d8b3d36924e40400de96f692
"
integrity sha512-
83GdGLIWrV1x04aK8DO9aZidqQfmuGXXUbxSCuQxRla+T9KfnFRmJwfqIxXQm8h+4jUBCFL38e8PqLa3fBOf9w
==
vditor@^3.6.
2
:
version "3.6.
2
"
resolved "https://registry.npmjs.org/vditor/-/vditor-3.6.
2.tgz#ee6011efa3ec563c6356ed82efbf2e00ba2e35c6
"
integrity sha512-
HPHHun5+IXmYGMKDWcUD83VfP1Qfncz7DmaIKoWpluJgE8ve7s+4RbFBcaEpYPXYzIuL2UTHoMnIjmTPbenOCA
==
dependencies:
diff-match-patch "^1.0.5"
...
...
@@ -8272,10 +8272,10 @@ vue-i18n@^9.0.0-beta.6:
dependencies:
source-map "^0.6.1"
vue-router@^4.0.0-rc.
2
:
version "4.0.0-rc.
2
"
resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.0-rc.
2.tgz#8545cab76a05ca4f6dffbe6c6a671a4dbf585ab2
"
integrity sha512-
51mBp39rzBFpk1nyU9SkhPcwR67gBzWIH8p3pyeDmtNYgWzGF3q8MneD/xbMwsfTQkw2H1qBk6uwRaVy3M8Nxw
==
vue-router@^4.0.0-rc.
3
:
version "4.0.0-rc.
3
"
resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.0-rc.
3.tgz#70d18e90030bc6a25e81a30401d673223998ec6b
"
integrity sha512-
NnPqWIfanEhJC4wu8BEFBmnEDIrx9ST0/HtmBiE+oV2MQlhyRk1TmdttWwVqx6Sh7kONsrI10GQV9l3YEkcWXg
==
vue-types@^3.0.0:
version "3.0.1"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录