123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- <template>
- <view class="upload_box">
- <view class="upload_list">
- <view v-for="(item, index) in fileList" :key="index" class="flex_box upload_item">
- <view @click="$openFile(item.url)" class="flex_box upload_left">
- <u-image
- width="60rpx"
- height="60rpx"
- :showError="false"
- :showLoading="false"
- :src="`${$IMG_URL}/static/format/${fileTypes.indexOf(item.type) === '-1' ? 'file' : item.type}.png`"
- ></u-image>
- <view class="upload_content">
- <view class="upload_name">{{ item.name }}</view>
- <view v-if="item.size" class="upload_text">{{ item.size }}</view>
- </view>
- </view>
- <u-image
- v-if="!isDetail"
- @click="deletePic(index)"
- width="48rpx"
- height="48rpx"
- :showError="false"
- :showLoading="false"
- :src="`${$IMG_URL}/static/home/icon_cancel@2x.png`"
- ></u-image>
- <view class="service_check">
- <u-icon color="#FD910C" size="24rpx" :name="item.status === 'success' ? 'checkmark-circle-fill' : 'close-circle-fill'"></u-icon>
- </view>
- </view>
- </view>
- <!-- #ifdef APP -->
- <view class="upload_btn_box" v-if="(!isDetail || limit === fileList.length) && fileShow">
- <template v-if="authList['WRITE_EXTERNAL_STORAGE'] && authList['CAMERA']">
- <lsj-upload
- ref="lsjUpload"
- :wxFileType="wxFileType"
- :extension="extension"
- :childId="childId"
- :width="width"
- :height="height"
- :option="option"
- :size="fileSize"
- :count="limit"
- :multiple="multiple"
- :formats="fileType"
- :accept="fileAccept"
- :debug="debug"
- :instantly="instantly"
- @uploadEnd="onuploadEnd"
- @progress="onprogre"
- @change="change"
- >
- <view class="upload_btn">
- <u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
- </view>
- </lsj-upload>
- </template>
- <view v-else-if="!authList['WRITE_EXTERNAL_STORAGE']" class="upload_btn_auth" @tap.stop="openAuth('WRITE_EXTERNAL_STORAGE')">
- <view class="upload_btn">
- <u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
- </view>
- </view>
- <view v-else class="upload_btn_auth" @tap.stop="openAuth('CAMERA')">
- <view class="upload_btn">
- <u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
- </view>
- </view>
- </view>
- <yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" :permissionID="permissionID"></yk-authpup>
- <!-- #endif -->
- <!-- #ifndef APP -->
- <view class="upload_btn_box" v-if="(!isDetail || limit === fileList.length) && fileShow">
- <lsj-upload
- ref="lsjUpload"
- :wxFileType="wxFileType"
- :extension="extension"
- :childId="childId"
- :width="width"
- :height="height"
- :option="option"
- :size="fileSize"
- :count="limit"
- :multiple="multiple"
- :formats="fileType"
- :accept="fileAccept"
- :debug="debug"
- :instantly="instantly"
- @uploadEnd="onuploadEnd"
- @progress="onprogre"
- @change="change"
- >
- <view class="upload_btn">
- <u-image :width="width" :height="height" :showError="false" :showLoading="false" :src="`${$IMG_URL}/static/contract/icon_increase2-2.png`"></u-image>
- </view>
- </lsj-upload>
- </view>
- <!-- #endif -->
- </view>
- </template>
- <script>
- import { mapGetters } from 'vuex'
- import ykAuthpup from '@/components/yk-authpup/yk-authpup'
- import { getFileName } from '@/common/request/apis/index'
- export default {
- name: 'UploadFile',
- components: {
- ykAuthpup
- },
- props: {
- // 值
- value: [String, Object, Array],
- // 宽度
- width: {
- type: String,
- default: '104rpx'
- },
- // 高度
- height: {
- type: String,
- default: '104rpx'
- },
- // 数量限制
- limit: {
- type: Number,
- default: 9
- },
- // 大小限制(MB)
- fileSize: {
- type: Number,
- default: 200
- },
- // 文件类型, 例如'png, jpg, jpeg']
- fileType: {
- type: String,
- default: ''
- },
- // 文件类型, 例如'audio/*, video/*, image/*']
- fileAccept: {
- type: String,
- default: '*'
- },
- // 是否文件覆盖图片
- isOne: {
- type: Boolean,
- default: false
- },
- // 强制刷新
- fileShow: {
- type: Boolean,
- default: true
- },
- // 是否多选
- multiple: {
- type: Boolean,
- default: true
- },
- // 是否显示提示
- isShowTip: {
- type: Boolean,
- default: true
- },
- // 是否详情
- isDetail: {
- type: Boolean,
- default: false
- },
- //id
- childId: {
- type: String,
- default: 'lsjUpload'
- },
- // 微信选择文件类型
- //all=从所有文件选择,
- //video=只能选择视频文件,
- //image=只能选择图片文件,
- //file=可以选择除了图片和视频之外的其它的文件
- wxFileType: { type: String, default: 'all' },
- extension: { type: Array, default: () => ['*'] }
- },
- data() {
- return {
- fileTypes: ['bmp', 'doc', 'docx', 'gif', 'jpeg', 'jpg', 'mp3', 'mp4', 'pdf', 'png', 'ppt', 'pptx', 'rar', 'wav', 'webm', 'webp', 'xls', 'xlsx', 'zip'],
- // 上传接口参数
- option: {
- // 上传服务器地址,需要替换为你的接口地址
- url: this.$UPLOAD_URL, // 该地址非真实路径,需替换为你项目自己的接口地址
- // 上传附件的key
- name: 'file',
- // 根据你接口需求自定义请求头,默认不要写content-type,让浏览器自适配
- header: {
- token: `${this.$store.getters.token}`
- },
- // 根据你接口需求自定义body参数
- formData: {
- filename: ''
- }
- },
- // 选择文件后是否立即自动上传,true=选择后立即上传
- instantly: true,
- // 文件回显列表
- files: new Map(),
- // 微信小程序Map对象for循环不显示,所以转成普通数组,不要问为什么,我也不知道
- wxFiles: [],
- // 是否打印日志
- debug: false,
- // 文件显示列表
- fileList: [],
- // 权限判断
- permissionID: ''
- }
- },
- watch: {
- value: {
- async handler(val) {
- if (val) {
- // if (this.fileList.length > 0) return
- // 首先将值转为数组
- const list = Array.isArray(val) ? val : this.value.split(',')
- const files = []
- // 然后将数组转为对象数组
- for (let i = 0; i < list.length; i++) {
- let item = list[i]
- if (typeof item === 'string') {
- let name = item + ''
- let size = ''
- if (name && name.lastIndexOf('/') > -1) {
- const result = await getFileName({
- file_name: name,
- type: 1
- })
- name = result && result.code === 1 ? result.data.filename : name
- size = result && result.code === 1 ? this.$filterSize(result.data.filesize) : size
- }
- item = {
- name: name,
- url: this.getUrl(item),
- fullurl: item,
- size: size,
- status: 'success',
- message: '',
- type: item.slice(item.lastIndexOf('.') + 1).toLowerCase()
- }
- }
- files.push(item)
- }
- this.fileList = files
- } else {
- this.fileList = []
- return []
- }
- },
- deep: true,
- immediate: true
- }
- },
- computed: {
- // 是否显示提示
- showTip() {
- return this.isShowTip && (this.fileType || this.fileSize)
- },
- ...mapGetters('auth', ['authList', 'onceIn'])
- },
- mounted() {
- // #ifdef APP
- // if (this.onceIn) {
- // this.$store.commit('auth/edit', {data: false, index: 'onceIn'})
- // this.openAuth('WRITE_EXTERNAL_STORAGE')
- // }
- // #endif
- },
- methods: {
- //打开自定义权限目的弹框
- openAuth(permissionID) {
- this.permissionID = permissionID //这个是对应的权限 ACCESS_FINE_LOCATION 位置权限 / WRITE_EXTERNAL_STORAGE 存储空间/照片权限 / CAMERA相机权限 / CALL_PHONE 拨打电话
- setTimeout(() => {
- this.$refs['authpup'].open()
- }, 500)
- },
- //用户授权权限后的回调
- changeAuth() {
- //这里是权限通过后执行自己的代码逻辑
- console.log('权限已授权,可执行自己的代码逻辑了')
- this.authList[this.permissionID] = true
- const list = { ...this.authList }
- this.$store.commit('auth/edit', { data: list, index: 'authList' })
- if (!this.authList['CAMERA']) {
- this.openAuth('CAMERA')
- }
- },
- // 手动触发
- actionClick() {
- // 强制更新视图
- this.$forceUpdate()
- console.log(this.extension)
- this.$nextTick(() => {
- this.$refs.lsjUpload.onClick()
- })
- },
- // 刷新组件
- refresh() {
- this.$refs.lsjUpload.hide()
- this.$nextTick(() => {
- setTimeout(() => {
- this.$refs.lsjUpload.show()
- }, 200)
- })
- },
- /**
- * 某文件上传结束回调(成功失败都回调)
- * @param {Object} item 当前上传完成的文件
- */
- onuploadEnd(item) {
- if (item) {
- if (this.isOne) {
- this.files.clear()
- this.wxFiles = []
- this.fileList = []
- }
- // 更新当前窗口状态变化的文件
- this.files.set(item.name, item)
- this.wxFiles = [...this.files.values()]
- // 强制更新视图
- this.$forceUpdate()
- const isHas = this.fileList.find((file) => file.name === item.name)
- if (item.responseText && !isHas) {
- const result = JSON.parse(item.responseText)
- if (result.code === 1) {
- this.fileList.push({
- status: 'success',
- name: item.name,
- size: this.$filterSize(item.size),
- message: '',
- url: result.data.fullurl,
- fullurl: result.data.url,
- type: result.data.url.slice(result.data.url.lastIndexOf('.') + 1).toLowerCase()
- })
- } else {
- uni.showModal({
- content: `${item.name}上传失败,请重新上传`,
- showCancel: false
- })
- }
- }
- }
- let isAll = [...this.files.values()].find((item) => item.type !== 'success')
- if (!isAll) {
- this.setUrl()
- }
- },
- /**
- * 上传进度回调
- * 如果网页上md文档没有渲染出事件名称onprogre,请复制代码的小伙伴自行添加上哈,没有哪个事件是只(item)的
- * @param {Object} item 当前正在上传的文件
- */
- onprogre(item) {
- // 更新当前状态变化的文件
- this.files.set(item.name, item)
- // 微信小程序Map对象for循环不显示,所以转成普通数组,不要问为什么,我也不知道
- this.wxFiles = [...this.files.values()]
- // 强制更新视图
- this.$forceUpdate()
- },
- /**
- * 文件选择回调
- * @param {Object} files 已选择的所有文件Map集合
- */
- change(files) {
- const list = [...files.values()]
- if (list.length === 0) return
- uni.showLoading({
- title: '上传中',
- mask: true
- })
- // 更新选择的文件
- this.files = files
- // 强制更新视图
- this.$forceUpdate()
- this.wxFiles = [...list]
- },
- /**
- * 移除某个文件
- * @param {Object} name 带后缀名的文件名称
- */
- deletePic(index) {
- // name=指定文件名,不传name默认移除所有文件
- this.$refs.lsjUpload.clear(this.fileList[index].name)
- this.fileList.splice(index, 1)
- this.setUrl()
- },
- // 设置图片
- setUrl() {
- let that = this
- let urls = []
- let list = []
- for (let i = 0; i < that.fileList.length; i++) {
- if (that.fileList[i].status === 'success') {
- urls.push(that.fileList[i].fullurl)
- list.push({
- url: that.fileList[i].fullurl,
- fullurl: that.fileList[i].url,
- index: i,
- name: that.fileList[i].name
- })
- }
- }
- that.$emit('input', urls.join(','))
- that.$emit('change', list)
- uni.hideLoading()
- },
- // 设置域名
- getUrl(url) {
- if (url.indexOf('http') === -1) url = this.$UPLOAD_BASE + url
- return url
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .upload_box {
- position: relative;
- .upload_btn_box {
- position: relative;
- z-index: 99;
- .upload_btn_auth {
- width: 96rpx;
- height: 96rpx;
- }
- .upload_btn {
- width: 96rpx;
- height: 96rpx;
- position: relative;
- }
- }
- .upload_list {
- .upload_item {
- background: rgba(134, 158, 180, 0.1);
- border-radius: 8rpx;
- padding: 8rpx 24rpx 8rpx 8rpx;
- margin-bottom: 24rpx;
- position: relative;
- .upload_left {
- width: calc(100% - 48rpx);
- padding-left: 16rpx;
- }
- .upload_content {
- width: calc(100% - 96rpx);
- padding: 0 16rpx;
- .upload_name {
- width: 100%;
- word-break: break-all;
- font-size: 28rpx;
- color: #333333;
- line-height: 40rpx;
- margin-bottom: 8rpx;
- }
- .upload_text {
- font-size: 24rpx;
- color: #999999;
- line-height: 34rpx;
- }
- }
- .service_check {
- position: absolute;
- top: 0;
- right: 0;
- z-index: 10;
- text-align: center;
- padding: 6rpx;
- }
- }
- }
- }
- </style>
|