iZaiZaiA 2 years ago
parent
commit
8b39cf7563

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
         "moment": "^2.29.4",
         "naive-ui": "^2.32.2",
         "pinia": "^2.0.20",
+        "remixicon": "^2.5.0",
         "vue": "^3.2.37",
         "vue-router": "^4.1.4",
         "vue-utils-plus": "^1.0.2",

+ 155 - 0
src/global/components/hc-table/index.vue

@@ -0,0 +1,155 @@
+<template>
+    <div class="hc-table-ref-box" :class="ui">
+        <el-table ref="tableRef" hc :data="tableData" height="100%" :loading="isLoading" stripe @selection-change="tableSelectionChange"
+                  @row-click="tableRowClick" @row-dblclick="tableRowDblClick" @row-contextmenu="tableRowContextmenu"
+                  @cell-click="tableCellClick" @cell-dblclick="tableCellDblClick" @cell-contextmenu="tableCellContextmenu">
+            <el-table-column type="selection" width="50" v-if="isCheck"/>
+            <el-table-column type="index" prop="num" label="序号" width="80" v-if="isIndex"/>
+            <template v-for="item in columns">
+                <el-table-column :prop="item.key" :label="item.name" :align="item.align ?? 'left'" :width="item.width ?? ''">
+                    <template #default="scope" v-if="item.isSlot">
+                        <slot :name='item.key' :row="scope.row" :index="scope.$index"></slot>
+                    </template>
+                </el-table-column>
+            </template>
+        </el-table>
+    </div>
+</template>
+
+<script setup>
+import {ref,watch,nextTick,useSlots} from "vue";
+const props = defineProps({
+    ui: {
+        type: String,
+        default: ''
+    },
+    column: {
+        type: Array,
+        default: () => ([])
+    },
+    datas: {
+        type: Array,
+        default: () => ([])
+    },
+    loading: {
+        type: Boolean,
+        default: false
+    },
+    isCheck: {
+        type: Boolean,
+        default: false
+    },
+    isIndex: {
+        type: Boolean,
+        default: true
+    },
+})
+
+//初始变量
+const tableRef = ref(null)
+const columns = ref(props.column)
+const tableData = ref(props.datas)
+const isLoading = ref(props.loading)
+
+//监听
+watch(() => [
+    props.datas,
+    props.loading
+], ([datas, loading]) => {
+    tableData.value = datas;
+    isLoading.value = loading;
+})
+
+//监听表头
+watch(() => [
+    props.column
+], ([column]) => {
+    columns.value = column;
+    setIsSlots()
+})
+
+//加载完成
+nextTick(()=>{
+    setIsSlots()
+})
+
+//判断<slot>是否有传值
+const slots = useSlots()
+const setIsSlots = () => {
+    let arr = columns.value
+    for (let i = 0; i < arr.length; i++) {
+        arr[i].isSlot = !!slots[arr[i].key]
+    }
+    columns.value = arr
+}
+
+//事件
+const emit = defineEmits([
+    'selection-change',
+    'row-click', 'row-dblclick', 'row-contextmenu',
+    'cell-click', 'cell-dblclick', 'cell-contextmenu'
+])
+
+//清空多选
+const clearSelection = () => {
+    tableRef.value?.clearSelection()
+    emit('selection-change', [])
+}
+//返回当前选中的行
+const getSelectionRows = () => {
+    tableRef.value?.getSelectionRows()
+}
+
+//多选
+const tableSelectionChange = (rows) => {
+    let tableRows = rows.filter((item) => {
+        return (item??'') !== '';
+    })
+    emit('selection-change', tableRows)
+}
+
+//当某一行被点击时会触发该事件
+const tableRowClick = (row, column, event) => {
+    emit('row-click', {row, column, event})
+}
+
+//当某一行被双击时会触发该事件
+const tableRowDblClick = (row, column, event) => {
+    emit('row-dblclick', {row, column, event})
+}
+
+//当某一行被鼠标右键点击时会触发该事件
+const tableRowContextmenu = (row, column, event) => {
+    emit('row-contextmenu', {row, column, event})
+}
+
+//当某个单元格被点击时会触发该事件
+const tableCellClick = (row, column, cell, event) => {
+    emit('cell-click', {row, column, cell, event})
+}
+
+//当某个单元格被双击击时会触发该事件
+const tableCellDblClick = (row, column, cell, event) => {
+    emit('cell-dblclick', {row, column, cell, event})
+}
+
+//当某个单元格被鼠标右键点击时会触发该事件
+const tableCellContextmenu = (row, column, cell, event) => {
+    emit('cell-contextmenu', {row, column, cell, event})
+}
+
+// 暴露出去
+defineExpose({
+    clearSelection,
+    getSelectionRows
+})
+</script>
+
+<style lang="scss">
+.hc-table-ref-box {
+    height: 100%;
+    .el-scrollbar .el-scrollbar__bar.is-vertical {
+        right: 0;
+    }
+}
+</style>

+ 53 - 10
src/global/components/hc-uploads/index.vue

@@ -1,6 +1,6 @@
 <template>
     <div class="hc-uploads-box" v-loading="spinShow">
-        <el-upload ref="uploadRef" :file-list="fileListData" :action="action" :headers="getTokenHeader()" :data="uploadData" :limit="limit" :accept="accept"
+        <el-upload ref="uploadRef" v-model:file-list="fileListData" :action="api + action" :headers="getTokenHeader()" :data="uploadData" :limit="limit" :accept="accept"
                    list-type="picture-card" :multiple="limit > 1"  :disabled="uploadDisabled" :on-preview="uploadPreview"
                    :on-success="uploadSuccess" :on-exceed="uploadExceed" :on-error="uploadError"
                    :before-upload="beforeUpload" :on-progress="uploadprogress" :on-remove="uploadRemove">
@@ -13,7 +13,7 @@
 <script setup>
 import {ref,watch,onMounted} from "vue";
 import {getTokenHeader} from '~src/api/request/header';
-import {getIndex, isSize} from "vue-utils-plus"
+import {getIndex, getObjValue, getObjNullValue, isSize} from "vue-utils-plus"
 import {genFileId} from "element-plus";
 
 const props = defineProps({
@@ -25,9 +25,13 @@ const props = defineProps({
         type: Object,
         default: () => ({})
     },
+    api: {
+        type: String,
+        default: "/api/blade-resource/oss/endpoint/"
+    },
     action: {
         type: String,
-        default: "/api/blade-resource/oss/endpoint/put-file"
+        default: "put-file"
     },
     accept: {
         type: String,
@@ -74,7 +78,7 @@ const showViewerClose = () => {
 }
 
 //事件
-const emit = defineEmits(['change', 'del', 'preview'])
+const emit = defineEmits(['change', 'progress', 'del', 'preview'])
 
 //上传前
 const spinShow = ref(false)
@@ -106,6 +110,7 @@ const uploadExceed = (files) => {
 //上传中
 const uploadprogress = () => {
     uploadDisabled.value = true
+    emit('progress', true)
 }
 
 //上传完成
@@ -113,9 +118,11 @@ const finishFileNum = ref(0)
 const uploadSuccess = (response,uploadFile,uploadFiles) => {
     finishFileNum.value ++;
     if (beforeFileNum.value === finishFileNum.value) {
+        let fileList = getUploadFileList(uploadFiles)
         spinShow.value = false
         uploadDisabled.value = false
-        emit('change', {type: 'success', fileList: uploadFiles})
+        emit('change', {type: 'success', fileList})
+        emit('progress', false)
     }
 }
 
@@ -126,14 +133,32 @@ const uploadError = () => {
     window?.$message?.error('上传失败');
     const num = finishFileNum.value + errorFileNum.value;
     if (beforeFileNum.value === num) {
-        const fileList = fileListData.value ?? [];
+        let fileList = getUploadFileList(fileListData.value)
         spinShow.value = false
         uploadDisabled.value = false
-        console.log(fileList)
-        emit('change', {type: 'error', fileList: fileListData.value})
+        emit('change', {type: 'error', fileList})
+        emit('progress', false)
     }
 }
 
+//获取文件URL
+const getUploadFileList = (fileListArr) => {
+    let fileArr = [], fileList = fileListArr ??[];
+    fileList.forEach(item => {
+        if (getObjNullValue(item?.response)) {
+            const data = getObjValue(item?.response?.data)
+            fileArr.push({
+                ...data,
+                url: data['link'],
+                name: data['originalName']
+            })
+        } else {
+            fileArr.push(item)
+        }
+    })
+    return fileArr
+}
+
 //预览
 const showViewer = ref(false)
 const initialIndex = ref(-1)
@@ -155,13 +180,31 @@ const uploadPreview = (file) => {
 const getUploadFileUrl = () => {
     let fileArr = [], fileList = fileListData.value ?? [];
     fileList.forEach(item => {
-        fileArr.push(item?.response?.data?.link)
+        if (getObjNullValue(item?.response)) {
+            fileArr.push(item?.response?.data?.link)
+        } else {
+            fileArr.push(item?.url)
+        }
     })
     return fileArr
 }
 
 //删除文件
 const uploadRemove = (row) => {
-    emit('del', {row, fileList: fileListData.value})
+    let link;
+    if (getObjNullValue(row?.response)) {
+        link = row?.response?.data?.link
+    } else {
+        link = row?.url
+    }
+    emit('del', {link, row, fileList: fileListData.value})
 }
 </script>
+
+<style lang="scss">
+.hc-uploads-box .el-upload-list .el-upload-list__item {
+    .el-upload-list__item-status-label, .el-icon--close-tip {
+        display: none;
+    }
+}
+</style>

+ 2 - 0
src/global/components/index.js

@@ -1,6 +1,7 @@
 import HcImg from './hc-img/index.vue'
 import HcIcon from './hc-icon/index.vue'
 import HcCard from './hc-card/index.vue'
+import HcTable from './hc-table/index.vue'
 import HcPages from './hc-page/index.vue'
 import HcDrawer from './hc-drawer/index.vue'
 import HcUploads from './hc-uploads/index.vue'
@@ -18,6 +19,7 @@ export const setupComponents = (App) => {
     App.component('HcImg', HcImg)
     App.component('HcIcon', HcIcon)
     App.component('HcCard', HcCard)
+    App.component('HcTable', HcTable)
     App.component('HcPages', HcPages)
     App.component('HcDrawer', HcDrawer)
     App.component('HcUploads', HcUploads)

+ 1 - 0
src/main.js

@@ -16,6 +16,7 @@ import { setupComponents } from './global/index'
 //导入其它样式
 import "./styles/icon/index.scss"
 import "./styles/font/index.scss"
+import 'remixicon/fonts/remixicon.css'
 import "./styles/index.scss"
 
 //创建实例

+ 1 - 1
src/styles/other-file/image-form.scss

@@ -7,6 +7,7 @@
         position: relative;
         background: #f1f5f8;
         border-radius: 10px;
+        margin-right: 24px;
         box-shadow: -2px 0 10px 0 rgba(32,37,50,0.03), 0 10px 21px 20px rgba(32,37,50,0.03);
         .horizontal-drag-line {
             position: absolute;
@@ -50,6 +51,5 @@
     .hc-layout-content-box {
         flex: 1;
         position: relative;
-        margin-left: 24px;
     }
 }

+ 289 - 43
src/views/other-file/image-form.vue

@@ -18,40 +18,75 @@
             <!--左右拖动-->
             <div class="horizontal-drag-line" @mousedown="onmousedown"/>
         </div>
-        <div class="hc-layout-content-box">
+        <div class="hc-layout-content-box" v-loading="queryByLoading" element-loading-text="获取数据中...">
             <HcCard :title="`上传${fileType === 1 ? '视频' : fileType === 2 ? '图片' : ''}`" :scrollbar="false" actionSize="lg">
-                <el-scrollbar>
-                    <div class="hc-form-box w-750">
-                        <el-form ref="formRef" :model="formValue" :rules="rules" label-width="auto" size="large">
-                            <el-form-item label="上传日期" prop="uploadTime">
-                                <el-date-picker v-model="formValue.uploadTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"/>
-                            </el-form-item>
-                            <el-form-item label="上传文件" prop="imageUrl">
-                                <div class="w-full">
-                                    <HcUploads :fileList="uploadFileList" :accept="fileType === 1 ? videoAccept : fileType === 2 ? imageAccept : null"
-                                               :limit="fileType === 2 ? 10 : 1" :size="fileType === 2 ? 30 : 500" :viewer="false" @change="uploadsChange"
-                                               @del="uploadsDel" @preview="uploadsPreview"/>
+                <el-row class="hc-form-row-box" :gutter="20">
+                    <el-col :span="10">
+                        <el-scrollbar>
+                            <el-form ref="formRef" :model="formValue" :rules="rules" label-width="auto" size="large">
+                                <el-form-item label="上传日期" prop="uploadTime">
+                                    <el-date-picker v-model="formValue.uploadTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"/>
+                                </el-form-item>
+                                <el-form-item label="上传文件" prop="imageUrl">
+                                    <div class="w-full">
+                                        <HcUploads :fileList="uploadFileList" :accept="fileType === 1 ? videoAccept : fileType === 2 ? imageAccept : null" action="upload-file"
+                                                   :limit="fileType === 2 ? 10 : 1" :size="fileType === 2 ? 30 : 500" :viewer="false" @change="uploadsChange" @progress="uploadsProgress"
+                                                   @del="uploadsDel" @preview="uploadsPreview"/>
+                                    </div>
+                                    <el-image-viewer v-if="previewModal && fileType === 2" :initial-index="initialIndex" :url-list="previewFileList" @close="previewModalClose"/>
+                                    <el-dialog v-model="previewVideoModal" width="62rem" destroy-on-close :before-close="previewModalClose">
+                                        <video class="preview-video" :src="previewVideoUrl" controls="controls" autoplay="autoplay">
+                                            您的浏览器不支持 video
+                                        </video>
+                                    </el-dialog>
+                                    <el-alert title="请上传MP4、MOV格式的视频文件,文件大小不超过500M,只能上传1个视频文件" type="error" :closable="false" v-if="fileType === 1"/>
+                                    <el-alert title="请上传JPG/JPEG、PNG格式的图片文件,文件大小不超过30M,最多10张图片文件" type="error" :closable="false" v-if="fileType === 2"/>
+                                </el-form-item>
+                                <el-form-item label="题名" prop="title">
+                                    <el-input v-model="formValue.title" placeholder="请输入题名"/>
+                                </el-form-item>
+                                <div class="flex">
+                                    <el-form-item class="flex-1" :class="fileType === 2?'mr-4':''" prop="shootingUser" label="拍摄者">
+                                        <el-input v-model="formValue.shootingUser" placeholder="请输入拍摄者"/>
+                                    </el-form-item>
+                                    <el-form-item class="flex-1 ml-4" prop="photoCode" label="拍摄者" v-if="fileType === 2">
+                                        <el-input v-model="formValue.photoCode" placeholder="请输入照片号"/>
+                                    </el-form-item>
                                 </div>
-                            </el-form-item>
-                            <el-form-item label="题名" prop="title">
-                                <el-input v-model="formValue.title" placeholder="请输入题名"/>
-                            </el-form-item>
-                        </el-form>
-                    </div>
-                </el-scrollbar>
+                                <el-form-item label="拍摄时间" prop="shootingTimeStr">
+                                    <el-date-picker v-model="formValue.shootingTimeStr" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"/>
+                                </el-form-item>
+                                <div class="flex" v-if="fileType === 2">
+                                    <el-form-item class="flex-1 mr-4" prop="filmCode" label="底片号">
+                                        <el-input v-model="formValue.filmCode" placeholder="请输入底片号"/>
+                                    </el-form-item>
+                                    <el-form-item class="flex-1 ml-4" prop="seeAlsoCode" label="参见号">
+                                        <el-input v-model="formValue.seeAlsoCode" placeholder="请输入参见号"/>
+                                    </el-form-item>
+                                </div>
+                                <el-form-item label="文字说明" prop="textContent">
+                                    <el-input type="textarea" v-model="formValue.textContent" placeholder="请输入文字说明" :autosize="{ minRows: 3, maxRows: 5 }"/>
+                                </el-form-item>
+                            </el-form>
+                        </el-scrollbar>
+                    </el-col>
+                    <el-col :span="14">
+                        <HcTable :column="tableColumn" :datas="tableData"/>
+                    </el-col>
+                </el-row>
                 <template #action>
-                    <HcTooltip keys="image-data-add">
-                        <el-button type="primary" hc-btn>
-                            <HcIcon name="save"/>
-                            <span>保存</span>
-                        </el-button>
-                    </HcTooltip>
-                    <HcTooltip keys="image-data-download">
-                        <el-button hc-btn>
-                            <HcIcon name="undo"/>
-                            <span>返回</span>
-                        </el-button>
-                    </HcTooltip>
+                    <el-button type="primary" :disabled="uploadsLoading" hc-btn :loading="saveLoading" @click="saveClick">
+                        <HcIcon name="save"/>
+                        <span>保存</span>
+                    </el-button>
+                    <el-button hc-btn :disabled="uploadsLoading" :loading="saveLoading" v-if="dataType === 2" @click="saveLogClick">
+                        <HcIcon name="save"/>
+                        <span>保存并再次添加</span>
+                    </el-button>
+                    <el-button hc-btn @click="toBackClick">
+                        <HcIcon name="undo"/>
+                        <span>返回</span>
+                    </el-button>
                 </template>
             </HcCard>
         </div>
@@ -65,7 +100,8 @@ import {useRouter, useRoute} from 'vue-router'
 import WbsTree from "./components/WbsTree.vue"
 import imageApi from '~api/other-file/imageData';
 import {getStoreData, setStoreData} from '~src/utils/storage'
-import {getArrValue,getObjNullValue} from "vue-utils-plus"
+import {formValidate, getObjValue, getRandom, deepClone, dateFormat} from "vue-utils-plus"
+import ossApi from "~api/oss";
 
 //变量
 const router = useRouter()
@@ -80,8 +116,11 @@ const isCollapse = ref(useAppState.getCollapse)
 const routerQuery = useRoutes?.query;
 //存储目录格式 1按部位存储,2按日期存储
 const dataId = routerQuery?.id || '';
-const dataType = parseInt(routerQuery?.type + '') || 1;
+const wbsNodeIds = routerQuery?.wbsId || '';
+const classifyId = routerQuery?.classifyId || '';
+const dataType = parseInt(routerQuery?.dataType + '') || 1;
 const fileType = parseInt(routerQuery?.fileType + '') || 2;
+const toDayDate = dateFormat(new Date(), 'yyyy-MM-dd')
 
 //监听
 watch(() => [
@@ -95,9 +134,23 @@ const TreeAutoExpandKeys = ref(getStoreData('TreeExpandKeys') || [])
 
 //渲染完成
 onMounted(() => {
-
+    queryById()
 })
 
+//详情
+const queryByLoading = ref(false)
+const queryById = async () => {
+    if (dataId) {
+        queryByLoading.value = true
+        const {error, code, data} = await imageApi.queryById({id: dataId})
+        //判断状态
+        queryByLoading.value = false
+        if (!error && code === 200) {
+            formDataFormat(getObjValue(data))
+        }
+    }
+}
+
 //项目树被点击
 const nodeWbsElTreeClick = () => {
 
@@ -105,7 +158,12 @@ const nodeWbsElTreeClick = () => {
 
 //表单相关数据
 const formRef = ref(null)
-const formValue = ref({})
+const formValue = ref({
+    uploadTime: toDayDate,
+    shootingTimeStr: toDayDate,
+    filmCode: '',
+    seeAlsoCode: ''
+})
 const rules = {
     uploadTime: {
         required: true,
@@ -143,25 +201,198 @@ const rules = {
     },
 }
 
+//表单默认数据
+const formDataFormat = (info) => {
+    //表单数据
+    formValue.value = {
+        ...info,
+        type: fileType || '2',
+        wbsId: info?.wbsId || wbsNodeIds,
+        classifyId: info?.classifyId || classifyId,
+        projectId: info?.projectId || projectId.value,
+        contractId: info?.contractId || contractId.value,
+    }
+    //原始文件地址
+    let imageUrl = info['imageUrl'] || '';
+    let imageUrlArr = imageUrl ? imageUrl.split(',') : []
+    //PDF地址
+    let pdfUrl = info['pdfUrl'] || '';
+    let pdfUrlArr = pdfUrl ? pdfUrl.split(',') : []
+    //处理数据
+    if (imageUrlArr.length > 0) {
+        //状态处理
+        let InfoPdfUrl = pdfUrlArr.length === imageUrlArr.length;
+        //遍历数据
+        for (let i = 0; i < imageUrlArr.length; i++) {
+            let item = imageUrlArr[i];
+            uploadFileList.value.push({
+                name: getRandom(),
+                url: item,
+                page: '',
+                pdfUrl: InfoPdfUrl ? pdfUrlArr[i] : ''
+            })
+        }
+    } else {
+        uploadFileList.value = []
+    }
+}
+
 //上传组件参数
-const action = '/api/blade-resource/oss/endpoint/upload-file';
 const imageAccept = 'image/png,image/jpg,image/jpeg';
 const videoAccept = 'video/*';
+
 //上传文件的相关数据
 const previewFileList = ref([])
 const uploadFileList = ref([])
+
 //上传的文件结果
-const uploadsChange = ({ type, fileList}) => {
-    console.log(type, fileList)
+const uploadsChange = ({ fileList}) => {
+    uploadFileList.value = fileList
+}
+
+//上传进度
+const uploadsLoading = ref(false)
+const uploadsProgress = (val) => {
+    uploadsLoading.value = val
 }
+
 //预览上传的文件
-const uploadsPreview = ({ index, fileArr, fileList}) => {
-    console.log(index, fileArr, fileList)
+const previewModal = ref(false)
+const previewVideoModal = ref(false)
+const initialIndex = ref(-1)
+const previewVideoUrl = ref('')
+const uploadsPreview = ({ index, fileArr}) => {
+    if (fileType === 2) {
+        previewFileList.value = fileArr
+        initialIndex.value = index
+        previewModal.value = true
+    } else if (fileType === 1) {
+        previewVideoUrl.value = fileArr[index]
+        previewVideoModal.value = true
+    }
+}
+
+//预览关闭
+const previewModalClose = () => {
+    initialIndex.value = -1
+    previewModal.value = false
+    previewVideoModal.value = false
 }
 
 //删除上传的文件
-const uploadsDel = ({ row, fileList}) => {
-    console.log(row, fileList)
+const uploadsDel = async ({link}) => {
+    const arrUrl = link.split(".com//");
+    if (arrUrl.length > 0) {
+        await ossApi.removeFile({fileName: arrUrl[1]},false)
+    }
+}
+
+//上传记录表格
+const tableColumn = ref([
+    {name: '上传日期', key: 'uploadTime'},
+    {name: '题名', key: 'title'},
+    {name: '拍摄者', key: 'shootingUser'},
+    {name: '拍摄时间', key: 'shootingTimeStr'}
+])
+const tableData = ref([])
+
+//保存
+const saveLoading = ref(false)
+const saveClick = () => {
+    verifyFormData(false)
+}
+
+//保存并添加记录
+const saveLogClick = () => {
+    verifyFormData(true)
+}
+
+//表单效验
+const shootingTimeStr = ref('')
+const verifyFormData = async (log) => {
+    const formData = formValue.value;
+    const fileList = uploadFileList.value;
+    //处理文件
+    let imageUrl = '', pdfUrl = '';
+    if (fileList.length > 0) {
+        imageUrl = rowsToKey(fileList,'url')
+        pdfUrl = rowsToKey(fileList,'pdfUrl')
+    }
+    //设置数据
+    formData.imageUrl = imageUrl
+    formData.pdfUrl = pdfUrl
+    shootingTimeStr.value = formData['shootingTimeStr'] || ''
+    //验证数据
+    if (!formData?.wbsId && dataType === 1) {
+        window.$message?.warning('请先选择节点')
+    } else {
+        const res = await formValidate(formRef.value)
+        if (res) {
+            if (formData?.id) {
+                updateImageclassifyFile(formData,log)
+            } else {
+                addImageclassifyFile(formData,log)
+            }
+        } else {
+            window.$message?.warning('请先完善表单')
+        }
+    }
+}
+
+//新增资料
+const addImageclassifyFile = async (formData,log) => {
+
+}
+
+//修改资料
+const updateImageclassifyFile = async (formData,log) => {
+    saveLoading.value = true
+    const {error, code} = await imageApi.updateImageclassifyFile(formData)
+    //判断状态
+    saveLoading.value = false
+    if (!error && code === 200) {
+        if (log) {
+            tableData.value.push(deepClone(formValue.value))
+            formDataFormat({})
+        } else {
+            toBackClick()
+        }
+    }
+}
+
+//拼接字段
+const rowsToKey = (rows,key) => {
+    return rows.map((obj) => {
+        return obj[key];
+    }).join(",")
+}
+
+//处理data类型的自动展开
+const dataNodeExpandKeys = () => {
+    let TimeStr = shootingTimeStr.value || ''
+    let TimeArr = TimeStr.split('-')
+    if (TimeStr && TimeArr.length > 0) {
+        let timeKey = TimeArr[0] + '-' + TimeArr[1];
+        setStoreData('TreeExpandedKeys', [timeKey])
+    }
+}
+
+//返回上页
+const toBackClick = () => {
+    if (dataType === 1) {
+        //NodeExpandKeys()
+    } else if (dataType === 2) {
+        dataNodeExpandKeys()
+    }
+    //返回上级
+    router.push({
+        path: '/other-file/image-view',
+        query: {
+            fileType: fileType,
+            type: dataType,
+            id: classifyId,
+        }
+    })
 }
 
 //左右拖动,改变树形结构宽度
@@ -186,5 +417,20 @@ const onmousedown = () => {
 </style>
 
 <style lang="scss">
-
+.hc-form-row-box {
+    height: 100%;
+    .el-col {
+        height: 100%;
+        .el-date-editor {
+            --el-date-editor-width: 100%;
+            .el-input__wrapper {
+                width: 100%;
+            }
+        }
+        .el-alert {
+            margin-top: 14px;
+            --el-alert-padding: 0px 16px;
+        }
+    }
+}
 </style>

+ 95 - 74
src/views/other-file/image-view.vue

@@ -29,19 +29,19 @@
             <HcCard :scrollbar="false" actionSize="lg">
                 <template #header>
                     <HcTooltip keys="image-data-add">
-                        <el-button type="primary" hc-btn :disabled="!queryKey" @click="addFormFile">
+                        <el-button type="primary" hc-btn :disabled="!queryKey && fileType === 1" @click="addFormFile">
                             <HcIcon name="add_box"/>
                             <span>新增文件</span>
                         </el-button>
                     </HcTooltip>
                     <HcTooltip keys="image-data-download">
-                        <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="downloadClick">
+                        <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="downloadLoading" @click="downloadClick">
                             <HcIcon name="download"/>
                             <span>下载</span>
                         </el-button>
                     </HcTooltip>
                     <HcTooltip keys="image-data-del">
-                        <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" @click="delClick">
+                        <el-button hc-btn :disabled="tableCheckedKeys.length <= 0" :loading="delLoading" @click="delClick">
                             <HcIcon name="delete"/>
                             <span>删除</span>
                         </el-button>
@@ -55,49 +55,34 @@
                         <el-button type="primary" size="large" @click="searchClick">搜索</el-button>
                     </div>
                 </template>
-                <el-scrollbar>
-                    <div class="hc-table-ref-box">
-                        <el-table ref="tableListRef" hc :data="tableListData" :loading="tableLoading" stripe @selection-change="tableSelectionChange">
-                            <el-table-column type="selection" width="50" />
-                            <el-table-column prop="num" label="序号" width="80">
-                                <template #default="scope">
-                                    {{scope.$index + 1}}
-                                </template>
-                            </el-table-column>
-                            <el-table-column prop="info" label="文件详情">
-                                <template #default="scope">
-                                    <div class="hc-table-col-item">
-                                        <div class="img-box" v-if="scope.row.type !== 1">
-                                            <HcImg class="hc-image" :src="setImageUrl(scope.row.imageUrl)"/>
-                                        </div>
-                                        <div class="img-box" v-else>
-                                            <video :src="scope.row.imageUrl">
-                                                您的浏览器不支持 video
-                                            </video>
-                                        </div>
-                                        <div class="content-box">
-                                            <div class="text-cut title">{{scope.row.title}}</div>
-                                            <div class="shootingUser">拍摄者:{{scope.row.shootingUser}}</div>
-                                            <div class="shootingTimeStr">拍摄时间:{{scope.row.shootingTimeStr}}</div>
-                                            <div class="fileSize">文件大小:{{scope.row.fileSize}}</div>
-                                        </div>
-                                    </div>
-                                </template>
-                            </el-table-column>
-                            <el-table-column prop="textContent" label="文字说明"/>
-                            <el-table-column label="操作" align="center" width="130">
-                                <template #default="scope">
-                                    <HcTooltip keys="image-data-preview">
-                                        <el-button type="primary" size="small" text @click="previewClick(scope.row)">查看</el-button>
-                                    </HcTooltip>
-                                    <HcTooltip keys="image-data-edit">
-                                        <el-button type="primary" size="small" text @click="editClick(scope.row)">编辑</el-button>
-                                    </HcTooltip>
-                                </template>
-                            </el-table-column>
-                        </el-table>
-                    </div>
-                </el-scrollbar>
+                <HcTable ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading" isCheck @selection-change="tableSelectionChange">
+                    <template #info="{row}">
+                        <div class="hc-table-col-item">
+                            <div class="img-box" v-if="row.type !== 1">
+                                <HcImg class="hc-image" :src="setImageUrl(row.imageUrl)"/>
+                            </div>
+                            <div class="img-box" v-else>
+                                <video :src="row.imageUrl">
+                                    您的浏览器不支持 video
+                                </video>
+                            </div>
+                            <div class="content-box">
+                                <div class="text-cut title">{{row.title}}</div>
+                                <div class="shootingUser">拍摄者:{{row.shootingUser}}</div>
+                                <div class="shootingTimeStr">拍摄时间:{{row.shootingTimeStr}}</div>
+                                <div class="fileSize">文件大小:{{row.fileSize}}</div>
+                            </div>
+                        </div>
+                    </template>
+                    <template #operate="{row}">
+                        <HcTooltip keys="image-data-preview">
+                            <el-button type="primary" size="small" text @click="previewClick(row)">查看</el-button>
+                        </HcTooltip>
+                        <HcTooltip keys="image-data-edit">
+                            <el-button type="primary" size="small" text @click="editClick(row)">编辑</el-button>
+                        </HcTooltip>
+                    </template>
+                </HcTable>
                 <template #action>
                     <div class="lr-dialog-footer">
                         <div class="left">
@@ -127,7 +112,7 @@ import WbsTree from "./components/WbsTree.vue"
 import HcTreeData from "./components/HcTreeData.vue"
 import imageApi from '~api/other-file/imageData';
 import {getStoreData, setStoreData} from '~src/utils/storage'
-import {getArrValue,getObjNullValue} from "vue-utils-plus"
+import {downloadBlob, getArrValue, getObjNullValue} from "vue-utils-plus"
 
 //变量
 const router = useRouter()
@@ -261,6 +246,11 @@ const pageChange = ({current, size}) => {
 const tableListRef = ref(null)
 const tableLoading = ref(false)
 const tableListData = ref([])
+const tableListColumn = ref([
+    {key:'info', name: '文件详情'},
+    {key:'textContent', name: '文字说明'},
+    {key:'operate', name: '操作', align: 'center', width: '130'},
+])
 const getTableData = async () => {
     tableLoading.value = true
     const {error, code, data} = await imageApi.getPageList({
@@ -351,37 +341,66 @@ const editClick = ({id}) => {
     })
 }
 
+//拼接ID
+const rowsToId = (rows) => {
+    return rows.map((obj) => {
+        return obj.id;
+    }).join(",")
+}
+
 //下载文件
-const downloadClick = () => {
-    /*let url = imageUrl || '';
-    if (url) {
-        let urlArr = url.split(',')
-        if (urlArr.length === 1) {
-            window.open(urlArr[0],"_blank");
-        } else {
-            imageData.batchDownloadFileToZip({ids: id}).then(res => {
-                download(res)   //下载文件
-            })
+const downloadLoading = ref(false)
+const downloadClick = async () => {
+    const rows = tableCheckedKeys.value
+    if (rows.length > 0) {
+        downloadLoading.value = true
+        const ids = rowsToId(rows)
+        const { error, disposition, res } = await imageApi.batchDownloadFileToZip({ids: ids}, false)
+        //判断状态
+        if (!error) {
+            if (disposition) {
+                downloadBlob(res,disposition)
+            } else {
+                window.$message?.error('下载异常')
+            }
         }
     } else {
-        window.$message?.warning('暂无可下载的资料文件');
-    }*/
+        window.$message?.warning('请先勾选需要下载的资料文件');
+    }
 }
 
 //删除文件
-const delClick = () => {
-    /*imageData.removeImageclassifyFile({
-        ids: item.id
-    }).then(({data}) => {
-        if (data.code === 200) {
-            window.$message?.success('删除成功')
-            getTableData()
-        } else {
-            window.$message?.error(data.msg || '删除异常')
-        }
-    })*/
+const delLoading = ref(false)
+const delClick = async () => {
+    const rows = tableCheckedKeys.value
+    if (rows.length > 0) {
+        const ids = rowsToId(rows)
+        window?.$messageBox?.alert('是否删除勾选的资料文件?', '删除提醒', {
+            showCancelButton: true,
+            confirmButtonText: '确定删除',
+            cancelButtonText: '取消',
+            callback: (action) => {
+                if (action === 'confirm') {
+                    removeImageclassifyFile(ids)
+                }
+            }
+        })
+    } else {
+        window.$message?.warning('请先勾选需要删除的资料文件');
+    }
+}
+const removeImageclassifyFile = async (ids) => {
+    delLoading.value = true
+    const {error, code} = await imageApi.removeImageclassifyFile({ids: ids}, false)
+    //判断状态
+    delLoading.value = false
+    if (!error && code === 200) {
+        window.$message?.success('删除成功')
+        getTableData()
+    } else {
+        window.$message?.error('删除异常')
+    }
 }
-
 
 //回到影像资料页
 const goToBack = () => {
@@ -389,12 +408,14 @@ const goToBack = () => {
 }
 
 //左右拖动,改变树形结构宽度
-const leftWidth = ref(382);
+const leftWidth = ref(dataType === 1 ? 382 : 220);
 const onmousedown = () => {
     const leftNum = isCollapse.value ? 142 : 272
     document.onmousemove = (ve) => {
-        let diffVal = ve.clientX - leftNum;
-        if(diffVal >= 310 && diffVal <= 900) {
+        const diffVal = ve.clientX - leftNum;
+        const minWidth = dataType === 1 ? 310 : 200
+        const maxWidth = dataType === 1 ? 900 : 300
+        if(diffVal >= minWidth && diffVal <= maxWidth) {
             leftWidth.value = diffVal;
         }
     }

+ 5 - 0
yarn.lock

@@ -1102,6 +1102,11 @@ readdirp@~3.6.0:
   dependencies:
     picomatch "^2.2.1"
 
+remixicon@^2.5.0:
+  version "2.5.0"
+  resolved "https://registry.yarnpkg.com/remixicon/-/remixicon-2.5.0.tgz#b5e245894a1550aa23793f95daceadbf96ad1a41"
+  integrity sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww==
+
 resolve@^1.1.7, resolve@^1.22.1:
   version "1.22.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"