This commit is contained in:
2026-09-24 16:25:22 +08:00
commit 7428184f01
1198 changed files with 314515 additions and 0 deletions
@@ -0,0 +1,875 @@
<script lang="ts">
import { type PropType,toRaw } from "vue"
import { getUid, rpx2px } from "../../core/util/xCoreUtil.uts"
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
import { checkIsCssUnit } from "../../core/util/xCoreUtil.uts"
import { xUploadMedia } from "../../core/util/xUploadFileMedia.uts"
import { XUPLOADFILE_INFO, XUPLOADFILE_FILE_INFO, XUPLOADFILE_FILE_VALUE } from "../../interface.uts"
import { xConfig } from "../../config/xConfig.uts"
type funcalldel = (index : number, item : XUPLOADFILE_FILE_INFO) => Promise<boolean>
type funbeforeCompelte = (item : XUPLOADFILE_FILE_INFO) => XUPLOADFILE_FILE_INFO
type beforeUploadType = (item : XUPLOADFILE_FILE_INFO) => Promise<XUPLOADFILE_FILE_INFO>
/**
* @name 图片上传 xUploadMedia
* @description 可以上传视频或者图片,注意不要混搭.要么上传视频,要么上传图片.当用户自行添加默认文件时可以给你的文件对象加status:0表示待上传,要确保你的上传文件路径是正确的
* 否则安卓会引发io错误,并且uni.upload是无法捕捉到fail事件中,会导致整个程序不可用
* @page /pages/index/upload-media
* @category 表单组件
* @constant 平台兼容
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
*/
export default {
data() {
return {
nowFileList: [] as XUPLOADFILE_FILE_INFO[],
itemWidth: 0,
spaceGap: 4,
xupload: new xUploadMedia() as xUploadMedia | null,
mouse_x: 0,
mouse_y: 0,
_totalHeight: 0,
_nowIndex: -1,
// 是否已经长按触发了拖动排序功能。
_isLongPressCanDisableMove: false,
movexitem_x: 0,
movexitem_y: 0,
_newIndex: 0,
showMoveItem: false,
tempMoveIndex: -1,
diffY: 0,
diffX: 0,
tid2: 0,
nowshowClickMedioSrc:'',
showVideo:false,
tid3:66
}
},
emits: [
/**
* 每次全部上传完时触发
* @param {XUPLOADFILE_FILE_VALUE[]} 列表数据
*/
'complete',
/**
* 变化时触发
* @param {XUPLOADFILE_FILE_VALUE[]} 列表数据
*/
'change',
/**
* 图片被删除时触发
* @param {XUPLOADFILE_FILE_VALUE[]} 列表数据
*/
'delete',
'update:modelValue'
],
props: {
/**
* 上传的类型,video,photo,默认是上传图片
*/
mode:{
type:String,
default:'photo'
},
/**
* 当mode=video时,选择视频上传的参数,
* 些参数为utsjson,所有字段为可选,具体字段为uni.chooseVideo(options)中的部分有效字段
* pageOrientation,albumMode,compressed,compressed,maxDuration,camera
*/
videoOps:{
type:Object as PropType<UTSJSONObject>,
default:():UTSJSONObject =>{
return {
pageOrientation:'auto',
albumMode:'system',
sourceType:['album', 'camera'] as string[],
compressed:true,
maxDuration:60,
camera:'back'
} as UTSJSONObject
}
},
/**
* 最大的可上传数量
*/
maxCount: {
type: Number,
default: 9
},
/**
* 上传地址
*/
url: {
type: String,
default: "https://mockapi.eolink.com/LRViGGZ8e6c1e8b4a636cd82bca1eb15d2635ed8c74e774/admin/upload_pic/"
},
/**
* 上传到服务器的名称字段
*/
name: {
type: String,
default: "file"
},
/**
* 上传到服务器的头文件
*/
header: {
type: Object as PropType<UTSJSONObject>,
default: () : UTSJSONObject => {
return {} as UTSJSONObject
}
},
/**
* 额外的表单数据。
*/
formData: {
type: Object as PropType<UTSJSONObject | null>,
default: () : UTSJSONObject => {
return {} as UTSJSONObject
}
},
/**
* 图片高,此处不可使用%单位
*/
imgHeight: {
type: String,
default: "80"
},
/**
* 一行显示几列
*/
column: {
type: Number,
default: 5
},
/**
* 上传成功的文件是否允许删除
*/
okFileIsDelete: {
type: Boolean,
default: true
},
/**
* 上传中的文件是否允许删除
*/
uploadingFileIsDelete: {
type: Boolean,
default: true
},
/**
* 等同v-model
*/
modelValue: {
type: Array as PropType<XUPLOADFILE_FILE_VALUE[]>,
default: () : XUPLOADFILE_FILE_VALUE[] => [] as XUPLOADFILE_FILE_VALUE[]
},
/**
* 图片被删除时触发
* 如果返回Promise<false>删除失败否则成功
* 类型null|(index:number,item:XUPLOADFILE_FILE_INFO)=>Promise<boolean>
*/
beforeDel: {
type: Function as PropType<funcalldel | null>,
default: null
},
/**
* 你需要原路返回参数提供的item
* item可以自行修改响应内容,响应类型这样可以自己根据服务的内容判断
* 是成功还是失败或者没有权限。示例见demo使用。
*/
beforeComplete:{
type:Function as PropType<funbeforeCompelte|null>,
default:null
},
/**
* 上传前的最后一步执行,异步回调,函数返回一个item:XUPLOADFILE_FILE_INFO
* 返回时要原样类型返回Promise<XUPLOADFILE_FILE_INFO>,你可以在这里修改文件参数跳过上传或者
* 进行最后的头参数设置.demo有参考.
*/
beforeUpload:{
type:Function as PropType<beforeUploadType|null>,
default:null
},
/**
* 是否自动上传
*/
autoStart: {
type: Boolean,
default: true
},
/**
* 图片来源同官方的sourceType
* 'album','camera'
*/
sourceType: {
type: Array as PropType<string[]>,
default: () : string[] => ['album', 'camera'] as string[]
},
/**
* 是否压缩
*/
compress: {
type: Boolean,
default: true
},
/**
* 压缩后的缩放高,0表示不压缩高
*/
compressedHeight: {
type: Number,
default: 0
},
/**
* 压缩后的缩放高,0表示不压缩宽
*/
compressedWidth: {
type: Number,
default: 0
},
/**
* 压缩质量
*/
quality: {
type: Number,
default: 80
},
/**
* 添加图片的位置
* 'before'出现在前面
* 'after'出现在后面
*/
addPos:{
type:String,
default:"after"
},
/**
* 子项对齐方式,left左对齐默认,right:右对齐
*/
align:{
type:String,
default:"left"
}
},
computed: {
_fileList() : XUPLOADFILE_FILE_INFO[] {
return this.nowFileList
},
_imgHeight() : string {
return checkIsCssUnit(this.imgHeight, xConfig.unit)
},
_okFileIsDelete() : boolean {
return this.okFileIsDelete
},
_uploadingFileIsDelete() : boolean {
return this.uploadingFileIsDelete
},
_itemHeight() : number {
let item = this._imgHeight;
let h = 0;
if (item.lastIndexOf('rpx') > -1) {
h = parseFloat(item.replace(/[rpx]/g, ''));
h = rpx2px(h)
} else {
h = parseFloat(item.replace(/[px,%]/g, ''));
}
return h;
},
_borderColor() : string {
if (xConfig.dark == 'dark') return xConfig.borderDarkColor
return '#eeeeee';
},
_bgColor() : string {
if (xConfig.dark == 'dark') return xConfig.inputDarkColor
return '#f5f5f5';
},
_columnRatio() : string {
return (100 / this.column).toString() + '%'
},
_formData() : UTSJSONObject | null {
return this.formData
}
},
watch: {
modelValue(newValue : XUPLOADFILE_FILE_VALUE[]) {
if(this._fileList.length==0&&newValue.length==0) return;
if(newValue.length==0){
this.xupload!.stop()
this.xupload!.clear()
this.nowFileList = []
return;
}
this.xupload!.addFile(JSON.parseArray<XUPLOADFILE_FILE_VALUE>(JSON.stringify(newValue)!)!)
clearTimeout(this.tid3)
let t = this;
this.tid3 = setTimeout(()=>{
t.getNodeInfo()
},200)
},
header() {
this.setConfig()
},
maxCount() {
this.setConfig()
},
url() {
this.setConfig()
},
name() {
this.setConfig()
},
formData() {
this.setConfig()
}
},
mounted() {
let t = this;
this.setConfig()
this.xupload!.beforeUpload = (res : XUPLOADFILE_FILE_INFO) : Promise<XUPLOADFILE_FILE_INFO> => {
let call = this.beforeUpload as beforeUploadType|null
if(call==null||res.status==1||res.status==2||res.status==4||res.status==5){
return Promise.resolve(toRaw(res) as XUPLOADFILE_FILE_INFO)
}
let realcall = call! as beforeUploadType
return realcall(toRaw(res) as XUPLOADFILE_FILE_INFO )
}
this.xupload!.addListenEvent('complete', (res : any) : Promise<any> => {
let result = res as XUPLOADFILE_FILE_INFO[];
let clonelist = t.cloneListData(result)
/**
* 全部上传完时触发
* @parsm {XUPLOADFILE_FILE_VALUE[]} result - 列表数据
*/
t.$emit('complete', clonelist)
t.$emit("update:modelValue", clonelist)
return Promise.resolve(res)
})
this.xupload!.beforeComplete = (res : XUPLOADFILE_FILE_INFO) : XUPLOADFILE_FILE_INFO => {
let result = res as XUPLOADFILE_FILE_INFO;
if(t.beforeComplete!=null){
let bef = t.beforeComplete! as funbeforeCompelte
result = bef(isProxy(result)?toRaw(result):result )
}
return result
}
this.xupload!.setChangeSync(function (res : XUPLOADFILE_FILE_INFO[]) {
t.nowFileList = res;
t._totalHeight = t.totalHeight()
let clonelist = t.cloneListData(res)
/**
* 列表操作变化时触发,删除,上传成功并添加到列表中(选择图片,不上传不触发)
* @parsm {XUPLOADFILE_FILE_INFO[]} result - 列表数据
*/
t.$emit('change', clonelist)
t.$emit("update:modelValue", clonelist)
})
if (this.modelValue.length > 0) {
let clonelist = t.cloneListDataByValue(this.modelValue)
this.xupload!.addFile(clonelist)
}
clearTimeout(this.tid3)
this.tid3 = setTimeout(()=>{
t.getNodeInfo()
},200)
uni.$on('onResize', this.resetInit)
},
beforeUnmount() {
clearTimeout(this.tid3)
uni.$off('onResize', this.resetInit)
this.xupload = null;
},
methods: {
cloneListData(listReal:XUPLOADFILE_FILE_INFO[]):XUPLOADFILE_FILE_VALUE[]{
let list = listReal.map((el : XUPLOADFILE_FILE_INFO) : XUPLOADFILE_FILE_VALUE => {
return {
id: el.id,
url: el.path,
response: el.response
} as XUPLOADFILE_FILE_VALUE
})
return JSON.parseArray<XUPLOADFILE_FILE_VALUE>(JSON.stringify(list)!)!
},
cloneListDataByValue(list:any):XUPLOADFILE_FILE_VALUE[]{
return JSON.parseArray<XUPLOADFILE_FILE_VALUE>(JSON.stringify(list)!)!
},
setConfig() {
this.xupload!.setConfig({
autoUpload: this.autoStart,
count: this.maxCount,
header: this.header as UTSJSONObject,
hostUrl: this.url,
name: this.name,
formData: this._formData,
sourceType: this.sourceType,
compress: this.compress,
quality:this.quality,
compressedWidth: this.compressedWidth == 0 ? null : this.compressedWidth,
compressedHeight: this.compressedHeight == 0 ? null : this.compressedHeight
} as XUPLOADFILE_INFO)
},
resetInit() {
this.diffY = 0
this.diffX = 0
let t = this;
clearTimeout(this.tid3)
this.tid3 = setTimeout(()=>{
t.getNodeInfo()
},200)
},
totalHeight() : number {
let realItemHeight = this._itemHeight + this.spaceGap
let row = Math.ceil(this.nowFileList.length / this.column);
let height = row * realItemHeight
let total = Math.max(height, realItemHeight)
return total;
},
chooseFile() {
this.xupload!.setVideoOps(this.videoOps,this.mode)
this.xupload!.chooseMedia()
},
/**
* 手动上传图片
* @public
*/
upload() {
this.xupload!.start()
},
getNodeInfo() {
uni.createSelectorQuery().in(this)
.select(".xUploadMedia")
.boundingClientRect().exec((ret) => {
let nodeinfo = ret[0] as NodeInfo
let space = (this.column - 1) * this.spaceGap;
// #ifdef APP-IOS
this.itemWidth = (nodeinfo.width! - space) / this.column - 0.28
// #endif
// #ifndef APP-IOS
this.itemWidth = (nodeinfo.width! - space) / this.column
// #endif
this._totalHeight = this.totalHeight()
})
},
getStatusColor(item : XUPLOADFILE_FILE_INFO) : string {
if (item.status == 1) return 'rgba(99, 83, 4, 0.5)'
if (item.status == 2) return 'rgba(0, 0, 0, 0.5)'
if (item.status == 3 || item.status == 4 || item.status == 5) return 'rgba(115, 26, 4, 0.7)'
return 'rgba(0, 0, 0, 0.5)'
},
getTextStatus(status : number) : string {
// 0未上传,1上传中,2上传成功,3上传失败(网络错误),4已取消(终止,上到一半取消了),5超过大小
let text = "";
if (status == 0) {
text = this!.i18n.t("tmui4x.uploadFile.uploadStatus",0);//"待上传"
} else if (status == 3) {
text = this!.i18n.t("tmui4x.uploadFile.uploadStatus",2);//"上传失败"
} else if (status == 2) {
text = this!.i18n.t("tmui4x.uploadFile.uploadStatus",3);//"上传成功"
} else if (status == 1) {
text = this!.i18n.t("tmui4x.uploadFile.uploadStatus",1);//"上传中..."
} else if (status == 5) {
text = this!.i18n.t("tmui4x.uploadFile.uploadStatus",4);//"超过大小"
}
return text
},
delRemove(item : XUPLOADFILE_FILE_INFO, index : number) {
let _this = this;
if (!this._okFileIsDelete) {
// "不允许删除"
uni.showToast({ title: this!.i18n.t("tmui4x.uploadFile.tips2"), mask: true, icon: 'none' })
return;
}
if (item.status == 1 && !this._uploadingFileIsDelete) {
// "上传中,不允许删除"
uni.showToast({ title: this!.i18n.t("tmui4x.uploadFile.tips1"), mask: true, icon: 'none' })
return;
}
if (this.beforeDel == null) {
_this.xupload!.delFile(item.id)
let clonelist = this.cloneListData(_this.xupload!.fileList)
_this.$emit("update:modelValue", clonelist)
return;
}
let call = this.beforeDel! as funcalldel
call(index, item).then((res : boolean) => {
if (res) {
_this.xupload!.delFile(item.id)
let recorelist = _this.xupload!.fileList.slice(0)
let clonelist = this.cloneListData(recorelist)
_this.$emit('delete',clonelist)
_this.$emit("update:modelValue", clonelist)
}
}).catch(() => { })
},
mStart(index : number) {
this._nowIndex = index
this._newIndex = index
},
mMove(evt : UniTouchEvent) {
if (!this._isLongPressCanDisableMove) return;
evt.stopPropagation()
evt.preventDefault()
let selfEle = this.$refs['xUploadMedia'] as UniElement
let selfEeleBox = selfEle.getBoundingClientRect()
let x = evt.changedTouches[0].clientX - selfEeleBox.left
let y = evt.changedTouches[0].clientY - selfEeleBox.top
let moveItemel = this.$refs['moveItem'] as UniElement
let offset_x = (x - this.itemWidth / 2) + this.spaceGap / 2
let offset_y = (y - this._itemHeight / 2) + this.spaceGap / 2
moveItemel.style.setProperty('left', offset_x.toString() + 'px')
moveItemel.style.setProperty('top', offset_y.toString() + 'px')
this.mouse_x = offset_x
this.mouse_y = offset_y
this.tempXy(this.mouse_x, this.mouse_y)
},
mEnd(evt : UniTouchEvent) {
if (!this._isLongPressCanDisableMove) return;
this._isLongPressCanDisableMove = false;
let maxxy = Math.max(Math.abs(evt.changedTouches[0].clientX - this.diffX), Math.abs(evt.changedTouches[0].clientY - this.diffY))
this.movexitem_x = this.mouse_x
this.movexitem_y = this.mouse_y
this.coverXy(maxxy > 10);
},
// 将当前的x,y坐标转换为 对应的item的index的坐标。
coverXy(isJiaoHuan : boolean) {
// 计算最大行数
let maxRow = Math.ceil((this.nowFileList.length) / this.column) - 1;
// 当前理论值的列数
let col = Math.ceil((this.movexitem_x - this.itemWidth / 2) / this.itemWidth)
// 当前理论值的行数
let row = Math.ceil((this.movexitem_y - this._itemHeight / 2) / this._itemHeight)
// 比较不能让col越界超过最大值和最小值的列数
col = Math.min(Math.max(col, 0), this.column - 1)
// 比较不能让row越界超过最大值和最小值的行数
row = Math.min(Math.max(row, 0), maxRow)
// 理论值的index,类似一个网格中的x,y坐标
let index = (col * row);
// index不能越界超过最大文件长度值的索引
index = Math.max(Math.min(0, index), this.nowFileList.length - 1)
let realCol = col;
// 理论值的col可能会超过实际的col,比如计算col为第3列,但这个值是最大值,并不是真实的最大值
// 如果有两行,第2行只有1列,那其实col只能为1,而不是鼠标xy计算出的col
if (row >= maxRow) {
realCol = Math.min(col, (this.nowFileList.length - 1) % this.column)
}
let realRow = row
let x = realCol * this.itemWidth - this.spaceGap * realCol
let y = realRow * this._itemHeight - this.spaceGap * realRow
// 经过比较得出真实的index值。
this._newIndex = realCol + realRow * (this.column)
if (isJiaoHuan) {
this.setItem()
} else {
this._nowIndex = -1
this._newIndex = -1;
}
this.movexitem_x = x
this.movexitem_y = y
this.showMoveItem = false;
this.tempMoveIndex = -1;
},
tempXy(mvx : number, mvy : number) {
// 计算最大行数
let maxRow = Math.ceil((this.nowFileList.length) / this.column) - 1;
// 当前理论值的列数
let col = Math.ceil((mvx - this.itemWidth / 2 - this.spaceGap) / this.itemWidth)
// 当前理论值的行数
let row = Math.ceil((mvy - this._itemHeight / 2) / this._itemHeight)
// 比较不能让col越界超过最大值和最小值的列数
col = Math.min(Math.max(col, 0), this.column - 1)
// 比较不能让row越界超过最大值和最小值的行数
row = Math.min(Math.max(row, 0), maxRow)
// 理论值的index,类似一个网格中的x,y坐标
let index = (col * row);
// index不能越界超过最大文件长度值的索引
index = Math.max(Math.min(0, index), this.nowFileList.length - 1)
let realCol = col;
// 理论值的col可能会超过实际的col,比如计算col为第3列,但这个值是最大值,并不是真实的最大值
// 如果有两行,第2行只有1列,那其实col只能为1,而不是鼠标xy计算出的col
if (row >= maxRow) {
realCol = Math.min(col, (this.nowFileList.length - 1) % this.column)
}
let realRow = row
// 经过比较得出真实的index值。
this.tempMoveIndex = realCol + realRow * (this.column)
},
setItem() {
// 新旧项目交换。
let newIndexItem = this._fileList.slice(0)[this._newIndex]
let oldindexItem = this._fileList.slice(0)[this._nowIndex]
this._fileList.splice(this._newIndex, 1, oldindexItem)
this._fileList.splice(this._nowIndex, 1, newIndexItem)
this.$nextTick(function () {
this.xupload!._addFilesByself(this._fileList)
// 结束交换后,把索引归-1,即为初始状态值。
this._nowIndex = -1
this._newIndex = -1;
let list = this._fileList.slice(0);
let clonelist = this.cloneListData(list)
// 最后同步到外层的排序列表。
this.$emit("update:modelValue", clonelist)
})
},
getUploadIngStatus() : boolean {
let UploadingOk = false;
for (let i = 0; i < this._fileList.length; i++) {
if (this._fileList[i].status == 1) {
UploadingOk = true;
break;
}
}
return UploadingOk;
},
mLongStart(evt : UniTouchEvent) {
let t = this;
if (this.getUploadIngStatus()) {
// '上传中不允许拖动排序'
uni.showToast({ title: this!.i18n.t("tmui4x.uploadMedia.tips1"), icon: 'none' })
return;
}
this._isLongPressCanDisableMove = true;
let selfEle = this.$refs['xUploadMedia'] as UniElement
let selfEeleBox = selfEle.getBoundingClientRect()
let x = evt.changedTouches[0].clientX
let y = evt.changedTouches[0].clientY
this.mouse_x = x - selfEeleBox.left
this.mouse_y = y - selfEeleBox.top
this.diffY = y
this.diffX = x
let offset_x = (this.mouse_x - this.itemWidth / 2) + this.spaceGap
let offset_y = (this.mouse_y - this._itemHeight / 2) + this.spaceGap
this.movexitem_x = offset_x
this.movexitem_y = offset_y
this.$nextTick(function () {
t.showMoveItem = true;
})
},
imgClickPrve(index : number) {
let urls = this.nowFileList.map((el) : string => el.path);
if(this.mode == 'photo'){
uni.previewImage({
current: index,
urls
})
}else if(this.mode == 'video'){
this.nowshowClickMedioSrc = this.nowFileList[index].path;
this.$nextTick(()=>{
this.showVideo = true;
})
}
}
},
}
</script>
<template>
<view>
<view @longpress="mLongStart" @touchmove="mMove" @touchend="mEnd" @touchcancel="mEnd"
ref="xUploadMedia"
class="xUploadMedia"
:style="{justifyContent: align=='left'?'flex-start':'flex-end'}"
>
<view v-for="(item,index) in _fileList" :key="index" :style="{width:_columnRatio}"
class="xUploadMediaItemParent">
<view class="xUploadMediaItem" @click="imgClickPrve(index)" @touchstart="mStart(index)" :style="{
height:_imgHeight,
marginRight:((index+1)%column)==0?'0px':spaceGap+'px',
marginBottom:spaceGap+'px'
}">
<view @click.stop="delRemove(item,index)" class="xUploadMediaClose" >
<x-icon color="rgba(255,255,255,0.6)" font-size="18" name="close-line"></x-icon>
</view>
<image v-if="mode=='photo'" class="xUploadMediaImg" :src="item.path" :key="item.id"></image>
<video v-if="mode=='video'" object-fit='fill' :enable-progress-gesture="false" :show-loading="false" :show-progress="false" :show-fullscreen-btn="false" :show-play-btn="false" class="xUploadMediaImg" width="100%" height="100%" :src="item.path" :key="item.id"></video>
<view class="xUploadMediaLabel" :style="{backgroundColor:getStatusColor(item)}">
<text class="xUploadMediaLabelText">
<!-- {{item.statusText}} -->
{{getTextStatus(item.status)}}
</text>
</view>
<!-- hover -->
<view v-if="tempMoveIndex==index" class="xUploadMediaItemHover"></view>
</view>
</view>
<view v-if="_fileList.length < maxCount " @click="chooseFile" class="xUploadMediaItem"
:style="{width:itemWidth+'px',height:_imgHeight}">
<!--
@slot 上传图片按钮插槽。
-->
<slot>
<view class="xUploadMediaAddSlot"
:style="{border: `1px solid ${_borderColor}`,'backgroundColor': _bgColor}">
<x-icon font-size="36" color="#d6d6d6" dark-color="#4a4a4a" name="add-line"></x-icon>
</view>
</slot>
</view>
<!-- 备用移动块。 -->
<!-- transitionDuration:_isLongPressCanDisableMove?'0ms':'200ms', -->
<view ref="moveItem" class="xUploadMediaMoveitem" v-show="_nowIndex>-1"
:style="{
left:movexitem_x+'px',top:movexitem_y+'px',width:itemWidth+'px',height:_imgHeight,marginRight:((_nowIndex+1)%column)==0?'0px':spaceGap+'px',marginBottom:spaceGap+'px'}">
<view v-if="showMoveItem"
:style="{backgroundColor:'rgba(0,0,0,0.5)',position: 'relative',width:'100%',height:'100%'}">
<view class="xUploadMediaClose">
<x-icon style="opacity: 0.5;" color="white" font-size="18" name="close-line"></x-icon>
</view>
<x-image v-if="mode=='photo'" style="opacity: 0.5;" width="100%" height="100%" :src="_fileList[_nowIndex].path"
:key="_fileList[_nowIndex].id"></x-image>
<view :style="{opacity: 0.5,backgroundColor:getStatusColor(_fileList[_nowIndex])}" class="xUploadMediaLabel">
<text class="xUploadMediaLabelText">
<!-- {{_fileList[_nowIndex].statusText}} -->
{{getTextStatus(_fileList[_nowIndex].status)}}
</text>
</view>
</view>
</view>
</view>
<!-- 视频预览 关闭-->
<x-modal :title="i18n!.t('tmui4x.uploadMedia.videoPreview')"
:confirm-text="i18n!.t('tmui4x.uploadMedia.close')" v-model:show="showVideo" height="360" :showCancel="false" :overlay-click="false" :show-close="false" >
<video :src="nowshowClickMedioSrc" style="width: 100%;height: 200px;" v-if="nowshowClickMedioSrc!=''&&showVideo"></video>
</x-modal>
</view>
</template>
<style scoped>
.xUploadMediaAddSlot {
height: 100%;
width: 100%;
/* border: 1px solid #eeeeee; */
/* background-color: #f5f5f5; */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.xUploadMediaImg {
pointer-events: none;
width:100%;
height:100%;
}
.xUploadMediaMoveitem {
position: absolute;
left: 0px;
top: 0px;
z-index: 8;
pointer-events: none;
}
.xUploadMediaLabel {
position: absolute;
left: 0rpx;
bottom: 0rpx;
z-index: 5;
width: 100%;
padding: 4px 6px;
background-color: rgba(0, 0, 0, 0.6);
/* #ifdef WEB || MP-WEIXIN */
box-sizing:border-box;
/* #endif */
}
.xUploadMediaLabelText {
lines: 1;
text-overflow: ellipsis;
font-size: 10px;
color: rgba(255,255,255,0.8);
text-align: center;
}
.xUploadMediaClose {
position: absolute;
right: 0rpx;
top: 0rpx;
padding:0px;
width:20px;
height:20px;
background-color: rgba(0, 0, 0, 0.4);
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
z-index: 5;
border-bottom-left-radius: 6px;
}
.xUploadMediaItemParent {
position: relative;
border-radius: 6px;
}
.xUploadMediaItem {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-radius: 6px;
position: relative;
/* #ifdef WEB || MP-WEIXIN */
overflow:hidden;
/* #endif */
}
.xUploadMedia {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
position: relative;
}
.xUploadMediaItemHover {
position: absolute;
z-index: 6;
width: 100%;
height: 100%;
border: 3px solid #1C84FF;
border-radius: 6px;
}
</style>