<!-- 文件管理 -->
<template>
    <div class="default-main main" :style="{ height: pageHeight.height }">
        <div class="main_left">
            <DeviceTree @node-click="nodeClick" @deviceTypeChange="deviceTypeChange" @init="nodeClick"></DeviceTree>
        </div>
        <div class="main_right" v-loading="loading">
            <div class="right_nav">
                <div class="menu" v-if="activePathList.length != 0">
                    <el-breadcrumb separator="/">
                        <el-breadcrumb-item v-for="(item, index) in activePathList" style="cursor: pointer" :key="index"
                            @click="handleIntoByPath(item)">
                            <span>{{ outPutPath(item, index) }}</span>
                        </el-breadcrumb-item>
                    </el-breadcrumb>
                </div>
                <!-- <el-button :icon="Refresh" @click="handleRestartDevice" type="primary" :loading="deviceRestartLoading">
                    设备重启
                </el-button> -->
            </div>

            <div class="filter" v-if="activePathList.length != 0">
                <el-input maxlength="32" show-word-limit style="width: 240px; height: 32px" placeholder="请输入文件或文件夹名称"
                    clearable v-model.trim="filterText" type="text"></el-input>
                <el-button type="primary" @click="handleSearch" :icon="Search">搜索</el-button>
                <!-- <el-button @click="handleRefresh" :icon="Refresh">重置</el-button> -->
                <el-upload v-if="activePath != '/'" action="" :auto-upload="false" :show-file-list="false" :on-change="(file: any, fileList: any) => {
                    handleUpload(file, fileList, activePath)
                }
                    ">
                    <el-button>
                        文件上传
                        <el-icon class="el-icon--right">
                            <Upload />
                        </el-icon>
                    </el-button>
                </el-upload>
                <el-button @click="handleAddNewDir" v-if="activePath != '/'" type="primary" :icon="Plus">
                    新建文件夹
                </el-button>
                <div class="upload_progress" v-if="status != 0 && status != 100 && changeType == 'upload'">
                    正在上传：{{ fileName }}
                    <el-progress :percentage="status" />
                </div>
            </div>
            <!-- 以列表形式展示 -->
            <div :style="tableHeight">
                <vxe-table style="margin-top: 10px" border auto-resize height="auto" :data="dirList"
                    v-bind="defaultAttribute">
                    <vxe-column type="seq" title="序号" width="80"></vxe-column>
                    <vxe-column field="prjDataPath" align="center" title="名称" minWidth="180" #default="{ row }">
                        <span style="cursor: pointer; color: #551a8b" :style="{
                            'text-decoration': row.type == 'dir' ? 'underline' : 'none',
                            color: row.type == 'dir' ? '#551a8b' : '#000'
                        }" @click="handleIntoDir(row)">
                            {{
                                row &&
                                    row?.prjDataPath &&
                                    row?.prjDataPath.includes(activePath) &&
                                    row?.prjDataPath.length > activePath.length
                                    ? row?.prjDataPath.replace(activePath, ' ').replace('/', ' ')
                                    : row?.prjDataPath.replace('/', ' ')
                            }}
                        </span>
                    </vxe-column>

                    <vxe-column field="startTime" align="center" title="文件时间" minWidth="140" #default="{ row }">
                        {{ row.startTime ? row.startTime : '/' }}
                    </vxe-column>
                    <vxe-column field="type" align="center" title="类型" minWidth="100" #default="{ row }">
                        <span>
                            {{ row.type == 'dir' ? '文件夹' : row.type == 'file' ? '文件' : '/' }}
                        </span>
                    </vxe-column>
                    <vxe-column field="size" align="center" minWidth="100" title="大小" #default="{ row }">
                        <span>
                            {{ row.size && row.type == 'file' ? row.size + 'KB' : '/' }}
                        </span>
                    </vxe-column>
                    <!--<vxe-column field="fileCheck" align="center" title="文件校验码" width="100" #default="{ row }">
                    {{ row.fileCheck ? row.fileCheck : '/' }}
                </vxe-column> -->
                    <vxe-column title="操作" width="120px" fixed="right">
                        <template #default="{ row }">
                            <el-button link size="small" type="danger" @click="handleDelDirOrFile(row)">删除</el-button>
                            <el-button v-if="row.type == 'file'" link size="small" type="primary" :loading="row.loading"
                                @click="handleDownLoad(row)">
                                下载
                            </el-button>
                        </template>
                    </vxe-column>
                </vxe-table>
            </div>

            <div class="list" v-if="dirList.length != 0 && !loading" style="display: none">
                <div class="list_item" v-for="(item, index) in dirList" :key="index">
                    <div class="item_download">
                        <el-button v-if="activePath && activePath != '/'" type="danger" size="small"
                            @click="handleDelDirOrFile(item)" circle>
                            <el-icon>
                                <Delete />
                            </el-icon>
                        </el-button>
                        <el-button v-if="item?.type == 'file'" size="small" @click="handleDownLoad(item)" circle>
                            <el-icon>
                                <Download />
                            </el-icon>
                        </el-button>
                    </div>
                    <img v-if="item?.type == 'dir'" @click="handleIntoDir(item)" src="@/assets/img/wenjianjia.svg" />
                    <img class="img_file" @click="handleIntoDir(item)" v-if="item?.type == 'file'"
                        src="@/assets/img/wenjian.svg" />
                    <!-- <span v-if="!item.type">暂无数据</span> -->
                    <p>
                        {{
                            item &&
                                item?.prjDataPath &&
                                item?.prjDataPath.includes(activePath) &&
                                item?.prjDataPath.length > activePath.length
                                ? item?.prjDataPath.replace(activePath, ' ').replace('/', ' ')
                                : item?.prjDataPath.replace('/', ' ')
                        }}
                    </p>
                </div>
            </div>
            <!-- <el-empty v-if="dirList.length === 0" /> -->
        </div>
        <popup ref="fileRef"></popup>
        <el-dialog v-model.trim="addDeviceDirOpen" draggable  :destroy-on-close="true" title="新建文件夹目录" width="500" @closed="close">
            <el-form ref="formRef" :model="form"
                :rules="{ path: [{ required: true, message: '请输入文件夹名称', trigger: 'blur' }] }">
                <el-form-item label="文件夹名称" prop="path">
                    <el-input maxlength="32" show-word-limit v-model.trim="form.path" placeholder="请输入文件夹名称" />
                </el-form-item>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="close">取消</el-button>
                    <el-button type="primary" @click="submitDeviceDir" :loading="loading1">确定</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import DeviceTree from '@/components/tree/govern/deviceTree.vue'
import { mainHeight } from '@/utils/layout'
import { ref, watch, onMounted, onBeforeUnmount, h, inject } from 'vue'
import { ElMessage, ElMessageBox, ElInput, ElSegmented } from 'element-plus'
import {
    getFileServiceFileOrDir,
    uploadDeviceFile,
    reStartDevice,
    addDeviceDir,
    delDeviceDir,
    listDir,
    downloadFileFromFrontr,
    deleteCld,
    uploadFileToFront,
    mkdir
} from '@/api/cs-device-boot/fileService'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { Delete, Download, Upload, Plus, Refresh, Search } from '@element-plus/icons-vue'
import popup from './popup.vue'
import mqtt from 'mqtt'
import { useAdminInfo } from '@/stores/adminInfo'
import { passwordConfirm } from '@/api/user-boot/user'
import { downLoadFile } from '@/utils/downloadFile.ts'
defineOptions({
    name: 'govern/device/fileService/index'
})
const pageHeight = mainHeight(20)
const tableHeight = mainHeight(130)
const adminInfo = useAdminInfo()
const loading = ref(false)
const loading1 = ref(false)
//nDid
const nDid = ref<string>('')
const devId = ref<string>('')
//当前目录
const activePath = ref<string>('')
//判断是否是根目录
const isRoot = ref<boolean>(true)
//储存所有点击过的目录
const activePathList: any = ref([])
const devConType = ref<string>('')
const deviceTypeChange = (val: any, obj: any) => {

    nodeClick(obj)
}
const nodeClick = (e: any) => {
    if (e && (e.level == 2 || e.level == 3 || e.type == 'device')) {
        loading.value = true
        nDid.value = e.ndid
        devId.value = e.id
        dirList.value = []
        activePathList.value = []
        activePath.value = '/'
        devConType.value = e.devConType
        if (devConType.value == 'CLD') {
            listDir({ devId: devId.value, filePath: activePath.value })
                .then((resp: any) => {
                    if (resp.code == 'A0000') {
                        dirList.value = resp.data
                        currentDirList.value = resp.data
                        activePathList.value = [{ path: activePath.value }]
                        loading.value = false
                    }
                })
                .catch(e => {
                    loading.value = false
                })
        } else {
            getFileServiceFileOrDir({ nDid: nDid.value, name: activePath.value, type: 'dir' })
                .then((resp: any) => {
                    if (resp.code == 'A0000') {
                        dirList.value = resp.data
                        currentDirList.value = resp.data
                        activePathList.value = [{ path: activePath.value }]
                        loading.value = false
                    }
                })
                .catch(e => {
                    loading.value = false
                })
        }
    }
}
//搜索文件或文件夹
const filterText = ref('')
const handleSearch = () => {
    let filterList: any = []
    dirList.value = currentDirList.value
    dirList.value.map(item => {
        if (filterText.value && item.prjDataPath.includes(filterText.value)) {
            filterList.push(item)
        }
    })
    if (filterList.length != 0) {
        dirList.value = filterList
    }
    if (filterList.length == 0) {
        dirList.value = []
    }
    if (!filterText.value) {
        dirList.value = currentDirList.value
    }
}
//重置搜索
const handleRefresh = () => {
    loading.value = true
    filterText.value = ''
    dirList.value = currentDirList.value
    reloadCurrentMenu('')
}

const reboot: any = ref('')
const vNode = () => {
    return h('div', {}, [
        h(ElInput, {
            modelValue: reboot.value,
            'onUpdate:modelValue': ($event: any) => {
                reboot.value = $event
            },
            placeholder: '请输入姓名',
            type: 'password',
            autocomplete: 'off',
            class: 'displayPass'
        })
    ])
}

//设备重启
const deviceRestartLoading = ref<boolean>(false)
const handleRestartDevice = () => {
    deviceRestartLoading.value = true
    ElMessageBox.prompt('二次校验密码确认', '设备重启', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        customClass: 'customInput',
        inputType: 'text',
        beforeClose: (action, instance, done) => {
            if (action === 'confirm') {
                if (instance.inputValue == null) {
                    return ElMessage.warning('请输入密码')
                } else if (instance.inputValue?.length > 32) {
                    return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
                } else {
                    done()
                }
            } else {
                done()
            }
        }
    })
        .then(({ value }) => {
            if (!value) {
                ElMessage.warning('请输入密码')
                loading.value = false
                deviceRestartLoading.value = false
            } else {
                passwordConfirm(value)
                    .then((resp: any) => {
                        if (resp.code == 'A0000') {
                            reStartDevice({ nDid: nDid.value }).then((res: any) => {
                                if (res.code == 'A0000') {
                                    deviceRestartLoading.value = false
                                    ElMessage({ message: res.message, type: 'success', duration: 5000 })
                                } else {
                                    deviceRestartLoading.value = false
                                }
                            })
                        }
                    })
                    .catch(e => {
                        loading.value = false
                        deviceRestartLoading.value = false
                    })
            }
        })
        .catch(() => {
            deviceRestartLoading.value = false
        })
}
// 进入文件夹
const dirList = ref([])
// 当前目录数据
const currentDirList = ref([])
const handleIntoDir = (row: any) => {
    if (!row.type || row.type == 'file') return
    loading.value = true
    const obj = {
        nDid: nDid.value,
        name: row.prjDataPath,
        type: row.type
    }
    //当前点击的目录
    activePath.value = row.prjDataPath
    if (activePathList.value.indexOf(obj.name) == -1) {
        activePathList.value.push({ path: obj.name })
    }

    if (devConType.value == 'CLD') {
        listDir({ devId: devId.value, filePath: row.prjDataPath })
            .then((resp: any) => {
                if (resp.code == 'A0000') {
                    dirList.value = resp.data
                    currentDirList.value = resp.data
                    activePathList.value.map((item: any, index: any) => {
                        if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                            activePathList.value.splice(index, 1)
                        }
                    })
                    loading.value = false
                }
            })
            .catch(e => {
                loading.value = false
            })
    } else {
        getFileServiceFileOrDir(obj)
            .then(res => {
                dirList.value = res.data
                loading.value = false
                currentDirList.value = res.data
                activePathList.value.map((item: any, index: any) => {
                    if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                        activePathList.value.splice(index, 1)
                    }
                })
                isRoot.value = false
            })
            .catch(e => {
                loading.value = false
            })
    }
}

//处理导航栏路径
const outPutPath = (row: any, key: any) => {
    let path = ''
    if (key == 0) {
        path = '/根目录'
    }
    if (key == 1) {
        path = row.path
    }
    if (key > 1) {
        if (row.path.includes(activePathList.value[1].path)) {
            path = row.path.replace(activePathList.value[1].path, ' ')
        }
        if (row.path.split('/').length !== 0) {
            path = '/' + row.path.split('/')[row.path.split('/').length - 1]
        }
    }
    return path.split('/')[1]
}

//根据面包屑导航切换
const handleIntoByPath = async (val: any) => {
    const obj = {
        nDid: nDid.value,
        name: val.path,
        type: 'dir'
    }
    activePath.value = val.path
    loading.value = true
    if (devConType.value == 'CLD') {
        listDir({ devId: devId.value, filePath: val.path })
            .then((resp: any) => {
                if (resp.code == 'A0000') {
                    dirList.value = resp.data

                    activePathList.value.map((item: any, index: any) => {
                        if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                            activePathList.value.splice(index, 1)
                        }
                    })
                    loading.value = false
                }
            })
            .catch(e => {
                loading.value = false
            })
    } else {
        getFileServiceFileOrDir(obj)
            .then(res => {
                dirList.value = res.data
                activePathList.value.map((item: any, index: any) => {
                    if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                        activePathList.value.splice(index, 1)
                    }
                })
                loading.value = false
            })
            .catch(e => {
                loading.value = false
            })
    }
}
const form = ref({
    path: ''
})
//新建文件夹弹框flag
const addDeviceDirOpen = ref<boolean>(false)
const close = () => {
    addDeviceDirOpen.value = false
}
//打开新建文件夹弹框
const handleAddNewDir = () => {
    form.value.path = ''
    addDeviceDirOpen.value = true
}
const formRef = ref()
//重新加载当前页面菜单
const reloadCurrentMenu = (msg: string) => {
    loading.value = true

    if (devConType.value == 'CLD') {
        listDir({ devId: devId.value, filePath: activePath.value })
            .then((resp: any) => {
                if (resp.code == 'A0000') {
                    dirList.value = resp.data
                    currentDirList.value = resp.data
                    activePathList.value.map((item: any, index: any) => {
                        if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                            activePathList.value.splice(index, 1)
                        }
                    })
                    loading.value = false
                    if (!msg) return
                    ElMessage({ message: msg, type: 'success', duration: 5000 })
                }
            })
            .catch(e => {
                loading.value = false
            })
    } else {
        getFileServiceFileOrDir({ nDid: nDid.value, name: activePath.value, type: 'dir' })
            .then((resp: any) => {
                if (resp.code == 'A0000') {
                    loading.value = false
                    dirList.value = resp.data
                    currentDirList.value = resp.data
                    activePathList.value.map((item: any, index: any) => {
                        if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                            activePathList.value.splice(index, 1)
                        }
                    })
                    loading.value = false

                    if (!msg) return
                    ElMessage({ message: msg, type: 'success', duration: 5000 })
                }
            })
            .catch(e => {
                loading.value = false
            })
    }
}
//新建文件夹
const submitDeviceDir = () => {
    formRef.value.validate((valid: any) => {
        if (valid) {
            loading1.value = true
            if (devConType.value == 'CLD') {
                let obj = {
                    devId: devId.value,
                    filePath:
                        activePath.value == '/'
                            ? activePath.value + form.value.path
                            : activePath.value + '/' + form.value.path
                }
                loading.value = true
                mkdir(obj).then((res: any) => {
                    if (res.code == 'A0000') {
                        reloadCurrentMenu(res.message)
                        addDeviceDirOpen.value = false
                    }
                }).finally(() => {
                    loading1.value = false
                })
            } else {
                let obj = {
                    nDid: nDid.value,
                    path:
                        activePath.value == '/'
                            ? activePath.value + form.value.path
                            : activePath.value + '/' + form.value.path
                }
                loading.value = true
                addDeviceDir(obj).then((res: any) => {
                    if (res.code == 'A0000') {
                        reloadCurrentMenu(res.message)
                        addDeviceDirOpen.value = false
                    }
                }).finally(() => {
                    loading1.value = false
                })
            }
        }
    })
}
//删除文件夹或文件
const handleDelDirOrFile = (row: any) => {
    ElMessageBox.prompt('二次校验密码确认', '', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        customClass: 'customInput',
        inputType: 'text',
        beforeClose: (action, instance, done) => {
            if (action === 'confirm') {
                if (instance.inputValue == null) {
                    return ElMessage.warning('请输入密码')
                } else if (instance.inputValue?.length > 32) {
                    return ElMessage.warning('密码长度不能超过32位,当前密码长度为' + instance.inputValue.length)
                } else {
                    done()
                }
            } else {
                done()
            }
        }
    }).then(({ value }) => {
        if (!value) {
            ElMessage.warning('请输入密码')
        } else {
            loading.value = true
            passwordConfirm(value)
                .then((resp: any) => {
                    if (resp.code == 'A0000') {
                        if (devConType.value == 'CLD') {
                            deleteCld({
                                devId: devId.value,
                                filePath: row.prjDataPath
                            })
                                .then((res: any) => {
                                    if (res.code == 'A0000') {
                                        reloadCurrentMenu(res.message)
                                    }
                                })
                                .catch(e => {
                                    loading.value = false
                                })
                        } else {
                            delDeviceDir({ nDid: nDid.value, path: row.prjDataPath })
                                .then((res: any) => {
                                    if (res.code == 'A0000') {
                                        reloadCurrentMenu(res.message)
                                    }
                                })
                                .catch(e => {
                                    loading.value = false
                                })
                        }
                    }
                })
                .catch(e => {
                    loading.value = false
                })
        }
    })
}
const changeType = ref<any>('')
//下载文件
const fileRef = ref()
const handleDownLoad = async (row: any) => {
    if (devConType.value == 'CLD') {
        row.loading = true
        ElMessage.info('下载中，请稍等...')
        downloadFileFromFrontr({
            devId: devId.value,
            filePath: row.prjDataPath
        }).then(res => {
            downLoadFile(row.name, row.name, res)
            row.loading = false
        }).catch(e => {
            row.loading = false
        })
    } else {
        ; (await nDid.value) && fileRef.value && fileRef.value.open(row, nDid.value)
        // fileName.value = row?.prjDataPath.split('/')[row?.prjDataPath.split('/').length - 1]
        // localStorage.setItem('fileName', fileName.value)
        changeType.value = 'download'
        localStorage.setItem('changeType', changeType.value)
    }
}
//上传文件
const fileName = ref<any>('')
const handleUpload = (e: any, fileList: any, row: any) => {
    // loading.value=true
    fileName.value = e.name
    localStorage.setItem('fileName', fileName.value)
    changeType.value = 'upload'
    localStorage.setItem('changeType', changeType.value)

    if (devConType.value == 'CLD') {
        const obj = {
            devId: devId.value,
            file: e.raw,
            dirPath: row || row.prjDataPath
        }
        uploadFileToFront(obj).then((res: any) => {
            if (res.code == 'A0000') {
                reloadCurrentMenu(res.message)
                status.value = 100
            }
        })
    } else {
        const obj = {
            id: nDid.value,
            file: e.raw,
            filePath: row || row.prjDataPath
        }
        uploadDeviceFile(obj).then((res: any) => {
            if (res.code == 'A0000') {
                reloadCurrentMenu(res.message)
                status.value = 100
            }
        })
    }
}
watch(
    () => activePathList.value,
    async (val, oldVal) => {
        if (val) {
            val.map((item: any, index: any) => {
                if (item.path.includes(activePath.value) && item.path.length > activePath.value.length) {
                    val.splice(index, 1)
                }
            })
        }
    },
    {
        immediate: true,
        deep: true
    }
)
const mqttRef = ref()
const url: any = window.localStorage.getItem('MQTTURL')
const connectMqtt = () => {
    if (mqttRef.value) {
        if (mqttRef.value.connected) {
            return
        }
    }
    const options = {
        protocolId: 'MQTT',
        qos: 2,
        clean: true,
        connectTimeout: 30 * 1000,
        clientId: 'mqttjs' + Math.random(),
        username: 't_user',
        password: 'njcnpqs'
    }
    mqttRef.value = mqtt.connect(url, options)
}
connectMqtt()
mqttRef.value.on('connect', (e: any) => {
    // ElMessage.success('连接mqtt服务器成功!')
    console.log('mqtt客户端已连接....')
    // mqttRef.value.subscribe('/Web/Progress')
    mqttRef.value.subscribe('/Web/Progress/+')
})
const mqttMessage = ref<any>({})
const status: any = ref()
function parseStringToObject(str: string) {
    const content = str.replace(/^{|}$/g, '')
    const result: any = {}

    // 正则匹配：key:value 格式，支持 value 里带 : / 等字符
    const regex = /([^,:]+):([^,]+)(?=,|$)/g
    let match

    while ((match = regex.exec(content)) !== null) {
        const key = match[1].trim()
        const value = match[2].trim()
        // 数字自动转 Number
        result[key] = isNaN(Number(value)) ? value : Number(value)
    }

    return result
}
mqttRef.value.on('message', (topic: any, message: any) => {
    // console.log('mqtt接收到消息', JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message)))))

    let str = JSON.parse(JSON.stringify(JSON.parse(new TextDecoder().decode(message))))
    mqttMessage.value = parseStringToObject(str)
    if (adminInfo.id != mqttMessage.value.userId) return

    // console.log("🚀 ~ str.match(regex3)[1]:", str.match(regex3)[1])
    status.value = parseInt(Number((mqttMessage.value.nowStep / mqttMessage.value.allStep) * 100))
    fileRef.value.setStatus(mqttMessage.value)
    fileName.value = mqttMessage.value.fileName
    localStorage.setItem('fileName', fileName.value)
    if (status.value == 100) {
        status.value = 99
    }
})

mqttRef.value.on('error', (error: any) => {
    console.log('mqtt连接失败...', error)
    mqttRef.value.end()
})

mqttRef.value.on('close', function () {
    console.log('mqtt客户端已断开连接.....')
})
onMounted(() => {
    status.value = 0
    fileName.value = localStorage.getItem('fileName') ? localStorage.getItem('fileName') : ''
    changeType.value = localStorage.getItem('changeType') ? localStorage.getItem('changeType') : ''
})
onBeforeUnmount(() => {
    if (mqttRef.value) {
        mqttRef.value.end()
    }
})
</script>

<style lang="scss" scoped>
.main {
    display: flex;
    justify-content: space-between;
    padding-bottom: 10px;

    .main_left {
        // width: 280px;
    }

    .main_right {
        overflow: hidden;
        flex: 1;
        padding: 10px 10px 10px 10px;
        //margin-left: 10px;
        border: 1px solid #eee;

        .el-input__wrapper {
            -webkit-text-security: disc !important;
        }

        .right_nav {
            width: 100%;
            height: 32px;
            display: flex;
            justify-content: space-between;
            align-items: center;

            .menu {
                width: 100%;
                height: 100%;
                display: flex;
                justify-content: flex-start;
                overflow-x: auto;
                align-items: center;
                background-color: var(--el-color-primary);
                border-radius: 4px;

                span {
                    font-size: 14px;
                    font-weight: 800;
                    padding: 0 5px;
                    color: #fff;
                    cursor: pointer;
                }
            }

            .el-button {
                margin: 0 10px;
            }
        }

        .filter {
            width: 100%;
            height: 30px;
            display: flex;
            margin-top: 10px;
            justify-content: flex-start;

            .el-button {
                margin-left: 10px;
            }

            .upload_progress {
                flex: 1;
                height: 30px;
                display: flex;
                align-items: center;
                justify-content: flex-start;
                margin-left: 10px;

                .el-progress {
                    width: 300px;
                    margin-left: 10px;
                }
            }
        }

        .list {
            // display: flex;
            // flex-wrap: wrap;
            // align-items: flex-start;
            // justify-content: space-between;
            overflow-y: auto;
            margin-top: 10px;
            max-height: 100%;
            padding-bottom: 200px;
            z-index: 100;
            position: relative;

            .list_item {
                flex: none;
                width: 23.3%;
                height: 100px;
                border: 1px solid var(--el-color-primary);
                margin: 10px 0.5%;
                display: flex;
                align-items: center;
                flex-direction: column;
                justify-content: center;
                // border-radius: 6px;
                cursor: pointer;
                position: relative;
                z-index: 1001 !important;
                width: 100%;
                height: 40px;
                margin: 0;
                border: 1px solid #eee;

                .item_download,
                .item_upload {
                    position: absolute;
                    top: 10px;
                    right: 10px;
                    z-index: 2001;
                }

                .img_file {
                    // width: 60px;
                    // height: 60px;
                    width: 30px;
                    height: 30px;
                }

                img {
                    // width: 50px;
                    // height: 50px;
                    width: 30px;
                    height: 30px;
                    cursor: pointer !important;
                }

                p {
                    margin-top: 10px;
                }
            }

            .list_item:nth-child(4n + 2),
            .list_item:nth-child(4n + 3) {
                // margin: 10px 0.8%;
            }
        }
    }
}

.el-form {
    padding: 20px 10px;
    box-sizing: border-box;
}

:deep(.el-breadcrumb__separator) {
    margin: 0px -10px 0px 0px;
}
</style>
<style lang="scss">
.customInput {
    .el-input__inner {
        -webkit-text-security: disc !important;
    }
}
</style>
